File Coverage

lib/mb.pm
Criterion Covered Total %
statement 1606 2119 75.7
branch 1380 1890 73.0
condition 130 241 53.9
subroutine 124 132 93.9
pod 2 68 2.9
total 3242 4450 72.8


line stmt bran cond sub pod time code
1             package mb;
2             '有朋自遠方来不亦楽乎'=~/^\xE6\x9C\x89/ or die "Perl script '@{[__FILE__]}' must be UTF-8 encoding.\n";
3             # You are welcome! MOJIBAKE-san, you are our friend forever!!
4             ######################################################################
5             #
6             # mb - Can easy script in Big5, Big5-HKSCS, GBK, Sjis(also CP932), UHC, UTF-8, ...
7             #
8             # https://metacpan.org/release/mb
9             #
10             # Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2018, 2019, 2020, 2021, 2022, 2023, 2024, 2026 INABA Hitoshi in a CPAN
11             ######################################################################
12              
13 151     145   2827221 use 5.00503; # Universal Consensus 1998 for primetools
  145         462  
14             # use 5.008001; # Lancaster Consensus 2013 for toolchains
15              
16             $VERSION = '0.64';
17             $VERSION = $VERSION;
18              
19             # internal use
20             $mb::last_s_passed = 0; # last s/// status (1 if s/// passed)
21              
22             # filehandle sequence counter for _open_a/_open_r/_open_w
23             $mb::_fh_seq = 0;
24              
25 151 100   145   3897 BEGIN { pop @INC if $INC[-1] eq '.' } # CVE-2016-1238: Important unsafe module load path flaw
26 151     141   1074 use strict;
  151         483  
  151         9873  
27 147 50 33 141   3443 BEGIN { if ($] < 5.006 && !defined(&warnings::import)) { $INC{'warnings.pm'} = 'stub'; eval 'package warnings; sub import {}' } } use warnings; local $^W=1;
  10     140   24  
  10         130  
  147         646  
  147         228  
  147         79268  
28              
29             # set OSNAME
30             my $OSNAME = $^O;
31              
32             # encoding name of operating system
33             my $system_encoding = undef;
34              
35             # encoding name of MBCS script
36             my $script_encoding = undef;
37              
38             # over US-ASCII
39             my $over_ascii = undef;
40              
41             # supports qr/./ in MBCS script
42             my $x = undef;
43              
44             # supports [\b] \d \h \s \v \w in MBCS script
45             my $bare_backspace = '\x08';
46             my $bare_d = '0123456789';
47             my $bare_h = '\x09\x20';
48             my $bare_s = '\t\n\f\r\x20';
49             my $bare_v = '\x0A\x0B\x0C\x0D';
50             my $bare_w = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_';
51              
52             # as many escapes as possible to avoid perl's feature
53             my $escapee_in_qq_like = join('', map {"\\$_"} grep( ! /[A-Za-z0-9_]/, map { CORE::chr } 0x21..0x7E));
54              
55             # as less escapes as possible to avoid over-escaping
56             my $escapee_in_q__like = '\\' . "\x5C";
57              
58             # generic linebreak
59             my $R = '(?>\\r\\n|\\r|\\n)';
60              
61             # check running perl interpreter
62             if ($^X =~ /jperl/i) {
63             die "script '@{[__FILE__]}' can run on only perl, not JPerl\n";
64             }
65              
66             # this file is used as command on command line
67             if ($0 eq __FILE__) {
68              
69             # register this modulino in %INC so that a "use mb;" / "require mb" inside an
70             # in-process transpiled script (see sub main) is satisfied by the already
71             # loaded modulino instead of reloading mb.pm (which would emit a flood of
72             # "Subroutine ... redefined" warnings). This mirrors the child-interpreter
73             # path, where -Mmb=ver,enc already populates $INC{'mb.pm'}.
74             $INC{'mb.pm'} = __FILE__ if not exists $INC{'mb.pm'};
75              
76             main();
77             }
78              
79             ######################################################################
80             # main program
81             ######################################################################
82              
83             #---------------------------------------------------------------------
84             # running as module, runtime routines
85             sub import {
86 135     135   4509 my $self = shift @_;
87              
88             # confirm version
89 135 50 66     2526 if (defined($_[0]) and ($_[0] =~ /\A [0-9] /xms)) {
90 3 50       14 if ($_[0] ne $mb::VERSION) {
91 3         4 my($package, $filename, $line) = caller;
92 3         70 die "$filename requires @{[__PACKAGE__]} $_[0], however @{[__FILE__]} am only $mb::VERSION, stopped at $filename line $line.\n";
  3         13  
  3         3  
93             }
94 3         67 shift @_;
95             }
96              
97             # scan import arguments
98 135         648 my $want_runtime = 0; # *mb or %mb requested -> runtime interface, no filter
99 135         365 my $encoding = undef;
100 135         536 for my $arg (@_) {
101 42 100 100     334 if (($arg eq '*mb') or ($arg eq '%mb')) {
    100          
102 6         8 $want_runtime = 1;
103             }
104             elsif ($arg =~ /\A (?: big5 | big5hkscs | eucjp | gb18030 | gbk | rfc2279 | sjis | uhc | utf8 | wtf8 ) \z/xms) {
105 30         125 $encoding = $arg;
106             }
107             else {
108 12         20 die "@{[__FILE__]} import argument '$arg' not supported (use one of: *mb, %mb, big5, big5hkscs, eucjp, gb18030, gbk, rfc2279, sjis, uhc, utf8, wtf8).\n";
  12         32  
109             }
110             }
111              
112             # set system encoding
113 126         707 $system_encoding = detect_system_encoding();
114              
115             # set script encoding
116 126 100       369 if (defined $encoding) {
117 30         91 mb::set_script_encoding($encoding);
118             }
119             else {
120 99         373 mb::set_script_encoding($system_encoding);
121             }
122              
123             # tie my %mb, __PACKAGE__; # makes: Parentheses missing around "my" list
124 146     140   957 no strict qw(refs);
  146         209  
  146         115467  
125 126         708 tie my %mb, 'mb';
126 126         512 *{caller().'::mb'} = { %mb };
  126         892  
127              
128             # $^X($EXECUTABLE_NAME) for execute MBCS Perl script
129 126         270 $mb::PERL = qq{$^X @{[__FILE__]}};
  126         442  
130 126         317 $mb::PERL = $mb::PERL; # to avoid: Name "mb::PERL" used only once: possible typo at ...
131              
132             # original $0($PROGRAM_NAME) before transpile
133 126         527 ($mb::ORIG_PROGRAM_NAME = $0) =~ s/\.oo(\.[^.]+)\z/$1/;
134 126         178 $mb::ORIG_PROGRAM_NAME = $mb::ORIG_PROGRAM_NAME; # to avoid: Name "mb::ORIG_PROGRAM_NAME" used only once: possible typo at ...
135              
136             # Sjis software compatible subroutines
137 126         449 my $old_package = mb::get_old_package();
138 126         381 for my $subroutine (qw( chop chr do dosglob eval getc index index_byte length ord require reverse rindex rindex_byte substr tr )) {
139 1971         1671 *{$old_package . $subroutine} = \&{"mb::$subroutine"};
  1971         4749  
  1971         3286  
140             }
141              
142             # path 1: opportunistic source code filter
143             #
144             # Installed for "use mb;" style loading (no *mb/%mb token) and not when
145             # running an already transpiled *.oo script through -Mmb=ver,enc (the
146             # modulino sets PERL_MB_OCTET in that case, see sub main).
147             #
148             # ADDITIVE GUARD (zero regression): a script that calls
149             # mb::set_script_encoding() itself is, by construction, an octet-oriented
150             # / runtime-managed script (this is mb's long-standing "use mb; then call
151             # mb::* functions on octet data" convention, used throughout t/*.t). Such
152             # a script must NOT have its own source transpiled, so the filter passes it
153             # through unchanged. Only a genuine path-1 script -- one that does not
154             # manage the encoding at run time -- is auto-transpiled. This keeps every
155             # pre-existing "use mb;" caller behaving exactly as before (it was never
156             # source-filtered, because no filter existed in mb-0.63) while still letting
157             # a plain "use mb;" / "use mb 'utf8';" script be transpiled with no modulino.
158             #
159             # Filter::Util::Call has been a core module since perl 5.8.0; it is only
160             # require()d at run time, so no extra dependency is declared. On perl
161             # 5.005_03 / 5.6 the filter is unavailable and "use mb;" loads as a plain
162             # runtime import (the modulino remains the way to transpile there).
163 126 100 100     18562 if ((not $want_runtime) and (not $ENV{'PERL_MB_OCTET'}) and ($] >= 5.008)) {
      66        
164 111 50       284 if (eval { require Filter::Util::Call; 1 }) {
  111         60686  
  111         94419  
165 111         268 my $done = 0;
166             Filter::Util::Call::filter_add(sub {
167 117 100   117   9675 return 0 if $done;
168 111         260 my $buffer = '';
169 111         181 my $status = 0;
170 111         1191 while (($status = Filter::Util::Call::filter_read()) > 0) {
171 37490         36306 $buffer .= $_;
172 37490         58897 $_ = '';
173             }
174 111 50       442 if ($status == 0) {
175             # runtime-managed (octet-oriented) script: pass through as is
176 111 100       994 if ($buffer =~ /\b mb::set_script_encoding \s* \(/xms) {
177 94         216 $_ = $buffer;
178             }
179             else {
180 20         72 $_ = mb::_insert_source_encoding_unimport(mb::parse($buffer));
181             }
182 111         245 $done = 1;
183 111         10750 return 1;
184             }
185 3         4 return $status;
186 111         805 });
187             }
188             }
189             }
190              
191             #---------------------------------------------------------------------
192             # running as command
193             sub main {
194              
195             # usage
196 24 50   24 0 324 if (scalar(@ARGV) == 0) {
197 3         12 die <
198             usage:
199              
200             perl mb.pm script_by_mbcs.pl (auto detect)
201             perl mb.pm -e big5 script_by_big5.pl
202             perl mb.pm -e big5hkscs script_by_big5hkscs.pl
203             perl mb.pm -e eucjp script_by_eucjp.pl
204             perl mb.pm -e gb18030 script_by_gb18030.pl
205             perl mb.pm -e gbk script_by_gbk.pl
206             perl mb.pm -e rfc2279 script_by_rfc2279.pl
207             perl mb.pm -e sjis script_by_sjis.pl
208             perl mb.pm -e sjis script_by_cp932.pl
209             perl mb.pm -e uhc script_by_uhc.pl
210             perl mb.pm -e utf8 script_by_utf8.pl
211             perl mb.pm -e wtf8 script_by_wtf8.pl
212              
213             perl mb.pm script.pl ??-DOS-like *wildcard* available
214              
215             END
216             }
217              
218             # set system encoding
219 24         47 $system_encoding = detect_system_encoding();
220              
221             # set script encoding from command line
222 24         113 my $encoding = '';
223 24 100       93 if (($encoding) = $ARGV[0] =~ /\A -e ( .+ ) \z/xms) {
    50          
224 14 50       17 if ($encoding =~ /\A (?: big5 | big5hkscs | eucjp | gb18030 | gbk | rfc2279 | sjis | uhc | utf8 | wtf8 ) \z/xms) {
225 3         64 mb::set_script_encoding($encoding);
226 3         13 shift @ARGV;
227             }
228             else {
229 14         45 die "script_encoding '$encoding' not supported (use one of: big5, big5hkscs, eucjp, gb18030, gbk, rfc2279, sjis, uhc, utf8, wtf8).\n";
230             }
231             }
232             elsif ($ARGV[0] =~ /\A -e \z/xms) {
233 13         84 $encoding = $ARGV[1];
234 13 100       46 if ($encoding =~ /\A (?: big5 | big5hkscs | eucjp | gb18030 | gbk | rfc2279 | sjis | uhc | utf8 | wtf8 ) \z/xms) {
235 9         28 mb::set_script_encoding($encoding);
236 9         74 shift @ARGV;
237 9         26 shift @ARGV;
238             }
239             else {
240 7         15 die "script_encoding '$encoding' not supported (use one of: big5, big5hkscs, eucjp, gb18030, gbk, rfc2279, sjis, uhc, utf8, wtf8).\n";
241             }
242             }
243             else {
244 3         83 mb::set_script_encoding($system_encoding);
245             }
246              
247             # remember the target script name and read its source once
248 9         27 my $script = $ARGV[0];
249              
250             # read application script
251 9 50       52 my $rfh = mb::_open_r($script) or die "$0(@{[__LINE__]}): can't open file: $script\n";
  3         70  
252              
253             # sysread(...) has hidden binmode($fh) that's not portable
254             # local $_; sysread($fh, $_, -s $ARGV[0]);
255 146     140   1058 local $_ = CORE::do { local $/; no strict 'refs'; readline(*{$rfh}) };
  146         234  
  146         6535  
  9         24  
  9         30  
  9         75  
  9         248  
256 146     140   587 { no strict 'refs'; close($rfh) }
  326         490  
  704         50580  
  9         20  
  9         133  
257 9         47 my $source = $_;
258              
259             # @ARGV wildcard globbing
260 9 50       31 if ($OSNAME =~ /MSWin32/) {
261 3         66 my @argv = ();
262 3         11 for (@ARGV) {
263              
264             # has space
265 3 0       4 if (/\A (?:$x)*? [ ] /xms) {
    0          
266 3 0       66 if (my @glob = mb::dosglob(qq{"$_"})) {
267 3         12 push @argv, @glob;
268             }
269             else {
270 3         4 push @argv, $_;
271             }
272             }
273              
274             # has wildcard metachar
275             elsif (/\A (?:$x)*? [*?] /xms) {
276 3 0       66 if (my @glob = mb::dosglob($_)) {
277 3         12 push @argv, @glob;
278             }
279             else {
280 3         5 push @argv, $_;
281             }
282             }
283              
284             # no wildcard globbing
285             else {
286 3         63 push @argv, $_;
287             }
288             }
289 3         13 @ARGV = @argv;
290             }
291              
292             # Strategy for :
293             # - no __DATA__/__END__ : transpile and run in-process by CORE::eval
294             # (no temporary file is created)
295             # - has __DATA__/__END__: a string eval cannot provide a working
296             # handle, so write a *.oo script and run it as a
297             # real file through a child interpreter.
298 9 100       103 if ($source =~ /^__(?:END|DATA)__\b/m) {
299              
300             # poor "make": (re)transpile to *.oo only when stale
301 5         99 (my $script_oo = $script) =~ s{\A (.*) \. ([^.]+) \z}{$1.oo.$2}xms;
302 5 50 66     2022 if (
      66        
303             (not -e $script_oo) or
304             (mtime($script_oo) <= mtime($script)) or
305             (mtime($script_oo) <= mtime(__FILE__))
306             ) {
307              
308             # poor file locking
309 4     3   14 local $SIG{__DIE__} = sub { rmdir "$script.lock"; };
  3         67  
310 4 50       328 if (mkdir "$script.lock", 0755) {
311 4 50       9 my $wfh = mb::_open_w($script_oo) or die "$0(@{[__LINE__]}): can't open file: $script_oo\n";
  3         65  
312 146     140   949 { no strict 'refs'; print {*{$wfh}} mb::_insert_source_encoding_unimport(mb::parse($source)) }
  146         601  
  146         7844  
  4         6  
  4         62  
  4         21  
313 140     140   724 { no strict 'refs'; close($wfh) }
  140         261  
  146         176086  
  4         13  
  4         6  
  4         110  
314 4         97 rmdir "$script.lock";
315             }
316             else {
317 3         3 die "$0(@{[__LINE__]}): can't mkdir: $script.lock\n";
  3         62  
318             }
319             }
320              
321             # locate this module for the child interpreter
322 5         19 my $module_path = '';
323 5         8 my $module_name = '';
324 5         70 my $quote = '';
325 5 50       19 if ($OSNAME =~ /MSWin32/) {
326 3 0       5 if ($0 =~ m{ ([^\/\\]+)\.pm \z}xmsi) {
327 3         62 ($module_path, $module_name) = ($`, $1);
328 3   0     12 $module_path ||= '.';
329 3         5 $module_path =~ s{ [\/\\] \z}{}xms;
330             }
331             else {
332 3         62 die "$0(@{[__LINE__]}): can't run as module.\n";
  3         12  
333             }
334 3         3 $quote = q{"};
335             }
336             else {
337 5 50       109 if ($0 =~ m{ ([^\/]+)\.pm \z}xmsi) {
338 5         20 ($module_path, $module_name) = ($`, $1);
339 5   50     18 $module_path ||= '.';
340 5         110 $module_path =~ s{ / \z}{}xms;
341             }
342             else {
343 3         12 die "$0(@{[__LINE__]}): can't run as module.\n";
  3         5  
344             }
345 5         73 $quote = q{'};
346             }
347              
348             # run octet-oriented script
349             # PERL_MB_OCTET tells the child interpreter (which loads -Mmb=ver,enc) not
350             # to install the path-1 source filter on the already transpiled *.oo script.
351 5         20 $| = 1;
352 5         28 local $ENV{'PERL_MB_OCTET'} = 1;
353 5 50       81 system($^X, "-I$module_path", "-M$module_name=$mb::VERSION,$script_encoding", map { / / ? "$quote$_$quote" : $_ } $script_oo, @ARGV[1..$#ARGV]);
  5         4362064  
354 5         3 exit($? >> 8);
355             }
356             else {
357              
358             # transpile and run in-process (no temporary file is created)
359 7         1649 my $transpiled = mb::_insert_source_encoding_unimport(mb::parse($source));
360              
361             # make the script see its own name and its own arguments
362 7         96 local $0 = $script;
363 7         21 local @ARGV = @ARGV[1..$#ARGV];
364              
365             # escape the file name for the #line directive so error messages
366             # point back at the original script with correct line numbers
367 7         83 (my $filename = $script) =~ s/([\\"])/\\$1/g;
368 7         25 my $code = "package main;\n#line 1 \"$filename\"\n" . $transpiled;
369              
370             # PERL_MB_OCTET keeps any "use mb ..." inside the transpiled source from
371             # re-installing the path-1 source filter (which would transpile twice).
372 7         28 $| = 1;
373 7         118 local $ENV{'PERL_MB_OCTET'} = 1;
374 7         1569 CORE::eval $code;
375 7 100       194 if ($@) {
376 4         98 print STDERR $@;
377 4         14 exit 1;
378             }
379 6         4 exit 0;
380             }
381             }
382              
383             #---------------------------------------------------------------------
384             # cluck() for MBCS encoding
385             sub cluck {
386 3     3 0 70 my $i = 0;
387 3         13 my @cluck = ();
388 3         4 while (my($package, $filename, $line, $subroutine) = caller($i)) {
389 3         107 push @cluck, "[$i] $filename($line) $subroutine\n";
390 3         13 $i++;
391             }
392 3         4 print STDERR "\n", @_, "\n";
393 3         80 print STDERR CORE::reverse @cluck;
394             }
395              
396             #---------------------------------------------------------------------
397             # confess() for MBCS encoding
398             sub confess {
399 3     3 0 15 my $i = 0;
400 3         4 my @confess = ();
401 3         72 while (my($package, $filename, $line, $subroutine) = caller($i)) {
402 3         14 push @confess, "[$i] $filename($line) $subroutine\n";
403 3         4 $i++;
404             }
405 3         71 print STDERR "\n", @_, "\n";
406 3         14 print STDERR CORE::reverse @confess;
407 3         4 die;
408             }
409              
410             #---------------------------------------------------------------------
411             # short cut of (stat(file))[9]
412             sub mtime {
413 7     7 0 84 my($file) = @_;
414 7         78 return ((stat $file)[9]);
415             }
416              
417             ######################################################################
418             # subroutines for MBCS application programmers
419             ######################################################################
420              
421             #---------------------------------------------------------------------
422             # chop() for MBCS encoding
423             sub mb::chop (@) {
424 21     21 0 372 my $chop = '';
425 21 100       109 for (@_ ? @_ : $_) {
426 29 100       175 if (my @x = /\G$x/g) {
427 23         27 $chop = pop @x;
428 23         103 $_ = join '', @x;
429             }
430             }
431 21         36 return $chop;
432             }
433              
434             #---------------------------------------------------------------------
435             # chr() for MBCS encoding
436             sub mb::chr (;$) {
437 30 100   30 0 568 my $number = @_ ? $_[0] : $_;
438              
439             # Negative values give the Unicode replacement character (chr(0xfffd)),
440             # except under the bytes pragma, where the low eight bits of the value
441             # (truncated to an integer) are used.
442              
443 30         99 my @octet = ();
444 30         44 CORE::do {
445 34         60 unshift @octet, ($number % 0x100);
446 34         147 $number = int($number / 0x100);
447             } while ($number > 0);
448 30         126 return pack 'C*', @octet;
449             }
450              
451             #---------------------------------------------------------------------
452             # do FILE for MBCS encoding
453             sub mb::do ($) {
454 8     8 0 2101 my($file) = @_;
455 8         123 for my $prefix_file ($file, map { "$_/$file" } @INC) {
  43         81  
456 8 50       112 if (-f $prefix_file) {
457              
458             # poor "make"
459 8         126 (my $prefix_file_oo = $prefix_file) =~ s{\A (.*) \. ([^.]+) \z}{$1.oo.$2}xms;
460 8 0 33     167 if (
      33        
461             (not -e $prefix_file_oo) or
462             (mtime($prefix_file_oo) <= mtime($prefix_file)) or
463             (mtime($prefix_file_oo) <= mtime(__FILE__))
464             ) {
465 8 50       21 my $fh = mb::_open_r($prefix_file) or confess "$0(@{[__LINE__]}): can't open file: $prefix_file\n";
  3         65  
466 146     140   1051 local $_ = CORE::do { local $/; no strict 'refs'; readline(*{$fh}) };
  146         322  
  140         6640  
  8         20  
  8         20  
  8         73  
  8         179  
467 140     140   592 { no strict 'refs'; close($fh) }
  140         193  
  140         14899  
  8         16  
  8         214  
468              
469             # poor file locking
470 8     3   56 local $SIG{__DIE__} = sub { rmdir "$prefix_file.lock"; };
  3         64  
471 8 50       602 if (mkdir "$prefix_file.lock", 0755) {
472 8 50       29 my $fh = mb::_open_w($prefix_file_oo) or confess "$0(@{[__LINE__]}): can't open file: $prefix_file_oo\n";
  3         3  
473 140     140   680 { no strict 'refs'; print {*{$fh}} mb::_insert_source_encoding_unimport(mb::parse()) }
  140         214  
  140         6404  
  8         15  
  8         8  
  8         109  
474 140     140   543 { no strict 'refs'; close($fh) }
  140         174  
  140         259727  
  8         74  
  8         24  
  8         249  
475 8         485 rmdir "$prefix_file.lock";
476             }
477             else {
478 3         13 confess "$0(@{[__LINE__]}): can't mkdir: $prefix_file.lock\n";
  3         4  
479             }
480             }
481 8         101 $INC{$file} = $prefix_file_oo;
482              
483             # run as Perl script
484             # must use CORE::do to use , because CORE::eval cannot do it
485             # moreover "goto &CORE::do" doesn't work
486 8         308 return CORE::eval sprintf(<<'END', (caller)[0,2,1]);
487             package %s;
488             #line %s "%s"
489             CORE::do "$prefix_file_oo";
490             END
491             }
492             }
493 3         4 confess "Can't find $file in \@INC";
494             }
495              
496             #---------------------------------------------------------------------
497             # DOS-like glob() for MBCS encoding
498             sub mb::dosglob (;$) {
499 11 50   11 0 692 my $expr = @_ ? $_[0] : $_;
500 11         21 my @glob = ();
501              
502             # works on not MSWin32
503 11 50       21 if ($OSNAME !~ /MSWin32/) {
504 11         1828 @glob = CORE::glob($expr);
505             }
506              
507             # works on MSWin32
508             else {
509              
510             # gets pattern
511 3         64 while ($expr =~ s{\A [\x20]* ( "(?:$x)+?" | (?:(?!["\x20])$x)+ ) }{}xms) {
512 3         6 my $pattern = $1;
513              
514             # avoids command injection
515 3 0       81 next if $pattern =~ /\G${mb::_anchor} \& /xms;
516 3 0       13 next if $pattern =~ /\G${mb::_anchor} \( /xms;
517 3 0       3 next if $pattern =~ /\G${mb::_anchor} \) /xms;
518 3 0       64 next if $pattern =~ /\G${mb::_anchor} \< /xms;
519 3 0       13 next if $pattern =~ /\G${mb::_anchor} \> /xms;
520 3 0       3 next if $pattern =~ /\G${mb::_anchor} \^ /xms;
521 3 0       67 next if $pattern =~ /\G${mb::_anchor} \| /xms;
522              
523             # makes globbing result
524 3         12 mb::tr($pattern, '/', "\x5C");
525 3 0       5 if (my($dir) = $pattern =~ m{\A ($x*) \\ }xms) {
526 3         63 push @glob, map { "$dir\\$_" } CORE::split /\n/, `DIR /B $pattern 2>NUL`;
  3         15  
527             }
528             else {
529 3         6 push @glob, CORE::split /\n/, `DIR /B $pattern 2>NUL`;
530             }
531             }
532             }
533              
534             # returns globbing result
535 11         121 my %glob = map { $_ => 1 } @glob;
  27         54  
536 11 50       28 return sort { (mb::uc($a) cmp mb::uc($b)) || ($a cmp $b) } keys %glob;
  25         116  
537             }
538              
539             #---------------------------------------------------------------------
540             # eval STRING for MBCS encoding
541             sub mb::eval (;$) {
542 15039 100   15039 0 38458602 local $_ = @_ ? $_[0] : $_;
543              
544             # run as Perl script in caller package
545 15039         56761 return CORE::eval sprintf(<<'END', (caller)[0,2,1], mb::parse());
546             package %s;
547             #line %s "%s"
548             %s
549             END
550             }
551              
552             #---------------------------------------------------------------------
553             # getc() for MBCS encoding
554             sub mb::getc (;*) {
555 40 100   40 0 2295054 my $fh = @_ ? shift(@_) : \*STDIN;
556 40 50 33     91 confess 'Too many arguments for mb::getc' if @_ and not wantarray;
557 40         1324 my $getc = CORE::getc $fh;
558 40 100       174 if ($script_encoding =~ /\A (?: sjis ) \z/xms) {
    50          
    50          
    50          
    50          
559 39 100       68 if ($getc =~ /\A [\x81-\x9F\xE0-\xFC] \z/xms) {
560 21         35 $getc .= CORE::getc $fh;
561             }
562             }
563             elsif ($script_encoding =~ /\A (?: eucjp ) \z/xms) {
564 3 0       66 if ($getc =~ /\A [\xA1-\xFE] \z/xms) {
565 3         14 $getc .= CORE::getc $fh;
566             }
567             }
568             elsif ($script_encoding =~ /\A (?: gbk | uhc | big5 | big5hkscs ) \z/xms) {
569 3 0       4 if ($getc =~ /\A [\x81-\xFE] \z/xms) {
570 3         63 $getc .= CORE::getc $fh;
571             }
572             }
573             elsif ($script_encoding =~ /\A (?: gb18030 ) \z/xms) {
574 3 0       11 if ($getc =~ /\A [\x81-\xFE] \z/xms) {
575 3         4 $getc .= CORE::getc $fh;
576 3 0       64 if ($getc =~ /\A [\x81-\xFE] [\x30-\x39] \z/xms) {
577 3         13 $getc .= CORE::getc $fh;
578 3         4 $getc .= CORE::getc $fh;
579             }
580             }
581             }
582             elsif ($script_encoding =~ /\A (?: rfc2279 | utf8 | wtf8 ) \z/xms) {
583 4 50       83 if ($getc =~ /\A [\x00-\x7F\x80-\xC1\xF5-\xFF] \z/xms) {
    0          
    0          
    0          
584             }
585             elsif ($getc =~ /\A [\xC2-\xDF] \z/xms) {
586 3         12 $getc .= CORE::getc $fh;
587             }
588             elsif ($getc =~ /\A [\xE0-\xEF] \z/xms) {
589 3         5 $getc .= CORE::getc $fh;
590 3         68 $getc .= CORE::getc $fh;
591             }
592             elsif ($getc =~ /\A [\xF0-\xF4] \z/xms) {
593 3         13 $getc .= CORE::getc $fh;
594 3         3 $getc .= CORE::getc $fh;
595 3         66 $getc .= CORE::getc $fh;
596             }
597             }
598 40 100       112 return wantarray ? ($getc,@_) : $getc;
599             }
600              
601             #---------------------------------------------------------------------
602             # index() for MBCS encoding
603             sub mb::index ($$;$) {
604 11     11 0 293 my $index = 0;
605 11 100       88 if (@_ == 3) {
606 6         84 $index = mb::index_byte($_[0], $_[1], CORE::length(mb::substr($_[0], 0, $_[2])));
607             }
608             else {
609 6         12 $index = mb::index_byte($_[0], $_[1]);
610             }
611 10 100       61 if ($index == -1) {
612 4         6 return -1;
613             }
614             else {
615 4         11 return mb::length(CORE::substr $_[0], 0, $index);
616             }
617             }
618              
619             #---------------------------------------------------------------------
620             # JPerl like index() for MBCS encoding
621             sub mb::index_byte ($$;$) {
622 16     19 0 260 my($str,$substr,$position) = @_;
623 16   100     42 $position ||= 0;
624 16         16 my $pos = 0;
625 16         27 while ($pos < CORE::length($str)) {
626 178 100       220 if (CORE::substr($str,$pos,CORE::length($substr)) eq $substr) {
627 12 100       24 if ($pos >= $position) {
628 8         32 return $pos;
629             }
630             }
631 170 50       509 if (CORE::substr($str,$pos) =~ /\A($x)/xms) {
632 170         220 $pos += CORE::length($1);
633             }
634             else {
635 0         0 $pos += 1;
636             }
637             }
638 8         13 return -1;
639             }
640              
641             #---------------------------------------------------------------------
642             # universal lc() for MBCS encoding
643             sub mb::lc (;$) {
644 11 100   14 1 1491 local $_ = @_ ? $_[0] : $_;
645             # A a B b C c D d E e F f G g H h I i J j K k L l M m N n O o P p Q q R r S s T t U u V v W w X x Y y Z z
646 11 100       286 return join '', map { {qw( A a B b C c D d E e F f G g H h I i J j K k L l M m N n O o P p Q q R r S s T t U u V v W w X x Y y Z z )}->{$_}||$_ } /\G$x/g;
  119         1074  
647             # A a B b C c D d E e F f G g H h I i J j K k L l M m N n O o P p Q q R r S s T t U u V v W w X x Y y Z z
648             }
649              
650             #---------------------------------------------------------------------
651             # universal lcfirst() for MBCS encoding
652             sub mb::lcfirst (;$) {
653 2 100   5 0 117 local $_ = @_ ? $_[0] : $_;
654 2 50       69 if (/\A($x)(.*)\z/s) {
655 2         7 return mb::lc($1) . $2;
656             }
657             else {
658 0         0 return '';
659             }
660             }
661              
662             #---------------------------------------------------------------------
663             # length() for MBCS encoding
664             sub mb::length (;$) {
665 22 100   25 0 126857 local $_ = @_ ? $_[0] : $_;
666 22         833 return scalar(() = /\G$x/g);
667             }
668              
669             #---------------------------------------------------------------------
670             # ord() for MBCS encoding
671             sub mb::ord (;$) {
672 4 100   7 0 179 local $_ = @_ ? $_[0] : $_;
673 4         3 my $ord = 0;
674 4 50       52 if (/\A($x)/) {
675 4         11 for my $octet (unpack 'C*', $1) {
676 6         8 $ord = $ord * 0x100 + $octet;
677             }
678             }
679 4         6 return $ord;
680             }
681              
682             #---------------------------------------------------------------------
683             # valid() tests well-formedness of a string for the current script encoding
684             sub mb::valid (;$) {
685 39 100   42 0 204 local $_ = @_ ? $_[0] : $_;
686              
687             # mb has no UTF-8 flag and no decode boundary, so the everyday operations
688             # are deliberately lenient (every octet is at least a one-byte character).
689             # mb::valid is the explicit, opt-in validity check for callers who do want
690             # to reject malformed input. It uses the STRICT unit -- $over_ascii (a
691             # well-formed multi-byte sequence) or a US-ASCII byte -- NOT the lenient
692             # $x, so any stray octet makes the whole string fail to match and the
693             # predicate returns false. The string itself is never modified.
694 39 100       1092 return /\A (?: $over_ascii | [\x00-\x7F] )* \z/xms ? 1 : 0;
695             }
696              
697             #---------------------------------------------------------------------
698             # require for MBCS encoding
699             sub mb::require (;$) {
700 5 50   8 0 1481 local $_ = @_ ? $_[0] : $_;
701              
702             # require perl version
703 5 50       19 if (/^[0-9]/) {
704 0 0       0 if ($] < $_) {
705 0         0 confess "Perl $_ required--this is only version $], stopped";
706             }
707             else {
708 0         0 undef $@;
709 0         0 return 1;
710             }
711             }
712              
713             # require expr
714             else {
715              
716             # find expr in @INC
717 5         5 my $file = $_;
718 5 50 33     34 if (($file =~ s{::}{/}g) or ($file !~ m{[\./\\]})) {
719 0         0 $file .= '.pm';
720             }
721 5 100       10 if (exists $INC{$file}) {
722 1         1 undef $@;
723 1 50       6 return 1 if $INC{$file};
724 0         0 confess "Compilation failed in require";
725             }
726 4         9 for my $prefix_file ($file, map { "$_/$file" } @INC) {
  32         42  
727 4 50       59 if (-f $prefix_file) {
728              
729             # poor "make"
730 4         45 (my $prefix_file_oo = $prefix_file) =~ s{\A (.*) \. ([^.]+) \z}{$1.oo.$2}xms;
731 4 0 33     129 if (
      33        
732             (not -e $prefix_file_oo) or
733             (mtime($prefix_file_oo) <= mtime($prefix_file)) or
734             (mtime($prefix_file_oo) <= mtime(__FILE__))
735             ) {
736 4 50       16 my $fh = mb::_open_r($prefix_file) or confess "$0(@{[__LINE__]}): can't open file: $prefix_file\n";
  0         0  
737 140     140   1033 local $_ = CORE::do { local $/; no strict 'refs'; readline(*{$fh}) };
  140         270  
  140         6960  
  4         19  
  4         14  
  4         4  
  4         97  
738 140     140   563 { no strict 'refs'; close($fh) }
  140         631  
  140         18850  
  4         6  
  4         31  
739              
740             # poor file locking
741 4     3   31 local $SIG{__DIE__} = sub { rmdir "$prefix_file.lock"; };
  0         0  
742 4 50       406 if (mkdir "$prefix_file.lock", 0755) {
743 4 50       21 my $fh = mb::_open_w($prefix_file_oo) or confess "$0(@{[__LINE__]}): can't open file: $prefix_file_oo\n";
  0         0  
744 140     140   830 { no strict 'refs'; print {*{$fh}} mb::_insert_source_encoding_unimport(mb::parse()) }
  140         346  
  140         6967  
  4         5  
  4         3  
  4         23  
745 140     140   592 { no strict 'refs'; close($fh) }
  140         265  
  140         181044  
  4         4  
  4         9  
  4         150  
746 4         304 rmdir "$prefix_file.lock";
747             }
748             else {
749 0         0 confess "$0(@{[__LINE__]}): can't mkdir: $prefix_file.lock\n";
  0         0  
750             }
751             }
752 4         15 $INC{$_} = $prefix_file_oo;
753              
754             # run as Perl script
755             # must use CORE::do to use , because CORE::eval cannot do it.
756 4         5 local $@;
757 4         249 my $result = CORE::eval sprintf(<<'END', (caller)[0,2,1]);
758             package %s;
759             #line %s "%s"
760             CORE::do "$prefix_file_oo";
761             END
762              
763             # return result
764 4 50       312 if ($@) {
    50          
765 0         0 $INC{$_} = undef;
766 0         0 confess $@;
767             }
768             elsif (not $result) {
769 0         0 delete $INC{$_};
770 0         0 confess "$_ did not return true value";
771             }
772             else {
773 4         25 return $result;
774             }
775             }
776             }
777 0         0 confess "Can't find $_ in \@INC";
778             }
779             }
780              
781             #---------------------------------------------------------------------
782             # reverse() for MBCS encoding
783             sub mb::reverse (@) {
784              
785             # in list context,
786 10 100   13 0 244 if (wantarray) {
787              
788             # returns a list value consisting of the elements of @_ in the opposite order
789 2         4 return CORE::reverse @_;
790             }
791              
792             # in scalar context,
793             else {
794              
795             # returns a string value with all characters in the opposite order of
796 8 100       115 return (join '',
797             CORE::reverse(
798             @_ ?
799             join('',@_) =~ /\G$x/g : # concatenates the elements of @_
800             /\G$x/g # $_ when without arguments
801             )
802             );
803             }
804             }
805              
806             #---------------------------------------------------------------------
807             # rindex() for MBCS encoding
808             sub mb::rindex ($$;$) {
809 8     11 0 237 my $rindex = 0;
810 8 100       16 if (@_ == 3) {
811 4         88 $rindex = mb::rindex_byte($_[0], $_[1], CORE::length(mb::substr($_[0], 0, $_[2])));
812             }
813             else {
814 4         7 $rindex = mb::rindex_byte($_[0], $_[1]);
815             }
816 8 100       13 if ($rindex == -1) {
817 4         7 return -1;
818             }
819             else {
820 4         10 return mb::length(CORE::substr $_[0], 0, $rindex);
821             }
822             }
823              
824             #---------------------------------------------------------------------
825             # JPerl like rindex() for MBCS encoding
826             sub mb::rindex_byte ($$;$) {
827 16     19 0 328 my($str,$substr,$position) = @_;
828 16   66     43 $position ||= CORE::length($str) - 1;
829 16         16 my $pos = 0;
830 16         12 my $rindex = -1;
831 16   100     44 while (($pos < CORE::length($str)) and ($pos <= $position)) {
832 230 100       301 if (CORE::substr($str,$pos,CORE::length($substr)) eq $substr) {
833 20         19 $rindex = $pos;
834             }
835 230 50       706 if (CORE::substr($str,$pos) =~ /\A($x)/xms) {
836 230         520 $pos += CORE::length($1);
837             }
838             else {
839 0         0 $pos += 1;
840             }
841             }
842 16         30 return $rindex;
843             }
844              
845             #---------------------------------------------------------------------
846             # set OSNAME
847             sub mb::set_OSNAME ($) {
848 0     3 0 0 $OSNAME = $_[0];
849             }
850              
851             #---------------------------------------------------------------------
852             # get OSNAME
853             sub mb::get_OSNAME () {
854 0     3 0 0 return $OSNAME;
855             }
856              
857             #---------------------------------------------------------------------
858             # set script encoding name and more
859             sub mb::set_script_encoding ($) {
860 244     247 0 11499564 $script_encoding = $_[0];
861              
862             # over US-ASCII
863             $over_ascii = {
864             'sjis' => '(?>[\x81-\x9F\xE0-\xFC][\x00-\xFF]|[\x80-\xFF])', # shift_jis ANSI/OEM Japanese; Japanese (Shift-JIS)
865             'gbk' => '(?>[\x81-\xFE][\x00-\xFF])', # gb2312 ANSI/OEM Simplified Chinese (PRC, Singapore); Chinese Simplified (GB2312)
866             'uhc' => '(?>[\x81-\xFE][\x00-\xFF])', # ks_c_5601-1987 ANSI/OEM Korean (Unified Hangul Code)
867             'big5' => '(?>[\x81-\xFE][\x00-\xFF])', # big5 ANSI/OEM Traditional Chinese (Taiwan; Hong Kong SAR, PRC); Chinese Traditional (Big5)
868             'big5hkscs' => '(?>[\x81-\xFE][\x00-\xFF])', # HKSCS support on top of traditional Chinese Windows
869             'eucjp' => '(?>[\xA1-\xFE][\x00-\xFF])', # EUC-JP Japanese (JIS 0208-1990 and 0121-1990)
870             'gb18030' => '(?>[\x81-\xFE][\x30-\x39][\x81-\xFE][\x30-\x39]|[\x81-\xFE][\x00-\xFF])', # GB18030 Windows XP and later: GB18030 Simplified Chinese (4 byte); Chinese Simplified (GB18030)
871             'rfc2279' => '(?>[\xC2-\xDF][\x80-\xBF]|[\xE0-\xEF][\x80-\xBF][\x80-\xBF]|[\xF0-\xF4][\x80-\xBF][\x80-\xBF][\x80-\xBF])', # utf-8 Unicode (UTF-8) RFC2279
872             'utf8' => '(?>[\xE1-\xEC][\x80-\xBF][\x80-\xBF]|[\xC2-\xDF][\x80-\xBF]|[\xEE-\xEF][\x80-\xBF][\x80-\xBF]|[\xF0-\xF0][\x90-\xBF][\x80-\xBF][\x80-\xBF]|[\xE0-\xE0][\xA0-\xBF][\x80-\xBF]|[\xED-\xED][\x80-\x9F][\x80-\xBF]|[\xF1-\xF3][\x80-\xBF][\x80-\xBF][\x80-\xBF]|[\xF4-\xF4][\x80-\x8F][\x80-\xBF][\x80-\xBF])', # utf-8 Unicode (UTF-8) optimized RFC3629 for ja_JP
873             'wtf8' => '(?>[\xE1-\xEF][\x80-\xBF][\x80-\xBF]|[\xC2-\xDF][\x80-\xBF]|[\xE0-\xE0][\xA0-\xBF][\x80-\xBF]|[\xF0-\xF0][\x90-\xBF][\x80-\xBF][\x80-\xBF]|[\xF1-\xF3][\x80-\xBF][\x80-\xBF][\x80-\xBF]|[\xF4-\xF4][\x80-\x8F][\x80-\xBF][\x80-\xBF])', # optimized WTF-8 for ja_JP
874 244   50     4104 }->{$script_encoding} || '[\x80-\xFF]';
875              
876             # supports qr/./ in MBCS script
877             #
878             # NOTE (0.64 step 4 read-only audit): this transpile-path $x is kept as a
879             # qr// OBJECT on purpose. A qr// interpolates into another pattern as a
880             # modifier-isolated subpattern ((?^...:...) / (?-xism:...)); the transpile
881             # path relies on that isolation when $x is embedded inside /x and escape
882             # contexts. Re-expressing $x as a plain string (the form used by mb8 and
883             # by the local $x inside _r2_qr) drops that wrapper and regresses the
884             # qr-as-q / s-as-q escape transpilation (observed: 406 failures on perl
885             # 5.38). So the "mitigation B" stringification is NOT applied here; the
886             # file-scoped $x stays a qr// object and stays STRICT ([\x00-\x7F]).
887             # Read-only safety on perl 5.005_03 is not needed for this $x: it is only
888             # ever interpolated into search patterns, never the target of a
889             # destructive s///. The runtime engine that DOES need a writable copy
890             # (_r2_qr) already takes one via my $source = "$_[0]".
891 244         26758 $x = qr/(?>$over_ascii|[\x00-\x7F])/;
892              
893             # regexp of multi-byte anchoring
894              
895             # Quantifiers
896             # {n,m} --- Match at least n but not more than m times
897             #
898             # n and m are limited to non-negative integral values less than a
899             # preset limit defined when perl is built. This is usually 32766 on
900             # the most common platforms.
901             #
902             # The following code is an attempt to solve the above limitations
903             # in a multi-byte anchoring.
904             #
905             # avoid "Segmentation fault" and "Error: Parse exception"
906             #
907             # perl5101delta
908             # http://perldoc.perl.org/perl5101delta.html
909             # In 5.10.0, the * quantifier in patterns was sometimes treated as {0,32767}
910             # [RT #60034, #60464]. For example, this match would fail:
911             # ("ab" x 32768) =~ /^(ab)*$/
912             #
913             # SEE ALSO
914             #
915             # Complex regular subexpression recursion limit
916             # http://www.perlmonks.org/?node_id=810857
917             #
918             # regexp iteration limits
919             # http://www.nntp.perl.org/group/perl.perl5.porters/2009/02/msg144065.html
920             #
921             # latest Perl won't match certain regexes more than 32768 characters long
922             # http://stackoverflow.com/questions/26226630/latest-perl-wont-match-certain-regexes-more-than-32768-characters-long
923             #
924             # Break through the limitations of regular expressions of Perl
925             # http://d.hatena.ne.jp/gfx/20110212/1297512479
926             #
927             # REG_INF has been raised from 65,536 to 2,147,483,647
928             # https://perldoc.perl.org/perl5380delta#REG_INF-has-been-raised-from-65,536-to-2,147,483,647
929              
930 244 100       2089 if ($script_encoding =~ /\A (?: rfc2279 | utf8 | wtf8 ) \z/xms) {
    50          
    0          
    0          
931 140         370 ${mb::_anchor} = qr{.*?}xms;
932             }
933             elsif ($] >= 5.038000) {
934             ${mb::_anchor} = {
935             'sjis' => qr{(?(?=.{0,2147483646}\z)(?:$x)*?|(?(?=[^\x81-\x9F\xE0-\xFC]+\z).*?|.*?[^\x81-\x9F\xE0-\xFC](?>[\x81-\x9F\xE0-\xFC][\x81-\x9F\xE0-\xFC])*?))}xms,
936             'eucjp' => qr{(?(?=.{0,2147483646}\z)(?:$x)*?|(?(?=[^\xA1-\xFE\xA1-\xFE]+\z).*?|.*?[^\xA1-\xFE\xA1-\xFE](?>[\xA1-\xFE\xA1-\xFE][\xA1-\xFE\xA1-\xFE])*?))}xms,
937             'gbk' => qr{(?(?=.{0,2147483646}\z)(?:$x)*?|(?(?=[^\x81-\xFE\x81-\xFE]+\z).*?|.*?[^\x81-\xFE\x81-\xFE](?>[\x81-\xFE\x81-\xFE][\x81-\xFE\x81-\xFE])*?))}xms,
938             'uhc' => qr{(?(?=.{0,2147483646}\z)(?:$x)*?|(?(?=[^\x81-\xFE\x81-\xFE]+\z).*?|.*?[^\x81-\xFE\x81-\xFE](?>[\x81-\xFE\x81-\xFE][\x81-\xFE\x81-\xFE])*?))}xms,
939             'big5' => qr{(?(?=.{0,2147483646}\z)(?:$x)*?|(?(?=[^\x81-\xFE\x81-\xFE]+\z).*?|.*?[^\x81-\xFE\x81-\xFE](?>[\x81-\xFE\x81-\xFE][\x81-\xFE\x81-\xFE])*?))}xms,
940             'big5hkscs' => qr{(?(?=.{0,2147483646}\z)(?:$x)*?|(?(?=[^\x81-\xFE\x81-\xFE]+\z).*?|.*?[^\x81-\xFE\x81-\xFE](?>[\x81-\xFE\x81-\xFE][\x81-\xFE\x81-\xFE])*?))}xms,
941             'gb18030' => qr{(?(?=.{0,2147483646}\z)(?:$x)*?|(?(?=[^\x81-\xFE\x81-\xFE]+\z).*?|.*?[^\x81-\xFE\x81-\xFE](?>[\x81-\xFE\x81-\xFE][\x81-\xFE\x81-\xFE])*?))}xms,
942 104   50     50641 }->{$script_encoding} || die;
943             }
944             elsif ($] >= 5.030000) {
945             ${mb::_anchor} = {
946             'sjis' => qr{(?(?=.{0,65534}\z)(?:$x)*?|(?(?=[^\x81-\x9F\xE0-\xFC]+\z).*?|.*?[^\x81-\x9F\xE0-\xFC](?>[\x81-\x9F\xE0-\xFC][\x81-\x9F\xE0-\xFC])*?))}xms,
947             'eucjp' => qr{(?(?=.{0,65534}\z)(?:$x)*?|(?(?=[^\xA1-\xFE\xA1-\xFE]+\z).*?|.*?[^\xA1-\xFE\xA1-\xFE](?>[\xA1-\xFE\xA1-\xFE][\xA1-\xFE\xA1-\xFE])*?))}xms,
948             'gbk' => qr{(?(?=.{0,65534}\z)(?:$x)*?|(?(?=[^\x81-\xFE\x81-\xFE]+\z).*?|.*?[^\x81-\xFE\x81-\xFE](?>[\x81-\xFE\x81-\xFE][\x81-\xFE\x81-\xFE])*?))}xms,
949             'uhc' => qr{(?(?=.{0,65534}\z)(?:$x)*?|(?(?=[^\x81-\xFE\x81-\xFE]+\z).*?|.*?[^\x81-\xFE\x81-\xFE](?>[\x81-\xFE\x81-\xFE][\x81-\xFE\x81-\xFE])*?))}xms,
950             'big5' => qr{(?(?=.{0,65534}\z)(?:$x)*?|(?(?=[^\x81-\xFE\x81-\xFE]+\z).*?|.*?[^\x81-\xFE\x81-\xFE](?>[\x81-\xFE\x81-\xFE][\x81-\xFE\x81-\xFE])*?))}xms,
951             'big5hkscs' => qr{(?(?=.{0,65534}\z)(?:$x)*?|(?(?=[^\x81-\xFE\x81-\xFE]+\z).*?|.*?[^\x81-\xFE\x81-\xFE](?>[\x81-\xFE\x81-\xFE][\x81-\xFE\x81-\xFE])*?))}xms,
952             'gb18030' => qr{(?(?=.{0,65534}\z)(?:$x)*?|(?(?=[^\x81-\xFE\x81-\xFE]+\z).*?|.*?[^\x81-\xFE\x81-\xFE](?>[\x81-\xFE\x81-\xFE][\x81-\xFE\x81-\xFE])*?))}xms,
953 0   0     0 }->{$script_encoding} || die;
954             }
955             elsif ($] >= 5.010001) {
956             ${mb::_anchor} = {
957             'sjis' => qr{(?(?=.{0,32766}\z)(?:$x)*?|(?(?=[^\x81-\x9F\xE0-\xFC]+\z).*?|.*?[^\x81-\x9F\xE0-\xFC](?>[\x81-\x9F\xE0-\xFC][\x81-\x9F\xE0-\xFC])*?))}xms,
958             'eucjp' => qr{(?(?=.{0,32766}\z)(?:$x)*?|(?(?=[^\xA1-\xFE\xA1-\xFE]+\z).*?|.*?[^\xA1-\xFE\xA1-\xFE](?>[\xA1-\xFE\xA1-\xFE][\xA1-\xFE\xA1-\xFE])*?))}xms,
959             'gbk' => qr{(?(?=.{0,32766}\z)(?:$x)*?|(?(?=[^\x81-\xFE\x81-\xFE]+\z).*?|.*?[^\x81-\xFE\x81-\xFE](?>[\x81-\xFE\x81-\xFE][\x81-\xFE\x81-\xFE])*?))}xms,
960             'uhc' => qr{(?(?=.{0,32766}\z)(?:$x)*?|(?(?=[^\x81-\xFE\x81-\xFE]+\z).*?|.*?[^\x81-\xFE\x81-\xFE](?>[\x81-\xFE\x81-\xFE][\x81-\xFE\x81-\xFE])*?))}xms,
961             'big5' => qr{(?(?=.{0,32766}\z)(?:$x)*?|(?(?=[^\x81-\xFE\x81-\xFE]+\z).*?|.*?[^\x81-\xFE\x81-\xFE](?>[\x81-\xFE\x81-\xFE][\x81-\xFE\x81-\xFE])*?))}xms,
962             'big5hkscs' => qr{(?(?=.{0,32766}\z)(?:$x)*?|(?(?=[^\x81-\xFE\x81-\xFE]+\z).*?|.*?[^\x81-\xFE\x81-\xFE](?>[\x81-\xFE\x81-\xFE][\x81-\xFE\x81-\xFE])*?))}xms,
963             'gb18030' => qr{(?(?=.{0,32766}\z)(?:$x)*?|(?(?=[^\x81-\xFE\x81-\xFE]+\z).*?|.*?[^\x81-\xFE\x81-\xFE](?>[\x81-\xFE\x81-\xFE][\x81-\xFE\x81-\xFE])*?))}xms,
964 0   0     0 }->{$script_encoding} || die;
965             }
966             else {
967 0         0 ${mb::_anchor} = qr{(?:$x)*?}xms;
968             }
969              
970             # codepoint class shortcuts in qq-like regular expression
971 244         2361 @{mb::_dot} = "(?>$over_ascii|.)"; # supports /s modifier by /./
972 244         831 @{mb::_B} = "(?:(?
973 244         965 @{mb::_D} = "(?:(?![0-9])$x)";
974 244         743 @{mb::_H} = "(?:(?![\\x09\\x20])$x)";
975 244         713 @{mb::_N} = "(?:(?!\\n)$x)";
976 244         522 @{mb::_R} = "(?>\\r\\n|[\\x0A\\x0B\\x0C\\x0D])";
977 244         696 @{mb::_S} = "(?:(?![\\t\\n\\f\\r\\x20])$x)";
978 244         693 @{mb::_V} = "(?:(?![\\x0A\\x0B\\x0C\\x0D])$x)";
979 244         758 @{mb::_W} = "(?:(?![A-Za-z0-9_])$x)";
980 244         1353 @{mb::_b} = "(?:(?
981 244         521 @{mb::_d} = "[0-9]";
982 244         457 @{mb::_h} = "[\\x09\\x20]";
983 244         505 @{mb::_s} = "[\\t\\n\\f\\r\\x20]";
984 244         418 @{mb::_v} = "[\\x0A\\x0B\\x0C\\x0D]";
985 244         646 @{mb::_w} = "[A-Za-z0-9_]";
986             }
987              
988             #---------------------------------------------------------------------
989             # get script encoding name
990             sub mb::get_script_encoding () {
991 683824     683827 0 2652792 return $script_encoding;
992             }
993              
994             #---------------------------------------------------------------------
995             # get old package name
996             sub mb::get_old_package () {
997             return {qw(
998             sjis Sjis::
999             gbk GBK::
1000             uhc UHC::
1001             big5 Big5::
1002             big5hkscs Big5HKSCS::
1003             eucjp EUCJP::
1004             gb18030 GB18030::
1005             rfc2279 RFC2279::
1006             utf8 UTF2::
1007             wtf8 WTF8::
1008 683822   50 683825 0 3794486 )}->{mb::get_script_encoding()} || die;
1009             }
1010              
1011             #---------------------------------------------------------------------
1012             # substr() for MBCS encoding
1013             BEGIN {
1014 140 50 100 140 0 323018 CORE::eval sprintf <<'END', ($] >= 5.014) ? ':lvalue' : '';
  50 100   3   2926  
  50 100   53   182  
  2 100       7  
  48 50       81  
  16 100       32  
  16 50       27  
  16 100       28  
  24 100       110  
  24 100       101  
  24         77  
  24         212  
  8         21  
  8         42  
1015             # VV------------------------AAAAAAA
1016             sub mb::substr ($$;$$) %s {
1017             my @x = $_[0] =~ /\G$x/g;
1018              
1019             # If the substring is beyond either end of the string, substr() returns the undefined
1020             # value and produces a warning. When used as an lvalue, specifying a substring that
1021             # is entirely outside the string raises an exception.
1022             # http://perldoc.perl.org/functions/substr.html
1023              
1024             # A return with no argument returns the scalar value undef in scalar context,
1025             # an empty list () in list context, and (naturally) nothing at all in void
1026             # context.
1027              
1028             if (($_[1] < (-1 * scalar(@x))) or (+1 * scalar(@x) < $_[1])) {
1029             return;
1030             }
1031              
1032             # substr($string,$offset,$length,$replacement)
1033             if (@_ == 4) {
1034             my $substr = join '', splice @x, $_[1], $_[2], $_[3];
1035             $_[0] = join '', @x;
1036             $substr; # "return $substr" doesn't work, don't write "return"
1037             }
1038              
1039             # substr($string,$offset,$length)
1040             elsif (@_ == 3) {
1041             local $SIG{__WARN__} = sub {}; # avoid: Use of uninitialized value in join or string at here
1042             my $octet_offset =
1043             ($_[1] < 0) ? -1 * CORE::length(join '', @x[$#x+$_[1]+1 .. $#x]) :
1044             ($_[1] > 0) ? CORE::length(join '', @x[0 .. $_[1]-1]) :
1045             0;
1046             my $octet_length =
1047             ($_[2] < 0) ? -1 * CORE::length(join '', @x[$#x+$_[2]+1 .. $#x]) :
1048             ($_[2] > 0) ? CORE::length(join '', @x[$_[1] .. $_[1]+$_[2]-1]) :
1049             0;
1050             CORE::substr($_[0], $octet_offset, $octet_length);
1051             }
1052              
1053             # substr($string,$offset)
1054             else {
1055             my $octet_offset =
1056             ($_[1] < 0) ? -1 * CORE::length(join '', @x[$#x+$_[1]+1 .. $#x]) :
1057             ($_[1] > 0) ? CORE::length(join '', @x[0 .. $_[1]-1]) :
1058             0;
1059             CORE::substr($_[0], $octet_offset);
1060             }
1061             }
1062             END
1063             }
1064              
1065             #---------------------------------------------------------------------
1066             # tr/// and y/// for MBCS encoding
1067             sub mb::tr ($$$;$) {
1068 2530     2533 0 433658 my @x = $_[0] =~ /\G($x)/xmsg;
1069 2530         11380 my @search = list_all_ASCII_by_hyphen($_[1] =~ /\G(\\-|$x)/xmsg);
1070 2530         9087 my @replacement = list_all_ASCII_by_hyphen($_[2] =~ /\G(\\-|$x)/xmsg);
1071 2530 100       6454 my %modifier = (defined $_[3]) ? (map { $_ => 1 } CORE::split //, $_[3]) : ();
  2753         7226  
1072              
1073 2530         3397 my %tr = ();
1074 2530         3818 for (my $i=0; $i <= $#search; $i++) {
1075              
1076             # tr/AAA/123/ works as tr/A/1/
1077 3388 100       5584 if (not exists $tr{$search[$i]}) {
1078              
1079             # tr/ABC/123/ makes %tr = ('A'=>'1','B'=>'2','C'=>'3',);
1080 3328 100 66     8672 if (defined($replacement[$i]) and ($replacement[$i] ne '')) {
    100 66        
    100          
1081 3123         6717 $tr{$search[$i]} = $replacement[$i];
1082             }
1083              
1084             # tr/ABC/12/d makes %tr = ('A'=>'1','B'=>'2','C'=>'',);
1085             elsif (exists $modifier{d}) {
1086 108         181 $tr{$search[$i]} = '';
1087             }
1088              
1089             # tr/ABC/12/ makes %tr = ('A'=>'1','B'=>'2','C'=>'2',);
1090             elsif (defined($replacement[-1]) and ($replacement[-1] ne '')) {
1091 89         147 $tr{$search[$i]} = $replacement[-1];
1092             }
1093              
1094             # tr/ABC// makes %tr = ('A'=>'A','B'=>'B','C'=>'C',);
1095             else {
1096 8         13 $tr{$search[$i]} = $search[$i];
1097             }
1098             }
1099             }
1100              
1101 2530         2771 my $tr = 0;
1102 2530         2608 my $replaced = '';
1103              
1104             # has /c modifier
1105 2530 100       3705 if (exists $modifier{c}) {
1106              
1107             # has /s modifier
1108 126 100       135 if (exists $modifier{s}) {
1109 54         53 my $last_transliterated = undef;
1110 54         83 while (defined(my $x = shift @x)) {
1111              
1112             # /c modifier works here
1113 428 100       417 if (exists $tr{$x}) {
1114 252         191 $replaced .= $x;
1115 252         353 $last_transliterated = undef;
1116             }
1117             else {
1118              
1119             # /d modifier works here
1120 176 100       203 if (exists $modifier{d}) {
    50          
1121             }
1122              
1123             elsif (defined $replacement[-1]) {
1124              
1125             # /s modifier works here
1126 52 100 66     82 if (defined($last_transliterated) and ($replacement[-1] eq $last_transliterated)) {
1127             }
1128              
1129             # tr/// works here
1130             else {
1131 43         40 $replaced .= ($last_transliterated = $replacement[-1]);
1132             }
1133             }
1134 176         215 $tr++;
1135             }
1136             }
1137             }
1138              
1139             # has no /s modifier
1140             else {
1141 72         107 while (defined(my $x = shift @x)) {
1142              
1143             # /c modifier works here
1144 314 100       292 if (exists $tr{$x}) {
1145 210         262 $replaced .= $x;
1146             }
1147             else {
1148              
1149             # /d modifier works here
1150 104 100       126 if (exists $modifier{d}) {
    50          
1151             }
1152              
1153             # tr/// works here
1154             elsif (defined $replacement[-1]) {
1155 70         52 $replaced .= $replacement[-1];
1156             }
1157 104         148 $tr++;
1158             }
1159             }
1160             }
1161             }
1162              
1163             # has no /c modifier
1164             else {
1165              
1166             # has /s modifier
1167 2404 100       3041 if (exists $modifier{s}) {
1168 85         73 my $last_transliterated = undef;
1169 85         124 while (defined(my $x = shift @x)) {
1170 593 100       578 if (exists $tr{$x}) {
1171              
1172             # /d modifier works here
1173 425 100 100     656 if ($tr{$x} eq '') {
    100          
1174             }
1175              
1176             # /s modifier works here
1177             elsif (defined($last_transliterated) and ($tr{$x} eq $last_transliterated)) {
1178             }
1179              
1180             # tr/// works here
1181             else {
1182 159         164 $replaced .= ($last_transliterated = $tr{$x});
1183             }
1184 425         512 $tr++;
1185             }
1186             else {
1187 168         134 $replaced .= $x;
1188 168         201 $last_transliterated = undef;
1189             }
1190             }
1191             }
1192              
1193             # has no /s modifier
1194             else {
1195 2319         4345 while (defined(my $x = shift @x)) {
1196 2749 100       3664 if (exists $tr{$x}) {
1197 2621         3289 $replaced .= $tr{$x};
1198 2621         4752 $tr++;
1199             }
1200             else {
1201 128         159 $replaced .= $x;
1202             }
1203             }
1204             }
1205             }
1206              
1207             # /r modifier works here
1208 2530 100       3387 if (exists $modifier{r}) {
1209 2362         12771 return $replaced;
1210             }
1211              
1212             # has no /r modifier
1213             else {
1214 168         156 $_[0] = $replaced;
1215 168         429 return $tr;
1216             }
1217             }
1218              
1219             #---------------------------------------------------------------------
1220             # universal uc() for MBCS encoding
1221             sub mb::uc (;$) {
1222 50 100   53 1 484 local $_ = @_ ? $_[0] : $_;
1223             # a A b B c C d D e E f F g G h H i I j J k K l L m M n N o O p P q Q r R s S t T u U v V w W x X y Y z Z
1224 50 100       784 return join '', map { {qw( a A b B c C d D e E f F g G h H i I j J k K l L m M n N o O p P q Q r R s S t T u U v V w W x X y Y z Z )}->{$_}||$_ } /\G$x/g;
  946         6469  
1225             # a A b B c C d D e E f F g G h H i I j J k K l L m M n N o O p P q Q r R s S t T u U v V w W x X y Y z Z
1226             }
1227              
1228             #---------------------------------------------------------------------
1229             # universal ucfirst() for MBCS encoding
1230             sub mb::ucfirst (;$) {
1231 2 100   5 0 107 local $_ = @_ ? $_[0] : $_;
1232 2 50       54 if (/\A($x)(.*)\z/s) {
1233 2         5 return mb::uc($1) . $2;
1234             }
1235             else {
1236 0         0 return '';
1237             }
1238             }
1239              
1240             ######################################################################
1241             # runtime routines on all operating systems (used automatically)
1242             ######################################################################
1243              
1244             #---------------------------------------------------------------------
1245             # implement of special variable $1,$2,$3,...
1246             sub mb::_CAPTURE (;$) {
1247 90 100   93   660 if ($mb::last_s_passed) {
1248 29 50       49 if (defined $_[0]) {
1249              
1250             # $1 is used for multi-byte anchoring
1251 29         1325 return CORE::eval('$' . ($_[0] + 1));
1252             }
1253             else {
1254 0         0 my @capture = ();
1255 0 0       0 if ($] >= 5.006) {
1256              
1257             # $1 is used for multi-byte anchoring in s///
1258 0         0 push @capture, map { CORE::eval('$'.$_) } 2 .. CORE::eval('$#-');
  0         0  
1259             }
1260             else {
1261              
1262             # @{^CAPTURE} doesn't work enough in perl 5.005
1263 0         0 for (my $n_th=2; defined(CORE::eval('$'.$n_th)); $n_th++) {
1264 0         0 push @capture, CORE::eval('$'.$n_th);
1265             }
1266             }
1267 0         0 return @capture;
1268             }
1269             }
1270             else {
1271 61 50       114 if (defined $_[0]) {
1272 61         3146 return CORE::eval('$' . $_[0]);
1273             }
1274             else {
1275 0         0 my @capture = ();
1276 0 0       0 if ($] >= 5.006) {
1277 0         0 push @capture, map { CORE::eval('$'.$_) } 1 .. CORE::eval('$#-');
  0         0  
1278             }
1279             else {
1280              
1281             # @{^CAPTURE} doesn't work enough in perl 5.005
1282 0         0 for (my $n_th=1; defined(CORE::eval('$'.$n_th)); $n_th++) {
1283 0         0 push @capture, CORE::eval('$'.$n_th);
1284             }
1285             }
1286 0         0 return @capture;
1287             }
1288             }
1289             }
1290              
1291             #---------------------------------------------------------------------
1292             # implement of special variable @+
1293             sub mb::_LAST_MATCH_END (@) {
1294              
1295             # perl 5.005 does not support @+, so it need CORE::eval
1296              
1297 10 100   13   51 if ($mb::last_s_passed) {
1298 5 50       11 if (scalar(@_) >= 1) {
1299 5         401 return CORE::eval q{ ($+[0], @+[2..$#-])[ @_ ] };
1300             }
1301             else {
1302 0         0 return CORE::eval q{ ($+[0], @+[2..$#-]) };
1303             }
1304             }
1305             else {
1306 5 50       8 if (scalar(@_) >= 1) {
1307 5         167 return CORE::eval q{ @+[ @_ ] };
1308             }
1309             else {
1310 0         0 return CORE::eval q{ @+ };
1311             }
1312             }
1313             }
1314              
1315             #---------------------------------------------------------------------
1316             # implement of special variable @-
1317             sub mb::_LAST_MATCH_START (@) {
1318              
1319             # perl 5.005 does not support @-, so it need CORE::eval
1320              
1321 18 100   21   40 if ($mb::last_s_passed) {
1322 9 50       21 if (scalar(@_) >= 1) {
1323 9         715 return CORE::eval q{ ($-[2], @-[2..$#-])[ @_ ] };
1324             }
1325             else {
1326 0         0 return CORE::eval q{ ($-[2], @-[2..$#-]) };
1327             }
1328             }
1329             else {
1330 9 50       13 if (scalar(@_) >= 1) {
1331 9         341 return CORE::eval q{ @-[ @_ ] };
1332             }
1333             else {
1334 0         0 return CORE::eval q{ @- };
1335             }
1336             }
1337             }
1338              
1339             #---------------------------------------------------------------------
1340             # implement of special variable $&
1341             sub mb::_MATCH () {
1342 61 50   64   585 if (defined $&) {
1343 61 100       95 if ($mb::last_s_passed) {
1344 8 50 33     54 if (defined($1) and (CORE::substr($&, 0, CORE::length($1)) eq $1)) {
1345 8         127 return CORE::substr($&, CORE::length($1));
1346             }
1347             else {
1348 0         0 confess 'Use of "$&", $MATCH, and ${^MATCH} need to /( capture all )/ in regexp';
1349             }
1350             }
1351             else {
1352 53 50 33     279 if (defined($1) and (CORE::substr($&, -CORE::length($1)) eq $1)) {
1353 53         879 return $1;
1354             }
1355             else {
1356 0         0 confess 'Use of "$&", $MATCH, and ${^MATCH} need to /( capture all )/ in regexp';
1357             }
1358             }
1359             }
1360             else {
1361 0         0 return '';
1362             }
1363             }
1364              
1365             #---------------------------------------------------------------------
1366             # implement of special variable $`
1367             sub mb::_PREMATCH () {
1368 15 50   18   137 if (defined $&) {
1369 15 100       23 if ($mb::last_s_passed) {
1370 8         166 return $1;
1371             }
1372             else {
1373 7 50 33     40 if (defined($1) and (CORE::substr($&,-CORE::length($1)) eq $1)) {
1374 7         98 return CORE::substr($&, 0, -CORE::length($1));
1375             }
1376             else {
1377 0         0 confess 'Use of "$`", $PREMATCH, and ${^PREMATCH} need to /( capture all )/ in regexp';
1378             }
1379             }
1380             }
1381             else {
1382 0         0 return '';
1383             }
1384             }
1385              
1386             #---------------------------------------------------------------------
1387             # flag off if last m// was pass
1388             sub mb::_m_passed () {
1389 118483     118486   579797 $mb::last_s_passed = 0;
1390 118483         23368175 return '';
1391             }
1392              
1393             #---------------------------------------------------------------------
1394             # flag on if last s/// was pass
1395             sub mb::_s_passed () {
1396 85     88   124263 $mb::last_s_passed = 1;
1397 85         8081 return '';
1398             }
1399              
1400             #---------------------------------------------------------------------
1401             # ignore space of m/[here]/xx, qr/[here]/xx, s/[here]//xx
1402             sub mb::_ignore_space ($) {
1403 33     36   40 my($has_space) = @_;
1404 33         34 my $has_no_space = '';
1405              
1406             # parse into elements
1407 33         439 while ($has_space =~ /\G (
1408             \(\? \^? [a-z]* [:\)] | # cloister (?^x) (?^x: ...
1409             \(\? \^? [a-z]*-[a-z]+ [:\)] | # cloister (?^x-y) (?^x-y: ...
1410             \[ ((?: \\@{mb::_dot} | @{mb::_dot} )+?) \] |
1411             \\x\{ [0-9A-Fa-f]{2} \} |
1412             \\o\{ [0-7]{3} \} |
1413             \\x [0-9A-Fa-f]{2} |
1414             \\ [0-7]{3} |
1415             \\@{mb::_dot} |
1416             @{mb::_dot}
1417             ) /xmsgc) {
1418 424         540 my($element, $classmate) = ($1, $2);
1419              
1420             # in codepoint class
1421 424 100       433 if (defined $classmate) {
1422 33         50 $has_no_space .= '[';
1423 33         237 while ($classmate =~ /\G (
1424             \\x\{ [0-9A-Fa-f]{2} \} |
1425             \\o\{ [0-7]{3} \} |
1426             \\x [0-9A-Fa-f]{2} |
1427             \\ [0-7]{3} |
1428             \\@{mb::_dot} |
1429             @{mb::_dot}
1430             ) /xmsgc) {
1431 693         652 my $element = $1;
1432 693 100       1541 if ($element !~ /\A[$bare_s]\z/) {
1433 559         1611 $has_no_space .= $element;
1434             }
1435             }
1436 33         160 $has_no_space .= ']';
1437             }
1438              
1439             # out of codepoint class
1440             else {
1441 391         1818 $has_no_space .= $element;
1442             }
1443             }
1444 33         57 return $has_no_space;
1445             }
1446              
1447             #---------------------------------------------------------------------
1448             # ignore case of m//i, qr//i, s///i
1449             sub mb::_ignorecase ($) {
1450 64     67   423 my($has_case) = @_;
1451 64         88 my $has_no_case = '';
1452              
1453             # parse into elements
1454 64         1616 while ($has_case =~ /\G (
1455             \(\? \^? [a-z]* [:\)] | # cloister (?^x) (?^x: ...
1456             \(\? \^? [a-z]*-[a-z]+ [:\)] | # cloister (?^x-y) (?^x-y: ...
1457             \[ ((?: \\@{mb::_dot} | @{mb::_dot} )+?) \] |
1458             \\x\{ [0-9A-Fa-f]{2} \} |
1459             \\o\{ [0-7]{3} \} |
1460             \\x [0-9A-Fa-f]{2} |
1461             \\ [0-7]{3} |
1462             \\@{mb::_dot} |
1463             @{mb::_dot}
1464             ) /xmsgc) {
1465 512         867 my($element, $classmate) = ($1, $2);
1466              
1467             # in codepoint class
1468 512 100       564 if (defined $classmate) {
1469 60         53 $has_no_case .= '[';
1470 60         302 while ($classmate =~ /\G (
1471             \\x\{ [0-9A-Fa-f]{2} \} |
1472             \\o\{ [0-7]{3} \} |
1473             \\x [0-9A-Fa-f]{2} |
1474             \\ [0-7]{3} |
1475             \\@{mb::_dot} |
1476             @{mb::_dot}
1477             ) /xmsgc) {
1478 192         204 my $element = $1;
1479             $has_no_case .= {qw(
1480             A Aa a Aa
1481             B Bb b Bb
1482             C Cc c Cc
1483             D Dd d Dd
1484             E Ee e Ee
1485             F Ff f Ff
1486             G Gg g Gg
1487             H Hh h Hh
1488             I Ii i Ii
1489             J Jj j Jj
1490             K Kk k Kk
1491             L Ll l Ll
1492             M Mm m Mm
1493             N Nn n Nn
1494             O Oo o Oo
1495             P Pp p Pp
1496             Q Qq q Qq
1497             R Rr r Rr
1498             S Ss s Ss
1499             T Tt t Tt
1500             U Uu u Uu
1501             V Vv v Vv
1502             W Ww w Ww
1503             X Xx x Xx
1504             Y Yy y Yy
1505             Z Zz z Zz
1506 192   66     3109 )}->{$element} || $element;
1507             }
1508 60         278 $has_no_case .= ']';
1509             }
1510              
1511             # out of codepoint class
1512             else {
1513             $has_no_case .= {qw(
1514             A [Aa] a [Aa]
1515             B [Bb] b [Bb]
1516             C [Cc] c [Cc]
1517             D [Dd] d [Dd]
1518             E [Ee] e [Ee]
1519             F [Ff] f [Ff]
1520             G [Gg] g [Gg]
1521             H [Hh] h [Hh]
1522             I [Ii] i [Ii]
1523             J [Jj] j [Jj]
1524             K [Kk] k [Kk]
1525             L [Ll] l [Ll]
1526             M [Mm] m [Mm]
1527             N [Nn] n [Nn]
1528             O [Oo] o [Oo]
1529             P [Pp] p [Pp]
1530             Q [Qq] q [Qq]
1531             R [Rr] r [Rr]
1532             S [Ss] s [Ss]
1533             T [Tt] t [Tt]
1534             U [Uu] u [Uu]
1535             V [Vv] v [Vv]
1536             W [Ww] w [Ww]
1537             X [Xx] x [Xx]
1538             Y [Yy] y [Yy]
1539             Z [Zz] z [Zz]
1540 452   66     9607 )}->{$element} || $element;
1541             }
1542             }
1543 64         594 return qr{$has_no_case};
1544             }
1545              
1546             #---------------------------------------------------------------------
1547             # custom codepoint class in qq-like regular expression
1548             sub mb::_cc ($) {
1549 118274     118277   958299 my($classmate) = @_;
1550 118274 100       273811 if ($classmate =~ s{\A \^ }{}xms) {
1551 58975         117130 return '(?:(?!' . parse_re_codepoint_class($classmate) . ")$x)";
1552             }
1553             else {
1554 59299         108993 return '(?:(?=' . parse_re_codepoint_class($classmate) . ")$x)";
1555             }
1556             }
1557              
1558             #---------------------------------------------------------------------
1559             # makes clustered codepoint from string
1560             sub mb::_clustered_codepoint ($) {
1561 22 100   25   198 if (my @codepoint = $_[0] =~ /\G($x)/xmsgc) {
1562 10 100       24 if (CORE::length($codepoint[$#codepoint]) == 1) {
1563 5         80 return $_[0];
1564             }
1565             else {
1566 5         96 return join '', @codepoint[ 0 .. $#codepoint-1 ], "(?:$codepoint[$#codepoint])";
1567             }
1568             }
1569             else {
1570 12         201 return '';
1571             }
1572             }
1573              
1574             #---------------------------------------------------------------------
1575             # open for append -- returns glob-name string on success, "" on failure.
1576             # Works on Perl 5.005_03 and all later versions.
1577             # Always uses a unique numbered package glob (mb::FH::H) so that
1578             # concurrent callers each get their own IO slot.
1579             sub mb::_open_a ($) {
1580 0     3   0 $mb::_fh_seq++;
1581 0         0 my $fhn = "mb::FH::H$mb::_fh_seq";
1582 140 0   140   1090 { no strict 'refs'; open($fhn, ">> $_[0]") or return "" }
  140         291  
  140         17003  
  0         0  
  0         0  
1583 0         0 return $fhn;
1584             }
1585              
1586             #---------------------------------------------------------------------
1587             # open for read -- returns glob-name string on success, "" on failure.
1588             sub mb::_open_r ($) {
1589 15     18   20 $mb::_fh_seq++;
1590 15         32 my $fhn = "mb::FH::H$mb::_fh_seq";
1591 140 50   140   700 { no strict 'refs'; open($fhn, "< $_[0]") or return "" }
  140         306  
  140         13295  
  15         19  
  15         1204  
1592 15         72 return $fhn;
1593             }
1594              
1595             #---------------------------------------------------------------------
1596             # open for write -- returns glob-name string on success, "" on failure.
1597             sub mb::_open_w ($) {
1598 10     13   12 $mb::_fh_seq++;
1599 10         23 my $fhn = "mb::FH::H$mb::_fh_seq";
1600 140 50   140   644 { no strict 'refs'; open($fhn, "> $_[0]") or return "" }
  140         297  
  140         4024725  
  10         22  
  10         914  
1601 10         67 return $fhn;
1602             }
1603              
1604             #---------------------------------------------------------------------
1605             # split() runtime function (UTF8::R2 compatible)
1606             #
1607             # This is the runtime entry point that a path-3 user calls directly as
1608             # mb::split(...). It mirrors UTF8::R2::split so that scripts ported from the
1609             # UTF8::R2 environment behave identically. The transpiler does NOT use this;
1610             # transpiled "split" is rewritten to mb::_split() below, which is a separate,
1611             # more elaborate implementation tuned for the filter/modulino paths.
1612             #
1613             # Note: mb::qr() returns a plain regular-expression STRING (not a qr// object,
1614             # which matters on perl 5.005_03; see _r2_qr), so the pattern is interpolated
1615             # into a fresh qr{...} before it is handed to CORE::split.
1616             sub mb::split (;$$$) {
1617 56 100 100 59 0 1013 if (defined($_[0]) and (($_[0] eq '') or ($_[0] =~ /\A \( \? \^? [-a-z]* : \) \z/x))) {
    100 66        
    50          
    0          
1618 38 100       336 my @x = (defined($_[1]) ? $_[1] : $_) =~ /\G$x/g;
1619 38 100 100     78 if (defined($_[2]) and ($_[2] > 0) and (scalar(@x) > $_[2])) {
      100        
1620 12         38 @x = (@x[0..$_[2]-1-1], join('', @x[$_[2]-1..$#x]));
1621             }
1622 38 100       41 if (wantarray) {
1623 26         66 return @x;
1624             }
1625             else {
1626 12 50       14 if ($] < 5.012) {
1627 0 0       0 warn "Use of implicit split to \@_ is deprecated" if $^W;
1628 0         0 @_ = @x; # unlike camel book and perldoc saying, can return only scalar(@_), cannot @_
1629             }
1630 12         24 return scalar @x;
1631             }
1632             }
1633             elsif (@_ == 3) {
1634 12         19 return CORE::split qr{@{[mb::qr($_[0])]}}, $_[1], $_[2];
  12         19  
1635             }
1636             elsif (@_ == 2) {
1637 6         6 return CORE::split qr{@{[mb::qr($_[0])]}}, $_[1];
  6         14  
1638             }
1639             elsif (@_ == 1) {
1640 0         0 return CORE::split qr{@{[mb::qr($_[0])]}};
  0         0  
1641             }
1642             else {
1643 0         0 return CORE::split;
1644             }
1645             }
1646              
1647             #---------------------------------------------------------------------
1648             # split() for MBCS encoding
1649             sub mb::_split (;$$$) {
1650 336 100   339   7299 my $pattern = defined($_[0]) ? $_[0] : ' ';
1651 336 100       468 my $string = defined($_[1]) ? $_[1] : $_;
1652 336         374 my @split = ();
1653              
1654             # split's first argument is more consistently interpreted
1655             #
1656             # After some changes earlier in v5.17, split's behavior has been simplified:
1657             # if the PATTERN argument evaluates to a string containing one space, it is
1658             # treated the way that a literal string containing one space once was.
1659             # http://search.cpan.org/dist/perl-5.18.0/pod/perldelta.pod#split's_first_argument_is_more_consistently_interpreted
1660             # if $pattern is also omitted or is the literal space, " ", the function splits
1661             # on whitespace, /\s+/, after skipping any leading whitespace
1662              
1663 336 100       638 if ($pattern eq ' ') {
1664 108         227 $pattern = qr/\s+/;
1665 108         263 $string =~ s{\A \s+ }{}xms;
1666             }
1667              
1668             # count '(' in pattern
1669 336         354 my @parsed = ();
1670 336         347 my $modifier = '';
1671 336 100 100     1910 if ((($modifier) = $pattern =~ /\A \(\?\^? (.+?) [\)\-\:] /xms) and ($modifier =~ /x/xms)) {
1672 34         1043 @parsed = $pattern =~ m{ \G (
1673             \\ $x |
1674             \# .*? $ | # comment on /x modifier
1675             \(\?\# (?:$x)*? \) |
1676             \[ (?:$x)+? \] |
1677             \(\? |
1678             \(\+ |
1679             \(\* |
1680             $x |
1681             [\x00-\xFF]
1682             ) }xgc;
1683             }
1684             else {
1685 302         3607 @parsed = $pattern =~ m{ \G (
1686             \\ $x |
1687             \(\?\# (?:$x)*? \) |
1688             \[ (?:$x)+? \] |
1689             \(\? |
1690             \(\+ |
1691             \(\* |
1692             $x |
1693             [\x00-\xFF]
1694             ) }xgc;
1695             }
1696             my $last_match_no =
1697             1 + # first '(' is for substring
1698 336         535 scalar(grep { $_ eq '(' } @parsed); # other '(' are for pattern of split()
  2398         2616  
1699              
1700             # Repeated Patterns Matching a Zero-length Substring
1701             # https://perldoc.perl.org/perlre.html#Repeated-Patterns-Matching-a-Zero-length-Substring
1702 336 100       2416 my $substring_quantifier = ('' =~ / \A $pattern \z /xms) ? '+?' : '*?';
1703              
1704             # if $_[2] specified and positive
1705 336 100 100     685 if (defined($_[2]) and ($_[2] >= 1)) {
1706 21         21 my $limit = $_[2];
1707              
1708 21         1128 CORE::eval q{ no warnings }; # avoid: Complex regular subexpression recursion limit (nnnnn) exceeded at ...
1709              
1710             # gets substrings by repeat chopping by pattern
1711 21   100     461 while ((--$limit > 0) and ($string =~ s<\A((?:$x)$substring_quantifier)$pattern><>)) {
1712 42         78 for (my $n_th=1; $n_th <= $last_match_no; $n_th++) {
1713 42         1388 push @split, CORE::eval('$'.$n_th);
1714             }
1715             }
1716             }
1717              
1718             # if $_[2] is omitted or zero or negative
1719             else {
1720 315     5   16138 CORE::eval q{ no warnings }; # avoid: Complex regular subexpression recursion limit (nnnnn) exceeded at ...
  5     5   32  
  5         7  
  5         218  
  5         25  
  5         7  
  5         150  
1721              
1722             # gets substrings by repeat chopping by pattern
1723 315         7067 while ($string =~ s<\A((?:$x)$substring_quantifier)$pattern><>) {
1724 740         1337 for (my $n_th=1; $n_th <= $last_match_no; $n_th++) {
1725 792         23158 push @split, CORE::eval('$'.$n_th);
1726             }
1727             }
1728             }
1729              
1730             # get last substring
1731 336 100 100     607 if (CORE::length($string) > 0) {
    100          
1732 303         388 push @split, $string;
1733             }
1734             elsif (defined($_[2]) and ($_[2] >= 1)) {
1735 6 50       23 if (scalar(@split) < $_[2]) {
1736 6         13 push @split, ('') x ($_[2] - scalar(@split));
1737             }
1738             }
1739              
1740             # if $_[2] is omitted or zero, trailing null fields are stripped from the result
1741 336 100 100     649 if ((not defined $_[2]) or ($_[2] == 0)) {
1742 309   33     1019 while ((scalar(@split) >= 1) and ($split[-1] eq '')) {
1743 0         0 pop @split;
1744             }
1745             }
1746              
1747             # old days, split had write its result to @_ on scalar context,
1748             # but this usage is no longer supported
1749              
1750 336 100       493 if (wantarray) {
1751 203         1041 return @split;
1752             }
1753             else {
1754 133         491 return scalar @split;
1755             }
1756             }
1757              
1758             ######################################################################
1759             # runtime routines for MSWin32 (used automatically)
1760             ######################################################################
1761              
1762             #---------------------------------------------------------------------
1763             # chdir() for MSWin32
1764             sub mb::_chdir (;$) {
1765              
1766             # not on MSWin32 or UTF-8
1767 2 50 33 5   17 if (($OSNAME !~ /MSWin32/) or ($script_encoding !~ /\A (?: sjis | gbk | uhc | big5 | big5hkscs | gb18030 ) \z/xms)) {
1768 2 50       5 if (@_ == 0) {
1769 0         0 return CORE::chdir;
1770             }
1771             else {
1772 2         37 return CORE::chdir $_[0];
1773             }
1774             }
1775              
1776             # on MSWin32
1777 0 0 0     0 if (@_ == 0) {
    0 0        
    0          
1778 0         0 return CORE::chdir;
1779             }
1780             elsif (($script_encoding =~ /\A (?: sjis ) \z/xms) and ($_[0] =~ /\A $x* [\x81-\x9F\xE0-\xFC][\x5C] \z/xms)) {
1781 0 0       0 if (defined wantarray) {
1782 0         0 return 0;
1783             }
1784             else {
1785 0         0 confess "mb::_chdir: Can't chdir '$_[0]'\n";
1786             }
1787             }
1788             elsif (($script_encoding =~ /\A (?: gbk | uhc | big5 | big5hkscs | gb18030 ) \z/xms) and ($_[0] =~ /\A $x* [\x81-\xFE][\x5C] \z/xms)) {
1789 0 0       0 if (defined wantarray) {
1790 0         0 return 0;
1791             }
1792             else {
1793 0         0 confess "mb::_chdir: Can't chdir '$_[0]'\n";
1794             }
1795             }
1796             else {
1797 0         0 return CORE::chdir $_[0];
1798             }
1799             }
1800              
1801             #---------------------------------------------------------------------
1802             # stackable filetest -X -Y -Z for MSWin32
1803             sub mb::_filetest {
1804 11209     11212   48844 my @filetest = map { /(-[A-Za-z])/g } @{ shift(@_) };
  11217         52344  
  11209         23101  
1805 11209 0       25400 local $_ = @_ ? shift : (($filetest[-1] eq '-t') ? \*STDIN : $_);
    50          
1806 11209 50 33     20791 confess "Too many arguments for filetest @filetest" if @_ and not wantarray;
1807              
1808             # testee has "\x5C" octet at end
1809 11209 0 33     18909 if (
      33        
1810             ($OSNAME =~ /MSWin32/) and
1811             ($script_encoding =~ /\A (?: sjis | gbk | uhc | big5 | big5hkscs | gb18030 ) \z/xms) and
1812             /[\x5C]\z/
1813             ) {
1814 0         0 $_ = qq{$_.};
1815             }
1816              
1817             # supports stackable filetest
1818 11209         10880 my $result;
1819 11209         16204 my $filetest = pop @filetest;
1820 11209 100       477381 if ($result = CORE::eval($filetest . ' $_')) { # '$_' at 1st time, and ...
1821             }
1822             else {
1823 2043 50       21754 return wantarray ? ($result, @_) : $result;
1824             }
1825 9166         34173 for my $filetest (CORE::reverse @filetest) {
1826 7 50       248 if ($result = CORE::eval($filetest . ' _')) { # '_' at 2nd time or later
1827             }
1828             else {
1829 0 0       0 return wantarray ? ($result, @_) : $result;
1830             }
1831             }
1832 9166 50       83402 return wantarray ? ($result, @_) : $result;
1833             }
1834              
1835             #---------------------------------------------------------------------
1836             # lstat() for MSWin32
1837             sub mb::_lstat (;$) {
1838 3 50   6   40 local $_ = @_ ? $_[0] : $_;
1839 3 50       7 if ($_ eq '_') {
1840 0         0 confess qq{lstat doesn't support '_'\n};
1841             }
1842              
1843             # testee has "\x5C" octet at end
1844 3 0 33     4 if (
      33        
1845             ($OSNAME =~ /MSWin32/) and
1846             ($script_encoding =~ /\A (?: sjis | gbk | uhc | big5 | big5hkscs | gb18030 ) \z/xms) and
1847             /[\x5C]\z/
1848             ) {
1849 0         0 $_ = qq{$_.};
1850             }
1851              
1852 3         35 return CORE::lstat $_;
1853             }
1854              
1855             #---------------------------------------------------------------------
1856             # opendir() for MSWin32
1857             sub mb::_opendir ($$) {
1858 7 100   10   60 if (not defined $_[0]) {
1859 3         4 $_[0] = \do { local *_ };
  3         25  
1860             }
1861              
1862             # works on MSWin32 only
1863 7 50 33     23 if (($OSNAME !~ /MSWin32/) or ($script_encoding !~ /\A (?: sjis | gbk | uhc | big5 | big5hkscs | gb18030 ) \z/xms)) {
    0          
    0          
1864 7         211 return CORE::opendir $_[0], $_[1];
1865             }
1866             elsif (-d $_[1]) {
1867 0         0 return CORE::opendir $_[0], $_[1];
1868             }
1869             elsif (-d qq{$_[1].}) {
1870 0         0 return CORE::opendir $_[0], qq{$_[1].};
1871             }
1872 0         0 return undef;
1873             }
1874              
1875             #---------------------------------------------------------------------
1876             # stat() for MSWin32
1877             sub mb::_stat (;$) {
1878 9 50   12   244 local $_ = @_ ? $_[0] : $_;
1879              
1880             # testee has "\x5C" octet at end
1881 9 0 33     19 if (
      33        
1882             ($OSNAME =~ /MSWin32/) and
1883             ($script_encoding =~ /\A (?: sjis | gbk | uhc | big5 | big5hkscs | gb18030 ) \z/xms) and
1884             /[\x5C]\z/
1885             ) {
1886 0         0 $_ = qq{$_.};
1887             }
1888              
1889 9         61 return CORE::stat $_;
1890             }
1891              
1892             #---------------------------------------------------------------------
1893             # unlink() for MSWin32
1894             sub mb::_unlink (@) {
1895              
1896             # works on MSWin32 only
1897 10222 50 33 10225   58528 if (($OSNAME !~ /MSWin32/) or ($script_encoding !~ /\A (?: sjis | gbk | uhc | big5 | big5hkscs | gb18030 ) \z/xms)) {
1898 10222 50       622021 return CORE::unlink(@_ ? @_ : $_);
1899             }
1900              
1901 0         0 my $unlink = 0;
1902 0 0       0 for (@_ ? @_ : $_) {
1903 0 0       0 if (CORE::unlink) {
    0          
1904 0         0 $unlink++;
1905             }
1906             elsif (CORE::unlink qq{$_.}) {
1907 0         0 $unlink++;
1908             }
1909             }
1910 0         0 return $unlink;
1911             }
1912              
1913             ######################################################################
1914             # source code filter
1915             ######################################################################
1916              
1917             #---------------------------------------------------------------------
1918             # detect system encoding any of big5, big5hkscs, eucjp, gb18030, gbk, rfc2279, sjis, uhc, utf8, wtf8
1919             sub detect_system_encoding {
1920              
1921             # running on Microsoft Windows
1922 144 50   147 0 1157 if ($OSNAME =~ /MSWin32/) {
    50          
    50          
    50          
1923 0 0       0 if (my($codepage) = qx{chcp} =~ m/[^0123456789](932|936|949|950|951|20932|54936)\Z/) {
1924             return {qw(
1925             932 sjis
1926             936 gbk
1927             949 uhc
1928             950 big5
1929             951 big5hkscs
1930             20932 eucjp
1931             54936 gb18030
1932 0         0 )}->{$codepage};
1933             }
1934             else {
1935 0         0 return 'utf8';
1936             }
1937             }
1938              
1939             # running on Oracle Solaris
1940             elsif ($OSNAME =~ /solaris/) {
1941             my $LANG =
1942             defined($ENV{'LC_ALL'}) ? $ENV{'LC_ALL'} :
1943             defined($ENV{'LC_CTYPE'}) ? $ENV{'LC_CTYPE'} :
1944 0 0       0 defined($ENV{'LANG'}) ? $ENV{'LANG'} :
    0          
    0          
1945             '';
1946             return {qw(
1947             ja_JP.PCK sjis
1948             ja eucjp
1949             japanese eucjp
1950             ja_JP.eucJP eucjp
1951             zh gbk
1952             zh.GBK gbk
1953             zh_CN.GBK gbk
1954             zh_CN.EUC gbk
1955             zh_CN.GB18030 gb18030
1956             ko uhc
1957             ko_KR.EUC uhc
1958             zh_TW.BIG5 big5
1959             zh_HK.BIG5HK big5hkscs
1960 0   0     0 )}->{$LANG} || 'utf8';
1961             }
1962              
1963             # running on HP HP-UX
1964             elsif ($OSNAME =~ /hpux/) {
1965             my $LANG =
1966             defined($ENV{'LC_ALL'}) ? $ENV{'LC_ALL'} :
1967             defined($ENV{'LC_CTYPE'}) ? $ENV{'LC_CTYPE'} :
1968 0 0       0 defined($ENV{'LANG'}) ? $ENV{'LANG'} :
    0          
    0          
1969             '';
1970             return {qw(
1971             japanese sjis
1972             ja_JP.SJIS sjis
1973             japanese.euc eucjp
1974             ja_JP.eucJP eucjp
1975             zh_CN.hp15CN gbk
1976             zh_CN.gb18030 gb18030
1977             ko_KR.eucKR uhc
1978             zh_TW.big5 big5
1979             zh_HK.big5 big5hkscs
1980             zh_HK.hkbig5 big5hkscs
1981 0   0     0 )}->{$LANG} || 'utf8';
1982             }
1983              
1984             # running on IBM AIX
1985             elsif ($OSNAME =~ /aix/) {
1986             my $LANG =
1987             defined($ENV{'LC_ALL'}) ? $ENV{'LC_ALL'} :
1988             defined($ENV{'LC_CTYPE'}) ? $ENV{'LC_CTYPE'} :
1989 0 0       0 defined($ENV{'LANG'}) ? $ENV{'LANG'} :
    0          
    0          
1990             '';
1991             return {qw(
1992             Ja_JP sjis
1993             Ja_JP.IBM-943 sjis
1994             ja_JP eucjp
1995             ja_JP.IBM-eucJP eucjp
1996             zh_CN gbk
1997             zh_CN.IBM-eucCN gbk
1998             Zh_CN gb18030
1999             Zh_CN.GB18030 gb18030
2000             ko_KR uhc
2001             ko_KR.IBM-eucKR uhc
2002             Zh_TW big5
2003             Zh_TW.big-5 big5
2004             Zh_HK big5hkscs
2005             Zh_HK.BIG5-HKSCS big5hkscs
2006 0   0     0 )}->{$LANG} || 'utf8';
2007             }
2008              
2009             # running on Other Systems
2010             else {
2011             my $LANG =
2012             defined($ENV{'LC_ALL'}) ? $ENV{'LC_ALL'} :
2013             defined($ENV{'LC_CTYPE'}) ? $ENV{'LC_CTYPE'} :
2014 144 50       957 defined($ENV{'LANG'}) ? $ENV{'LANG'} :
    50          
    50          
2015             '';
2016             return {qw(
2017             japanese sjis
2018             ja_JP.SJIS sjis
2019             ja_JP.mscode sjis
2020             ja eucjp
2021             japan eucjp
2022             japanese.euc eucjp
2023             Japanese-EUC eucjp
2024             ja_JP eucjp
2025             ja_JP.ujis eucjp
2026             ja_JP.eucJP eucjp
2027             ja_JP.AJEC eucjp
2028             ja_JP.EUC eucjp
2029             Jp_JP eucjp
2030             zh_CN.EUC gbk
2031             zh_CN.GB2312 gbk
2032             zh_CN.hp15CN gbk
2033             zh_CN.gb18030 gb18030
2034             ko_KR.eucKR uhc
2035             zh_TW.Big5 big5
2036             zh_TW.big5 big5
2037             zh_HK.big5 big5hkscs
2038 144   50     3170 )}->{$LANG} || 'utf8';
2039             }
2040             }
2041              
2042             my @here_document_delimiter = ();
2043              
2044             #---------------------------------------------------------------------
2045             # parse script
2046             sub parse {
2047 136761 100   136764 0 5019968 local $_ = @_ ? $_[0] : $_;
2048              
2049             # Yes, I studied study yesterday, once again.
2050 136761         172171 study $_; # acts between perl 5.005 to perl 5.014
2051              
2052 136761         212204 @here_document_delimiter = ();
2053              
2054             # transpile JPerl script to Perl script
2055 136761         177044 my $parsed_script = '';
2056 136761         461573 while (not /\G \z /xmsgc) {
2057 680000         1022937 $parsed_script .= parse_expr();
2058             }
2059              
2060             # return octet-oriented Perl script
2061 136761         13276119 return $parsed_script;
2062             }
2063              
2064             #---------------------------------------------------------------------
2065             # Perl 5.42 introduces source::encoding and automatically enables
2066             # ASCII-only checking for "use v5.41" and later.
2067             #
2068             # mb transpiles scripts to mostly US-ASCII, but it intentionally keeps
2069             # comments and POD as-is. Those may contain multibyte characters.
2070             #
2071             # source::encoding is only activated when "use v5.41" or later appears
2072             # in the script. We append "no source::encoding;" on the same line as
2073             # the "use VERSION" statement (replacing any trailing semicolon first)
2074             # to avoid introducing extra lines that would shift line numbers in
2075             # error messages.
2076             sub _insert_source_encoding_unimport {
2077 67     70   600 my($script) = @_;
2078              
2079             # append "no source::encoding;" on the same line as "use v5.41" or later,
2080             # before any trailing comment, to avoid line number shifts in error messages.
2081             # matches: use v5.41; use v5.42; use 5.041; use 5.042; etc.
2082 67         259 $script =~ s{
2083             ( \buse \s+
2084             (?: v5\. (?:4[1-9]|[5-9]\d|\d{3,}) # use v5.41 and later
2085             | 5\.0(?:4[1-9]|[5-9]\d|\d{3,}) # use 5.041 and later
2086             )
2087             [^\n#;]* # rest of statement (no # or ;)
2088             )
2089             ;? # consume trailing semicolon
2090             ( [^\n]* ) # trailing comment (if any)
2091             ( (?:\r\n|\r|\n) ) # line ending
2092             }{$1; no source::encoding;$2$3}xmsg;
2093              
2094 67         216 return $script;
2095             }
2096              
2097             #---------------------------------------------------------------------
2098             # parse ambiguous characters
2099             sub parse_ambiguous_char {
2100 277314     277317 0 313648 my $parsed = '';
2101              
2102             # Ambiguous characters
2103             # --------------------------------------------------------
2104             # Character Operator Term
2105             # --------------------------------------------------------
2106             # % modulo %hash
2107             # & &, && &subroutine
2108             # ' package 'string'
2109             # * multiplication *typeglob
2110             # + addition unary plus
2111             # - subtraction unary minus
2112             # . concatenation .3333
2113             # / division /pattern/
2114             # < less than <>, ,
2115             # << left shift <>
2116             # ? ?: ?pattern?
2117             # --------------------------------------------------------
2118              
2119             # any term then operator
2120 277314 100       607142 if (m{\G ( \s* (?:
2121              
2122             # 12345 | 12345 | 12345 | 12345 | 12345 | 12345 |
2123             %= | % | # "\x25" [%] PERCENT SIGN (U+0025)
2124             &&= | && | &\.= | &\. | &= | & | # "\x26" [&] AMPERSAND (U+0026)
2125             \*\*= | \*\* | \*= | \* | # "\x2A" [*] ASTERISK (U+002A)
2126             \.\.\.| \.\. | \.= | \. | # "\x2E" [.] FULL STOP (U+002E)
2127             \/\/= | \/\/ | \/= | \/ | # "\x2F" [/] SOLIDUS (U+002F)
2128             <=> | << | <= | < | # "\x3C" [<] LESS-THAN SIGN (U+003C)
2129             \? # "\x3F" [?] QUESTION MARK (U+003F)
2130             )) }xmsgc) {
2131 123         186 $parsed .= $1;
2132             }
2133              
2134 277314         426170 return $parsed;
2135             }
2136              
2137             #---------------------------------------------------------------------
2138             # parse expression in script
2139             sub parse_expr {
2140 683699     683702 0 817318 my $parsed = '';
2141 683699         1033490 my $old_package = mb::get_old_package();
2142              
2143             # __END__ or __DATA__
2144 683699 100       12808419 if (/\G ^ ( (?: __END__ | __DATA__ ) $R .* ) \z/xmsgc) {
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    50          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    50          
    50          
    100          
    100          
    100          
    100          
    50          
    50          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    50          
    100          
    50          
    100          
    100          
    100          
    50          
    0          
2145 14         28 $parsed .= $1;
2146             }
2147              
2148             # =pod ... =cut
2149             elsif (/\G ^ ( = [A-Za-z_][A-Za-z_0-9]* [\x00-\xFF]*? $R =cut \b [^\n]* $R ) /xmsgc) {
2150 1         3 $parsed .= $1;
2151             }
2152              
2153             # "\r\n", "\r", "\n"
2154             elsif (/\G (?= $R ) /xmsgc) {
2155 8654         16291 while (my $here_document_delimiter = shift @here_document_delimiter) {
2156 23         21 my($delimiter, $quote_type) = @{$here_document_delimiter};
  23         30  
2157 23 100       38 if ($quote_type eq 'qq') {
    50          
2158 14         20 $parsed .= parse_heredocument_as_qq_endswith($delimiter);
2159             }
2160             elsif ($quote_type eq 'q') {
2161              
2162             # perlop > Quote-Like Operators > < Single Quotes
2163             #
2164             # Single quotes indicate the text is to be treated literally
2165             # with no interpolation of its content. This is similar to
2166             # single quoted strings except that backslashes have no special
2167             # meaning, with \\ being treated as two backslashes and not
2168             # one as they would in every other quoting construct.
2169             # https://perldoc.perl.org/perlop.html#Quote-Like-Operators
2170              
2171 9         16 $parsed .= parse_heredocument_as_q_endswith($delimiter);
2172             }
2173             else {
2174 0         0 die "$0(@{[__LINE__]}): $ARGV[0] here document delimiter '$delimiter' not found.\n";
  0         0  
2175             }
2176             }
2177             }
2178              
2179             # "\t"
2180             # "\x20" [ ] SPACE (U+0020)
2181             elsif (/\G ( [\t ]+ ) /xmsgc) {
2182 257411         473453 $parsed .= $1;
2183             }
2184              
2185             # "\x3B" [;] SEMICOLON (U+003B)
2186             elsif (/\G ( ; ) /xmsgc) {
2187 5233         9507 $parsed .= $1;
2188             }
2189              
2190             # balanced brackets
2191             # "\x28" [(] LEFT PARENTHESIS (U+0028)
2192             # "\x7B" [{] LEFT CURLY BRACKET (U+007B)
2193             # "\x5B" [[] LEFT SQUARE BRACKET (U+005B)
2194             elsif (/\G ( [(\{\[] ) /xmsgc) {
2195 552         1006 $parsed .= parse_expr_balanced($1);
2196 552         723 $parsed .= parse_ambiguous_char();
2197             }
2198              
2199             # version string
2200             # v102.111.111
2201             # 102.111.111
2202             elsif (/\G (
2203             v [0-9]+ (?: \.[0-9]+ ){1,} \b |
2204             [0-9]+ (?: \.[0-9]+ ){2,} \b
2205             ) /xmsgc) {
2206 2         3 my $v_string = $1;
2207 2         10 $parsed .= join('.', map { "mb::chr($_)" } ($v_string =~ /[0-9]+/g));
  8         13  
2208 2         4 $parsed .= parse_ambiguous_char();
2209             }
2210              
2211             # version string
2212             # v9786
2213             elsif (/\G v ( [0-9]+ ) \b (?! \s* => ) /xmsgc) {
2214 1         3 $parsed .= "mb::chr($1)";
2215 1         2 $parsed .= parse_ambiguous_char();
2216             }
2217              
2218             # numbers
2219             # "\x2E" [.] [0-9]
2220             # "\x30" [0] DIGIT ZERO (U+0030)
2221             # "\x31" [1] DIGIT ONE (U+0031)
2222             # "\x32" [2] DIGIT TWO (U+0032)
2223             # "\x33" [3] DIGIT THREE (U+0033)
2224             # "\x34" [4] DIGIT FOUR (U+0034)
2225             # "\x35" [5] DIGIT FIVE (U+0035)
2226             # "\x36" [6] DIGIT SIX (U+0036)
2227             # "\x37" [7] DIGIT SEVEN (U+0037)
2228             # "\x38" [8] DIGIT EIGHT (U+0038)
2229             # "\x39" [9] DIGIT NINE (U+0039)
2230             elsif (m{\G (
2231              
2232             # since Perl v5.22 adds hexadecimal floating point literals
2233             # https://perldoc.perl.org/perl5220delta#Floating-point-parsing-has-been-improved
2234             # https://perldoc.perl.org/5.32.0/perldata#Scalar-value-constructors
2235              
2236             # https://qiita.com/mod_poppo/items/3fa4cdc35f9bfb352ad5
2237             # https://qiita.com/mod_poppo/items/3fa4cdc35f9bfb352ad5#perl
2238             #
2239             # $ perl -l -e 'print(0x1.23); print(0x1.23p0)'
2240             # makes ==> 123
2241             # makes ==> 1.13671875
2242              
2243             0[Xx] [0-9A-Fa-f_]+ \. [0-9A-Fa-f_]* [Pp] [+-]? [0-9_]+ |
2244             0[Xx] \. [0-9A-Fa-f_]+ [Pp] [+-]? [0-9_]+ |
2245             0[Xx] [0-9A-Fa-f_]+ |
2246              
2247             # since perl v5.33.5 Core Enhancements New octal syntax 0oddddd
2248              
2249             0[Oo] [0-7_]+ |
2250             0 [0-7_]* |
2251              
2252             0[Bb] [01_]+ |
2253              
2254             [1-9] [0-9_]* \. [0-9_]* [Ee] [+-]? [0-9_]+ |
2255             [1-9] [0-9_]* |
2256             \. [0-9_]+ [Ee] [+-]? [0-9_]+ |
2257             \. [0-9_]+
2258              
2259             ) }xmsgc) {
2260 935         1350 $parsed .= $1;
2261 935         1170 $parsed .= parse_ambiguous_char();
2262             }
2263              
2264             # file test operators on MSWin32
2265             # "\x2D" [-] HYPHEN-MINUS (U+002D)
2266              
2267             # -X -Y -Z 'file' --> mb::_filetest [qw( -X -Y -Z )], 'file'
2268             # -X -Y -Z "file" --> mb::_filetest [qw( -X -Y -Z )], "file"
2269             # -X -Y -Z `file` --> mb::_filetest [qw( -X -Y -Z )], `file`
2270             # -X -Y -Z $file --> mb::_filetest [qw( -X -Y -Z )], $file
2271             # ..., and filetest any word except file handle or directory handle
2272             # -X -Y -Z m// --> mb::_filetest [qw( -X -Y -Z )], m//
2273             # -X -Y -Z q// --> mb::_filetest [qw( -X -Y -Z )], q//
2274             # -X -Y -Z qq// --> mb::_filetest [qw( -X -Y -Z )], qq//
2275             # -X -Y -Z qr// --> mb::_filetest [qw( -X -Y -Z )], qr//
2276             # -X -Y -Z qw// --> mb::_filetest [qw( -X -Y -Z )], qw//
2277             # -X -Y -Z qx// --> mb::_filetest [qw( -X -Y -Z )], qx//
2278             # -X -Y -Z s/// --> mb::_filetest [qw( -X -Y -Z )], s///
2279             # -X -Y -Z tr/// --> mb::_filetest [qw( -X -Y -Z )], tr///
2280             # -X -Y -Z y/// --> mb::_filetest [qw( -X -Y -Z )], y///
2281             # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
2282             # vvvvvvvvvvvv vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
2283             elsif (/\G ( (?: -[ABCMORSTWXbcdefgkloprstuwxz] \s* )+ \b ) (?= (?: \( \s* )* (?: ' | " | ` | \$ | (?: (?: m | q | qq | qr | qw | qx | s | tr | y ) \b )) ) /xmsgc) {
2284 0         0 $parsed .= "mb::_filetest [qw( $1 )], ";
2285             }
2286              
2287             # filetest file handle or directory handle
2288             # -X -Y -Z _ --> mb::_filetest [qw( -X -Y -Z )], \*_
2289             # -X -Y -Z FILE --> mb::_filetest [qw( -X -Y -Z )], \*FILE
2290             # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
2291             # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv vvvvvvvvvvvvvvvvvvvvvvvvvvvv
2292             elsif (/\G ( (?: -[ABCMORSTWXbcdefgkloprstuwxz] \s* )+ \b ) (?= [A-Za-z_][A-Za-z0-9_]* ) /xmsgc) {
2293 2828         9545 $parsed .= "mb::_filetest [qw( $1)], ";
2294 2828         4056 $parsed .= '\\*';
2295             }
2296              
2297             # -X -Y -Z ... --> mb::_filetest [qw( -X -Y -Z )], ...
2298             # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
2299             # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
2300             elsif (/\G ( (?: -[ABCMORSTWXbcdefgkloprstuwxz] \s* )+ \b ) /xmsgc) {
2301 8409         25506 $parsed .= "mb::_filetest [qw( $1)]";
2302 8409 50       14430 if (my $ambiguous_char = parse_ambiguous_char()) {
2303 0         0 $parsed .= $ambiguous_char;
2304             }
2305             else {
2306 8409         12793 $parsed .= ', ';
2307             }
2308             }
2309              
2310             # yada-yada or triple-dot operator
2311             elsif (/\G ( \.\.\. ) /xmsgc) {
2312 1         2 $parsed .= $1;
2313             }
2314              
2315             # -> and any method
2316             elsif (/\G ( -> \s* [A-Za-z_][A-Za-z_0-9]* ) /xmsgc) {
2317 1         2 $parsed .= $1;
2318             }
2319              
2320             # symbolic operators
2321             elsif (/\G (
2322              
2323             # 12345 | 12345 | 12345 | 12345 | 12345 | 12345 |
2324             != | !~ | ! | # "\x21" [!] EXCLAMATION MARK (U+0021)
2325             \+\+ | \+= | \+ | # "\x2B" [+] PLUS SIGN (U+002B)
2326             , | # "\x2C" [,] COMMA (U+002C)
2327             -- | -= | -> | - | # "\x2D" [-] HYPHEN-MINUS (U+002D)
2328             == | => | =~ | = | # "\x3D" [=] EQUALS SIGN (U+003D)
2329             >> | >= | > | # "\x3E" [>] GREATER-THAN SIGN (U+003E)
2330             \\ | # "\x5C" [\] REVERSE SOLIDUS (U+005C)
2331             \^\^= | \^\^ | \^\.= | \^\. | \^= | \^ | # "\x5E" [^] CIRCUMFLEX ACCENT (U+005E)
2332             \|\|= | \|\| | \|\.= | \|\. | \|= | \| | # "\x7C" [|] VERTICAL LINE (U+007C)
2333             ~~ | ~\. | ~= | ~ # "\x7E" [~] TILDE (U+007E)
2334              
2335             ) /xmsgc) {
2336 121783         239424 $parsed .= $1;
2337             }
2338              
2339             # named operators
2340             elsif (/\G ( (?: and | cmp | eq | ge | gt | isa | le | lt | ne | not | or | x | x= | xor ) \b ) /xmsgc) {
2341 2431         3440 $parsed .= $1;
2342             }
2343              
2344             # $` --> mb::_PREMATCH()
2345             # ${`} --> mb::_PREMATCH()
2346             # $PREMATCH --> mb::_PREMATCH()
2347             # ${PREMATCH} --> mb::_PREMATCH()
2348             # ${^PREMATCH} --> mb::_PREMATCH()
2349             elsif (/\G (?: \$` | \$\{`\} | \$PREMATCH | \$\{PREMATCH\} | \$\{\^PREMATCH\} ) /xmsgc) {
2350 20         25 $parsed .= 'mb::_PREMATCH()';
2351 20         24 $parsed .= parse_ambiguous_char();
2352             }
2353              
2354             # $& --> mb::_MATCH()
2355             # ${&} --> mb::_MATCH()
2356             # $MATCH --> mb::_MATCH()
2357             # ${MATCH} --> mb::_MATCH()
2358             # ${^MATCH} --> mb::_MATCH()
2359             elsif (/\G (?: \$& | \$\{&\} | \$MATCH | \$\{MATCH\} | \$\{\^MATCH\} ) /xmsgc) {
2360 68         90 $parsed .= 'mb::_MATCH()';
2361 68         84 $parsed .= parse_ambiguous_char();
2362             }
2363              
2364             # $1 --> mb::_CAPTURE(1)
2365             # $2 --> mb::_CAPTURE(2)
2366             # $3 --> mb::_CAPTURE(3)
2367             elsif (/\G \$ ([1-9][0-9]*) /xmsgc) {
2368 55         108 $parsed .= "mb::_CAPTURE($1)";
2369 55         74 $parsed .= parse_ambiguous_char();
2370             }
2371              
2372             # @{^CAPTURE} --> mb::_CAPTURE()
2373             elsif (/\G \@\{\^CAPTURE\} /xmsgc) {
2374 3         3 $parsed .= 'mb::_CAPTURE()';
2375 3         4 $parsed .= parse_ambiguous_char();
2376             }
2377              
2378             # ${^CAPTURE}[0] --> mb::_CAPTURE(1)
2379             # ${^CAPTURE}[1] --> mb::_CAPTURE(2)
2380             # ${^CAPTURE}[2] --> mb::_CAPTURE(3)
2381             elsif (/\G \$\{\^CAPTURE\} \s* (\[) /xmsgc) {
2382 3         7 my $n_th = quotee_of(parse_expr_balanced($1));
2383 3         5 $parsed .= "mb::_CAPTURE($n_th+1)";
2384 3         4 $parsed .= parse_ambiguous_char();
2385             }
2386              
2387             # @- --> mb::_LAST_MATCH_START()
2388             # @LAST_MATCH_START --> mb::_LAST_MATCH_START()
2389             # @{LAST_MATCH_START} --> mb::_LAST_MATCH_START()
2390             # @{^LAST_MATCH_START} --> mb::_LAST_MATCH_START()
2391             elsif (/\G (?: \@- | \@LAST_MATCH_START | \@\{LAST_MATCH_START\} | \@\{\^LAST_MATCH_START\} ) /xmsgc) {
2392 12         13 $parsed .= 'mb::_LAST_MATCH_START()';
2393 12         14 $parsed .= parse_ambiguous_char();
2394             }
2395              
2396             # $-[1] --> mb::_LAST_MATCH_START(1)
2397             # $LAST_MATCH_START[1] --> mb::_LAST_MATCH_START(1)
2398             # ${LAST_MATCH_START}[1] --> mb::_LAST_MATCH_START(1)
2399             # ${^LAST_MATCH_START}[1] --> mb::_LAST_MATCH_START(1)
2400             elsif (/\G (?: \$- | \$LAST_MATCH_START | \$\{LAST_MATCH_START\} | \$\{\^LAST_MATCH_START\} ) \s* (\[) /xmsgc) {
2401 22         44 my $n_th = quotee_of(parse_expr_balanced($1));
2402 22         40 $parsed .= "mb::_LAST_MATCH_START($n_th)";
2403 22         30 $parsed .= parse_ambiguous_char();
2404             }
2405              
2406             # @+ --> mb::_LAST_MATCH_END()
2407             # @LAST_MATCH_END --> mb::_LAST_MATCH_END()
2408             # @{LAST_MATCH_END} --> mb::_LAST_MATCH_END()
2409             # @{^LAST_MATCH_END} --> mb::_LAST_MATCH_END()
2410             elsif (/\G (?: \@\+ | \@LAST_MATCH_END | \@\{LAST_MATCH_END\} | \@\{\^LAST_MATCH_END\} ) /xmsgc) {
2411 12         15 $parsed .= 'mb::_LAST_MATCH_END()';
2412 12         14 $parsed .= parse_ambiguous_char();
2413             }
2414              
2415             # $+[1] --> mb::_LAST_MATCH_END(1)
2416             # $LAST_MATCH_END[1] --> mb::_LAST_MATCH_END(1)
2417             # ${LAST_MATCH_END}[1] --> mb::_LAST_MATCH_END(1)
2418             # ${^LAST_MATCH_END}[1] --> mb::_LAST_MATCH_END(1)
2419             elsif (/\G (?: \$\+ | \$LAST_MATCH_END | \$\{LAST_MATCH_END\} | \$\{\^LAST_MATCH_END\} ) \s* (\[) /xmsgc) {
2420 14         52 my $n_th = quotee_of(parse_expr_balanced($1));
2421 14         22 $parsed .= "mb::_LAST_MATCH_END($n_th)";
2422 14         29 $parsed .= parse_ambiguous_char();
2423             }
2424              
2425             # CORE::do { block } --> CORE::do { block }
2426             # CORE::eval { block } --> CORE::eval { block }
2427             # CORE::try { block } --> CORE::try { block }
2428             # CORE::finally { block } --> CORE::finally { block }
2429             elsif (/\G ( CORE:: (?: do | eval | try | finally ) \s* ) ( \{ ) /xmsgc) {
2430 11         18 $parsed .= $1;
2431 11         17 $parsed .= parse_expr_balanced($2);
2432 11         15 $parsed .= parse_ambiguous_char();
2433             }
2434              
2435             # mb::do { block } --> do { block }
2436             # mb::eval { block } --> eval { block }
2437             # mb::try { block } --> try { block }
2438             # mb::finally { block } --> finally { block }
2439             # do { block } --> do { block }
2440             # eval { block } --> eval { block }
2441             # try { block } --> try { block }
2442             # finally { block } --> finally { block }
2443             elsif (/\G (?: mb:: | $old_package )? ( (?: do | eval | try | finally ) \s* ) ( \{ ) /xmsgc) {
2444 30         73 $parsed .= $1;
2445 30         48 $parsed .= parse_expr_balanced($2);
2446 30         37 $parsed .= parse_ambiguous_char();
2447             }
2448              
2449             # $#{}, ${}, @{}, %{}, &{}, *{}, defer {}, sub {}
2450             # "\x24" [$] DOLLAR SIGN (U+0024)
2451             elsif (/\G ((?: \$[#] | [\$\@%&*] | defer | sub ) \s* ) ( \{ ) /xmsgc) {
2452 221         321 $parsed .= $1;
2453 221         315 $parsed .= parse_expr_balanced($2);
2454 221         274 $parsed .= parse_ambiguous_char();
2455             }
2456              
2457             # mb::do --> mb::do
2458             # CORE::do --> CORE::do
2459             # do --> do
2460             elsif (/\G ( (?: mb:: | CORE:: )? do ) \b /xmsgc) {
2461 3         5 $parsed .= $1;
2462             }
2463              
2464             # mb::eval --> mb::eval
2465             # CORE::eval --> CORE::eval
2466             # eval --> eval
2467             elsif (/\G ( (?: mb:: | CORE:: )? eval ) \b /xmsgc) {
2468 3         4 $parsed .= $1;
2469 3         4 $parsed .= parse_ambiguous_char();
2470             }
2471              
2472             # last index of array
2473             elsif (/\G ( [\$] [#] (?: [A-Za-z_][A-Za-z_0-9]*(?:(?:'|::)[A-Za-z_][A-Za-z_0-9]*)* ) ) /xmsgc) {
2474 3         4 $parsed .= $1;
2475 3         5 $parsed .= parse_ambiguous_char();
2476             }
2477              
2478             # scalar variable
2479             elsif (/\G ( [\$] [\$]* (?: [A-Za-z_][A-Za-z_0-9]*(?:(?:'|::)[A-Za-z_][A-Za-z_0-9]*)* | ^\{[A-Za-z_][A-Za-z_0-9]*\} | [0-9]+ | [!"#\$%&'()+,\-.\/:;<=>?\@\[\\\]\^_`|~] ) (?: \s* (?: \+\+ | -- ) )? ) /xmsgc) {
2480 5070         10133 $parsed .= $1;
2481 5070         7028 $parsed .= parse_ambiguous_char();
2482             }
2483              
2484             # array variable
2485             # "\x40" [@] COMMERCIAL AT (U+0040)
2486             elsif (/\G ( [\@\$] [\$]* (?: [A-Za-z_][A-Za-z_0-9]*(?:(?:'|::)[A-Za-z_][A-Za-z_0-9]*)* | [_] ) ) /xmsgc) {
2487 155         246 $parsed .= $1;
2488 155         217 $parsed .= parse_ambiguous_char();
2489             }
2490              
2491             # hash variable
2492             elsif (/\G ( [\%\@\$] [\$]* (?: [A-Za-z_][A-Za-z_0-9]*(?:(?:'|::)[A-Za-z_][A-Za-z_0-9]*)* | [!+\-] ) ) /xmsgc) {
2493 11         16 $parsed .= $1;
2494 11         12 $parsed .= parse_ambiguous_char();
2495             }
2496              
2497             # user subroutine call
2498             # type glob
2499             elsif (/\G ( [&*] [\$]* (?: [A-Za-z_][A-Za-z_0-9]*(?:(?:'|::)[A-Za-z_][A-Za-z_0-9]*)* ) ) /xmsgc) {
2500 172         326 $parsed .= $1;
2501 172         284 $parsed .= parse_ambiguous_char();
2502             }
2503              
2504             # comment
2505             # "\x23" [#] NUMBER SIGN (U+0023)
2506             elsif (/\G ( [#] [^\n]* ) /xmsgc) {
2507 41         78 $parsed .= $1;
2508             }
2509              
2510             # 2-quotes
2511              
2512             # '...'
2513             # "\x27" ['] APOSTROPHE (U+0027)
2514             elsif (m{\G ( ' ) }xmsgc) {
2515 5859         11654 $parsed .= parse_q__like_endswith($1);
2516 5859         9180 $parsed .= parse_ambiguous_char();
2517             }
2518              
2519             # "...", `...`
2520             # "\x22" ["] QUOTATION MARK (U+0022)
2521             # "\x60" [`] GRAVE ACCENT (U+0060)
2522             elsif (m{\G ( ["`] ) }xmsgc) {
2523 126241         323708 $parsed .= parse_qq_like_endswith($1);
2524 126241         268380 $parsed .= parse_ambiguous_char();
2525             }
2526              
2527             # /.../
2528             elsif (m{\G ( [/] ) }xmsgc) {
2529 118046         293178 my $regexp = parse_re_endswith('m',$1);
2530 118046         199571 my($modifier_i, $modifier_not_cegir, $modifier_cegr) = parse_re_modifier();
2531              
2532             # /xx modifier
2533 118046 100       267774 if (($modifier_not_cegir =~ tr/x//) >= 2) {
2534 28         48 $regexp = mb::_ignore_space($regexp);
2535             }
2536              
2537             # /i modifier
2538 118046 100       155430 if ($modifier_i) {
2539 23         37 $parsed .= sprintf('m{\\G${mb::_anchor}@{[mb::_ignorecase(qr%s%s)]}@{[mb::_m_passed()]}}%s', $regexp, $modifier_not_cegir, $modifier_cegr);
2540             }
2541             else {
2542 118023         169127 $parsed .= sprintf('m{\\G${mb::_anchor}@{[' . 'qr%s%s ]}@{[mb::_m_passed()]}}%s', $regexp, $modifier_not_cegir, $modifier_cegr);
2543             }
2544 118046         160447 $parsed .= parse_ambiguous_char();
2545             }
2546              
2547             # ?...?
2548             elsif (m{\G ( [?] ) }xmsgc) {
2549 1         2 my $regexp = parse_re_endswith('m',$1);
2550 1         3 my($modifier_i, $modifier_not_cegir, $modifier_cegr) = parse_re_modifier();
2551              
2552             # /xx modifier
2553 1 50       3 if (($modifier_not_cegir =~ tr/x//) >= 2) {
2554 0         0 $regexp = mb::_ignore_space($regexp);
2555             }
2556              
2557             # /i modifier
2558 1 50       3 if ($modifier_i) {
2559 0         0 $parsed .= sprintf('m{\\G${mb::_anchor}@{[mb::_ignorecase(qr%s%s)]}@{[mb::_m_passed()]}}%s', $regexp, $modifier_not_cegir, $modifier_cegr);
2560             }
2561             else {
2562 1         2 $parsed .= sprintf('m{\\G${mb::_anchor}@{[' . 'qr%s%s ]}@{[mb::_m_passed()]}}%s', $regexp, $modifier_not_cegir, $modifier_cegr);
2563             }
2564 1         4 $parsed .= parse_ambiguous_char();
2565             }
2566              
2567             # <<>> double-diamond operator
2568             elsif (/\G ( <<>> ) /xmsgc) {
2569 1         2 $parsed .= $1;
2570 1         2 $parsed .= parse_ambiguous_char();
2571             }
2572              
2573             # diamond operator
2574             # <${file}>
2575             # <$file>
2576             #
2577             elsif (/\G (<) ((?:(?!\s)$x)*?) (>) /xmsgc) {
2578 5         13 my($open_bracket, $quotee, $close_bracket) = ($1, $2, $3);
2579 5         6 $parsed .= $open_bracket;
2580 5         59 while ($quotee =~ /\G ($x) /xmsgc) {
2581 25         28 $parsed .= escape_qq($1, $close_bracket);
2582             }
2583 5         6 $parsed .= $close_bracket;
2584 5         6 $parsed .= parse_ambiguous_char();
2585             }
2586              
2587             # qw/.../, q/.../
2588             elsif (/\G ( qw | q ) \b /xmsgc) {
2589 171         268 $parsed .= $1;
2590 171 100       587 if (/\G ( [#] ) /xmsgc) { $parsed .= parse_q__like_endswith($1); }
  2 100       5  
    100          
    100          
    100          
    50          
2591 2         4 elsif (/\G ( ['] ) /xmsgc) { $parsed .= parse_q__like_endswith($1); }
2592 45         102 elsif (/\G ( [\(\{\[\<] ) /xmsgc) { $parsed .= parse_q__like_balanced($1); }
2593 6         10 elsif (m{\G( [/] ) }xmsgc) { $parsed .= parse_q__like_endswith($1); }
2594 48         75 elsif (/\G ( [\S] ) /xmsgc) { $parsed .= parse_q__like_endswith($1); }
2595 68         69 elsif (/\G ( \s+ ) /xmsgc) { $parsed .= $1;
2596 68         119 while (/\G ( \s+ | [#] [^\n]* ) /xmsgc) {
2597 4         10 $parsed .= $1;
2598             }
2599 68 100       264 if (/\G ( [A-Za-z_0-9] ) /xmsgc) { $parsed .= parse_q__like_endswith($1); }
  6 100       9  
    100          
    100          
    50          
2600 2         4 elsif (/\G ( ['] ) /xmsgc) { $parsed .= parse_q__like_endswith($1); }
2601 8         45 elsif (/\G ( [\(\{\[\<] ) /xmsgc) { $parsed .= parse_q__like_balanced($1); }
2602 2         3 elsif (m{\G( [/] ) }xmsgc) { $parsed .= parse_q__like_endswith($1); }
2603 50         67 elsif (/\G ( [\S] ) /xmsgc) { $parsed .= parse_q__like_endswith($1); }
2604 0         0 else { die "$0(@{[__LINE__]}): $ARGV[0] has not closed:\n", $parsed; }
  0         0  
2605             }
2606 0         0 else { die "$0(@{[__LINE__]}): $ARGV[0] has not closed:\n", $parsed; }
  0         0  
2607 171         233 $parsed .= parse_ambiguous_char();
2608             }
2609              
2610             # qq/.../
2611             elsif (/\G ( qq ) \b /xmsgc) {
2612 69         101 $parsed .= $1;
2613 69 100       269 if (/\G ( [#] ) /xmsgc) { $parsed .= parse_qq_like_endswith($1); }
  1 100       4  
    100          
    100          
    100          
    50          
2614 1         2 elsif (/\G ( ['] ) /xmsgc) { $parsed .= parse_qq_like_endswith($1); } # qq'...' works as "..."
2615 6         12 elsif (/\G ( [\(\{\[\<] ) /xmsgc) { $parsed .= parse_qq_like_balanced($1); }
2616 3         5 elsif (m{\G( [/] ) }xmsgc) { $parsed .= parse_qq_like_endswith($1); }
2617 24         42 elsif (/\G ( [\S] ) /xmsgc) { $parsed .= parse_qq_like_endswith($1); }
2618 34         39 elsif (/\G ( \s+ ) /xmsgc) { $parsed .= $1;
2619 34         55 while (/\G ( \s+ | [#] [^\n]* ) /xmsgc) {
2620 2         5 $parsed .= $1;
2621             }
2622 34 100       101 if (/\G ( [A-Za-z_0-9] ) /xmsgc) { $parsed .= parse_qq_like_endswith($1); }
  3 100       6  
    100          
    100          
    50          
2623 1         3 elsif (/\G ( ['] ) /xmsgc) { $parsed .= parse_qq_like_endswith($1); } # qq'...' works as "..."
2624 4         7 elsif (/\G ( [\(\{\[\<] ) /xmsgc) { $parsed .= parse_qq_like_balanced($1); }
2625 1         3 elsif (m{\G( [/] ) }xmsgc) { $parsed .= parse_qq_like_endswith($1); }
2626 25         35 elsif (/\G ( [\S] ) /xmsgc) { $parsed .= parse_qq_like_endswith($1); }
2627 0         0 else { die "$0(@{[__LINE__]}): $ARGV[0] has not closed:\n", $parsed; }
  0         0  
2628             }
2629 0         0 else { die "$0(@{[__LINE__]}): $ARGV[0] has not closed:\n", $parsed; }
  0         0  
2630 69         111 $parsed .= parse_ambiguous_char();
2631             }
2632              
2633             # qx/.../
2634             elsif (/\G ( qx ) \b /xmsgc) {
2635 67         148 $parsed .= $1;
2636 67 100       247 if (/\G ( [#] ) /xmsgc) { $parsed .= parse_qq_like_endswith($1); }
  1 100       2  
    100          
    100          
    100          
    50          
2637 1         3 elsif (/\G ( ['] ) /xmsgc) { $parsed .= parse_q__like_endswith($1); }
2638 4         5 elsif (/\G ( [\(\{\[\<] ) /xmsgc) { $parsed .= parse_qq_like_balanced($1); }
2639 3         7 elsif (m{\G( [/] ) }xmsgc) { $parsed .= parse_qq_like_endswith($1); }
2640 24         38 elsif (/\G ( [\S] ) /xmsgc) { $parsed .= parse_qq_like_endswith($1); }
2641 34         40 elsif (/\G ( \s+ ) /xmsgc) { $parsed .= $1;
2642 34         58 while (/\G ( \s+ | [#] [^\n]* ) /xmsgc) {
2643 2         4 $parsed .= $1;
2644             }
2645 34 100       108 if (/\G ( [A-Za-z_0-9] ) /xmsgc) { $parsed .= parse_qq_like_endswith($1); }
  3 100       4  
    100          
    100          
    50          
2646 1         2 elsif (/\G ( ['] ) /xmsgc) { $parsed .= parse_q__like_endswith($1); }
2647 4         6 elsif (/\G ( [\(\{\[\<] ) /xmsgc) { $parsed .= parse_qq_like_balanced($1); }
2648 1         2 elsif (m{\G( [/] ) }xmsgc) { $parsed .= parse_qq_like_endswith($1); }
2649 25         35 elsif (/\G ( [\S] ) /xmsgc) { $parsed .= parse_qq_like_endswith($1); }
2650 0         0 else { die "$0(@{[__LINE__]}): $ARGV[0] has not closed:\n", $parsed; }
  0         0  
2651             }
2652 0         0 else { die "$0(@{[__LINE__]}): $ARGV[0] has not closed:\n", $parsed; }
  0         0  
2653 67         94 $parsed .= parse_ambiguous_char();
2654             }
2655              
2656             # m/.../, qr/.../
2657             elsif (/\G ( m | qr ) \b /xmsgc) {
2658 1655         2960 $parsed .= $1;
2659 1655         1980 my $regexp = '';
2660 1655 100       4984 if (/\G ( [#] ) /xmsgc) { $regexp .= parse_re_endswith('m',$1); } # qr#...#
  2 100       11  
    100          
    100          
    100          
    100          
    50          
2661 643         1203 elsif (/\G ( ['] ) /xmsgc) { $regexp .= parse_re_as_q_endswith('m',$1); } # qr'...'
2662 8         15 elsif (/\G ( [\(\{\[\<] ) /xmsgc) { $regexp .= parse_re_balanced('m',$1); } # qr{...}
2663 360         664 elsif (m{\G( [/] ) }xmsgc) { $regexp .= parse_re_endswith('m',$1); } # qr/.../
2664 530         843 elsif (/\G ( [:\@] ) /xmsgc) { $regexp .= ('`' . quotee_of(parse_re_endswith('m',$1)) . '`'); } # qr@...@
2665 44         55 elsif (/\G ( [\S] ) /xmsgc) { $regexp .= parse_re_endswith('m',$1); } # qr?...?
2666 68         68 elsif (/\G ( \s+ ) /xmsgc) { $parsed .= $1; $regexp .= $1; # qr SPACE ...
  68         65  
2667 68         120 while (/\G ( \s+ | [#] [^\n]* ) /xmsgc) {
2668 4         9 $parsed .= $1;
2669             }
2670 68 100       211 if (/\G ( [A-Za-z_0-9] ) /xmsgc) { $regexp .= parse_re_endswith('m',$1); } # qr SPACE A...A
  6 100       10  
    100          
    100          
    100          
    50          
2671 2         4 elsif (/\G ( ['] ) /xmsgc) { $regexp .= parse_re_as_q_endswith('m',$1); } # qr SPACE '...'
2672 8         15 elsif (/\G ( [\(\{\[\<] ) /xmsgc) { $regexp .= parse_re_balanced('m',$1); } # qr SPACE {...}
2673 2         3 elsif (m{\G( [/] ) }xmsgc) { $regexp .= parse_re_endswith('m',$1); } # qr SPACE /.../
2674 4         5 elsif (/\G ( [:\@] ) /xmsgc) { $regexp .= ('`' . quotee_of(parse_re_endswith('m',$1)) . '`'); } # qr SPACE @...@
2675 46         62 elsif (/\G ( [\S] ) /xmsgc) { $regexp .= parse_re_endswith('m',$1); } # qr SPACE ?...?
2676 0         0 else { die "$0(@{[__LINE__]}): $ARGV[0] has not closed:\n", $parsed; }
  0         0  
2677             }
2678 0         0 else { die "$0(@{[__LINE__]}): $ARGV[0] has not closed:\n", $parsed; }
  0         0  
2679              
2680 1655         2586 my($modifier_i, $modifier_not_cegir, $modifier_cegr) = parse_re_modifier();
2681              
2682             # /xx modifier
2683 1655 100       3277 if (($modifier_not_cegir =~ tr/x//) >= 2) {
2684 2         6 $regexp = mb::_ignore_space($regexp);
2685             }
2686              
2687             # /i modifier
2688 1655 100       1991 if ($modifier_i) {
2689 37         59 $parsed .= sprintf('{\\G${mb::_anchor}@{[mb::_ignorecase(qr%s%s)]}@{[mb::_m_passed()]}}%s', $regexp, $modifier_not_cegir, $modifier_cegr);
2690             }
2691             else {
2692 1618         3516 $parsed .= sprintf('{\\G${mb::_anchor}@{[' . 'qr%s%s ]}@{[mb::_m_passed()]}}%s', $regexp, $modifier_not_cegir, $modifier_cegr);
2693             }
2694 1655         2214 $parsed .= parse_ambiguous_char();
2695             }
2696              
2697             # 3-quotes
2698              
2699             # s/.../.../
2700             elsif (/\G ( s ) \b /xmsgc) {
2701 1713         2987 $parsed .= $1;
2702 1713         1703 my $regexp = '';
2703 1713         1472 my $comment = '';
2704 1713         1709 my @replacement = ();
2705 1713 100       5298 if (/\G ( [#] ) /xmsgc) { $regexp .= parse_re_endswith('s',$1); @replacement = parse_qq_like_endswith($1); } # s#...#...#
  1 100       3  
  1 100       3  
    100          
    100          
    100          
    50          
2706 286         401 elsif (/\G ( ['] ) /xmsgc) { $regexp .= parse_re_as_q_endswith('s',$1); @replacement = parse_qq_like_endswith($1); } # s'...'...'
  286         488  
2707 240         370 elsif (/\G ( [\(\{\[\<] ) /xmsgc) { $regexp .= parse_re_balanced('s',$1); # s{...}...
2708 240 50       857 if (/\G ( [#] ) /xmsgc) { @replacement = parse_qq_like_endswith($1); } # s{}#...#
  0 100       0  
    100          
    100          
    100          
    50          
2709 4         17 elsif (/\G ( ['] ) /xmsgc) { @replacement = parse_qq_like_endswith($1); } # s{}'...'
2710 16         34 elsif (/\G ( [\(\{\[\<] ) /xmsgc) { @replacement = parse_qq_like_balanced($1); } # s{}{...}
2711 4         9 elsif (m{\G( [/] ) }xmsgc) { @replacement = parse_qq_like_endswith($1); } # s{}/.../
2712 96         172 elsif (/\G ( [\S] ) /xmsgc) { @replacement = parse_qq_like_endswith($1); } # s{}?...?
2713 120         140 elsif (/\G ( \s+ ) /xmsgc) { $comment .= $1; # s{} SPACE ...
2714 120         228 while (/\G ( \s+ | [#] [^\n]* ) /xmsgc) {
2715 0         0 $comment .= $1;
2716             }
2717 120 50       386 if (/\G ( [A-Za-z_0-9] ) /xmsgc) { @replacement = parse_qq_like_endswith($1); } # s{} SPACE A...A
  0 100       0  
    100          
    100          
    50          
2718 4         12 elsif (/\G ( ['] ) /xmsgc) { @replacement = parse_qq_like_endswith($1); } # s{} SPACE '...'
2719 16         23 elsif (/\G ( [\(\{\[\<] ) /xmsgc) { @replacement = parse_qq_like_balanced($1); } # s{} SPACE {...}
2720 4         9 elsif (m{\G( [/] ) }xmsgc) { @replacement = parse_qq_like_endswith($1); } # s{} SPACE /.../
2721 96         142 elsif (/\G ( [\S] ) /xmsgc) { @replacement = parse_qq_like_endswith($1); } # s{} SPACE ?...?
2722 0         0 else { die "$0(@{[__LINE__]}): $ARGV[0] has not closed:\n", $parsed; }
  0         0  
2723             }
2724 0         0 else { die "$0(@{[__LINE__]}): $ARGV[0] has not closed:\n", $parsed; }
  0         0  
2725             }
2726 354         497 elsif (m{\G( [/] ) }xmsgc) { $regexp .= parse_re_endswith('s',$1); @replacement = parse_qq_like_endswith($1); } # s/.../.../
  354         602  
2727 528         755 elsif (/\G ( [:\@] ) /xmsgc) { $regexp .= ('`' . quotee_of(parse_re_endswith('s',$1)) . '`');
2728 528         772 @replacement = parse_qq_like_endswith($1); } # s@...@...@
2729 22         32 elsif (/\G ( [\S] ) /xmsgc) { $regexp .= parse_re_endswith('s',$1); @replacement = parse_qq_like_endswith($1); } # s?...?...?
  22         38  
2730 282         293 elsif (/\G ( \s+ ) /xmsgc) { $parsed .= $1; $regexp .= $1; # s SPACE ...
  282         283  
2731 282         540 while (/\G ( \s+ | [#] [^\n]* ) /xmsgc) {
2732 12         25 $parsed .= $1;
2733             }
2734 282 100       701 if (/\G ( [A-Za-z_0-9] ) /xmsgc) { $regexp .= parse_re_endswith('s',$1); @replacement = parse_qq_like_endswith($1); } # s SPACE A...A...A
  12 100       17  
  12 100       19  
    100          
    100          
    50          
2735 1         2 elsif (/\G ( ['] ) /xmsgc) { $regexp .= parse_re_as_q_endswith('s',$1); @replacement = parse_qq_like_endswith($1); } # s SPACE '...'...'
  1         2  
2736 244         378 elsif (/\G ( [\(\{\[\<] ) /xmsgc) { $regexp .= parse_re_balanced('s',$1); # s SPACE {...}...
2737 244 100       950 if (/\G ( [#] ) /xmsgc) { @replacement = parse_qq_like_endswith($1); } # s SPACE {}#...#
  1 100       3  
    100          
    100          
    100          
    50          
2738 4         20 elsif (/\G ( ['] ) /xmsgc) { @replacement = parse_qq_like_endswith($1); } # s SPACE {}'...'
2739 17         23 elsif (/\G ( [\(\{\[\<] ) /xmsgc) { @replacement = parse_qq_like_balanced($1); } # s SPACE {}{...}
2740 4         10 elsif (m{\G( [/] ) }xmsgc) { @replacement = parse_qq_like_endswith($1); } # s SPACE {}/.../
2741 96         146 elsif (/\G ( [\S] ) /xmsgc) { @replacement = parse_qq_like_endswith($1); } # s SPACE {}?...?
2742 122         162 elsif (/\G ( \s+ ) /xmsgc) { $comment .= $1; # s SPACE {} SPACE ...
2743 122         216 while (/\G ( \s+ | [#] [^\n]* ) /xmsgc) {
2744 8         17 $comment .= $1;
2745             }
2746 122 50       376 if (/\G ( [A-Za-z_0-9] ) /xmsgc) { @replacement = parse_qq_like_endswith($1); } # s SPACE {} SPACE A...A
  0 100       0  
    100          
    100          
    50          
2747 4         13 elsif (/\G ( ['] ) /xmsgc) { @replacement = parse_qq_like_endswith($1); } # s SPACE {} SPACE '...'
2748 18         41 elsif (/\G ( [\(\{\[\<] ) /xmsgc) { @replacement = parse_qq_like_balanced($1); } # s SPACE {} SPACE {...}
2749 4         27 elsif (m{\G( [/] ) }xmsgc) { @replacement = parse_qq_like_endswith($1); } # s SPACE {} SPACE /.../
2750 96         137 elsif (/\G ( [\S] ) /xmsgc) { @replacement = parse_qq_like_endswith($1); } # s SPACE {} SPACE ?...?
2751 0         0 else { die "$0(@{[__LINE__]}): $ARGV[0] has not closed:\n", $parsed; }
  0         0  
2752             }
2753 0         0 else { die "$0(@{[__LINE__]}): $ARGV[0] has not closed:\n", $parsed; }
  0         0  
2754             }
2755 1         2 elsif (m{\G( [/] ) }xmsgc) { $regexp .= parse_re_endswith('s',$1); @replacement = parse_qq_like_endswith($1); } # s SPACE /.../.../
  1         2  
2756 2         3 elsif (/\G ( [:\@] ) /xmsgc) { $regexp .= ('`' . quotee_of(parse_re_endswith('s',$1)) . '`');
2757 2         4 @replacement = parse_qq_like_endswith($1); } # s SPACE @...@...@
2758 22         27 elsif (/\G ( [\S] ) /xmsgc) { $regexp .= parse_re_endswith('s',$1); @replacement = parse_qq_like_endswith($1); } # s SPACE ?...?...?
  22         40  
2759 0         0 else { die "$0(@{[__LINE__]}): $ARGV[0] has not closed:\n", $parsed; }
  0         0  
2760             }
2761 0         0 else { die "$0(@{[__LINE__]}): $ARGV[0] has not closed:\n", $parsed; }
  0         0  
2762              
2763 1713         2266 my($modifier_i, $modifier_not_cegir, $modifier_cegr) = parse_re_modifier();
2764 1713         2030 my $replacement = '';
2765 1713         1577 my $eval = '';
2766              
2767             # has /e modifier
2768 1713 100       3852 if (my $e = $modifier_cegr =~ tr/e//d) {
    100          
    100          
2769 9         11 $replacement = 'q'. $replacement[1]; # q-type quotee
2770 9         11 $eval = 'mb::eval ' x $e;
2771             }
2772              
2773             # s''q-quotee'
2774             elsif ($replacement[0] =~ /\A ' /xms) {
2775 300         296 $replacement = $replacement[1]; # q-type quotee
2776             }
2777              
2778             # s##qq-quotee#
2779             elsif ($replacement[0] =~ /\A [#] /xms) {
2780 2         14 $replacement = 'qq' . $replacement[0]; # qq-type quotee
2781             }
2782              
2783             # s//qq-quotee/
2784             else {
2785 1402         1330 $replacement = 'qq ' . $replacement[0]; # qq-type quotee
2786             }
2787              
2788             # /xx modifier
2789 1713 100       2426 if (($modifier_not_cegir =~ tr/x//) >= 2) {
2790 1         2 $regexp = mb::_ignore_space($regexp);
2791             }
2792              
2793             # /i modifier
2794 1713 100       1888 if ($modifier_i) {
2795 18         29 $parsed .= sprintf('{(\\G${mb::_anchor})@{[mb::_ignorecase(qr%s%s)]}@{[mb::_s_passed()]}}%s{$1 . %s%s}e%s', $regexp, $modifier_not_cegir, $comment, $eval, $replacement, $modifier_cegr);
2796             }
2797             else {
2798 1695         2273 $parsed .= sprintf('{(\\G${mb::_anchor})@{[' . 'qr%s%s ]}@{[mb::_s_passed()]}}%s{$1 . %s%s}e%s', $regexp, $modifier_not_cegir, $comment, $eval, $replacement, $modifier_cegr);
2799             }
2800 1713         2165 $parsed .= parse_ambiguous_char();
2801             }
2802              
2803             # tr/.../.../, y/.../.../
2804             elsif (/\G (?: tr | y ) \b /xmsgc) {
2805 2159         3346 $parsed .= 's'; # not 'tr'
2806 2159         2612 my $search = '';
2807 2159         2473 my $comment = '';
2808 2159         2275 my $replacement = '';
2809 2159 100       9445 if (/\G ( [#] ) /xmsgc) { $search .= parse_tr_like_endswith($1); $replacement .= parse_tr_like_endswith($1); } # tr#...#...#
  4 100       13  
  4 100       7  
    100          
    100          
    50          
2810 4         10 elsif (/\G ( ['] ) /xmsgc) { $search .= parse_tr_like_endswith($1); $replacement .= parse_tr_like_endswith($1); } # tr'...'...'
  4         11  
2811 912         1776 elsif (/\G ( [\(\{\[\<] ) /xmsgc) { $search .= parse_tr_like_balanced($1); # tr{...}...
2812 912 50       4384 if (/\G ( [#] ) /xmsgc) { $replacement .= parse_tr_like_endswith($1); } # tr{}#...#
  0 100       0  
    100          
    100          
    100          
    50          
2813 16         34 elsif (/\G ( ['] ) /xmsgc) { $replacement .= parse_tr_like_endswith($1); } # tr{}'...'
2814 64         84 elsif (/\G ( [\(\{\[\<] ) /xmsgc) { $replacement .= parse_tr_like_balanced($1); } # tr{}{...}
2815 16         25 elsif (m{\G( [/] ) }xmsgc) { $replacement .= parse_tr_like_endswith($1); } # tr{}/.../
2816 360         569 elsif (/\G ( [\S] ) /xmsgc) { $replacement .= parse_tr_like_endswith($1); } # tr{}?...?
2817 456         725 elsif (/\G ( \s+ ) /xmsgc) { $comment .= $1; # tr{} SPACE ...
2818 456         1252 while (/\G ( \s+ | [#] [^\n]* ) /xmsgc) {
2819 0         0 $comment .= $1;
2820             }
2821 456 50       1850 if (/\G ( [A-Za-z_0-9] ) /xmsgc) { $replacement .= parse_tr_like_endswith($1); } # tr{} SPACE A...A
  0 100       0  
    100          
    100          
    50          
2822 16         22 elsif (/\G ( ['] ) /xmsgc) { $replacement .= parse_tr_like_endswith($1); } # tr{} SPACE '...'
2823 64         83 elsif (/\G ( [\(\{\[\<] ) /xmsgc) { $replacement .= parse_tr_like_balanced($1); } # tr{} SPACE {...}
2824 16         27 elsif (m{\G( [/] ) }xmsgc) { $replacement .= parse_tr_like_endswith($1); } # tr{} SPACE /.../
2825 360         522 elsif (/\G ( [\S] ) /xmsgc) { $replacement .= parse_tr_like_endswith($1); } # tr{} SPACE ?...?
2826 0         0 else { die "$0(@{[__LINE__]}): $ARGV[0] has not closed:\n", $parsed; }
  0         0  
2827             }
2828 0         0 else { die "$0(@{[__LINE__]}): $ARGV[0] has not closed:\n", $parsed; }
  0         0  
2829             }
2830 98         151 elsif (m{\G( [/] ) }xmsgc) { $search .= parse_tr_like_endswith($1); $replacement .= parse_tr_like_endswith($1); } # tr/.../.../
  98         118  
2831 131         254 elsif (/\G ( [\S] ) /xmsgc) { $search .= parse_tr_like_endswith($1); $replacement .= parse_tr_like_endswith($1); } # tr?...?...?
  131         237  
2832 1010         1941 elsif (/\G ( \s+ ) /xmsgc) { $parsed .= $1; # tr SPACE ...
2833 1010         2807 while (/\G ( \s+ | [#] [^\n]* ) /xmsgc) {
2834 0         0 $parsed .= $1;
2835             }
2836 1010 50       3360 if (/\G ( [A-Za-z_0-9] ) /xmsgc) { $search .= parse_tr_like_endswith($1); $replacement .= parse_tr_like_endswith($1); } # tr SPACE A...A...A
  0 100       0  
  0 100       0  
    100          
    50          
2837 4         9 elsif (/\G ( ['] ) /xmsgc) { $search .= parse_tr_like_endswith($1); $replacement .= parse_tr_like_endswith($1); } # tr SPACE '...'...'
  4         8  
2838 912         1688 elsif (/\G ( [\(\{\[\<] ) /xmsgc) { $search .= parse_tr_like_balanced($1); # tr SPACE {...}...
2839 912 50       4579 if (/\G ( [#] ) /xmsgc) { $replacement .= parse_tr_like_endswith($1); } # tr SPACE {}#...#
  0 100       0  
    100          
    100          
    100          
    50          
2840 16         27 elsif (/\G ( ['] ) /xmsgc) { $replacement .= parse_tr_like_endswith($1); } # tr SPACE {}'...'
2841 64         83 elsif (/\G ( [\(\{\[\<] ) /xmsgc) { $replacement .= parse_tr_like_balanced($1); } # tr SPACE {}{...}
2842 16         28 elsif (m{\G( [/] ) }xmsgc) { $replacement .= parse_tr_like_endswith($1); } # tr SPACE {}/.../
2843 360         511 elsif (/\G ( [\S] ) /xmsgc) { $replacement .= parse_tr_like_endswith($1); } # tr SPACE {}?...?
2844 456         792 elsif (/\G ( \s+ ) /xmsgc) { $comment .= $1; # tr SPACE {} SPACE ...
2845 456         1130 while (/\G ( \s+ | [#] [^\n]* ) /xmsgc) {
2846 0         0 $comment .= $1;
2847             }
2848 456 50       1787 if (/\G ( [A-Za-z_0-9] ) /xmsgc) { $replacement .= parse_tr_like_endswith($1); } # tr SPACE {} SPACE A...A
  0 100       0  
    100          
    100          
    50          
2849 16         51 elsif (/\G ( ['] ) /xmsgc) { $replacement .= parse_tr_like_endswith($1); } # tr SPACE {} SPACE '...'
2850 64         83 elsif (/\G ( [\(\{\[\<] ) /xmsgc) { $replacement .= parse_tr_like_balanced($1); } # tr SPACE {} SPACE {...}
2851 16         29 elsif (m{\G( [/] ) }xmsgc) { $replacement .= parse_tr_like_endswith($1); } # tr SPACE {} SPACE /.../
2852 360         590 elsif (/\G ( [\S] ) /xmsgc) { $replacement .= parse_tr_like_endswith($1); } # tr SPACE {} SPACE ?...?
2853 0         0 else { die "$0(@{[__LINE__]}): $ARGV[0] has not closed:\n", $parsed; }
  0         0  
2854             }
2855 0         0 else { die "$0(@{[__LINE__]}): $ARGV[0] has not closed:\n", $parsed; }
  0         0  
2856             }
2857 4         13 elsif (m{\G( [/] ) }xmsgc) { $search .= parse_tr_like_endswith($1); $replacement .= parse_tr_like_endswith($1); } # tr SPACE /.../.../
  4         34  
2858 90         192 elsif (/\G ( [\S] ) /xmsgc) { $search .= parse_tr_like_endswith($1); $replacement .= parse_tr_like_endswith($1); } # tr SPACE ?...?...?
  90         150  
2859 0         0 else { die "$0(@{[__LINE__]}): $ARGV[0] has not closed:\n", $parsed; }
  0         0  
2860             }
2861 0         0 else { die "$0(@{[__LINE__]}): $ARGV[0] has not closed:\n", $parsed; }
  0         0  
2862              
2863             # modifier
2864 2159         4164 my($modifier_not_r, $modifier_r) = parse_tr_modifier();
2865 2159 50       4259 if ($modifier_r) {
    100          
2866 0         0 $parsed .= sprintf(q<{[\x00-\xFF]*}%s{mb::tr($&,q%s,q%s,'%sr')}ser>, $comment, $search, $replacement, $modifier_not_r);
2867             }
2868             elsif ($modifier_not_r =~ /s/) {
2869              
2870             # this implementation cannot return right count of codepoints replaced.
2871             # if you want right count, you can call mb::tr() yourself.
2872 28         44 $parsed .= sprintf(q<{[\x00-\xFF]+}%s{mb::tr($&,q%s,q%s,'%sr')}se>, $comment, $search, $replacement, $modifier_not_r);
2873             }
2874             else {
2875              
2876             # $parsed .= sprintf(q<{@{mb::_dot}}%s{mb::tr($&,q%s,q%s,'%sr')}msge>, $comment, $search, $replacement, $modifier_not_r);
2877             #------------------------------------------------------------------------------------------------------------------------------------------------
2878             # do { $_='AAABBCDEA'; $r=tr/ABC/12/; ($r,$_) } => (9,111222DE1)
2879             # do { $_='AAABBCDEA'; $r=tr/ABC/12/s; ($r,$_) } => (9,111222DE1)
2880             # do { $_='AAABBCDEA'; $r=tr/ABC/12/d; ($r,$_) } => (9,11122DE1)
2881             # do { $_='AAABBCDEA'; $r=tr/ABC/12/ds; ($r,$_) } => (9,11122DE1)
2882             # do { $_='AAABBCDEA'; $r=tr/ABC/12/c; ($r,$_) } => (9,AAABBC22A)
2883             # do { $_='AAABBCDEA'; $r=tr/ABC/12/cs; ($r,$_) } => (9,AAABBC22A)
2884             # do { $_='AAABBCDEA'; $r=tr/ABC/12/cd; ($r,$_) } => (9,AAABBCA)
2885             # do { $_='AAABBCDEA'; $r=tr/ABC/12/cds; ($r,$_) } => (9,AAABBCA)
2886              
2887             # $parsed .= sprintf(q<{[\x00-\xFF]*}%s{mb::tr($&,q%s,q%s,'%sr')}msge>, $comment, $search, $replacement, $modifier_not_r);
2888             #------------------------------------------------------------------------------------------------------------------------------------------------
2889             # do { $_='AAABBCDEA'; $r=tr/ABC/12/; ($r,$_) } => (2,111222DE1)
2890             # do { $_='AAABBCDEA'; $r=tr/ABC/12/s; ($r,$_) } => (2,12DE1)
2891             # do { $_='AAABBCDEA'; $r=tr/ABC/12/d; ($r,$_) } => (2,11122DE1)
2892             # do { $_='AAABBCDEA'; $r=tr/ABC/12/ds; ($r,$_) } => (2,12DE1)
2893             # do { $_='AAABBCDEA'; $r=tr/ABC/12/c; ($r,$_) } => (2,AAABBC22A)
2894             # do { $_='AAABBCDEA'; $r=tr/ABC/12/cs; ($r,$_) } => (2,AAABBC2A)
2895             # do { $_='AAABBCDEA'; $r=tr/ABC/12/cd; ($r,$_) } => (2,AAABBCA)
2896             # do { $_='AAABBCDEA'; $r=tr/ABC/12/cds; ($r,$_) } => (2,AAABBCA)
2897              
2898             # if ($modifier_not_r =~ /c/) {
2899             # $parsed .= sprintf(q<{@{[mb::_cc(q[^%s])]}}%s{mb::tr($&,q%s,q%s,'%sr')}msge>, $search, $comment, $search, $replacement, $modifier_not_r);
2900             # }
2901             # else {
2902             # $parsed .= sprintf(q<{@{[mb::_cc(q[%s])]}}%s{mb::tr($&,q%s,q%s,'%sr')}msge>, $search, $comment, $search, $replacement, $modifier_not_r);
2903             # }
2904             #------------------------------------------------------------------------------------------------------------------------------------------------
2905             # do { $_='AAABBCDEA'; $r=tr/ABC/12/; ($r,$_) } => (7,111222DE1)
2906             # do { $_='AAABBCDEA'; $r=tr/ABC/12/s; ($r,$_) } => (7,111222DE1)
2907             # do { $_='AAABBCDEA'; $r=tr/ABC/12/d; ($r,$_) } => (7,11122DE1)
2908             # do { $_='AAABBCDEA'; $r=tr/ABC/12/ds; ($r,$_) } => (7,11122DE1)
2909             # do { $_='AAABBCDEA'; $r=tr/ABC/12/c; ($r,$_) } => (2,AAABBC22A)
2910             # do { $_='AAABBCDEA'; $r=tr/ABC/12/cs; ($r,$_) } => (2,AAABBC22A)
2911             # do { $_='AAABBCDEA'; $r=tr/ABC/12/cd; ($r,$_) } => (2,AAABBCA)
2912             # do { $_='AAABBCDEA'; $r=tr/ABC/12/cds; ($r,$_) } => (2,AAABBCA)
2913              
2914             # better idea of mine
2915 2131 100       2628 if ($modifier_not_r =~ /c/) {
2916 16         22 $parsed .= sprintf(q<{(\\G${mb::_anchor})((?!%s)@{mb::_dot})}%s{$1.mb::tr($2,q%s,q%s,'%sr')}sge>, codepoint_tr($search), $comment, $search, $replacement, $modifier_not_r);
2917             }
2918             else {
2919 2115         2930 $parsed .= sprintf(q<{(\\G${mb::_anchor})((?=%s)@{mb::_dot})}%s{$1.mb::tr($2,q%s,q%s,'%sr')}sge>, codepoint_tr($search), $comment, $search, $replacement, $modifier_not_r);
2920             }
2921             #------------------------------------------------------------------------------------------------------------------------------------------------
2922             # do { $_='AAABBCDEA'; $r=tr/ABC/12/; ($r,$_) } => (7,111222DE1)
2923             # do { $_='AAABBCDEA'; $r=tr/ABC/12/s; ($r,$_) } => (1,12DE1)
2924             # do { $_='AAABBCDEA'; $r=tr/ABC/12/d; ($r,$_) } => (7,11122DE1)
2925             # do { $_='AAABBCDEA'; $r=tr/ABC/12/ds; ($r,$_) } => (1,12DE1)
2926             # do { $_='AAABBCDEA'; $r=tr/ABC/12/c; ($r,$_) } => (2,AAABBC22A)
2927             # do { $_='AAABBCDEA'; $r=tr/ABC/12/cs; ($r,$_) } => (1,AAABBC2A)
2928             # do { $_='AAABBCDEA'; $r=tr/ABC/12/cd; ($r,$_) } => (2,AAABBCA)
2929             # do { $_='AAABBCDEA'; $r=tr/ABC/12/cds; ($r,$_) } => (1,AAABBCA)
2930             }
2931 2159         3562 $parsed .= parse_ambiguous_char();
2932             }
2933              
2934             # indented here document
2935             elsif (/\G ( <<~ ) /xmsgc) {
2936 11         20 $parsed .= $1;
2937 11 100       43 if (/\G ( ([A-Za-z_][A-Za-z_0-9]*) ) /xmsgc) { $parsed .= $1; push @here_document_delimiter, ["[\\t ]*$2$R", 'qq']; }
  1 100       2  
  1 100       5  
    100          
    50          
2938 1         2 elsif (/\G ( \\([A-Za-z_][A-Za-z_0-9]*) ) /xmsgc) { $parsed .= $1; push @here_document_delimiter, ["[\\t ]*$2$R", 'q' ]; }
  1         4  
2939 3         4 elsif (/\G ( [\t ]* '([A-Za-z_][A-Za-z_0-9]*)' ) /xmsgc) { $parsed .= $1; push @here_document_delimiter, ["[\\t ]*$2$R", 'q' ]; }
  3         8  
2940 3         4 elsif (/\G ( [\t ]* "([A-Za-z_][A-Za-z_0-9]*)" ) /xmsgc) { $parsed .= $1; push @here_document_delimiter, ["[\\t ]*$2$R", 'qq']; }
  3         8  
2941 3         4 elsif (/\G ( [\t ]* `([A-Za-z_][A-Za-z_0-9]*)` ) /xmsgc) { $parsed .= $1; push @here_document_delimiter, ["[\\t ]*$2$R", 'qq']; }
  3         8  
2942 0         0 else { die "$0(@{[__LINE__]}): $ARGV[0] has not closed:\n", $parsed; }
  0         0  
2943 11         12 $parsed .= parse_ambiguous_char();
2944             }
2945              
2946             # here document
2947             elsif (/\G ( << ) /xmsgc) {
2948 12         21 $parsed .= $1;
2949 12 100       48 if (/\G ( ([A-Za-z_][A-Za-z_0-9]*) ) /xmsgc) { $parsed .= $1; push @here_document_delimiter, [ "$2$R", 'qq']; }
  1 100       2  
  1 100       3  
    100          
    50          
2950 1         2 elsif (/\G ( \\([A-Za-z_][A-Za-z_0-9]*) ) /xmsgc) { $parsed .= $1; push @here_document_delimiter, [ "$2$R", 'q' ]; }
  1         4  
2951 4         5 elsif (/\G ( [\t ]* '([A-Za-z_][A-Za-z_0-9]*)' ) /xmsgc) { $parsed .= $1; push @here_document_delimiter, [ "$2$R", 'q' ]; }
  4         11  
2952 3         4 elsif (/\G ( [\t ]* "([A-Za-z_][A-Za-z_0-9]*)" ) /xmsgc) { $parsed .= $1; push @here_document_delimiter, [ "$2$R", 'qq']; }
  3         7  
2953 3         4 elsif (/\G ( [\t ]* `([A-Za-z_][A-Za-z_0-9]*)` ) /xmsgc) { $parsed .= $1; push @here_document_delimiter, [ "$2$R", 'qq']; }
  3         6  
2954 0         0 else { die "$0(@{[__LINE__]}): $ARGV[0] has not closed:\n", $parsed; }
  0         0  
2955 12         18 $parsed .= parse_ambiguous_char();
2956             }
2957              
2958             # sub subroutine();
2959             elsif (/\G ( sub \s+ [A-Za-z_][A-Za-z_0-9]*(?:(?:'|::)[A-Za-z_][A-Za-z_0-9]*)* \s* ) /xmsgc) {
2960 29         62 $parsed .= $1;
2961             }
2962              
2963             # while (<<>>)
2964             elsif (/\G ( while \s* \( \s* ) ( <<>> ) ( \s* \) ) /xmsgc) {
2965 2         4 $parsed .= $1;
2966 2         2 $parsed .= $2;
2967 2         4 $parsed .= $3;
2968             }
2969              
2970             # while (<${file}>)
2971             # while (<$file>)
2972             # while ()
2973             # while ()
2974             elsif (/\G ( while \s* \( \s* ) (<) ((?:(?!\s)$x)*?) (>) ( \s* \) ) /xmsgc) {
2975 9         14 $parsed .= $1;
2976 9         29 my($open_bracket, $quotee, $close_bracket) = ($2, $3, $4);
2977 9         11 my $close_bracket2 = $5;
2978 9         10 $parsed .= $open_bracket;
2979 9         224 while ($quotee =~ /\G ($x) /xmsgc) {
2980 54         60 $parsed .= escape_qq($1, $close_bracket);
2981             }
2982 9         10 $parsed .= $close_bracket;
2983 9         12 $parsed .= $close_bracket2;
2984             }
2985              
2986             # while <<>>
2987             elsif (/\G ( while \s* ) ( <<>> ) /xmsgc) {
2988 0         0 $parsed .= $1;
2989 0         0 $parsed .= $2;
2990             }
2991              
2992             # while <${file}>
2993             # while <$file>
2994             # while
2995             # while
2996             elsif (/\G ( while \s* ) (<) ((?:(?!\s)$x)*?) (>) /xmsgc) {
2997 0         0 $parsed .= $1;
2998 0         0 my($open_bracket, $quotee, $close_bracket) = ($2, $3, $4);
2999 0         0 $parsed .= $open_bracket;
3000 0         0 while ($quotee =~ /\G ($x) /xmsgc) {
3001 0         0 $parsed .= escape_qq($1, $close_bracket);
3002             }
3003 0         0 $parsed .= $close_bracket;
3004             }
3005              
3006             # if (expr)
3007             # elsif (expr)
3008             # unless (expr)
3009             # while (expr)
3010             # until (expr)
3011             # given (expr)
3012             # when (expr)
3013             # CORE::catch (expr)
3014             # catch (expr)
3015             elsif (/\G ( (?: if | elsif | unless | while | until | given | when | (?: CORE:: )? catch ) \s* ) ( \( ) /xmsgc) {
3016 25         46 $parsed .= $1;
3017              
3018             # outputs expr
3019 25         35 my $expr = parse_expr_balanced($2);
3020 25         29 $parsed .= $expr;
3021             }
3022              
3023             # mb::catch (expr) --> catch (expr)
3024             elsif (/\G mb:: ( catch \s* ) ( \( ) /xmsgc) {
3025 4         7 $parsed .= $1;
3026              
3027             # outputs expr
3028 4         6 my $expr = parse_expr_balanced($2);
3029 4         4 $parsed .= $expr;
3030             }
3031              
3032             # else
3033             elsif (/\G ( else ) \b /xmsgc) {
3034 1         2 $parsed .= $1;
3035             }
3036              
3037             # ... if expr;
3038             # ... unless expr;
3039             # ... while expr;
3040             # ... until expr;
3041             elsif (/\G ( if | unless | while | until ) \b /xmsgc) {
3042 13         25 $parsed .= $1;
3043             }
3044              
3045             # foreach my $var (expr) --> foreach my $var (expr)
3046             # for my $var (expr) --> for my $var (expr)
3047             elsif (/\G ( (?: foreach | for ) \s+ my \s* [\$] [A-Za-z_][A-Za-z_0-9]* ) ( \( ) /xmsgc) {
3048 0         0 $parsed .= $1;
3049 0         0 $parsed .= parse_expr_balanced($2);
3050             }
3051              
3052             # foreach $var (expr) --> foreach $var (expr)
3053             # for $var (expr) --> for $var (expr)
3054             elsif (/\G ( (?: foreach | for ) \s* [\$] [\$]* (?: \{[A-Za-z_][A-Za-z_0-9]*(?:(?:'|::)[A-Za-z_][A-Za-z_0-9]*)*\} | [A-Za-z_][A-Za-z_0-9]*(?:(?:'|::)[A-Za-z_][A-Za-z_0-9]* ) ) ) ( \( ) /xmsgc) {
3055 0         0 $parsed .= $1;
3056 0         0 $parsed .= parse_expr_balanced($2);
3057             }
3058              
3059             # foreach (expr1; expr2; expr3) --> foreach (expr1; expr2; expr3)
3060             # foreach (expr) --> foreach (expr)
3061             # for (expr1; expr2; expr3) --> for (expr1; expr2; expr3)
3062             # for (expr) --> for (expr)
3063             elsif (/\G ( (?: foreach | for ) \s* ) ( \( ) /xmsgc) {
3064 4         9 $parsed .= $1;
3065 4         6 $parsed .= parse_expr_balanced($2);
3066             }
3067              
3068             # CORE::split --> mb::_split
3069             # mb::split --> mb::_split
3070             # split --> mb::_split
3071             elsif (/\G (?: CORE:: | mb:: | $old_package )? ( split ) \b /xmsgc) {
3072 679         965 $parsed .= "mb::_split";
3073              
3074             # parse \s and '('
3075 679         633 while (1) {
3076 1364 100       2851 if (/\G ( \s+ ) /xmsgc) {
    100          
    100          
3077 296         431 $parsed .= $1;
3078             }
3079             elsif (/\G ( \( ) /xmsgc) {
3080 389         575 $parsed .= $1;
3081             }
3082             elsif (/\G ( \# .* \n ) /xmgc) {
3083 16         21 $parsed .= $1;
3084 16         39 last;
3085             }
3086             else {
3087 663         766 last;
3088             }
3089             }
3090 679         689 my $regexp = '';
3091              
3092             # split /^/ --> mb::_split qr/^/m
3093             # split /.../ --> mb::_split qr/.../
3094 679 100       1653 if (m{\G ( [/] ) }xmsgc) {
    100          
3095 24         23 $parsed .= "qr";
3096 24         30 $regexp = parse_re_endswith('m',$1); # split /.../
3097 24         36 my($modifier_i, $modifier_not_cegir, $modifier_cegr) = parse_re_modifier();
3098              
3099             # P.794 29.2.161. split
3100             # in Chapter 29: Functions
3101             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
3102              
3103             # P.951 split
3104             # in Chapter 27: Functions
3105             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
3106              
3107             # said "The //m modifier is assumed when you split on the pattern /^/",
3108             # but perl5.008 is not so. Therefore, this software adds //m.
3109             # (and so on)
3110              
3111 24 100       44 if ($modifier_not_cegir !~ /m/xms) {
3112 18         20 $modifier_not_cegir .= 'm';
3113             }
3114              
3115             # /xx modifier
3116 24 100       40 if (($modifier_not_cegir =~ tr/x//) >= 2) {
3117 1         4 $regexp = mb::_ignore_space($regexp);
3118             }
3119              
3120             # /i modifier
3121 24 100       44 if ($modifier_i) {
3122 6         9 $parsed .= sprintf('{@{[mb::_ignorecase(qr%s%s)]}}%s', $regexp, $modifier_not_cegir, $modifier_cegr);
3123             }
3124             else {
3125 18         27 $parsed .= sprintf('{@{[' . 'qr%s%s ]}}%s', $regexp, $modifier_not_cegir, $modifier_cegr);
3126             }
3127             }
3128              
3129             # split m/^/ --> mb::_split qr/^/m
3130             # split m/.../ --> mb::_split qr/.../
3131             elsif (/\G ( m | qr ) \b /xmsgc) {
3132 611         572 $parsed .= "qr";
3133              
3134 611 100       2301 if (/\G ( [#] ) /xmsgc) { $regexp = parse_re_endswith('m',$1); } # split qr#...#
  8 100       15  
    100          
    100          
    100          
    100          
    50          
3135 8         19 elsif (/\G ( ['] ) /xmsgc) { $regexp = parse_re_as_q_endswith('m',$1); } # split qr'...'
3136 32         53 elsif (/\G ( [\(\{\[\<] ) /xmsgc) { $regexp = parse_re_balanced('m',$1); } # split qr{...}
3137 83         152 elsif (m{\G( [/] ) }xmsgc) { $regexp = parse_re_endswith('m',$1); } # split qr/.../
3138 16         24 elsif (/\G ( [:\@] ) /xmsgc) { $regexp = ('`' . quotee_of(parse_re_endswith('m',$1)) . '`'); } # split qr@...@
3139 184         255 elsif (/\G ( [\S] ) /xmsgc) { $regexp = parse_re_endswith('m',$1); } # split qr?...?
3140 280         394 elsif (/\G ( \s+ ) /xmsgc) { $parsed .= $1; $regexp = $1; # split qr SPACE ...
  280         318  
3141 280         517 while (/\G ( \s+ | [#] [^\n]* ) /xmsgc) {
3142 32         75 $parsed .= $1;
3143             }
3144 280 100       943 if (/\G ( [A-Za-z_0-9] ) /xmsgc) { $regexp .= parse_re_endswith('m',$1); } # split qr SPACE A...A
  24 100       34  
    100          
    100          
    100          
    50          
3145 8         18 elsif (/\G ( ['] ) /xmsgc) { $regexp .= parse_re_as_q_endswith('m',$1); } # split qr SPACE '...'
3146 32         49 elsif (/\G ( [\(\{\[\<] ) /xmsgc) { $regexp .= parse_re_balanced('m',$1); } # split qr SPACE {...}
3147 8         15 elsif (m{\G( [/] ) }xmsgc) { $regexp .= parse_re_endswith('m',$1); } # split qr SPACE /.../
3148 16         25 elsif (/\G ( [:\@] ) /xmsgc) { $regexp .= ('`' . quotee_of(parse_re_endswith('m',$1)) . '`'); } # split qr SPACE @...@
3149 192         261 elsif (/\G ( [\S] ) /xmsgc) { $regexp .= parse_re_endswith('m',$1); } # split qr SPACE ?...?
3150 0         0 else { die "$0(@{[__LINE__]}): $ARGV[0] has not closed:\n", $parsed; }
  0         0  
3151             }
3152 0         0 else { die "$0(@{[__LINE__]}): $ARGV[0] has not closed:\n", $parsed; }
  0         0  
3153              
3154 611         884 my($modifier_i, $modifier_not_cegir, $modifier_cegr) = parse_re_modifier();
3155              
3156 611 100       993 if ($modifier_not_cegir !~ /m/xms) {
3157 607         614 $modifier_not_cegir .= 'm';
3158             }
3159              
3160             # /xx modifier
3161 611 100       1036 if (($modifier_not_cegir =~ tr/x//) >= 2) {
3162 1         2 $regexp = mb::_ignore_space($regexp);
3163             }
3164              
3165             # /i modifier
3166 611 100       726 if ($modifier_i) {
3167 16         30 $parsed .= sprintf('{@{[mb::_ignorecase(qr%s%s)]}}%s', $regexp, $modifier_not_cegir, $modifier_cegr);
3168             }
3169             else {
3170 595         735 $parsed .= sprintf('{@{[' . 'qr%s%s ]}}%s', $regexp, $modifier_not_cegir, $modifier_cegr);
3171             }
3172             }
3173              
3174 679         968 $parsed .= parse_ambiguous_char();
3175             }
3176              
3177             # provides bare Perl and JPerl compatible functions
3178             elsif (/\G ( (?: lc | lcfirst | uc | ucfirst ) ) \b /xmsgc) {
3179 15         36 $parsed .= "mb::$1";
3180 15         24 $parsed .= parse_ambiguous_char();
3181             }
3182              
3183             # CORE::require, mb::require, require
3184             elsif (/\G ( (?: CORE:: | mb:: )? require ) /xmsgc) {
3185 3         7 $parsed .= $1;
3186 3         4 $parsed .= parse_ambiguous_char();
3187             }
3188              
3189             # mb::use --> BEGIN { mb::require ... }
3190             # mb::no --> BEGIN { mb::require ... }
3191             elsif (/\G ( mb::use | mb::no ) \b /xmsgc) {
3192 42   50     145 my $method = { 'mb::use'=>'import', 'mb::no'=>'unimport' }->{$1} || die;
3193 42         66 $parsed .= "BEGIN { mb::require";
3194 42         93 while (/\G ( \s+ | [#] [^\n]* ) /xmsgc) {
3195 58         123 $parsed .= $1;
3196             }
3197 42 50       124 if (/\G ( [A-Za-z_][A-Za-z_0-9]* (?: ::[A-Za-z_][A-Za-z_0-9]*)* ) /xmsgc) {
3198 42         64 my $module = $1;
3199 42         52 $parsed .= qq{'$module';};
3200 42         81 while (/\G ( \s+ | [#] [^\n]* ) /xmsgc) {
3201 54         90 $parsed .= $1;
3202             }
3203 42 100       87 if (/\G ( [0-9]+ (?: \.[0-9]+)* ) /xmsgc) {
3204 26         44 my $version = $1;
3205 26         30 $parsed .= qq{$module->VERSION($version);};
3206 26         45 while (/\G ( \s+ | [#] [^\n]* ) /xmsgc) {
3207 46         76 $parsed .= $1;
3208             }
3209             }
3210 42         105 my $list = parse_expr_endswith(qr< [;\}] | \z >xms);
3211 42 100       1578 if ($list eq '') {
    100          
3212 12         19 $parsed .= qq{ $module->$method; };
3213             }
3214             elsif (scalar(CORE::eval("()=$list")) == 0) {
3215             }
3216             else {
3217 22         40 $parsed .= qq{ $module->$method($list); };
3218             }
3219             }
3220 42         81 $parsed .= "}";
3221             }
3222              
3223             # mb::getc() --> mb::getc()
3224             # vvvvvvvvvvvvvvvvvvvvvvvvvv
3225             # vvvvvvvvvvvv
3226             elsif (/\G ( mb::getc ) (?= (?: \s* \( )+ \s* \) ) /xmsgc) {
3227 1         2 $parsed .= $1;
3228             }
3229              
3230             # mb::getc($fh) --> mb::getc($fh)
3231             # mb::getc $fh --> mb::getc $fh
3232             # vvvvvvvvvvvvvvvvvvvvvvvvvv
3233             # vvvvvvvvvvvv
3234             elsif (/\G ( mb::getc ) (?= (?: \s* \( )* \s* \$ ) /xmsgc) {
3235 2         4 $parsed .= $1;
3236             }
3237              
3238             # mb::getc(FILE) --> mb::getc(\*FILE)
3239             # mb::getc FILE --> mb::getc \*FILE
3240             # vvvvvvvvvvvvvvvvvvvvv
3241             # vvvvvvvvvvvv vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
3242             elsif (/\G ( mb::getc ) \b ( (?: \s* \( )* \s* ) (?= [A-Za-z_][A-Za-z0-9_]* \b ) /xmsgc) {
3243 2         5 $parsed .= $1;
3244 2         3 $parsed .= $2;
3245 2         3 $parsed .= '\\*';
3246             }
3247              
3248             # mb::getc --> mb::getc
3249             elsif (/\G ( mb::getc ) /xmsgc) {
3250 1         3 $parsed .= $1;
3251 1         2 $parsed .= parse_ambiguous_char();
3252             }
3253              
3254             # CORE::functions that allow zero parameters
3255             # mb::functions that allow zero parameters
3256             elsif (/\G ( (?: CORE:: | mb:: )? (?:
3257             chop |
3258             chr |
3259             getc |
3260             lc |
3261             lcfirst |
3262             length |
3263             ord |
3264             uc |
3265             ucfirst
3266             ) ) \b /xmsgc) {
3267 28         66 $parsed .= $1;
3268 28         34 $parsed .= parse_ambiguous_char();
3269             }
3270              
3271             # CORE::functions that must parameters
3272             # mb::functions that must parameters
3273             elsif (/\G ( (?: CORE:: | mb:: )? (?:
3274             index |
3275             reverse |
3276             rindex |
3277             substr
3278             ) ) \b /xmsgc) {
3279 26         60 $parsed .= $1;
3280             }
3281              
3282             # mb::subroutines
3283             elsif (/\G ( mb:: (?: index_byte | rindex_byte ) ) \b /xmsgc) {
3284 2         5 $parsed .= $1;
3285             }
3286              
3287             # CORE::functions that allow zero parameters
3288             # functions that allow zero parameters
3289             elsif (/\G ( (?: CORE:: )? (?:
3290             _ |
3291             abs |
3292             chomp |
3293             cos |
3294             exp |
3295             fc |
3296             hex |
3297             int |
3298             __LINE__ |
3299             log |
3300             oct |
3301             pop |
3302             pos |
3303             quotemeta |
3304             rand |
3305             rmdir |
3306             shift |
3307             sin |
3308             sqrt |
3309             tell |
3310             time |
3311             umask |
3312             wantarray
3313             ) ) \b /xmsgc) {
3314 2885         6462 $parsed .= $1;
3315 2885         4026 $parsed .= parse_ambiguous_char();
3316             }
3317              
3318             # lstat(), stat() on MSWin32
3319              
3320             # lstat() --> mb::_lstat()
3321             # stat() --> mb::_stat()
3322             # vvvvvvvvvvvvvvvvvvvvvvvvvv
3323             # vvvvvvvvvvvv
3324             elsif (/\G ( lstat | stat ) (?= (?: \s* \( )+ \s* \) ) /xmsgc) {
3325 2         4 $parsed .= "mb::_$1";
3326             }
3327              
3328             # lstat(...) --> mb::_lstat(...)
3329             # stat(...) --> mb::_stat(...)
3330             # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
3331             # vvvvvvvvvvvv vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
3332             elsif (/\G ( lstat | stat ) (?= (?: \s* \( )* \b (?: ' | " | ` | m | q | qq | qr | qw | qx | s | tr | y | \$ ) \b ) /xmsgc) {
3333 18         37 $parsed .= "mb::_$1";
3334             }
3335              
3336             # lstat(FILE) --> mb::_lstat(\*FILE)
3337             # lstat FILE --> mb::_lstat \*FILE
3338             # stat(FILE) --> mb::_stat(\*FILE)
3339             # stat FILE --> mb::_stat \*FILE
3340             # vvvvvvvvvvvvvvvvvvvvv
3341             # vvvvvvvvvvvv vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
3342             elsif (/\G ( lstat | stat ) \b ( (?: \s* \( )* \s* ) (?= [A-Za-z_][A-Za-z0-9_]* \b ) /xmsgc) {
3343 10         19 $parsed .= "mb::_$1";
3344 10         14 $parsed .= $2;
3345 10         11 $parsed .= '\\*';
3346             }
3347              
3348             # opendir(DIR, ...) --> mb::_opendir(\*DIR, ...)
3349             # opendir DIR, ... --> mb::_opendir \*DIR, ...
3350             # vvvvvvvvvvvvvvvvvvvvv
3351             # vvvvvvvvvvvv vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
3352             elsif (/\G ( opendir ) \b ( (?: \s* \( )* \s* ) (?= [A-Za-z_][A-Za-z0-9_]* \s* , ) /xmsgc) {
3353 4         11 $parsed .= "mb::_$1";
3354 4         9 $parsed .= $2;
3355 4         5 $parsed .= '\\*';
3356             }
3357              
3358             # function --> mb::subroutine on MSWin32
3359             # implements run on any systems by transpiling once
3360             elsif (/\G ( chdir | lstat | stat | unlink ) \b /xmsgc) {
3361 32         80 $parsed .= "mb::_$1";
3362 32         44 $parsed .= parse_ambiguous_char();
3363             }
3364             elsif (/\G ( opendir ) \b /xmsgc) {
3365 4         12 $parsed .= "mb::_$1";
3366             }
3367              
3368             # Carp::carp <
3369             # Carp::cluck <
3370             # Carp::confess <
3371             # Carp::croak <
3372             # carp <
3373             # cluck <
3374             # confess <
3375             # croak <
3376             # die <
3377             # print <
3378             # printf <
3379             # say <
3380             # warn <
3381             elsif (/\G (
3382             Carp::carp |
3383             Carp::cluck |
3384             Carp::confess |
3385             Carp::croak |
3386             carp |
3387             cluck |
3388             confess |
3389             croak |
3390             die |
3391             print |
3392             printf |
3393             say |
3394             warn
3395             ) (?= (?: \s+ | [#] .* )* << ) /xgc) {
3396 0         0 $parsed .= $1;
3397             # without $parsed .= parse_ambiguous_char();
3398             }
3399              
3400             # printf FILEHANDLE <
3401             # print FILEHANDLE <
3402             # say FILEHANDLE <
3403             elsif (/\G (
3404             (?: printf | print | say )
3405             (?: \s+ | [#] .* )*
3406             (?! [a-z]+ ) # lowercase is considered to be function
3407             (?: \b [A-Za-z_][A-Za-z_0-9]*(?: :: [A-Za-z_][A-Za-z_0-9]*)* |
3408             \$ [A-Za-z_][A-Za-z_0-9]*(?: :: [A-Za-z_][A-Za-z_0-9]*)*
3409             )
3410             ) /xgc) {
3411 25         53 $parsed .= $1;
3412             # without $parsed .= parse_ambiguous_char();
3413             }
3414              
3415             # printf {FILEHANDLE} <
3416             # print {FILEHANDLE} <
3417             # say {FILEHANDLE} <
3418             elsif (/\G (
3419             (?: printf | print | say )
3420             (?: \s+ | [#] .* )*
3421             ) (\{)
3422             /xgc) {
3423 0         0 $parsed .= $1;
3424 0         0 $parsed .= parse_expr_balanced($2);
3425             # without $parsed .= parse_ambiguous_char();
3426             }
3427              
3428             # return
3429             elsif (/\G ( return ) /xmsgc) {
3430 14         25 $parsed .= $1;
3431             }
3432              
3433             # any word
3434             # "\x5F" [_] LOW LINE (U+005F)
3435             # "\x41" [A] LATIN CAPITAL LETTER A (U+0041)
3436             # "\x42" [B] LATIN CAPITAL LETTER B (U+0042)
3437             # "\x43" [C] LATIN CAPITAL LETTER C (U+0043)
3438             # "\x44" [D] LATIN CAPITAL LETTER D (U+0044)
3439             # "\x45" [E] LATIN CAPITAL LETTER E (U+0045)
3440             # "\x46" [F] LATIN CAPITAL LETTER F (U+0046)
3441             # "\x47" [G] LATIN CAPITAL LETTER G (U+0047)
3442             # "\x48" [H] LATIN CAPITAL LETTER H (U+0048)
3443             # "\x49" [I] LATIN CAPITAL LETTER I (U+0049)
3444             # "\x4A" [J] LATIN CAPITAL LETTER J (U+004A)
3445             # "\x4B" [K] LATIN CAPITAL LETTER K (U+004B)
3446             # "\x4C" [L] LATIN CAPITAL LETTER L (U+004C)
3447             # "\x4D" [M] LATIN CAPITAL LETTER M (U+004D)
3448             # "\x4E" [N] LATIN CAPITAL LETTER N (U+004E)
3449             # "\x4F" [O] LATIN CAPITAL LETTER O (U+004F)
3450             # "\x50" [P] LATIN CAPITAL LETTER P (U+0050)
3451             # "\x51" [Q] LATIN CAPITAL LETTER Q (U+0051)
3452             # "\x52" [R] LATIN CAPITAL LETTER R (U+0052)
3453             # "\x53" [S] LATIN CAPITAL LETTER S (U+0053)
3454             # "\x54" [T] LATIN CAPITAL LETTER T (U+0054)
3455             # "\x55" [U] LATIN CAPITAL LETTER U (U+0055)
3456             # "\x56" [V] LATIN CAPITAL LETTER V (U+0056)
3457             # "\x57" [W] LATIN CAPITAL LETTER W (U+0057)
3458             # "\x58" [X] LATIN CAPITAL LETTER X (U+0058)
3459             # "\x59" [Y] LATIN CAPITAL LETTER Y (U+0059)
3460             # "\x5A" [Z] LATIN CAPITAL LETTER Z (U+005A)
3461             # "\x61" [a] LATIN SMALL LETTER A (U+0061)
3462             # "\x62" [b] LATIN SMALL LETTER B (U+0062)
3463             # "\x63" [c] LATIN SMALL LETTER C (U+0063)
3464             # "\x64" [d] LATIN SMALL LETTER D (U+0064)
3465             # "\x65" [e] LATIN SMALL LETTER E (U+0065)
3466             # "\x66" [f] LATIN SMALL LETTER F (U+0066)
3467             # "\x67" [g] LATIN SMALL LETTER G (U+0067)
3468             # "\x68" [h] LATIN SMALL LETTER H (U+0068)
3469             # "\x69" [i] LATIN SMALL LETTER I (U+0069)
3470             # "\x6A" [j] LATIN SMALL LETTER J (U+006A)
3471             # "\x6B" [k] LATIN SMALL LETTER K (U+006B)
3472             # "\x6C" [l] LATIN SMALL LETTER L (U+006C)
3473             # "\x6D" [m] LATIN SMALL LETTER M (U+006D)
3474             # "\x6E" [n] LATIN SMALL LETTER N (U+006E)
3475             # "\x6F" [o] LATIN SMALL LETTER O (U+006F)
3476             # "\x70" [p] LATIN SMALL LETTER P (U+0070)
3477             # "\x71" [q] LATIN SMALL LETTER Q (U+0071)
3478             # "\x72" [r] LATIN SMALL LETTER R (U+0072)
3479             # "\x73" [s] LATIN SMALL LETTER S (U+0073)
3480             # "\x74" [t] LATIN SMALL LETTER T (U+0074)
3481             # "\x75" [u] LATIN SMALL LETTER U (U+0075)
3482             # "\x76" [v] LATIN SMALL LETTER V (U+0076)
3483             # "\x77" [w] LATIN SMALL LETTER W (U+0077)
3484             # "\x78" [x] LATIN SMALL LETTER X (U+0078)
3485             # "\x79" [y] LATIN SMALL LETTER Y (U+0079)
3486             # "\x7A" [z] LATIN SMALL LETTER Z (U+007A)
3487             elsif (/\G ( [A-Za-z_][A-Za-z_0-9]*(?:(?:'|::)[A-Za-z_][A-Za-z_0-9]*)* ) /xmsgc) {
3488 561         1141 $parsed .= $1;
3489 561         876 $parsed .= parse_ambiguous_char();
3490             }
3491              
3492             # any right parenthesis
3493             # "\x29" [)] RIGHT PARENTHESIS (U+0029)
3494             # "\x7D" [}] RIGHT CURLY BRACKET (U+007D)
3495             # "\x5D" []] RIGHT SQUARE BRACKET (U+005D)
3496             elsif (/\G ([\)\}\]]) /xmsgc) {
3497 396         763 $parsed .= $1;
3498 396         466 $parsed .= parse_ambiguous_char();
3499             }
3500              
3501             # any US-ASCII
3502             # "\x3A" [:] COLON (U+003A)
3503             elsif (/\G ([\x00-\x7F]) /xmsgc) {
3504 8665         14817 $parsed .= $1;
3505             }
3506              
3507             # otherwise
3508             elsif (/\G ($x) /xmsgc) {
3509 0         0 die "$0(@{[__LINE__]}): can't parse not US-ASCII '$1'.\n";
  0         0  
3510             }
3511              
3512 683699         1843939 return $parsed;
3513             }
3514              
3515             #---------------------------------------------------------------------
3516             # parse expression in balanced blackets
3517             sub parse_expr_balanced {
3518 886     889 0 1470 my($open_bracket) = @_;
3519 886   50     3042 my $close_bracket = {qw| ( ) { } [ ] < > |}->{$open_bracket} || die;
3520 886         1463 my $parsed = $open_bracket;
3521 886         986 my $nest_bracket = 1;
3522 886         867 while (1) {
3523              
3524             # open bracket
3525 4623 100       25673 if (/\G (\Q$open_bracket\E) /xmsgc) {
    100          
3526 34         65 $parsed .= $1;
3527 34         40 $nest_bracket++;
3528             }
3529              
3530             # close bracket
3531             elsif (/\G (\Q$close_bracket\E) /xmsgc) {
3532 920         1143 $parsed .= $1;
3533 920         1099 $parsed .= parse_ambiguous_char();
3534 920 100       1450 if (--$nest_bracket <= 0) {
3535 886         970 last;
3536             }
3537             }
3538              
3539             # otherwise
3540             else {
3541 3669         8569 $parsed .= parse_expr();
3542             }
3543             }
3544 886         1417 return $parsed;
3545             }
3546              
3547             #---------------------------------------------------------------------
3548             # parse expression that ends with a regexp
3549             sub parse_expr_endswith {
3550 42     45 0 49 my($endswith) = @_;
3551 42         38 my $parsed = '';
3552 42         37 while (1) {
3553 72 100       248 if (/\G (?= $endswith ) /xmsgc) {
3554 42         38 last;
3555             }
3556             else {
3557 30         168 $parsed .= parse_expr();
3558             }
3559             }
3560 42         58 return $parsed;
3561             }
3562              
3563             #---------------------------------------------------------------------
3564             # parse <<'HERE_DOCUMENT' as q-like
3565             sub parse_heredocument_as_q_endswith {
3566 9     12 0 12 my($endswith) = @_;
3567 9         12 my $parsed = '';
3568 9         9 while (1) {
3569 465 100       1479 if (/\G ( $R $endswith ) /xmsgc) {
    50          
3570 9         14 $parsed .= $1;
3571 9         10 last;
3572             }
3573             elsif (/\G ($x) /xmsgc) {
3574 456         450 $parsed .= $1;
3575             }
3576              
3577             # something wrong happened
3578             else {
3579 0         0 die sprintf(<
3580 0         0 $0(@{[__LINE__]}): something wrong happened in script at pos=%s
3581             ------------------------------------------------------------------------------
3582             %s
3583             ------------------------------------------------------------------------------
3584             END
3585             }
3586             }
3587 9         32 return $parsed;
3588             }
3589              
3590             #---------------------------------------------------------------------
3591             # parse <<"HERE_DOCUMENT" as qq-like
3592             sub parse_heredocument_as_qq_endswith {
3593 14     17 0 15 my($endswith) = @_;
3594 14         14 my $parsed = '';
3595 14         11 my $nest_escape = 0;
3596 14         11 while (1) {
3597 14 50       122 if (/\G ( $R $endswith ) /xmsgc) {
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
3598 14         22 $parsed .= ('>)]}' x $nest_escape);
3599 14         70 $parsed .= $1;
3600 14         15 last;
3601             }
3602              
3603             # \L\u --> \u\L
3604             elsif (/\G \\L \\u /xmsgc) {
3605 0         0 $parsed .= '@{[mb::ucfirst(qq<';
3606 0         0 $parsed .= '@{[mb::lc(qq<';
3607 0         0 $nest_escape++;
3608 0         0 $nest_escape++;
3609             }
3610              
3611             # \U\l --> \l\U
3612             elsif (/\G \\U \\l /xmsgc) {
3613 0         0 $parsed .= '@{[mb::lcfirst(qq<';
3614 0         0 $parsed .= '@{[mb::uc(qq<';
3615 0         0 $nest_escape++;
3616 0         0 $nest_escape++;
3617             }
3618              
3619             # \L
3620             elsif (/\G \\L /xmsgc) {
3621 0         0 $parsed .= '@{[mb::lc(qq<';
3622 0         0 $nest_escape++;
3623             }
3624              
3625             # \U
3626             elsif (/\G \\U /xmsgc) {
3627 0         0 $parsed .= '@{[mb::uc(qq<';
3628 0         0 $nest_escape++;
3629             }
3630              
3631             # \l
3632             elsif (/\G \\l /xmsgc) {
3633 0         0 $parsed .= '@{[mb::lcfirst(qq<';
3634 0         0 $nest_escape++;
3635             }
3636              
3637             # \u
3638             elsif (/\G \\u /xmsgc) {
3639 0         0 $parsed .= '@{[mb::ucfirst(qq<';
3640 0         0 $nest_escape++;
3641             }
3642              
3643             # \Q
3644             elsif (/\G \\Q /xmsgc) {
3645 0         0 $parsed .= '@{[quotemeta(qq<';
3646 0         0 $nest_escape++;
3647             }
3648              
3649             # \E
3650             elsif (/\G \\E /xmsgc) {
3651 0         0 $parsed .= ('>)]}' x $nest_escape);
3652 0         0 $nest_escape = 0;
3653             }
3654              
3655             # \o{...}
3656             elsif (/\G \\o\{ (.*?) \} /xmsgc) {
3657 0         0 $parsed .= escape_to_hex(mb::chr(oct $1), '\\');
3658             }
3659              
3660             # \x{...}
3661             elsif (/\G \\x\{ (.*?) \} /xmsgc) {
3662 0         0 $parsed .= escape_to_hex(mb::chr(hex $1), '\\');
3663             }
3664              
3665             # \any
3666             elsif (/\G (\\) ($x) /xmsgc) {
3667 0         0 $parsed .= ($1 . escape_qq($2, '\\'));
3668             }
3669              
3670             # $` --> @{[mb::_PREMATCH()]}
3671             # ${`} --> @{[mb::_PREMATCH()]}
3672             # $PREMATCH --> @{[mb::_PREMATCH()]}
3673             # ${PREMATCH} --> @{[mb::_PREMATCH()]}
3674             # ${^PREMATCH} --> @{[mb::_PREMATCH()]}
3675             elsif (/\G (?: \$` | \$\{`\} | \$PREMATCH | \$\{PREMATCH\} | \$\{\^PREMATCH\} ) /xmsgc) {
3676 0         0 $parsed .= '@{[mb::_PREMATCH()]}';
3677             }
3678              
3679             # $& --> @{[mb::_MATCH()]}
3680             # ${&} --> @{[mb::_MATCH()]}
3681             # $MATCH --> @{[mb::_MATCH()]}
3682             # ${MATCH} --> @{[mb::_MATCH()]}
3683             # ${^MATCH} --> @{[mb::_MATCH()]}
3684             elsif (/\G (?: \$& | \$\{&\} | \$MATCH | \$\{MATCH\} | \$\{\^MATCH\} ) /xmsgc) {
3685 0         0 $parsed .= '@{[mb::_MATCH()]}';
3686             }
3687              
3688             # $1 --> @{[mb::_CAPTURE(1)]}
3689             # $2 --> @{[mb::_CAPTURE(2)]}
3690             # $3 --> @{[mb::_CAPTURE(3)]}
3691             elsif (/\G \$ ([1-9][0-9]*) /xmsgc) {
3692 0         0 $parsed .= "\@{[mb::_CAPTURE($1)]}";
3693             }
3694              
3695             # @{^CAPTURE} --> @{[mb::_CAPTURE()]}
3696             elsif (/\G \@\{\^CAPTURE\} /xmsgc) {
3697 0         0 $parsed .= '@{[mb::_CAPTURE()]}';
3698             }
3699              
3700             # ${^CAPTURE}[0] --> @{[mb::_CAPTURE(1)]}
3701             # ${^CAPTURE}[1] --> @{[mb::_CAPTURE(2)]}
3702             # ${^CAPTURE}[2] --> @{[mb::_CAPTURE(3)]}
3703             elsif (/\G \$\{\^CAPTURE\} \s* (\[) /xmsgc) {
3704 0         0 my $n_th = quotee_of(parse_expr_balanced($1));
3705 0         0 $parsed .= "\@{[mb::_CAPTURE($n_th+1)]}";
3706             }
3707              
3708             # @- --> @{[mb::_LAST_MATCH_START()]}
3709             # @LAST_MATCH_START --> @{[mb::_LAST_MATCH_START()]}
3710             # @{LAST_MATCH_START} --> @{[mb::_LAST_MATCH_START()]}
3711             # @{^LAST_MATCH_START} --> @{[mb::_LAST_MATCH_START()]}
3712             elsif (/\G (?: \@- | \@LAST_MATCH_START | \@\{LAST_MATCH_START\} | \@\{\^LAST_MATCH_START\} ) /xmsgc) {
3713 0         0 $parsed .= '@{[mb::_LAST_MATCH_START()]}';
3714             }
3715              
3716             # $-[1] --> @{[mb::_LAST_MATCH_START(1)]}
3717             # $LAST_MATCH_START[1] --> @{[mb::_LAST_MATCH_START(1)]}
3718             # ${LAST_MATCH_START}[1] --> @{[mb::_LAST_MATCH_START(1)]}
3719             # ${^LAST_MATCH_START}[1] --> @{[mb::_LAST_MATCH_START(1)]}
3720             elsif (/\G (?: \$- | \$LAST_MATCH_START | \$\{LAST_MATCH_START\} | \$\{\^LAST_MATCH_START\} ) \s* (\[) /xmsgc) {
3721 0         0 my $n_th = quotee_of(parse_expr_balanced($1));
3722 0         0 $parsed .= "\@{[mb::_LAST_MATCH_START($n_th)]}";
3723             }
3724              
3725             # @+ --> @{[mb::_LAST_MATCH_END()]}
3726             # @LAST_MATCH_END --> @{[mb::_LAST_MATCH_END()]}
3727             # @{LAST_MATCH_END} --> @{[mb::_LAST_MATCH_END()]}
3728             # @{^LAST_MATCH_END} --> @{[mb::_LAST_MATCH_END()]}
3729             elsif (/\G (?: \@\+ | \@LAST_MATCH_END | \@\{LAST_MATCH_END\} | \@\{\^LAST_MATCH_END\} ) /xmsgc) {
3730 0         0 $parsed .= '@{[mb::_LAST_MATCH_END()]}';
3731             }
3732              
3733             # $+[1] --> @{[mb::_LAST_MATCH_END(1)]}
3734             # $LAST_MATCH_END[1] --> @{[mb::_LAST_MATCH_END(1)]}
3735             # ${LAST_MATCH_END}[1] --> @{[mb::_LAST_MATCH_END(1)]}
3736             # ${^LAST_MATCH_END}[1] --> @{[mb::_LAST_MATCH_END(1)]}
3737             elsif (/\G (?: \$\+ | \$LAST_MATCH_END | \$\{LAST_MATCH_END\} | \$\{\^LAST_MATCH_END\} ) \s* (\[) /xmsgc) {
3738 0         0 my $n_th = quotee_of(parse_expr_balanced($1));
3739 0         0 $parsed .= "\@{[mb::_LAST_MATCH_END($n_th)]}";
3740             }
3741              
3742             # any
3743             elsif (/\G ($x) /xmsgc) {
3744 0         0 $parsed .= escape_qq($1, '\\');
3745             }
3746              
3747             # something wrong happened
3748             else {
3749 0         0 die sprintf(<
3750 0         0 $0(@{[__LINE__]}): something wrong happened in script at pos=%s
3751             ------------------------------------------------------------------------------
3752             %s
3753             ------------------------------------------------------------------------------
3754             END
3755             }
3756             }
3757 14         33 return $parsed;
3758             }
3759              
3760             #---------------------------------------------------------------------
3761             # parse q{string} in balanced blackets
3762             sub parse_q__like_balanced {
3763 53     56 0 361 my($open_bracket) = @_;
3764 53   50     275 my $close_bracket = {qw| ( ) { } [ ] < > |}->{$open_bracket} || die;
3765 53         99 my $parsed = $open_bracket;
3766 53         106 my $nest_bracket = 1;
3767 53         51 while (1) {
3768 258 50       1514 if (/\G (\Q$open_bracket\E) /xmsgc) {
    100          
    50          
3769 0         0 $parsed .= $1;
3770 0         0 $nest_bracket++;
3771             }
3772             elsif (/\G (\Q$close_bracket\E) /xmsgc) {
3773 53         68 $parsed .= $1;
3774 53 50       114 if (--$nest_bracket <= 0) {
3775 53         64 last;
3776             }
3777             }
3778             elsif (/\G (\\ \Q$close_bracket\E) /xmsgc) {
3779 0         0 $parsed .= $1;
3780             }
3781             else {
3782 205         279 $parsed .= parse_q__like($close_bracket);
3783             }
3784             }
3785 53         88 return $parsed;
3786             }
3787              
3788             #---------------------------------------------------------------------
3789             # parse q/string/ that ends with a character
3790             sub parse_q__like_endswith {
3791 5979     5982 0 11876 my($endswith) = @_;
3792 5979         7360 my $parsed = $endswith;
3793 5979         6264 while (1) {
3794 14662 100       46449 if (/\G (\Q$endswith\E) /xmsgc) {
    50          
3795 5979         11312 $parsed .= $1;
3796 5979         7443 last;
3797             }
3798             elsif (/\G (\\ \Q$endswith\E) /xmsgc) {
3799 0         0 $parsed .= $1;
3800             }
3801             else {
3802 8683         11727 $parsed .= parse_q__like($endswith);
3803             }
3804             }
3805 5979         9164 return $parsed;
3806             }
3807              
3808             #---------------------------------------------------------------------
3809             # parse q/string/ common routine
3810             sub parse_q__like {
3811 8888     8891 0 10535 my($closewith) = @_;
3812 8888 100       31869 if (/\G (\\\\) /xmsgc) {
    50          
3813 13         20 return $1;
3814             }
3815             elsif (/\G ($x) /xmsgc) {
3816 8875         13604 return escape_q($1, $closewith);
3817             }
3818              
3819             # something wrong happened
3820             else {
3821 0         0 die sprintf(<
3822 0         0 $0(@{[__LINE__]}): something wrong happened in script at pos=%s
3823             ------------------------------------------------------------------------------
3824             %s
3825             ------------------------------------------------------------------------------
3826             END
3827             }
3828             }
3829              
3830             #---------------------------------------------------------------------
3831             # parse qq{string} in balanced blackets
3832             sub parse_qq_like_balanced {
3833 85     88 0 111 my($open_bracket) = @_;
3834 85   50     286 my $close_bracket = {qw| ( ) { } [ ] < > |}->{$open_bracket} || die;
3835 85         135 my $parsed_as_q = $open_bracket;
3836 85         78 my $parsed_as_qq = $open_bracket;
3837 85         81 my $nest_bracket = 1;
3838 85         69 my $nest_escape = 0;
3839 85         71 while (1) {
3840              
3841             # blackets
3842 317 50       3373 if (/\G (\\ \Q$open_bracket\E) /xmsgc) {
    50          
    50          
    100          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
3843 0         0 $parsed_as_q .= $1;
3844 0         0 $parsed_as_qq .= $1;
3845             }
3846             elsif (/\G (\\ \Q$close_bracket\E) /xmsgc) {
3847 0         0 $parsed_as_q .= $1;
3848 0         0 $parsed_as_qq .= $1;
3849             }
3850             elsif (/\G (\Q$open_bracket\E) /xmsgc) {
3851 0         0 $parsed_as_q .= $1;
3852 0         0 $parsed_as_qq .= $1;
3853 0         0 $nest_bracket++;
3854             }
3855             elsif (/\G (\Q$close_bracket\E) /xmsgc) {
3856 85 50       128 if (--$nest_bracket <= 0) {
3857 85         95 $parsed_as_q .= $1;
3858 85         92 $parsed_as_qq .= ('>)]}' x $nest_escape);
3859 85         107 $parsed_as_qq .= $1;
3860 85         94 last;
3861             }
3862             else {
3863 0         0 $parsed_as_q .= $1;
3864 0         0 $parsed_as_qq .= $1;
3865             }
3866             }
3867              
3868             # \L\u --> \u\L
3869             elsif (/\G (\\L \\u) /xmsgc) {
3870 0         0 $parsed_as_q .= $1;
3871 0         0 $parsed_as_qq .= '@{[mb::ucfirst(qq<';
3872 0         0 $parsed_as_qq .= '@{[mb::lc(qq<';
3873 0         0 $nest_escape++;
3874 0         0 $nest_escape++;
3875             }
3876              
3877             # \U\l --> \l\U
3878             elsif (/\G (\\U \\l) /xmsgc) {
3879 0         0 $parsed_as_q .= $1;
3880 0         0 $parsed_as_qq .= '@{[mb::lcfirst(qq<';
3881 0         0 $parsed_as_qq .= '@{[mb::uc(qq<';
3882 0         0 $nest_escape++;
3883 0         0 $nest_escape++;
3884             }
3885              
3886             # \L
3887             elsif (/\G (\\L) /xmsgc) {
3888 0         0 $parsed_as_q .= $1;
3889 0         0 $parsed_as_qq .= '@{[mb::lc(qq<';
3890 0         0 $nest_escape++;
3891             }
3892              
3893             # \U
3894             elsif (/\G (\\U) /xmsgc) {
3895 0         0 $parsed_as_q .= $1;
3896 0         0 $parsed_as_qq .= '@{[mb::uc(qq<';
3897 0         0 $nest_escape++;
3898             }
3899              
3900             # \l
3901             elsif (/\G (\\l) /xmsgc) {
3902 0         0 $parsed_as_q .= $1;
3903 0         0 $parsed_as_qq .= '@{[mb::lcfirst(qq<';
3904 0         0 $nest_escape++;
3905             }
3906              
3907             # \u
3908             elsif (/\G (\\u) /xmsgc) {
3909 0         0 $parsed_as_q .= $1;
3910 0         0 $parsed_as_qq .= '@{[mb::ucfirst(qq<';
3911 0         0 $nest_escape++;
3912             }
3913              
3914             # \Q
3915             elsif (/\G (\\Q) /xmsgc) {
3916 0         0 $parsed_as_q .= $1;
3917 0         0 $parsed_as_qq .= '@{[quotemeta(qq<';
3918 0         0 $nest_escape++;
3919             }
3920              
3921             # \E
3922             elsif (/\G (\\E) /xmsgc) {
3923 0         0 $parsed_as_q .= $1;
3924 0         0 $parsed_as_qq .= ('>)]}' x $nest_escape);
3925 0         0 $nest_escape = 0;
3926             }
3927              
3928             else {
3929 232         330 my($as_qq, $as_q) = parse_qq_like($close_bracket);
3930 232         213 $parsed_as_q .= $as_q;
3931 232         220 $parsed_as_qq .= $as_qq;
3932             }
3933             }
3934              
3935             # return qq-like and q-like quotee
3936 85 100       90 if (wantarray) {
3937 67         117 return ($parsed_as_qq, $parsed_as_q);
3938             }
3939             else {
3940 18         29 return $parsed_as_qq;
3941             }
3942             }
3943              
3944             #---------------------------------------------------------------------
3945             # parse qq/string/ that ends with a character
3946             sub parse_qq_like_endswith {
3947 128003     128006 0 349259 my($endswith) = @_;
3948 128003         178269 my $parsed_as_q = $endswith;
3949 128003         155640 my $parsed_as_qq = $endswith;
3950 128003         168692 my $nest_escape = 0;
3951 128003         142467 while (1) {
3952              
3953             # ends with
3954 689290 50       3580339 if (/\G (\\ \Q$endswith\E) /xmsgc) {
    100          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
3955 0         0 $parsed_as_q .= $1;
3956 0         0 $parsed_as_qq .= $1;
3957             }
3958             elsif (/\G (\Q$endswith\E) /xmsgc) {
3959 128003         266762 $parsed_as_q .= $1;
3960 128003         214253 $parsed_as_qq .= ('>)]}' x $nest_escape);
3961 128003 50       299098 $parsed_as_qq .= "\n" if CORE::length($1) >= 2; # here document
3962 128003         184286 $parsed_as_qq .= $1;
3963 128003         200567 last;
3964             }
3965              
3966             # \L\u --> \u\L
3967             elsif (/\G (\\L \\u) /xmsgc) {
3968 0         0 $parsed_as_q .= $1;
3969 0         0 $parsed_as_qq .= '@{[mb::ucfirst(qq<';
3970 0         0 $parsed_as_qq .= '@{[mb::lc(qq<';
3971 0         0 $nest_escape++;
3972 0         0 $nest_escape++;
3973             }
3974              
3975             # \U\l --> \l\U
3976             elsif (/\G (\\U \\l) /xmsgc) {
3977 0         0 $parsed_as_q .= $1;
3978 0         0 $parsed_as_qq .= '@{[mb::lcfirst(qq<';
3979 0         0 $parsed_as_qq .= '@{[mb::uc(qq<';
3980 0         0 $nest_escape++;
3981 0         0 $nest_escape++;
3982             }
3983              
3984             # \L
3985             elsif (/\G (\\L) /xmsgc) {
3986 0         0 $parsed_as_q .= $1;
3987 0         0 $parsed_as_qq .= '@{[mb::lc(qq<';
3988 0         0 $nest_escape++;
3989             }
3990              
3991             # \U
3992             elsif (/\G (\\U) /xmsgc) {
3993 0         0 $parsed_as_q .= $1;
3994 0         0 $parsed_as_qq .= '@{[mb::uc(qq<';
3995 0         0 $nest_escape++;
3996             }
3997              
3998             # \l
3999             elsif (/\G (\\l) /xmsgc) {
4000 0         0 $parsed_as_q .= $1;
4001 0         0 $parsed_as_qq .= '@{[mb::lcfirst(qq<';
4002 0         0 $nest_escape++;
4003             }
4004              
4005             # \u
4006             elsif (/\G (\\u) /xmsgc) {
4007 0         0 $parsed_as_q .= $1;
4008 0         0 $parsed_as_qq .= '@{[mb::ucfirst(qq<';
4009 0         0 $nest_escape++;
4010             }
4011              
4012             # \Q
4013             elsif (/\G (\\Q) /xmsgc) {
4014 0         0 $parsed_as_q .= $1;
4015 0         0 $parsed_as_qq .= '@{[quotemeta(qq<';
4016 0         0 $nest_escape++;
4017             }
4018              
4019             # \E
4020             elsif (/\G (\\E) /xmsgc) {
4021 0         0 $parsed_as_q .= $1;
4022 0         0 $parsed_as_qq .= ('>)]}' x $nest_escape);
4023 0         0 $nest_escape = 0;
4024             }
4025              
4026             else {
4027 561287         700521 my($as_qq, $as_q) = parse_qq_like($endswith);
4028 561287         563515 $parsed_as_q .= $as_q;
4029 561287         554122 $parsed_as_qq .= $as_qq;
4030             }
4031             }
4032              
4033             # return qq-like and q-like quotee
4034 128003 100       186587 if (wantarray) {
4035 1646         2759 return ($parsed_as_qq, $parsed_as_q);
4036             }
4037             else {
4038 126357         295654 return $parsed_as_qq;
4039             }
4040             }
4041              
4042             #---------------------------------------------------------------------
4043             # parse qq/string/ common routine
4044             sub parse_qq_like {
4045 561519     561522 0 611116 my($closewith) = @_;
4046 561519         537171 my $parsed_as_q = '';
4047 561519         495184 my $parsed_as_qq = '';
4048              
4049             # \o{...}
4050 561519 50       4069730 if (/\G ( \\o\{ (.*?) \} ) /xmsgc) {
    100          
    100          
    100          
    100          
    100          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
4051 0         0 $parsed_as_q .= $1;
4052 0         0 $parsed_as_qq .= escape_to_hex(mb::chr(oct $2), $closewith);
4053             }
4054              
4055             # \x{...}
4056             elsif (/\G ( \\x\{ (.*?) \} ) /xmsgc) {
4057 1         2 $parsed_as_q .= $1;
4058 1         3 $parsed_as_qq .= escape_to_hex(mb::chr(hex $2), $closewith);
4059             }
4060              
4061             # \any
4062             elsif (/\G ( (\\) ($x) ) /xmsgc) {
4063 269         447 $parsed_as_q .= $1;
4064 269         547 $parsed_as_qq .= ($2 . escape_qq($3, $closewith));
4065             }
4066              
4067             # $` --> @{[mb::_PREMATCH()]}
4068             # ${`} --> @{[mb::_PREMATCH()]}
4069             # $PREMATCH --> @{[mb::_PREMATCH()]}
4070             # ${PREMATCH} --> @{[mb::_PREMATCH()]}
4071             # ${^PREMATCH} --> @{[mb::_PREMATCH()]}
4072             elsif (/\G ( \$` | \$\{`\} | \$PREMATCH | \$\{PREMATCH\} | \$\{\^PREMATCH\} ) /xmsgc) {
4073 2         5 $parsed_as_q .= $1;
4074 2         3 $parsed_as_qq .= '@{[mb::_PREMATCH()]}';
4075             }
4076              
4077             # $& --> @{[mb::_MATCH()]}
4078             # ${&} --> @{[mb::_MATCH()]}
4079             # $MATCH --> @{[mb::_MATCH()]}
4080             # ${MATCH} --> @{[mb::_MATCH()]}
4081             # ${^MATCH} --> @{[mb::_MATCH()]}
4082             elsif (/\G ( \$& | \$\{&\} | \$MATCH | \$\{MATCH\} | \$\{\^MATCH\} ) /xmsgc) {
4083 2         3 $parsed_as_q .= $1;
4084 2         2 $parsed_as_qq .= '@{[mb::_MATCH()]}';
4085             }
4086              
4087             # $1 --> @{[mb::_CAPTURE(1)]}
4088             # $2 --> @{[mb::_CAPTURE(2)]}
4089             # $3 --> @{[mb::_CAPTURE(3)]}
4090             elsif (/\G ( \$ ([1-9][0-9]*) ) /xmsgc) {
4091 23         28 $parsed_as_q .= $1;
4092 23         36 $parsed_as_qq .= "\@{[mb::_CAPTURE($2)]}";
4093             }
4094              
4095             # @{^CAPTURE} --> @{[mb::_CAPTURE()]}
4096             elsif (/\G ( \@\{\^CAPTURE\} ) /xmsgc) {
4097 0         0 $parsed_as_q .= $1;
4098 0         0 $parsed_as_qq .= '@{[mb::_CAPTURE()]}';
4099             }
4100              
4101             # ${^CAPTURE}[0] --> @{[mb::_CAPTURE(1)]}
4102             # ${^CAPTURE}[1] --> @{[mb::_CAPTURE(2)]}
4103             # ${^CAPTURE}[2] --> @{[mb::_CAPTURE(3)]}
4104             elsif (/\G (\$\{\^CAPTURE\}) \s* (\[) /xmsgc) {
4105 0         0 my $indexing = parse_expr_balanced($2);
4106 0         0 $parsed_as_q .= ($1 . $indexing);
4107 0         0 my $n_th = quotee_of($indexing);
4108 0         0 $parsed_as_qq .= "\@{[mb::_CAPTURE($n_th)]}";
4109             }
4110              
4111             # @- --> @{[mb::_LAST_MATCH_START()]}
4112             # @LAST_MATCH_START --> @{[mb::_LAST_MATCH_START()]}
4113             # @{LAST_MATCH_START} --> @{[mb::_LAST_MATCH_START()]}
4114             # @{^LAST_MATCH_START} --> @{[mb::_LAST_MATCH_START()]}
4115             elsif (/\G (?: \@- | \@LAST_MATCH_START | \@\{LAST_MATCH_START\} | \@\{\^LAST_MATCH_START\} ) /xmsgc) {
4116 0         0 $parsed_as_q .= $&;
4117 0         0 $parsed_as_qq .= '@{[mb::_LAST_MATCH_START()]}';
4118             }
4119              
4120             # $-[1] --> @{[mb::_LAST_MATCH_START(1)]}
4121             # $LAST_MATCH_START[1] --> @{[mb::_LAST_MATCH_START(1)]}
4122             # ${LAST_MATCH_START}[1] --> @{[mb::_LAST_MATCH_START(1)]}
4123             # ${^LAST_MATCH_START}[1] --> @{[mb::_LAST_MATCH_START(1)]}
4124             elsif (/\G ( \$- | \$LAST_MATCH_START | \$\{LAST_MATCH_START\} | \$\{\^LAST_MATCH_START\} ) \s* (\[) /xmsgc) {
4125 0         0 my $indexing = parse_expr_balanced($2);
4126 0         0 $parsed_as_q .= ($1 . $indexing);
4127 0         0 my $n_th = quotee_of($indexing);
4128 0         0 $parsed_as_qq .= "\@{[mb::_LAST_MATCH_START($n_th)]}";
4129             }
4130              
4131             # @+ --> @{[mb::_LAST_MATCH_END()]}
4132             # @LAST_MATCH_END --> @{[mb::_LAST_MATCH_END()]}
4133             # @{LAST_MATCH_END} --> @{[mb::_LAST_MATCH_END()]}
4134             # @{^LAST_MATCH_END} --> @{[mb::_LAST_MATCH_END()]}
4135             elsif (/\G ( \@\+ | \@LAST_MATCH_END | \@\{LAST_MATCH_END\} | \@\{\^LAST_MATCH_END\} ) /xmsgc) {
4136 0         0 $parsed_as_q .= $1;
4137 0         0 $parsed_as_qq .= '@{[mb::_LAST_MATCH_END()]}';
4138             }
4139              
4140             # $+[1] --> @{[mb::_LAST_MATCH_END(1)]}
4141             # $LAST_MATCH_END[1] --> @{[mb::_LAST_MATCH_END(1)]}
4142             # ${LAST_MATCH_END}[1] --> @{[mb::_LAST_MATCH_END(1)]}
4143             # ${^LAST_MATCH_END}[1] --> @{[mb::_LAST_MATCH_END(1)]}
4144             elsif (/\G ( \$\+ | \$LAST_MATCH_END | \$\{LAST_MATCH_END\} | \$\{\^LAST_MATCH_END\} ) \s* (\[) /xmsgc) {
4145 0         0 my $indexing = parse_expr_balanced($2);
4146 0         0 $parsed_as_q .= ($1 . $indexing);
4147 0         0 my $n_th = quotee_of($indexing);
4148 0         0 $parsed_as_qq .= "\@{[mb::_LAST_MATCH_END($n_th)]}";
4149             }
4150              
4151             # any
4152             elsif (/\G ($x) /xmsgc) {
4153 561222         781914 $parsed_as_q .= escape_q ($1, $closewith);
4154 561222         733829 $parsed_as_qq .= escape_qq($1, $closewith);
4155             }
4156              
4157             # something wrong happened
4158             else {
4159 0         0 die sprintf(<
4160 0         0 $0(@{[__LINE__]}): something wrong happened in script at pos=%s
4161             ------------------------------------------------------------------------------
4162             %s
4163             ------------------------------------------------------------------------------
4164             END
4165             }
4166              
4167             # return qq-like and q-like quotee
4168 561519 50       669569 if (wantarray) {
4169 561519         942795 return ($parsed_as_qq, $parsed_as_q);
4170             }
4171             else {
4172 0         0 return $parsed_as_qq;
4173             }
4174             }
4175              
4176             #---------------------------------------------------------------------
4177             # tr/A-C/1-3/ for US-ASCII codepoint
4178             sub list_all_ASCII_by_hyphen {
4179 5060     5063 0 8440 my @hyphened = @_;
4180 5060         5428 my @list_all = ();
4181 5060         9692 for (my $i=0; $i <= $#hyphened; ) {
4182 6417 100 100     12445 if (
      100        
4183             ($i+1 < $#hyphened) and
4184             ($hyphened[$i+1] eq '-') and
4185             1) {
4186 95 100       156 $hyphened[$i+0] = ($hyphened[$i+0] eq '\\-') ? '-' : $hyphened[$i+0];
4187 95 100       127 $hyphened[$i+2] = ($hyphened[$i+2] eq '\\-') ? '-' : $hyphened[$i+2];
4188 95 50       269 if (0) { }
    50          
    50          
4189 0         0 elsif ($hyphened[$i+0] !~ m/\A [\x00-\x7F] \z/xms) {
4190 0         0 confess sprintf(qq{@{[__FILE__]}: "$hyphened[$i+0]-$hyphened[$i+2]" in tr/// is not US-ASCII});
  0         0  
4191             }
4192             elsif ($hyphened[$i+2] !~ m/\A [\x00-\x7F] \z/xms) {
4193 0         0 confess sprintf(qq{@{[__FILE__]}: "$hyphened[$i+0]-$hyphened[$i+2]" in tr/// is not US-ASCII});
  0         0  
4194             }
4195             elsif ($hyphened[$i+0] gt $hyphened[$i+2]) {
4196 0         0 confess sprintf(qq{@{[__FILE__]}: "$hyphened[$i+0]-$hyphened[$i+2]" in tr/// is not "$hyphened[$i+0]" le "$hyphened[$i+2]"});
  0         0  
4197             }
4198             else {
4199 95         195 push @list_all, map { CORE::chr($_) } (CORE::ord($hyphened[$i+0]) .. CORE::ord($hyphened[$i+2]));
  297         476  
4200 95         152 $i += 3;
4201             }
4202             }
4203             else {
4204 6322 100       8613 if ($hyphened[$i] eq '\\-') {
4205 19         19 push @list_all, '-';
4206             }
4207             else {
4208 6303         7799 push @list_all, $hyphened[$i];
4209             }
4210 6322         8694 $i++;
4211             }
4212             }
4213 5060         9432 return @list_all;
4214             }
4215              
4216             #---------------------------------------------------------------------
4217             # parse tr{here}{here} in balanced blackets
4218             sub parse_tr_like_balanced {
4219 2080     2083 0 3752 my($open_bracket) = @_;
4220 2080   50     9290 my $close_bracket = {qw| ( ) { } [ ] < > |}->{$open_bracket} || die;
4221 2080         4400 my @x = ();
4222 2080         2301 my $nest_bracket = 1;
4223 2080         2051 while (1) {
4224              
4225             # blackets
4226 4160 50       73373 if (/\G (\\ \Q$open_bracket\E) /xmsgc) {
    50          
    50          
    100          
    50          
4227 0         0 push @x, $1;
4228             }
4229             elsif (/\G (\\ \Q$close_bracket\E) /xmsgc) {
4230 0         0 push @x, $1;
4231             }
4232             elsif (/\G (\Q$open_bracket\E) /xmsgc) {
4233 0         0 push @x, $1;
4234 0         0 $nest_bracket++;
4235             }
4236             elsif (/\G (\Q$close_bracket\E) /xmsgc) {
4237 2080 50       3897 if (--$nest_bracket <= 0) {
4238 2080         2745 last;
4239             }
4240 0         0 push @x, $1;
4241             }
4242              
4243             # \-
4244             elsif (/\G (\\ -) /xmsgc) {
4245 0         0 push @x, $1;
4246             }
4247              
4248             else {
4249 2080         4333 push @x, parse_tr_like($close_bracket);
4250             }
4251             }
4252 2080         5885 return join('', $open_bracket, @x, $close_bracket);
4253             }
4254              
4255             #---------------------------------------------------------------------
4256             # parse tr/here/here/ that ends with a character
4257             sub parse_tr_like_endswith {
4258 2238     2241 0 3412 my($endswith) = @_;
4259 2238         2359 my $openwith = $endswith;
4260 2238         2402 my @x = ();
4261 2238         2012 while (1) {
4262 4800 50       18353 if (/\G (\\ \Q$endswith\E) /xmsgc) {
    100          
    100          
4263 0         0 push @x, $1;
4264             }
4265             elsif (/\G (\Q$endswith\E) /xmsgc) {
4266 2238         2663 last;
4267             }
4268              
4269             # \-
4270             elsif (/\G (\\ -) /xmsgc) {
4271 9         15 push @x, $1;
4272             }
4273              
4274             else {
4275 2553         3396 push @x, parse_tr_like($endswith);
4276             }
4277             }
4278 2238         5472 return join('', $openwith, @x, $endswith);
4279             }
4280              
4281             #---------------------------------------------------------------------
4282             # parse tr/here/here/ common routine
4283             sub parse_tr_like {
4284 4633     4636 0 6179 my($closewith) = @_;
4285              
4286 4633 100       26869 if (0) {
    100          
    100          
    100          
    100          
    100          
    100          
    50          
4287             }
4288              
4289             # https://perldoc.perl.org/perlop#Interpolation
4290             # tr///, y///
4291             # No variable interpolation occurs.
4292             # String modifying combinations for case and quoting such as \Q, \U, and \E are not recognized.
4293             # The other escape sequences such as \200 and \t and backslashed characters such as \\ and \- are converted to appropriate literals.
4294             # The character "-" is treated specially and therefore \- is treated as a literal "-".
4295              
4296             # \ddd
4297 0         0 elsif (/\G \\ ( [0-3][0-7][0-7] | [0-7][0-7] | [0-7] ) /xmsgc) {
4298 4         11 return escape_tr(mb::chr(oct $1), $closewith);
4299             }
4300              
4301             # \oddd
4302             elsif (/\G \\o ( [0-3][0-7][0-7] | [0-7][0-7] | [0-7] ) /xmsgc) {
4303 4         9 return escape_tr(mb::chr(oct $1), $closewith);
4304             }
4305              
4306             # \o{...}
4307             elsif (/\G \\o\{ (.*?) \} /xmsgc) {
4308 4         10 return escape_tr(mb::chr(oct $1), $closewith);
4309             }
4310              
4311             # \xhh
4312             elsif (/\G \\x ( [0-9A-Fa-f][0-9A-Fa-f] | [0-9A-Fa-f] ) /xmsgc) {
4313 3         7 return escape_tr(mb::chr(hex $1), $closewith);
4314             }
4315              
4316             # \x{...}
4317             elsif (/\G \\x\{ (.*?) \} /xmsgc) {
4318 3         8 return escape_tr(mb::chr(hex $1), $closewith);
4319             }
4320              
4321             # \cX
4322             elsif (/\G ( \\c [\@ABCDEFGHIJKLMNOPQRSTUVWXYZ\[\\\]^_?] ) /xmsgc) {
4323             return {
4324             '\\c@' => "\c@",
4325             '\\cA' => "\cA",
4326             '\\cB' => "\cB",
4327             '\\cC' => "\cC",
4328             '\\cD' => "\cD",
4329             '\\cE' => "\cE",
4330             '\\cF' => "\cF",
4331             '\\cG' => "\cG",
4332             '\\cH' => "\cH",
4333             '\\cI' => "\cI",
4334             '\\cJ' => "\cJ",
4335             '\\cK' => "\cK",
4336             '\\cL' => "\cL",
4337             '\\cM' => "\cM",
4338             '\\cN' => "\cN",
4339             '\\cO' => "\cO",
4340             '\\cP' => "\cP",
4341             '\\cQ' => "\cQ",
4342             '\\cR' => "\cR",
4343             '\\cS' => "\cS",
4344             '\\cT' => "\cT",
4345             '\\cU' => "\cU",
4346             '\\cV' => "\cV",
4347             '\\cW' => "\cW",
4348             '\\cX' => "\cX",
4349             '\\cY' => "\cY",
4350             '\\cZ' => "\cZ",
4351             '\\c[' => "\c[",
4352             '\\c\\' => CORE::chr(0x1C),
4353             '\\c]' => "\c]",
4354             '\\c^' => "\c^",
4355             '\\c_' => "\c_",
4356             '\\c?' => CORE::chr(0x7F),
4357 9   50     155 }->{$1} || die;
4358             }
4359              
4360             # \\ \a \b \e \f \n \r \t \E \l \L \u \U \Q
4361             elsif (/\G ( \\ ([\\abefnrtElLuUQ]) ) /xmsgc) {
4362             return {
4363             "\x5C\x5C" => "\x5C\x5C",
4364             '\a' => "\a",
4365             '\b' => "\b",
4366             '\e' => "\e",
4367             '\f' => "\f",
4368             '\n' => "\n",
4369             '\r' => "\r",
4370             '\t' => "\t",
4371 16   66     127 }->{$1} || $2;
4372             }
4373              
4374             # any
4375             elsif (/\G ($x) /xmsgc) {
4376 4590         6930 return escape_tr($1, $closewith);
4377             }
4378              
4379             # something wrong happened
4380             else {
4381 0         0 die sprintf(<
4382 0         0 $0(@{[__LINE__]}): something wrong happened in script at pos=%s
4383             ------------------------------------------------------------------------------
4384             %s
4385             ------------------------------------------------------------------------------
4386             END
4387             }
4388             }
4389              
4390             #---------------------------------------------------------------------
4391             # qr/ [A-Z] / for Shift_JIS-like encoding
4392             sub list_all_by_hyphen_sjis_like {
4393 8434     8437 0 11645 my($a, $b) = @_;
4394 8434         21176 my @a = (undef, unpack 'C*', $a);
4395 8434         11107 my @b = (undef, unpack 'C*', $b);
4396              
4397 8434 100       16172 if (0) { }
    50          
4398 0         0 elsif (CORE::length($a) == 1) {
4399 2994 100       5228 if (0) { }
    50          
4400 0         0 elsif (CORE::length($b) == 1) {
4401             return (
4402 434 50 100     2476 (($a[1] <= 0x80) and (0xA0 <= $b[1])) ?
    100          
4403             sprintf(join('', qw( [\x%02x-\x80\xA0-\x%02x] )), $a[1],
4404             $b[1]) :
4405             $a[1]<=$b[1] ? sprintf(join('', qw( [\x%02x-\x%02x] )), $a[1],
4406             $b[1]) : (),
4407             );
4408             }
4409             elsif (CORE::length($b) == 2) {
4410             return (
4411 2560 100       18471 sprintf(join('', qw( \x%02x [\x00-\x%02x] )), $b[1], $b[2]),
    50          
    50          
    100          
4412             0x81 < $b[1] ? sprintf(join('', qw( [\x81-\x%02x] [\x00-\xFF ] )), $b[1]-1 ) : (),
4413             $a[1] <= 0x80 ? sprintf(join('', qw( [\x%02x-\x80\xA0-\xDF] )), $a[1]) :
4414             $a[1] < 0xA0 ? () :
4415             $a[1] <= 0xDF ? sprintf(join('', qw( [\x%02x-\xDF] )), $a[1]) : (),
4416             );
4417             }
4418             }
4419             elsif (CORE::length($a) == 2) {
4420 5440 50       7457 if (0) { }
4421 0         0 elsif (CORE::length($b) == 2) {
4422 5440 100       24010 my $lower_limit = join('|',
4423             $a[1] < 0xFC ? sprintf(join('', qw( [\x%02x-\xFC] [\x00-\xFF ] )), $a[1]+1 ) : (),
4424             sprintf(join('', qw( \x%02x [\x%02x-\xFF] )), $a[1], $a[2]),
4425             );
4426 5440 100       14785 my $upper_limit = join('|',
4427             sprintf(join('', qw( \x%02x [\x00-\x%02x] )), $b[1], $b[2]),
4428             0x81 < $b[1] ? sprintf(join('', qw( [\x81-\x%02x] [\x00-\xFF ] )), $b[1]-1 ) : (),
4429             );
4430 5440         16184 return qq{(?=$lower_limit)(?=$upper_limit)};
4431             }
4432             }
4433              
4434             # over range of codepoint
4435 0         0 confess sprintf(qq{@{[__FILE__]}: codepoint class [$_[0]-$_[1]] is not 1 to 4 octets (%d-%d)}, CORE::length($a), CORE::length($b));
  0         0  
4436             }
4437              
4438             #---------------------------------------------------------------------
4439             # qr/ [A-Z] / for EUC-JP-like encoding
4440             sub list_all_by_hyphen_eucjp_like {
4441 252     255 0 350 my($a, $b) = @_;
4442 252         750 my @a = (undef, unpack 'C*', $a);
4443 252         360 my @b = (undef, unpack 'C*', $b);
4444              
4445 252 100       428 if (0) { }
    50          
4446 0         0 elsif (CORE::length($a) == 1) {
4447 132 100       295 if (0) { }
    50          
4448 0         0 elsif (CORE::length($b) == 1) {
4449             return (
4450 36 50       196 $a[1]<=$b[1] ? sprintf(join('', qw( [\x%02x-\x%02x] )), $a[1],
4451             $b[1]) : (),
4452             );
4453             }
4454             elsif (CORE::length($b) == 2) {
4455             return (
4456 96 100       590 sprintf(join('', qw( \x%02x [\x00-\x%02x] )), $b[1], $b[2]),
4457             0xA1 < $b[1] ? sprintf(join('', qw( [\xA1-\x%02x] [\x00-\xFF ] )), $b[1]-1 ) : (),
4458             sprintf(join('', qw( [\x%02x-\x7F] )), $a[1] ),
4459             );
4460             }
4461             }
4462             elsif (CORE::length($a) == 2) {
4463 120 50       149 if (0) { }
4464 0         0 elsif (CORE::length($b) == 2) {
4465 120 100       500 my $lower_limit = join('|',
4466             $a[1] < 0xFE ? sprintf(join('', qw( [\x%02x-\xFE] [\x00-\xFF ] )), $a[1]+1 ) : (),
4467             sprintf(join('', qw( \x%02x [\x%02x-\xFF] )), $a[1], $a[2]),
4468             );
4469 120 100       317 my $upper_limit = join('|',
4470             sprintf(join('', qw( \x%02x [\x00-\x%02x] )), $b[1], $b[2]),
4471             0xA1 < $b[1] ? sprintf(join('', qw( [\xA1-\x%02x] [\x00-\xFF ] )), $b[1]-1 ) : (),
4472             );
4473 120         338 return qq{(?=$lower_limit)(?=$upper_limit)};
4474             }
4475             }
4476              
4477             # over range of codepoint
4478 0         0 confess sprintf(qq{@{[__FILE__]}: codepoint class [$_[0]-$_[1]] is not 1 to 4 octets (%d-%d)}, CORE::length($a), CORE::length($b));
  0         0  
4479             }
4480              
4481             #---------------------------------------------------------------------
4482             # qr/ [A-Z] / for Big5-like encoding
4483             sub list_all_by_hyphen_big5_like {
4484 252     255 0 359 my($a, $b) = @_;
4485 252         716 my @a = (undef, unpack 'C*', $a);
4486 252         405 my @b = (undef, unpack 'C*', $b);
4487              
4488 252 100       449 if (0) { }
    50          
4489 0         0 elsif (CORE::length($a) == 1) {
4490 132 100       276 if (0) { }
    50          
4491 0         0 elsif (CORE::length($b) == 1) {
4492             return (
4493 36 50       196 $a[1]<=$b[1] ? sprintf(join('', qw( [\x%02x-\x%02x] )), $a[1],
4494             $b[1]) : (),
4495             );
4496             }
4497             elsif (CORE::length($b) == 2) {
4498             return (
4499 96 100       717 sprintf(join('', qw( \x%02x [\x00-\x%02x] )), $b[1], $b[2]),
4500             0x81 < $b[1] ? sprintf(join('', qw( [\x81-\x%02x] [\x00-\xFF ] )), $b[1]-1 ) : (),
4501             sprintf(join('', qw( [\x%02x-\x7F] )), $a[1] ),
4502             );
4503             }
4504             }
4505             elsif (CORE::length($a) == 2) {
4506 120 50       148 if (0) { }
4507 0         0 elsif (CORE::length($b) == 2) {
4508 120 100       502 my $lower_limit = join('|',
4509             $a[1] < 0xFE ? sprintf(join('', qw( [\x%02x-\xFE] [\x00-\xFF ] )), $a[1]+1 ) : (),
4510             sprintf(join('', qw( \x%02x [\x%02x-\xFF] )), $a[1], $a[2]),
4511             );
4512 120 100       327 my $upper_limit = join('|',
4513             sprintf(join('', qw( \x%02x [\x00-\x%02x] )), $b[1], $b[2]),
4514             0x81 < $b[1] ? sprintf(join('', qw( [\x81-\x%02x] [\x00-\xFF ] )), $b[1]-1 ) : (),
4515             );
4516 120         384 return qq{(?=$lower_limit)(?=$upper_limit)};
4517             }
4518             }
4519              
4520             # over range of codepoint
4521 0         0 confess sprintf(qq{@{[__FILE__]}: codepoint class [$_[0]-$_[1]] is not 1 to 4 octets (%d-%d)}, CORE::length($a), CORE::length($b));
  0         0  
4522             }
4523              
4524             #---------------------------------------------------------------------
4525             # qr/ [A-Z] / for GB18030-like encoding
4526             sub list_all_by_hyphen_gb18030_like {
4527 18252     18255 0 25456 my($a, $b) = @_;
4528 18252         49503 my @a = (undef, unpack 'C*', $a);
4529 18252         30023 my @b = (undef, unpack 'C*', $b);
4530              
4531 18252 100       42507 if (0) { }
    100          
    50          
4532 0         0 elsif (CORE::length($a) == 1) {
4533 2652 100       6114 if (0) { }
    100          
    50          
4534 0         0 elsif (CORE::length($b) == 1) {
4535             return (
4536 156 50       706 $a[1]<=$b[1] ? sprintf(join('', qw( [\x%02x-\x%02x] )), $a[1],
4537             $b[1]) : (),
4538             );
4539             }
4540             elsif (CORE::length($b) == 2) {
4541             return (
4542 832 100       5285 sprintf(join('', qw( \x%02x [\x00-\x2F\x3A-\x%02x] )), $b[1], $b[2]),
4543             0x81 < $b[1] ? sprintf(join('', qw( [\x81-\x%02x] [^\x30-\x39 ] )), $b[1]-1 ) : (),
4544             sprintf(join('', qw( [\x%02x-\x7F] )), $a[1] ),
4545             );
4546             }
4547             elsif (CORE::length($b) == 4) {
4548             return (
4549 1664 100       13528 sprintf(join('', qw( \x%02x \x%02x \x%02x [\x30-\x%02x] )), $b[1], $b[2], $b[3], $b[4]),
    100          
    100          
4550             0x81 < $b[3] ? sprintf(join('', qw( \x%02x \x%02x [\x81-\x%02x] [\x30-\x39 ] )), $b[1], $b[2], $b[3]-1 ) : (),
4551             0x30 < $b[2] ? sprintf(join('', qw( \x%02x [\x30-\x%02x] [\x81-\xFE ] [\x30-\x39 ] )), $b[1], $b[2]-1 ) : (),
4552             0x81 < $b[1] ? sprintf(join('', qw( [\x81-\x%02x] [\x30-\x39 ] [\x81-\xFE ] [\x30-\x39 ] )), $b[1]-1 ) : (),
4553             sprintf(join('', qw( [\x81-\xFE ] [^\x30-\x39 ] )), ),
4554             sprintf(join('', qw( [\x%02x-\x7F] )), $a[1] ),
4555             );
4556             }
4557             }
4558             elsif (CORE::length($a) == 2) {
4559 8528 100       15681 if (0) { }
    50          
4560 0         0 elsif (CORE::length($b) == 2) {
4561 1872 100       8706 my $lower_limit = join('|',
4562             $a[1] < 0xFE ? sprintf(join('', qw( [\x%02x-\xFE] [^\x30-\x39 ] )), $a[1]+1 ) : (),
4563             sprintf(join('', qw( \x%02x [\x%02x-\xFF] )), $a[1], $a[2]),
4564             );
4565 1872 100       5741 my $upper_limit = join('|',
4566             sprintf(join('', qw( \x%02x [\x00-\x%02x] )), $b[1], $b[2]),
4567             0x81 < $b[1] ? sprintf(join('', qw( [\x81-\x%02x] [^\x30-\x39 ] )), $b[1]-1 ) : (),
4568             );
4569 1872         5670 return qq{(?=$lower_limit)(?=$upper_limit)};
4570             }
4571             elsif (CORE::length($b) == 4) {
4572             return (
4573 6656 100       60010 sprintf(join('', qw( \x%02x \x%02x \x%02x [\x30-\x%02x] )), $b[1], $b[2], $b[3], $b[4]),
    100          
    100          
    100          
4574             0x81 < $b[3] ? sprintf(join('', qw( \x%02x \x%02x [\x81-\x%02x] [\x30-\x39 ] )), $b[1], $b[2], $b[3]-1 ) : (),
4575             0x30 < $b[2] ? sprintf(join('', qw( \x%02x [\x30-\x%02x] [\x81-\xFE ] [\x30-\x39 ] )), $b[1], $b[2]-1 ) : (),
4576             0x81 < $b[1] ? sprintf(join('', qw( [\x81-\x%02x] [\x30-\x39 ] [\x81-\xFE ] [\x30-\x39 ] )), $b[1]-1 ) : (),
4577             $a[1] < 0xFE ? sprintf(join('', qw( [\x%02x-\xFE] [^\x30-\x39 ] )), $a[1]+1 ) : (),
4578             sprintf(join('', qw( \x%02x [\x%02x-\xFF] )), $a[1], $a[2] ),
4579             );
4580             }
4581             }
4582             elsif (CORE::length($a) == 4) {
4583 7072 50       11166 if (0) { }
4584 0         0 elsif (CORE::length($b) == 4) {
4585 7072 100       46012 my $lower_limit = join('|',
    100          
    100          
4586             $a[1] < 0xFE ? sprintf(join('', qw( [\x%02x-\xFE] [\x30-\x39 ] [\x81-\xFE ] [\x30-\x39 ] )), $a[1]+1 ) : (),
4587             $a[2] < 0x39 ? sprintf(join('', qw( \x%02x [\x%02x-\x39] [\x81-\xFE ] [\x30-\x39 ] )), $a[1], $a[2]+1 ) : (),
4588             $a[3] < 0xFE ? sprintf(join('', qw( \x%02x \x%02x [\x%02x-\xFE] [\x30-\x39 ] )), $a[1], $a[2], $a[3]+1 ) : (),
4589             sprintf(join('', qw( \x%02x \x%02x \x%02x [\x%02x-\x39] )), $a[1], $a[2], $a[3], $a[4]),
4590             );
4591 7072 100       34195 my $upper_limit = join('|',
    100          
    100          
4592             sprintf(join('', qw( \x%02x \x%02x \x%02x [\x30-\x%02x] )), $b[1], $b[2], $b[3], $b[4]),
4593             0x81 < $b[3] ? sprintf(join('', qw( \x%02x \x%02x [\x81-\x%02x] [\x30-\x39 ] )), $b[1], $b[2], $b[3]-1 ) : (),
4594             0x30 < $b[2] ? sprintf(join('', qw( \x%02x [\x30-\x%02x] [\x81-\xFE ] [\x30-\x39 ] )), $b[1], $b[2]-1 ) : (),
4595             0x81 < $b[1] ? sprintf(join('', qw( [\x81-\x%02x] [\x30-\x39 ] [\x81-\xFE ] [\x30-\x39 ] )), $b[1]-1 ) : (),
4596             );
4597 7072         24113 return qq{(?=$lower_limit)(?=$upper_limit)};
4598             }
4599             }
4600              
4601             # over range of codepoint
4602 0         0 confess sprintf(qq{@{[__FILE__]}: codepoint class [$_[0]-$_[1]] is not 1 to 4 octets (%d-%d)}, CORE::length($a), CORE::length($b));
  0         0  
4603             }
4604              
4605             #---------------------------------------------------------------------
4606             # qr/ [A-Z] / for UTF-8-like encoding
4607             sub list_all_by_hyphen_utf8_like {
4608 90126     90129 0 119913 my($a, $b) = @_;
4609 90126         253106 my @a = (undef, unpack 'C*', $a);
4610 90126         144919 my @b = (undef, unpack 'C*', $b);
4611              
4612 90126 100       273029 if (0) { }
    100          
    100          
    50          
4613 0         0 elsif (CORE::length($a) == 1) {
4614 9736 100       23088 if (0) { }
    100          
    100          
    50          
4615 0         0 elsif (CORE::length($b) == 1) {
4616             return (
4617 424 50       1942 $a[1]<=$b[1] ? sprintf(join('', qw( [\x%02x-\x%02x] )), $a[1],
4618             $b[1]) : (),
4619             );
4620             }
4621             elsif (CORE::length($b) == 2) {
4622             return (
4623 816 100       4935 sprintf(join('', qw( \x%02x [\x80-\x%02x] )), $b[1], $b[2]),
4624             0xC2 < $b[1] ? sprintf(join('', qw( [\xC2-\x%02x] [\x80-\xBF ] )), $b[1]-1 ) : (),
4625             sprintf(join('', qw( [\x%02x-\x7F] )), $a[1] ),
4626             );
4627             }
4628             elsif (CORE::length($b) == 3) {
4629             return (
4630 3376 100       25086 sprintf(join('', qw( \x%02x \x%02x [\x80-\x%02x] )), $b[1], $b[2], $b[3]),
    100          
4631             0x80 < $b[2] ? sprintf(join('', qw( \x%02x [\x80-\x%02x] [\x80-\xBF ] )), $b[1], $b[2]-1 ) : (),
4632             0xE0 < $b[1] ? sprintf(join('', qw( [\xE0-\x%02x] [\x80-\xBF ] [\x80-\xBF ] )), $b[1]-1 ) : (),
4633             sprintf(join('', qw( [\xC2-\xDF ] [\x80-\xBF ] )), ),
4634             sprintf(join('', qw( [\x%02x-\x7F] )), $a[1] ),
4635             );
4636             }
4637             elsif (CORE::length($b) == 4) {
4638             return (
4639 5120 100       44169 sprintf(join('', qw( \x%02x \x%02x \x%02x [\x80-\x%02x] )), $b[1], $b[2], $b[3], $b[4]),
    100          
    100          
4640             0x80 < $b[3] ? sprintf(join('', qw( \x%02x \x%02x [\x80-\x%02x] [\x80-\xBF ] )), $b[1], $b[2], $b[3]-1 ) : (),
4641             0x80 < $b[2] ? sprintf(join('', qw( \x%02x [\x80-\x%02x] [\x80-\xBF ] [\x80-\xBF ] )), $b[1], $b[2]-1 ) : (),
4642             0xF0 < $b[1] ? sprintf(join('', qw( [\xF0-\x%02x] [\x80-\xBF ] [\x80-\xBF ] [\x80-\xBF ] )), $b[1]-1 ) : (),
4643             sprintf(join('', qw( [\xE0-\xEF ] [\x80-\xBF ] [\x80-\xBF ] )), ),
4644             sprintf(join('', qw( [\xC2-\xDF ] [\x80-\xBF ] )), ),
4645             sprintf(join('', qw( [\x%02x-\x7F] )), $a[1] ),
4646             );
4647             }
4648             }
4649             elsif (CORE::length($a) == 2) {
4650 12692 100       30635 if (0) { }
    100          
    50          
4651 0         0 elsif (CORE::length($b) == 2) {
4652 868 100       3954 my $lower_limit = join('|',
4653             $a[1] < 0xDF ? sprintf(join('', qw( [\x%02x-\xDF] [\x80-\xBF ] )), $a[1]+1 ) : (),
4654             sprintf(join('', qw( \x%02x [\x%02x-\xBF] )), $a[1], $a[2]),
4655             );
4656 868 100       2295 my $upper_limit = join('|',
4657             sprintf(join('', qw( \x%02x [\x80-\x%02x] )), $b[1], $b[2]),
4658             0xC2 < $b[1] ? sprintf(join('', qw( [\xC2-\x%02x] [\x80-\xBF ] )), $b[1]-1 ) : (),
4659             );
4660 868         2649 return qq{(?=$lower_limit)(?=$upper_limit)};
4661             }
4662             elsif (CORE::length($b) == 3) {
4663             return (
4664 6448 100       54718 sprintf(join('', qw( \x%02x \x%02x [\x80-\x%02x] )), $b[1], $b[2], $b[3] ),
    100          
    100          
4665             0x80 < $b[2] ? sprintf(join('', qw( \x%02x [\x80-\x%02x] [\x80-\xBF ] )), $b[1], $b[2]-1 ) : (),
4666             0xE0 < $b[1] ? sprintf(join('', qw( [\xE0-\x%02x] [\x80-\xBF ] [\x80-\xBF ] )), $b[1]-1 ) : (),
4667             $a[1] < 0xDF ? sprintf(join('', qw( [\x%02x-\xDF] [\x80-\xBF ] )), $a[1]+1 ) : (),
4668             sprintf(join('', qw( \x%02x [\x%02x-\xBF] )), $a[1], $a[2] ),
4669             );
4670             }
4671             elsif (CORE::length($b) == 4) {
4672             return (
4673 5376 100       52179 sprintf(join('', qw( \x%02x \x%02x \x%02x [\x80-\x%02x] )), $b[1], $b[2], $b[3], $b[4]),
    100          
    100          
    100          
4674             0x80 < $b[3] ? sprintf(join('', qw( \x%02x \x%02x [\x80-\x%02x] [\x80-\xBF ] )), $b[1], $b[2], $b[3]-1 ) : (),
4675             0x80 < $b[2] ? sprintf(join('', qw( \x%02x [\x80-\x%02x] [\x80-\xBF ] [\x80-\xBF ] )), $b[1], $b[2]-1 ) : (),
4676             0xF0 < $b[1] ? sprintf(join('', qw( [\xF0-\x%02x] [\x80-\xBF ] [\x80-\xBF ] [\x80-\xBF ] )), $b[1]-1 ) : (),
4677             sprintf(join('', qw( [\xE0-\xEF ] [\x80-\xBF ] [\x80-\xBF ] )), ),
4678             $a[1] < 0xDF ? sprintf(join('', qw( [\x%02x-\xDF] [\x80-\xBF ] )), $a[1]+1 ) : (),
4679             sprintf(join('', qw( \x%02x [\x%02x-\xBF] )), $a[1], $a[2] ),
4680             );
4681             }
4682             }
4683             elsif (CORE::length($a) == 3) {
4684 27378 100       47263 if (0) { }
    50          
4685 0         0 elsif (CORE::length($b) == 3) {
4686 19442 100       113765 my $lower_limit = join('|',
    100          
4687             $a[1] < 0xEF ? sprintf(join('', qw( [\x%02x-\xEF] [\x80-\xBF ] [\x80-\xBF ] )), $a[1]+1 ) : (),
4688             $a[2] < 0xBF ? sprintf(join('', qw( \x%02x [\x%02x-\xBF] [\x80-\xBF ] )), $a[1], $a[2]+1 ) : (),
4689             sprintf(join('', qw( \x%02x \x%02x [\x%02x-\xBF] )), $a[1], $a[2], $a[3]),
4690             );
4691 19442 100       78618 my $upper_limit = join('|',
    100          
4692             sprintf(join('', qw( \x%02x \x%02x [\x80-\x%02x] )), $b[1], $b[2], $b[3]),
4693             0x80 < $b[2] ? sprintf(join('', qw( \x%02x [\x80-\x%02x] [\x80-\xBF ] )), $b[1], $b[2]-1 ) : (),
4694             0xE0 < $b[1] ? sprintf(join('', qw( [\xE0-\x%02x] [\x80-\xBF ] [\x80-\xBF ] )), $b[1]-1 ) : (),
4695             );
4696 19442         62025 return qq{(?=$lower_limit)(?=$upper_limit)};
4697             }
4698             elsif (CORE::length($b) == 4) {
4699             return (
4700 7936 100       81645 sprintf(join('', qw( \x%02x \x%02x \x%02x [\x80-\x%02x] )), $b[1], $b[2], $b[3], $b[4]),
    100          
    100          
    100          
    100          
4701             0x80 < $b[3] ? sprintf(join('', qw( \x%02x \x%02x [\x80-\x%02x] [\x80-\xBF ] )), $b[1], $b[2], $b[3]-1 ) : (),
4702             0x80 < $b[2] ? sprintf(join('', qw( \x%02x [\x80-\x%02x] [\x80-\xBF ] [\x80-\xBF ] )), $b[1], $b[2]-1 ) : (),
4703             0xF0 < $b[1] ? sprintf(join('', qw( [\xF0-\x%02x] [\x80-\xBF ] [\x80-\xBF ] [\x80-\xBF ] )), $b[1]-1 ) : (),
4704             $a[1] < 0xEF ? sprintf(join('', qw( [\x%02x-\xEF] [\x80-\xBF ] [\x80-\xBF ] )), $a[1]+1 ) : (),
4705             $a[2] < 0xBF ? sprintf(join('', qw( \x%02x [\x%02x-\xBF] [\x80-\xBF ] )), $a[1], $a[2]+1 ) : (),
4706             sprintf(join('', qw( \x%02x \x%02x [\x%02x-\xBF] )), $a[1], $a[2], $a[3] ),
4707             );
4708             }
4709             }
4710             elsif (CORE::length($a) == 4) {
4711 40320 50       70731 if (0) { }
4712 0         0 elsif (CORE::length($b) == 4) {
4713 40320 100       273157 my $lower_limit = join('|',
    100          
    100          
4714             $a[1] < 0xF4 ? sprintf(join('', qw( [\x%02x-\xF4] [\x80-\xBF ] [\x80-\xBF ] [\x80-\xBF ] )), $a[1]+1 ) : (),
4715             $a[2] < 0xBF ? sprintf(join('', qw( \x%02x [\x%02x-\xBF] [\x80-\xBF ] [\x80-\xBF ] )), $a[1], $a[2]+1 ) : (),
4716             $a[3] < 0xBF ? sprintf(join('', qw( \x%02x \x%02x [\x%02x-\xBF] [\x80-\xBF ] )), $a[1], $a[2], $a[3]+1 ) : (),
4717             sprintf(join('', qw( \x%02x \x%02x \x%02x [\x%02x-\xBF] )), $a[1], $a[2], $a[3], $a[4]),
4718             );
4719 40320 100       189894 my $upper_limit = join('|',
    100          
    100          
4720             sprintf(join('', qw( \x%02x \x%02x \x%02x [\x80-\x%02x] )), $b[1], $b[2], $b[3], $b[4]),
4721             0x80 < $b[3] ? sprintf(join('', qw( \x%02x \x%02x [\x80-\x%02x] [\x80-\xBF ] )), $b[1], $b[2], $b[3]-1 ) : (),
4722             0x80 < $b[2] ? sprintf(join('', qw( \x%02x [\x80-\x%02x] [\x80-\xBF ] [\x80-\xBF ] )), $b[1], $b[2]-1 ) : (),
4723             0xF0 < $b[1] ? sprintf(join('', qw( [\xF0-\x%02x] [\x80-\xBF ] [\x80-\xBF ] [\x80-\xBF ] )), $b[1]-1 ) : (),
4724             );
4725 40320         135174 return qq{(?=$lower_limit)(?=$upper_limit)};
4726             }
4727             }
4728              
4729             # over range of codepoint
4730 0         0 confess sprintf(qq{@{[__FILE__]}: codepoint class [$_[0]-$_[1]] is not 1 to 4 octets (%d-%d)}, CORE::length($a), CORE::length($b));
  0         0  
4731             }
4732             #---------------------------------------------------------------------
4733             # qr// for UTF-8 codepoint string at runtime (used by $mb{qr/.../})
4734             # ported from UTF8::R2::qr; uses mb::chr and list_all_by_hyphen_utf8_like
4735             sub _r2_qr ($) {
4736              
4737             # Local STRING form of the one-codepoint matcher, used throughout this
4738             # subroutine in place of the file-scoped qr// object $x.
4739             #
4740             # The file-scoped $x is a qr// object ($x = qr/(?>$over_ascii|...)/). On
4741             # perl 5.005_03 a qr// object loses its body when interpolated into
4742             # another pattern ("$qr" becomes "(?-xism:)" with the contents dropped),
4743             # so an embedded $x would silently degrade to a match-anything sub-pattern
4744             # in BOTH the parsing regexes below and the generated output. That makes
4745             # negative codepoint classes, hyphen-range boundaries, quantifier shortfall
4746             # and "." (without /s) over-match on old perl. A plain string interpolates
4747             # losslessly on every perl from 5.005_03 onward, so build one here.
4748             #
4749             # It is kept STRICT (ASCII tail is [\x00-\x7F], not [\x00-\xFF]): leniency
4750             # is deliberately not introduced. $over_ascii is itself a plain string.
4751             # The file-scoped qr// $x is left untouched for mb's transpile path.
4752 45     47   55 my $x = "(?>$over_ascii|[\\x00-\\x7F])";
4753              
4754             # Work on a stringified, writable copy of the argument. The caller passes
4755             # either a qr// object (from $mb{qr/.../}) or a plain string. On perl
4756             # 5.005_03 a destructive s/// applied directly to a qr// argument (or to a
4757             # read-only literal) fails ("Modification of a read-only value") or yields
4758             # an empty body, so copy "$_[0]" into a lexical first.
4759 45         51 my $source = "$_[0]";
4760              
4761 45         59 my $modifiers = '';
4762 45 50       174 if (my($m) = $source =~ /\A \( \? \^? (.*?) : /x) {
4763 45         42 $modifiers = $m;
4764 45         47 $modifiers =~ s/-.*//;
4765             }
4766              
4767 45         46 my @after = ();
4768 45         1269 while ($source =~ s! \A (
4769             (?> \[ (?: \[:[^:]+?:\] | \\x\{[0123456789ABCDEFabcdef]+\} | \\c[\x00-\xFF] | (?>\\$x) | $x )+? \] ) |
4770             \\x\{[0123456789ABCDEFabcdef]+\} | \\c[\x00-\xFF] | (?>\\$x) | $x
4771             ) !!x) {
4772 336         385 my $before = $1;
4773              
4774             # [^...] or [...]
4775 336 100       2434 if (my($negative, $class) = $before =~ /\A \[ (\^?) ((?>\\$x|$x)+?) \] \z/x) {
    100          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    100          
    50          
    100          
    50          
    100          
    100          
    50          
4776 12         304 my @classmate = $class =~ /\G (?: \[:.+?:\] | \\x\{[0123456789ABCDEFabcdef]+\} | (?>\\$x) | $x ) /xg;
4777 12         16 my @sbcs = ();
4778 12         10 my @xbcs = ();
4779              
4780 12         21 for (my $i=0; $i <= $#classmate; ) {
4781 15         22 my $classmate = $classmate[$i];
4782              
4783             # hyphen of [A-Z] or [^A-Z]
4784 15 100 66     40 if (($i < $#classmate) and ($classmate[$i+1] eq '-')) {
4785 13 50       18 my $a = ($classmate[$i+0] =~ /\A \\x \{ ([0123456789ABCDEFabcdef]+) \} \z/x) ? mb::chr(hex $1) : $classmate[$i+0];
4786 13 50       18 my $b = ($classmate[$i+2] =~ /\A \\x \{ ([0123456789ABCDEFabcdef]+) \} \z/x) ? mb::chr(hex $1) : $classmate[$i+2];
4787 13         18 push @xbcs, list_all_by_hyphen_utf8_like($a, $b);
4788 13         25 $i += 3;
4789             }
4790              
4791             # any "one"
4792             else {
4793              
4794             # \x{UTF8hex}
4795 2 50       32 if ($classmate =~ /\A \\x \{ ([0123456789ABCDEFabcdef]+) \} \z/x) {
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    100          
    50          
    50          
    50          
    50          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
4796 0         0 push @xbcs, mb::chr(hex $1);
4797             }
4798              
4799             # \any
4800 0         0 elsif ($classmate eq '\D' ) { push @xbcs, "(?:(?![$bare_d])$x)" }
4801 0         0 elsif ($classmate eq '\H' ) { push @xbcs, "(?:(?![$bare_h])$x)" }
4802             # elsif ($classmate eq '\N' ) { push @xbcs, "(?:(?!\\n)$x)" } # \N in a character class must be a named character: \N{...} in regex
4803             # elsif ($classmate eq '\R' ) { push @xbcs, "(?>\\r\\n|[$bare_v])" } # Unrecognized escape \R in character class passed through in regex
4804 0         0 elsif ($classmate eq '\S' ) { push @xbcs, "(?:(?![$bare_s])$x)" }
4805 0         0 elsif ($classmate eq '\V' ) { push @xbcs, "(?:(?![$bare_v])$x)" }
4806 0         0 elsif ($classmate eq '\W' ) { push @xbcs, "(?:(?![$bare_w])$x)" }
4807 0         0 elsif ($classmate eq '\b' ) { push @sbcs, $bare_backspace }
4808 0         0 elsif ($classmate eq '\d' ) { push @sbcs, $bare_d }
4809 0         0 elsif ($classmate eq '\h' ) { push @sbcs, $bare_h }
4810 0         0 elsif ($classmate eq '\s' ) { push @sbcs, $bare_s }
4811 0         0 elsif ($classmate eq '\v' ) { push @sbcs, $bare_v }
4812 0         0 elsif ($classmate eq '\w' ) { push @sbcs, $bare_w }
4813              
4814             # [:POSIX:]
4815 0         0 elsif ($classmate eq '[:alnum:]' ) { push @sbcs, '\x30-\x39\x41-\x5A\x61-\x7A'; }
4816 1         2 elsif ($classmate eq '[:alpha:]' ) { push @sbcs, '\x41-\x5A\x61-\x7A'; }
4817 0         0 elsif ($classmate eq '[:ascii:]' ) { push @sbcs, '\x00-\x7F'; }
4818 0         0 elsif ($classmate eq '[:blank:]' ) { push @sbcs, '\x09\x20'; }
4819 0         0 elsif ($classmate eq '[:cntrl:]' ) { push @sbcs, '\x00-\x1F\x7F'; }
4820 1         2 elsif ($classmate eq '[:digit:]' ) { push @sbcs, '\x30-\x39'; }
4821 0         0 elsif ($classmate eq '[:graph:]' ) { push @sbcs, '\x21-\x7F'; }
4822 0         0 elsif ($classmate eq '[:lower:]' ) { push @sbcs, '\x61-\x7A'; } # /i modifier requires 'a' to 'z' literally
4823 0         0 elsif ($classmate eq '[:print:]' ) { push @sbcs, '\x20-\x7F'; }
4824 0         0 elsif ($classmate eq '[:punct:]' ) { push @sbcs, '\x21-\x2F\x3A-\x3F\x40\x5B-\x5F\x60\x7B-\x7E'; }
4825 0         0 elsif ($classmate eq '[:space:]' ) { push @sbcs, '\s\x0B'; } # "\s" and vertical tab ("\cK")
4826 0         0 elsif ($classmate eq '[:upper:]' ) { push @sbcs, '\x41-\x5A'; } # /i modifier requires 'A' to 'Z' literally
4827 0         0 elsif ($classmate eq '[:word:]' ) { push @sbcs, '\x30-\x39\x41-\x5A\x5F\x61-\x7A'; }
4828 0         0 elsif ($classmate eq '[:xdigit:]' ) { push @sbcs, '\x30-\x39\x41-\x46\x61-\x66'; }
4829              
4830             # [:^POSIX:]
4831 0         0 elsif ($classmate eq '[:^alnum:]' ) { push @xbcs, "(?:(?![\\x30-\\x39\\x41-\\x5A\\x61-\\x7A])$x)"; }
4832 0         0 elsif ($classmate eq '[:^alpha:]' ) { push @xbcs, "(?:(?![\\x41-\\x5A\\x61-\\x7A])$x)"; }
4833 0         0 elsif ($classmate eq '[:^ascii:]' ) { push @xbcs, "(?:(?![\\x00-\\x7F])$x)"; }
4834 0         0 elsif ($classmate eq '[:^blank:]' ) { push @xbcs, "(?:(?![\\x09\\x20])$x)"; }
4835 0         0 elsif ($classmate eq '[:^cntrl:]' ) { push @xbcs, "(?:(?![\\x00-\\x1F\\x7F])$x)"; }
4836 0         0 elsif ($classmate eq '[:^digit:]' ) { push @xbcs, "(?:(?![\\x30-\\x39])$x)"; }
4837 0         0 elsif ($classmate eq '[:^graph:]' ) { push @xbcs, "(?:(?![\\x21-\\x7F])$x)"; }
4838 0         0 elsif ($classmate eq '[:^lower:]' ) { push @xbcs, "(?:(?![\\x61-\\x7A])$x)"; } # /i modifier requires 'a' to 'z' literally
4839 0         0 elsif ($classmate eq '[:^print:]' ) { push @xbcs, "(?:(?![\\x20-\\x7F])$x)"; }
4840 0         0 elsif ($classmate eq '[:^punct:]' ) { push @xbcs, "(?:(?![\\x21-\\x2F\\x3A-\\x3F\\x40\\x5B-\\x5F\\x60\\x7B-\\x7E])$x)"; }
4841 0         0 elsif ($classmate eq '[:^space:]' ) { push @xbcs, "(?:(?![\\s\\x0B])$x)"; } # "\s" and vertical tab ("\cK")
4842 0         0 elsif ($classmate eq '[:^upper:]' ) { push @xbcs, "(?:(?![\\x41-\\x5A])$x)"; } # /i modifier requires 'A' to 'Z' literally
4843 0         0 elsif ($classmate eq '[:^word:]' ) { push @xbcs, "(?:(?![\\x30-\\x39\\x41-\\x5A\\x5F\\x61-\\x7A])$x)"; }
4844 0         0 elsif ($classmate eq '[:^xdigit:]') { push @xbcs, "(?:(?![\\x30-\\x39\\x41-\\x46\\x61-\\x66])$x)"; }
4845              
4846             # other all
4847 0         0 elsif (CORE::length($classmate)==1) { push @sbcs, $classmate }
4848 0         0 else { push @xbcs, $classmate }
4849 2         5 $i += 1;
4850             }
4851             }
4852              
4853             # [^...]
4854 12 100       25 if ($negative eq q[^]) {
    50          
4855 2 0 33     27 push @after,
    50 33        
    50 0        
4856             ( @sbcs and @xbcs) ? '(?:(?!' . join('|', @xbcs, '['.join('', @sbcs).']') . ")$x)" :
4857             (!@sbcs and @xbcs) ? '(?:(?!' . join('|', @xbcs ) . ")$x)" :
4858             ( @sbcs and !@xbcs) ? '(?:(?!' . '['.join('', @sbcs).']' . ")$x)" :
4859             '';
4860             }
4861              
4862             # [...] on Perl 5.006
4863             elsif ($] =~ /\A5\.006/) {
4864 0 0 0     0 push @after,
    0 0        
    0 0        
4865             ( @sbcs and @xbcs) ? '(?:' . join('|', @xbcs, '['.join('', @sbcs).']') . ')' :
4866             (!@sbcs and @xbcs) ? '(?:' . join('|', @xbcs ) . ')' :
4867             ( @sbcs and !@xbcs) ? '['.join('', @sbcs).']' :
4868             '';
4869             }
4870              
4871             # [...]
4872             else {
4873 10 50 66     101 push @after,
    100 66        
    50 33        
4874             ( @sbcs and @xbcs) ? '(?:(?=' . join('|', @xbcs, '['.join('', @sbcs).']') . ")$x)" :
4875             (!@sbcs and @xbcs) ? '(?:(?=' . join('|', @xbcs ) . ")$x)" :
4876             ( @sbcs and !@xbcs) ? '['.join('', @sbcs).']' :
4877             '';
4878             }
4879             }
4880              
4881             # \any or /./
4882 4 100       20 elsif ($before eq '.' ) { push @after, ($modifiers =~ /s/) ? $x : "(?:(?!\\n)$x)" }
4883 0         0 elsif ($before eq '\B') { push @after, "(?:(?
4884 0         0 elsif ($before eq '\D') { push @after, "(?:(?![$bare_d])$x)" }
4885 0         0 elsif ($before eq '\H') { push @after, "(?:(?![$bare_h])$x)" }
4886 0         0 elsif ($before eq '\N') { push @after, "(?:(?!\\n)$x)" }
4887 0         0 elsif ($before eq '\R') { push @after, "(?>\\r\\n|[$bare_v])" }
4888 0         0 elsif ($before eq '\S') { push @after, "(?:(?![$bare_s])$x)" }
4889 0         0 elsif ($before eq '\V') { push @after, "(?:(?![$bare_v])$x)" }
4890 0         0 elsif ($before eq '\W') { push @after, "(?:(?![$bare_w])$x)" }
4891 0         0 elsif ($before eq '\b') { push @after, "(?:(?
4892 1         5 elsif ($before eq '\d') { push @after, "[$bare_d]" }
4893 0         0 elsif ($before eq '\h') { push @after, "[$bare_h]" }
4894 1         5 elsif ($before eq '\s') { push @after, "[$bare_s]" }
4895 0         0 elsif ($before eq '\v') { push @after, "[$bare_v]" }
4896 1         4 elsif ($before eq '\w') { push @after, "[$bare_w]" }
4897              
4898             # quantifiers ? + * {n} {n,} {n,m}
4899             elsif ($before =~ /\A[?+*{]\z/) {
4900 52 50       126 if (0) { }
    50          
    100          
    100          
4901 0         0 elsif ($after[-1] =~ /\A \\c [\x00-\xFF] \z/x) { } # \c) \c} \c] \cX
4902             elsif ($after[-1] =~ /\A \\ [\x00-\xFF] \z/x) { } # \) \} \] \" \0 \1 \D \E \F \G \H \K \L \N \Q \R \S \U \V \W \\ \a \d \e \f \h \l \n \r \s \t \u \v \w
4903             elsif ($after[-1] =~ /\A [\x00-\xFF] \z/x) { } # (a) a{1} [a] a . \012 \x12 \o{12} \g{1}
4904             elsif ($after[-1] =~ / [\x00-\xFF] [)}\]] \z/x) { } # (any) any{1} [any]
4905             else { # XBCS
4906 4         5 $after[-1] = '(?:' . $after[-1] . ')';
4907             }
4908 52         206 push @after, $before;
4909             }
4910              
4911             # \x{UTF8hex}
4912             elsif ($before =~ /\A \\x \{ ([0123456789ABCDEFabcdef]+) \} \z/x) {
4913 0         0 push @after, mb::chr(hex $1);
4914             }
4915              
4916             # else
4917             else {
4918 265         996 push @after, $before;
4919             }
4920             }
4921              
4922 45         64 my $after = join '', @after;
4923              
4924             # Return a plain regular-expression STRING, not a qr// object.
4925             #
4926             # On perl 5.005_03 a qr// object, when interpolated into another pattern
4927             # (for example m<\G$mb{qr/.../}>g or s<$mb{qr/.../}><...> or even a
4928             # second =~ // after stringification) loses its body: "$qr" becomes
4929             # "(?-xism:)" with the contents dropped, so the pattern then matches
4930             # anything. A plain string interpolates losslessly on every perl from
4931             # 5.005_03 onward. The (?modifiers:...) wrapper preserves the i/m/s/x
4932             # flags that were present on the original qr/.../ token.
4933 45 100       56 if ($modifiers ne '') {
4934 2         126 return "(?$modifiers:$after)";
4935             }
4936             else {
4937 43         2657 return "(?:$after)";
4938             }
4939             }
4940              
4941             #---------------------------------------------------------------------
4942             # mb::qr() - functional form of the runtime UTF-8 codepoint regex builder.
4943             # This is the same engine as $mb{qr/.../} (the tie FETCH), exposed as a
4944             # named subroutine for UTF8::R2 source compatibility:
4945             # $_ =~ mb::qr(qr/.../) is equivalent to $_ =~ $mb{qr/.../}
4946             # It returns a plain regular-expression string (see _r2_qr above for why a
4947             # string and not a qr// object, which matters on perl 5.005_03).
4948             sub mb::qr ($) {
4949 18     18 0 42 return _r2_qr($_[0]);
4950             }
4951              
4952             #---------------------------------------------------------------------
4953             # parse codepoint class
4954             sub parse_re_codepoint_class {
4955 118274     118274 0 147477 my($codepoint_class) = @_;
4956 118274         132330 my @sbcs = ();
4957 118274         102470 my @xbcs = (); # "xbcs" means DBCS, TBCS, QBCS, ...
4958              
4959             # get members from class
4960 118274         109207 my @classmate = ();
4961 118274         282469 while ($codepoint_class !~ /\G \z /xmsgc) {
4962 353332 50       1928484 if (0) { }
    50          
    100          
    100          
    50          
4963 0         0 elsif ($codepoint_class =~ /\G\\o\{([01234567]+)\}/xmsgc) {
4964 0         0 push @classmate, mb::chr(oct $1);
4965             }
4966             elsif ($codepoint_class =~ /\G\\x\{([0123456789ABCDEFabcdef]+)\}/xmsgc) {
4967 0         0 push @classmate, mb::chr(hex $1);
4968             }
4969             elsif ($codepoint_class =~ /\G(\[:.+?:\])/xmsgc) {
4970 100         311 push @classmate, $1;
4971             }
4972             elsif ($codepoint_class =~ /\G((?>\\$x))/xmsgc) {
4973 562         2017 push @classmate, $1;
4974             }
4975             elsif ($codepoint_class =~ /\G($x)/xmsgc) {
4976 352670         747570 push @classmate, $1;
4977             }
4978             else {
4979 0         0 confess qq{@{[__FILE__]}: codepoint_class=($codepoint_class), classmate=(@classmate)};
  0         0  
4980             }
4981             }
4982              
4983             # get regular expression for MBCS codepoint class
4984 118274         258293 for (my $i=0; $i <= $#classmate; $i++) {
4985 118726         162645 my $classmate = $classmate[$i];
4986              
4987             # hyphen of [A-Z] or [^A-Z]
4988 118726 100 100     432951 if (($i < $#classmate) and ($classmate[$i+1] eq '-')) {
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    50          
4989 117303         122464 my $a = $classmate[$i];
4990 117303         140658 my $b = $classmate[$i+2];
4991 117303 100       474086 if (0) { }
    100          
    100          
    100          
    50          
4992 0         0 elsif ($script_encoding =~ /\A (?: sjis ) \z/xms) {
4993 8434         16122 push @xbcs, list_all_by_hyphen_sjis_like ($a, $b);
4994             }
4995             elsif ($script_encoding =~ /\A (?: eucjp ) \z/xms) {
4996 252         454 push @xbcs, list_all_by_hyphen_eucjp_like ($a, $b);
4997             }
4998             elsif ($script_encoding =~ /\A (?: gbk | uhc | big5 | big5hkscs ) \z/xms) {
4999 252         497 push @xbcs, list_all_by_hyphen_big5_like ($a, $b);
5000             }
5001             elsif ($script_encoding =~ /\A (?: gb18030 ) \z/xms) {
5002 18252         35215 push @xbcs, list_all_by_hyphen_gb18030_like($a, $b);
5003             }
5004             elsif ($script_encoding =~ /\A (?: rfc2279 | utf8 | wtf8 ) \z/xms) {
5005 90113         161493 push @xbcs, list_all_by_hyphen_utf8_like ($a, $b);
5006             }
5007             else {
5008 0         0 push @sbcs, "$a-$b";
5009             }
5010 117303         278611 $i += 2;
5011             }
5012              
5013             # classic perl codepoint class shortcuts
5014 34         126 elsif ($classmate eq '\\D') { push @xbcs, "(?:(?![$bare_d])$x)"; }
5015 10         34 elsif ($classmate eq '\\H') { push @xbcs, "(?:(?![$bare_h])$x)"; }
5016             # elsif ($classmate eq '\\N') { push @xbcs, "(?:(?!\\n)$x)"; } # \N in a codepoint class must be a named character: \N{...} in regex
5017             # elsif ($classmate eq '\\R') { push @xbcs, "(?>\\r\\n|[$bare_v])"; } # Unrecognized escape \R in codepoint class passed through in regex
5018 19         62 elsif ($classmate eq '\\S') { push @xbcs, "(?:(?![$bare_s])$x)"; }
5019 16         56 elsif ($classmate eq '\\V') { push @xbcs, "(?:(?![$bare_v])$x)"; }
5020 193         688 elsif ($classmate eq '\\W') { push @xbcs, "(?:(?![$bare_w])$x)"; }
5021 6         19 elsif ($classmate eq '\\b') { push @sbcs, $bare_backspace; }
5022 34         74 elsif ($classmate eq '\\d') { push @sbcs, $bare_d; }
5023 10         23 elsif ($classmate eq '\\h') { push @sbcs, $bare_h; }
5024 19         39 elsif ($classmate eq '\\s') { push @sbcs, $bare_s; }
5025 16         36 elsif ($classmate eq '\\v') { push @sbcs, $bare_v; }
5026 193         436 elsif ($classmate eq '\\w') { push @sbcs, $bare_w; }
5027              
5028             # [:POSIX:]
5029 19         33 elsif ($classmate eq '[:alnum:]' ) { push @sbcs, '\x30-\x39\x41-\x5A\x61-\x7A'; }
5030 3         13 elsif ($classmate eq '[:alpha:]' ) { push @sbcs, '\x41-\x5A\x61-\x7A'; }
5031 3         10 elsif ($classmate eq '[:ascii:]' ) { push @sbcs, '\x00-\x7F'; }
5032 3         8 elsif ($classmate eq '[:blank:]' ) { push @sbcs, '\x09\x20'; }
5033 3         9 elsif ($classmate eq '[:cntrl:]' ) { push @sbcs, '\x00-\x1F\x7F'; }
5034 3         11 elsif ($classmate eq '[:digit:]' ) { push @sbcs, '\x30-\x39'; }
5035 3         11 elsif ($classmate eq '[:graph:]' ) { push @sbcs, '\x21-\x7F'; }
5036 3         8 elsif ($classmate eq '[:lower:]' ) { push @sbcs, 'abcdefghijklmnopqrstuvwxyz'; } # /i modifier requires 'a' to 'z' literally
5037 3         10 elsif ($classmate eq '[:print:]' ) { push @sbcs, '\x20-\x7F'; }
5038 3         8 elsif ($classmate eq '[:punct:]' ) { push @sbcs, '\x21-\x2F\x3A-\x3F\x40\x5B-\x5F\x60\x7B-\x7E'; }
5039 3         6 elsif ($classmate eq '[:space:]' ) { push @sbcs, '\s\x0B'; } # "\s" and vertical tab ("\cK")
5040 3         9 elsif ($classmate eq '[:upper:]' ) { push @sbcs, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; } # /i modifier requires 'A' to 'Z' literally
5041 3         9 elsif ($classmate eq '[:word:]' ) { push @sbcs, '\x30-\x39\x41-\x5A\x5F\x61-\x7A'; }
5042 3         11 elsif ($classmate eq '[:xdigit:]') { push @sbcs, '\x30-\x39\x41-\x46\x61-\x66'; }
5043              
5044             # [:^POSIX:]
5045 3         12 elsif ($classmate eq '[:^alnum:]' ) { push @xbcs, "(?:(?![\\x30-\\x39\\x41-\\x5A\\x61-\\x7A])$x)"; }
5046 3         15 elsif ($classmate eq '[:^alpha:]' ) { push @xbcs, "(?:(?![\\x41-\\x5A\\x61-\\x7A])$x)"; }
5047 3         12 elsif ($classmate eq '[:^ascii:]' ) { push @xbcs, "(?:(?![\\x00-\\x7F])$x)"; }
5048 3         14 elsif ($classmate eq '[:^blank:]' ) { push @xbcs, "(?:(?![\\x09\\x20])$x)"; }
5049 3         12 elsif ($classmate eq '[:^cntrl:]' ) { push @xbcs, "(?:(?![\\x00-\\x1F\\x7F])$x)"; }
5050 3         15 elsif ($classmate eq '[:^digit:]' ) { push @xbcs, "(?:(?![\\x30-\\x39])$x)"; }
5051 3         12 elsif ($classmate eq '[:^graph:]' ) { push @xbcs, "(?:(?![\\x21-\\x7F])$x)"; }
5052 3         11 elsif ($classmate eq '[:^lower:]' ) { push @xbcs, "(?:(?![abcdefghijklmnopqrstuvwxyz])$x)"; } # /i modifier requires 'a' to 'z' literally
5053 3         57 elsif ($classmate eq '[:^print:]' ) { push @xbcs, "(?:(?![\\x20-\\x7F])$x)"; }
5054 3         16 elsif ($classmate eq '[:^punct:]' ) { push @xbcs, "(?:(?![\\x21-\\x2F\\x3A-\\x3F\\x40\\x5B-\\x5F\\x60\\x7B-\\x7E])$x)"; }
5055 3         12 elsif ($classmate eq '[:^space:]' ) { push @xbcs, "(?:(?![\\s\\x0B])$x)"; } # "\s" and vertical tab ("\cK")
5056 3         12 elsif ($classmate eq '[:^upper:]' ) { push @xbcs, "(?:(?![ABCDEFGHIJKLMNOPQRSTUVWXYZ])$x)"; } # /i modifier requires 'A' to 'Z' literally
5057 3         17 elsif ($classmate eq '[:^word:]' ) { push @xbcs, "(?:(?![\\x30-\\x39\\x41-\\x5A\\x5F\\x61-\\x7A])$x)"; }
5058 3         15 elsif ($classmate eq '[:^xdigit:]') { push @xbcs, "(?:(?![\\x30-\\x39\\x41-\\x46\\x61-\\x66])$x)"; }
5059              
5060             # \any
5061             elsif ($classmate =~ /\G (\\) ($x) /xmsgc) {
5062 12 50       26 if (CORE::length($2) == 1) {
5063 12         37 push @sbcs, ($1 . $2);
5064             }
5065             else {
5066 0         0 push @xbcs, '(?:' . $1 . escape_to_hex($2, ']') . ')';
5067             }
5068             }
5069              
5070             # any
5071             elsif ($classmate =~ /\G ($x) /xmsgc) {
5072 761 100       1000 if (CORE::length($1) == 1) {
5073 417         750 push @sbcs, $1;
5074             }
5075             else {
5076 344         500 push @xbcs, '(?:' . escape_to_hex($1, ']') . ')';
5077             }
5078             }
5079              
5080             # something wrong happened
5081             else {
5082 0         0 die sprintf(<
5083 0         0 $0(@{[__LINE__]}): something wrong happened in script at pos=%s
5084             ------------------------------------------------------------------------------
5085             %s
5086             ------------------------------------------------------------------------------
5087             END
5088             }
5089             }
5090              
5091             # return codepoint class
5092 118274 50 100     461687 my $parsed =
    100 66        
    100 33        
5093             ( @sbcs and @xbcs) ? join('|', @xbcs, '['.join('',@sbcs).']') :
5094             (!@sbcs and @xbcs) ? join('|', @xbcs ) :
5095             ( @sbcs and !@xbcs) ? '['.join('',@sbcs).']' :
5096             die;
5097 118274         22181178 return $parsed;
5098             }
5099              
5100             #---------------------------------------------------------------------
5101             # parse qr'regexp' as q-like
5102             sub parse_re_as_q_endswith {
5103 948     948 0 2017 my($operator, $endswith) = @_;
5104 948         1187 my $parsed = $endswith;
5105 948         910 while (1) {
5106 1956 100       8854 if (/\G (\Q$endswith\E) /xmsgc) {
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    50          
    50          
    50          
    50          
    50          
    50          
5107 948         1124 $parsed .= $1;
5108 948         876 last;
5109             }
5110              
5111             # get codepoint class
5112             elsif (/\G \[ /xmsgc) {
5113 566         683 my $classmate = '';
5114 566         678 while (1) {
5115 1766 100       5805 if (/\G \] /xmsgc) {
    100          
    100          
    50          
5116 566         685 last;
5117             }
5118             elsif (/\G (\[:\^[a-z]*:\]) /xmsgc) {
5119 28         40 $classmate .= $1;
5120             }
5121             elsif (/\G (\[:[a-z]*:\]) /xmsgc) {
5122 44         61 $classmate .= $1;
5123             }
5124             elsif (/\G ($x) /xmsgc) {
5125 1128         1569 $classmate .= $1;
5126             }
5127              
5128             # something wrong happened
5129             else {
5130 0         0 die sprintf(<
5131 0         0 $0(@{[__LINE__]}): something wrong happened in script at pos=%s
5132             ------------------------------------------------------------------------------
5133             %s
5134             ------------------------------------------------------------------------------
5135             END
5136             }
5137             }
5138              
5139             # parse codepoint class
5140 566         974 $parsed .= mb::_cc($classmate);
5141             }
5142              
5143             # /./ or \any
5144 2         5 elsif (/\G \. /xmsgc) { $parsed .= "(?:$over_ascii|.)"; } # after $over_ascii, /s modifier wants "." (not [\x00-\xFF])
5145 2         7 elsif (/\G \\B /xmsgc) { $parsed .= "(?:(?
5146 12         35 elsif (/\G \\D /xmsgc) { $parsed .= "(?:(?![$bare_d])$x)"; }
5147 4         13 elsif (/\G \\H /xmsgc) { $parsed .= "(?:(?![$bare_h])$x)"; }
5148 2         6 elsif (/\G \\N /xmsgc) { $parsed .= "(?:(?!\\n)$x)"; }
5149 2         4 elsif (/\G \\R /xmsgc) { $parsed .= "(?>\\r\\n|[$bare_v])"; }
5150 7         21 elsif (/\G \\S /xmsgc) { $parsed .= "(?:(?![$bare_s])$x)"; }
5151 6         16 elsif (/\G \\V /xmsgc) { $parsed .= "(?:(?![$bare_v])$x)"; }
5152 65         154 elsif (/\G \\W /xmsgc) { $parsed .= "(?:(?![$bare_w])$x)"; }
5153 2         4 elsif (/\G \\b /xmsgc) { $parsed .= "(?:(?
5154 12         26 elsif (/\G \\d /xmsgc) { $parsed .= "[$bare_d]"; }
5155 4         8 elsif (/\G \\h /xmsgc) { $parsed .= "[$bare_h]"; }
5156 7         11 elsif (/\G \\s /xmsgc) { $parsed .= "[$bare_s]"; }
5157 6         10 elsif (/\G \\v /xmsgc) { $parsed .= "[$bare_v]"; }
5158 65         103 elsif (/\G \\w /xmsgc) { $parsed .= "[$bare_w]"; }
5159              
5160             # \o{...}
5161             elsif (/\G \\o\{ (.*?) \} /xmsgc) {
5162 0         0 $parsed .= '(?:';
5163 0         0 $parsed .= escape_to_hex(mb::chr(oct $1), $endswith);
5164 0         0 $parsed .= ')';
5165             }
5166              
5167             # \x{...}
5168             elsif (/\G \\x\{ (.*?) \} /xmsgc) {
5169 0         0 $parsed .= '(?:';
5170 0         0 $parsed .= escape_to_hex(mb::chr(hex $1), $endswith);
5171 0         0 $parsed .= ')';
5172             }
5173              
5174             # \0... octal escape
5175             elsif (/\G (\\ 0[1-7]*) /xmsgc) {
5176 0         0 $parsed .= $1;
5177             }
5178              
5179             # \100...\x377 octal escape
5180             elsif (/\G (\\ [1-3][0-7][0-7]) /xmsgc) {
5181 0         0 $parsed .= $1;
5182             }
5183              
5184             # \1...\99, ... n-th previously captured string (decimal)
5185             elsif (/\G (\\) ([1-9][0-9]*) /xmsgc) {
5186 0         0 $parsed .= $1;
5187 0 0       0 if ($operator eq 's') {
5188 0         0 $parsed .= ($2 + 1);
5189             }
5190             else {
5191 0         0 $parsed .= $2;
5192             }
5193             }
5194              
5195             # any
5196             elsif (/\G ($x) /xmsgc) {
5197 244 100       394 if (CORE::length($1) == 1) {
5198 99         133 $parsed .= $1;
5199             }
5200             else {
5201 145         138 $parsed .= '(?:';
5202 145         200 $parsed .= escape_to_hex($1, $endswith);
5203 145         196 $parsed .= ')';
5204             }
5205             }
5206              
5207             # something wrong happened
5208             else {
5209 0         0 die sprintf(<
5210 0         0 $0(@{[__LINE__]}): something wrong happened in script at pos=%s
5211             ------------------------------------------------------------------------------
5212             %s
5213             ------------------------------------------------------------------------------
5214             END
5215             }
5216             }
5217 948         1366 return $parsed;
5218             }
5219              
5220             #---------------------------------------------------------------------
5221             # parse qr{regexp} in balanced blackets
5222             sub parse_re_balanced {
5223 564     564 0 1012 my($operator, $open_bracket) = @_;
5224 564   50     1987 my $close_bracket = {qw| ( ) { } [ ] < > |}->{$open_bracket} || die;
5225 564         883 my $parsed = $open_bracket;
5226 564         641 my $nest_bracket = 1;
5227 564         533 my $nest_escape = 0;
5228 564         499 while (1) {
5229 1133 50       6387 if (/\G (\Q$open_bracket\E) /xmsgc) {
    100          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
5230 0         0 $parsed .= $1;
5231 0         0 $nest_bracket++;
5232             }
5233             elsif (/\G (\Q$close_bracket\E) /xmsgc) {
5234 564 50       715 if (--$nest_bracket <= 0) {
5235 564         670 $parsed .= ('>)]}' x $nest_escape);
5236 564         603 $parsed .= $1;
5237 564         600 last;
5238             }
5239             else {
5240 0         0 $parsed .= $1;
5241             }
5242             }
5243              
5244             # \L\u --> \u\L
5245             elsif (/\G \\L \\u /xmsgc) {
5246 0         0 $parsed .= '@{[mb::ucfirst(qq<';
5247 0         0 $parsed .= '@{[mb::lc(qq<';
5248 0         0 $nest_escape++;
5249 0         0 $nest_escape++;
5250             }
5251              
5252             # \U\l --> \l\U
5253             elsif (/\G \\U \\l /xmsgc) {
5254 0         0 $parsed .= '@{[mb::lcfirst(qq<';
5255 0         0 $parsed .= '@{[mb::uc(qq<';
5256 0         0 $nest_escape++;
5257 0         0 $nest_escape++;
5258             }
5259              
5260             # \L
5261             elsif (/\G \\L /xmsgc) {
5262 0         0 $parsed .= '@{[mb::lc(qq<';
5263 0         0 $nest_escape++;
5264             }
5265              
5266             # \U
5267             elsif (/\G \\U /xmsgc) {
5268 0         0 $parsed .= '@{[mb::uc(qq<';
5269 0         0 $nest_escape++;
5270             }
5271              
5272             # \l
5273             elsif (/\G \\l /xmsgc) {
5274 0         0 $parsed .= '@{[mb::lcfirst(qq<';
5275 0         0 $nest_escape++;
5276             }
5277              
5278             # \u
5279             elsif (/\G \\u /xmsgc) {
5280 0         0 $parsed .= '@{[mb::ucfirst(qq<';
5281 0         0 $nest_escape++;
5282             }
5283              
5284             # \Q
5285             elsif (/\G \\Q /xmsgc) {
5286 0         0 $parsed .= '@{[quotemeta(qq<';
5287 0         0 $nest_escape++;
5288             }
5289              
5290             # \E
5291             elsif (/\G \\E /xmsgc) {
5292 0         0 $parsed .= ('>)]}' x $nest_escape);
5293 0         0 $nest_escape = 0;
5294             }
5295              
5296             else {
5297 569         844 $parsed .= parse_re($operator, $open_bracket);
5298             }
5299             }
5300 564         766 return $parsed;
5301             }
5302              
5303             #---------------------------------------------------------------------
5304             # parse qr/regexp/ that ends with a character
5305             sub parse_re_endswith {
5306 120538     120538 0 334386 my($operator, $endswith) = @_;
5307 120538         168193 my $parsed = $endswith;
5308 120538         147295 my $nest_escape = 0;
5309 120538         138427 while (1) {
5310 242474 100       1018595 if (/\G (\Q$endswith\E) /xmsgc) {
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
5311 120538         149918 $parsed .= ('>)]}' x $nest_escape);
5312 120538         159351 $parsed .= $1;
5313 120538         122521 last;
5314             }
5315              
5316             # \L\u --> \u\L
5317             elsif (/\G \\L \\u /xmsgc) {
5318 0         0 $parsed .= '@{[mb::ucfirst(qq<';
5319 0         0 $parsed .= '@{[mb::lc(qq<';
5320 0         0 $nest_escape++;
5321 0         0 $nest_escape++;
5322             }
5323              
5324             # \U\l --> \l\U
5325             elsif (/\G \\U \\l /xmsgc) {
5326 0         0 $parsed .= '@{[mb::lcfirst(qq<';
5327 0         0 $parsed .= '@{[mb::uc(qq<';
5328 0         0 $nest_escape++;
5329 0         0 $nest_escape++;
5330             }
5331              
5332             # \L
5333             elsif (/\G \\L /xmsgc) {
5334 0         0 $parsed .= '@{[mb::lc(qq<';
5335 0         0 $nest_escape++;
5336             }
5337              
5338             # \U
5339             elsif (/\G \\U /xmsgc) {
5340 0         0 $parsed .= '@{[mb::uc(qq<';
5341 0         0 $nest_escape++;
5342             }
5343              
5344             # \l
5345             elsif (/\G \\l /xmsgc) {
5346 0         0 $parsed .= '@{[mb::lcfirst(qq<';
5347 0         0 $nest_escape++;
5348             }
5349              
5350             # \u
5351             elsif (/\G \\u /xmsgc) {
5352 0         0 $parsed .= '@{[mb::ucfirst(qq<';
5353 0         0 $nest_escape++;
5354             }
5355              
5356             # \Q
5357             elsif (/\G \\Q /xmsgc) {
5358 0         0 $parsed .= '@{[quotemeta(qq<';
5359 0         0 $nest_escape++;
5360             }
5361              
5362             # \E
5363             elsif (/\G \\E /xmsgc) {
5364 0         0 $parsed .= ('>)]}' x $nest_escape);
5365 0         0 $nest_escape = 0;
5366             }
5367              
5368             else {
5369 121936         201863 $parsed .= parse_re($operator, $endswith);
5370             }
5371             }
5372 120538         176225 return $parsed;
5373             }
5374              
5375             #---------------------------------------------------------------------
5376             # parse qr/regexp/ common routine
5377             sub parse_re {
5378 122505     122505 0 155630 my($operator, $closewith) = @_;
5379 122505         134083 my $parsed = '';
5380              
5381             # codepoint class
5382 122505 100       263131 if (/\G \[ /xmsgc) {
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    50          
    50          
    50          
    50          
    100          
    100          
    50          
    50          
    100          
    50          
    50          
    50          
    50          
    50          
    50          
5383 118842         127934 my $classmate = '';
5384 118842         106151 while (1) {
5385 532673 100       1946801 if (/\G \] /xmsgc) {
    100          
    100          
    100          
    50          
5386 118842         140078 last;
5387             }
5388             elsif (/\G (\\) /xmsgc) {
5389 510         839 $classmate .= "\\$1";
5390             }
5391             elsif (/\G (\[:\^[a-z]*:\]) /xmsgc) {
5392 98         152 $classmate .= $1;
5393             }
5394             elsif (/\G (\[:[a-z]*:\]) /xmsgc) {
5395 114         193 $classmate .= $1;
5396             }
5397             elsif (/\G ($x) /xmsgc) {
5398 413109         483751 $classmate .= escape_qq($1, ']');
5399             }
5400              
5401             # something wrong happened
5402             else {
5403 0         0 die sprintf(<
5404 0         0 $0(@{[__LINE__]}): something wrong happened in script at pos=%s
5405             ------------------------------------------------------------------------------
5406             %s
5407             ------------------------------------------------------------------------------
5408             END
5409             }
5410             }
5411              
5412             # quote by (?: ... ) to avoid syntax error: Can't coerce array into hash at ...
5413             #
5414             # [ABC]{3} --> @{[mb::_cc(qq[ABC])]}{3} # makes: Can't coerce array into hash at ...
5415             # [ABC]{3} --> (?:@{[mb::_cc(qq[ABC])]}){3} # ok
5416              
5417 118842         200126 $parsed .= "(?:\@{[mb::_cc(qq[$classmate])]})";
5418             }
5419              
5420             # /./ or \any
5421 21         33 elsif (/\G \. /xmsgc) { $parsed .= '(?:@{[@mb::_dot]})'; }
5422 7         12 elsif (/\G \\B /xmsgc) { $parsed .= '(?:@{[@mb::_B]})'; }
5423 18         38 elsif (/\G \\D /xmsgc) { $parsed .= '(?:@{[@mb::_D]})'; }
5424 10         15 elsif (/\G \\H /xmsgc) { $parsed .= '(?:@{[@mb::_H]})'; }
5425 8         12 elsif (/\G \\N /xmsgc) { $parsed .= '(?:@{[@mb::_N]})'; }
5426 12         18 elsif (/\G \\R /xmsgc) { $parsed .= '(?:@{[@mb::_R]})'; }
5427 14         24 elsif (/\G \\S /xmsgc) { $parsed .= '(?:@{[@mb::_S]})'; }
5428 12         19 elsif (/\G \\V /xmsgc) { $parsed .= '(?:@{[@mb::_V]})'; }
5429 71         155 elsif (/\G \\W /xmsgc) { $parsed .= '(?:@{[@mb::_W]})'; }
5430 7         8 elsif (/\G \\b /xmsgc) { $parsed .= '(?:@{[@mb::_b]})'; }
5431 17         36 elsif (/\G \\d /xmsgc) { $parsed .= '(?:@{[@mb::_d]})'; }
5432 10         16 elsif (/\G \\h /xmsgc) { $parsed .= '(?:@{[@mb::_h]})'; }
5433 18         27 elsif (/\G \\s /xmsgc) { $parsed .= '(?:@{[@mb::_s]})'; }
5434 14         38 elsif (/\G \\v /xmsgc) { $parsed .= '(?:@{[@mb::_v]})'; }
5435 70         159 elsif (/\G \\w /xmsgc) { $parsed .= '(?:@{[@mb::_w]})'; }
5436              
5437             # \o{...}
5438             elsif (/\G \\o\{ (.*?) \} /xmsgc) {
5439 0         0 $parsed .= '(?:';
5440 0         0 $parsed .= escape_to_hex(mb::chr(oct $1), $closewith);
5441 0         0 $parsed .= ')';
5442             }
5443              
5444             # \x{...}
5445             elsif (/\G \\x\{ (.*?) \} /xmsgc) {
5446 0         0 $parsed .= '(?:';
5447 0         0 $parsed .= escape_to_hex(mb::chr(hex $1), $closewith);
5448 0         0 $parsed .= ')';
5449             }
5450              
5451             # \0... octal escape
5452             elsif (/\G (\\ 0[1-7]*) /xmsgc) {
5453 0         0 $parsed .= $1;
5454             }
5455              
5456             # \100...\x377 octal escape
5457             elsif (/\G (\\ [1-3][0-7][0-7]) /xmsgc) {
5458 0         0 $parsed .= $1;
5459             }
5460              
5461             # \1...\99, ... n-th previously captured string (decimal)
5462             elsif (/\G (\\) ([1-9][0-9]*) /xmsgc) {
5463 24         31 $parsed .= $1;
5464 24 50       33 if ($operator eq 's') {
5465 0         0 $parsed .= ($2 + 1);
5466             }
5467             else {
5468 24         28 $parsed .= $2;
5469             }
5470             }
5471              
5472             # \any
5473             elsif (/\G (\\) ($x) /xmsgc) {
5474 8 50       15 if (CORE::length($2) == 1) {
5475 8         17 $parsed .= ($1 . $2);
5476             }
5477             else {
5478 0         0 $parsed .= ('(?:' . $1 . escape_qq($2, $closewith) . ')');
5479             }
5480             }
5481              
5482             # $` --> @{[mb::_clustered_codepoint(mb::_PREMATCH())]}
5483             # ${`} --> @{[mb::_clustered_codepoint(mb::_PREMATCH())]}
5484             # $PREMATCH --> @{[mb::_clustered_codepoint(mb::_PREMATCH())]}
5485             # ${PREMATCH} --> @{[mb::_clustered_codepoint(mb::_PREMATCH())]}
5486             # ${^PREMATCH} --> @{[mb::_clustered_codepoint(mb::_PREMATCH())]}
5487             elsif (/\G (?: \$` | \$\{`\} | \$PREMATCH | \$\{PREMATCH\} | \$\{\^PREMATCH\} ) /xmsgc) {
5488 0         0 $parsed .= '@{[mb::_clustered_codepoint(mb::_PREMATCH())]}';
5489             }
5490              
5491             # $& --> @{[mb::_clustered_codepoint(mb::_MATCH())]}
5492             # ${&} --> @{[mb::_clustered_codepoint(mb::_MATCH())]}
5493             # $MATCH --> @{[mb::_clustered_codepoint(mb::_MATCH())]}
5494             # ${MATCH} --> @{[mb::_clustered_codepoint(mb::_MATCH())]}
5495             # ${^MATCH} --> @{[mb::_clustered_codepoint(mb::_MATCH())]}
5496             elsif (/\G (?: \$& | \$\{&\} | \$MATCH | \$\{MATCH\} | \$\{\^MATCH\} ) /xmsgc) {
5497 0         0 $parsed .= '@{[mb::_clustered_codepoint(mb::_MATCH())]}';
5498             }
5499              
5500             # $1 --> @{[mb::_clustered_codepoint(mb::_CAPTURE(1))]}
5501             # $2 --> @{[mb::_clustered_codepoint(mb::_CAPTURE(2))]}
5502             # $3 --> @{[mb::_clustered_codepoint(mb::_CAPTURE(3))]}
5503             elsif (/\G \$ ([1-9][0-9]*) /xmsgc) {
5504 24         81 $parsed .= "\@{[mb::_clustered_codepoint(mb::_CAPTURE($1))]}";
5505             }
5506              
5507             # ${^CAPTURE}[0] --> @{[mb::_clustered_codepoint(mb::_CAPTURE(1))]}
5508             # ${^CAPTURE}[1] --> @{[mb::_clustered_codepoint(mb::_CAPTURE(2))]}
5509             # ${^CAPTURE}[2] --> @{[mb::_clustered_codepoint(mb::_CAPTURE(3))]}
5510             elsif (/\G \$\{\^CAPTURE\} \s* (\[) /xmsgc) {
5511 0         0 my $n_th = quotee_of(parse_expr_balanced($1));
5512 0         0 $parsed .= "\@{[mb::_clustered_codepoint(mb::_CAPTURE($n_th+1))]}";
5513             }
5514              
5515             # @- --> @{[mb::_LAST_MATCH_START()]}
5516             # @LAST_MATCH_START --> @{[mb::_LAST_MATCH_START()]}
5517             # @{LAST_MATCH_START} --> @{[mb::_LAST_MATCH_START()]}
5518             # @{^LAST_MATCH_START} --> @{[mb::_LAST_MATCH_START()]}
5519             elsif (/\G (?: \@- | \@LAST_MATCH_START | \@\{LAST_MATCH_START\} | \@\{\^LAST_MATCH_START\} ) /xmsgc) {
5520 0         0 $parsed .= '@{[mb::_LAST_MATCH_START()]}';
5521             }
5522              
5523             # $-[1] --> @{[mb::_LAST_MATCH_START(1)]}
5524             # $LAST_MATCH_START[1] --> @{[mb::_LAST_MATCH_START(1)]}
5525             # ${LAST_MATCH_START}[1] --> @{[mb::_LAST_MATCH_START(1)]}
5526             # ${^LAST_MATCH_START}[1] --> @{[mb::_LAST_MATCH_START(1)]}
5527             elsif (/\G (?: \$- | \$LAST_MATCH_START | \$\{LAST_MATCH_START\} | \$\{\^LAST_MATCH_START\} ) \s* (\[) /xmsgc) {
5528 0         0 my $n_th = quotee_of(parse_expr_balanced($1));
5529 0         0 $parsed .= "\@{[mb::_LAST_MATCH_START($n_th)]}";
5530             }
5531              
5532             # @+ --> @{[mb::_LAST_MATCH_END()]}
5533             # @LAST_MATCH_END --> @{[mb::_LAST_MATCH_END()]}
5534             # @{LAST_MATCH_END} --> @{[mb::_LAST_MATCH_END()]}
5535             # @{^LAST_MATCH_END} --> @{[mb::_LAST_MATCH_END()]}
5536             elsif (/\G (?: \@\+ | \@LAST_MATCH_END | \@\{LAST_MATCH_END\} | \@\{\^LAST_MATCH_END\} ) /xmsgc) {
5537 0         0 $parsed .= '@{[mb::_LAST_MATCH_END()]}';
5538             }
5539              
5540             # $+[1] --> @{[mb::_LAST_MATCH_END(1)]}
5541             # $LAST_MATCH_END[1] --> @{[mb::_LAST_MATCH_END(1)]}
5542             # ${LAST_MATCH_END}[1] --> @{[mb::_LAST_MATCH_END(1)]}
5543             # ${^LAST_MATCH_END}[1] --> @{[mb::_LAST_MATCH_END(1)]}
5544             elsif (/\G (?: \$\+ | \$LAST_MATCH_END | \$\{LAST_MATCH_END\} | \$\{\^LAST_MATCH_END\} ) \s* (\[) /xmsgc) {
5545 0         0 my $n_th = quotee_of(parse_expr_balanced($1));
5546 0         0 $parsed .= "\@{[mb::_LAST_MATCH_END($n_th)]}";
5547             }
5548              
5549             # any
5550             elsif (/\G ($x) /xmsgc) {
5551 3298 100       4654 if (CORE::length($1) == 1) {
5552 2735         3748 $parsed .= $1;
5553             }
5554             else {
5555 563         730 $parsed .= ('(?:' . escape_qq($1, $closewith) . ')');
5556             }
5557             }
5558              
5559             # something wrong happened
5560             else {
5561 0         0 die sprintf(<
5562 0         0 $0(@{[__LINE__]}): something wrong happened in script at pos=%s
5563             ------------------------------------------------------------------------------
5564             %s
5565             ------------------------------------------------------------------------------
5566             END
5567             }
5568 122505         223572 return $parsed;
5569             }
5570              
5571             #---------------------------------------------------------------------
5572             # parse modifiers of qr///here
5573             sub parse_re_modifier {
5574 122050     122050 0 119166 my $modifier_i = '';
5575 122050         108277 my $modifier_not_cegir = '';
5576 122050         131877 my $modifier_cegr = '';
5577 122050         107285 while (1) {
5578 122351 50       273431 if (/\G [adlpu] /xmsgc) {
    100          
    100          
    100          
5579             # drop modifiers
5580             }
5581             elsif (/\G ([i]) /xmsgc) {
5582 100         142 $modifier_i .= $1;
5583             }
5584             elsif (/\G ([cegr]) /xmsgc) {
5585 36         69 $modifier_cegr .= $1;
5586             }
5587             elsif (/\G ([a-z]) /xmsgc) {
5588 165         200 $modifier_not_cegir .= $1;
5589             }
5590             else {
5591 122050         107107 last;
5592             }
5593             }
5594 122050         240417 return ($modifier_i, $modifier_not_cegir, $modifier_cegr);
5595             }
5596              
5597             #---------------------------------------------------------------------
5598             # parse modifiers of tr///here
5599             sub parse_tr_modifier {
5600 2159     2159 0 2492 my $modifier_not_r = '';
5601 2159         2303 my $modifier_r = '';
5602 2159         2233 while (1) {
5603 2247 50       4959 if (/\G ([r]) /xmsgc) {
    100          
5604 0         0 $modifier_r .= $1;
5605             }
5606             elsif (/\G ([a-z]) /xmsgc) {
5607 88         100 $modifier_not_r .= $1;
5608             }
5609             else {
5610 2159         2232 last;
5611             }
5612             }
5613 2159         4501 return ($modifier_not_r, $modifier_r);
5614             }
5615              
5616             #---------------------------------------------------------------------
5617             # makes codepoint class from string
5618             sub codepoint_tr {
5619 2131     2131 0 3591 my $searchlist = quotee_of($_[0]);
5620              
5621 2131         2484 my @sbcs = ();
5622 2131         2187 my @xbcs = (); # "xbcs" means DBCS, TBCS, QBCS, ...
5623 2131         5561 while ($searchlist !~ /\G \z /xmsgc) {
5624              
5625             # \-
5626 3267 100       16109 if ($searchlist =~ /\G (\\-) /xmsgc) {
    100          
    100          
    50          
5627 9         18 push @sbcs, $1;
5628             }
5629              
5630             # -
5631             elsif ($searchlist =~ /\G (-) /xmsgc) {
5632 31         61 push @sbcs, $1;
5633             }
5634              
5635             # any qq escapee
5636             elsif ($searchlist =~ /\G ([$escapee_in_qq_like]) /xmsgc) {
5637 1036         2770 push @sbcs, "\\$1";
5638             }
5639              
5640             # any
5641             elsif ($searchlist =~ /\G ($x) /xmsgc) {
5642 2191 100       3943 if (CORE::length($1) == 1) {
5643 1160         3706 push @sbcs, $1;
5644             }
5645             else {
5646 1031         1503 push @xbcs, escape_qq($1, '\\');
5647             }
5648             }
5649              
5650             # something wrong happened
5651             else {
5652 0         0 die sprintf(<
5653 0         0 $0(@{[__LINE__]}): something wrong happened in script at pos=%s
5654             ------------------------------------------------------------------------------
5655             %s
5656             ------------------------------------------------------------------------------
5657             END
5658             }
5659             }
5660              
5661             # return codepoint class
5662             return
5663 2131 50 100     17510 ( @sbcs and @xbcs) ? join('|', @xbcs, '['.join('',@sbcs).']') :
    100 66        
    100 33        
5664             (!@sbcs and @xbcs) ? join('|', @xbcs ) :
5665             ( @sbcs and !@xbcs) ? '['.join('',@sbcs).']' :
5666             die;
5667             }
5668              
5669             #---------------------------------------------------------------------
5670             # get quotee from quoted "quotee"
5671             sub quotee_of {
5672 3266 50   3266 0 4866 if (CORE::length($_[0]) >= 2) {
5673 3266         6015 return CORE::substr($_[0],1,-1);
5674             }
5675             else {
5676 0         0 die;
5677             }
5678             }
5679              
5680             #---------------------------------------------------------------------
5681             # escape q/string/ as q-like quote
5682             sub escape_q {
5683 570097     570097 0 826398 my($codepoint, $endswith) = @_;
5684 570097 50       1745521 if ($codepoint =~ /\A ([^\x00-\x7F]) (\Q$endswith\E) \z/xms) {
    100          
5685 0         0 return "$1\\$2";
5686             }
5687             elsif ($codepoint =~ /\A ([^\x00-\x7F]) ($escapee_in_q__like) \z/xms) {
5688 1992         5704 return "$1\\$2";
5689             }
5690             else {
5691 568105         858597 return $codepoint;
5692             }
5693             }
5694              
5695             #---------------------------------------------------------------------
5696             # escape qq/string/ as qq-like quote
5697             sub escape_qq {
5698 976273     976273 0 1298006 my($codepoint, $endswith) = @_;
5699              
5700             # m@`@ --> m`\x60`
5701             # qr@`@ --> qr`\x60`
5702             # s@`@``@ --> s`\x60`\x60\x60`
5703             # m:`: --> m`\x60`
5704             # qr:`: --> qr`\x60`
5705             # s:`:``: --> s`\x60`\x60\x60`
5706 976273 50       8462961 if ($codepoint eq '`') {
    100          
    100          
5707 0         0 return '\\x60';
5708             }
5709             elsif ($codepoint =~ /\A ([^\x00-\x7F]) (\Q$endswith\E) \z/xms) {
5710 1032         3044 return "$1\\$2";
5711             }
5712             elsif ($codepoint =~ /\A ([^\x00-\x7F]) ([$escapee_in_qq_like]) \z/xms) {
5713 18843         64658 return "$1\\$2";
5714             }
5715             else {
5716 956398         1488870 return $codepoint;
5717             }
5718             }
5719              
5720             #---------------------------------------------------------------------
5721             # escape tr/here/here/ as tr-like quote
5722             sub escape_tr {
5723 4608     4608 0 7273 my($codepoint, $endswith) = @_;
5724 4608 50       90533 if ($codepoint =~ /\A (\Q$endswith\E) \z/xms) {
    50          
    100          
5725 0         0 return "\\$1";
5726             }
5727             elsif ($codepoint =~ /\A ([^\x00-\x7F]) (\Q$endswith\E) \z/xms) {
5728 0         0 return "$1\\$2";
5729             }
5730             elsif ($codepoint =~ /\A ([^\x00-\x7F]) ($escapee_in_q__like) \z/xms) {
5731 1988         7214 return "$1\\$2";
5732             }
5733             else {
5734 2620         7262 return $codepoint;
5735             }
5736             }
5737              
5738             #---------------------------------------------------------------------
5739             # escape qq/string/ or qr/regexp/ to hex
5740             sub escape_to_hex {
5741 490     490 0 737 my($codepoint, $endswith) = @_;
5742 490 100       2615 if ($codepoint =~ /\A ([^\x00-\x7F]) (\Q$endswith\E) \z/xms) {
    100          
5743 28         92 return sprintf('\x%02X\x%02X', CORE::ord($1), CORE::ord($2));
5744             }
5745              
5746             # in qr'...', $escapee_in_qq_like is right, not $escapee_in_q__like
5747             elsif ($codepoint =~ /\A ([^\x00-\x7F]) ([$escapee_in_qq_like]) \z/xms) {
5748 82         394 return sprintf('\x%02X\x%02X', CORE::ord($1), CORE::ord($2));
5749             }
5750             else {
5751 380         921 return $codepoint;
5752             }
5753             }
5754              
5755             #---------------------------------------------------------------------
5756             # compatible routines for %mb of UTF8::R2 module
5757             #
5758             # tie my %mb, 'mb';
5759             # $result = $_ =~ $mb{qr/$utf8regex/imsxo}
5760             # $result = $_ =~ m<\G$mb{qr/$utf8regex/imsxo}>gc
5761             # $result = $_ =~ s<$mb{qr/before/imsxo}>egr
5762              
5763 124     124   426 sub TIEHASH { bless { }, $_[0] }
5764 27     27   585 sub FETCH { _r2_qr($_[1]) }
5765       0     sub STORE { }
5766       123     sub FIRSTKEY { }
5767       0     sub NEXTKEY { }
5768       0     sub EXISTS { }
5769       0     sub DELETE { }
5770       0     sub CLEAR { }
5771       0     sub UNTIE { }
5772       0     sub DESTROY { }
5773       0     sub SCALAR { }
5774              
5775             #---------------------------------------------------------------------
5776              
5777             1;
5778              
5779             __END__