File Coverage

Char/Ekoi8r.pm
Criterion Covered Total %
statement 83 3062 2.7
branch 4 2670 0.1
condition 1 373 0.2
subroutine 36 125 28.8
pod 7 74 9.4
total 131 6304 2.0


line stmt bran cond sub pod time code
1             #
2             # This file is *** FOR CPAN USE ONLY ***.
3             #
4             package Char::Ekoi8r;
5             ######################################################################
6             #
7             # Char::Ekoi8r - Run-time routines for Char/KOI8R.pm
8             #
9             # http://search.cpan.org/dist/Char-KOI8R/
10             #
11             # Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015 INABA Hitoshi
12             ######################################################################
13              
14 197     197   5158 use 5.00503; # Galapagos Consensus 1998 for primetools
  197         655  
  197         11769  
15             # use 5.008001; # Lancaster Consensus 2013 for toolchains
16              
17             # 12.3. Delaying use Until Runtime
18             # in Chapter 12. Packages, Libraries, and Modules
19             # of ISBN 0-596-00313-7 Perl Cookbook, 2nd Edition.
20             # (and so on)
21              
22 197     197   15052 BEGIN { CORE::eval q{ use vars qw($VERSION) } }
  197     197   1217  
  197         518  
  197         48324  
23             $VERSION = sprintf '%d.%02d', q$Revision: 1.02 $ =~ /(\d+)/xmsg;
24              
25             BEGIN {
26 197 50   197   1485 if ($^X =~ / jperl /oxmsi) {
27 0         0 die __FILE__, ": needs perl(not jperl) 5.00503 or later. (\$^X==$^X)";
28             }
29 197         283 if (CORE::ord('A') == 193) {
30             die __FILE__, ": is not US-ASCII script (may be EBCDIC or EBCDIK script).";
31             }
32 197         32022 if (CORE::ord('A') != 0x41) {
33             die __FILE__, ": is not US-ASCII script (must be US-ASCII script).";
34             }
35             }
36              
37             BEGIN {
38              
39             # instead of utf8.pm
40 197     197   14099 CORE::eval q{
  197     197   1209  
  197     66   341  
  197         30906  
  66         12314  
  63         12062  
  73         13872  
  61         10903  
  67         11378  
  64         12795  
41             no warnings qw(redefine);
42             *utf8::upgrade = sub { CORE::length $_[0] };
43             *utf8::downgrade = sub { 1 };
44             *utf8::encode = sub { };
45             *utf8::decode = sub { 1 };
46             *utf8::is_utf8 = sub { };
47             *utf8::valid = sub { 1 };
48             };
49 197 50       123211 if ($@) {
50 0         0 *utf8::upgrade = sub { CORE::length $_[0] };
  0         0  
51 0         0 *utf8::downgrade = sub { 1 };
  0         0  
52 0         0 *utf8::encode = sub { };
  0         0  
53 0         0 *utf8::decode = sub { 1 };
  0         0  
54 0         0 *utf8::is_utf8 = sub { };
  0         0  
55 0         0 *utf8::valid = sub { 1 };
  0         0  
56             }
57             }
58              
59             # instead of Symbol.pm
60             BEGIN {
61 197     197   505 my $genpkg = "Symbol::";
62 197         9441 my $genseq = 0;
63              
64             sub gensym () {
65 0     0 0 0 my $name = "GEN" . $genseq++;
66              
67             # here, no strict qw(refs); if strict.pm exists
68              
69 0         0 my $ref = \*{$genpkg . $name};
  0         0  
70 0         0 delete $$genpkg{$name};
71 0         0 return $ref;
72             }
73              
74             sub qualify ($;$) {
75 0     0 0 0 my ($name) = @_;
76 0 0 0     0 if (!ref($name) && (Char::Ekoi8r::index($name, '::') == -1) && (Char::Ekoi8r::index($name, "'") == -1)) {
      0        
77 0         0 my $pkg;
78 0         0 my %global = map {$_ => 1} qw(ARGV ARGVOUT ENV INC SIG STDERR STDIN STDOUT DATA);
  0         0  
79              
80             # Global names: special character, "^xyz", or other.
81 0 0 0     0 if ($name =~ /^(([^a-z])|(\^[a-z_]+))\z/i || $global{$name}) {
82             # RGS 2001-11-05 : translate leading ^X to control-char
83 0         0 $name =~ s/^\^([a-z_])/'qq(\c'.$1.')'/eei;
  0         0  
84 0         0 $pkg = "main";
85             }
86             else {
87 0 0       0 $pkg = (@_ > 1) ? $_[1] : caller;
88             }
89 0         0 $name = $pkg . "::" . $name;
90             }
91 0         0 return $name;
92             }
93              
94             sub qualify_to_ref ($;$) {
95              
96             # here, no strict qw(refs); if strict.pm exists
97              
98 0 0   0 0 0 return \*{ qualify $_[0], @_ > 1 ? $_[1] : caller };
  0         0  
99             }
100             }
101              
102             # Column: local $@
103             # in Chapter 9. Osaete okitai Perl no kiso
104             # of ISBN 10: 4798119172 | ISBN 13: 978-4798119175 MODAN Perl NYUMON
105             # (and so on)
106              
107             # use strict; if strict.pm exists
108             BEGIN {
109 197 50   197   451 if (CORE::eval { local $@; CORE::require strict }) {
  197         371  
  197         2195  
110 197         32775 strict::->import;
111             }
112             }
113              
114             # P.714 29.2.39. flock
115             # in Chapter 29: Functions
116             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
117              
118             # P.863 flock
119             # in Chapter 27: Functions
120             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
121              
122             sub LOCK_SH() {1}
123             sub LOCK_EX() {2}
124             sub LOCK_UN() {8}
125             sub LOCK_NB() {4}
126              
127             # instead of Carp.pm
128             sub carp;
129             sub croak;
130             sub cluck;
131             sub confess;
132              
133             # 6.18. Matching Multiple-Byte Characters
134             # in Chapter 6. Pattern Matching
135             # of ISBN 978-1-56592-243-3 Perl Perl Cookbook.
136             # (and so on)
137              
138             # regexp of character
139 197     197   13203 BEGIN { CORE::eval q{ use vars qw($your_char) } } $your_char = q{[\x00-\xFF]};
  197     197   1146  
  197         309  
  197         13939  
140 197     197   11385 BEGIN { CORE::eval q{ use vars qw($qq_char ) } } $qq_char = qr/\\c[\x40-\x5F]|\\?(?:$your_char)/oxms;
  197     197   1176  
  197         427  
  197         15376  
141 197     197   13844 BEGIN { CORE::eval q{ use vars qw($q_char ) } } $q_char = qr/$your_char/oxms;
  197     197   1070  
  197         325  
  197         14761  
142              
143             #
144             # KOI8-R character range per length
145             #
146             my %range_tr = ();
147              
148             #
149             # alias of encoding name
150             #
151 197     197   13201 BEGIN { CORE::eval q{ use vars qw($encoding_alias) } }
  197     197   1073  
  197         326  
  197         387280  
152              
153             #
154             # KOI8-R case conversion
155             #
156             my %lc = ();
157             @lc{qw(A B C D E F G H I J K L M N O P Q R S T U V W X Y Z)} =
158             qw(a b c d e f g h i j k l m n o p q r s t u v w x y z);
159             my %uc = ();
160             @uc{qw(a b c d e f g h i j k l m n o p q r s t u v w x y z)} =
161             qw(A B C D E F G H I J K L M N O P Q R S T U V W X Y Z);
162             my %fc = ();
163             @fc{qw(A B C D E F G H I J K L M N O P Q R S T U V W X Y Z)} =
164             qw(a b c d e f g h i j k l m n o p q r s t u v w x y z);
165              
166             if (0) {
167             }
168              
169             elsif (__PACKAGE__ =~ / \b Ekoi8r \z/oxms) {
170             %range_tr = (
171             1 => [ [0x00..0xFF],
172             ],
173             );
174             $encoding_alias = qr/ \b (?: koi8-?r ) \b /oxmsi;
175              
176             %lc = (%lc,
177             "\xB3" => "\xA3", # CYRILLIC LETTER IO
178             "\xE0" => "\xC0", # CYRILLIC LETTER IU
179             "\xE1" => "\xC1", # CYRILLIC LETTER A
180             "\xE2" => "\xC2", # CYRILLIC LETTER BE
181             "\xE3" => "\xC3", # CYRILLIC LETTER TSE
182             "\xE4" => "\xC4", # CYRILLIC LETTER DE
183             "\xE5" => "\xC5", # CYRILLIC LETTER IE
184             "\xE6" => "\xC6", # CYRILLIC LETTER EF
185             "\xE7" => "\xC7", # CYRILLIC LETTER GE
186             "\xE8" => "\xC8", # CYRILLIC LETTER KHA
187             "\xE9" => "\xC9", # CYRILLIC LETTER II
188             "\xEA" => "\xCA", # CYRILLIC LETTER SHORT II
189             "\xEB" => "\xCB", # CYRILLIC LETTER KA
190             "\xEC" => "\xCC", # CYRILLIC LETTER EL
191             "\xED" => "\xCD", # CYRILLIC LETTER EM
192             "\xEE" => "\xCE", # CYRILLIC LETTER EN
193             "\xEF" => "\xCF", # CYRILLIC LETTER O
194             "\xF0" => "\xD0", # CYRILLIC LETTER PE
195             "\xF1" => "\xD1", # CYRILLIC LETTER IA
196             "\xF2" => "\xD2", # CYRILLIC LETTER ER
197             "\xF3" => "\xD3", # CYRILLIC LETTER ES
198             "\xF4" => "\xD4", # CYRILLIC LETTER TE
199             "\xF5" => "\xD5", # CYRILLIC LETTER U
200             "\xF6" => "\xD6", # CYRILLIC LETTER ZHE
201             "\xF7" => "\xD7", # CYRILLIC LETTER VE
202             "\xF8" => "\xD8", # CYRILLIC LETTER SOFT SIGN
203             "\xF9" => "\xD9", # CYRILLIC LETTER YERI
204             "\xFA" => "\xDA", # CYRILLIC LETTER ZE
205             "\xFB" => "\xDB", # CYRILLIC LETTER SHA
206             "\xFC" => "\xDC", # CYRILLIC LETTER REVERSED E
207             "\xFD" => "\xDD", # CYRILLIC LETTER SHCHA
208             "\xFE" => "\xDE", # CYRILLIC LETTER CHE
209             "\xFF" => "\xDF", # CYRILLIC LETTER HARD SIGN
210             );
211              
212             %uc = (%uc,
213             "\xA3" => "\xB3", # CYRILLIC LETTER IO
214             "\xC0" => "\xE0", # CYRILLIC LETTER IU
215             "\xC1" => "\xE1", # CYRILLIC LETTER A
216             "\xC2" => "\xE2", # CYRILLIC LETTER BE
217             "\xC3" => "\xE3", # CYRILLIC LETTER TSE
218             "\xC4" => "\xE4", # CYRILLIC LETTER DE
219             "\xC5" => "\xE5", # CYRILLIC LETTER IE
220             "\xC6" => "\xE6", # CYRILLIC LETTER EF
221             "\xC7" => "\xE7", # CYRILLIC LETTER GE
222             "\xC8" => "\xE8", # CYRILLIC LETTER KHA
223             "\xC9" => "\xE9", # CYRILLIC LETTER II
224             "\xCA" => "\xEA", # CYRILLIC LETTER SHORT II
225             "\xCB" => "\xEB", # CYRILLIC LETTER KA
226             "\xCC" => "\xEC", # CYRILLIC LETTER EL
227             "\xCD" => "\xED", # CYRILLIC LETTER EM
228             "\xCE" => "\xEE", # CYRILLIC LETTER EN
229             "\xCF" => "\xEF", # CYRILLIC LETTER O
230             "\xD0" => "\xF0", # CYRILLIC LETTER PE
231             "\xD1" => "\xF1", # CYRILLIC LETTER IA
232             "\xD2" => "\xF2", # CYRILLIC LETTER ER
233             "\xD3" => "\xF3", # CYRILLIC LETTER ES
234             "\xD4" => "\xF4", # CYRILLIC LETTER TE
235             "\xD5" => "\xF5", # CYRILLIC LETTER U
236             "\xD6" => "\xF6", # CYRILLIC LETTER ZHE
237             "\xD7" => "\xF7", # CYRILLIC LETTER VE
238             "\xD8" => "\xF8", # CYRILLIC LETTER SOFT SIGN
239             "\xD9" => "\xF9", # CYRILLIC LETTER YERI
240             "\xDA" => "\xFA", # CYRILLIC LETTER ZE
241             "\xDB" => "\xFB", # CYRILLIC LETTER SHA
242             "\xDC" => "\xFC", # CYRILLIC LETTER REVERSED E
243             "\xDD" => "\xFD", # CYRILLIC LETTER SHCHA
244             "\xDE" => "\xFE", # CYRILLIC LETTER CHE
245             "\xDF" => "\xFF", # CYRILLIC LETTER HARD SIGN
246             );
247              
248             %fc = (%fc,
249             "\xB3" => "\xA3", # CYRILLIC CAPITAL LETTER IO --> CYRILLIC SMALL LETTER IO
250             "\xE0" => "\xC0", # CYRILLIC CAPITAL LETTER YU --> CYRILLIC SMALL LETTER YU
251             "\xE1" => "\xC1", # CYRILLIC CAPITAL LETTER A --> CYRILLIC SMALL LETTER A
252             "\xE2" => "\xC2", # CYRILLIC CAPITAL LETTER BE --> CYRILLIC SMALL LETTER BE
253             "\xE3" => "\xC3", # CYRILLIC CAPITAL LETTER TSE --> CYRILLIC SMALL LETTER TSE
254             "\xE4" => "\xC4", # CYRILLIC CAPITAL LETTER DE --> CYRILLIC SMALL LETTER DE
255             "\xE5" => "\xC5", # CYRILLIC CAPITAL LETTER IE --> CYRILLIC SMALL LETTER IE
256             "\xE6" => "\xC6", # CYRILLIC CAPITAL LETTER EF --> CYRILLIC SMALL LETTER EF
257             "\xE7" => "\xC7", # CYRILLIC CAPITAL LETTER GHE --> CYRILLIC SMALL LETTER GHE
258             "\xE8" => "\xC8", # CYRILLIC CAPITAL LETTER HA --> CYRILLIC SMALL LETTER HA
259             "\xE9" => "\xC9", # CYRILLIC CAPITAL LETTER I --> CYRILLIC SMALL LETTER I
260             "\xEA" => "\xCA", # CYRILLIC CAPITAL LETTER SHORT I --> CYRILLIC SMALL LETTER SHORT I
261             "\xEB" => "\xCB", # CYRILLIC CAPITAL LETTER KA --> CYRILLIC SMALL LETTER KA
262             "\xEC" => "\xCC", # CYRILLIC CAPITAL LETTER EL --> CYRILLIC SMALL LETTER EL
263             "\xED" => "\xCD", # CYRILLIC CAPITAL LETTER EM --> CYRILLIC SMALL LETTER EM
264             "\xEE" => "\xCE", # CYRILLIC CAPITAL LETTER EN --> CYRILLIC SMALL LETTER EN
265             "\xEF" => "\xCF", # CYRILLIC CAPITAL LETTER O --> CYRILLIC SMALL LETTER O
266             "\xF0" => "\xD0", # CYRILLIC CAPITAL LETTER PE --> CYRILLIC SMALL LETTER PE
267             "\xF1" => "\xD1", # CYRILLIC CAPITAL LETTER YA --> CYRILLIC SMALL LETTER YA
268             "\xF2" => "\xD2", # CYRILLIC CAPITAL LETTER ER --> CYRILLIC SMALL LETTER ER
269             "\xF3" => "\xD3", # CYRILLIC CAPITAL LETTER ES --> CYRILLIC SMALL LETTER ES
270             "\xF4" => "\xD4", # CYRILLIC CAPITAL LETTER TE --> CYRILLIC SMALL LETTER TE
271             "\xF5" => "\xD5", # CYRILLIC CAPITAL LETTER U --> CYRILLIC SMALL LETTER U
272             "\xF6" => "\xD6", # CYRILLIC CAPITAL LETTER ZHE --> CYRILLIC SMALL LETTER ZHE
273             "\xF7" => "\xD7", # CYRILLIC CAPITAL LETTER VE --> CYRILLIC SMALL LETTER VE
274             "\xF8" => "\xD8", # CYRILLIC CAPITAL LETTER SOFT SIGN --> CYRILLIC SMALL LETTER SOFT SIGN
275             "\xF9" => "\xD9", # CYRILLIC CAPITAL LETTER YERU --> CYRILLIC SMALL LETTER YERU
276             "\xFA" => "\xDA", # CYRILLIC CAPITAL LETTER ZE --> CYRILLIC SMALL LETTER ZE
277             "\xFB" => "\xDB", # CYRILLIC CAPITAL LETTER SHA --> CYRILLIC SMALL LETTER SHA
278             "\xFC" => "\xDC", # CYRILLIC CAPITAL LETTER E --> CYRILLIC SMALL LETTER E
279             "\xFD" => "\xDD", # CYRILLIC CAPITAL LETTER SHCHA --> CYRILLIC SMALL LETTER SHCHA
280             "\xFE" => "\xDE", # CYRILLIC CAPITAL LETTER CHE --> CYRILLIC SMALL LETTER CHE
281             "\xFF" => "\xDF", # CYRILLIC CAPITAL LETTER HARD SIGN --> CYRILLIC SMALL LETTER HARD SIGN
282             );
283             }
284              
285             else {
286             croak "Don't know my package name '@{[__PACKAGE__]}'";
287             }
288              
289             #
290             # @ARGV wildcard globbing
291             #
292             sub import {
293              
294 0 0   0   0 if ($^O =~ /\A (?: MSWin32 | NetWare | symbian | dos ) \z/oxms) {
295 0         0 my @argv = ();
296 0         0 for (@ARGV) {
297              
298             # has space
299 0 0       0 if (/\A (?:$q_char)*? [ ] /oxms) {
    0          
300 0 0       0 if (my @glob = Char::Ekoi8r::glob(qq{"$_"})) {
301 0         0 push @argv, @glob;
302             }
303             else {
304 0         0 push @argv, $_;
305             }
306             }
307              
308             # has wildcard metachar
309             elsif (/\A (?:$q_char)*? [*?] /oxms) {
310 0 0       0 if (my @glob = Char::Ekoi8r::glob($_)) {
311 0         0 push @argv, @glob;
312             }
313             else {
314 0         0 push @argv, $_;
315             }
316             }
317              
318             # no wildcard globbing
319             else {
320 0         0 push @argv, $_;
321             }
322             }
323 0         0 @ARGV = @argv;
324             }
325             }
326              
327             # P.230 Care with Prototypes
328             # in Chapter 6: Subroutines
329             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
330             #
331             # If you aren't careful, you can get yourself into trouble with prototypes.
332             # But if you are careful, you can do a lot of neat things with them. This is
333             # all very powerful, of course, and should only be used in moderation to make
334             # the world a better place.
335              
336             # P.332 Care with Prototypes
337             # in Chapter 7: Subroutines
338             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
339             #
340             # If you aren't careful, you can get yourself into trouble with prototypes.
341             # But if you are careful, you can do a lot of neat things with them. This is
342             # all very powerful, of course, and should only be used in moderation to make
343             # the world a better place.
344              
345             #
346             # Prototypes of subroutines
347             #
348 0     0   0 sub unimport {}
349             sub Char::Ekoi8r::split(;$$$);
350             sub Char::Ekoi8r::tr($$$$;$);
351             sub Char::Ekoi8r::chop(@);
352             sub Char::Ekoi8r::index($$;$);
353             sub Char::Ekoi8r::rindex($$;$);
354             sub Char::Ekoi8r::lcfirst(@);
355             sub Char::Ekoi8r::lcfirst_();
356             sub Char::Ekoi8r::lc(@);
357             sub Char::Ekoi8r::lc_();
358             sub Char::Ekoi8r::ucfirst(@);
359             sub Char::Ekoi8r::ucfirst_();
360             sub Char::Ekoi8r::uc(@);
361             sub Char::Ekoi8r::uc_();
362             sub Char::Ekoi8r::fc(@);
363             sub Char::Ekoi8r::fc_();
364             sub Char::Ekoi8r::ignorecase;
365             sub Char::Ekoi8r::classic_character_class;
366             sub Char::Ekoi8r::capture;
367             sub Char::Ekoi8r::chr(;$);
368             sub Char::Ekoi8r::chr_();
369             sub Char::Ekoi8r::glob($);
370             sub Char::Ekoi8r::glob_();
371              
372             sub Char::KOI8R::ord(;$);
373             sub Char::KOI8R::ord_();
374             sub Char::KOI8R::reverse(@);
375             sub Char::KOI8R::getc(;*@);
376             sub Char::KOI8R::length(;$);
377             sub Char::KOI8R::substr($$;$$);
378             sub Char::KOI8R::index($$;$);
379             sub Char::KOI8R::rindex($$;$);
380             sub Char::KOI8R::escape(;$);
381              
382             #
383             # Regexp work
384             #
385 197     197   17392 BEGIN { CORE::eval q{ use vars qw(
  197     197   1426  
  197         586  
  197         95336  
386             $Char::KOI8R::re_a
387             $Char::KOI8R::re_t
388             $Char::KOI8R::re_n
389             $Char::KOI8R::re_r
390             ) } }
391              
392             #
393             # Character class
394             #
395 197     197   16192 BEGIN { CORE::eval q{ use vars qw(
  197     197   1121  
  197         316  
  197         3305577  
396             $dot
397             $dot_s
398             $eD
399             $eS
400             $eW
401             $eH
402             $eV
403             $eR
404             $eN
405             $not_alnum
406             $not_alpha
407             $not_ascii
408             $not_blank
409             $not_cntrl
410             $not_digit
411             $not_graph
412             $not_lower
413             $not_lower_i
414             $not_print
415             $not_punct
416             $not_space
417             $not_upper
418             $not_upper_i
419             $not_word
420             $not_xdigit
421             $eb
422             $eB
423             ) } }
424              
425             ${Char::Ekoi8r::dot} = qr{(?:[^\x0A])};
426             ${Char::Ekoi8r::dot_s} = qr{(?:[\x00-\xFF])};
427             ${Char::Ekoi8r::eD} = qr{(?:[^0-9])};
428              
429             # Vertical tabs are now whitespace
430             # \s in a regex now matches a vertical tab in all circumstances.
431             # http://search.cpan.org/dist/perl-5.18.0/pod/perldelta.pod#Vertical_tabs_are_now_whitespace
432             # ${Char::Ekoi8r::eS} = qr{(?:[^\x09\x0A \x0C\x0D\x20])};
433             # ${Char::Ekoi8r::eS} = qr{(?:[^\x09\x0A\x0B\x0C\x0D\x20])};
434             ${Char::Ekoi8r::eS} = qr{(?:[^\s])};
435              
436             ${Char::Ekoi8r::eW} = qr{(?:[^0-9A-Z_a-z])};
437             ${Char::Ekoi8r::eH} = qr{(?:[^\x09\x20])};
438             ${Char::Ekoi8r::eV} = qr{(?:[^\x0A\x0B\x0C\x0D])};
439             ${Char::Ekoi8r::eR} = qr{(?:\x0D\x0A|[\x0A\x0D])};
440             ${Char::Ekoi8r::eN} = qr{(?:[^\x0A])};
441             ${Char::Ekoi8r::not_alnum} = qr{(?:[^\x30-\x39\x41-\x5A\x61-\x7A])};
442             ${Char::Ekoi8r::not_alpha} = qr{(?:[^\x41-\x5A\x61-\x7A])};
443             ${Char::Ekoi8r::not_ascii} = qr{(?:[^\x00-\x7F])};
444             ${Char::Ekoi8r::not_blank} = qr{(?:[^\x09\x20])};
445             ${Char::Ekoi8r::not_cntrl} = qr{(?:[^\x00-\x1F\x7F])};
446             ${Char::Ekoi8r::not_digit} = qr{(?:[^\x30-\x39])};
447             ${Char::Ekoi8r::not_graph} = qr{(?:[^\x21-\x7F])};
448             ${Char::Ekoi8r::not_lower} = qr{(?:[^\x61-\x7A])};
449             ${Char::Ekoi8r::not_lower_i} = qr{(?:[\x00-\xFF])};
450             ${Char::Ekoi8r::not_print} = qr{(?:[^\x20-\x7F])};
451             ${Char::Ekoi8r::not_punct} = qr{(?:[^\x21-\x2F\x3A-\x3F\x40\x5B-\x5F\x60\x7B-\x7E])};
452             ${Char::Ekoi8r::not_space} = qr{(?:[^\s\x0B])};
453             ${Char::Ekoi8r::not_upper} = qr{(?:[^\x41-\x5A])};
454             ${Char::Ekoi8r::not_upper_i} = qr{(?:[\x00-\xFF])};
455             ${Char::Ekoi8r::not_word} = qr{(?:[^\x30-\x39\x41-\x5A\x5F\x61-\x7A])};
456             ${Char::Ekoi8r::not_xdigit} = qr{(?:[^\x30-\x39\x41-\x46\x61-\x66])};
457             ${Char::Ekoi8r::eb} = qr{(?:\A(?=[0-9A-Z_a-z])|(?<=[\x00-\x2F\x40\x5B-\x5E\x60\x7B-\xFF])(?=[0-9A-Z_a-z])|(?<=[0-9A-Z_a-z])(?=[\x00-\x2F\x40\x5B-\x5E\x60\x7B-\xFF]|\z))};
458             ${Char::Ekoi8r::eB} = qr{(?:(?<=[0-9A-Z_a-z])(?=[0-9A-Z_a-z])|(?<=[\x00-\x2F\x40\x5B-\x5E\x60\x7B-\xFF])(?=[\x00-\x2F\x40\x5B-\x5E\x60\x7B-\xFF]))};
459              
460             # avoid: Name "Char::Ekoi8r::foo" used only once: possible typo at here.
461             ${Char::Ekoi8r::dot} = ${Char::Ekoi8r::dot};
462             ${Char::Ekoi8r::dot_s} = ${Char::Ekoi8r::dot_s};
463             ${Char::Ekoi8r::eD} = ${Char::Ekoi8r::eD};
464             ${Char::Ekoi8r::eS} = ${Char::Ekoi8r::eS};
465             ${Char::Ekoi8r::eW} = ${Char::Ekoi8r::eW};
466             ${Char::Ekoi8r::eH} = ${Char::Ekoi8r::eH};
467             ${Char::Ekoi8r::eV} = ${Char::Ekoi8r::eV};
468             ${Char::Ekoi8r::eR} = ${Char::Ekoi8r::eR};
469             ${Char::Ekoi8r::eN} = ${Char::Ekoi8r::eN};
470             ${Char::Ekoi8r::not_alnum} = ${Char::Ekoi8r::not_alnum};
471             ${Char::Ekoi8r::not_alpha} = ${Char::Ekoi8r::not_alpha};
472             ${Char::Ekoi8r::not_ascii} = ${Char::Ekoi8r::not_ascii};
473             ${Char::Ekoi8r::not_blank} = ${Char::Ekoi8r::not_blank};
474             ${Char::Ekoi8r::not_cntrl} = ${Char::Ekoi8r::not_cntrl};
475             ${Char::Ekoi8r::not_digit} = ${Char::Ekoi8r::not_digit};
476             ${Char::Ekoi8r::not_graph} = ${Char::Ekoi8r::not_graph};
477             ${Char::Ekoi8r::not_lower} = ${Char::Ekoi8r::not_lower};
478             ${Char::Ekoi8r::not_lower_i} = ${Char::Ekoi8r::not_lower_i};
479             ${Char::Ekoi8r::not_print} = ${Char::Ekoi8r::not_print};
480             ${Char::Ekoi8r::not_punct} = ${Char::Ekoi8r::not_punct};
481             ${Char::Ekoi8r::not_space} = ${Char::Ekoi8r::not_space};
482             ${Char::Ekoi8r::not_upper} = ${Char::Ekoi8r::not_upper};
483             ${Char::Ekoi8r::not_upper_i} = ${Char::Ekoi8r::not_upper_i};
484             ${Char::Ekoi8r::not_word} = ${Char::Ekoi8r::not_word};
485             ${Char::Ekoi8r::not_xdigit} = ${Char::Ekoi8r::not_xdigit};
486             ${Char::Ekoi8r::eb} = ${Char::Ekoi8r::eb};
487             ${Char::Ekoi8r::eB} = ${Char::Ekoi8r::eB};
488              
489             #
490             # KOI8-R split
491             #
492             sub Char::Ekoi8r::split(;$$$) {
493              
494             # P.794 29.2.161. split
495             # in Chapter 29: Functions
496             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
497              
498             # P.951 split
499             # in Chapter 27: Functions
500             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
501              
502 0     0 0 0 my $pattern = $_[0];
503 0         0 my $string = $_[1];
504 0         0 my $limit = $_[2];
505              
506             # if $pattern is also omitted or is the literal space, " "
507 0 0       0 if (not defined $pattern) {
508 0         0 $pattern = ' ';
509             }
510              
511             # if $string is omitted, the function splits the $_ string
512 0 0       0 if (not defined $string) {
513 0 0       0 if (defined $_) {
514 0         0 $string = $_;
515             }
516             else {
517 0         0 $string = '';
518             }
519             }
520              
521 0         0 my @split = ();
522              
523             # when string is empty
524 0 0       0 if ($string eq '') {
    0          
525              
526             # resulting list value in list context
527 0 0       0 if (wantarray) {
528 0         0 return @split;
529             }
530              
531             # count of substrings in scalar context
532             else {
533 0 0       0 carp "Use of implicit split to \@_ is deprecated" if $^W;
534 0         0 @_ = @split;
535 0         0 return scalar @_;
536             }
537             }
538              
539             # split's first argument is more consistently interpreted
540             #
541             # After some changes earlier in v5.17, split's behavior has been simplified:
542             # if the PATTERN argument evaluates to a string containing one space, it is
543             # treated the way that a literal string containing one space once was.
544             # http://search.cpan.org/dist/perl-5.18.0/pod/perldelta.pod#split's_first_argument_is_more_consistently_interpreted
545              
546             # if $pattern is also omitted or is the literal space, " ", the function splits
547             # on whitespace, /\s+/, after skipping any leading whitespace
548             # (and so on)
549              
550             elsif ($pattern eq ' ') {
551 0 0       0 if (not defined $limit) {
552 0         0 return CORE::split(' ', $string);
553             }
554             else {
555 0         0 return CORE::split(' ', $string, $limit);
556             }
557             }
558              
559             # if $limit is negative, it is treated as if an arbitrarily large $limit has been specified
560 0 0 0     0 if ((not defined $limit) or ($limit <= 0)) {
    0          
561              
562             # a pattern capable of matching either the null string or something longer than the
563             # null string will split the value of $string into separate characters wherever it
564             # matches the null string between characters
565             # (and so on)
566              
567 0 0       0 if ('' =~ / \A $pattern \z /xms) {
568 0         0 my $last_subexpression_offsets = _last_subexpression_offsets($pattern);
569 0         0 my $limit = scalar(() = $string =~ /($pattern)/oxmsg);
570              
571             # P.1024 Appendix W.10 Multibyte Processing
572             # of ISBN 1-56592-224-7 CJKV Information Processing
573             # (and so on)
574              
575             # the //m modifier is assumed when you split on the pattern /^/
576             # (and so on)
577              
578             # V
579 0   0     0 while ((--$limit > 0) and ($string =~ s/\A((?:$q_char)+?)$pattern//m)) {
580              
581             # if the $pattern contains parentheses, then the substring matched by each pair of parentheses
582             # is included in the resulting list, interspersed with the fields that are ordinarily returned
583             # (and so on)
584              
585 0         0 local $@;
586 0         0 for (my $digit=1; $digit <= ($last_subexpression_offsets + 1); $digit++) {
587 0         0 push @split, CORE::eval('$' . $digit);
588             }
589             }
590             }
591              
592             else {
593 0         0 my $last_subexpression_offsets = _last_subexpression_offsets($pattern);
594              
595             # V
596 0         0 while ($string =~ s/\A((?:$q_char)*?)$pattern//m) {
597 0         0 local $@;
598 0         0 for (my $digit=1; $digit <= ($last_subexpression_offsets + 1); $digit++) {
599 0         0 push @split, CORE::eval('$' . $digit);
600             }
601             }
602             }
603             }
604              
605             elsif ($limit > 0) {
606 0 0       0 if ('' =~ / \A $pattern \z /xms) {
607 0         0 my $last_subexpression_offsets = _last_subexpression_offsets($pattern);
608 0   0     0 while ((--$limit > 0) and (CORE::length($string) > 0)) {
609              
610             # V
611 0 0       0 if ($string =~ s/\A((?:$q_char)+?)$pattern//m) {
612 0         0 local $@;
613 0         0 for (my $digit=1; $digit <= ($last_subexpression_offsets + 1); $digit++) {
614 0         0 push @split, CORE::eval('$' . $digit);
615             }
616             }
617             }
618             }
619             else {
620 0         0 my $last_subexpression_offsets = _last_subexpression_offsets($pattern);
621 0   0     0 while ((--$limit > 0) and (CORE::length($string) > 0)) {
622              
623             # V
624 0 0       0 if ($string =~ s/\A((?:$q_char)*?)$pattern//m) {
625 0         0 local $@;
626 0         0 for (my $digit=1; $digit <= ($last_subexpression_offsets + 1); $digit++) {
627 0         0 push @split, CORE::eval('$' . $digit);
628             }
629             }
630             }
631             }
632             }
633              
634 0 0       0 if (CORE::length($string) > 0) {
635 0         0 push @split, $string;
636             }
637              
638             # if $_[2] (NOT "$limit") is omitted or zero, trailing null fields are stripped from the result
639 0 0 0     0 if ((not defined $_[2]) or ($_[2] == 0)) {
640 0   0     0 while ((scalar(@split) >= 1) and ($split[-1] eq '')) {
641 0         0 pop @split;
642             }
643             }
644              
645             # resulting list value in list context
646 0 0       0 if (wantarray) {
647 0         0 return @split;
648             }
649              
650             # count of substrings in scalar context
651             else {
652 0 0       0 carp "Use of implicit split to \@_ is deprecated" if $^W;
653 0         0 @_ = @split;
654 0         0 return scalar @_;
655             }
656             }
657              
658             #
659             # get last subexpression offsets
660             #
661             sub _last_subexpression_offsets {
662 0     0   0 my $pattern = $_[0];
663              
664             # remove comment
665 0         0 $pattern =~ s/\(\?\# .*? \)//oxmsg;
666              
667 0         0 my $modifier = '';
668 0 0       0 if ($pattern =~ /\(\?\^? ([\-A-Za-z]+) :/oxms) {
669 0         0 $modifier = $1;
670 0         0 $modifier =~ s/-[A-Za-z]*//;
671             }
672              
673             # with /x modifier
674 0         0 my @char = ();
675 0 0       0 if ($modifier =~ /x/oxms) {
676 0         0 @char = $pattern =~ /\G(
677             \\ (?:$q_char) |
678             \# (?:$q_char)*? $ |
679             \[ (?: \\\] | (?:$q_char))+? \] |
680             \(\? |
681             (?:$q_char)
682             )/oxmsg;
683             }
684              
685             # without /x modifier
686             else {
687 0         0 @char = $pattern =~ /\G(
688             \\ (?:$q_char) |
689             \[ (?: \\\] | (?:$q_char))+? \] |
690             \(\? |
691             (?:$q_char)
692             )/oxmsg;
693             }
694              
695 0         0 return scalar grep { $_ eq '(' } @char;
  0         0  
696             }
697              
698             #
699             # KOI8-R transliteration (tr///)
700             #
701             sub Char::Ekoi8r::tr($$$$;$) {
702              
703 0     0 0 0 my $bind_operator = $_[1];
704 0         0 my $searchlist = $_[2];
705 0         0 my $replacementlist = $_[3];
706 0   0     0 my $modifier = $_[4] || '';
707              
708 0 0       0 if ($modifier =~ /r/oxms) {
709 0 0       0 if ($bind_operator =~ / !~ /oxms) {
710 0         0 croak "Using !~ with tr///r doesn't make sense";
711             }
712             }
713              
714 0         0 my @char = $_[0] =~ /\G ($q_char) /oxmsg;
715 0         0 my @searchlist = _charlist_tr($searchlist);
716 0         0 my @replacementlist = _charlist_tr($replacementlist);
717              
718 0         0 my %tr = ();
719 0         0 for (my $i=0; $i <= $#searchlist; $i++) {
720 0 0       0 if (not exists $tr{$searchlist[$i]}) {
721 0 0 0     0 if (defined $replacementlist[$i] and ($replacementlist[$i] ne '')) {
    0 0        
    0          
722 0         0 $tr{$searchlist[$i]} = $replacementlist[$i];
723             }
724             elsif ($modifier =~ /d/oxms) {
725 0         0 $tr{$searchlist[$i]} = '';
726             }
727             elsif (defined $replacementlist[-1] and ($replacementlist[-1] ne '')) {
728 0         0 $tr{$searchlist[$i]} = $replacementlist[-1];
729             }
730             else {
731 0         0 $tr{$searchlist[$i]} = $searchlist[$i];
732             }
733             }
734             }
735              
736 0         0 my $tr = 0;
737 0         0 my $replaced = '';
738 0 0       0 if ($modifier =~ /c/oxms) {
739 0         0 while (defined(my $char = shift @char)) {
740 0 0       0 if (not exists $tr{$char}) {
741 0 0       0 if (defined $replacementlist[0]) {
742 0         0 $replaced .= $replacementlist[0];
743             }
744 0         0 $tr++;
745 0 0       0 if ($modifier =~ /s/oxms) {
746 0   0     0 while (@char and (not exists $tr{$char[0]})) {
747 0         0 shift @char;
748 0         0 $tr++;
749             }
750             }
751             }
752             else {
753 0         0 $replaced .= $char;
754             }
755             }
756             }
757             else {
758 0         0 while (defined(my $char = shift @char)) {
759 0 0       0 if (exists $tr{$char}) {
760 0         0 $replaced .= $tr{$char};
761 0         0 $tr++;
762 0 0       0 if ($modifier =~ /s/oxms) {
763 0   0     0 while (@char and (exists $tr{$char[0]}) and ($tr{$char[0]} eq $tr{$char})) {
      0        
764 0         0 shift @char;
765 0         0 $tr++;
766             }
767             }
768             }
769             else {
770 0         0 $replaced .= $char;
771             }
772             }
773             }
774              
775 0 0       0 if ($modifier =~ /r/oxms) {
776 0         0 return $replaced;
777             }
778             else {
779 0         0 $_[0] = $replaced;
780 0 0       0 if ($bind_operator =~ / !~ /oxms) {
781 0         0 return not $tr;
782             }
783             else {
784 0         0 return $tr;
785             }
786             }
787             }
788              
789             #
790             # KOI8-R chop
791             #
792             sub Char::Ekoi8r::chop(@) {
793              
794 0     0 0 0 my $chop;
795 0 0       0 if (@_ == 0) {
796 0         0 my @char = /\G ($q_char) /oxmsg;
797 0         0 $chop = pop @char;
798 0         0 $_ = join '', @char;
799             }
800             else {
801 0         0 for (@_) {
802 0         0 my @char = /\G ($q_char) /oxmsg;
803 0         0 $chop = pop @char;
804 0         0 $_ = join '', @char;
805             }
806             }
807 0         0 return $chop;
808             }
809              
810             #
811             # KOI8-R index by octet
812             #
813             sub Char::Ekoi8r::index($$;$) {
814              
815 0     0 1 0 my($str,$substr,$position) = @_;
816 0   0     0 $position ||= 0;
817 0         0 my $pos = 0;
818              
819 0         0 while ($pos < CORE::length($str)) {
820 0 0       0 if (CORE::substr($str,$pos,CORE::length($substr)) eq $substr) {
821 0 0       0 if ($pos >= $position) {
822 0         0 return $pos;
823             }
824             }
825 0 0       0 if (CORE::substr($str,$pos) =~ /\A ($q_char) /oxms) {
826 0         0 $pos += CORE::length($1);
827             }
828             else {
829 0         0 $pos += 1;
830             }
831             }
832 0         0 return -1;
833             }
834              
835             #
836             # KOI8-R reverse index
837             #
838             sub Char::Ekoi8r::rindex($$;$) {
839              
840 0     0 0 0 my($str,$substr,$position) = @_;
841 0   0     0 $position ||= CORE::length($str) - 1;
842 0         0 my $pos = 0;
843 0         0 my $rindex = -1;
844              
845 0   0     0 while (($pos < CORE::length($str)) and ($pos <= $position)) {
846 0 0       0 if (CORE::substr($str,$pos,CORE::length($substr)) eq $substr) {
847 0         0 $rindex = $pos;
848             }
849 0 0       0 if (CORE::substr($str,$pos) =~ /\A ($q_char) /oxms) {
850 0         0 $pos += CORE::length($1);
851             }
852             else {
853 0         0 $pos += 1;
854             }
855             }
856 0         0 return $rindex;
857             }
858              
859             #
860             # KOI8-R lower case first with parameter
861             #
862             sub Char::Ekoi8r::lcfirst(@) {
863 0 0   0 0 0 if (@_) {
864 0         0 my $s = shift @_;
865 0 0 0     0 if (@_ and wantarray) {
866 0         0 return Char::Ekoi8r::lc(CORE::substr($s,0,1)) . CORE::substr($s,1), @_;
867             }
868             else {
869 0         0 return Char::Ekoi8r::lc(CORE::substr($s,0,1)) . CORE::substr($s,1);
870             }
871             }
872             else {
873 0         0 return Char::Ekoi8r::lc(CORE::substr($_,0,1)) . CORE::substr($_,1);
874             }
875             }
876              
877             #
878             # KOI8-R lower case first without parameter
879             #
880             sub Char::Ekoi8r::lcfirst_() {
881 0     0 0 0 return Char::Ekoi8r::lc(CORE::substr($_,0,1)) . CORE::substr($_,1);
882             }
883              
884             #
885             # KOI8-R lower case with parameter
886             #
887             sub Char::Ekoi8r::lc(@) {
888 0 0   0 0 0 if (@_) {
889 0         0 my $s = shift @_;
890 0 0 0     0 if (@_ and wantarray) {
891 0 0       0 return join('', map {defined($lc{$_}) ? $lc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg)), @_;
  0         0  
892             }
893             else {
894 0 0       0 return join('', map {defined($lc{$_}) ? $lc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg));
  0         0  
895             }
896             }
897             else {
898 0         0 return Char::Ekoi8r::lc_();
899             }
900             }
901              
902             #
903             # KOI8-R lower case without parameter
904             #
905             sub Char::Ekoi8r::lc_() {
906 0     0 0 0 my $s = $_;
907 0 0       0 return join '', map {defined($lc{$_}) ? $lc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg);
  0         0  
908             }
909              
910             #
911             # KOI8-R upper case first with parameter
912             #
913             sub Char::Ekoi8r::ucfirst(@) {
914 0 0   0 0 0 if (@_) {
915 0         0 my $s = shift @_;
916 0 0 0     0 if (@_ and wantarray) {
917 0         0 return Char::Ekoi8r::uc(CORE::substr($s,0,1)) . CORE::substr($s,1), @_;
918             }
919             else {
920 0         0 return Char::Ekoi8r::uc(CORE::substr($s,0,1)) . CORE::substr($s,1);
921             }
922             }
923             else {
924 0         0 return Char::Ekoi8r::uc(CORE::substr($_,0,1)) . CORE::substr($_,1);
925             }
926             }
927              
928             #
929             # KOI8-R upper case first without parameter
930             #
931             sub Char::Ekoi8r::ucfirst_() {
932 0     0 0 0 return Char::Ekoi8r::uc(CORE::substr($_,0,1)) . CORE::substr($_,1);
933             }
934              
935             #
936             # KOI8-R upper case with parameter
937             #
938             sub Char::Ekoi8r::uc(@) {
939 0 0   0 0 0 if (@_) {
940 0         0 my $s = shift @_;
941 0 0 0     0 if (@_ and wantarray) {
942 0 0       0 return join('', map {defined($uc{$_}) ? $uc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg)), @_;
  0         0  
943             }
944             else {
945 0 0       0 return join('', map {defined($uc{$_}) ? $uc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg));
  0         0  
946             }
947             }
948             else {
949 0         0 return Char::Ekoi8r::uc_();
950             }
951             }
952              
953             #
954             # KOI8-R upper case without parameter
955             #
956             sub Char::Ekoi8r::uc_() {
957 0     0 0 0 my $s = $_;
958 0 0       0 return join '', map {defined($uc{$_}) ? $uc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg);
  0         0  
959             }
960              
961             #
962             # KOI8-R fold case with parameter
963             #
964             sub Char::Ekoi8r::fc(@) {
965 0 0   0 0 0 if (@_) {
966 0         0 my $s = shift @_;
967 0 0 0     0 if (@_ and wantarray) {
968 0 0       0 return join('', map {defined($fc{$_}) ? $fc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg)), @_;
  0         0  
969             }
970             else {
971 0 0       0 return join('', map {defined($fc{$_}) ? $fc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg));
  0         0  
972             }
973             }
974             else {
975 0         0 return Char::Ekoi8r::fc_();
976             }
977             }
978              
979             #
980             # KOI8-R fold case without parameter
981             #
982             sub Char::Ekoi8r::fc_() {
983 0     0 0 0 my $s = $_;
984 0 0       0 return join '', map {defined($fc{$_}) ? $fc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg);
  0         0  
985             }
986              
987             #
988             # KOI8-R regexp capture
989             #
990             {
991             sub Char::Ekoi8r::capture {
992 0     0 1 0 return $_[0];
993             }
994             }
995              
996             #
997             # KOI8-R regexp ignore case modifier
998             #
999             sub Char::Ekoi8r::ignorecase {
1000              
1001 0     0 0 0 my @string = @_;
1002 0         0 my $metachar = qr/[\@\\|[\]{]/oxms;
1003              
1004             # ignore case of $scalar or @array
1005 0         0 for my $string (@string) {
1006              
1007             # split regexp
1008 0         0 my @char = $string =~ /\G(
1009             \[\^ |
1010             \\? (?:$q_char)
1011             )/oxmsg;
1012              
1013             # unescape character
1014 0         0 for (my $i=0; $i <= $#char; $i++) {
1015 0 0       0 next if not defined $char[$i];
1016              
1017             # open character class [...]
1018 0 0       0 if ($char[$i] eq '[') {
    0          
    0          
    0          
1019 0         0 my $left = $i;
1020              
1021             # [] make die "unmatched [] in regexp ..."
1022              
1023 0 0       0 if ($char[$i+1] eq ']') {
1024 0         0 $i++;
1025             }
1026              
1027 0         0 while (1) {
1028 0 0       0 if (++$i > $#char) {
1029 0         0 croak "Unmatched [] in regexp";
1030             }
1031 0 0       0 if ($char[$i] eq ']') {
1032 0         0 my $right = $i;
1033 0         0 my @charlist = charlist_qr(@char[$left+1..$right-1], 'i');
1034              
1035             # escape character
1036 0         0 for my $char (@charlist) {
1037 0 0       0 if (0) {
1038             }
1039              
1040 0         0 elsif ($char =~ /\A [.|)] \z/oxms) {
1041 0         0 $char = $1 . '\\' . $char;
1042             }
1043             }
1044              
1045             # [...]
1046 0         0 splice @char, $left, $right-$left+1, '(?:' . join('|', @charlist) . ')';
1047              
1048 0         0 $i = $left;
1049 0         0 last;
1050             }
1051             }
1052             }
1053              
1054             # open character class [^...]
1055             elsif ($char[$i] eq '[^') {
1056 0         0 my $left = $i;
1057              
1058             # [^] make die "unmatched [] in regexp ..."
1059              
1060 0 0       0 if ($char[$i+1] eq ']') {
1061 0         0 $i++;
1062             }
1063              
1064 0         0 while (1) {
1065 0 0       0 if (++$i > $#char) {
1066 0         0 croak "Unmatched [] in regexp";
1067             }
1068 0 0       0 if ($char[$i] eq ']') {
1069 0         0 my $right = $i;
1070 0         0 my @charlist = charlist_not_qr(@char[$left+1..$right-1], 'i');
1071              
1072             # escape character
1073 0         0 for my $char (@charlist) {
1074 0 0       0 if (0) {
1075             }
1076              
1077 0         0 elsif ($char =~ /\A [.|)] \z/oxms) {
1078 0         0 $char = '\\' . $char;
1079             }
1080             }
1081              
1082             # [^...]
1083 0         0 splice @char, $left, $right-$left+1, '(?!' . join('|', @charlist) . ")(?:$your_char)";
1084              
1085 0         0 $i = $left;
1086 0         0 last;
1087             }
1088             }
1089             }
1090              
1091             # rewrite classic character class or escape character
1092             elsif (my $char = classic_character_class($char[$i])) {
1093 0         0 $char[$i] = $char;
1094             }
1095              
1096             # with /i modifier
1097             elsif ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) {
1098 0         0 my $uc = Char::Ekoi8r::uc($char[$i]);
1099 0         0 my $fc = Char::Ekoi8r::fc($char[$i]);
1100 0 0       0 if ($uc ne $fc) {
1101 0 0       0 if (CORE::length($fc) == 1) {
1102 0         0 $char[$i] = '[' . $uc . $fc . ']';
1103             }
1104             else {
1105 0         0 $char[$i] = '(?:' . $uc . '|' . $fc . ')';
1106             }
1107             }
1108             }
1109             }
1110              
1111             # characterize
1112 0         0 for (my $i=0; $i <= $#char; $i++) {
1113 0 0       0 next if not defined $char[$i];
1114              
1115 0 0       0 if (0) {
1116             }
1117              
1118             # quote character before ? + * {
1119 0 0       0 elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
1120 0 0       0 if ($char[$i-1] !~ /\A [\x00-\xFF] \z/oxms) {
1121 0         0 $char[$i-1] = '(?:' . $char[$i-1] . ')';
1122             }
1123             }
1124             }
1125              
1126 0         0 $string = join '', @char;
1127             }
1128              
1129             # make regexp string
1130 0         0 return @string;
1131             }
1132              
1133             #
1134             # classic character class ( \D \S \W \d \s \w \C \X \H \V \h \v \R \N \b \B )
1135             #
1136             sub Char::Ekoi8r::classic_character_class {
1137 0     0 0 0 my($char) = @_;
1138              
1139             return {
1140 0   0     0 '\D' => '${Char::Ekoi8r::eD}',
1141             '\S' => '${Char::Ekoi8r::eS}',
1142             '\W' => '${Char::Ekoi8r::eW}',
1143             '\d' => '[0-9]',
1144              
1145             # Before Perl 5.6, \s only matched the five whitespace characters
1146             # tab, newline, form-feed, carriage return, and the space character
1147             # itself, which, taken together, is the character class [\t\n\f\r ].
1148              
1149             # Vertical tabs are now whitespace
1150             # \s in a regex now matches a vertical tab in all circumstances.
1151             # http://search.cpan.org/dist/perl-5.18.0/pod/perldelta.pod#Vertical_tabs_are_now_whitespace
1152             # \t \n \v \f \r space
1153             # '\s' => '[\x09\x0A \x0C\x0D\x20]',
1154             # '\s' => '[\x09\x0A\x0B\x0C\x0D\x20]',
1155             '\s' => '\s',
1156              
1157             '\w' => '[0-9A-Z_a-z]',
1158             '\C' => '[\x00-\xFF]',
1159             '\X' => 'X',
1160              
1161             # \h \v \H \V
1162              
1163             # P.114 Character Class Shortcuts
1164             # in Chapter 7: In the World of Regular Expressions
1165             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
1166              
1167             # P.357 13.2.3 Whitespace
1168             # in Chapter 13: perlrecharclass: Perl Regular Expression Character Classes
1169             # of ISBN-13: 978-1-906966-02-7 The Perl Language Reference Manual (for Perl version 5.12.1)
1170             #
1171             # 0x00009 CHARACTER TABULATION h s
1172             # 0x0000a LINE FEED (LF) vs
1173             # 0x0000b LINE TABULATION v
1174             # 0x0000c FORM FEED (FF) vs
1175             # 0x0000d CARRIAGE RETURN (CR) vs
1176             # 0x00020 SPACE h s
1177              
1178             # P.196 Table 5-9. Alphanumeric regex metasymbols
1179             # in Chapter 5. Pattern Matching
1180             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
1181              
1182             # (and so on)
1183              
1184             '\H' => '${Char::Ekoi8r::eH}',
1185             '\V' => '${Char::Ekoi8r::eV}',
1186             '\h' => '[\x09\x20]',
1187             '\v' => '[\x0A\x0B\x0C\x0D]',
1188             '\R' => '${Char::Ekoi8r::eR}',
1189              
1190             # \N
1191             #
1192             # http://perldoc.perl.org/perlre.html
1193             # Character Classes and other Special Escapes
1194             # Any character but \n (experimental). Not affected by /s modifier
1195              
1196             '\N' => '${Char::Ekoi8r::eN}',
1197              
1198             # \b \B
1199              
1200             # P.180 Boundaries: The \b and \B Assertions
1201             # in Chapter 5: Pattern Matching
1202             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
1203              
1204             # P.219 Boundaries: The \b and \B Assertions
1205             # in Chapter 5: Pattern Matching
1206             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
1207              
1208             # '\b' => '(?:(?<=\A|\W)(?=\w)|(?<=\w)(?=\W|\z))',
1209             '\b' => '${Char::Ekoi8r::eb}',
1210              
1211             # '\B' => '(?:(?<=\w)(?=\w)|(?<=\W)(?=\W))',
1212             '\B' => '${Char::Ekoi8r::eB}',
1213              
1214             }->{$char} || '';
1215             }
1216              
1217             #
1218             # prepare KOI8-R characters per length
1219             #
1220              
1221             # 1 octet characters
1222             my @chars1 = ();
1223             sub chars1 {
1224 0 0   0 0 0 if (@chars1) {
1225 0         0 return @chars1;
1226             }
1227 0 0       0 if (exists $range_tr{1}) {
1228 0         0 my @ranges = @{ $range_tr{1} };
  0         0  
1229 0         0 while (my @range = splice(@ranges,0,1)) {
1230 0         0 for my $oct0 (@{$range[0]}) {
  0         0  
1231 0         0 push @chars1, pack 'C', $oct0;
1232             }
1233             }
1234             }
1235 0         0 return @chars1;
1236             }
1237              
1238             # 2 octets characters
1239             my @chars2 = ();
1240             sub chars2 {
1241 0 0   0 0 0 if (@chars2) {
1242 0         0 return @chars2;
1243             }
1244 0 0       0 if (exists $range_tr{2}) {
1245 0         0 my @ranges = @{ $range_tr{2} };
  0         0  
1246 0         0 while (my @range = splice(@ranges,0,2)) {
1247 0         0 for my $oct0 (@{$range[0]}) {
  0         0  
1248 0         0 for my $oct1 (@{$range[1]}) {
  0         0  
1249 0         0 push @chars2, pack 'CC', $oct0,$oct1;
1250             }
1251             }
1252             }
1253             }
1254 0         0 return @chars2;
1255             }
1256              
1257             # 3 octets characters
1258             my @chars3 = ();
1259             sub chars3 {
1260 0 0   0 0 0 if (@chars3) {
1261 0         0 return @chars3;
1262             }
1263 0 0       0 if (exists $range_tr{3}) {
1264 0         0 my @ranges = @{ $range_tr{3} };
  0         0  
1265 0         0 while (my @range = splice(@ranges,0,3)) {
1266 0         0 for my $oct0 (@{$range[0]}) {
  0         0  
1267 0         0 for my $oct1 (@{$range[1]}) {
  0         0  
1268 0         0 for my $oct2 (@{$range[2]}) {
  0         0  
1269 0         0 push @chars3, pack 'CCC', $oct0,$oct1,$oct2;
1270             }
1271             }
1272             }
1273             }
1274             }
1275 0         0 return @chars3;
1276             }
1277              
1278             # 4 octets characters
1279             my @chars4 = ();
1280             sub chars4 {
1281 0 0   0 0 0 if (@chars4) {
1282 0         0 return @chars4;
1283             }
1284 0 0       0 if (exists $range_tr{4}) {
1285 0         0 my @ranges = @{ $range_tr{4} };
  0         0  
1286 0         0 while (my @range = splice(@ranges,0,4)) {
1287 0         0 for my $oct0 (@{$range[0]}) {
  0         0  
1288 0         0 for my $oct1 (@{$range[1]}) {
  0         0  
1289 0         0 for my $oct2 (@{$range[2]}) {
  0         0  
1290 0         0 for my $oct3 (@{$range[3]}) {
  0         0  
1291 0         0 push @chars4, pack 'CCCC', $oct0,$oct1,$oct2,$oct3;
1292             }
1293             }
1294             }
1295             }
1296             }
1297             }
1298 0         0 return @chars4;
1299             }
1300              
1301             #
1302             # KOI8-R open character list for tr
1303             #
1304             sub _charlist_tr {
1305              
1306 0     0   0 local $_ = shift @_;
1307              
1308             # unescape character
1309 0         0 my @char = ();
1310 0         0 while (not /\G \z/oxmsgc) {
1311 0 0       0 if (/\G (\\0?55|\\x2[Dd]|\\-) /oxmsgc) {
    0          
    0          
    0          
    0          
    0          
    0          
1312 0         0 push @char, '\-';
1313             }
1314             elsif (/\G \\ ([0-7]{2,3}) /oxmsgc) {
1315 0         0 push @char, CORE::chr(oct $1);
1316             }
1317             elsif (/\G \\x ([0-9A-Fa-f]{1,2}) /oxmsgc) {
1318 0         0 push @char, CORE::chr(hex $1);
1319             }
1320             elsif (/\G \\c ([\x40-\x5F]) /oxmsgc) {
1321 0         0 push @char, CORE::chr(CORE::ord($1) & 0x1F);
1322             }
1323             elsif (/\G (\\ [0nrtfbae]) /oxmsgc) {
1324 0         0 push @char, {
1325             '\0' => "\0",
1326             '\n' => "\n",
1327             '\r' => "\r",
1328             '\t' => "\t",
1329             '\f' => "\f",
1330             '\b' => "\x08", # \b means backspace in character class
1331             '\a' => "\a",
1332             '\e' => "\e",
1333             }->{$1};
1334             }
1335             elsif (/\G \\ ($q_char) /oxmsgc) {
1336 0         0 push @char, $1;
1337             }
1338             elsif (/\G ($q_char) /oxmsgc) {
1339 0         0 push @char, $1;
1340             }
1341             }
1342              
1343             # join separated multiple-octet
1344 0         0 @char = join('',@char) =~ /\G (\\-|$q_char) /oxmsg;
1345              
1346             # unescape '-'
1347 0         0 my @i = ();
1348 0         0 for my $i (0 .. $#char) {
1349 0 0       0 if ($char[$i] eq '\-') {
    0          
1350 0         0 $char[$i] = '-';
1351             }
1352             elsif ($char[$i] eq '-') {
1353 0 0 0     0 if ((0 < $i) and ($i < $#char)) {
1354 0         0 push @i, $i;
1355             }
1356             }
1357             }
1358              
1359             # open character list (reverse for splice)
1360 0         0 for my $i (CORE::reverse @i) {
1361 0         0 my @range = ();
1362              
1363             # range error
1364 0 0 0     0 if ((CORE::length($char[$i-1]) > CORE::length($char[$i+1])) or ($char[$i-1] gt $char[$i+1])) {
1365 0         0 croak "Invalid tr/// range \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1366             }
1367              
1368             # range of multiple-octet code
1369 0 0       0 if (CORE::length($char[$i-1]) == 1) {
    0          
    0          
    0          
1370 0 0       0 if (CORE::length($char[$i+1]) == 1) {
    0          
    0          
    0          
1371 0 0       0 push @range, grep {($char[$i-1] le $_) and ($_ le $char[$i+1])} chars1();
  0         0  
1372             }
1373             elsif (CORE::length($char[$i+1]) == 2) {
1374 0         0 push @range, grep {$char[$i-1] le $_} chars1();
  0         0  
1375 0         0 push @range, grep {$_ le $char[$i+1]} chars2();
  0         0  
1376             }
1377             elsif (CORE::length($char[$i+1]) == 3) {
1378 0         0 push @range, grep {$char[$i-1] le $_} chars1();
  0         0  
1379 0         0 push @range, chars2();
1380 0         0 push @range, grep {$_ le $char[$i+1]} chars3();
  0         0  
1381             }
1382             elsif (CORE::length($char[$i+1]) == 4) {
1383 0         0 push @range, grep {$char[$i-1] le $_} chars1();
  0         0  
1384 0         0 push @range, chars2();
1385 0         0 push @range, chars3();
1386 0         0 push @range, grep {$_ le $char[$i+1]} chars4();
  0         0  
1387             }
1388             else {
1389 0         0 croak "Invalid tr/// range (over 4octets) \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1390             }
1391             }
1392             elsif (CORE::length($char[$i-1]) == 2) {
1393 0 0       0 if (CORE::length($char[$i+1]) == 2) {
    0          
    0          
1394 0 0       0 push @range, grep {($char[$i-1] le $_) and ($_ le $char[$i+1])} chars2();
  0         0  
1395             }
1396             elsif (CORE::length($char[$i+1]) == 3) {
1397 0         0 push @range, grep {$char[$i-1] le $_} chars2();
  0         0  
1398 0         0 push @range, grep {$_ le $char[$i+1]} chars3();
  0         0  
1399             }
1400             elsif (CORE::length($char[$i+1]) == 4) {
1401 0         0 push @range, grep {$char[$i-1] le $_} chars2();
  0         0  
1402 0         0 push @range, chars3();
1403 0         0 push @range, grep {$_ le $char[$i+1]} chars4();
  0         0  
1404             }
1405             else {
1406 0         0 croak "Invalid tr/// range (over 4octets) \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1407             }
1408             }
1409             elsif (CORE::length($char[$i-1]) == 3) {
1410 0 0       0 if (CORE::length($char[$i+1]) == 3) {
    0          
1411 0 0       0 push @range, grep {($char[$i-1] le $_) and ($_ le $char[$i+1])} chars3();
  0         0  
1412             }
1413             elsif (CORE::length($char[$i+1]) == 4) {
1414 0         0 push @range, grep {$char[$i-1] le $_} chars3();
  0         0  
1415 0         0 push @range, grep {$_ le $char[$i+1]} chars4();
  0         0  
1416             }
1417             else {
1418 0         0 croak "Invalid tr/// range (over 4octets) \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1419             }
1420             }
1421             elsif (CORE::length($char[$i-1]) == 4) {
1422 0 0       0 if (CORE::length($char[$i+1]) == 4) {
1423 0 0       0 push @range, grep {($char[$i-1] le $_) and ($_ le $char[$i+1])} chars4();
  0         0  
1424             }
1425             else {
1426 0         0 croak "Invalid tr/// range (over 4octets) \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1427             }
1428             }
1429             else {
1430 0         0 croak "Invalid tr/// range (over 4octets) \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1431             }
1432              
1433 0         0 splice @char, $i-1, 3, @range;
1434             }
1435              
1436 0         0 return @char;
1437             }
1438              
1439             #
1440             # KOI8-R open character class
1441             #
1442             sub _cc {
1443 0 0   0   0 if (scalar(@_) == 0) {
    0          
    0          
1444 0         0 die __FILE__, ": subroutine cc got no parameter.";
1445             }
1446             elsif (scalar(@_) == 1) {
1447 0         0 return sprintf('\x%02X',$_[0]);
1448             }
1449             elsif (scalar(@_) == 2) {
1450 0 0       0 if ($_[0] > $_[1]) {
    0          
    0          
1451 0         0 die __FILE__, ": subroutine cc got \$_[0] > \$_[1] parameters).";
1452             }
1453             elsif ($_[0] == $_[1]) {
1454 0         0 return sprintf('\x%02X',$_[0]);
1455             }
1456             elsif (($_[0]+1) == $_[1]) {
1457 0         0 return sprintf('[\\x%02X\\x%02X]',$_[0],$_[1]);
1458             }
1459             else {
1460 0         0 return sprintf('[\\x%02X-\\x%02X]',$_[0],$_[1]);
1461             }
1462             }
1463             else {
1464 0         0 die __FILE__, ": subroutine cc got 3 or more parameters (@{[scalar(@_)]} parameters).";
  0         0  
1465             }
1466             }
1467              
1468             #
1469             # KOI8-R octet range
1470             #
1471             sub _octets {
1472 0     0   0 my $length = shift @_;
1473              
1474 0 0       0 if ($length == 1) {
1475 0         0 my($a1) = unpack 'C', $_[0];
1476 0         0 my($z1) = unpack 'C', $_[1];
1477              
1478 0 0       0 if ($a1 > $z1) {
1479 0         0 croak 'Invalid [] range in regexp (CORE::ord(A) > CORE::ord(B)) ' . '\x' . unpack('H*',$a1) . '-\x' . unpack('H*',$z1);
1480             }
1481              
1482 0 0       0 if ($a1 == $z1) {
    0          
1483 0         0 return sprintf('\x%02X',$a1);
1484             }
1485             elsif (($a1+1) == $z1) {
1486 0         0 return sprintf('\x%02X\x%02X',$a1,$z1);
1487             }
1488             else {
1489 0         0 return sprintf('\x%02X-\x%02X',$a1,$z1);
1490             }
1491             }
1492             else {
1493 0         0 die __FILE__, ": subroutine _octets got invalid length ($length).";
1494             }
1495             }
1496              
1497             #
1498             # KOI8-R range regexp
1499             #
1500             sub _range_regexp {
1501 0     0   0 my($length,$first,$last) = @_;
1502              
1503 0         0 my @range_regexp = ();
1504 0 0       0 if (not exists $range_tr{$length}) {
1505 0         0 return @range_regexp;
1506             }
1507              
1508 0         0 my @ranges = @{ $range_tr{$length} };
  0         0  
1509 0         0 while (my @range = splice(@ranges,0,$length)) {
1510 0         0 my $min = '';
1511 0         0 my $max = '';
1512 0         0 for (my $i=0; $i < $length; $i++) {
1513 0         0 $min .= pack 'C', $range[$i][0];
1514 0         0 $max .= pack 'C', $range[$i][-1];
1515             }
1516              
1517             # min___max
1518             # FIRST_____________LAST
1519             # (nothing)
1520              
1521 0 0 0     0 if ($max lt $first) {
    0 0        
    0 0        
    0 0        
    0 0        
    0 0        
    0 0        
1522             }
1523              
1524             # **********
1525             # min_________max
1526             # FIRST_____________LAST
1527             # **********
1528              
1529             elsif (($min le $first) and ($first le $max) and ($max le $last)) {
1530 0         0 push @range_regexp, _octets($length,$first,$max,$min,$max);
1531             }
1532              
1533             # **********************
1534             # min________________max
1535             # FIRST_____________LAST
1536             # **********************
1537              
1538             elsif (($min eq $first) and ($max eq $last)) {
1539 0         0 push @range_regexp, _octets($length,$first,$last,$min,$max);
1540             }
1541              
1542             # *********
1543             # min___max
1544             # FIRST_____________LAST
1545             # *********
1546              
1547             elsif (($first le $min) and ($max le $last)) {
1548 0         0 push @range_regexp, _octets($length,$min,$max,$min,$max);
1549             }
1550              
1551             # **********************
1552             # min__________________________max
1553             # FIRST_____________LAST
1554             # **********************
1555              
1556             elsif (($min le $first) and ($last le $max)) {
1557 0         0 push @range_regexp, _octets($length,$first,$last,$min,$max);
1558             }
1559              
1560             # *********
1561             # min________max
1562             # FIRST_____________LAST
1563             # *********
1564              
1565             elsif (($first le $min) and ($min le $last) and ($last le $max)) {
1566 0         0 push @range_regexp, _octets($length,$min,$last,$min,$max);
1567             }
1568              
1569             # min___max
1570             # FIRST_____________LAST
1571             # (nothing)
1572              
1573             elsif ($last lt $min) {
1574             }
1575              
1576             else {
1577 0         0 die __FILE__, ": subroutine _range_regexp panic.";
1578             }
1579             }
1580              
1581 0         0 return @range_regexp;
1582             }
1583              
1584             #
1585             # KOI8-R open character list for qr and not qr
1586             #
1587             sub _charlist {
1588              
1589 0     0   0 my $modifier = pop @_;
1590 0         0 my @char = @_;
1591              
1592 0 0       0 my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
1593              
1594             # unescape character
1595 0         0 for (my $i=0; $i <= $#char; $i++) {
1596              
1597             # escape - to ...
1598 0 0 0     0 if ($char[$i] eq '-') {
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
1599 0 0 0     0 if ((0 < $i) and ($i < $#char)) {
1600 0         0 $char[$i] = '...';
1601             }
1602             }
1603              
1604             # octal escape sequence
1605             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
1606 0         0 $char[$i] = octchr($1);
1607             }
1608              
1609             # hexadecimal escape sequence
1610             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
1611 0         0 $char[$i] = hexchr($1);
1612             }
1613              
1614             # \N{CHARNAME} --> N\{CHARNAME}
1615             elsif ($char[$i] =~ /\A \\ (N) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
1616 0         0 $char[$i] = $1 . '\\' . $2;
1617             }
1618              
1619             # \p{PROPERTY} --> p\{PROPERTY}
1620             elsif ($char[$i] =~ /\A \\ (p) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
1621 0         0 $char[$i] = $1 . '\\' . $2;
1622             }
1623              
1624             # \P{PROPERTY} --> P\{PROPERTY}
1625             elsif ($char[$i] =~ /\A \\ (P) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
1626 0         0 $char[$i] = $1 . '\\' . $2;
1627             }
1628              
1629             # \p, \P, \X --> p, P, X
1630             elsif ($char[$i] =~ /\A \\ ( [pPX] ) \z/oxms) {
1631 0         0 $char[$i] = $1;
1632             }
1633              
1634             elsif ($char[$i] =~ /\A \\ ([0-7]{2,3}) \z/oxms) {
1635 0         0 $char[$i] = CORE::chr oct $1;
1636             }
1637             elsif ($char[$i] =~ /\A \\x ([0-9A-Fa-f]{1,2}) \z/oxms) {
1638 0         0 $char[$i] = CORE::chr hex $1;
1639             }
1640             elsif ($char[$i] =~ /\A \\c ([\x40-\x5F]) \z/oxms) {
1641 0         0 $char[$i] = CORE::chr(CORE::ord($1) & 0x1F);
1642             }
1643             elsif ($char[$i] =~ /\A (\\ [0nrtfbaedswDSWHVhvR]) \z/oxms) {
1644 0         0 $char[$i] = {
1645             '\0' => "\0",
1646             '\n' => "\n",
1647             '\r' => "\r",
1648             '\t' => "\t",
1649             '\f' => "\f",
1650             '\b' => "\x08", # \b means backspace in character class
1651             '\a' => "\a",
1652             '\e' => "\e",
1653             '\d' => '[0-9]',
1654              
1655             # Vertical tabs are now whitespace
1656             # \s in a regex now matches a vertical tab in all circumstances.
1657             # http://search.cpan.org/dist/perl-5.18.0/pod/perldelta.pod#Vertical_tabs_are_now_whitespace
1658             # \t \n \v \f \r space
1659             # '\s' => '[\x09\x0A \x0C\x0D\x20]',
1660             # '\s' => '[\x09\x0A\x0B\x0C\x0D\x20]',
1661             '\s' => '\s',
1662              
1663             '\w' => '[0-9A-Z_a-z]',
1664             '\D' => '${Char::Ekoi8r::eD}',
1665             '\S' => '${Char::Ekoi8r::eS}',
1666             '\W' => '${Char::Ekoi8r::eW}',
1667              
1668             '\H' => '${Char::Ekoi8r::eH}',
1669             '\V' => '${Char::Ekoi8r::eV}',
1670             '\h' => '[\x09\x20]',
1671             '\v' => '[\x0A\x0B\x0C\x0D]',
1672             '\R' => '${Char::Ekoi8r::eR}',
1673              
1674             }->{$1};
1675             }
1676              
1677             # POSIX-style character classes
1678             elsif ($ignorecase and ($char[$i] =~ /\A ( \[\: \^? (?:lower|upper) :\] ) \z/oxms)) {
1679 0         0 $char[$i] = {
1680              
1681             '[:lower:]' => '[\x41-\x5A\x61-\x7A]',
1682             '[:upper:]' => '[\x41-\x5A\x61-\x7A]',
1683             '[:^lower:]' => '${Char::Ekoi8r::not_lower_i}',
1684             '[:^upper:]' => '${Char::Ekoi8r::not_upper_i}',
1685              
1686             }->{$1};
1687             }
1688             elsif ($char[$i] =~ /\A ( \[\: \^? (?:alnum|alpha|ascii|blank|cntrl|digit|graph|lower|print|punct|space|upper|word|xdigit) :\] ) \z/oxms) {
1689 0         0 $char[$i] = {
1690              
1691             '[:alnum:]' => '[\x30-\x39\x41-\x5A\x61-\x7A]',
1692             '[:alpha:]' => '[\x41-\x5A\x61-\x7A]',
1693             '[:ascii:]' => '[\x00-\x7F]',
1694             '[:blank:]' => '[\x09\x20]',
1695             '[:cntrl:]' => '[\x00-\x1F\x7F]',
1696             '[:digit:]' => '[\x30-\x39]',
1697             '[:graph:]' => '[\x21-\x7F]',
1698             '[:lower:]' => '[\x61-\x7A]',
1699             '[:print:]' => '[\x20-\x7F]',
1700             '[:punct:]' => '[\x21-\x2F\x3A-\x3F\x40\x5B-\x5F\x60\x7B-\x7E]',
1701              
1702             # P.174 POSIX-Style Character Classes
1703             # in Chapter 5: Pattern Matching
1704             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
1705              
1706             # P.311 11.2.4 Character Classes and other Special Escapes
1707             # in Chapter 11: perlre: Perl regular expressions
1708             # of ISBN-13: 978-1-906966-02-7 The Perl Language Reference Manual (for Perl version 5.12.1)
1709              
1710             # P.210 POSIX-Style Character Classes
1711             # in Chapter 5: Pattern Matching
1712             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
1713              
1714             '[:space:]' => '[\s\x0B]', # "\s" plus vertical tab ("\cK")
1715              
1716             '[:upper:]' => '[\x41-\x5A]',
1717             '[:word:]' => '[\x30-\x39\x41-\x5A\x5F\x61-\x7A]',
1718             '[:xdigit:]' => '[\x30-\x39\x41-\x46\x61-\x66]',
1719             '[:^alnum:]' => '${Char::Ekoi8r::not_alnum}',
1720             '[:^alpha:]' => '${Char::Ekoi8r::not_alpha}',
1721             '[:^ascii:]' => '${Char::Ekoi8r::not_ascii}',
1722             '[:^blank:]' => '${Char::Ekoi8r::not_blank}',
1723             '[:^cntrl:]' => '${Char::Ekoi8r::not_cntrl}',
1724             '[:^digit:]' => '${Char::Ekoi8r::not_digit}',
1725             '[:^graph:]' => '${Char::Ekoi8r::not_graph}',
1726             '[:^lower:]' => '${Char::Ekoi8r::not_lower}',
1727             '[:^print:]' => '${Char::Ekoi8r::not_print}',
1728             '[:^punct:]' => '${Char::Ekoi8r::not_punct}',
1729             '[:^space:]' => '${Char::Ekoi8r::not_space}',
1730             '[:^upper:]' => '${Char::Ekoi8r::not_upper}',
1731             '[:^word:]' => '${Char::Ekoi8r::not_word}',
1732             '[:^xdigit:]' => '${Char::Ekoi8r::not_xdigit}',
1733              
1734             }->{$1};
1735             }
1736             elsif ($char[$i] =~ /\A \\ ($q_char) \z/oxms) {
1737 0         0 $char[$i] = $1;
1738             }
1739             }
1740              
1741             # open character list
1742 0         0 my @singleoctet = ();
1743 0         0 my @multipleoctet = ();
1744 0         0 for (my $i=0; $i <= $#char; ) {
1745              
1746             # escaped -
1747 0 0 0     0 if (defined($char[$i+1]) and ($char[$i+1] eq '...')) {
    0          
    0          
    0          
    0          
    0          
1748 0         0 $i += 1;
1749 0         0 next;
1750             }
1751              
1752             # make range regexp
1753             elsif ($char[$i] eq '...') {
1754              
1755             # range error
1756 0 0       0 if (CORE::length($char[$i-1]) > CORE::length($char[$i+1])) {
    0          
1757 0         0 croak 'Invalid [] range in regexp (length(A) > length(B)) ' . '\x' . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]);
1758             }
1759             elsif (CORE::length($char[$i-1]) == CORE::length($char[$i+1])) {
1760 0 0       0 if ($char[$i-1] gt $char[$i+1]) {
1761 0         0 croak 'Invalid [] range in regexp (CORE::ord(A) > CORE::ord(B)) ' . '\x' . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]);
1762             }
1763             }
1764              
1765             # make range regexp per length
1766 0         0 for my $length (CORE::length($char[$i-1]) .. CORE::length($char[$i+1])) {
1767 0         0 my @regexp = ();
1768              
1769             # is first and last
1770 0 0 0     0 if (($length == CORE::length($char[$i-1])) and ($length == CORE::length($char[$i+1]))) {
    0 0        
    0          
    0          
1771 0         0 push @regexp, _range_regexp($length, $char[$i-1], $char[$i+1]);
1772             }
1773              
1774             # is first
1775             elsif ($length == CORE::length($char[$i-1])) {
1776 0         0 push @regexp, _range_regexp($length, $char[$i-1], "\xFF" x $length);
1777             }
1778              
1779             # is inside in first and last
1780             elsif ((CORE::length($char[$i-1]) < $length) and ($length < CORE::length($char[$i+1]))) {
1781 0         0 push @regexp, _range_regexp($length, "\x00" x $length, "\xFF" x $length);
1782             }
1783              
1784             # is last
1785             elsif ($length == CORE::length($char[$i+1])) {
1786 0         0 push @regexp, _range_regexp($length, "\x00" x $length, $char[$i+1]);
1787             }
1788              
1789             else {
1790 0         0 die __FILE__, ": subroutine make_regexp panic.";
1791             }
1792              
1793 0 0       0 if ($length == 1) {
1794 0         0 push @singleoctet, @regexp;
1795             }
1796             else {
1797 0         0 push @multipleoctet, @regexp;
1798             }
1799             }
1800              
1801 0         0 $i += 2;
1802             }
1803              
1804             # with /i modifier
1805             elsif ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) {
1806 0 0       0 if ($modifier =~ /i/oxms) {
1807 0         0 my $uc = Char::Ekoi8r::uc($char[$i]);
1808 0         0 my $fc = Char::Ekoi8r::fc($char[$i]);
1809 0 0       0 if ($uc ne $fc) {
1810 0 0       0 if (CORE::length($fc) == 1) {
1811 0         0 push @singleoctet, $uc, $fc;
1812             }
1813             else {
1814 0         0 push @singleoctet, $uc;
1815 0         0 push @multipleoctet, $fc;
1816             }
1817             }
1818             else {
1819 0         0 push @singleoctet, $char[$i];
1820             }
1821             }
1822             else {
1823 0         0 push @singleoctet, $char[$i];
1824             }
1825 0         0 $i += 1;
1826             }
1827              
1828             # single character of single octet code
1829             elsif ($char[$i] =~ /\A (?: \\h ) \z/oxms) {
1830 0         0 push @singleoctet, "\t", "\x20";
1831 0         0 $i += 1;
1832             }
1833             elsif ($char[$i] =~ /\A (?: \\v ) \z/oxms) {
1834 0         0 push @singleoctet, "\x0A", "\x0B", "\x0C", "\x0D";
1835 0         0 $i += 1;
1836             }
1837             elsif ($char[$i] =~ /\A (?: \\d | \\s | \\w ) \z/oxms) {
1838 0         0 push @singleoctet, $char[$i];
1839 0         0 $i += 1;
1840             }
1841              
1842             # single character of multiple-octet code
1843             else {
1844 0         0 push @multipleoctet, $char[$i];
1845 0         0 $i += 1;
1846             }
1847             }
1848              
1849             # quote metachar
1850 0         0 for (@singleoctet) {
1851 0 0       0 if ($_ eq '...') {
    0          
    0          
    0          
    0          
1852 0         0 $_ = '-';
1853             }
1854             elsif (/\A \n \z/oxms) {
1855 0         0 $_ = '\n';
1856             }
1857             elsif (/\A \r \z/oxms) {
1858 0         0 $_ = '\r';
1859             }
1860             elsif (/\A ([\x00-\x20\x7F-\xFF]) \z/oxms) {
1861 0         0 $_ = sprintf('\x%02X', CORE::ord $1);
1862             }
1863             elsif (/\A [\x00-\xFF] \z/oxms) {
1864 0         0 $_ = quotemeta $_;
1865             }
1866             }
1867              
1868             # return character list
1869 0         0 return \@singleoctet, \@multipleoctet;
1870             }
1871              
1872             #
1873             # KOI8-R octal escape sequence
1874             #
1875             sub octchr {
1876 0     0 0 0 my($octdigit) = @_;
1877              
1878 0         0 my @binary = ();
1879 0         0 for my $octal (split(//,$octdigit)) {
1880 0         0 push @binary, {
1881             '0' => '000',
1882             '1' => '001',
1883             '2' => '010',
1884             '3' => '011',
1885             '4' => '100',
1886             '5' => '101',
1887             '6' => '110',
1888             '7' => '111',
1889             }->{$octal};
1890             }
1891 0         0 my $binary = join '', @binary;
1892              
1893 0         0 my $octchr = {
1894             # 1234567
1895             1 => pack('B*', "0000000$binary"),
1896             2 => pack('B*', "000000$binary"),
1897             3 => pack('B*', "00000$binary"),
1898             4 => pack('B*', "0000$binary"),
1899             5 => pack('B*', "000$binary"),
1900             6 => pack('B*', "00$binary"),
1901             7 => pack('B*', "0$binary"),
1902             0 => pack('B*', "$binary"),
1903              
1904             }->{CORE::length($binary) % 8};
1905              
1906 0         0 return $octchr;
1907             }
1908              
1909             #
1910             # KOI8-R hexadecimal escape sequence
1911             #
1912             sub hexchr {
1913 0     0 0 0 my($hexdigit) = @_;
1914              
1915 0         0 my $hexchr = {
1916             1 => pack('H*', "0$hexdigit"),
1917             0 => pack('H*', "$hexdigit"),
1918              
1919             }->{CORE::length($_[0]) % 2};
1920              
1921 0         0 return $hexchr;
1922             }
1923              
1924             #
1925             # KOI8-R open character list for qr
1926             #
1927             sub charlist_qr {
1928              
1929 0     0 0 0 my $modifier = pop @_;
1930 0         0 my @char = @_;
1931              
1932 0         0 my($singleoctet, $multipleoctet) = _charlist(@char, $modifier);
1933 0         0 my @singleoctet = @$singleoctet;
1934 0         0 my @multipleoctet = @$multipleoctet;
1935              
1936             # return character list
1937 0 0       0 if (scalar(@singleoctet) >= 1) {
1938              
1939             # with /i modifier
1940 0 0       0 if ($modifier =~ m/i/oxms) {
1941 0         0 my %singleoctet_ignorecase = ();
1942 0         0 for (@singleoctet) {
1943 0   0     0 while (s/ \A \\x(..) - \\x(..) //oxms or s/ \A \\x((..)) //oxms) {
1944 0         0 for my $ord (hex($1) .. hex($2)) {
1945 0         0 my $char = CORE::chr($ord);
1946 0         0 my $uc = Char::Ekoi8r::uc($char);
1947 0         0 my $fc = Char::Ekoi8r::fc($char);
1948 0 0       0 if ($uc eq $fc) {
1949 0         0 $singleoctet_ignorecase{unpack 'C*', $char} = 1;
1950             }
1951             else {
1952 0 0       0 if (CORE::length($fc) == 1) {
1953 0         0 $singleoctet_ignorecase{unpack 'C*', $uc} = 1;
1954 0         0 $singleoctet_ignorecase{unpack 'C*', $fc} = 1;
1955             }
1956             else {
1957 0         0 $singleoctet_ignorecase{unpack 'C*', $uc} = 1;
1958 0         0 push @multipleoctet, join '', map {sprintf('\x%02X',$_)} unpack 'C*', $fc;
  0         0  
1959             }
1960             }
1961             }
1962             }
1963 0 0       0 if ($_ ne '') {
1964 0         0 $singleoctet_ignorecase{unpack 'C*', $_} = 1;
1965             }
1966             }
1967 0         0 my $i = 0;
1968 0         0 my @singleoctet_ignorecase = ();
1969 0         0 for my $ord (0 .. 255) {
1970 0 0       0 if (exists $singleoctet_ignorecase{$ord}) {
1971 0         0 push @{$singleoctet_ignorecase[$i]}, $ord;
  0         0  
1972             }
1973             else {
1974 0         0 $i++;
1975             }
1976             }
1977 0         0 @singleoctet = ();
1978 0         0 for my $range (@singleoctet_ignorecase) {
1979 0 0       0 if (ref $range) {
1980 0 0       0 if (scalar(@{$range}) == 1) {
  0 0       0  
  0         0  
1981 0         0 push @singleoctet, sprintf('\x%02X', @{$range}[0]);
  0         0  
1982             }
1983             elsif (scalar(@{$range}) == 2) {
1984 0         0 push @singleoctet, sprintf('\x%02X\x%02X', @{$range}[0], @{$range}[-1]);
  0         0  
  0         0  
1985             }
1986             else {
1987 0         0 push @singleoctet, sprintf('\x%02X-\x%02X', @{$range}[0], @{$range}[-1]);
  0         0  
  0         0  
1988             }
1989             }
1990             }
1991             }
1992              
1993 0         0 my $not_anchor = '';
1994              
1995 0         0 push @multipleoctet, join('', $not_anchor, '[', @singleoctet, ']' );
1996             }
1997 0 0       0 if (scalar(@multipleoctet) >= 2) {
1998 0         0 return '(?:' . join('|', @multipleoctet) . ')';
1999             }
2000             else {
2001 0         0 return $multipleoctet[0];
2002             }
2003             }
2004              
2005             #
2006             # KOI8-R open character list for not qr
2007             #
2008             sub charlist_not_qr {
2009              
2010 0     0 0 0 my $modifier = pop @_;
2011 0         0 my @char = @_;
2012              
2013 0         0 my($singleoctet, $multipleoctet) = _charlist(@char, $modifier);
2014 0         0 my @singleoctet = @$singleoctet;
2015 0         0 my @multipleoctet = @$multipleoctet;
2016              
2017             # with /i modifier
2018 0 0       0 if ($modifier =~ m/i/oxms) {
2019 0         0 my %singleoctet_ignorecase = ();
2020 0         0 for (@singleoctet) {
2021 0   0     0 while (s/ \A \\x(..) - \\x(..) //oxms or s/ \A \\x((..)) //oxms) {
2022 0         0 for my $ord (hex($1) .. hex($2)) {
2023 0         0 my $char = CORE::chr($ord);
2024 0         0 my $uc = Char::Ekoi8r::uc($char);
2025 0         0 my $fc = Char::Ekoi8r::fc($char);
2026 0 0       0 if ($uc eq $fc) {
2027 0         0 $singleoctet_ignorecase{unpack 'C*', $char} = 1;
2028             }
2029             else {
2030 0 0       0 if (CORE::length($fc) == 1) {
2031 0         0 $singleoctet_ignorecase{unpack 'C*', $uc} = 1;
2032 0         0 $singleoctet_ignorecase{unpack 'C*', $fc} = 1;
2033             }
2034             else {
2035 0         0 $singleoctet_ignorecase{unpack 'C*', $uc} = 1;
2036 0         0 push @multipleoctet, join '', map {sprintf('\x%02X',$_)} unpack 'C*', $fc;
  0         0  
2037             }
2038             }
2039             }
2040             }
2041 0 0       0 if ($_ ne '') {
2042 0         0 $singleoctet_ignorecase{unpack 'C*', $_} = 1;
2043             }
2044             }
2045 0         0 my $i = 0;
2046 0         0 my @singleoctet_ignorecase = ();
2047 0         0 for my $ord (0 .. 255) {
2048 0 0       0 if (exists $singleoctet_ignorecase{$ord}) {
2049 0         0 push @{$singleoctet_ignorecase[$i]}, $ord;
  0         0  
2050             }
2051             else {
2052 0         0 $i++;
2053             }
2054             }
2055 0         0 @singleoctet = ();
2056 0         0 for my $range (@singleoctet_ignorecase) {
2057 0 0       0 if (ref $range) {
2058 0 0       0 if (scalar(@{$range}) == 1) {
  0 0       0  
  0         0  
2059 0         0 push @singleoctet, sprintf('\x%02X', @{$range}[0]);
  0         0  
2060             }
2061             elsif (scalar(@{$range}) == 2) {
2062 0         0 push @singleoctet, sprintf('\x%02X\x%02X', @{$range}[0], @{$range}[-1]);
  0         0  
  0         0  
2063             }
2064             else {
2065 0         0 push @singleoctet, sprintf('\x%02X-\x%02X', @{$range}[0], @{$range}[-1]);
  0         0  
  0         0  
2066             }
2067             }
2068             }
2069             }
2070              
2071             # return character list
2072 0 0       0 if (scalar(@multipleoctet) >= 1) {
2073 0 0       0 if (scalar(@singleoctet) >= 1) {
2074              
2075             # any character other than multiple-octet and single octet character class
2076 0         0 return '(?!' . join('|', @multipleoctet) . ')(?:[^' . join('', @singleoctet) . '])';
2077             }
2078             else {
2079              
2080             # any character other than multiple-octet character class
2081 0         0 return '(?!' . join('|', @multipleoctet) . ")(?:$your_char)";
2082             }
2083             }
2084             else {
2085 0 0       0 if (scalar(@singleoctet) >= 1) {
2086              
2087             # any character other than single octet character class
2088 0         0 return '(?:[^' . join('', @singleoctet) . '])';
2089             }
2090             else {
2091              
2092             # any character
2093 0         0 return "(?:$your_char)";
2094             }
2095             }
2096             }
2097              
2098             #
2099             # open file in read mode
2100             #
2101             sub _open_r {
2102 197     197   633 my(undef,$file) = @_;
2103 197         976 $file =~ s#\A (\s) #./$1#oxms;
2104 197   33     24090 return CORE::eval(q{open($_[0],'<',$_[1])}) ||
2105             open($_[0],"< $file\0");
2106             }
2107              
2108             #
2109             # open file in write mode
2110             #
2111             sub _open_w {
2112 0     0   0 my(undef,$file) = @_;
2113 0         0 $file =~ s#\A (\s) #./$1#oxms;
2114 0   0     0 return CORE::eval(q{open($_[0],'>',$_[1])}) ||
2115             open($_[0],"> $file\0");
2116             }
2117              
2118             #
2119             # open file in append mode
2120             #
2121             sub _open_a {
2122 0     0   0 my(undef,$file) = @_;
2123 0         0 $file =~ s#\A (\s) #./$1#oxms;
2124 0   0     0 return CORE::eval(q{open($_[0],'>>',$_[1])}) ||
2125             open($_[0],">> $file\0");
2126             }
2127              
2128             #
2129             # safe system
2130             #
2131             sub _systemx {
2132              
2133             # P.707 29.2.33. exec
2134             # in Chapter 29: Functions
2135             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
2136             #
2137             # Be aware that in older releases of Perl, exec (and system) did not flush
2138             # your output buffer, so you needed to enable command buffering by setting $|
2139             # on one or more filehandles to avoid lost output in the case of exec, or
2140             # misordererd output in the case of system. This situation was largely remedied
2141             # in the 5.6 release of Perl. (So, 5.005 release not yet.)
2142              
2143             # P.855 exec
2144             # in Chapter 27: Functions
2145             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
2146             #
2147             # In very old release of Perl (before v5.6), exec (and system) did not flush
2148             # your output buffer, so you needed to enable command buffering by setting $|
2149             # on one or more filehandles to avoid lost output with exec or misordered
2150             # output with system.
2151              
2152 197     197   708 $| = 1;
2153              
2154             # P.565 23.1.2. Cleaning Up Your Environment
2155             # in Chapter 23: Security
2156             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
2157              
2158             # P.656 Cleaning Up Your Environment
2159             # in Chapter 20: Security
2160             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
2161              
2162             # local $ENV{'PATH'} = '.';
2163 197         2215 local @ENV{qw(IFS CDPATH ENV BASH_ENV)}; # Make %ENV safer
2164              
2165             # P.707 29.2.33. exec
2166             # in Chapter 29: Functions
2167             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
2168             #
2169             # As we mentioned earlier, exec treats a discrete list of arguments as an
2170             # indication that it should bypass shell processing. However, there is one
2171             # place where you might still get tripped up. The exec call (and system, too)
2172             # will not distinguish between a single scalar argument and an array containing
2173             # only one element.
2174             #
2175             # @args = ("echo surprise"); # just one element in list
2176             # exec @args # still subject to shell escapes
2177             # or die "exec: $!"; # because @args == 1
2178             #
2179             # To avoid this, you can use the PATHNAME syntax, explicitly duplicating the
2180             # first argument as the pathname, which forces the rest of the arguments to be
2181             # interpreted as a list, even if there is only one of them:
2182             #
2183             # exec { $args[0] } @args # safe even with one-argument list
2184             # or die "can't exec @args: $!";
2185              
2186             # P.855 exec
2187             # in Chapter 27: Functions
2188             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
2189             #
2190             # As we mentioned earlier, exec treats a discrete list of arguments as a
2191             # directive to bypass shell processing. However, there is one place where
2192             # you might still get tripped up. The exec call (and system, too) cannot
2193             # distinguish between a single scalar argument and an array containing
2194             # only one element.
2195             #
2196             # @args = ("echo surprise"); # just one element in list
2197             # exec @args # still subject to shell escapes
2198             # || die "exec: $!"; # because @args == 1
2199             #
2200             # To avoid this, use the PATHNAME syntax, explicitly duplicating the first
2201             # argument as the pathname, which forces the rest of the arguments to be
2202             # interpreted as a list, even if there is only one of them:
2203             #
2204             # exec { $args[0] } @args # safe even with one-argument list
2205             # || die "can't exec @args: $!";
2206              
2207 197         465 return CORE::system { $_[0] } @_; # safe even with one-argument list
  197         24136893  
2208             }
2209              
2210             #
2211             # KOI8-R order to character (with parameter)
2212             #
2213             sub Char::Ekoi8r::chr(;$) {
2214              
2215 0 0   0 0   my $c = @_ ? $_[0] : $_;
2216              
2217 0 0         if ($c == 0x00) {
2218 0           return "\x00";
2219             }
2220             else {
2221 0           my @chr = ();
2222 0           while ($c > 0) {
2223 0           unshift @chr, ($c % 0x100);
2224 0           $c = int($c / 0x100);
2225             }
2226 0           return pack 'C*', @chr;
2227             }
2228             }
2229              
2230             #
2231             # KOI8-R order to character (without parameter)
2232             #
2233             sub Char::Ekoi8r::chr_() {
2234              
2235 0     0 0   my $c = $_;
2236              
2237 0 0         if ($c == 0x00) {
2238 0           return "\x00";
2239             }
2240             else {
2241 0           my @chr = ();
2242 0           while ($c > 0) {
2243 0           unshift @chr, ($c % 0x100);
2244 0           $c = int($c / 0x100);
2245             }
2246 0           return pack 'C*', @chr;
2247             }
2248             }
2249              
2250             #
2251             # KOI8-R path globbing (with parameter)
2252             #
2253             sub Char::Ekoi8r::glob($) {
2254              
2255 0 0   0 0   if (wantarray) {
2256 0           my @glob = _DOS_like_glob(@_);
2257 0           for my $glob (@glob) {
2258 0           $glob =~ s{ \A (?:\./)+ }{}oxms;
2259             }
2260 0           return @glob;
2261             }
2262             else {
2263 0           my $glob = _DOS_like_glob(@_);
2264 0           $glob =~ s{ \A (?:\./)+ }{}oxms;
2265 0           return $glob;
2266             }
2267             }
2268              
2269             #
2270             # KOI8-R path globbing (without parameter)
2271             #
2272             sub Char::Ekoi8r::glob_() {
2273              
2274 0 0   0 0   if (wantarray) {
2275 0           my @glob = _DOS_like_glob();
2276 0           for my $glob (@glob) {
2277 0           $glob =~ s{ \A (?:\./)+ }{}oxms;
2278             }
2279 0           return @glob;
2280             }
2281             else {
2282 0           my $glob = _DOS_like_glob();
2283 0           $glob =~ s{ \A (?:\./)+ }{}oxms;
2284 0           return $glob;
2285             }
2286             }
2287              
2288             #
2289             # KOI8-R path globbing via File::DosGlob 1.10
2290             #
2291             # Often I confuse "_dosglob" and "_doglob".
2292             # So, I renamed "_dosglob" to "_DOS_like_glob".
2293             #
2294             my %iter;
2295             my %entries;
2296             sub _DOS_like_glob {
2297              
2298             # context (keyed by second cxix argument provided by core)
2299 0     0     my($expr,$cxix) = @_;
2300              
2301             # glob without args defaults to $_
2302 0 0         $expr = $_ if not defined $expr;
2303              
2304             # represents the current user's home directory
2305             #
2306             # 7.3. Expanding Tildes in Filenames
2307             # in Chapter 7. File Access
2308             # of ISBN 0-596-00313-7 Perl Cookbook, 2nd Edition.
2309             #
2310             # and File::HomeDir, File::HomeDir::Windows module
2311              
2312             # DOS-like system
2313 0 0         if ($^O =~ /\A (?: MSWin32 | NetWare | symbian | dos ) \z/oxms) {
2314 0           $expr =~ s{ \A ~ (?= [^/\\] ) }
2315 0           { my_home_MSWin32() }oxmse;
2316             }
2317              
2318             # UNIX-like system
2319             else {
2320 0           $expr =~ s{ \A ~ ( (?:[^/])* ) }
2321 0 0 0       { $1 ? (CORE::eval(q{(getpwnam($1))[7]})||my_home()) : my_home() }oxmse;
2322             }
2323              
2324             # assume global context if not provided one
2325 0 0         $cxix = '_G_' if not defined $cxix;
2326 0 0         $iter{$cxix} = 0 if not exists $iter{$cxix};
2327              
2328             # if we're just beginning, do it all first
2329 0 0         if ($iter{$cxix} == 0) {
2330 0           $entries{$cxix} = [ _do_glob(1, _parse_line($expr)) ];
2331             }
2332              
2333             # chuck it all out, quick or slow
2334 0 0         if (wantarray) {
2335 0           delete $iter{$cxix};
2336 0           return @{delete $entries{$cxix}};
  0            
2337             }
2338             else {
2339 0 0         if ($iter{$cxix} = scalar @{$entries{$cxix}}) {
  0            
2340 0           return shift @{$entries{$cxix}};
  0            
2341             }
2342             else {
2343             # return undef for EOL
2344 0           delete $iter{$cxix};
2345 0           delete $entries{$cxix};
2346 0           return undef;
2347             }
2348             }
2349             }
2350              
2351             #
2352             # KOI8-R path globbing subroutine
2353             #
2354             sub _do_glob {
2355              
2356 0     0     my($cond,@expr) = @_;
2357 0           my @glob = ();
2358 0           my $fix_drive_relative_paths = 0;
2359              
2360             OUTER:
2361 0           for my $expr (@expr) {
2362 0 0         next OUTER if not defined $expr;
2363 0 0         next OUTER if $expr eq '';
2364              
2365 0           my @matched = ();
2366 0           my @globdir = ();
2367 0           my $head = '.';
2368 0           my $pathsep = '/';
2369 0           my $tail;
2370              
2371             # if argument is within quotes strip em and do no globbing
2372 0 0         if ($expr =~ /\A " ((?:$q_char)*) " \z/oxms) {
2373 0           $expr = $1;
2374 0 0         if ($cond eq 'd') {
2375 0 0         if (-d $expr) {
2376 0           push @glob, $expr;
2377             }
2378             }
2379             else {
2380 0 0         if (-e $expr) {
2381 0           push @glob, $expr;
2382             }
2383             }
2384 0           next OUTER;
2385             }
2386              
2387             # wildcards with a drive prefix such as h:*.pm must be changed
2388             # to h:./*.pm to expand correctly
2389 0 0         if ($^O =~ /\A (?: MSWin32 | NetWare | symbian | dos ) \z/oxms) {
2390 0 0         if ($expr =~ s# \A ((?:[A-Za-z]:)?) ([^/\\]) #$1./$2#oxms) {
2391 0           $fix_drive_relative_paths = 1;
2392             }
2393             }
2394              
2395 0 0         if (($head, $tail) = _parse_path($expr,$pathsep)) {
2396 0 0         if ($tail eq '') {
2397 0           push @glob, $expr;
2398 0           next OUTER;
2399             }
2400 0 0         if ($head =~ / \A (?:$q_char)*? [*?] /oxms) {
2401 0 0         if (@globdir = _do_glob('d', $head)) {
2402 0           push @glob, _do_glob($cond, map {"$_$pathsep$tail"} @globdir);
  0            
2403 0           next OUTER;
2404             }
2405             }
2406 0 0 0       if ($head eq '' or $head =~ /\A [A-Za-z]: \z/oxms) {
2407 0           $head .= $pathsep;
2408             }
2409 0           $expr = $tail;
2410             }
2411              
2412             # If file component has no wildcards, we can avoid opendir
2413 0 0         if ($expr !~ / \A (?:$q_char)*? [*?] /oxms) {
2414 0 0         if ($head eq '.') {
2415 0           $head = '';
2416             }
2417 0 0 0       if ($head ne '' and ($head =~ / \G ($q_char) /oxmsg)[-1] ne $pathsep) {
2418 0           $head .= $pathsep;
2419             }
2420 0           $head .= $expr;
2421 0 0         if ($cond eq 'd') {
2422 0 0         if (-d $head) {
2423 0           push @glob, $head;
2424             }
2425             }
2426             else {
2427 0 0         if (-e $head) {
2428 0           push @glob, $head;
2429             }
2430             }
2431 0           next OUTER;
2432             }
2433 0 0         opendir(*DIR, $head) or next OUTER;
2434 0           my @leaf = readdir DIR;
2435 0           closedir DIR;
2436              
2437 0 0         if ($head eq '.') {
2438 0           $head = '';
2439             }
2440 0 0 0       if ($head ne '' and ($head =~ / \G ($q_char) /oxmsg)[-1] ne $pathsep) {
2441 0           $head .= $pathsep;
2442             }
2443              
2444 0           my $pattern = '';
2445 0           while ($expr =~ / \G ($q_char) /oxgc) {
2446 0           my $char = $1;
2447              
2448             # 6.9. Matching Shell Globs as Regular Expressions
2449             # in Chapter 6. Pattern Matching
2450             # of ISBN 0-596-00313-7 Perl Cookbook, 2nd Edition.
2451             # (and so on)
2452              
2453 0 0         if ($char eq '*') {
    0          
    0          
2454 0           $pattern .= "(?:$your_char)*",
2455             }
2456             elsif ($char eq '?') {
2457 0           $pattern .= "(?:$your_char)?", # DOS style
2458             # $pattern .= "(?:$your_char)", # UNIX style
2459             }
2460             elsif ((my $fc = Char::Ekoi8r::fc($char)) ne $char) {
2461 0           $pattern .= $fc;
2462             }
2463             else {
2464 0           $pattern .= quotemeta $char;
2465             }
2466             }
2467 0     0     my $matchsub = sub { Char::Ekoi8r::fc($_[0]) =~ /\A $pattern \z/xms };
  0            
2468              
2469             # if ($@) {
2470             # print STDERR "$0: $@\n";
2471             # next OUTER;
2472             # }
2473              
2474             INNER:
2475 0           for my $leaf (@leaf) {
2476 0 0 0       if ($leaf eq '.' or $leaf eq '..') {
2477 0           next INNER;
2478             }
2479 0 0 0       if ($cond eq 'd' and not -d "$head$leaf") {
2480 0           next INNER;
2481             }
2482              
2483 0 0         if (&$matchsub($leaf)) {
2484 0           push @matched, "$head$leaf";
2485 0           next INNER;
2486             }
2487              
2488             # [DOS compatibility special case]
2489             # Failed, add a trailing dot and try again, but only...
2490              
2491 0 0 0       if (Char::Ekoi8r::index($leaf,'.') == -1 and # if name does not have a dot in it *and*
      0        
2492             CORE::length($leaf) <= 8 and # name is shorter than or equal to 8 chars *and*
2493             Char::Ekoi8r::index($pattern,'\\.') != -1 # pattern has a dot.
2494             ) {
2495 0 0         if (&$matchsub("$leaf.")) {
2496 0           push @matched, "$head$leaf";
2497 0           next INNER;
2498             }
2499             }
2500             }
2501 0 0         if (@matched) {
2502 0           push @glob, @matched;
2503             }
2504             }
2505 0 0         if ($fix_drive_relative_paths) {
2506 0           for my $glob (@glob) {
2507 0           $glob =~ s# \A ([A-Za-z]:) \./ #$1#oxms;
2508             }
2509             }
2510 0           return @glob;
2511             }
2512              
2513             #
2514             # KOI8-R parse line
2515             #
2516             sub _parse_line {
2517              
2518 0     0     my($line) = @_;
2519              
2520 0           $line .= ' ';
2521 0           my @piece = ();
2522 0           while ($line =~ /
2523             " ( (?: [^"] )* ) " \s+ |
2524             ( (?: [^"\s] )* ) \s+
2525             /oxmsg
2526             ) {
2527 0 0         push @piece, defined($1) ? $1 : $2;
2528             }
2529 0           return @piece;
2530             }
2531              
2532             #
2533             # KOI8-R parse path
2534             #
2535             sub _parse_path {
2536              
2537 0     0     my($path,$pathsep) = @_;
2538              
2539 0           $path .= '/';
2540 0           my @subpath = ();
2541 0           while ($path =~ /
2542             ((?: [^\/\\] )+?) [\/\\]
2543             /oxmsg
2544             ) {
2545 0           push @subpath, $1;
2546             }
2547              
2548 0           my $tail = pop @subpath;
2549 0           my $head = join $pathsep, @subpath;
2550 0           return $head, $tail;
2551             }
2552              
2553             #
2554             # via File::HomeDir::Windows 1.00
2555             #
2556             sub my_home_MSWin32 {
2557              
2558             # A lot of unix people and unix-derived tools rely on
2559             # the ability to overload HOME. We will support it too
2560             # so that they can replace raw HOME calls with File::HomeDir.
2561 0 0 0 0 0   if (exists $ENV{'HOME'} and $ENV{'HOME'}) {
    0 0        
    0 0        
      0        
      0        
2562 0           return $ENV{'HOME'};
2563             }
2564              
2565             # Do we have a user profile?
2566             elsif (exists $ENV{'USERPROFILE'} and $ENV{'USERPROFILE'}) {
2567 0           return $ENV{'USERPROFILE'};
2568             }
2569              
2570             # Some Windows use something like $ENV{'HOME'}
2571             elsif (exists $ENV{'HOMEDRIVE'} and exists $ENV{'HOMEPATH'} and $ENV{'HOMEDRIVE'} and $ENV{'HOMEPATH'}) {
2572 0           return join '', $ENV{'HOMEDRIVE'}, $ENV{'HOMEPATH'};
2573             }
2574              
2575 0           return undef;
2576             }
2577              
2578             #
2579             # via File::HomeDir::Unix 1.00
2580             #
2581             sub my_home {
2582 0     0 0   my $home;
2583              
2584 0 0 0       if (exists $ENV{'HOME'} and defined $ENV{'HOME'}) {
    0 0        
2585 0           $home = $ENV{'HOME'};
2586             }
2587              
2588             # This is from the original code, but I'm guessing
2589             # it means "login directory" and exists on some Unixes.
2590             elsif (exists $ENV{'LOGDIR'} and $ENV{'LOGDIR'}) {
2591 0           $home = $ENV{'LOGDIR'};
2592             }
2593              
2594             ### More-desperate methods
2595              
2596             # Light desperation on any (Unixish) platform
2597             else {
2598 0           $home = CORE::eval q{ (getpwuid($<))[7] };
2599             }
2600              
2601             # On Unix in general, a non-existant home means "no home"
2602             # For example, "nobody"-like users might use /nonexistant
2603 0 0 0       if (defined $home and ! -d($home)) {
2604 0           $home = undef;
2605             }
2606 0           return $home;
2607             }
2608              
2609             #
2610             # ${^PREMATCH}, $PREMATCH, $` the string preceding what was matched
2611             #
2612             sub Char::Ekoi8r::PREMATCH {
2613 0     0 0   return $`;
2614             }
2615              
2616             #
2617             # ${^MATCH}, $MATCH, $& the string that matched
2618             #
2619             sub Char::Ekoi8r::MATCH {
2620 0     0 0   return $&;
2621             }
2622              
2623             #
2624             # ${^POSTMATCH}, $POSTMATCH, $' the string following what was matched
2625             #
2626             sub Char::Ekoi8r::POSTMATCH {
2627 0     0 0   return $';
2628             }
2629              
2630             #
2631             # KOI8-R character to order (with parameter)
2632             #
2633             sub Char::KOI8R::ord(;$) {
2634              
2635 0 0   0 1   local $_ = shift if @_;
2636              
2637 0 0         if (/\A ($q_char) /oxms) {
2638 0           my @ord = unpack 'C*', $1;
2639 0           my $ord = 0;
2640 0           while (my $o = shift @ord) {
2641 0           $ord = $ord * 0x100 + $o;
2642             }
2643 0           return $ord;
2644             }
2645             else {
2646 0           return CORE::ord $_;
2647             }
2648             }
2649              
2650             #
2651             # KOI8-R character to order (without parameter)
2652             #
2653             sub Char::KOI8R::ord_() {
2654              
2655 0 0   0 0   if (/\A ($q_char) /oxms) {
2656 0           my @ord = unpack 'C*', $1;
2657 0           my $ord = 0;
2658 0           while (my $o = shift @ord) {
2659 0           $ord = $ord * 0x100 + $o;
2660             }
2661 0           return $ord;
2662             }
2663             else {
2664 0           return CORE::ord $_;
2665             }
2666             }
2667              
2668             #
2669             # KOI8-R reverse
2670             #
2671             sub Char::KOI8R::reverse(@) {
2672              
2673 0 0   0 0   if (wantarray) {
2674 0           return CORE::reverse @_;
2675             }
2676             else {
2677              
2678             # One of us once cornered Larry in an elevator and asked him what
2679             # problem he was solving with this, but he looked as far off into
2680             # the distance as he could in an elevator and said, "It seemed like
2681             # a good idea at the time."
2682              
2683 0           return join '', CORE::reverse(join('',@_) =~ /\G ($q_char) /oxmsg);
2684             }
2685             }
2686              
2687             #
2688             # KOI8-R getc (with parameter, without parameter)
2689             #
2690             sub Char::KOI8R::getc(;*@) {
2691              
2692 0     0 0   my($package) = caller;
2693 0 0         my $fh = @_ ? qualify_to_ref(shift,$package) : \*STDIN;
2694 0 0 0       croak 'Too many arguments for Char::KOI8R::getc' if @_ and not wantarray;
2695              
2696 0           my @length = sort { $a <=> $b } keys %range_tr;
  0            
2697 0           my $getc = '';
2698 0           for my $length ($length[0] .. $length[-1]) {
2699 0           $getc .= CORE::getc($fh);
2700 0 0         if (exists $range_tr{CORE::length($getc)}) {
2701 0 0         if ($getc =~ /\A ${Char::Ekoi8r::dot_s} \z/oxms) {
2702 0 0         return wantarray ? ($getc,@_) : $getc;
2703             }
2704             }
2705             }
2706 0 0         return wantarray ? ($getc,@_) : $getc;
2707             }
2708              
2709             #
2710             # KOI8-R length by character
2711             #
2712             sub Char::KOI8R::length(;$) {
2713              
2714 0 0   0 1   local $_ = shift if @_;
2715              
2716 0           local @_ = /\G ($q_char) /oxmsg;
2717 0           return scalar @_;
2718             }
2719              
2720             #
2721             # KOI8-R substr by character
2722             #
2723             BEGIN {
2724              
2725             # P.232 The lvalue Attribute
2726             # in Chapter 6: Subroutines
2727             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
2728              
2729             # P.336 The lvalue Attribute
2730             # in Chapter 7: Subroutines
2731             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
2732              
2733             # P.144 8.4 Lvalue subroutines
2734             # in Chapter 8: perlsub: Perl subroutines
2735             # of ISBN-13: 978-1-906966-02-7 The Perl Language Reference Manual (for Perl version 5.12.1)
2736              
2737 197 50 0 197 1 185926 CORE::eval sprintf(<<'END', ($] >= 5.014000) ? ':lvalue' : '');
  0 0   0      
  0 0          
  0 0          
  0 0          
  0 0          
  0 0          
  0 0          
  0 0          
  0 0          
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
2738             # vv----------------*******
2739             sub Char::KOI8R::substr($$;$$) %s {
2740              
2741             my @char = $_[0] =~ /\G ($q_char) /oxmsg;
2742              
2743             # If the substring is beyond either end of the string, substr() returns the undefined
2744             # value and produces a warning. When used as an lvalue, specifying a substring that
2745             # is entirely outside the string raises an exception.
2746             # http://perldoc.perl.org/functions/substr.html
2747              
2748             # A return with no argument returns the scalar value undef in scalar context,
2749             # an empty list () in list context, and (naturally) nothing at all in void
2750             # context.
2751              
2752             my $offset = $_[1];
2753             if (($offset > scalar(@char)) or ($offset < (-1 * scalar(@char)))) {
2754             return;
2755             }
2756              
2757             # substr($string,$offset,$length,$replacement)
2758             if (@_ == 4) {
2759             my(undef,undef,$length,$replacement) = @_;
2760             my $substr = join '', splice(@char, $offset, $length, $replacement);
2761             $_[0] = join '', @char;
2762              
2763             # return $substr; this doesn't work, don't say "return"
2764             $substr;
2765             }
2766              
2767             # substr($string,$offset,$length)
2768             elsif (@_ == 3) {
2769             my(undef,undef,$length) = @_;
2770             my $octet_offset = 0;
2771             my $octet_length = 0;
2772             if ($offset == 0) {
2773             $octet_offset = 0;
2774             }
2775             elsif ($offset > 0) {
2776             $octet_offset = CORE::length(join '', @char[0..$offset-1]);
2777             }
2778             else {
2779             $octet_offset = -1 * CORE::length(join '', @char[$#char+$offset+1..$#char]);
2780             }
2781             if ($length == 0) {
2782             $octet_length = 0;
2783             }
2784             elsif ($length > 0) {
2785             $octet_length = CORE::length(join '', @char[$offset..$offset+$length-1]);
2786             }
2787             else {
2788             $octet_length = -1 * CORE::length(join '', @char[$#char+$length+1..$#char]);
2789             }
2790             CORE::substr($_[0], $octet_offset, $octet_length);
2791             }
2792              
2793             # substr($string,$offset)
2794             else {
2795             my $octet_offset = 0;
2796             if ($offset == 0) {
2797             $octet_offset = 0;
2798             }
2799             elsif ($offset > 0) {
2800             $octet_offset = CORE::length(join '', @char[0..$offset-1]);
2801             }
2802             else {
2803             $octet_offset = -1 * CORE::length(join '', @char[$#char+$offset+1..$#char]);
2804             }
2805             CORE::substr($_[0], $octet_offset);
2806             }
2807             }
2808             END
2809             }
2810              
2811             #
2812             # KOI8-R index by character
2813             #
2814             sub Char::KOI8R::index($$;$) {
2815              
2816 0     0 1   my $index;
2817 0 0         if (@_ == 3) {
2818 0           $index = Char::Ekoi8r::index($_[0], $_[1], CORE::length(Char::KOI8R::substr($_[0], 0, $_[2])));
2819             }
2820             else {
2821 0           $index = Char::Ekoi8r::index($_[0], $_[1]);
2822             }
2823              
2824 0 0         if ($index == -1) {
2825 0           return -1;
2826             }
2827             else {
2828 0           return Char::KOI8R::length(CORE::substr $_[0], 0, $index);
2829             }
2830             }
2831              
2832             #
2833             # KOI8-R rindex by character
2834             #
2835             sub Char::KOI8R::rindex($$;$) {
2836              
2837 0     0 1   my $rindex;
2838 0 0         if (@_ == 3) {
2839 0           $rindex = Char::Ekoi8r::rindex($_[0], $_[1], CORE::length(Char::KOI8R::substr($_[0], 0, $_[2])));
2840             }
2841             else {
2842 0           $rindex = Char::Ekoi8r::rindex($_[0], $_[1]);
2843             }
2844              
2845 0 0         if ($rindex == -1) {
2846 0           return -1;
2847             }
2848             else {
2849 0           return Char::KOI8R::length(CORE::substr $_[0], 0, $rindex);
2850             }
2851             }
2852              
2853             # when 'm//', '/' means regexp match 'm//' and '?' means regexp match '??'
2854             # when 'div', '/' means division operator and '?' means conditional operator (condition ? then : else)
2855 197     197   16712 BEGIN { CORE::eval q{ use vars qw($slash) } } $slash = 'm//';
  197     197   2029  
  197         420  
  197         16443  
2856              
2857             # ord() to ord() or Char::KOI8R::ord()
2858 197     197   14437 BEGIN { CORE::eval q{ use vars qw($function_ord) } } $function_ord = 'ord';
  197     197   1316  
  197         438  
  197         12364  
2859              
2860             # ord to ord or Char::KOI8R::ord_
2861 197     197   11814 BEGIN { CORE::eval q{ use vars qw($function_ord_) } } $function_ord_ = 'ord';
  197     197   1578  
  197         518  
  197         12921  
2862              
2863             # reverse to reverse or Char::KOI8R::reverse
2864 197     197   12621 BEGIN { CORE::eval q{ use vars qw($function_reverse) } } $function_reverse = 'reverse';
  197     197   1094  
  197         459  
  197         12574  
2865              
2866             # getc to getc or Char::KOI8R::getc
2867 197     197   13731 BEGIN { CORE::eval q{ use vars qw($function_getc) } } $function_getc = 'getc';
  197     197   5178  
  197         579  
  197         20945  
2868              
2869             # P.1023 Appendix W.9 Multibyte Anchoring
2870             # of ISBN 1-56592-224-7 CJKV Information Processing
2871              
2872             my $anchor = '';
2873              
2874 197     197   13154 BEGIN { CORE::eval q{ use vars qw($nest) } }
  197     197   1174  
  197         389  
  197         12566935  
2875              
2876             # regexp of nested parens in qqXX
2877              
2878             # P.340 Matching Nested Constructs with Embedded Code
2879             # in Chapter 7: Perl
2880             # of ISBN 0-596-00289-0 Mastering Regular Expressions, Second edition
2881              
2882             my $qq_paren = qr{(?{local $nest=0}) (?>(?:
2883             \\c[\x40-\x5F] |
2884             \\ [\x00-\xFF] |
2885             [^()] |
2886             \( (?{$nest++}) |
2887             \) (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!))
2888             }xms;
2889             my $qq_brace = qr{(?{local $nest=0}) (?>(?:
2890             \\c[\x40-\x5F] |
2891             \\ [\x00-\xFF] |
2892             [^{}] |
2893             \{ (?{$nest++}) |
2894             \} (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!))
2895             }xms;
2896             my $qq_bracket = qr{(?{local $nest=0}) (?>(?:
2897             \\c[\x40-\x5F] |
2898             \\ [\x00-\xFF] |
2899             [^[\]] |
2900             \[ (?{$nest++}) |
2901             \] (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!))
2902             }xms;
2903             my $qq_angle = qr{(?{local $nest=0}) (?>(?:
2904             \\c[\x40-\x5F] |
2905             \\ [\x00-\xFF] |
2906             [^<>] |
2907             \< (?{$nest++}) |
2908             \> (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!))
2909             }xms;
2910             my $qq_scalar = qr{(?: \{ (?:$qq_brace)*? \} |
2911             (?: ::)? (?:
2912             [a-zA-Z_][a-zA-Z_0-9]*
2913             (?: ::[a-zA-Z_][a-zA-Z_0-9]* )* (?: \[ (?: \$\[ | \$\] | $qq_char )*? \] | \{ (?:$qq_brace)*? \} )*
2914             (?: (?: -> )? (?: [\$\@\%\&\*]\* | \$\#\* | [\@\%]? \[ (?: \$\[ | \$\] | $qq_char )*? \] | [\@\%\*]? \{ (?:$qq_brace)*? \} ) )*
2915             ))
2916             }xms;
2917             my $qq_variable = qr{(?: \{ (?:$qq_brace)*? \} |
2918             (?: ::)? (?:
2919             [0-9]+ |
2920             [^a-zA-Z_0-9\[\]] |
2921             ^[A-Z] |
2922             [a-zA-Z_][a-zA-Z_0-9]*
2923             (?: ::[a-zA-Z_][a-zA-Z_0-9]* )* (?: \[ (?: \$\[ | \$\] | $qq_char )*? \] | \{ (?:$qq_brace)*? \} )*
2924             (?: (?: -> )? (?: [\$\@\%\&\*]\* | \$\#\* | [\@\%]? \[ (?: \$\[ | \$\] | $qq_char )*? \] | [\@\%\*]? \{ (?:$qq_brace)*? \} ) )*
2925             ))
2926             }xms;
2927             my $qq_substr = qr{(?: Char::KOI8R::substr | CORE::substr | substr ) \( $qq_paren \)
2928             }xms;
2929              
2930             # regexp of nested parens in qXX
2931             my $q_paren = qr{(?{local $nest=0}) (?>(?:
2932             [^()] |
2933             \( (?{$nest++}) |
2934             \) (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!))
2935             }xms;
2936             my $q_brace = qr{(?{local $nest=0}) (?>(?:
2937             [^{}] |
2938             \{ (?{$nest++}) |
2939             \} (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!))
2940             }xms;
2941             my $q_bracket = qr{(?{local $nest=0}) (?>(?:
2942             [^[\]] |
2943             \[ (?{$nest++}) |
2944             \] (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!))
2945             }xms;
2946             my $q_angle = qr{(?{local $nest=0}) (?>(?:
2947             [^<>] |
2948             \< (?{$nest++}) |
2949             \> (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!))
2950             }xms;
2951              
2952             my $matched = '';
2953             my $s_matched = '';
2954              
2955             my $tr_variable = ''; # variable of tr///
2956             my $sub_variable = ''; # variable of s///
2957             my $bind_operator = ''; # =~ or !~
2958              
2959             my @heredoc = (); # here document
2960             my @heredoc_delimiter = ();
2961             my $here_script = ''; # here script
2962              
2963             #
2964             # escape KOI8-R script
2965             #
2966             sub Char::KOI8R::escape(;$) {
2967 0 0   0 0   local($_) = $_[0] if @_;
2968              
2969             # P.359 The Study Function
2970             # in Chapter 7: Perl
2971             # of ISBN 0-596-00289-0 Mastering Regular Expressions, Second edition
2972              
2973 0           study $_; # Yes, I studied study yesterday.
2974              
2975             # while all script
2976              
2977             # 6.14. Matching from Where the Last Pattern Left Off
2978             # in Chapter 6. Pattern Matching
2979             # of ISBN 0-596-00313-7 Perl Cookbook, 2nd Edition.
2980             # (and so on)
2981              
2982             # one member of Tag-team
2983             #
2984             # P.128 Start of match (or end of previous match): \G
2985             # P.130 Advanced Use of \G with Perl
2986             # in Chapter 3: Overview of Regular Expression Features and Flavors
2987             # P.255 Use leading anchors
2988             # P.256 Expose ^ and \G at the front expressions
2989             # in Chapter 6: Crafting an Efficient Expression
2990             # P.315 "Tag-team" matching with /gc
2991             # in Chapter 7: Perl
2992             # of ISBN 0-596-00289-0 Mastering Regular Expressions, Second edition
2993              
2994 0           my $e_script = '';
2995 0           while (not /\G \z/oxgc) { # member
2996 0           $e_script .= Char::KOI8R::escape_token();
2997             }
2998              
2999 0           return $e_script;
3000             }
3001              
3002             #
3003             # escape KOI8-R token of script
3004             #
3005             sub Char::KOI8R::escape_token {
3006              
3007             # \n output here document
3008              
3009 0     0 0   my $ignore_modules = join('|', qw(
3010             utf8
3011             bytes
3012             charnames
3013             I18N::Japanese
3014             I18N::Collate
3015             I18N::JExt
3016             File::DosGlob
3017             Wild
3018             Wildcard
3019             Japanese
3020             ));
3021              
3022             # another member of Tag-team
3023             #
3024             # P.315 "Tag-team" matching with /gc
3025             # in Chapter 7: Perl
3026             # of ISBN 0-596-00289-0 Mastering Regular Expressions, Second edition
3027              
3028 0 0 0       if (/\G ( \n ) /oxgc) { # another member (and so on)
    0 0        
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
3029 0           my $heredoc = '';
3030 0 0         if (scalar(@heredoc_delimiter) >= 1) {
3031 0           $slash = 'm//';
3032              
3033 0           $heredoc = join '', @heredoc;
3034 0           @heredoc = ();
3035              
3036             # skip here document
3037 0           for my $heredoc_delimiter (@heredoc_delimiter) {
3038 0           /\G .*? \n $heredoc_delimiter \n/xmsgc;
3039             }
3040 0           @heredoc_delimiter = ();
3041              
3042 0           $here_script = '';
3043             }
3044 0           return "\n" . $heredoc;
3045             }
3046              
3047             # ignore space, comment
3048 0           elsif (/\G (\s+|\#.*) /oxgc) { return $1; }
3049              
3050             # if (, elsif (, unless (, while (, until (, given (, and when (
3051              
3052             # given, when
3053              
3054             # P.225 The given Statement
3055             # in Chapter 15: Smart Matching and given-when
3056             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
3057              
3058             # P.133 The given Statement
3059             # in Chapter 4: Statements and Declarations
3060             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
3061              
3062             elsif (/\G ( (?: if | elsif | unless | while | until | given | when ) \s* \( ) /oxgc) {
3063 0           $slash = 'm//';
3064 0           return $1;
3065             }
3066              
3067             # scalar variable ($scalar = ...) =~ tr///;
3068             # scalar variable ($scalar = ...) =~ s///;
3069              
3070             # state
3071              
3072             # P.68 Persistent, Private Variables
3073             # in Chapter 4: Subroutines
3074             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
3075              
3076             # P.160 Persistent Lexically Scoped Variables: state
3077             # in Chapter 4: Statements and Declarations
3078             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
3079              
3080             # (and so on)
3081              
3082             elsif (/\G ( \( \s* (?: local \b | my \b | our \b | state \b )? \s* \$ $qq_scalar ) /oxgc) {
3083 0           my $e_string = e_string($1);
3084              
3085 0 0         if (/\G ( \s* = $qq_paren \) ) ( \s* (?: =~ | !~ ) \s* ) (?= (?: tr | y ) \b ) /oxgc) {
    0          
3086 0           $tr_variable = $e_string . e_string($1);
3087 0           $bind_operator = $2;
3088 0           $slash = 'm//';
3089 0           return '';
3090             }
3091             elsif (/\G ( \s* = $qq_paren \) ) ( \s* (?: =~ | !~ ) \s* ) (?= s \b ) /oxgc) {
3092 0           $sub_variable = $e_string . e_string($1);
3093 0           $bind_operator = $2;
3094 0           $slash = 'm//';
3095 0           return '';
3096             }
3097             else {
3098 0           $slash = 'div';
3099 0           return $e_string;
3100             }
3101             }
3102              
3103             # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Char::Ekoi8r::PREMATCH()
3104             elsif (/\G ( \$` | \$\{`\} | \$ \s* PREMATCH \b | \$ \s* \{ \s* PREMATCH \s* \} | \$ \s* \{\^PREMATCH\} ) /oxmsgc) {
3105 0           $slash = 'div';
3106 0           return q{Char::Ekoi8r::PREMATCH()};
3107             }
3108              
3109             # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Char::Ekoi8r::MATCH()
3110             elsif (/\G ( \$& | \$\{&\} | \$ \s* MATCH \b | \$ \s* \{ \s* MATCH \s* \} | \$ \s* \{\^MATCH\} ) /oxmsgc) {
3111 0           $slash = 'div';
3112 0           return q{Char::Ekoi8r::MATCH()};
3113             }
3114              
3115             # $', ${'} --> $', ${'}
3116             elsif (/\G ( \$' | \$\{'\} ) /oxmsgc) {
3117 0           $slash = 'div';
3118 0           return $1;
3119             }
3120              
3121             # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Char::Ekoi8r::POSTMATCH()
3122             elsif (/\G ( \$ \s* POSTMATCH \b | \$ \s* \{ \s* POSTMATCH \s* \} | \$ \s* \{\^POSTMATCH\} ) /oxmsgc) {
3123 0           $slash = 'div';
3124 0           return q{Char::Ekoi8r::POSTMATCH()};
3125             }
3126              
3127             # scalar variable $scalar =~ tr///;
3128             # scalar variable $scalar =~ s///;
3129             # substr() =~ tr///;
3130             # substr() =~ s///;
3131             elsif (/\G ( \$ $qq_scalar | $qq_substr ) /oxgc) {
3132 0           my $scalar = e_string($1);
3133              
3134 0 0         if (/\G ( \s* (?: =~ | !~ ) \s* ) (?= (?: tr | y ) \b ) /oxgc) {
    0          
3135 0           $tr_variable = $scalar;
3136 0           $bind_operator = $1;
3137 0           $slash = 'm//';
3138 0           return '';
3139             }
3140             elsif (/\G ( \s* (?: =~ | !~ ) \s* ) (?= s \b ) /oxgc) {
3141 0           $sub_variable = $scalar;
3142 0           $bind_operator = $1;
3143 0           $slash = 'm//';
3144 0           return '';
3145             }
3146             else {
3147 0           $slash = 'div';
3148 0           return $scalar;
3149             }
3150             }
3151              
3152             # end of statement
3153             elsif (/\G ( [,;] ) /oxgc) {
3154 0           $slash = 'm//';
3155              
3156             # clear tr/// variable
3157 0           $tr_variable = '';
3158              
3159             # clear s/// variable
3160 0           $sub_variable = '';
3161              
3162 0           $bind_operator = '';
3163              
3164 0           return $1;
3165             }
3166              
3167             # bareword
3168             elsif (/\G ( \{ \s* (?: tr | index | rindex | reverse ) \s* \} ) /oxmsgc) {
3169 0           return $1;
3170             }
3171              
3172             # $0 --> $0
3173             elsif (/\G ( \$ 0 ) /oxmsgc) {
3174 0           $slash = 'div';
3175 0           return $1;
3176             }
3177             elsif (/\G ( \$ \{ \s* 0 \s* \} ) /oxmsgc) {
3178 0           $slash = 'div';
3179 0           return $1;
3180             }
3181              
3182             # $$ --> $$
3183             elsif (/\G ( \$ \$ ) (?![\w\{]) /oxmsgc) {
3184 0           $slash = 'div';
3185 0           return $1;
3186             }
3187              
3188             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
3189             # $1, $2, $3 --> $1, $2, $3 otherwise
3190             elsif (/\G \$ ([1-9][0-9]*) /oxmsgc) {
3191 0           $slash = 'div';
3192 0           return e_capture($1);
3193             }
3194             elsif (/\G \$ \{ \s* ([1-9][0-9]*) \s* \} /oxmsgc) {
3195 0           $slash = 'div';
3196 0           return e_capture($1);
3197             }
3198              
3199             # $$foo[ ... ] --> $ $foo->[ ... ]
3200             elsif (/\G \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) ( \[ .+? \] ) /oxmsgc) {
3201 0           $slash = 'div';
3202 0           return e_capture($1.'->'.$2);
3203             }
3204              
3205             # $$foo{ ... } --> $ $foo->{ ... }
3206             elsif (/\G \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) ( \{ .+? \} ) /oxmsgc) {
3207 0           $slash = 'div';
3208 0           return e_capture($1.'->'.$2);
3209             }
3210              
3211             # $$foo
3212             elsif (/\G \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) /oxmsgc) {
3213 0           $slash = 'div';
3214 0           return e_capture($1);
3215             }
3216              
3217             # ${ foo }
3218             elsif (/\G \$ \s* \{ ( \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* ) \} /oxmsgc) {
3219 0           $slash = 'div';
3220 0           return '${' . $1 . '}';
3221             }
3222              
3223             # ${ ... }
3224             elsif (/\G \$ \s* \{ \s* ( $qq_brace ) \s* \} /oxmsgc) {
3225 0           $slash = 'div';
3226 0           return e_capture($1);
3227             }
3228              
3229             # variable or function
3230             # $ @ % & * $ #
3231             elsif (/\G ( (?: [\$\@\%\&\*] | \$\# | -> | \b sub \b) \s* (?: split | chop | index | rindex | lc | uc | fc | chr | ord | reverse | getc | tr | y | q | qq | qx | qw | m | s | qr | glob | lstat | opendir | stat | unlink | chdir ) ) \b /oxmsgc) {
3232 0           $slash = 'div';
3233 0           return $1;
3234             }
3235             # $ $ $ $ $ $ $ $ $ $ $ $ $ $
3236             # $ @ # \ ' " / ? ( ) [ ] < >
3237             elsif (/\G ( \$[\$\@\#\\\'\"\/\?\(\)\[\]\<\>] ) /oxmsgc) {
3238 0           $slash = 'div';
3239 0           return $1;
3240             }
3241              
3242             # while ()
3243             elsif (/\G \b (while \s* \( \s* <[\$]?[A-Za-z_][A-Za-z_0-9]*> \s* \)) \b /oxgc) {
3244 0           return $1;
3245             }
3246              
3247             # while () --- glob
3248              
3249             # avoid "Error: Runtime exception" of perl version 5.005_03
3250              
3251             elsif (/\G \b while \s* \( \s* < ((?:[^>\0\a\e\f\n\r\t])+?) > \s* \) \b /oxgc) {
3252 0           return 'while ($_ = Char::Ekoi8r::glob("' . $1 . '"))';
3253             }
3254              
3255             # while (glob)
3256             elsif (/\G \b while \s* \( \s* glob \s* \) /oxgc) {
3257 0           return 'while ($_ = Char::Ekoi8r::glob_)';
3258             }
3259              
3260             # while (glob(WILDCARD))
3261             elsif (/\G \b while \s* \( \s* glob \b /oxgc) {
3262 0           return 'while ($_ = Char::Ekoi8r::glob';
3263             }
3264              
3265             # doit if, doit unless, doit while, doit until, doit for, doit when
3266 0           elsif (/\G \b ( if | unless | while | until | for | when ) \b /oxgc) { $slash = 'm//'; return $1; }
  0            
3267              
3268             # subroutines of package Char::Ekoi8r
3269 0           elsif (/\G \b (CORE:: | ->[ ]* (?: atan2 | [a-z]{2,})) \b /oxgc) { $slash = 'm//'; return $1; }
  0            
3270 0           elsif (/\G \b Char::KOI8R::eval (?= \s* \{ ) /oxgc) { $slash = 'm//'; return 'eval'; }
  0            
3271 0           elsif (/\G \b Char::KOI8R::eval \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'eval Char::KOI8R::escape'; }
  0            
3272 0           elsif (/\G \b bytes::substr \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'substr'; }
  0            
3273 0           elsif (/\G \b chop \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'Char::Ekoi8r::chop'; }
  0            
3274 0           elsif (/\G \b bytes::index \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'index'; }
  0            
3275 0           elsif (/\G \b Char::KOI8R::index \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'Char::KOI8R::index'; }
  0            
3276 0           elsif (/\G \b index \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'Char::Ekoi8r::index'; }
  0            
3277 0           elsif (/\G \b bytes::rindex \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'rindex'; }
  0            
3278 0           elsif (/\G \b Char::KOI8R::rindex \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'Char::KOI8R::rindex'; }
  0            
3279 0           elsif (/\G \b rindex \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'Char::Ekoi8r::rindex'; }
  0            
3280 0           elsif (/\G \b lc (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Char::Ekoi8r::lc'; }
  0            
3281 0           elsif (/\G \b lcfirst (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Char::Ekoi8r::lcfirst'; }
  0            
3282 0           elsif (/\G \b uc (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Char::Ekoi8r::uc'; }
  0            
3283 0           elsif (/\G \b ucfirst (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Char::Ekoi8r::ucfirst'; }
  0            
3284 0           elsif (/\G \b fc (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Char::Ekoi8r::fc'; }
  0            
3285              
3286             # "-s '' ..." means file test "-s 'filename' ..." (not means "- s/// ...")
3287 0           elsif (/\G -s \s+ \s* (\") ((?:$qq_char)+?) (\") /oxgc) { $slash = 'm//'; return '-s ' . e_qq('', $1,$3,$2); }
  0            
3288 0           elsif (/\G -s \s+ qq \s* (\#) ((?:$qq_char)+?) (\#) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0            
3289 0           elsif (/\G -s \s+ qq \s* (\() ((?:$qq_paren)+?) (\)) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0            
3290 0           elsif (/\G -s \s+ qq \s* (\{) ((?:$qq_brace)+?) (\}) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0            
3291 0           elsif (/\G -s \s+ qq \s* (\[) ((?:$qq_bracket)+?) (\]) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0            
3292 0           elsif (/\G -s \s+ qq \s* (\<) ((?:$qq_angle)+?) (\>) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0            
3293 0           elsif (/\G -s \s+ qq \s* (\S) ((?:$qq_char)+?) (\1) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0            
3294              
3295 0           elsif (/\G -s \s+ \s* (\') ((?:\\\'|\\\\|$q_char)+?) (\') /oxgc) { $slash = 'm//'; return '-s ' . e_q ('', $1,$3,$2); }
  0            
3296 0           elsif (/\G -s \s+ q \s* (\#) ((?:\\\#|\\\\|$q_char)+?) (\#) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0            
3297 0           elsif (/\G -s \s+ q \s* (\() ((?:\\\)|\\\\|$q_paren)+?) (\)) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0            
3298 0           elsif (/\G -s \s+ q \s* (\{) ((?:\\\}|\\\\|$q_brace)+?) (\}) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0            
3299 0           elsif (/\G -s \s+ q \s* (\[) ((?:\\\]|\\\\|$q_bracket)+?) (\]) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0            
3300 0           elsif (/\G -s \s+ q \s* (\<) ((?:\\\>|\\\\|$q_angle)+?) (\>) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0            
3301 0           elsif (/\G -s \s+ q \s* (\S) ((?:\\\1|\\\\|$q_char)+?) (\1) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0            
3302              
3303             elsif (/\G -s \s* (\$ \w+(?: ::\w+)* (?: (?: ->)? (?: [\$\@\%\&\*]\* | \$\#\* | \( (?:$qq_paren)*? \) | [\@\%\*]? \{ (?:$qq_brace)+? \} | [\@\%]? \[ (?:$qq_bracket)+? \] ) )*) /oxgc)
3304 0           { $slash = 'm//'; return "-s $1"; }
  0            
3305 0           elsif (/\G -s \s* \( ((?:$qq_paren)*?) \) /oxgc) { $slash = 'm//'; return "-s ($1)"; }
  0            
3306 0           elsif (/\G -s (?= \s+ [a-z]+) /oxgc) { $slash = 'm//'; return '-s'; }
  0            
3307 0           elsif (/\G -s \s+ (\w+) /oxgc) { $slash = 'm//'; return "-s $1"; }
  0            
3308              
3309 0           elsif (/\G \b bytes::length (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'length'; }
  0            
3310 0           elsif (/\G \b bytes::chr (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'chr'; }
  0            
3311 0           elsif (/\G \b chr (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Char::Ekoi8r::chr'; }
  0            
3312 0           elsif (/\G \b bytes::ord (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $slash = 'div'; return 'ord'; }
  0            
3313 0           elsif (/\G \b ord (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $slash = 'div'; return $function_ord; }
  0            
3314 0           elsif (/\G \b glob (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Char::Ekoi8r::glob'; }
  0            
3315 0           elsif (/\G \b lc \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'Char::Ekoi8r::lc_'; }
  0            
3316 0           elsif (/\G \b lcfirst \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'Char::Ekoi8r::lcfirst_'; }
  0            
3317 0           elsif (/\G \b uc \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'Char::Ekoi8r::uc_'; }
  0            
3318 0           elsif (/\G \b ucfirst \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'Char::Ekoi8r::ucfirst_'; }
  0            
3319 0           elsif (/\G \b fc \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'Char::Ekoi8r::fc_'; }
  0            
3320 0           elsif (/\G -s \b (?! \s* => ) /oxgc) { $slash = 'm//'; return '-s '; }
  0            
3321              
3322 0           elsif (/\G \b bytes::length \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'length'; }
  0            
3323 0           elsif (/\G \b bytes::chr \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'chr'; }
  0            
3324 0           elsif (/\G \b chr \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'Char::Ekoi8r::chr_'; }
  0            
3325 0           elsif (/\G \b bytes::ord \b (?! \s* => ) /oxgc) { $slash = 'div'; return 'ord'; }
  0            
3326 0           elsif (/\G \b ord \b (?! \s* => ) /oxgc) { $slash = 'div'; return $function_ord_; }
  0            
3327 0           elsif (/\G \b glob \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'Char::Ekoi8r::glob_'; }
  0            
3328 0           elsif (/\G \b reverse \b (?! \s* => ) /oxgc) { $slash = 'm//'; return $function_reverse; }
  0            
3329 0           elsif (/\G \b getc \b (?! \s* => ) /oxgc) { $slash = 'm//'; return $function_getc; }
  0            
3330             # split
3331             elsif (/\G \b (split) \b (?! \s* => ) /oxgc) {
3332 0           $slash = 'm//';
3333              
3334 0           my $e = '';
3335 0           while (/\G ( \s+ | \( | \#.* ) /oxgc) {
3336 0           $e .= $1;
3337             }
3338              
3339             # end of split
3340 0 0         if (/\G (?= [,;\)\}\]] ) /oxgc) { return 'Char::Ekoi8r::split' . $e; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
3341              
3342             # split scalar value
3343 0           elsif (/\G ( [\$\@\&\*] $qq_scalar ) /oxgc) { return 'Char::Ekoi8r::split' . $e . e_string($1); }
3344              
3345             # split literal space
3346 0           elsif (/\G \b qq (\#) [ ] (\#) /oxgc) { return 'Char::Ekoi8r::split' . $e . qq {qq$1 $2}; }
3347 0           elsif (/\G \b qq (\s*) (\() [ ] (\)) /oxgc) { return 'Char::Ekoi8r::split' . $e . qq{$1qq$2 $3}; }
3348 0           elsif (/\G \b qq (\s*) (\{) [ ] (\}) /oxgc) { return 'Char::Ekoi8r::split' . $e . qq{$1qq$2 $3}; }
3349 0           elsif (/\G \b qq (\s*) (\[) [ ] (\]) /oxgc) { return 'Char::Ekoi8r::split' . $e . qq{$1qq$2 $3}; }
3350 0           elsif (/\G \b qq (\s*) (\<) [ ] (\>) /oxgc) { return 'Char::Ekoi8r::split' . $e . qq{$1qq$2 $3}; }
3351 0           elsif (/\G \b qq (\s*) (\S) [ ] (\2) /oxgc) { return 'Char::Ekoi8r::split' . $e . qq{$1qq$2 $3}; }
3352 0           elsif (/\G \b q (\#) [ ] (\#) /oxgc) { return 'Char::Ekoi8r::split' . $e . qq {q$1 $2}; }
3353 0           elsif (/\G \b q (\s*) (\() [ ] (\)) /oxgc) { return 'Char::Ekoi8r::split' . $e . qq {$1q$2 $3}; }
3354 0           elsif (/\G \b q (\s*) (\{) [ ] (\}) /oxgc) { return 'Char::Ekoi8r::split' . $e . qq {$1q$2 $3}; }
3355 0           elsif (/\G \b q (\s*) (\[) [ ] (\]) /oxgc) { return 'Char::Ekoi8r::split' . $e . qq {$1q$2 $3}; }
3356 0           elsif (/\G \b q (\s*) (\<) [ ] (\>) /oxgc) { return 'Char::Ekoi8r::split' . $e . qq {$1q$2 $3}; }
3357 0           elsif (/\G \b q (\s*) (\S) [ ] (\2) /oxgc) { return 'Char::Ekoi8r::split' . $e . qq {$1q$2 $3}; }
3358 0           elsif (/\G ' [ ] ' /oxgc) { return 'Char::Ekoi8r::split' . $e . qq {' '}; }
3359 0           elsif (/\G " [ ] " /oxgc) { return 'Char::Ekoi8r::split' . $e . qq {" "}; }
3360              
3361             # split qq//
3362             elsif (/\G \b (qq) \b /oxgc) {
3363 0 0         if (/\G (\#) ((?:$qq_char)*?) (\#) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq# # --> qr # #
  0            
3364             else {
3365 0           while (not /\G \z/oxgc) {
3366 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
3367 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq ( ) --> qr ( )
3368 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq { } --> qr { }
3369 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq [ ] --> qr [ ]
3370 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq < > --> qr < >
3371 0           elsif (/\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) /oxgc) { return e_split($e.'qr','{','}',$2,''); } # qq | | --> qr { }
3372 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq * * --> qr * *
3373             }
3374 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3375             }
3376             }
3377              
3378             # split qr//
3379             elsif (/\G \b (qr) \b /oxgc) {
3380 0 0         if (/\G (\#) ((?:$qq_char)*?) (\#) ([imosxpadlubB]*) /oxgc) { return e_split ($e.'qr',$1,$3,$2,$4); } # qr# #
  0            
3381             else {
3382 0           while (not /\G \z/oxgc) {
3383 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
3384 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([imosxpadlubB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # qr ( )
3385 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([imosxpadlubB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # qr { }
3386 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([imosxpadlubB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # qr [ ]
3387 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([imosxpadlubB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # qr < >
3388 0           elsif (/\G (\') ((?:$qq_char)*?) (\') ([imosxpadlubB]*) /oxgc) { return e_split_q($e.'qr',$1, $3, $2,$4); } # qr ' '
3389 0           elsif (/\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ([imosxpadlubB]*) /oxgc) { return e_split ($e.'qr','{','}',$2,$4); } # qr | | --> qr { }
3390 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([imosxpadlubB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # qr * *
3391             }
3392 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3393             }
3394             }
3395              
3396             # split q//
3397             elsif (/\G \b (q) \b /oxgc) {
3398 0 0         if (/\G (\#) ((?:\\\#|\\\\|$q_char)*?) (\#) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q# # --> qr # #
  0            
3399             else {
3400 0           while (not /\G \z/oxgc) {
3401 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
3402 0           elsif (/\G (\() ((?:\\\\|\\\)|\\\(|$q_paren)*?) (\)) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q ( ) --> qr ( )
3403 0           elsif (/\G (\{) ((?:\\\\|\\\}|\\\{|$q_brace)*?) (\}) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q { } --> qr { }
3404 0           elsif (/\G (\[) ((?:\\\\|\\\]|\\\[|$q_bracket)*?) (\]) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q [ ] --> qr [ ]
3405 0           elsif (/\G (\<) ((?:\\\\|\\\>|\\\<|$q_angle)*?) (\>) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q < > --> qr < >
3406 0           elsif (/\G ([*\-:?\\^|]) ((?:$q_char)*?) (\1) /oxgc) { return e_split_q($e.'qr','{','}',$2,''); } # q | | --> qr { }
3407 0           elsif (/\G (\S) ((?:\\\\|\\\1| $q_char)*?) (\1) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q * * --> qr * *
3408             }
3409 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3410             }
3411             }
3412              
3413             # split m//
3414             elsif (/\G \b (m) \b /oxgc) {
3415 0 0         if (/\G (\#) ((?:$qq_char)*?) (\#) ([cgimosxpadlubB]*) /oxgc) { return e_split ($e.'qr',$1,$3,$2,$4); } # m# # --> qr # #
  0            
3416             else {
3417 0           while (not /\G \z/oxgc) {
3418 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
3419 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cgimosxpadlubB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # m ( ) --> qr ( )
3420 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cgimosxpadlubB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # m { } --> qr { }
3421 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cgimosxpadlubB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # m [ ] --> qr [ ]
3422 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cgimosxpadlubB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # m < > --> qr < >
3423 0           elsif (/\G (\') ((?:$qq_char)*?) (\') ([cgimosxpadlubB]*) /oxgc) { return e_split_q($e.'qr',$1, $3, $2,$4); } # m ' ' --> qr ' '
3424 0           elsif (/\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ([cgimosxpadlubB]*) /oxgc) { return e_split ($e.'qr','{','}',$2,$4); } # m | | --> qr { }
3425 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cgimosxpadlubB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # m * * --> qr * *
3426             }
3427 0           die __FILE__, ": Search pattern not terminated";
3428             }
3429             }
3430              
3431             # split ''
3432             elsif (/\G (\') /oxgc) {
3433 0           my $q_string = '';
3434 0           while (not /\G \z/oxgc) {
3435 0 0         if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0          
    0          
    0          
3436 0           elsif (/\G (\\\') /oxgc) { $q_string .= $1; } # splitqr'' --> split qr''
3437 0           elsif (/\G \' /oxgc) { return e_split_q($e.q{ qr},"'","'",$q_string,''); } # ' ' --> qr ' '
3438 0           elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3439             }
3440 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3441             }
3442              
3443             # split ""
3444             elsif (/\G (\") /oxgc) {
3445 0           my $qq_string = '';
3446 0           while (not /\G \z/oxgc) {
3447 0 0         if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0          
    0          
    0          
3448 0           elsif (/\G (\\\") /oxgc) { $qq_string .= $1; } # splitqr"" --> split qr""
3449 0           elsif (/\G \" /oxgc) { return e_split($e.q{ qr},'"','"',$qq_string,''); } # " " --> qr " "
3450 0           elsif (/\G ($q_char) /oxgc) { $qq_string .= $1; }
3451             }
3452 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3453             }
3454              
3455             # split //
3456             elsif (/\G (\/) /oxgc) {
3457 0           my $regexp = '';
3458 0           while (not /\G \z/oxgc) {
3459 0 0         if (/\G (\\\\) /oxgc) { $regexp .= $1; }
  0 0          
    0          
    0          
3460 0           elsif (/\G (\\\/) /oxgc) { $regexp .= $1; } # splitqr// --> split qr//
3461 0           elsif (/\G \/ ([cgimosxpadlubB]*) /oxgc) { return e_split($e.q{ qr}, '/','/',$regexp,$1); } # / / --> qr / /
3462 0           elsif (/\G ($q_char) /oxgc) { $regexp .= $1; }
3463             }
3464 0           die __FILE__, ": Search pattern not terminated";
3465             }
3466             }
3467              
3468             # tr/// or y///
3469              
3470             # about [cdsrbB]* (/B modifier)
3471             #
3472             # P.559 appendix C
3473             # of ISBN 4-89052-384-7 Programming perl
3474             # (Japanese title is: Perl puroguramingu)
3475              
3476             elsif (/\G \b ( tr | y ) \b /oxgc) {
3477 0           my $ope = $1;
3478              
3479             # $1 $2 $3 $4 $5 $6
3480 0 0         if (/\G (\#) ((?:$qq_char)*?) (\#) ((?:$qq_char)*?) (\#) ([cdsrbB]*) /oxgc) { # tr# # #
3481 0           my @tr = ($tr_variable,$2);
3482 0           return e_tr(@tr,'',$4,$6);
3483             }
3484             else {
3485 0           my $e = '';
3486 0           while (not /\G \z/oxgc) {
3487 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3488             elsif (/\G (\() ((?:$qq_paren)*?) (\)) /oxgc) {
3489 0           my @tr = ($tr_variable,$2);
3490 0           while (not /\G \z/oxgc) {
3491 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3492 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr ( ) ( )
3493 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr ( ) { }
3494 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr ( ) [ ]
3495 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr ( ) < >
3496 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr ( ) * *
3497             }
3498 0           die __FILE__, ": Transliteration replacement not terminated";
3499             }
3500             elsif (/\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) {
3501 0           my @tr = ($tr_variable,$2);
3502 0           while (not /\G \z/oxgc) {
3503 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3504 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr { } ( )
3505 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr { } { }
3506 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr { } [ ]
3507 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr { } < >
3508 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr { } * *
3509             }
3510 0           die __FILE__, ": Transliteration replacement not terminated";
3511             }
3512             elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) {
3513 0           my @tr = ($tr_variable,$2);
3514 0           while (not /\G \z/oxgc) {
3515 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3516 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr [ ] ( )
3517 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr [ ] { }
3518 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr [ ] [ ]
3519 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr [ ] < >
3520 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr [ ] * *
3521             }
3522 0           die __FILE__, ": Transliteration replacement not terminated";
3523             }
3524             elsif (/\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) {
3525 0           my @tr = ($tr_variable,$2);
3526 0           while (not /\G \z/oxgc) {
3527 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3528 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr < > ( )
3529 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr < > { }
3530 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr < > [ ]
3531 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr < > < >
3532 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr < > * *
3533             }
3534 0           die __FILE__, ": Transliteration replacement not terminated";
3535             }
3536             # $1 $2 $3 $4 $5 $6
3537             elsif (/\G (\S) ((?:$qq_char)*?) (\1) ((?:$qq_char)*?) (\1) ([cdsrbB]*) /oxgc) { # tr * * *
3538 0           my @tr = ($tr_variable,$2);
3539 0           return e_tr(@tr,'',$4,$6);
3540             }
3541             }
3542 0           die __FILE__, ": Transliteration pattern not terminated";
3543             }
3544             }
3545              
3546             # qq//
3547             elsif (/\G \b (qq) \b /oxgc) {
3548 0           my $ope = $1;
3549              
3550             # if (/\G (\#) ((?:$qq_char)*?) (\#) /oxgc) { return e_qq($ope,$1,$3,$2); } # qq# #
3551 0 0         if (/\G (\#) /oxgc) { # qq# #
3552 0           my $qq_string = '';
3553 0           while (not /\G \z/oxgc) {
3554 0 0         if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0          
    0          
    0          
3555 0           elsif (/\G (\\\#) /oxgc) { $qq_string .= $1; }
3556 0           elsif (/\G (\#) /oxgc) { return e_qq($ope,'#','#',$qq_string); }
3557 0           elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3558             }
3559 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3560             }
3561              
3562             else {
3563 0           my $e = '';
3564 0           while (not /\G \z/oxgc) {
3565 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3566              
3567             # elsif (/\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qq ( )
3568             elsif (/\G (\() /oxgc) { # qq ( )
3569 0           my $qq_string = '';
3570 0           local $nest = 1;
3571 0           while (not /\G \z/oxgc) {
3572 0 0         if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0          
    0          
    0          
    0          
3573 0           elsif (/\G (\\\)) /oxgc) { $qq_string .= $1; }
3574 0           elsif (/\G (\() /oxgc) { $qq_string .= $1; $nest++; }
  0            
3575             elsif (/\G (\)) /oxgc) {
3576 0 0         if (--$nest == 0) { return $e . e_qq($ope,'(',')',$qq_string); }
  0            
3577 0           else { $qq_string .= $1; }
3578             }
3579 0           elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3580             }
3581 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3582             }
3583              
3584             # elsif (/\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qq { }
3585             elsif (/\G (\{) /oxgc) { # qq { }
3586 0           my $qq_string = '';
3587 0           local $nest = 1;
3588 0           while (not /\G \z/oxgc) {
3589 0 0         if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0          
    0          
    0          
    0          
3590 0           elsif (/\G (\\\}) /oxgc) { $qq_string .= $1; }
3591 0           elsif (/\G (\{) /oxgc) { $qq_string .= $1; $nest++; }
  0            
3592             elsif (/\G (\}) /oxgc) {
3593 0 0         if (--$nest == 0) { return $e . e_qq($ope,'{','}',$qq_string); }
  0            
3594 0           else { $qq_string .= $1; }
3595             }
3596 0           elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3597             }
3598 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3599             }
3600              
3601             # elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qq [ ]
3602             elsif (/\G (\[) /oxgc) { # qq [ ]
3603 0           my $qq_string = '';
3604 0           local $nest = 1;
3605 0           while (not /\G \z/oxgc) {
3606 0 0         if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0          
    0          
    0          
    0          
3607 0           elsif (/\G (\\\]) /oxgc) { $qq_string .= $1; }
3608 0           elsif (/\G (\[) /oxgc) { $qq_string .= $1; $nest++; }
  0            
3609             elsif (/\G (\]) /oxgc) {
3610 0 0         if (--$nest == 0) { return $e . e_qq($ope,'[',']',$qq_string); }
  0            
3611 0           else { $qq_string .= $1; }
3612             }
3613 0           elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3614             }
3615 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3616             }
3617              
3618             # elsif (/\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qq < >
3619             elsif (/\G (\<) /oxgc) { # qq < >
3620 0           my $qq_string = '';
3621 0           local $nest = 1;
3622 0           while (not /\G \z/oxgc) {
3623 0 0         if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0          
    0          
    0          
    0          
3624 0           elsif (/\G (\\\>) /oxgc) { $qq_string .= $1; }
3625 0           elsif (/\G (\<) /oxgc) { $qq_string .= $1; $nest++; }
  0            
3626             elsif (/\G (\>) /oxgc) {
3627 0 0         if (--$nest == 0) { return $e . e_qq($ope,'<','>',$qq_string); }
  0            
3628 0           else { $qq_string .= $1; }
3629             }
3630 0           elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3631             }
3632 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3633             }
3634              
3635             # elsif (/\G (\S) ((?:$qq_char)*?) (\1) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qq * *
3636             elsif (/\G (\S) /oxgc) { # qq * *
3637 0           my $delimiter = $1;
3638 0           my $qq_string = '';
3639 0           while (not /\G \z/oxgc) {
3640 0 0         if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0          
    0          
    0          
3641 0           elsif (/\G (\\\Q$delimiter\E) /oxgc) { $qq_string .= $1; }
3642 0           elsif (/\G (\Q$delimiter\E) /oxgc) { return $e . e_qq($ope,$delimiter,$delimiter,$qq_string); }
3643 0           elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3644             }
3645 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3646             }
3647             }
3648 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3649             }
3650             }
3651              
3652             # qr//
3653             elsif (/\G \b (qr) \b /oxgc) {
3654 0           my $ope = $1;
3655 0 0         if (/\G (\#) ((?:$qq_char)*?) (\#) ([imosxpadlubB]*) /oxgc) { # qr# # #
3656 0           return e_qr($ope,$1,$3,$2,$4);
3657             }
3658             else {
3659 0           my $e = '';
3660 0           while (not /\G \z/oxgc) {
3661 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
3662 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([imosxpadlubB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # qr ( )
3663 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([imosxpadlubB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # qr { }
3664 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([imosxpadlubB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # qr [ ]
3665 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([imosxpadlubB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # qr < >
3666 0           elsif (/\G (\') ((?:$qq_char)*?) (\') ([imosxpadlubB]*) /oxgc) { return $e . e_qr_q($ope,$1, $3, $2,$4); } # qr ' '
3667 0           elsif (/\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ([imosxpadlubB]*) /oxgc) { return $e . e_qr ($ope,'{','}',$2,$4); } # qr | | --> qr { }
3668 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([imosxpadlubB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # qr * *
3669             }
3670 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3671             }
3672             }
3673              
3674             # qw//
3675             elsif (/\G \b (qw) \b /oxgc) {
3676 0           my $ope = $1;
3677 0 0         if (/\G (\#) (.*?) (\#) /oxmsgc) { # qw# #
3678 0           return e_qw($ope,$1,$3,$2);
3679             }
3680             else {
3681 0           my $e = '';
3682 0           while (not /\G \z/oxgc) {
3683 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
3684              
3685 0           elsif (/\G (\() ([^(]*?) (\)) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw ( )
3686 0           elsif (/\G (\() ((?:$q_paren)*?) (\)) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw ( )
3687              
3688 0           elsif (/\G (\{) ([^{]*?) (\}) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw { }
3689 0           elsif (/\G (\{) ((?:$q_brace)*?) (\}) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw { }
3690              
3691 0           elsif (/\G (\[) ([^[]*?) (\]) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw [ ]
3692 0           elsif (/\G (\[) ((?:$q_bracket)*?) (\]) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw [ ]
3693              
3694 0           elsif (/\G (\<) ([^<]*?) (\>) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw < >
3695 0           elsif (/\G (\<) ((?:$q_angle)*?) (\>) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw < >
3696              
3697 0           elsif (/\G ([\x21-\x3F]) (.*?) (\1) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw * *
3698 0           elsif (/\G (\S) ((?:$q_char)*?) (\1) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw * *
3699             }
3700 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3701             }
3702             }
3703              
3704             # qx//
3705             elsif (/\G \b (qx) \b /oxgc) {
3706 0           my $ope = $1;
3707 0 0         if (/\G (\#) ((?:$qq_char)*?) (\#) /oxgc) { # qx# #
3708 0           return e_qq($ope,$1,$3,$2);
3709             }
3710             else {
3711 0           my $e = '';
3712 0           while (not /\G \z/oxgc) {
3713 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
3714 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qx ( )
3715 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qx { }
3716 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qx [ ]
3717 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qx < >
3718 0           elsif (/\G (\') ((?:$qq_char)*?) (\') /oxgc) { return $e . e_q ($ope,$1,$3,$2); } # qx ' '
3719 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qx * *
3720             }
3721 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3722             }
3723             }
3724              
3725             # q//
3726             elsif (/\G \b (q) \b /oxgc) {
3727 0           my $ope = $1;
3728              
3729             # if (/\G (\#) ((?:\\\#|\\\\|$q_char)*?) (\#) /oxgc) { return e_q($ope,$1,$3,$2); } # q# #
3730              
3731             # avoid "Error: Runtime exception" of perl version 5.005_03
3732             # (and so on)
3733              
3734 0 0         if (/\G (\#) /oxgc) { # q# #
3735 0           my $q_string = '';
3736 0           while (not /\G \z/oxgc) {
3737 0 0         if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0          
    0          
    0          
3738 0           elsif (/\G (\\\#) /oxgc) { $q_string .= $1; }
3739 0           elsif (/\G (\#) /oxgc) { return e_q($ope,'#','#',$q_string); }
3740 0           elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3741             }
3742 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3743             }
3744              
3745             else {
3746 0           my $e = '';
3747 0           while (not /\G \z/oxgc) {
3748 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3749              
3750             # elsif (/\G (\() ((?:\\\)|\\\\|$q_paren)*?) (\)) /oxgc) { return $e . e_q($ope,$1,$3,$2); } # q ( )
3751             elsif (/\G (\() /oxgc) { # q ( )
3752 0           my $q_string = '';
3753 0           local $nest = 1;
3754 0           while (not /\G \z/oxgc) {
3755 0 0         if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3756 0           elsif (/\G (\\\)) /oxgc) { $q_string .= $1; }
3757 0           elsif (/\G (\\\() /oxgc) { $q_string .= $1; }
3758 0           elsif (/\G (\() /oxgc) { $q_string .= $1; $nest++; }
  0            
3759             elsif (/\G (\)) /oxgc) {
3760 0 0         if (--$nest == 0) { return $e . e_q($ope,'(',')',$q_string); }
  0            
3761 0           else { $q_string .= $1; }
3762             }
3763 0           elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3764             }
3765 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3766             }
3767              
3768             # elsif (/\G (\{) ((?:\\\}|\\\\|$q_brace)*?) (\}) /oxgc) { return $e . e_q($ope,$1,$3,$2); } # q { }
3769             elsif (/\G (\{) /oxgc) { # q { }
3770 0           my $q_string = '';
3771 0           local $nest = 1;
3772 0           while (not /\G \z/oxgc) {
3773 0 0         if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3774 0           elsif (/\G (\\\}) /oxgc) { $q_string .= $1; }
3775 0           elsif (/\G (\\\{) /oxgc) { $q_string .= $1; }
3776 0           elsif (/\G (\{) /oxgc) { $q_string .= $1; $nest++; }
  0            
3777             elsif (/\G (\}) /oxgc) {
3778 0 0         if (--$nest == 0) { return $e . e_q($ope,'{','}',$q_string); }
  0            
3779 0           else { $q_string .= $1; }
3780             }
3781 0           elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3782             }
3783 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3784             }
3785              
3786             # elsif (/\G (\[) ((?:\\\]|\\\\|$q_bracket)*?) (\]) /oxgc) { return $e . e_q($ope,$1,$3,$2); } # q [ ]
3787             elsif (/\G (\[) /oxgc) { # q [ ]
3788 0           my $q_string = '';
3789 0           local $nest = 1;
3790 0           while (not /\G \z/oxgc) {
3791 0 0         if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3792 0           elsif (/\G (\\\]) /oxgc) { $q_string .= $1; }
3793 0           elsif (/\G (\\\[) /oxgc) { $q_string .= $1; }
3794 0           elsif (/\G (\[) /oxgc) { $q_string .= $1; $nest++; }
  0            
3795             elsif (/\G (\]) /oxgc) {
3796 0 0         if (--$nest == 0) { return $e . e_q($ope,'[',']',$q_string); }
  0            
3797 0           else { $q_string .= $1; }
3798             }
3799 0           elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3800             }
3801 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3802             }
3803              
3804             # elsif (/\G (\<) ((?:\\\>|\\\\|$q_angle)*?) (\>) /oxgc) { return $e . e_q($ope,$1,$3,$2); } # q < >
3805             elsif (/\G (\<) /oxgc) { # q < >
3806 0           my $q_string = '';
3807 0           local $nest = 1;
3808 0           while (not /\G \z/oxgc) {
3809 0 0         if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3810 0           elsif (/\G (\\\>) /oxgc) { $q_string .= $1; }
3811 0           elsif (/\G (\\\<) /oxgc) { $q_string .= $1; }
3812 0           elsif (/\G (\<) /oxgc) { $q_string .= $1; $nest++; }
  0            
3813             elsif (/\G (\>) /oxgc) {
3814 0 0         if (--$nest == 0) { return $e . e_q($ope,'<','>',$q_string); }
  0            
3815 0           else { $q_string .= $1; }
3816             }
3817 0           elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3818             }
3819 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3820             }
3821              
3822             # elsif (/\G (\S) ((?:\\\1|\\\\|$q_char)*?) (\1) /oxgc) { return $e . e_q($ope,$1,$3,$2); } # q * *
3823             elsif (/\G (\S) /oxgc) { # q * *
3824 0           my $delimiter = $1;
3825 0           my $q_string = '';
3826 0           while (not /\G \z/oxgc) {
3827 0 0         if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0          
    0          
    0          
3828 0           elsif (/\G (\\\Q$delimiter\E) /oxgc) { $q_string .= $1; }
3829 0           elsif (/\G (\Q$delimiter\E) /oxgc) { return $e . e_q($ope,$delimiter,$delimiter,$q_string); }
3830 0           elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3831             }
3832 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3833             }
3834             }
3835 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3836             }
3837             }
3838              
3839             # m//
3840             elsif (/\G \b (m) \b /oxgc) {
3841 0           my $ope = $1;
3842 0 0         if (/\G (\#) ((?:$qq_char)*?) (\#) ([cgimosxpadlubB]*) /oxgc) { # m# #
3843 0           return e_qr($ope,$1,$3,$2,$4);
3844             }
3845             else {
3846 0           my $e = '';
3847 0           while (not /\G \z/oxgc) {
3848 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
3849 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cgimosxpadlubB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m ( )
3850 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cgimosxpadlubB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m { }
3851 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cgimosxpadlubB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m [ ]
3852 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cgimosxpadlubB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m < >
3853 0           elsif (/\G (\?) ((?:$qq_char)*?) (\?) ([cgimosxpadlubB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m ? ?
3854 0           elsif (/\G (\') ((?:$qq_char)*?) (\') ([cgimosxpadlubB]*) /oxgc) { return $e . e_qr_q($ope,$1, $3, $2,$4); } # m ' '
3855 0           elsif (/\G ([*\-:\\^|]) ((?:$qq_char)*?) (\1) ([cgimosxpadlubB]*) /oxgc) { return $e . e_qr ($ope,'{','}',$2,$4); } # m | | --> m { }
3856 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cgimosxpadlubB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m * *
3857             }
3858 0           die __FILE__, ": Search pattern not terminated";
3859             }
3860             }
3861              
3862             # s///
3863              
3864             # about [cegimosxpradlubB]* (/cg modifier)
3865             #
3866             # P.67 Pattern-Matching Operators
3867             # of ISBN 0-596-00241-6 Perl in a Nutshell, Second Edition.
3868              
3869             elsif (/\G \b (s) \b /oxgc) {
3870 0           my $ope = $1;
3871              
3872             # $1 $2 $3 $4 $5 $6
3873 0 0         if (/\G (\#) ((?:$qq_char)*?) (\#) ((?:$qq_char)*?) (\#) ([cegimosxpradlubB]*) /oxgc) { # s# # #
3874 0           return e_sub($sub_variable,$1,$2,$3,$3,$4,$5,$6);
3875             }
3876             else {
3877 0           my $e = '';
3878 0           while (not /\G \z/oxgc) {
3879 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
3880             elsif (/\G (\() ((?:$qq_paren)*?) (\)) /oxgc) {
3881 0           my @s = ($1,$2,$3);
3882 0           while (not /\G \z/oxgc) {
3883 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
3884             # $1 $2 $3 $4
3885 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3886 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3887 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3888 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3889 0           elsif (/\G (\') ((?:$qq_char)*?) (\') ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3890 0           elsif (/\G (\$) ((?:$qq_char)*?) (\$) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3891 0           elsif (/\G (\:) ((?:$qq_char)*?) (\:) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3892 0           elsif (/\G (\@) ((?:$qq_char)*?) (\@) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3893 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3894             }
3895 0           die __FILE__, ": Substitution replacement not terminated";
3896             }
3897             elsif (/\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) {
3898 0           my @s = ($1,$2,$3);
3899 0           while (not /\G \z/oxgc) {
3900 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
3901             # $1 $2 $3 $4
3902 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3903 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3904 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3905 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3906 0           elsif (/\G (\') ((?:$qq_char)*?) (\') ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3907 0           elsif (/\G (\$) ((?:$qq_char)*?) (\$) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3908 0           elsif (/\G (\:) ((?:$qq_char)*?) (\:) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3909 0           elsif (/\G (\@) ((?:$qq_char)*?) (\@) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3910 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3911             }
3912 0           die __FILE__, ": Substitution replacement not terminated";
3913             }
3914             elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) {
3915 0           my @s = ($1,$2,$3);
3916 0           while (not /\G \z/oxgc) {
3917 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
3918             # $1 $2 $3 $4
3919 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3920 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3921 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3922 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3923 0           elsif (/\G (\') ((?:$qq_char)*?) (\') ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3924 0           elsif (/\G (\$) ((?:$qq_char)*?) (\$) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3925 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3926             }
3927 0           die __FILE__, ": Substitution replacement not terminated";
3928             }
3929             elsif (/\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) {
3930 0           my @s = ($1,$2,$3);
3931 0           while (not /\G \z/oxgc) {
3932 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
3933             # $1 $2 $3 $4
3934 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3935 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3936 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3937 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3938 0           elsif (/\G (\') ((?:$qq_char)*?) (\') ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3939 0           elsif (/\G (\$) ((?:$qq_char)*?) (\$) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3940 0           elsif (/\G (\:) ((?:$qq_char)*?) (\:) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3941 0           elsif (/\G (\@) ((?:$qq_char)*?) (\@) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3942 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3943             }
3944 0           die __FILE__, ": Substitution replacement not terminated";
3945             }
3946             # $1 $2 $3 $4 $5 $6
3947             elsif (/\G (\') ((?:$qq_char)*?) (\') ((?:$qq_char)*?) (\') ([cegimosxpradlubB]*) /oxgc) {
3948 0           return e_sub($sub_variable,$1,$2,$3,$3,$4,$5,$6);
3949             }
3950             # $1 $2 $3 $4 $5 $6
3951             elsif (/\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ((?:$qq_char)*?) (\1) ([cegimosxpradlubB]*) /oxgc) {
3952 0           return e_sub($sub_variable,'{',$2,'}','{',$4,'}',$6); # s | | | --> s { } { }
3953             }
3954             # $1 $2 $3 $4 $5 $6
3955             elsif (/\G (\$) ((?:$qq_char)*?) (\1) ((?:$qq_char)*?) (\1) ([cegimosxpradlubB]*) /oxgc) {
3956 0           return e_sub($sub_variable,$1,$2,$3,$3,$4,$5,$6);
3957             }
3958             # $1 $2 $3 $4 $5 $6
3959             elsif (/\G (\S) ((?:$qq_char)*?) (\1) ((?:$qq_char)*?) (\1) ([cegimosxpradlubB]*) /oxgc) {
3960 0           return e_sub($sub_variable,$1,$2,$3,$3,$4,$5,$6);
3961             }
3962             }
3963 0           die __FILE__, ": Substitution pattern not terminated";
3964             }
3965             }
3966              
3967             # require ignore module
3968 0           elsif (/\G \b require (\s+ (?:$ignore_modules) .*? ;) ([ \t]* [#\n]) /oxmsgc) { return "# require$1$2"; }
3969 0           elsif (/\G \b require (\s+ (?:$ignore_modules) .*? ;) ([ \t]* [^#]) /oxmsgc) { return "# require$1\n$2"; }
3970 0           elsif (/\G \b require (\s+ (?:$ignore_modules)) \b /oxmsgc) { return "# require$1"; }
3971              
3972             # use strict; --> use strict; no strict qw(refs);
3973 0           elsif (/\G \b use (\s+ strict .*? ;) ([ \t]* [#\n]) /oxmsgc) { return "use$1 no strict qw(refs);$2"; }
3974 0           elsif (/\G \b use (\s+ strict .*? ;) ([ \t]* [^#]) /oxmsgc) { return "use$1 no strict qw(refs);\n$2"; }
3975 0           elsif (/\G \b use (\s+ strict) \b /oxmsgc) { return "use$1; no strict qw(refs)"; }
3976              
3977             # use 5.12.0; --> use 5.12.0; no strict qw(refs);
3978             elsif (/\G \b use \s+ (([1-9][0-9_]*)(?:\.([0-9_]+))*) \s* ; /oxmsgc) {
3979 0 0 0       if (($2 >= 6) or (($2 == 5) and ($3 ge '012'))) {
      0        
3980 0           return "use $1; no strict qw(refs);";
3981             }
3982             else {
3983 0           return "use $1;";
3984             }
3985             }
3986             elsif (/\G \b use \s+ (v([0-9][0-9_]*)(?:\.([0-9_]+))*) \s* ; /oxmsgc) {
3987 0 0 0       if (($2 >= 6) or (($2 == 5) and ($3 >= 12))) {
      0        
3988 0           return "use $1; no strict qw(refs);";
3989             }
3990             else {
3991 0           return "use $1;";
3992             }
3993             }
3994              
3995             # ignore use module
3996 0           elsif (/\G \b use (\s+ (?:$ignore_modules) .*? ;) ([ \t]* [#\n]) /oxmsgc) { return "# use$1$2"; }
3997 0           elsif (/\G \b use (\s+ (?:$ignore_modules) .*? ;) ([ \t]* [^#]) /oxmsgc) { return "# use$1\n$2"; }
3998 0           elsif (/\G \b use (\s+ (?:$ignore_modules)) \b /oxmsgc) { return "# use$1"; }
3999              
4000             # ignore no module
4001 0           elsif (/\G \b no (\s+ (?:$ignore_modules) .*? ;) ([ \t]* [#\n]) /oxmsgc) { return "# no$1$2"; }
4002 0           elsif (/\G \b no (\s+ (?:$ignore_modules) .*? ;) ([ \t]* [^#]) /oxmsgc) { return "# no$1\n$2"; }
4003 0           elsif (/\G \b no (\s+ (?:$ignore_modules)) \b /oxmsgc) { return "# no$1"; }
4004              
4005             # use else
4006 0           elsif (/\G \b use \b /oxmsgc) { return "use"; }
4007              
4008             # use else
4009 0           elsif (/\G \b no \b /oxmsgc) { return "no"; }
4010              
4011             # ''
4012             elsif (/\G (?
4013 0           my $q_string = '';
4014 0           while (not /\G \z/oxgc) {
4015 0 0         if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0          
    0          
    0          
4016 0           elsif (/\G (\\\') /oxgc) { $q_string .= $1; }
4017 0           elsif (/\G \' /oxgc) { return e_q('', "'","'",$q_string); }
4018 0           elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
4019             }
4020 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
4021             }
4022              
4023             # ""
4024             elsif (/\G (\") /oxgc) {
4025 0           my $qq_string = '';
4026 0           while (not /\G \z/oxgc) {
4027 0 0         if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0          
    0          
    0          
4028 0           elsif (/\G (\\\") /oxgc) { $qq_string .= $1; }
4029 0           elsif (/\G \" /oxgc) { return e_qq('', '"','"',$qq_string); }
4030 0           elsif (/\G ($q_char) /oxgc) { $qq_string .= $1; }
4031             }
4032 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
4033             }
4034              
4035             # ``
4036             elsif (/\G (\`) /oxgc) {
4037 0           my $qx_string = '';
4038 0           while (not /\G \z/oxgc) {
4039 0 0         if (/\G (\\\\) /oxgc) { $qx_string .= $1; }
  0 0          
    0          
    0          
4040 0           elsif (/\G (\\\`) /oxgc) { $qx_string .= $1; }
4041 0           elsif (/\G \` /oxgc) { return e_qq('', '`','`',$qx_string); }
4042 0           elsif (/\G ($q_char) /oxgc) { $qx_string .= $1; }
4043             }
4044 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
4045             }
4046              
4047             # // --- not divide operator (num / num), not defined-or
4048             elsif (($slash eq 'm//') and /\G (\/) /oxgc) {
4049 0           my $regexp = '';
4050 0           while (not /\G \z/oxgc) {
4051 0 0         if (/\G (\\\\) /oxgc) { $regexp .= $1; }
  0 0          
    0          
    0          
4052 0           elsif (/\G (\\\/) /oxgc) { $regexp .= $1; }
4053 0           elsif (/\G \/ ([cgimosxpadlubB]*) /oxgc) { return e_qr('', '/','/',$regexp,$1); }
4054 0           elsif (/\G ($q_char) /oxgc) { $regexp .= $1; }
4055             }
4056 0           die __FILE__, ": Search pattern not terminated";
4057             }
4058              
4059             # ?? --- not conditional operator (condition ? then : else)
4060             elsif (($slash eq 'm//') and /\G (\?) /oxgc) {
4061 0           my $regexp = '';
4062 0           while (not /\G \z/oxgc) {
4063 0 0         if (/\G (\\\\) /oxgc) { $regexp .= $1; }
  0 0          
    0          
    0          
4064 0           elsif (/\G (\\\?) /oxgc) { $regexp .= $1; }
4065 0           elsif (/\G \? ([cgimosxpadlubB]*) /oxgc) { return e_qr('m','?','?',$regexp,$1); }
4066 0           elsif (/\G ($q_char) /oxgc) { $regexp .= $1; }
4067             }
4068 0           die __FILE__, ": Search pattern not terminated";
4069             }
4070              
4071             # << (bit shift) --- not here document
4072 0           elsif (/\G ( << \s* ) (?= [0-9\$\@\&] ) /oxgc) { $slash = 'm//'; return $1; }
  0            
4073              
4074             # <<'HEREDOC'
4075             elsif (/\G ( << '([a-zA-Z_0-9]*)' ) /oxgc) {
4076 0           $slash = 'm//';
4077 0           my $here_quote = $1;
4078 0           my $delimiter = $2;
4079              
4080             # get here document
4081 0 0         if ($here_script eq '') {
4082 0           $here_script = CORE::substr $_, pos $_;
4083 0           $here_script =~ s/.*?\n//oxm;
4084             }
4085 0 0         if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4086 0           push @heredoc, $1 . qq{\n$delimiter\n};
4087 0           push @heredoc_delimiter, $delimiter;
4088             }
4089             else {
4090 0           die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF";
4091             }
4092 0           return $here_quote;
4093             }
4094              
4095             # <<\HEREDOC
4096              
4097             # P.66 2.6.6. "Here" Documents
4098             # in Chapter 2: Bits and Pieces
4099             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
4100              
4101             # P.73 "Here" Documents
4102             # in Chapter 2: Bits and Pieces
4103             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
4104              
4105             elsif (/\G ( << \\([a-zA-Z_0-9]+) ) /oxgc) {
4106 0           $slash = 'm//';
4107 0           my $here_quote = $1;
4108 0           my $delimiter = $2;
4109              
4110             # get here document
4111 0 0         if ($here_script eq '') {
4112 0           $here_script = CORE::substr $_, pos $_;
4113 0           $here_script =~ s/.*?\n//oxm;
4114             }
4115 0 0         if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4116 0           push @heredoc, $1 . qq{\n$delimiter\n};
4117 0           push @heredoc_delimiter, $delimiter;
4118             }
4119             else {
4120 0           die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF";
4121             }
4122 0           return $here_quote;
4123             }
4124              
4125             # <<"HEREDOC"
4126             elsif (/\G ( << "([a-zA-Z_0-9]*)" ) /oxgc) {
4127 0           $slash = 'm//';
4128 0           my $here_quote = $1;
4129 0           my $delimiter = $2;
4130              
4131             # get here document
4132 0 0         if ($here_script eq '') {
4133 0           $here_script = CORE::substr $_, pos $_;
4134 0           $here_script =~ s/.*?\n//oxm;
4135             }
4136 0 0         if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4137 0           push @heredoc, e_heredoc($1) . qq{\n$delimiter\n};
4138 0           push @heredoc_delimiter, $delimiter;
4139             }
4140             else {
4141 0           die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF";
4142             }
4143 0           return $here_quote;
4144             }
4145              
4146             # <
4147             elsif (/\G ( << ([a-zA-Z_0-9]+) ) /oxgc) {
4148 0           $slash = 'm//';
4149 0           my $here_quote = $1;
4150 0           my $delimiter = $2;
4151              
4152             # get here document
4153 0 0         if ($here_script eq '') {
4154 0           $here_script = CORE::substr $_, pos $_;
4155 0           $here_script =~ s/.*?\n//oxm;
4156             }
4157 0 0         if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4158 0           push @heredoc, e_heredoc($1) . qq{\n$delimiter\n};
4159 0           push @heredoc_delimiter, $delimiter;
4160             }
4161             else {
4162 0           die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF";
4163             }
4164 0           return $here_quote;
4165             }
4166              
4167             # <<`HEREDOC`
4168             elsif (/\G ( << `([a-zA-Z_0-9]*)` ) /oxgc) {
4169 0           $slash = 'm//';
4170 0           my $here_quote = $1;
4171 0           my $delimiter = $2;
4172              
4173             # get here document
4174 0 0         if ($here_script eq '') {
4175 0           $here_script = CORE::substr $_, pos $_;
4176 0           $here_script =~ s/.*?\n//oxm;
4177             }
4178 0 0         if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4179 0           push @heredoc, e_heredoc($1) . qq{\n$delimiter\n};
4180 0           push @heredoc_delimiter, $delimiter;
4181             }
4182             else {
4183 0           die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF";
4184             }
4185 0           return $here_quote;
4186             }
4187              
4188             # <<= <=> <= < operator
4189             elsif (/\G ( <<= | <=> | <= | < ) (?= \s* [A-Za-z_0-9'"`\$\@\&\*\(\+\-] )/oxgc) {
4190 0           return $1;
4191             }
4192              
4193             #
4194             elsif (/\G (<[\$]?[A-Za-z_][A-Za-z_0-9]*>) /oxgc) {
4195 0           return $1;
4196             }
4197              
4198             # --- glob
4199              
4200             # avoid "Error: Runtime exception" of perl version 5.005_03
4201              
4202             elsif (/\G < ((?:[^>\0\a\e\f\n\r\t])+?) > /oxgc) {
4203 0           return 'Char::Ekoi8r::glob("' . $1 . '")';
4204             }
4205              
4206             # __DATA__
4207 0           elsif (/\G ^ ( __DATA__ \n .*) \z /oxmsgc) { return $1; }
4208              
4209             # __END__
4210 0           elsif (/\G ^ ( __END__ \n .*) \z /oxmsgc) { return $1; }
4211              
4212             # \cD Control-D
4213              
4214             # P.68 2.6.8. Other Literal Tokens
4215             # in Chapter 2: Bits and Pieces
4216             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
4217              
4218             # P.76 Other Literal Tokens
4219             # in Chapter 2: Bits and Pieces
4220             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
4221              
4222 0           elsif (/\G ( \cD .*) \z /oxmsgc) { return $1; }
4223              
4224             # \cZ Control-Z
4225 0           elsif (/\G ( \cZ .*) \z /oxmsgc) { return $1; }
4226              
4227             # any operator before div
4228             elsif (/\G (
4229             -- | \+\+ |
4230             [\)\}\]]
4231              
4232 0           ) /oxgc) { $slash = 'div'; return $1; }
  0            
4233              
4234             # yada-yada or triple-dot operator
4235             elsif (/\G (
4236             \.\.\.
4237              
4238 0           ) /oxgc) { $slash = 'm//'; return q{die('Unimplemented')}; }
  0            
4239              
4240             # any operator before m//
4241              
4242             # //, //= (defined-or)
4243              
4244             # P.164 Logical Operators
4245             # in Chapter 10: More Control Structures
4246             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
4247              
4248             # P.119 C-Style Logical (Short-Circuit) Operators
4249             # in Chapter 3: Unary and Binary Operators
4250             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
4251              
4252             # (and so on)
4253              
4254             # ~~
4255              
4256             # P.221 The Smart Match Operator
4257             # in Chapter 15: Smart Matching and given-when
4258             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
4259              
4260             # P.112 Smartmatch Operator
4261             # in Chapter 3: Unary and Binary Operators
4262             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
4263              
4264             # (and so on)
4265              
4266             elsif (/\G (
4267              
4268             !~~ | !~ | != | ! |
4269             %= | % |
4270             &&= | && | &= | & |
4271             -= | -> | - |
4272             :\s*= |
4273             : |
4274             <<= | <=> | <= | < |
4275             == | => | =~ | = |
4276             >>= | >> | >= | > |
4277             \*\*= | \*\* | \*= | \* |
4278             \+= | \+ |
4279             \.\. | \.= | \. |
4280             \/\/= | \/\/ |
4281             \/= | \/ |
4282             \? |
4283             \\ |
4284             \^= | \^ |
4285             \b x= |
4286             \|\|= | \|\| | \|= | \| |
4287             ~~ | ~ |
4288             \b(?: and | cmp | eq | ge | gt | le | lt | ne | not | or | xor | x )\b |
4289             \b(?: print )\b |
4290              
4291             [,;\(\{\[]
4292              
4293 0           ) /oxgc) { $slash = 'm//'; return $1; }
  0            
4294              
4295             # other any character
4296 0           elsif (/\G ($q_char) /oxgc) { $slash = 'div'; return $1; }
  0            
4297              
4298             # system error
4299             else {
4300 0           die __FILE__, ": Oops, this shouldn't happen!";
4301             }
4302             }
4303              
4304             # escape KOI8-R string
4305             sub e_string {
4306 0     0 0   my($string) = @_;
4307 0           my $e_string = '';
4308              
4309 0           local $slash = 'm//';
4310              
4311             # P.1024 Appendix W.10 Multibyte Processing
4312             # of ISBN 1-56592-224-7 CJKV Information Processing
4313             # (and so on)
4314              
4315 0           my @char = $string =~ / \G (\\?(?:$q_char)) /oxmsg;
4316              
4317             # without { ... }
4318 0 0 0       if (not (grep(/\A \{ \z/xms, @char) and grep(/\A \} \z/xms, @char))) {
4319 0 0         if ($string !~ /<
4320 0           return $string;
4321             }
4322             }
4323              
4324             E_STRING_LOOP:
4325 0           while ($string !~ /\G \z/oxgc) {
4326 0 0         if (0) {
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
4327             }
4328              
4329             # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> @{[Char::Ekoi8r::PREMATCH()]}
4330 0           elsif ($string =~ /\G ( \$` | \$\{`\} | \$ \s* PREMATCH \b | \$ \s* \{ \s* PREMATCH \s* \} | \$ \s* \{\^PREMATCH\} ) /oxmsgc) {
4331 0           $e_string .= q{Char::Ekoi8r::PREMATCH()};
4332 0           $slash = 'div';
4333             }
4334              
4335             # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> @{[Char::Ekoi8r::MATCH()]}
4336             elsif ($string =~ /\G ( \$& | \$\{&\} | \$ \s* MATCH \b | \$ \s* \{ \s* MATCH \s* \} | \$ \s* \{\^MATCH\} ) /oxmsgc) {
4337 0           $e_string .= q{Char::Ekoi8r::MATCH()};
4338 0           $slash = 'div';
4339             }
4340              
4341             # $', ${'} --> $', ${'}
4342             elsif ($string =~ /\G ( \$' | \$\{'\} ) /oxmsgc) {
4343 0           $e_string .= $1;
4344 0           $slash = 'div';
4345             }
4346              
4347             # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> @{[Char::Ekoi8r::POSTMATCH()]}
4348             elsif ($string =~ /\G ( \$ \s* POSTMATCH \b | \$ \s* \{ \s* POSTMATCH \s* \} | \$ \s* \{\^POSTMATCH\} ) /oxmsgc) {
4349 0           $e_string .= q{Char::Ekoi8r::POSTMATCH()};
4350 0           $slash = 'div';
4351             }
4352              
4353             # bareword
4354             elsif ($string =~ /\G ( \{ \s* (?: tr | index | rindex | reverse ) \s* \} ) /oxmsgc) {
4355 0           $e_string .= $1;
4356 0           $slash = 'div';
4357             }
4358              
4359             # $0 --> $0
4360             elsif ($string =~ /\G ( \$ 0 ) /oxmsgc) {
4361 0           $e_string .= $1;
4362 0           $slash = 'div';
4363             }
4364             elsif ($string =~ /\G ( \$ \{ \s* 0 \s* \} ) /oxmsgc) {
4365 0           $e_string .= $1;
4366 0           $slash = 'div';
4367             }
4368              
4369             # $$ --> $$
4370             elsif ($string =~ /\G ( \$ \$ ) (?![\w\{]) /oxmsgc) {
4371 0           $e_string .= $1;
4372 0           $slash = 'div';
4373             }
4374              
4375             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
4376             # $1, $2, $3 --> $1, $2, $3 otherwise
4377             elsif ($string =~ /\G \$ ([1-9][0-9]*) /oxmsgc) {
4378 0           $e_string .= e_capture($1);
4379 0           $slash = 'div';
4380             }
4381             elsif ($string =~ /\G \$ \{ \s* ([1-9][0-9]*) \s* \} /oxmsgc) {
4382 0           $e_string .= e_capture($1);
4383 0           $slash = 'div';
4384             }
4385              
4386             # $$foo[ ... ] --> $ $foo->[ ... ]
4387             elsif ($string =~ /\G \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) ( \[ .+? \] ) /oxmsgc) {
4388 0           $e_string .= e_capture($1.'->'.$2);
4389 0           $slash = 'div';
4390             }
4391              
4392             # $$foo{ ... } --> $ $foo->{ ... }
4393             elsif ($string =~ /\G \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) ( \{ .+? \} ) /oxmsgc) {
4394 0           $e_string .= e_capture($1.'->'.$2);
4395 0           $slash = 'div';
4396             }
4397              
4398             # $$foo
4399             elsif ($string =~ /\G \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) /oxmsgc) {
4400 0           $e_string .= e_capture($1);
4401 0           $slash = 'div';
4402             }
4403              
4404             # ${ foo }
4405             elsif ($string =~ /\G \$ \s* \{ ( \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* ) \} /oxmsgc) {
4406 0           $e_string .= '${' . $1 . '}';
4407 0           $slash = 'div';
4408             }
4409              
4410             # ${ ... }
4411             elsif ($string =~ /\G \$ \s* \{ \s* ( $qq_brace ) \s* \} /oxmsgc) {
4412 0           $e_string .= e_capture($1);
4413 0           $slash = 'div';
4414             }
4415              
4416             # variable or function
4417             # $ @ % & * $ #
4418             elsif ($string =~ /\G ( (?: [\$\@\%\&\*] | \$\# | -> | \b sub \b) \s* (?: split | chop | index | rindex | lc | uc | fc | chr | ord | reverse | getc | tr | y | q | qq | qx | qw | m | s | qr | glob | lstat | opendir | stat | unlink | chdir ) ) \b /oxmsgc) {
4419 0           $e_string .= $1;
4420 0           $slash = 'div';
4421             }
4422             # $ $ $ $ $ $ $ $ $ $ $ $ $ $
4423             # $ @ # \ ' " / ? ( ) [ ] < >
4424             elsif ($string =~ /\G ( \$[\$\@\#\\\'\"\/\?\(\)\[\]\<\>] ) /oxmsgc) {
4425 0           $e_string .= $1;
4426 0           $slash = 'div';
4427             }
4428              
4429             # subroutines of package Char::Ekoi8r
4430 0           elsif ($string =~ /\G \b (CORE:: | ->[ ]* (?: atan2 | [a-z]{2,})) \b /oxgc) { $e_string .= $1; $slash = 'm//'; }
  0            
4431 0           elsif ($string =~ /\G \b Char::KOI8R::eval (?= \s* \{ ) /oxgc) { $e_string .= 'eval'; $slash = 'm//'; }
  0            
4432 0           elsif ($string =~ /\G \b Char::KOI8R::eval \b /oxgc) { $e_string .= 'eval Char::KOI8R::escape'; $slash = 'm//'; }
  0            
4433 0           elsif ($string =~ /\G \b bytes::substr \b /oxgc) { $e_string .= 'substr'; $slash = 'm//'; }
  0            
4434 0           elsif ($string =~ /\G \b chop \b /oxgc) { $e_string .= 'Char::Ekoi8r::chop'; $slash = 'm//'; }
  0            
4435 0           elsif ($string =~ /\G \b bytes::index \b /oxgc) { $e_string .= 'index'; $slash = 'm//'; }
  0            
4436 0           elsif ($string =~ /\G \b Char::KOI8R::index \b /oxgc) { $e_string .= 'Char::KOI8R::index'; $slash = 'm//'; }
  0            
4437 0           elsif ($string =~ /\G \b index \b /oxgc) { $e_string .= 'Char::Ekoi8r::index'; $slash = 'm//'; }
  0            
4438 0           elsif ($string =~ /\G \b bytes::rindex \b /oxgc) { $e_string .= 'rindex'; $slash = 'm//'; }
  0            
4439 0           elsif ($string =~ /\G \b Char::KOI8R::rindex \b /oxgc) { $e_string .= 'Char::KOI8R::rindex'; $slash = 'm//'; }
  0            
4440 0           elsif ($string =~ /\G \b rindex \b /oxgc) { $e_string .= 'Char::Ekoi8r::rindex'; $slash = 'm//'; }
  0            
4441 0           elsif ($string =~ /\G \b lc (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Char::Ekoi8r::lc'; $slash = 'm//'; }
  0            
4442 0           elsif ($string =~ /\G \b lcfirst (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Char::Ekoi8r::lcfirst'; $slash = 'm//'; }
  0            
4443 0           elsif ($string =~ /\G \b uc (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Char::Ekoi8r::uc'; $slash = 'm//'; }
  0            
4444 0           elsif ($string =~ /\G \b ucfirst (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Char::Ekoi8r::ucfirst'; $slash = 'm//'; }
  0            
4445 0           elsif ($string =~ /\G \b fc (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Char::Ekoi8r::fc'; $slash = 'm//'; }
  0            
4446              
4447             # "-s '' ..." means file test "-s 'filename' ..." (not means "- s/// ...")
4448 0           elsif ($string =~ /\G -s \s+ \s* (\") ((?:$qq_char)+?) (\") /oxgc) { $e_string .= '-s ' . e_qq('', $1,$3,$2); $slash = 'm//'; }
  0            
4449 0           elsif ($string =~ /\G -s \s+ qq \s* (\#) ((?:$qq_char)+?) (\#) /oxgc) { $e_string .= '-s ' . e_qq('qq',$1,$3,$2); $slash = 'm//'; }
  0            
4450 0           elsif ($string =~ /\G -s \s+ qq \s* (\() ((?:$qq_paren)+?) (\)) /oxgc) { $e_string .= '-s ' . e_qq('qq',$1,$3,$2); $slash = 'm//'; }
  0            
4451 0           elsif ($string =~ /\G -s \s+ qq \s* (\{) ((?:$qq_brace)+?) (\}) /oxgc) { $e_string .= '-s ' . e_qq('qq',$1,$3,$2); $slash = 'm//'; }
  0            
4452 0           elsif ($string =~ /\G -s \s+ qq \s* (\[) ((?:$qq_bracket)+?) (\]) /oxgc) { $e_string .= '-s ' . e_qq('qq',$1,$3,$2); $slash = 'm//'; }
  0            
4453 0           elsif ($string =~ /\G -s \s+ qq \s* (\<) ((?:$qq_angle)+?) (\>) /oxgc) { $e_string .= '-s ' . e_qq('qq',$1,$3,$2); $slash = 'm//'; }
  0            
4454 0           elsif ($string =~ /\G -s \s+ qq \s* (\S) ((?:$qq_char)+?) (\1) /oxgc) { $e_string .= '-s ' . e_qq('qq',$1,$3,$2); $slash = 'm//'; }
  0            
4455              
4456 0           elsif ($string =~ /\G -s \s+ \s* (\') ((?:\\\'|\\\\|$q_char)+?) (\') /oxgc) { $e_string .= '-s ' . e_q ('', $1,$3,$2); $slash = 'm//'; }
  0            
4457 0           elsif ($string =~ /\G -s \s+ q \s* (\#) ((?:\\\#|\\\\|$q_char)+?) (\#) /oxgc) { $e_string .= '-s ' . e_q ('q', $1,$3,$2); $slash = 'm//'; }
  0            
4458 0           elsif ($string =~ /\G -s \s+ q \s* (\() ((?:\\\)|\\\\|$q_paren)+?) (\)) /oxgc) { $e_string .= '-s ' . e_q ('q', $1,$3,$2); $slash = 'm//'; }
  0            
4459 0           elsif ($string =~ /\G -s \s+ q \s* (\{) ((?:\\\}|\\\\|$q_brace)+?) (\}) /oxgc) { $e_string .= '-s ' . e_q ('q', $1,$3,$2); $slash = 'm//'; }
  0            
4460 0           elsif ($string =~ /\G -s \s+ q \s* (\[) ((?:\\\]|\\\\|$q_bracket)+?) (\]) /oxgc) { $e_string .= '-s ' . e_q ('q', $1,$3,$2); $slash = 'm//'; }
  0            
4461 0           elsif ($string =~ /\G -s \s+ q \s* (\<) ((?:\\\>|\\\\|$q_angle)+?) (\>) /oxgc) { $e_string .= '-s ' . e_q ('q', $1,$3,$2); $slash = 'm//'; }
  0            
4462 0           elsif ($string =~ /\G -s \s+ q \s* (\S) ((?:\\\1|\\\\|$q_char)+?) (\1) /oxgc) { $e_string .= '-s ' . e_q ('q', $1,$3,$2); $slash = 'm//'; }
  0            
4463              
4464             elsif ($string =~ /\G -s \s* (\$ \w+(?: ::\w+)* (?: (?: ->)? (?: [\$\@\%\&\*]\* | \$\#\* | \( (?:$qq_paren)*? \) | [\@\%\*]? \{ (?:$qq_brace)+? \} | [\@\%]? \[ (?:$qq_bracket)+? \] ) )*) /oxgc)
4465 0           { $e_string .= "-s $1"; $slash = 'm//'; }
  0            
4466 0           elsif ($string =~ /\G -s \s* \( ((?:$qq_paren)*?) \) /oxgc) { $e_string .= "-s ($1)"; $slash = 'm//'; }
  0            
4467 0           elsif ($string =~ /\G -s (?= \s+ [a-z]+) /oxgc) { $e_string .= '-s'; $slash = 'm//'; }
  0            
4468 0           elsif ($string =~ /\G -s \s+ (\w+) /oxgc) { $e_string .= "-s $1"; $slash = 'm//'; }
  0            
4469              
4470 0           elsif ($string =~ /\G \b bytes::length (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'length'; $slash = 'm//'; }
  0            
4471 0           elsif ($string =~ /\G \b bytes::chr (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'chr'; $slash = 'm//'; }
  0            
4472 0           elsif ($string =~ /\G \b chr (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Char::Ekoi8r::chr'; $slash = 'm//'; }
  0            
4473 0           elsif ($string =~ /\G \b bytes::ord (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'ord'; $slash = 'div'; }
  0            
4474 0           elsif ($string =~ /\G \b ord (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $e_string .= $function_ord; $slash = 'div'; }
  0            
4475 0           elsif ($string =~ /\G \b glob (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Char::Ekoi8r::glob'; $slash = 'm//'; }
  0            
4476 0           elsif ($string =~ /\G \b lc \b /oxgc) { $e_string .= 'Char::Ekoi8r::lc_'; $slash = 'm//'; }
  0            
4477 0           elsif ($string =~ /\G \b lcfirst \b /oxgc) { $e_string .= 'Char::Ekoi8r::lcfirst_'; $slash = 'm//'; }
  0            
4478 0           elsif ($string =~ /\G \b uc \b /oxgc) { $e_string .= 'Char::Ekoi8r::uc_'; $slash = 'm//'; }
  0            
4479 0           elsif ($string =~ /\G \b ucfirst \b /oxgc) { $e_string .= 'Char::Ekoi8r::ucfirst_'; $slash = 'm//'; }
  0            
4480 0           elsif ($string =~ /\G \b fc \b /oxgc) { $e_string .= 'Char::Ekoi8r::fc_'; $slash = 'm//'; }
  0            
4481 0           elsif ($string =~ /\G -s \b /oxgc) { $e_string .= '-s '; $slash = 'm//'; }
  0            
4482              
4483 0           elsif ($string =~ /\G \b bytes::length \b /oxgc) { $e_string .= 'length'; $slash = 'm//'; }
  0            
4484 0           elsif ($string =~ /\G \b bytes::chr \b /oxgc) { $e_string .= 'chr'; $slash = 'm//'; }
  0            
4485 0           elsif ($string =~ /\G \b chr \b /oxgc) { $e_string .= 'Char::Ekoi8r::chr_'; $slash = 'm//'; }
  0            
4486 0           elsif ($string =~ /\G \b bytes::ord \b /oxgc) { $e_string .= 'ord'; $slash = 'div'; }
  0            
4487 0           elsif ($string =~ /\G \b ord \b /oxgc) { $e_string .= $function_ord_; $slash = 'div'; }
  0            
4488 0           elsif ($string =~ /\G \b glob \b /oxgc) { $e_string .= 'Char::Ekoi8r::glob_'; $slash = 'm//'; }
  0            
4489 0           elsif ($string =~ /\G \b reverse \b /oxgc) { $e_string .= $function_reverse; $slash = 'm//'; }
  0            
4490 0           elsif ($string =~ /\G \b getc \b /oxgc) { $e_string .= $function_getc; $slash = 'm//'; }
  0            
4491             # split
4492             elsif ($string =~ /\G \b (split) \b (?! \s* => ) /oxgc) {
4493 0           $slash = 'm//';
4494              
4495 0           my $e = '';
4496 0           while ($string =~ /\G ( \s+ | \( | \#.* ) /oxgc) {
4497 0           $e .= $1;
4498             }
4499              
4500             # end of split
4501 0 0         if ($string =~ /\G (?= [,;\)\}\]] ) /oxgc) { return 'Char::Ekoi8r::split' . $e; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
4502              
4503             # split scalar value
4504 0           elsif ($string =~ /\G ( [\$\@\&\*] $qq_scalar ) /oxgc) { $e_string .= 'Char::Ekoi8r::split' . $e . e_string($1); next E_STRING_LOOP; }
  0            
4505              
4506             # split literal space
4507 0           elsif ($string =~ /\G \b qq (\#) [ ] (\#) /oxgc) { $e_string .= 'Char::Ekoi8r::split' . $e . qq {qq$1 $2}; next E_STRING_LOOP; }
  0            
4508 0           elsif ($string =~ /\G \b qq (\s*) (\() [ ] (\)) /oxgc) { $e_string .= 'Char::Ekoi8r::split' . $e . qq{$1qq$2 $3}; next E_STRING_LOOP; }
  0            
4509 0           elsif ($string =~ /\G \b qq (\s*) (\{) [ ] (\}) /oxgc) { $e_string .= 'Char::Ekoi8r::split' . $e . qq{$1qq$2 $3}; next E_STRING_LOOP; }
  0            
4510 0           elsif ($string =~ /\G \b qq (\s*) (\[) [ ] (\]) /oxgc) { $e_string .= 'Char::Ekoi8r::split' . $e . qq{$1qq$2 $3}; next E_STRING_LOOP; }
  0            
4511 0           elsif ($string =~ /\G \b qq (\s*) (\<) [ ] (\>) /oxgc) { $e_string .= 'Char::Ekoi8r::split' . $e . qq{$1qq$2 $3}; next E_STRING_LOOP; }
  0            
4512 0           elsif ($string =~ /\G \b qq (\s*) (\S) [ ] (\2) /oxgc) { $e_string .= 'Char::Ekoi8r::split' . $e . qq{$1qq$2 $3}; next E_STRING_LOOP; }
  0            
4513 0           elsif ($string =~ /\G \b q (\#) [ ] (\#) /oxgc) { $e_string .= 'Char::Ekoi8r::split' . $e . qq {q$1 $2}; next E_STRING_LOOP; }
  0            
4514 0           elsif ($string =~ /\G \b q (\s*) (\() [ ] (\)) /oxgc) { $e_string .= 'Char::Ekoi8r::split' . $e . qq {$1q$2 $3}; next E_STRING_LOOP; }
  0            
4515 0           elsif ($string =~ /\G \b q (\s*) (\{) [ ] (\}) /oxgc) { $e_string .= 'Char::Ekoi8r::split' . $e . qq {$1q$2 $3}; next E_STRING_LOOP; }
  0            
4516 0           elsif ($string =~ /\G \b q (\s*) (\[) [ ] (\]) /oxgc) { $e_string .= 'Char::Ekoi8r::split' . $e . qq {$1q$2 $3}; next E_STRING_LOOP; }
  0            
4517 0           elsif ($string =~ /\G \b q (\s*) (\<) [ ] (\>) /oxgc) { $e_string .= 'Char::Ekoi8r::split' . $e . qq {$1q$2 $3}; next E_STRING_LOOP; }
  0            
4518 0           elsif ($string =~ /\G \b q (\s*) (\S) [ ] (\2) /oxgc) { $e_string .= 'Char::Ekoi8r::split' . $e . qq {$1q$2 $3}; next E_STRING_LOOP; }
  0            
4519 0           elsif ($string =~ /\G ' [ ] ' /oxgc) { $e_string .= 'Char::Ekoi8r::split' . $e . qq {' '}; next E_STRING_LOOP; }
  0            
4520 0           elsif ($string =~ /\G " [ ] " /oxgc) { $e_string .= 'Char::Ekoi8r::split' . $e . qq {" "}; next E_STRING_LOOP; }
  0            
4521              
4522             # split qq//
4523             elsif ($string =~ /\G \b (qq) \b /oxgc) {
4524 0 0         if ($string =~ /\G (\#) ((?:$qq_char)*?) (\#) /oxgc) { $e_string .= e_split($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # qq# # --> qr # #
  0            
  0            
4525             else {
4526 0           while ($string !~ /\G \z/oxgc) {
4527 0 0         if ($string =~ /\G (\s+|\#.*) /oxgc) { $e_string .= $e . $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
4528 0           elsif ($string =~ /\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { $e_string .= e_split($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # qq ( ) --> qr ( )
  0            
4529 0           elsif ($string =~ /\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { $e_string .= e_split($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # qq { } --> qr { }
  0            
4530 0           elsif ($string =~ /\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { $e_string .= e_split($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # qq [ ] --> qr [ ]
  0            
4531 0           elsif ($string =~ /\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { $e_string .= e_split($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # qq < > --> qr < >
  0            
4532 0           elsif ($string =~ /\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) /oxgc) { $e_string .= e_split($e.'qr','{','}',$2,''); next E_STRING_LOOP; } # qq | | --> qr { }
  0            
4533 0           elsif ($string =~ /\G (\S) ((?:$qq_char)*?) (\1) /oxgc) { $e_string .= e_split($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # qq * * --> qr * *
  0            
4534             }
4535 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
4536             }
4537             }
4538              
4539             # split qr//
4540             elsif ($string =~ /\G \b (qr) \b /oxgc) {
4541 0 0         if ($string =~ /\G (\#) ((?:$qq_char)*?) (\#) ([imosxpadlubB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1,$3,$2,$4); next E_STRING_LOOP; } # qr# #
  0            
  0            
4542             else {
4543 0           while ($string !~ /\G \z/oxgc) {
4544 0 0         if ($string =~ /\G (\s+|\#.*) /oxgc) { $e_string .= $e . $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
4545 0           elsif ($string =~ /\G (\() ((?:$qq_paren)*?) (\)) ([imosxpadlubB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # qr ( )
  0            
4546 0           elsif ($string =~ /\G (\{) ((?:$qq_brace)*?) (\}) ([imosxpadlubB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # qr { }
  0            
4547 0           elsif ($string =~ /\G (\[) ((?:$qq_bracket)*?) (\]) ([imosxpadlubB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # qr [ ]
  0            
4548 0           elsif ($string =~ /\G (\<) ((?:$qq_angle)*?) (\>) ([imosxpadlubB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # qr < >
  0            
4549 0           elsif ($string =~ /\G (\') ((?:$qq_char)*?) (\') ([imosxpadlubB]*) /oxgc) { $e_string .= e_split_q($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # qr ' '
  0            
4550 0           elsif ($string =~ /\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ([imosxpadlubB]*) /oxgc) { $e_string .= e_split ($e.'qr','{','}',$2,$4); next E_STRING_LOOP; } # qr | | --> qr { }
  0            
4551 0           elsif ($string =~ /\G (\S) ((?:$qq_char)*?) (\1) ([imosxpadlubB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # qr * *
  0            
4552             }
4553 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
4554             }
4555             }
4556              
4557             # split q//
4558             elsif ($string =~ /\G \b (q) \b /oxgc) {
4559 0 0         if ($string =~ /\G (\#) ((?:\\\#|\\\\|$q_char)*?) (\#) /oxgc) { $e_string .= e_split_q($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # q# # --> qr # #
  0            
  0            
4560             else {
4561 0           while ($string !~ /\G \z/oxgc) {
4562 0 0         if ($string =~ /\G (\s+|\#.*) /oxgc) { $e_string .= $e . $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
4563 0           elsif ($string =~ /\G (\() ((?:\\\\|\\\)|\\\(|$q_paren)*?) (\)) /oxgc) { $e_string .= e_split_q($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # q ( ) --> qr ( )
  0            
4564 0           elsif ($string =~ /\G (\{) ((?:\\\\|\\\}|\\\{|$q_brace)*?) (\}) /oxgc) { $e_string .= e_split_q($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # q { } --> qr { }
  0            
4565 0           elsif ($string =~ /\G (\[) ((?:\\\\|\\\]|\\\[|$q_bracket)*?) (\]) /oxgc) { $e_string .= e_split_q($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # q [ ] --> qr [ ]
  0            
4566 0           elsif ($string =~ /\G (\<) ((?:\\\\|\\\>|\\\<|$q_angle)*?) (\>) /oxgc) { $e_string .= e_split_q($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # q < > --> qr < >
  0            
4567 0           elsif ($string =~ /\G ([*\-:?\\^|]) ((?:$q_char)*?) (\1) /oxgc) { $e_string .= e_split_q($e.'qr','{','}',$2,''); next E_STRING_LOOP; } # q | | --> qr { }
  0            
4568 0           elsif ($string =~ /\G (\S) ((?:\\\\|\\\1| $q_char)*?) (\1) /oxgc) { $e_string .= e_split_q($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # q * * --> qr * *
  0            
4569             }
4570 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
4571             }
4572             }
4573              
4574             # split m//
4575             elsif ($string =~ /\G \b (m) \b /oxgc) {
4576 0 0         if ($string =~ /\G (\#) ((?:$qq_char)*?) (\#) ([cgimosxpadlubB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1,$3,$2,$4); next E_STRING_LOOP; } # m# # --> qr # #
  0            
  0            
4577             else {
4578 0           while ($string !~ /\G \z/oxgc) {
4579 0 0         if ($string =~ /\G (\s+|\#.*) /oxgc) { $e_string .= $e . $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
4580 0           elsif ($string =~ /\G (\() ((?:$qq_paren)*?) (\)) ([cgimosxpadlubB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # m ( ) --> qr ( )
  0            
4581 0           elsif ($string =~ /\G (\{) ((?:$qq_brace)*?) (\}) ([cgimosxpadlubB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # m { } --> qr { }
  0            
4582 0           elsif ($string =~ /\G (\[) ((?:$qq_bracket)*?) (\]) ([cgimosxpadlubB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # m [ ] --> qr [ ]
  0            
4583 0           elsif ($string =~ /\G (\<) ((?:$qq_angle)*?) (\>) ([cgimosxpadlubB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # m < > --> qr < >
  0            
4584 0           elsif ($string =~ /\G (\') ((?:$qq_char)*?) (\') ([cgimosxpadlubB]*) /oxgc) { $e_string .= e_split_q($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # m ' ' --> qr ' '
  0            
4585 0           elsif ($string =~ /\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ([cgimosxpadlubB]*) /oxgc) { $e_string .= e_split ($e.'qr','{','}',$2,$4); next E_STRING_LOOP; } # m | | --> qr { }
  0            
4586 0           elsif ($string =~ /\G (\S) ((?:$qq_char)*?) (\1) ([cgimosxpadlubB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # m * * --> qr * *
  0            
4587             }
4588 0           die __FILE__, ": Search pattern not terminated";
4589             }
4590             }
4591              
4592             # split ''
4593             elsif ($string =~ /\G (\') /oxgc) {
4594 0           my $q_string = '';
4595 0           while ($string !~ /\G \z/oxgc) {
4596 0 0         if ($string =~ /\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0          
    0          
    0          
4597 0           elsif ($string =~ /\G (\\\') /oxgc) { $q_string .= $1; } # splitqr'' --> split qr''
4598 0           elsif ($string =~ /\G \' /oxgc) { $e_string .= e_split_q($e.q{ qr},"'","'",$q_string,''); next E_STRING_LOOP; } # ' ' --> qr ' '
  0            
4599 0           elsif ($string =~ /\G ($q_char) /oxgc) { $q_string .= $1; }
4600             }
4601 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
4602             }
4603              
4604             # split ""
4605             elsif ($string =~ /\G (\") /oxgc) {
4606 0           my $qq_string = '';
4607 0           while ($string !~ /\G \z/oxgc) {
4608 0 0         if ($string =~ /\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0          
    0          
    0          
4609 0           elsif ($string =~ /\G (\\\") /oxgc) { $qq_string .= $1; } # splitqr"" --> split qr""
4610 0           elsif ($string =~ /\G \" /oxgc) { $e_string .= e_split($e.q{ qr},'"','"',$qq_string,''); next E_STRING_LOOP; } # " " --> qr " "
  0            
4611 0           elsif ($string =~ /\G ($q_char) /oxgc) { $qq_string .= $1; }
4612             }
4613 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
4614             }
4615              
4616             # split //
4617             elsif ($string =~ /\G (\/) /oxgc) {
4618 0           my $regexp = '';
4619 0           while ($string !~ /\G \z/oxgc) {
4620 0 0         if ($string =~ /\G (\\\\) /oxgc) { $regexp .= $1; }
  0 0          
    0          
    0          
4621 0           elsif ($string =~ /\G (\\\/) /oxgc) { $regexp .= $1; } # splitqr// --> split qr//
4622 0           elsif ($string =~ /\G \/ ([cgimosxpadlubB]*) /oxgc) { $e_string .= e_split($e.q{ qr}, '/','/',$regexp,$1); next E_STRING_LOOP; } # / / --> qr / /
  0            
4623 0           elsif ($string =~ /\G ($q_char) /oxgc) { $regexp .= $1; }
4624             }
4625 0           die __FILE__, ": Search pattern not terminated";
4626             }
4627             }
4628              
4629             # qq//
4630             elsif ($string =~ /\G \b (qq) \b /oxgc) {
4631 0           my $ope = $1;
4632 0 0         if ($string =~ /\G (\#) ((?:$qq_char)*?) (\#) /oxgc) { # qq# #
4633 0           $e_string .= e_qq($ope,$1,$3,$2);
4634             }
4635             else {
4636 0           my $e = '';
4637 0           while ($string !~ /\G \z/oxgc) {
4638 0 0         if ($string =~ /\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
4639 0           elsif ($string =~ /\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qq ( )
  0            
4640 0           elsif ($string =~ /\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qq { }
  0            
4641 0           elsif ($string =~ /\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qq [ ]
  0            
4642 0           elsif ($string =~ /\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qq < >
  0            
4643 0           elsif ($string =~ /\G (\S) ((?:$qq_char)*?) (\1) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qq * *
  0            
4644             }
4645 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
4646             }
4647             }
4648              
4649             # qx//
4650             elsif ($string =~ /\G \b (qx) \b /oxgc) {
4651 0           my $ope = $1;
4652 0 0         if ($string =~ /\G (\#) ((?:$qq_char)*?) (\#) /oxgc) { # qx# #
4653 0           $e_string .= e_qq($ope,$1,$3,$2);
4654             }
4655             else {
4656 0           my $e = '';
4657 0           while ($string !~ /\G \z/oxgc) {
4658 0 0         if ($string =~ /\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
4659 0           elsif ($string =~ /\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qx ( )
  0            
4660 0           elsif ($string =~ /\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qx { }
  0            
4661 0           elsif ($string =~ /\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qx [ ]
  0            
4662 0           elsif ($string =~ /\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qx < >
  0            
4663 0           elsif ($string =~ /\G (\') ((?:$qq_char)*?) (\') /oxgc) { $e_string .= $e . e_q ($ope,$1,$3,$2); next E_STRING_LOOP; } # qx ' '
  0            
4664 0           elsif ($string =~ /\G (\S) ((?:$qq_char)*?) (\1) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qx * *
  0            
4665             }
4666 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
4667             }
4668             }
4669              
4670             # q//
4671             elsif ($string =~ /\G \b (q) \b /oxgc) {
4672 0           my $ope = $1;
4673 0 0         if ($string =~ /\G (\#) ((?:\\\#|\\\\|$q_char)*?) (\#) /oxgc) { # q# #
4674 0           $e_string .= e_q($ope,$1,$3,$2);
4675             }
4676             else {
4677 0           my $e = '';
4678 0           while ($string !~ /\G \z/oxgc) {
4679 0 0         if ($string =~ /\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
4680 0           elsif ($string =~ /\G (\() ((?:\\\\|\\\)|\\\(|$q_paren)*?) (\)) /oxgc) { $e_string .= $e . e_q($ope,$1,$3,$2); next E_STRING_LOOP; } # q ( )
  0            
4681 0           elsif ($string =~ /\G (\{) ((?:\\\\|\\\}|\\\{|$q_brace)*?) (\}) /oxgc) { $e_string .= $e . e_q($ope,$1,$3,$2); next E_STRING_LOOP; } # q { }
  0            
4682 0           elsif ($string =~ /\G (\[) ((?:\\\\|\\\]|\\\[|$q_bracket)*?) (\]) /oxgc) { $e_string .= $e . e_q($ope,$1,$3,$2); next E_STRING_LOOP; } # q [ ]
  0            
4683 0           elsif ($string =~ /\G (\<) ((?:\\\\|\\\>|\\\<|$q_angle)*?) (\>) /oxgc) { $e_string .= $e . e_q($ope,$1,$3,$2); next E_STRING_LOOP; } # q < >
  0            
4684 0           elsif ($string =~ /\G (\S) ((?:\\\\|\\\1| $q_char)*?) (\1) /oxgc) { $e_string .= $e . e_q($ope,$1,$3,$2); next E_STRING_LOOP; } # q * *
  0            
4685             }
4686 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
4687             }
4688             }
4689              
4690             # ''
4691 0           elsif ($string =~ /\G (?
4692              
4693             # ""
4694 0           elsif ($string =~ /\G (\") ((?:$qq_char)*?) (\") /oxgc) { $e_string .= e_qq('',$1,$3,$2); }
4695              
4696             # ``
4697 0           elsif ($string =~ /\G (\`) ((?:$qq_char)*?) (\`) /oxgc) { $e_string .= e_qq('',$1,$3,$2); }
4698              
4699             # <<= <=> <= < operator
4700             elsif ($string =~ /\G ( <<= | <=> | <= | < ) (?= \s* [A-Za-z_0-9'"`\$\@\&\*\(\+\-] )/oxgc)
4701 0           { $e_string .= $1; }
4702              
4703             #
4704 0           elsif ($string =~ /\G (<[\$]?[A-Za-z_][A-Za-z_0-9]*>) /oxgc) { $e_string .= $1; }
4705              
4706             # --- glob
4707             elsif ($string =~ /\G < ((?:$q_char)+?) > /oxgc) {
4708 0           $e_string .= 'Char::Ekoi8r::glob("' . $1 . '")';
4709             }
4710              
4711             # << (bit shift) --- not here document
4712 0           elsif ($string =~ /\G ( << \s* ) (?= [0-9\$\@\&] ) /oxgc) { $slash = 'm//'; $e_string .= $1; }
  0            
4713              
4714             # <<'HEREDOC'
4715             elsif ($string =~ /\G ( << '([a-zA-Z_0-9]*)' ) /oxgc) {
4716 0           $slash = 'm//';
4717 0           my $here_quote = $1;
4718 0           my $delimiter = $2;
4719              
4720             # get here document
4721 0 0         if ($here_script eq '') {
4722 0           $here_script = CORE::substr $_, pos $_;
4723 0           $here_script =~ s/.*?\n//oxm;
4724             }
4725 0 0         if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4726 0           push @heredoc, $1 . qq{\n$delimiter\n};
4727 0           push @heredoc_delimiter, $delimiter;
4728             }
4729             else {
4730 0           die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF";
4731             }
4732 0           $e_string .= $here_quote;
4733             }
4734              
4735             # <<\HEREDOC
4736             elsif ($string =~ /\G ( << \\([a-zA-Z_0-9]+) ) /oxgc) {
4737 0           $slash = 'm//';
4738 0           my $here_quote = $1;
4739 0           my $delimiter = $2;
4740              
4741             # get here document
4742 0 0         if ($here_script eq '') {
4743 0           $here_script = CORE::substr $_, pos $_;
4744 0           $here_script =~ s/.*?\n//oxm;
4745             }
4746 0 0         if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4747 0           push @heredoc, $1 . qq{\n$delimiter\n};
4748 0           push @heredoc_delimiter, $delimiter;
4749             }
4750             else {
4751 0           die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF";
4752             }
4753 0           $e_string .= $here_quote;
4754             }
4755              
4756             # <<"HEREDOC"
4757             elsif ($string =~ /\G ( << "([a-zA-Z_0-9]*)" ) /oxgc) {
4758 0           $slash = 'm//';
4759 0           my $here_quote = $1;
4760 0           my $delimiter = $2;
4761              
4762             # get here document
4763 0 0         if ($here_script eq '') {
4764 0           $here_script = CORE::substr $_, pos $_;
4765 0           $here_script =~ s/.*?\n//oxm;
4766             }
4767 0 0         if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4768 0           push @heredoc, e_heredoc($1) . qq{\n$delimiter\n};
4769 0           push @heredoc_delimiter, $delimiter;
4770             }
4771             else {
4772 0           die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF";
4773             }
4774 0           $e_string .= $here_quote;
4775             }
4776              
4777             # <
4778             elsif ($string =~ /\G ( << ([a-zA-Z_0-9]+) ) /oxgc) {
4779 0           $slash = 'm//';
4780 0           my $here_quote = $1;
4781 0           my $delimiter = $2;
4782              
4783             # get here document
4784 0 0         if ($here_script eq '') {
4785 0           $here_script = CORE::substr $_, pos $_;
4786 0           $here_script =~ s/.*?\n//oxm;
4787             }
4788 0 0         if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4789 0           push @heredoc, e_heredoc($1) . qq{\n$delimiter\n};
4790 0           push @heredoc_delimiter, $delimiter;
4791             }
4792             else {
4793 0           die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF";
4794             }
4795 0           $e_string .= $here_quote;
4796             }
4797              
4798             # <<`HEREDOC`
4799             elsif ($string =~ /\G ( << `([a-zA-Z_0-9]*)` ) /oxgc) {
4800 0           $slash = 'm//';
4801 0           my $here_quote = $1;
4802 0           my $delimiter = $2;
4803              
4804             # get here document
4805 0 0         if ($here_script eq '') {
4806 0           $here_script = CORE::substr $_, pos $_;
4807 0           $here_script =~ s/.*?\n//oxm;
4808             }
4809 0 0         if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4810 0           push @heredoc, e_heredoc($1) . qq{\n$delimiter\n};
4811 0           push @heredoc_delimiter, $delimiter;
4812             }
4813             else {
4814 0           die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF";
4815             }
4816 0           $e_string .= $here_quote;
4817             }
4818              
4819             # any operator before div
4820             elsif ($string =~ /\G (
4821             -- | \+\+ |
4822             [\)\}\]]
4823              
4824 0           ) /oxgc) { $slash = 'div'; $e_string .= $1; }
  0            
4825              
4826             # yada-yada or triple-dot operator
4827             elsif ($string =~ /\G (
4828             \.\.\.
4829              
4830 0           ) /oxgc) { $slash = 'm//'; $e_string .= q{die('Unimplemented')}; }
  0            
4831              
4832             # any operator before m//
4833             elsif ($string =~ /\G (
4834              
4835             !~~ | !~ | != | ! |
4836             %= | % |
4837             &&= | && | &= | & |
4838             -= | -> | - |
4839             :\s*= |
4840             : |
4841             <<= | <=> | <= | < |
4842             == | => | =~ | = |
4843             >>= | >> | >= | > |
4844             \*\*= | \*\* | \*= | \* |
4845             \+= | \+ |
4846             \.\. | \.= | \. |
4847             \/\/= | \/\/ |
4848             \/= | \/ |
4849             \? |
4850             \\ |
4851             \^= | \^ |
4852             \b x= |
4853             \|\|= | \|\| | \|= | \| |
4854             ~~ | ~ |
4855             \b(?: and | cmp | eq | ge | gt | le | lt | ne | not | or | xor | x )\b |
4856             \b(?: print )\b |
4857              
4858             [,;\(\{\[]
4859              
4860 0           ) /oxgc) { $slash = 'm//'; $e_string .= $1; }
  0            
4861              
4862             # other any character
4863 0           elsif ($string =~ /\G ($q_char) /oxgc) { $e_string .= $1; }
4864              
4865             # system error
4866             else {
4867 0           die __FILE__, ": Oops, this shouldn't happen!";
4868             }
4869             }
4870              
4871 0           return $e_string;
4872             }
4873              
4874             #
4875             # character class
4876             #
4877             sub character_class {
4878 0     0 0   my($char,$modifier) = @_;
4879              
4880 0 0         if ($char eq '.') {
4881 0 0         if ($modifier =~ /s/) {
4882 0           return '${Char::Ekoi8r::dot_s}';
4883             }
4884             else {
4885 0           return '${Char::Ekoi8r::dot}';
4886             }
4887             }
4888             else {
4889 0           return Char::Ekoi8r::classic_character_class($char);
4890             }
4891             }
4892              
4893             #
4894             # escape capture ($1, $2, $3, ...)
4895             #
4896             sub e_capture {
4897              
4898 0     0 0   return join '', '${', $_[0], '}';
4899             }
4900              
4901             #
4902             # escape transliteration (tr/// or y///)
4903             #
4904             sub e_tr {
4905 0     0 0   my($variable,$charclass,$e,$charclass2,$modifier) = @_;
4906 0           my $e_tr = '';
4907 0   0       $modifier ||= '';
4908              
4909 0           $slash = 'div';
4910              
4911             # quote character class 1
4912 0           $charclass = q_tr($charclass);
4913              
4914             # quote character class 2
4915 0           $charclass2 = q_tr($charclass2);
4916              
4917             # /b /B modifier
4918 0 0         if ($modifier =~ tr/bB//d) {
4919 0 0         if ($variable eq '') {
4920 0           $e_tr = qq{tr$charclass$e$charclass2$modifier};
4921             }
4922             else {
4923 0           $e_tr = qq{$variable${bind_operator}tr$charclass$e$charclass2$modifier};
4924             }
4925             }
4926             else {
4927 0 0         if ($variable eq '') {
4928 0           $e_tr = qq{Char::Ekoi8r::tr(\$_,' =~ ',$charclass,$e$charclass2,'$modifier')};
4929             }
4930             else {
4931 0           $e_tr = qq{Char::Ekoi8r::tr($variable,'$bind_operator',$charclass,$e$charclass2,'$modifier')};
4932             }
4933             }
4934              
4935             # clear tr/// variable
4936 0           $tr_variable = '';
4937 0           $bind_operator = '';
4938              
4939 0           return $e_tr;
4940             }
4941              
4942             #
4943             # quote for escape transliteration (tr/// or y///)
4944             #
4945             sub q_tr {
4946 0     0 0   my($charclass) = @_;
4947              
4948             # quote character class
4949 0 0         if ($charclass !~ /'/oxms) {
    0          
    0          
    0          
    0          
    0          
4950 0           return e_q('', "'", "'", $charclass); # --> q' '
4951             }
4952             elsif ($charclass !~ /\//oxms) {
4953 0           return e_q('q', '/', '/', $charclass); # --> q/ /
4954             }
4955             elsif ($charclass !~ /\#/oxms) {
4956 0           return e_q('q', '#', '#', $charclass); # --> q# #
4957             }
4958             elsif ($charclass !~ /[\<\>]/oxms) {
4959 0           return e_q('q', '<', '>', $charclass); # --> q< >
4960             }
4961             elsif ($charclass !~ /[\(\)]/oxms) {
4962 0           return e_q('q', '(', ')', $charclass); # --> q( )
4963             }
4964             elsif ($charclass !~ /[\{\}]/oxms) {
4965 0           return e_q('q', '{', '}', $charclass); # --> q{ }
4966             }
4967             else {
4968 0           for my $char (qw( ! " $ % & * + . : = ? @ ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
4969 0 0         if ($charclass !~ /\Q$char\E/xms) {
4970 0           return e_q('q', $char, $char, $charclass);
4971             }
4972             }
4973             }
4974              
4975 0           return e_q('q', '{', '}', $charclass);
4976             }
4977              
4978             #
4979             # escape q string (q//, '')
4980             #
4981             sub e_q {
4982 0     0 0   my($ope,$delimiter,$end_delimiter,$string) = @_;
4983              
4984 0           $slash = 'div';
4985              
4986 0           return join '', $ope, $delimiter, $string, $end_delimiter;
4987             }
4988              
4989             #
4990             # escape qq string (qq//, "", qx//, ``)
4991             #
4992             sub e_qq {
4993 0     0 0   my($ope,$delimiter,$end_delimiter,$string) = @_;
4994              
4995 0           $slash = 'div';
4996              
4997 0           my $left_e = 0;
4998 0           my $right_e = 0;
4999 0           my @char = $string =~ /\G(
5000             \\o\{ [0-7]+ \} |
5001             \\x\{ [0-9A-Fa-f]+ \} |
5002             \\N\{ [^0-9\}][^\}]* \} |
5003             \$` | \$\{`\} | \$ \s* PREMATCH | \$ \s* \{ \s* PREMATCH \s* \} | \$ \s* \{\^PREMATCH\} |
5004             \$& | \$\{&\} | \$ \s* MATCH | \$ \s* \{ \s* MATCH \s* \} | \$ \s* \{\^MATCH\} |
5005             \$ \s* POSTMATCH | \$ \s* \{ \s* POSTMATCH \s* \} | \$ \s* \{\^POSTMATCH\} |
5006             \$ \s* \d+ |
5007             \$ \s* \{ \s* \d+ \s* \} |
5008             \$ \$ (?![\w\{]) |
5009             \$ \s* \$ \s* $qq_variable |
5010             \\?(?:$q_char)
5011             )/oxmsg;
5012              
5013 0           for (my $i=0; $i <= $#char; $i++) {
5014              
5015             # "\L\u" --> "\u\L"
5016 0 0 0       if (($char[$i] eq '\L') and ($char[$i+1] eq '\u')) {
    0 0        
    0          
    0          
    0          
5017 0           @char[$i,$i+1] = @char[$i+1,$i];
5018             }
5019              
5020             # "\U\l" --> "\l\U"
5021             elsif (($char[$i] eq '\U') and ($char[$i+1] eq '\l')) {
5022 0           @char[$i,$i+1] = @char[$i+1,$i];
5023             }
5024              
5025             # octal escape sequence
5026             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
5027 0           $char[$i] = Char::Ekoi8r::octchr($1);
5028             }
5029              
5030             # hexadecimal escape sequence
5031             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
5032 0           $char[$i] = Char::Ekoi8r::hexchr($1);
5033             }
5034              
5035             # \N{CHARNAME} --> N{CHARNAME}
5036             elsif ($char[$i] =~ /\A \\ ( N\{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
5037 0           $char[$i] = $1;
5038             }
5039              
5040 0 0         if (0) {
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
5041             }
5042              
5043             # \F
5044             #
5045             # P.69 Table 2-6. Translation escapes
5046             # in Chapter 2: Bits and Pieces
5047             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
5048             # (and so on)
5049              
5050             # \u \l \U \L \F \Q \E
5051 0           elsif ($char[$i] =~ /\A ([<>]) \z/oxms) {
5052 0 0         if ($right_e < $left_e) {
5053 0           $char[$i] = '\\' . $char[$i];
5054             }
5055             }
5056             elsif ($char[$i] eq '\u') {
5057              
5058             # "STRING @{[ LIST EXPR ]} MORE STRING"
5059              
5060             # P.257 Other Tricks You Can Do with Hard References
5061             # in Chapter 8: References
5062             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
5063              
5064             # P.353 Other Tricks You Can Do with Hard References
5065             # in Chapter 8: References
5066             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
5067              
5068             # (and so on)
5069              
5070 0           $char[$i] = '@{[Char::Ekoi8r::ucfirst qq<';
5071 0           $left_e++;
5072             }
5073             elsif ($char[$i] eq '\l') {
5074 0           $char[$i] = '@{[Char::Ekoi8r::lcfirst qq<';
5075 0           $left_e++;
5076             }
5077             elsif ($char[$i] eq '\U') {
5078 0           $char[$i] = '@{[Char::Ekoi8r::uc qq<';
5079 0           $left_e++;
5080             }
5081             elsif ($char[$i] eq '\L') {
5082 0           $char[$i] = '@{[Char::Ekoi8r::lc qq<';
5083 0           $left_e++;
5084             }
5085             elsif ($char[$i] eq '\F') {
5086 0           $char[$i] = '@{[Char::Ekoi8r::fc qq<';
5087 0           $left_e++;
5088             }
5089             elsif ($char[$i] eq '\Q') {
5090 0           $char[$i] = '@{[CORE::quotemeta qq<';
5091 0           $left_e++;
5092             }
5093             elsif ($char[$i] eq '\E') {
5094 0 0         if ($right_e < $left_e) {
5095 0           $char[$i] = '>]}';
5096 0           $right_e++;
5097             }
5098             else {
5099 0           $char[$i] = '';
5100             }
5101             }
5102             elsif ($char[$i] eq '\Q') {
5103 0           while (1) {
5104 0 0         if (++$i > $#char) {
5105 0           last;
5106             }
5107 0 0         if ($char[$i] eq '\E') {
5108 0           last;
5109             }
5110             }
5111             }
5112             elsif ($char[$i] eq '\E') {
5113             }
5114              
5115             # $0 --> $0
5116             elsif ($char[$i] =~ /\A \$ 0 \z/oxms) {
5117             }
5118             elsif ($char[$i] =~ /\A \$ \{ \s* 0 \s* \} \z/oxms) {
5119             }
5120              
5121             # $$ --> $$
5122             elsif ($char[$i] =~ /\A \$\$ \z/oxms) {
5123             }
5124              
5125             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
5126             # $1, $2, $3 --> $1, $2, $3 otherwise
5127             elsif ($char[$i] =~ /\A \$ ([1-9][0-9]*) \z/oxms) {
5128 0           $char[$i] = e_capture($1);
5129             }
5130             elsif ($char[$i] =~ /\A \$ \{ \s* ([1-9][0-9]*) \s* \} \z/oxms) {
5131 0           $char[$i] = e_capture($1);
5132             }
5133              
5134             # $$foo[ ... ] --> $ $foo->[ ... ]
5135             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) ( \[ (?:$qq_bracket)*? \] ) \z/oxms) {
5136 0           $char[$i] = e_capture($1.'->'.$2);
5137             }
5138              
5139             # $$foo{ ... } --> $ $foo->{ ... }
5140             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) ( \{ (?:$qq_brace)*? \} ) \z/oxms) {
5141 0           $char[$i] = e_capture($1.'->'.$2);
5142             }
5143              
5144             # $$foo
5145             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) \z/oxms) {
5146 0           $char[$i] = e_capture($1);
5147             }
5148              
5149             # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Char::Ekoi8r::PREMATCH()
5150             elsif ($char[$i] =~ /\A ( \$` | \$\{`\} | \$ \s* PREMATCH | \$ \s* \{ \s* PREMATCH \s* \} | \$ \s* \{\^PREMATCH\} ) \z/oxmsgc) {
5151 0           $char[$i] = '@{[Char::Ekoi8r::PREMATCH()]}';
5152             }
5153              
5154             # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Char::Ekoi8r::MATCH()
5155             elsif ($char[$i] =~ /\A ( \$& | \$\{&\} | \$ \s* MATCH | \$ \s* \{ \s* MATCH \s* \} | \$ \s* \{\^MATCH\} ) \z/oxmsgc) {
5156 0           $char[$i] = '@{[Char::Ekoi8r::MATCH()]}';
5157             }
5158              
5159             # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Char::Ekoi8r::POSTMATCH()
5160             elsif ($char[$i] =~ /\A ( \$ \s* POSTMATCH | \$ \s* \{ \s* POSTMATCH \s* \} | \$ \s* \{\^POSTMATCH\} ) \z/oxmsgc) {
5161 0           $char[$i] = '@{[Char::Ekoi8r::POSTMATCH()]}';
5162             }
5163              
5164             # ${ foo } --> ${ foo }
5165             elsif ($char[$i] =~ /\A \$ \s* \{ \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* \} \z/oxms) {
5166             }
5167              
5168             # ${ ... }
5169             elsif ($char[$i] =~ /\A \$ \s* \{ \s* ( .+ ) \s* \} \z/oxms) {
5170 0           $char[$i] = e_capture($1);
5171             }
5172             }
5173              
5174             # return string
5175 0 0         if ($left_e > $right_e) {
5176 0           return join '', $ope, $delimiter, @char, '>]}' x ($left_e - $right_e), $end_delimiter;
5177             }
5178 0           return join '', $ope, $delimiter, @char, $end_delimiter;
5179             }
5180              
5181             #
5182             # escape qw string (qw//)
5183             #
5184             sub e_qw {
5185 0     0 0   my($ope,$delimiter,$end_delimiter,$string) = @_;
5186              
5187 0           $slash = 'div';
5188              
5189             # choice again delimiter
5190 0           my %octet = map {$_ => 1} ($string =~ /\G ([\x00-\xFF]) /oxmsg);
  0            
5191 0 0         if (not $octet{$end_delimiter}) {
    0          
    0          
    0          
    0          
5192 0           return join '', $ope, $delimiter, $string, $end_delimiter;
5193             }
5194             elsif (not $octet{')'}) {
5195 0           return join '', $ope, '(', $string, ')';
5196             }
5197             elsif (not $octet{'}'}) {
5198 0           return join '', $ope, '{', $string, '}';
5199             }
5200             elsif (not $octet{']'}) {
5201 0           return join '', $ope, '[', $string, ']';
5202             }
5203             elsif (not $octet{'>'}) {
5204 0           return join '', $ope, '<', $string, '>';
5205             }
5206             else {
5207 0           for my $char (qw( ! " $ % & * + - . / : = ? @ ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
5208 0 0         if (not $octet{$char}) {
5209 0           return join '', $ope, $char, $string, $char;
5210             }
5211             }
5212             }
5213              
5214             # qw/AAA BBB C'CC/ --> ('AAA', 'BBB', 'C\'CC')
5215 0           my @string = CORE::split(/\s+/, $string);
5216 0           for my $string (@string) {
5217 0           my @octet = $string =~ /\G ([\x00-\xFF]) /oxmsg;
5218 0           for my $octet (@octet) {
5219 0 0         if ($octet =~ /\A (['\\]) \z/oxms) {
5220 0           $octet = '\\' . $1;
5221             }
5222             }
5223 0           $string = join '', @octet;
5224             }
5225 0           return join '', '(', (join ', ', map { "'$_'" } @string), ')';
  0            
5226             }
5227              
5228             #
5229             # escape here document (<<"HEREDOC", <
5230             #
5231             sub e_heredoc {
5232 0     0 0   my($string) = @_;
5233              
5234 0           $slash = 'm//';
5235              
5236 0           my $metachar = qr/[\@\\|]/oxms; # '|' is for <<`HEREDOC`
5237              
5238 0           my $left_e = 0;
5239 0           my $right_e = 0;
5240 0           my @char = $string =~ /\G(
5241             \\o\{ [0-7]+ \} |
5242             \\x\{ [0-9A-Fa-f]+ \} |
5243             \\N\{ [^0-9\}][^\}]* \} |
5244             \$` | \$\{`\} | \$ \s* PREMATCH | \$ \s* \{ \s* PREMATCH \s* \} | \$ \s* \{\^PREMATCH\} |
5245             \$& | \$\{&\} | \$ \s* MATCH | \$ \s* \{ \s* MATCH \s* \} | \$ \s* \{\^MATCH\} |
5246             \$ \s* POSTMATCH | \$ \s* \{ \s* POSTMATCH \s* \} | \$ \s* \{\^POSTMATCH\} |
5247             \$ \s* \d+ |
5248             \$ \s* \{ \s* \d+ \s* \} |
5249             \$ \$ (?![\w\{]) |
5250             \$ \s* \$ \s* $qq_variable |
5251             \\?(?:$q_char)
5252             )/oxmsg;
5253              
5254 0           for (my $i=0; $i <= $#char; $i++) {
5255              
5256             # "\L\u" --> "\u\L"
5257 0 0 0       if (($char[$i] eq '\L') and ($char[$i+1] eq '\u')) {
    0 0        
    0          
    0          
    0          
5258 0           @char[$i,$i+1] = @char[$i+1,$i];
5259             }
5260              
5261             # "\U\l" --> "\l\U"
5262             elsif (($char[$i] eq '\U') and ($char[$i+1] eq '\l')) {
5263 0           @char[$i,$i+1] = @char[$i+1,$i];
5264             }
5265              
5266             # octal escape sequence
5267             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
5268 0           $char[$i] = Char::Ekoi8r::octchr($1);
5269             }
5270              
5271             # hexadecimal escape sequence
5272             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
5273 0           $char[$i] = Char::Ekoi8r::hexchr($1);
5274             }
5275              
5276             # \N{CHARNAME} --> N{CHARNAME}
5277             elsif ($char[$i] =~ /\A \\ ( N\{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
5278 0           $char[$i] = $1;
5279             }
5280              
5281 0 0         if (0) {
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
5282             }
5283              
5284             # \u \l \U \L \F \Q \E
5285 0           elsif ($char[$i] =~ /\A ([<>]) \z/oxms) {
5286 0 0         if ($right_e < $left_e) {
5287 0           $char[$i] = '\\' . $char[$i];
5288             }
5289             }
5290             elsif ($char[$i] eq '\u') {
5291 0           $char[$i] = '@{[Char::Ekoi8r::ucfirst qq<';
5292 0           $left_e++;
5293             }
5294             elsif ($char[$i] eq '\l') {
5295 0           $char[$i] = '@{[Char::Ekoi8r::lcfirst qq<';
5296 0           $left_e++;
5297             }
5298             elsif ($char[$i] eq '\U') {
5299 0           $char[$i] = '@{[Char::Ekoi8r::uc qq<';
5300 0           $left_e++;
5301             }
5302             elsif ($char[$i] eq '\L') {
5303 0           $char[$i] = '@{[Char::Ekoi8r::lc qq<';
5304 0           $left_e++;
5305             }
5306             elsif ($char[$i] eq '\F') {
5307 0           $char[$i] = '@{[Char::Ekoi8r::fc qq<';
5308 0           $left_e++;
5309             }
5310             elsif ($char[$i] eq '\Q') {
5311 0           $char[$i] = '@{[CORE::quotemeta qq<';
5312 0           $left_e++;
5313             }
5314             elsif ($char[$i] eq '\E') {
5315 0 0         if ($right_e < $left_e) {
5316 0           $char[$i] = '>]}';
5317 0           $right_e++;
5318             }
5319             else {
5320 0           $char[$i] = '';
5321             }
5322             }
5323             elsif ($char[$i] eq '\Q') {
5324 0           while (1) {
5325 0 0         if (++$i > $#char) {
5326 0           last;
5327             }
5328 0 0         if ($char[$i] eq '\E') {
5329 0           last;
5330             }
5331             }
5332             }
5333             elsif ($char[$i] eq '\E') {
5334             }
5335              
5336             # $0 --> $0
5337             elsif ($char[$i] =~ /\A \$ 0 \z/oxms) {
5338             }
5339             elsif ($char[$i] =~ /\A \$ \{ \s* 0 \s* \} \z/oxms) {
5340             }
5341              
5342             # $$ --> $$
5343             elsif ($char[$i] =~ /\A \$\$ \z/oxms) {
5344             }
5345              
5346             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
5347             # $1, $2, $3 --> $1, $2, $3 otherwise
5348             elsif ($char[$i] =~ /\A \$ ([1-9][0-9]*) \z/oxms) {
5349 0           $char[$i] = e_capture($1);
5350             }
5351             elsif ($char[$i] =~ /\A \$ \{ \s* ([1-9][0-9]*) \s* \} \z/oxms) {
5352 0           $char[$i] = e_capture($1);
5353             }
5354              
5355             # $$foo[ ... ] --> $ $foo->[ ... ]
5356             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) ( \[ (?:$qq_bracket)*? \] ) \z/oxms) {
5357 0           $char[$i] = e_capture($1.'->'.$2);
5358             }
5359              
5360             # $$foo{ ... } --> $ $foo->{ ... }
5361             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) ( \{ (?:$qq_brace)*? \} ) \z/oxms) {
5362 0           $char[$i] = e_capture($1.'->'.$2);
5363             }
5364              
5365             # $$foo
5366             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) \z/oxms) {
5367 0           $char[$i] = e_capture($1);
5368             }
5369              
5370             # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Char::Ekoi8r::PREMATCH()
5371             elsif ($char[$i] =~ /\A ( \$` | \$\{`\} | \$ \s* PREMATCH | \$ \s* \{ \s* PREMATCH \s* \} | \$ \s* \{\^PREMATCH\} ) \z/oxmsgc) {
5372 0           $char[$i] = '@{[Char::Ekoi8r::PREMATCH()]}';
5373             }
5374              
5375             # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Char::Ekoi8r::MATCH()
5376             elsif ($char[$i] =~ /\A ( \$& | \$\{&\} | \$ \s* MATCH | \$ \s* \{ \s* MATCH \s* \} | \$ \s* \{\^MATCH\} ) \z/oxmsgc) {
5377 0           $char[$i] = '@{[Char::Ekoi8r::MATCH()]}';
5378             }
5379              
5380             # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Char::Ekoi8r::POSTMATCH()
5381             elsif ($char[$i] =~ /\A ( \$ \s* POSTMATCH | \$ \s* \{ \s* POSTMATCH \s* \} | \$ \s* \{\^POSTMATCH\} ) \z/oxmsgc) {
5382 0           $char[$i] = '@{[Char::Ekoi8r::POSTMATCH()]}';
5383             }
5384              
5385             # ${ foo } --> ${ foo }
5386             elsif ($char[$i] =~ /\A \$ \s* \{ \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* \} \z/oxms) {
5387             }
5388              
5389             # ${ ... }
5390             elsif ($char[$i] =~ /\A \$ \s* \{ \s* ( .+ ) \s* \} \z/oxms) {
5391 0           $char[$i] = e_capture($1);
5392             }
5393             }
5394              
5395             # return string
5396 0 0         if ($left_e > $right_e) {
5397 0           return join '', @char, '>]}' x ($left_e - $right_e);
5398             }
5399 0           return join '', @char;
5400             }
5401              
5402             #
5403             # escape regexp (m//, qr//)
5404             #
5405             sub e_qr {
5406 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
5407 0   0       $modifier ||= '';
5408              
5409 0           $modifier =~ tr/p//d;
5410 0 0         if ($modifier =~ /([adlu])/oxms) {
5411 0           my $line = 0;
5412 0           for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
5413 0 0         if ($filename ne __FILE__) {
5414 0           $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
5415 0           last;
5416             }
5417             }
5418 0           die qq{Unsupported modifier "$1" used at line $line.\n};
5419             }
5420              
5421 0           $slash = 'div';
5422              
5423             # literal null string pattern
5424 0 0         if ($string eq '') {
    0          
5425 0           $modifier =~ tr/bB//d;
5426 0           $modifier =~ tr/i//d;
5427 0           return join '', $ope, $delimiter, $end_delimiter, $modifier;
5428             }
5429              
5430             # /b /B modifier
5431             elsif ($modifier =~ tr/bB//d) {
5432              
5433             # choice again delimiter
5434 0 0         if ($delimiter =~ / [\@:] /oxms) {
5435 0           my @char = $string =~ /\G([\x00-\xFF])/oxmsg;
5436 0           my %octet = map {$_ => 1} @char;
  0            
5437 0 0         if (not $octet{')'}) {
    0          
    0          
    0          
5438 0           $delimiter = '(';
5439 0           $end_delimiter = ')';
5440             }
5441             elsif (not $octet{'}'}) {
5442 0           $delimiter = '{';
5443 0           $end_delimiter = '}';
5444             }
5445             elsif (not $octet{']'}) {
5446 0           $delimiter = '[';
5447 0           $end_delimiter = ']';
5448             }
5449             elsif (not $octet{'>'}) {
5450 0           $delimiter = '<';
5451 0           $end_delimiter = '>';
5452             }
5453             else {
5454 0           for my $char (qw( ! " $ % & * + - . / = ? ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
5455 0 0         if (not $octet{$char}) {
5456 0           $delimiter = $char;
5457 0           $end_delimiter = $char;
5458 0           last;
5459             }
5460             }
5461             }
5462             }
5463              
5464 0 0 0       if (($ope =~ /\A m? \z/oxms) and ($delimiter eq '?')) {
5465 0           return join '', $ope, $delimiter, $string, $matched, $end_delimiter, $modifier;
5466             }
5467             else {
5468 0           return join '', $ope, $delimiter, '(?:', $string, ')', $matched, $end_delimiter, $modifier;
5469             }
5470             }
5471              
5472 0 0         my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
5473 0           my $metachar = qr/[\@\\|[\]{^]/oxms;
5474              
5475             # split regexp
5476 0           my @char = $string =~ /\G(
5477             \\o\{ [0-7]+ \} |
5478             \\ [0-7]{2,3} |
5479             \\x\{ [0-9A-Fa-f]+ \} |
5480             \\x [0-9A-Fa-f]{1,2} |
5481             \\c [\x40-\x5F] |
5482             \\N\{ [^0-9\}][^\}]* \} |
5483             \\p\{ [^0-9\}][^\}]* \} |
5484             \\P\{ [^0-9\}][^\}]* \} |
5485             \\ (?:$q_char) |
5486             \$` | \$\{`\} | \$ \s* PREMATCH | \$ \s* \{ \s* PREMATCH \s* \} | \$ \s* \{\^PREMATCH\} |
5487             \$& | \$\{&\} | \$ \s* MATCH | \$ \s* \{ \s* MATCH \s* \} | \$ \s* \{\^MATCH\} |
5488             \$ \s* POSTMATCH | \$ \s* \{ \s* POSTMATCH \s* \} | \$ \s* \{\^POSTMATCH\} |
5489             [\$\@] $qq_variable |
5490             \$ \s* \d+ |
5491             \$ \s* \{ \s* \d+ \s* \} |
5492             \$ \$ (?![\w\{]) |
5493             \$ \s* \$ \s* $qq_variable |
5494             \[\:\^ (?:alnum|alpha|ascii|blank|cntrl|digit|graph|lower|print|punct|space|upper|word|xdigit) :\] |
5495             \[\: (?:alnum|alpha|ascii|blank|cntrl|digit|graph|lower|print|punct|space|upper|word|xdigit) :\] |
5496             \[\^ |
5497             \(\? |
5498             (?:$q_char)
5499             )/oxmsg;
5500              
5501             # choice again delimiter
5502 0 0         if ($delimiter =~ / [\@:] /oxms) {
5503 0           my %octet = map {$_ => 1} @char;
  0            
5504 0 0         if (not $octet{')'}) {
    0          
    0          
    0          
5505 0           $delimiter = '(';
5506 0           $end_delimiter = ')';
5507             }
5508             elsif (not $octet{'}'}) {
5509 0           $delimiter = '{';
5510 0           $end_delimiter = '}';
5511             }
5512             elsif (not $octet{']'}) {
5513 0           $delimiter = '[';
5514 0           $end_delimiter = ']';
5515             }
5516             elsif (not $octet{'>'}) {
5517 0           $delimiter = '<';
5518 0           $end_delimiter = '>';
5519             }
5520             else {
5521 0           for my $char (qw( ! " $ % & * + - . / = ? ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
5522 0 0         if (not $octet{$char}) {
5523 0           $delimiter = $char;
5524 0           $end_delimiter = $char;
5525 0           last;
5526             }
5527             }
5528             }
5529             }
5530              
5531 0           my $left_e = 0;
5532 0           my $right_e = 0;
5533 0           for (my $i=0; $i <= $#char; $i++) {
5534              
5535             # "\L\u" --> "\u\L"
5536 0 0 0       if (($char[$i] eq '\L') and ($char[$i+1] eq '\u')) {
    0 0        
    0          
    0          
    0          
    0          
    0          
    0          
5537 0           @char[$i,$i+1] = @char[$i+1,$i];
5538             }
5539              
5540             # "\U\l" --> "\l\U"
5541             elsif (($char[$i] eq '\U') and ($char[$i+1] eq '\l')) {
5542 0           @char[$i,$i+1] = @char[$i+1,$i];
5543             }
5544              
5545             # octal escape sequence
5546             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
5547 0           $char[$i] = Char::Ekoi8r::octchr($1);
5548             }
5549              
5550             # hexadecimal escape sequence
5551             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
5552 0           $char[$i] = Char::Ekoi8r::hexchr($1);
5553             }
5554              
5555             # \N{CHARNAME} --> N\{CHARNAME}
5556             elsif ($char[$i] =~ /\A \\ (N) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
5557 0           $char[$i] = $1 . '\\' . $2;
5558             }
5559              
5560             # \p{PROPERTY} --> p\{PROPERTY}
5561             elsif ($char[$i] =~ /\A \\ (p) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
5562 0           $char[$i] = $1 . '\\' . $2;
5563             }
5564              
5565             # \P{PROPERTY} --> P\{PROPERTY}
5566             elsif ($char[$i] =~ /\A \\ (P) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
5567 0           $char[$i] = $1 . '\\' . $2;
5568             }
5569              
5570             # \p, \P, \X --> p, P, X
5571             elsif ($char[$i] =~ /\A \\ ( [pPX] ) \z/oxms) {
5572 0           $char[$i] = $1;
5573             }
5574              
5575 0 0 0       if (0) {
    0 0        
    0 0        
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
5576             }
5577              
5578             # join separated multiple-octet
5579 0           elsif ($char[$i] =~ /\A (?: \\ [0-7]{2,3} | \\x [0-9A-Fa-f]{1,2}) \z/oxms) {
5580 0 0 0       if ( ($i+3 <= $#char) and (grep(/\A (?: \\ [0-7]{2,3} | \\x [0-9A-Fa-f]{1,2}) \z/oxms, @char[$i+1..$i+3]) == 3) and (CORE::eval(sprintf '"%s%s%s%s"', @char[$i..$i+3]) =~ /\A $q_char \z/oxms)) {
    0 0        
    0 0        
      0        
      0        
      0        
5581 0           $char[$i] .= join '', splice @char, $i+1, 3;
5582             }
5583             elsif (($i+2 <= $#char) and (grep(/\A (?: \\ [0-7]{2,3} | \\x [0-9A-Fa-f]{1,2}) \z/oxms, @char[$i+1..$i+2]) == 2) and (CORE::eval(sprintf '"%s%s%s"', @char[$i..$i+2]) =~ /\A $q_char \z/oxms)) {
5584 0           $char[$i] .= join '', splice @char, $i+1, 2;
5585             }
5586             elsif (($i+1 <= $#char) and (grep(/\A (?: \\ [0-7]{2,3} | \\x [0-9A-Fa-f]{1,2}) \z/oxms, $char[$i+1 ]) == 1) and (CORE::eval(sprintf '"%s%s"', @char[$i..$i+1]) =~ /\A $q_char \z/oxms)) {
5587 0           $char[$i] .= join '', splice @char, $i+1, 1;
5588             }
5589             }
5590              
5591             # open character class [...]
5592             elsif ($char[$i] eq '[') {
5593 0           my $left = $i;
5594              
5595             # [] make die "Unmatched [] in regexp ..."
5596             # (and so on)
5597              
5598 0 0         if ($char[$i+1] eq ']') {
5599 0           $i++;
5600             }
5601              
5602 0           while (1) {
5603 0 0         if (++$i > $#char) {
5604 0           die __FILE__, ": Unmatched [] in regexp";
5605             }
5606 0 0         if ($char[$i] eq ']') {
5607 0           my $right = $i;
5608              
5609             # [...]
5610 0 0         if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
5611 0           splice @char, $left, $right-$left+1, sprintf(q{@{[Char::Ekoi8r::charlist_qr(%s,'%s')]}}, join(',', map {qq_stuff($delimiter,$end_delimiter,$_)} @char[$left+1..$right-1]), $modifier);
  0            
5612             }
5613             else {
5614 0           splice @char, $left, $right-$left+1, Char::Ekoi8r::charlist_qr(@char[$left+1..$right-1], $modifier);
5615             }
5616              
5617 0           $i = $left;
5618 0           last;
5619             }
5620             }
5621             }
5622              
5623             # open character class [^...]
5624             elsif ($char[$i] eq '[^') {
5625 0           my $left = $i;
5626              
5627             # [^] make die "Unmatched [] in regexp ..."
5628             # (and so on)
5629              
5630 0 0         if ($char[$i+1] eq ']') {
5631 0           $i++;
5632             }
5633              
5634 0           while (1) {
5635 0 0         if (++$i > $#char) {
5636 0           die __FILE__, ": Unmatched [] in regexp";
5637             }
5638 0 0         if ($char[$i] eq ']') {
5639 0           my $right = $i;
5640              
5641             # [^...]
5642 0 0         if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
5643 0           splice @char, $left, $right-$left+1, sprintf(q{@{[Char::Ekoi8r::charlist_not_qr(%s,'%s')]}}, join(',', map {qq_stuff($delimiter,$end_delimiter,$_)} @char[$left+1..$right-1]), $modifier);
  0            
5644             }
5645             else {
5646 0           splice @char, $left, $right-$left+1, Char::Ekoi8r::charlist_not_qr(@char[$left+1..$right-1], $modifier);
5647             }
5648              
5649 0           $i = $left;
5650 0           last;
5651             }
5652             }
5653             }
5654              
5655             # rewrite character class or escape character
5656             elsif (my $char = character_class($char[$i],$modifier)) {
5657 0           $char[$i] = $char;
5658             }
5659              
5660             # /i modifier
5661             elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Char::Ekoi8r::uc($char[$i]) ne Char::Ekoi8r::fc($char[$i]))) {
5662 0 0         if (CORE::length(Char::Ekoi8r::fc($char[$i])) == 1) {
5663 0           $char[$i] = '[' . Char::Ekoi8r::uc($char[$i]) . Char::Ekoi8r::fc($char[$i]) . ']';
5664             }
5665             else {
5666 0           $char[$i] = '(?:' . Char::Ekoi8r::uc($char[$i]) . '|' . Char::Ekoi8r::fc($char[$i]) . ')';
5667             }
5668             }
5669              
5670             # \u \l \U \L \F \Q \E
5671             elsif ($char[$i] =~ /\A [<>] \z/oxms) {
5672 0 0         if ($right_e < $left_e) {
5673 0           $char[$i] = '\\' . $char[$i];
5674             }
5675             }
5676             elsif ($char[$i] eq '\u') {
5677 0           $char[$i] = '@{[Char::Ekoi8r::ucfirst qq<';
5678 0           $left_e++;
5679             }
5680             elsif ($char[$i] eq '\l') {
5681 0           $char[$i] = '@{[Char::Ekoi8r::lcfirst qq<';
5682 0           $left_e++;
5683             }
5684             elsif ($char[$i] eq '\U') {
5685 0           $char[$i] = '@{[Char::Ekoi8r::uc qq<';
5686 0           $left_e++;
5687             }
5688             elsif ($char[$i] eq '\L') {
5689 0           $char[$i] = '@{[Char::Ekoi8r::lc qq<';
5690 0           $left_e++;
5691             }
5692             elsif ($char[$i] eq '\F') {
5693 0           $char[$i] = '@{[Char::Ekoi8r::fc qq<';
5694 0           $left_e++;
5695             }
5696             elsif ($char[$i] eq '\Q') {
5697 0           $char[$i] = '@{[CORE::quotemeta qq<';
5698 0           $left_e++;
5699             }
5700             elsif ($char[$i] eq '\E') {
5701 0 0         if ($right_e < $left_e) {
5702 0           $char[$i] = '>]}';
5703 0           $right_e++;
5704             }
5705             else {
5706 0           $char[$i] = '';
5707             }
5708             }
5709             elsif ($char[$i] eq '\Q') {
5710 0           while (1) {
5711 0 0         if (++$i > $#char) {
5712 0           last;
5713             }
5714 0 0         if ($char[$i] eq '\E') {
5715 0           last;
5716             }
5717             }
5718             }
5719             elsif ($char[$i] eq '\E') {
5720             }
5721              
5722             # $0 --> $0
5723             elsif ($char[$i] =~ /\A \$ 0 \z/oxms) {
5724 0 0         if ($ignorecase) {
5725 0           $char[$i] = '@{[Char::Ekoi8r::ignorecase(' . $char[$i] . ')]}';
5726             }
5727             }
5728             elsif ($char[$i] =~ /\A \$ \{ \s* 0 \s* \} \z/oxms) {
5729 0 0         if ($ignorecase) {
5730 0           $char[$i] = '@{[Char::Ekoi8r::ignorecase(' . $char[$i] . ')]}';
5731             }
5732             }
5733              
5734             # $$ --> $$
5735             elsif ($char[$i] =~ /\A \$\$ \z/oxms) {
5736             }
5737              
5738             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
5739             # $1, $2, $3 --> $1, $2, $3 otherwise
5740             elsif ($char[$i] =~ /\A \$ ([1-9][0-9]*) \z/oxms) {
5741 0           $char[$i] = e_capture($1);
5742 0 0         if ($ignorecase) {
5743 0           $char[$i] = '@{[Char::Ekoi8r::ignorecase(' . $char[$i] . ')]}';
5744             }
5745             }
5746             elsif ($char[$i] =~ /\A \$ \{ \s* ([1-9][0-9]*) \s* \} \z/oxms) {
5747 0           $char[$i] = e_capture($1);
5748 0 0         if ($ignorecase) {
5749 0           $char[$i] = '@{[Char::Ekoi8r::ignorecase(' . $char[$i] . ')]}';
5750             }
5751             }
5752              
5753             # $$foo[ ... ] --> $ $foo->[ ... ]
5754             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) ( \[ (?:$qq_bracket)*? \] ) \z/oxms) {
5755 0           $char[$i] = e_capture($1.'->'.$2);
5756 0 0         if ($ignorecase) {
5757 0           $char[$i] = '@{[Char::Ekoi8r::ignorecase(' . $char[$i] . ')]}';
5758             }
5759             }
5760              
5761             # $$foo{ ... } --> $ $foo->{ ... }
5762             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) ( \{ (?:$qq_brace)*? \} ) \z/oxms) {
5763 0           $char[$i] = e_capture($1.'->'.$2);
5764 0 0         if ($ignorecase) {
5765 0           $char[$i] = '@{[Char::Ekoi8r::ignorecase(' . $char[$i] . ')]}';
5766             }
5767             }
5768              
5769             # $$foo
5770             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) \z/oxms) {
5771 0           $char[$i] = e_capture($1);
5772 0 0         if ($ignorecase) {
5773 0           $char[$i] = '@{[Char::Ekoi8r::ignorecase(' . $char[$i] . ')]}';
5774             }
5775             }
5776              
5777             # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Char::Ekoi8r::PREMATCH()
5778             elsif ($char[$i] =~ /\A ( \$` | \$\{`\} | \$ \s* PREMATCH | \$ \s* \{ \s* PREMATCH \s* \} | \$ \s* \{\^PREMATCH\} ) \z/oxmsgc) {
5779 0 0         if ($ignorecase) {
5780 0           $char[$i] = '@{[Char::Ekoi8r::ignorecase(Char::Ekoi8r::PREMATCH())]}';
5781             }
5782             else {
5783 0           $char[$i] = '@{[Char::Ekoi8r::PREMATCH()]}';
5784             }
5785             }
5786              
5787             # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Char::Ekoi8r::MATCH()
5788             elsif ($char[$i] =~ /\A ( \$& | \$\{&\} | \$ \s* MATCH | \$ \s* \{ \s* MATCH \s* \} | \$ \s* \{\^MATCH\} ) \z/oxmsgc) {
5789 0 0         if ($ignorecase) {
5790 0           $char[$i] = '@{[Char::Ekoi8r::ignorecase(Char::Ekoi8r::MATCH())]}';
5791             }
5792             else {
5793 0           $char[$i] = '@{[Char::Ekoi8r::MATCH()]}';
5794             }
5795             }
5796              
5797             # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Char::Ekoi8r::POSTMATCH()
5798             elsif ($char[$i] =~ /\A ( \$ \s* POSTMATCH | \$ \s* \{ \s* POSTMATCH \s* \} | \$ \s* \{\^POSTMATCH\} ) \z/oxmsgc) {
5799 0 0         if ($ignorecase) {
5800 0           $char[$i] = '@{[Char::Ekoi8r::ignorecase(Char::Ekoi8r::POSTMATCH())]}';
5801             }
5802             else {
5803 0           $char[$i] = '@{[Char::Ekoi8r::POSTMATCH()]}';
5804             }
5805             }
5806              
5807             # ${ foo }
5808             elsif ($char[$i] =~ /\A \$ \s* \{ ( \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* ) \} \z/oxms) {
5809 0 0         if ($ignorecase) {
5810 0           $char[$i] = '@{[Char::Ekoi8r::ignorecase(' . $char[$i] . ')]}';
5811             }
5812             }
5813              
5814             # ${ ... }
5815             elsif ($char[$i] =~ /\A \$ \s* \{ \s* ( .+ ) \s* \} \z/oxms) {
5816 0           $char[$i] = e_capture($1);
5817 0 0         if ($ignorecase) {
5818 0           $char[$i] = '@{[Char::Ekoi8r::ignorecase(' . $char[$i] . ')]}';
5819             }
5820             }
5821              
5822             # $scalar or @array
5823             elsif ($char[$i] =~ /\A [\$\@].+ /oxms) {
5824 0           $char[$i] = e_string($char[$i]);
5825 0 0         if ($ignorecase) {
5826 0           $char[$i] = '@{[Char::Ekoi8r::ignorecase(' . $char[$i] . ')]}';
5827             }
5828             }
5829              
5830             # quote character before ? + * {
5831             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
5832 0 0 0       if ($char[$i-1] =~ /\A (?:\\[0-7]{2,3}|\\x[0-9-A-Fa-f]{1,2}) \z/oxms) {
    0          
5833             }
5834             elsif (($ope =~ /\A m? \z/oxms) and ($delimiter eq '?')) {
5835 0           my $char = $char[$i-1];
5836 0 0         if ($char[$i] eq '{') {
5837 0           die __FILE__, qq{: "MULTIBYTE{n}" should be "(MULTIBYTE){n}" in m?? (and shift \$1,\$2,\$3,...) ($char){n}};
5838             }
5839             else {
5840 0           die __FILE__, qq{: "MULTIBYTE$char[$i]" should be "(MULTIBYTE)$char[$i]" in m?? (and shift \$1,\$2,\$3,...) ($char)$char[$i]};
5841             }
5842             }
5843             else {
5844 0           $char[$i-1] = '(?:' . $char[$i-1] . ')';
5845             }
5846             }
5847             }
5848              
5849             # make regexp string
5850 0           $modifier =~ tr/i//d;
5851 0 0         if ($left_e > $right_e) {
5852 0 0 0       if (($ope =~ /\A m? \z/oxms) and ($delimiter eq '?')) {
5853 0           return join '', $ope, $delimiter, $anchor, @char, '>]}' x ($left_e - $right_e), $matched, $end_delimiter, $modifier;
5854             }
5855             else {
5856 0           return join '', $ope, $delimiter, $anchor, '(?:', @char, '>]}' x ($left_e - $right_e), ')', $matched, $end_delimiter, $modifier;
5857             }
5858             }
5859 0 0 0       if (($ope =~ /\A m? \z/oxms) and ($delimiter eq '?')) {
5860 0           return join '', $ope, $delimiter, $anchor, @char, $matched, $end_delimiter, $modifier;
5861             }
5862             else {
5863 0           return join '', $ope, $delimiter, $anchor, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
5864             }
5865             }
5866              
5867             #
5868             # double quote stuff
5869             #
5870             sub qq_stuff {
5871 0     0 0   my($delimiter,$end_delimiter,$stuff) = @_;
5872              
5873             # scalar variable or array variable
5874 0 0         if ($stuff =~ /\A [\$\@] /oxms) {
5875 0           return $stuff;
5876             }
5877              
5878             # quote by delimiter
5879 0           my %octet = map {$_ => 1} ($stuff =~ /\G ([\x00-\xFF]) /oxmsg);
  0            
5880 0           for my $char (qw( ! " $ % & * + - . / : = ? @ ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
5881 0 0         next if $char eq $delimiter;
5882 0 0         next if $char eq $end_delimiter;
5883 0 0         if (not $octet{$char}) {
5884 0           return join '', 'qq', $char, $stuff, $char;
5885             }
5886             }
5887 0           return join '', 'qq', '<', $stuff, '>';
5888             }
5889              
5890             #
5891             # escape regexp (m'', qr'', and m''b, qr''b)
5892             #
5893             sub e_qr_q {
5894 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
5895 0   0       $modifier ||= '';
5896              
5897 0           $modifier =~ tr/p//d;
5898 0 0         if ($modifier =~ /([adlu])/oxms) {
5899 0           my $line = 0;
5900 0           for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
5901 0 0         if ($filename ne __FILE__) {
5902 0           $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
5903 0           last;
5904             }
5905             }
5906 0           die qq{Unsupported modifier "$1" used at line $line.\n};
5907             }
5908              
5909 0           $slash = 'div';
5910              
5911             # literal null string pattern
5912 0 0         if ($string eq '') {
    0          
5913 0           $modifier =~ tr/bB//d;
5914 0           $modifier =~ tr/i//d;
5915 0           return join '', $ope, $delimiter, $end_delimiter, $modifier;
5916             }
5917              
5918             # with /b /B modifier
5919             elsif ($modifier =~ tr/bB//d) {
5920 0           return e_qr_qb($ope,$delimiter,$end_delimiter,$string,$modifier);
5921             }
5922              
5923             # without /b /B modifier
5924             else {
5925 0           return e_qr_qt($ope,$delimiter,$end_delimiter,$string,$modifier);
5926             }
5927             }
5928              
5929             #
5930             # escape regexp (m'', qr'')
5931             #
5932             sub e_qr_qt {
5933 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
5934              
5935 0 0         my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
5936              
5937             # split regexp
5938 0           my @char = $string =~ /\G(
5939             \[\:\^ [a-z]+ \:\] |
5940             \[\: [a-z]+ \:\] |
5941             \[\^ |
5942             [\$\@\/\\] |
5943             \\? (?:$q_char)
5944             )/oxmsg;
5945              
5946             # unescape character
5947 0           for (my $i=0; $i <= $#char; $i++) {
5948 0 0 0       if (0) {
    0 0        
    0 0        
    0          
    0          
    0          
5949             }
5950              
5951             # open character class [...]
5952 0           elsif ($char[$i] eq '[') {
5953 0           my $left = $i;
5954 0 0         if ($char[$i+1] eq ']') {
5955 0           $i++;
5956             }
5957 0           while (1) {
5958 0 0         if (++$i > $#char) {
5959 0           die __FILE__, ": Unmatched [] in regexp";
5960             }
5961 0 0         if ($char[$i] eq ']') {
5962 0           my $right = $i;
5963              
5964             # [...]
5965 0           splice @char, $left, $right-$left+1, Char::Ekoi8r::charlist_qr(@char[$left+1..$right-1], $modifier);
5966              
5967 0           $i = $left;
5968 0           last;
5969             }
5970             }
5971             }
5972              
5973             # open character class [^...]
5974             elsif ($char[$i] eq '[^') {
5975 0           my $left = $i;
5976 0 0         if ($char[$i+1] eq ']') {
5977 0           $i++;
5978             }
5979 0           while (1) {
5980 0 0         if (++$i > $#char) {
5981 0           die __FILE__, ": Unmatched [] in regexp";
5982             }
5983 0 0         if ($char[$i] eq ']') {
5984 0           my $right = $i;
5985              
5986             # [^...]
5987 0           splice @char, $left, $right-$left+1, Char::Ekoi8r::charlist_not_qr(@char[$left+1..$right-1], $modifier);
5988              
5989 0           $i = $left;
5990 0           last;
5991             }
5992             }
5993             }
5994              
5995             # escape $ @ / and \
5996             elsif ($char[$i] =~ /\A [\$\@\/\\] \z/oxms) {
5997 0           $char[$i] = '\\' . $char[$i];
5998             }
5999              
6000             # rewrite character class or escape character
6001             elsif (my $char = character_class($char[$i],$modifier)) {
6002 0           $char[$i] = $char;
6003             }
6004              
6005             # /i modifier
6006             elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Char::Ekoi8r::uc($char[$i]) ne Char::Ekoi8r::fc($char[$i]))) {
6007 0 0         if (CORE::length(Char::Ekoi8r::fc($char[$i])) == 1) {
6008 0           $char[$i] = '[' . Char::Ekoi8r::uc($char[$i]) . Char::Ekoi8r::fc($char[$i]) . ']';
6009             }
6010             else {
6011 0           $char[$i] = '(?:' . Char::Ekoi8r::uc($char[$i]) . '|' . Char::Ekoi8r::fc($char[$i]) . ')';
6012             }
6013             }
6014              
6015             # quote character before ? + * {
6016             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
6017 0 0         if ($char[$i-1] =~ /\A [\x00-\xFF] \z/oxms) {
6018             }
6019             else {
6020 0           $char[$i-1] = '(?:' . $char[$i-1] . ')';
6021             }
6022             }
6023             }
6024              
6025 0           $delimiter = '/';
6026 0           $end_delimiter = '/';
6027              
6028 0           $modifier =~ tr/i//d;
6029 0           return join '', $ope, $delimiter, $anchor, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
6030             }
6031              
6032             #
6033             # escape regexp (m''b, qr''b)
6034             #
6035             sub e_qr_qb {
6036 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6037              
6038             # split regexp
6039 0           my @char = $string =~ /\G(
6040             \\\\ |
6041             [\$\@\/\\] |
6042             [\x00-\xFF]
6043             )/oxmsg;
6044              
6045             # unescape character
6046 0           for (my $i=0; $i <= $#char; $i++) {
6047 0 0         if (0) {
    0          
6048             }
6049              
6050             # remain \\
6051 0           elsif ($char[$i] eq '\\\\') {
6052             }
6053              
6054             # escape $ @ / and \
6055             elsif ($char[$i] =~ /\A [\$\@\/\\] \z/oxms) {
6056 0           $char[$i] = '\\' . $char[$i];
6057             }
6058             }
6059              
6060 0           $delimiter = '/';
6061 0           $end_delimiter = '/';
6062 0           return join '', $ope, $delimiter, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
6063             }
6064              
6065             #
6066             # escape regexp (s/here//)
6067             #
6068             sub e_s1 {
6069 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6070 0   0       $modifier ||= '';
6071              
6072 0           $modifier =~ tr/p//d;
6073 0 0         if ($modifier =~ /([adlu])/oxms) {
6074 0           my $line = 0;
6075 0           for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
6076 0 0         if ($filename ne __FILE__) {
6077 0           $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
6078 0           last;
6079             }
6080             }
6081 0           die qq{Unsupported modifier "$1" used at line $line.\n};
6082             }
6083              
6084 0           $slash = 'div';
6085              
6086             # literal null string pattern
6087 0 0         if ($string eq '') {
    0          
6088 0           $modifier =~ tr/bB//d;
6089 0           $modifier =~ tr/i//d;
6090 0           return join '', $ope, $delimiter, $end_delimiter, $modifier;
6091             }
6092              
6093             # /b /B modifier
6094             elsif ($modifier =~ tr/bB//d) {
6095              
6096             # choice again delimiter
6097 0 0         if ($delimiter =~ / [\@:] /oxms) {
6098 0           my @char = $string =~ /\G([\x00-\xFF])/oxmsg;
6099 0           my %octet = map {$_ => 1} @char;
  0            
6100 0 0         if (not $octet{')'}) {
    0          
    0          
    0          
6101 0           $delimiter = '(';
6102 0           $end_delimiter = ')';
6103             }
6104             elsif (not $octet{'}'}) {
6105 0           $delimiter = '{';
6106 0           $end_delimiter = '}';
6107             }
6108             elsif (not $octet{']'}) {
6109 0           $delimiter = '[';
6110 0           $end_delimiter = ']';
6111             }
6112             elsif (not $octet{'>'}) {
6113 0           $delimiter = '<';
6114 0           $end_delimiter = '>';
6115             }
6116             else {
6117 0           for my $char (qw( ! " $ % & * + - . / = ? ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
6118 0 0         if (not $octet{$char}) {
6119 0           $delimiter = $char;
6120 0           $end_delimiter = $char;
6121 0           last;
6122             }
6123             }
6124             }
6125             }
6126              
6127 0           my $prematch = '';
6128 0           return join '', $ope, $delimiter, $prematch, '(?:', $string, ')', $matched, $end_delimiter, $modifier;
6129             }
6130              
6131 0 0         my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
6132 0           my $metachar = qr/[\@\\|[\]{^]/oxms;
6133              
6134             # split regexp
6135 0           my @char = $string =~ /\G(
6136             \\g \s* \{ \s* - \s* [1-9][0-9]* \s* \} |
6137             \\g \s* \{ \s* [1-9][0-9]* \s* \} |
6138             \\g \s* [1-9][0-9]* |
6139             \\o\{ [0-7]+ \} |
6140             \\ [1-9][0-9]* |
6141             \\ [0-7]{2,3} |
6142             \\x\{ [0-9A-Fa-f]+ \} |
6143             \\x [0-9A-Fa-f]{1,2} |
6144             \\c [\x40-\x5F] |
6145             \\N\{ [^0-9\}][^\}]* \} |
6146             \\p\{ [^0-9\}][^\}]* \} |
6147             \\P\{ [^0-9\}][^\}]* \} |
6148             \\ (?:$q_char) |
6149             \$` | \$\{`\} | \$ \s* PREMATCH | \$ \s* \{ \s* PREMATCH \s* \} | \$ \s* \{\^PREMATCH\} |
6150             \$& | \$\{&\} | \$ \s* MATCH | \$ \s* \{ \s* MATCH \s* \} | \$ \s* \{\^MATCH\} |
6151             \$ \s* POSTMATCH | \$ \s* \{ \s* POSTMATCH \s* \} | \$ \s* \{\^POSTMATCH\} |
6152             [\$\@] $qq_variable |
6153             \$ \s* \d+ |
6154             \$ \s* \{ \s* \d+ \s* \} |
6155             \$ \$ (?![\w\{]) |
6156             \$ \s* \$ \s* $qq_variable |
6157             \[\:\^ (?:alnum|alpha|ascii|blank|cntrl|digit|graph|lower|print|punct|space|upper|word|xdigit) :\] |
6158             \[\: (?:alnum|alpha|ascii|blank|cntrl|digit|graph|lower|print|punct|space|upper|word|xdigit) :\] |
6159             \[\^ |
6160             \(\? |
6161             (?:$q_char)
6162             )/oxmsg;
6163              
6164             # choice again delimiter
6165 0 0         if ($delimiter =~ / [\@:] /oxms) {
6166 0           my %octet = map {$_ => 1} @char;
  0            
6167 0 0         if (not $octet{')'}) {
    0          
    0          
    0          
6168 0           $delimiter = '(';
6169 0           $end_delimiter = ')';
6170             }
6171             elsif (not $octet{'}'}) {
6172 0           $delimiter = '{';
6173 0           $end_delimiter = '}';
6174             }
6175             elsif (not $octet{']'}) {
6176 0           $delimiter = '[';
6177 0           $end_delimiter = ']';
6178             }
6179             elsif (not $octet{'>'}) {
6180 0           $delimiter = '<';
6181 0           $end_delimiter = '>';
6182             }
6183             else {
6184 0           for my $char (qw( ! " $ % & * + - . / = ? ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
6185 0 0         if (not $octet{$char}) {
6186 0           $delimiter = $char;
6187 0           $end_delimiter = $char;
6188 0           last;
6189             }
6190             }
6191             }
6192             }
6193              
6194             # count '('
6195 0           my $parens = grep { $_ eq '(' } @char;
  0            
6196              
6197 0           my $left_e = 0;
6198 0           my $right_e = 0;
6199 0           for (my $i=0; $i <= $#char; $i++) {
6200              
6201             # "\L\u" --> "\u\L"
6202 0 0 0       if (($char[$i] eq '\L') and ($char[$i+1] eq '\u')) {
    0 0        
    0          
    0          
    0          
    0          
    0          
    0          
6203 0           @char[$i,$i+1] = @char[$i+1,$i];
6204             }
6205              
6206             # "\U\l" --> "\l\U"
6207             elsif (($char[$i] eq '\U') and ($char[$i+1] eq '\l')) {
6208 0           @char[$i,$i+1] = @char[$i+1,$i];
6209             }
6210              
6211             # octal escape sequence
6212             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
6213 0           $char[$i] = Char::Ekoi8r::octchr($1);
6214             }
6215              
6216             # hexadecimal escape sequence
6217             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
6218 0           $char[$i] = Char::Ekoi8r::hexchr($1);
6219             }
6220              
6221             # \N{CHARNAME} --> N\{CHARNAME}
6222             elsif ($char[$i] =~ /\A \\ (N) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
6223 0           $char[$i] = $1 . '\\' . $2;
6224             }
6225              
6226             # \p{PROPERTY} --> p\{PROPERTY}
6227             elsif ($char[$i] =~ /\A \\ (p) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
6228 0           $char[$i] = $1 . '\\' . $2;
6229             }
6230              
6231             # \P{PROPERTY} --> P\{PROPERTY}
6232             elsif ($char[$i] =~ /\A \\ (P) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
6233 0           $char[$i] = $1 . '\\' . $2;
6234             }
6235              
6236             # \p, \P, \X --> p, P, X
6237             elsif ($char[$i] =~ /\A \\ ( [pPX] ) \z/oxms) {
6238 0           $char[$i] = $1;
6239             }
6240              
6241 0 0 0       if (0) {
    0 0        
    0 0        
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
6242             }
6243              
6244             # join separated multiple-octet
6245 0           elsif ($char[$i] =~ /\A (?: \\ [0-7]{2,3} | \\x [0-9A-Fa-f]{1,2}) \z/oxms) {
6246 0 0 0       if ( ($i+3 <= $#char) and (grep(/\A (?: \\ [0-7]{2,3} | \\x [0-9A-Fa-f]{1,2}) \z/oxms, @char[$i+1..$i+3]) == 3) and (CORE::eval(sprintf '"%s%s%s%s"', @char[$i..$i+3]) =~ /\A $q_char \z/oxms)) {
    0 0        
    0 0        
      0        
      0        
      0        
6247 0           $char[$i] .= join '', splice @char, $i+1, 3;
6248             }
6249             elsif (($i+2 <= $#char) and (grep(/\A (?: \\ [0-7]{2,3} | \\x [0-9A-Fa-f]{1,2}) \z/oxms, @char[$i+1..$i+2]) == 2) and (CORE::eval(sprintf '"%s%s%s"', @char[$i..$i+2]) =~ /\A $q_char \z/oxms)) {
6250 0           $char[$i] .= join '', splice @char, $i+1, 2;
6251             }
6252             elsif (($i+1 <= $#char) and (grep(/\A (?: \\ [0-7]{2,3} | \\x [0-9A-Fa-f]{1,2}) \z/oxms, $char[$i+1 ]) == 1) and (CORE::eval(sprintf '"%s%s"', @char[$i..$i+1]) =~ /\A $q_char \z/oxms)) {
6253 0           $char[$i] .= join '', splice @char, $i+1, 1;
6254             }
6255             }
6256              
6257             # open character class [...]
6258             elsif ($char[$i] eq '[') {
6259 0           my $left = $i;
6260 0 0         if ($char[$i+1] eq ']') {
6261 0           $i++;
6262             }
6263 0           while (1) {
6264 0 0         if (++$i > $#char) {
6265 0           die __FILE__, ": Unmatched [] in regexp";
6266             }
6267 0 0         if ($char[$i] eq ']') {
6268 0           my $right = $i;
6269              
6270             # [...]
6271 0 0         if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
6272 0           splice @char, $left, $right-$left+1, sprintf(q{@{[Char::Ekoi8r::charlist_qr(%s,'%s')]}}, join(',', map {qq_stuff($delimiter,$end_delimiter,$_)} @char[$left+1..$right-1]), $modifier);
  0            
6273             }
6274             else {
6275 0           splice @char, $left, $right-$left+1, Char::Ekoi8r::charlist_qr(@char[$left+1..$right-1], $modifier);
6276             }
6277              
6278 0           $i = $left;
6279 0           last;
6280             }
6281             }
6282             }
6283              
6284             # open character class [^...]
6285             elsif ($char[$i] eq '[^') {
6286 0           my $left = $i;
6287 0 0         if ($char[$i+1] eq ']') {
6288 0           $i++;
6289             }
6290 0           while (1) {
6291 0 0         if (++$i > $#char) {
6292 0           die __FILE__, ": Unmatched [] in regexp";
6293             }
6294 0 0         if ($char[$i] eq ']') {
6295 0           my $right = $i;
6296              
6297             # [^...]
6298 0 0         if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
6299 0           splice @char, $left, $right-$left+1, sprintf(q{@{[Char::Ekoi8r::charlist_not_qr(%s,'%s')]}}, join(',', map {qq_stuff($delimiter,$end_delimiter,$_)} @char[$left+1..$right-1]), $modifier);
  0            
6300             }
6301             else {
6302 0           splice @char, $left, $right-$left+1, Char::Ekoi8r::charlist_not_qr(@char[$left+1..$right-1], $modifier);
6303             }
6304              
6305 0           $i = $left;
6306 0           last;
6307             }
6308             }
6309             }
6310              
6311             # rewrite character class or escape character
6312             elsif (my $char = character_class($char[$i],$modifier)) {
6313 0           $char[$i] = $char;
6314             }
6315              
6316             # /i modifier
6317             elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Char::Ekoi8r::uc($char[$i]) ne Char::Ekoi8r::fc($char[$i]))) {
6318 0 0         if (CORE::length(Char::Ekoi8r::fc($char[$i])) == 1) {
6319 0           $char[$i] = '[' . Char::Ekoi8r::uc($char[$i]) . Char::Ekoi8r::fc($char[$i]) . ']';
6320             }
6321             else {
6322 0           $char[$i] = '(?:' . Char::Ekoi8r::uc($char[$i]) . '|' . Char::Ekoi8r::fc($char[$i]) . ')';
6323             }
6324             }
6325              
6326             # \u \l \U \L \F \Q \E
6327             elsif ($char[$i] =~ /\A [<>] \z/oxms) {
6328 0 0         if ($right_e < $left_e) {
6329 0           $char[$i] = '\\' . $char[$i];
6330             }
6331             }
6332             elsif ($char[$i] eq '\u') {
6333 0           $char[$i] = '@{[Char::Ekoi8r::ucfirst qq<';
6334 0           $left_e++;
6335             }
6336             elsif ($char[$i] eq '\l') {
6337 0           $char[$i] = '@{[Char::Ekoi8r::lcfirst qq<';
6338 0           $left_e++;
6339             }
6340             elsif ($char[$i] eq '\U') {
6341 0           $char[$i] = '@{[Char::Ekoi8r::uc qq<';
6342 0           $left_e++;
6343             }
6344             elsif ($char[$i] eq '\L') {
6345 0           $char[$i] = '@{[Char::Ekoi8r::lc qq<';
6346 0           $left_e++;
6347             }
6348             elsif ($char[$i] eq '\F') {
6349 0           $char[$i] = '@{[Char::Ekoi8r::fc qq<';
6350 0           $left_e++;
6351             }
6352             elsif ($char[$i] eq '\Q') {
6353 0           $char[$i] = '@{[CORE::quotemeta qq<';
6354 0           $left_e++;
6355             }
6356             elsif ($char[$i] eq '\E') {
6357 0 0         if ($right_e < $left_e) {
6358 0           $char[$i] = '>]}';
6359 0           $right_e++;
6360             }
6361             else {
6362 0           $char[$i] = '';
6363             }
6364             }
6365             elsif ($char[$i] eq '\Q') {
6366 0           while (1) {
6367 0 0         if (++$i > $#char) {
6368 0           last;
6369             }
6370 0 0         if ($char[$i] eq '\E') {
6371 0           last;
6372             }
6373             }
6374             }
6375             elsif ($char[$i] eq '\E') {
6376             }
6377              
6378             # \0 --> \0
6379             elsif ($char[$i] =~ /\A \\ \s* 0 \z/oxms) {
6380             }
6381              
6382             # \g{N}, \g{-N}
6383              
6384             # P.108 Using Simple Patterns
6385             # in Chapter 7: In the World of Regular Expressions
6386             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
6387              
6388             # P.221 Capturing
6389             # in Chapter 5: Pattern Matching
6390             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
6391              
6392             # \g{-1}, \g{-2}, \g{-3} --> \g{-1}, \g{-2}, \g{-3}
6393             elsif ($char[$i] =~ /\A \\g \s* \{ \s* - \s* ([1-9][0-9]*) \s* \} \z/oxms) {
6394             }
6395              
6396             # \g{1}, \g{2}, \g{3} --> \g{2}, \g{3}, \g{4} (only when multibyte anchoring is enable)
6397             elsif ($char[$i] =~ /\A \\g \s* \{ \s* ([1-9][0-9]*) \s* \} \z/oxms) {
6398             }
6399              
6400             # \g1, \g2, \g3 --> \g2, \g3, \g4 (only when multibyte anchoring is enable)
6401             elsif ($char[$i] =~ /\A \\g \s* ([1-9][0-9]*) \z/oxms) {
6402             }
6403              
6404             # \1, \2, \3 --> \2, \3, \4 (only when multibyte anchoring is enable)
6405             elsif ($char[$i] =~ /\A \\ \s* ([1-9][0-9]*) \z/oxms) {
6406             }
6407              
6408             # $0 --> $0
6409             elsif ($char[$i] =~ /\A \$ 0 \z/oxms) {
6410 0 0         if ($ignorecase) {
6411 0           $char[$i] = '@{[Char::Ekoi8r::ignorecase(' . $char[$i] . ')]}';
6412             }
6413             }
6414             elsif ($char[$i] =~ /\A \$ \{ \s* 0 \s* \} \z/oxms) {
6415 0 0         if ($ignorecase) {
6416 0           $char[$i] = '@{[Char::Ekoi8r::ignorecase(' . $char[$i] . ')]}';
6417             }
6418             }
6419              
6420             # $$ --> $$
6421             elsif ($char[$i] =~ /\A \$\$ \z/oxms) {
6422             }
6423              
6424             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
6425             # $1, $2, $3 --> $1, $2, $3 otherwise
6426             elsif ($char[$i] =~ /\A \$ ([1-9][0-9]*) \z/oxms) {
6427 0           $char[$i] = e_capture($1);
6428 0 0         if ($ignorecase) {
6429 0           $char[$i] = '@{[Char::Ekoi8r::ignorecase(' . $char[$i] . ')]}';
6430             }
6431             }
6432             elsif ($char[$i] =~ /\A \$ \{ \s* ([1-9][0-9]*) \s* \} \z/oxms) {
6433 0           $char[$i] = e_capture($1);
6434 0 0         if ($ignorecase) {
6435 0           $char[$i] = '@{[Char::Ekoi8r::ignorecase(' . $char[$i] . ')]}';
6436             }
6437             }
6438              
6439             # $$foo[ ... ] --> $ $foo->[ ... ]
6440             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) ( \[ (?:$qq_bracket)*? \] ) \z/oxms) {
6441 0           $char[$i] = e_capture($1.'->'.$2);
6442 0 0         if ($ignorecase) {
6443 0           $char[$i] = '@{[Char::Ekoi8r::ignorecase(' . $char[$i] . ')]}';
6444             }
6445             }
6446              
6447             # $$foo{ ... } --> $ $foo->{ ... }
6448             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) ( \{ (?:$qq_brace)*? \} ) \z/oxms) {
6449 0           $char[$i] = e_capture($1.'->'.$2);
6450 0 0         if ($ignorecase) {
6451 0           $char[$i] = '@{[Char::Ekoi8r::ignorecase(' . $char[$i] . ')]}';
6452             }
6453             }
6454              
6455             # $$foo
6456             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) \z/oxms) {
6457 0           $char[$i] = e_capture($1);
6458 0 0         if ($ignorecase) {
6459 0           $char[$i] = '@{[Char::Ekoi8r::ignorecase(' . $char[$i] . ')]}';
6460             }
6461             }
6462              
6463             # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Char::Ekoi8r::PREMATCH()
6464             elsif ($char[$i] =~ /\A ( \$` | \$\{`\} | \$ \s* PREMATCH | \$ \s* \{ \s* PREMATCH \s* \} | \$ \s* \{\^PREMATCH\} ) \z/oxmsgc) {
6465 0 0         if ($ignorecase) {
6466 0           $char[$i] = '@{[Char::Ekoi8r::ignorecase(Char::Ekoi8r::PREMATCH())]}';
6467             }
6468             else {
6469 0           $char[$i] = '@{[Char::Ekoi8r::PREMATCH()]}';
6470             }
6471             }
6472              
6473             # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Char::Ekoi8r::MATCH()
6474             elsif ($char[$i] =~ /\A ( \$& | \$\{&\} | \$ \s* MATCH | \$ \s* \{ \s* MATCH \s* \} | \$ \s* \{\^MATCH\} ) \z/oxmsgc) {
6475 0 0         if ($ignorecase) {
6476 0           $char[$i] = '@{[Char::Ekoi8r::ignorecase(Char::Ekoi8r::MATCH())]}';
6477             }
6478             else {
6479 0           $char[$i] = '@{[Char::Ekoi8r::MATCH()]}';
6480             }
6481             }
6482              
6483             # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Char::Ekoi8r::POSTMATCH()
6484             elsif ($char[$i] =~ /\A ( \$ \s* POSTMATCH | \$ \s* \{ \s* POSTMATCH \s* \} | \$ \s* \{\^POSTMATCH\} ) \z/oxmsgc) {
6485 0 0         if ($ignorecase) {
6486 0           $char[$i] = '@{[Char::Ekoi8r::ignorecase(Char::Ekoi8r::POSTMATCH())]}';
6487             }
6488             else {
6489 0           $char[$i] = '@{[Char::Ekoi8r::POSTMATCH()]}';
6490             }
6491             }
6492              
6493             # ${ foo }
6494             elsif ($char[$i] =~ /\A \$ \s* \{ ( \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* ) \} \z/oxms) {
6495 0 0         if ($ignorecase) {
6496 0           $char[$i] = '@{[Char::Ekoi8r::ignorecase(' . $char[$i] . ')]}';
6497             }
6498             }
6499              
6500             # ${ ... }
6501             elsif ($char[$i] =~ /\A \$ \s* \{ \s* ( .+ ) \s* \} \z/oxms) {
6502 0           $char[$i] = e_capture($1);
6503 0 0         if ($ignorecase) {
6504 0           $char[$i] = '@{[Char::Ekoi8r::ignorecase(' . $char[$i] . ')]}';
6505             }
6506             }
6507              
6508             # $scalar or @array
6509             elsif ($char[$i] =~ /\A [\$\@].+ /oxms) {
6510 0           $char[$i] = e_string($char[$i]);
6511 0 0         if ($ignorecase) {
6512 0           $char[$i] = '@{[Char::Ekoi8r::ignorecase(' . $char[$i] . ')]}';
6513             }
6514             }
6515              
6516             # quote character before ? + * {
6517             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
6518 0 0         if ($char[$i-1] =~ /\A (?:\\[0-7]{2,3}|\\x[0-9-A-Fa-f]{1,2}) \z/oxms) {
6519             }
6520             else {
6521 0           $char[$i-1] = '(?:' . $char[$i-1] . ')';
6522             }
6523             }
6524             }
6525              
6526             # make regexp string
6527 0           my $prematch = '';
6528 0           $modifier =~ tr/i//d;
6529 0 0         if ($left_e > $right_e) {
6530 0           return join '', $ope, $delimiter, $prematch, '(?:', @char, '>]}' x ($left_e - $right_e), ')', $matched, $end_delimiter, $modifier;
6531             }
6532 0           return join '', $ope, $delimiter, $prematch, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
6533             }
6534              
6535             #
6536             # escape regexp (s'here'' or s'here''b)
6537             #
6538             sub e_s1_q {
6539 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6540 0   0       $modifier ||= '';
6541              
6542 0           $modifier =~ tr/p//d;
6543 0 0         if ($modifier =~ /([adlu])/oxms) {
6544 0           my $line = 0;
6545 0           for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
6546 0 0         if ($filename ne __FILE__) {
6547 0           $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
6548 0           last;
6549             }
6550             }
6551 0           die qq{Unsupported modifier "$1" used at line $line.\n};
6552             }
6553              
6554 0           $slash = 'div';
6555              
6556             # literal null string pattern
6557 0 0         if ($string eq '') {
    0          
6558 0           $modifier =~ tr/bB//d;
6559 0           $modifier =~ tr/i//d;
6560 0           return join '', $ope, $delimiter, $end_delimiter, $modifier;
6561             }
6562              
6563             # with /b /B modifier
6564             elsif ($modifier =~ tr/bB//d) {
6565 0           return e_s1_qb($ope,$delimiter,$end_delimiter,$string,$modifier);
6566             }
6567              
6568             # without /b /B modifier
6569             else {
6570 0           return e_s1_qt($ope,$delimiter,$end_delimiter,$string,$modifier);
6571             }
6572             }
6573              
6574             #
6575             # escape regexp (s'here'')
6576             #
6577             sub e_s1_qt {
6578 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6579              
6580 0 0         my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
6581              
6582             # split regexp
6583 0           my @char = $string =~ /\G(
6584             \[\:\^ [a-z]+ \:\] |
6585             \[\: [a-z]+ \:\] |
6586             \[\^ |
6587             [\$\@\/\\] |
6588             \\? (?:$q_char)
6589             )/oxmsg;
6590              
6591             # unescape character
6592 0           for (my $i=0; $i <= $#char; $i++) {
6593 0 0 0       if (0) {
    0 0        
    0 0        
    0          
    0          
    0          
6594             }
6595              
6596             # open character class [...]
6597 0           elsif ($char[$i] eq '[') {
6598 0           my $left = $i;
6599 0 0         if ($char[$i+1] eq ']') {
6600 0           $i++;
6601             }
6602 0           while (1) {
6603 0 0         if (++$i > $#char) {
6604 0           die __FILE__, ": Unmatched [] in regexp";
6605             }
6606 0 0         if ($char[$i] eq ']') {
6607 0           my $right = $i;
6608              
6609             # [...]
6610 0           splice @char, $left, $right-$left+1, Char::Ekoi8r::charlist_qr(@char[$left+1..$right-1], $modifier);
6611              
6612 0           $i = $left;
6613 0           last;
6614             }
6615             }
6616             }
6617              
6618             # open character class [^...]
6619             elsif ($char[$i] eq '[^') {
6620 0           my $left = $i;
6621 0 0         if ($char[$i+1] eq ']') {
6622 0           $i++;
6623             }
6624 0           while (1) {
6625 0 0         if (++$i > $#char) {
6626 0           die __FILE__, ": Unmatched [] in regexp";
6627             }
6628 0 0         if ($char[$i] eq ']') {
6629 0           my $right = $i;
6630              
6631             # [^...]
6632 0           splice @char, $left, $right-$left+1, Char::Ekoi8r::charlist_not_qr(@char[$left+1..$right-1], $modifier);
6633              
6634 0           $i = $left;
6635 0           last;
6636             }
6637             }
6638             }
6639              
6640             # escape $ @ / and \
6641             elsif ($char[$i] =~ /\A [\$\@\/\\] \z/oxms) {
6642 0           $char[$i] = '\\' . $char[$i];
6643             }
6644              
6645             # rewrite character class or escape character
6646             elsif (my $char = character_class($char[$i],$modifier)) {
6647 0           $char[$i] = $char;
6648             }
6649              
6650             # /i modifier
6651             elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Char::Ekoi8r::uc($char[$i]) ne Char::Ekoi8r::fc($char[$i]))) {
6652 0 0         if (CORE::length(Char::Ekoi8r::fc($char[$i])) == 1) {
6653 0           $char[$i] = '[' . Char::Ekoi8r::uc($char[$i]) . Char::Ekoi8r::fc($char[$i]) . ']';
6654             }
6655             else {
6656 0           $char[$i] = '(?:' . Char::Ekoi8r::uc($char[$i]) . '|' . Char::Ekoi8r::fc($char[$i]) . ')';
6657             }
6658             }
6659              
6660             # quote character before ? + * {
6661             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
6662 0 0         if ($char[$i-1] =~ /\A [\x00-\xFF] \z/oxms) {
6663             }
6664             else {
6665 0           $char[$i-1] = '(?:' . $char[$i-1] . ')';
6666             }
6667             }
6668             }
6669              
6670 0           $modifier =~ tr/i//d;
6671 0           $delimiter = '/';
6672 0           $end_delimiter = '/';
6673 0           my $prematch = '';
6674 0           return join '', $ope, $delimiter, $prematch, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
6675             }
6676              
6677             #
6678             # escape regexp (s'here''b)
6679             #
6680             sub e_s1_qb {
6681 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6682              
6683             # split regexp
6684 0           my @char = $string =~ /\G(
6685             \\\\ |
6686             [\$\@\/\\] |
6687             [\x00-\xFF]
6688             )/oxmsg;
6689              
6690             # unescape character
6691 0           for (my $i=0; $i <= $#char; $i++) {
6692 0 0         if (0) {
    0          
6693             }
6694              
6695             # remain \\
6696 0           elsif ($char[$i] eq '\\\\') {
6697             }
6698              
6699             # escape $ @ / and \
6700             elsif ($char[$i] =~ /\A [\$\@\/\\] \z/oxms) {
6701 0           $char[$i] = '\\' . $char[$i];
6702             }
6703             }
6704              
6705 0           $delimiter = '/';
6706 0           $end_delimiter = '/';
6707 0           my $prematch = '';
6708 0           return join '', $ope, $delimiter, $prematch, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
6709             }
6710              
6711             #
6712             # escape regexp (s''here')
6713             #
6714             sub e_s2_q {
6715 0     0 0   my($ope,$delimiter,$end_delimiter,$string) = @_;
6716              
6717 0           $slash = 'div';
6718              
6719 0           my @char = $string =~ / \G (\\\\|[\$\@\/\\]|$q_char) /oxmsg;
6720 0           for (my $i=0; $i <= $#char; $i++) {
6721 0 0         if (0) {
    0          
6722             }
6723              
6724             # not escape \\
6725 0           elsif ($char[$i] =~ /\A \\\\ \z/oxms) {
6726             }
6727              
6728             # escape $ @ / and \
6729             elsif ($char[$i] =~ /\A [\$\@\/\\] \z/oxms) {
6730 0           $char[$i] = '\\' . $char[$i];
6731             }
6732             }
6733              
6734 0           return join '', $ope, $delimiter, @char, $end_delimiter;
6735             }
6736              
6737             #
6738             # escape regexp (s/here/and here/modifier)
6739             #
6740             sub e_sub {
6741 0     0 0   my($variable,$delimiter1,$pattern,$end_delimiter1,$delimiter2,$replacement,$end_delimiter2,$modifier) = @_;
6742 0   0       $modifier ||= '';
6743              
6744 0           $modifier =~ tr/p//d;
6745 0 0         if ($modifier =~ /([adlu])/oxms) {
6746 0           my $line = 0;
6747 0           for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
6748 0 0         if ($filename ne __FILE__) {
6749 0           $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
6750 0           last;
6751             }
6752             }
6753 0           die qq{Unsupported modifier "$1" used at line $line.\n};
6754             }
6755              
6756 0 0         if ($variable eq '') {
6757 0           $variable = '$_';
6758 0           $bind_operator = ' =~ ';
6759             }
6760              
6761 0           $slash = 'div';
6762              
6763             # P.128 Start of match (or end of previous match): \G
6764             # P.130 Advanced Use of \G with Perl
6765             # in Chapter 3: Overview of Regular Expression Features and Flavors
6766             # P.312 Iterative Matching: Scalar Context, with /g
6767             # in Chapter 7: Perl
6768             # of ISBN 0-596-00289-0 Mastering Regular Expressions, Second edition
6769              
6770             # P.181 Where You Left Off: The \G Assertion
6771             # in Chapter 5: Pattern Matching
6772             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
6773              
6774             # P.220 Where You Left Off: The \G Assertion
6775             # in Chapter 5: Pattern Matching
6776             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
6777              
6778 0           my $e_modifier = $modifier =~ tr/e//d;
6779 0           my $r_modifier = $modifier =~ tr/r//d;
6780              
6781 0           my $my = '';
6782 0 0         if ($variable =~ s/\A \( \s* ( (?: local \b | my \b | our \b | state \b )? .+ ) \) \z/$1/oxms) {
6783 0           $my = $variable;
6784 0           $variable =~ s/ (?: local \b | my \b | our \b | state \b ) \s* //oxms;
6785 0           $variable =~ s/ = .+ \z//oxms;
6786             }
6787              
6788 0           (my $variable_basename = $variable) =~ s/ [\[\{].* \z//oxms;
6789 0           $variable_basename =~ s/ \s+ \z//oxms;
6790              
6791             # quote replacement string
6792 0           my $e_replacement = '';
6793 0 0         if ($e_modifier >= 1) {
6794 0           $e_replacement = e_qq('', '', '', $replacement);
6795 0           $e_modifier--;
6796             }
6797             else {
6798 0 0         if ($delimiter2 eq "'") {
6799 0           $e_replacement = e_s2_q('qq', '/', '/', $replacement);
6800             }
6801             else {
6802 0           $e_replacement = e_qq ('qq', $delimiter2, $end_delimiter2, $replacement);
6803             }
6804             }
6805              
6806 0           my $sub = '';
6807              
6808             # with /r
6809 0 0         if ($r_modifier) {
6810 0 0         if (0) {
6811             }
6812              
6813             # s///gr without multibyte anchoring
6814 0           elsif ($modifier =~ /g/oxms) {
6815 0 0         $sub = sprintf(
6816             # 1 2 3 4 5
6817             q,
6818              
6819             $variable, # 1
6820             ($delimiter1 eq "'") ? # 2
6821             e_s1_q('m', $delimiter1, $end_delimiter1, $pattern, $modifier) : # :
6822             e_s1 ('m', $delimiter1, $end_delimiter1, $pattern, $modifier), # :
6823             $s_matched, # 3
6824             $e_replacement, # 4
6825             '$Char::KOI8R::re_r=CORE::eval $Char::KOI8R::re_r; ' x $e_modifier, # 5
6826             );
6827             }
6828              
6829             # s///r
6830             else {
6831              
6832 0           my $prematch = q{$`};
6833              
6834 0 0         $sub = sprintf(
6835             # 1 2 3 4 5 6 7
6836             q<(%s =~ %s) ? CORE::eval{%s local $^W=0; local $Char::KOI8R::re_r=%s; %s"%s$Char::KOI8R::re_r$'" } : %s>,
6837              
6838             $variable, # 1
6839             ($delimiter1 eq "'") ? # 2
6840             e_s1_q('m', $delimiter1, $end_delimiter1, $pattern, $modifier) : # :
6841             e_s1 ('m', $delimiter1, $end_delimiter1, $pattern, $modifier), # :
6842             $s_matched, # 3
6843             $e_replacement, # 4
6844             '$Char::KOI8R::re_r=CORE::eval $Char::KOI8R::re_r; ' x $e_modifier, # 5
6845             $prematch, # 6
6846             $variable, # 7
6847             );
6848             }
6849              
6850             # $var !~ s///r doesn't make sense
6851 0 0         if ($bind_operator =~ / !~ /oxms) {
6852 0           $sub = q{die("$0: Using !~ with s///r doesn't make sense"), } . $sub;
6853             }
6854             }
6855              
6856             # without /r
6857             else {
6858 0 0         if (0) {
6859             }
6860              
6861             # s///g without multibyte anchoring
6862 0           elsif ($modifier =~ /g/oxms) {
6863 0 0         $sub = sprintf(
    0          
6864             # 1 2 3 4 5 6 7 8
6865             q,
6866              
6867             $variable, # 1
6868             ($delimiter1 eq "'") ? # 2
6869             e_s1_q('m', $delimiter1, $end_delimiter1, $pattern, $modifier) : # :
6870             e_s1 ('m', $delimiter1, $end_delimiter1, $pattern, $modifier), # :
6871             $s_matched, # 3
6872             $e_replacement, # 4
6873             '$Char::KOI8R::re_r=CORE::eval $Char::KOI8R::re_r; ' x $e_modifier, # 5
6874             $variable, # 6
6875             $variable, # 7
6876             ($bind_operator =~ / !~ /oxms) ? '!' : '', # 8
6877             );
6878             }
6879              
6880             # s///
6881             else {
6882              
6883 0           my $prematch = q{$`};
6884              
6885 0 0         $sub = sprintf(
    0          
6886              
6887             ($bind_operator =~ / =~ /oxms) ?
6888              
6889             # 1 2 3 4 5 6 7 8
6890             q<(%s%s%s) ? CORE::eval{%s local $^W=0; local $Char::KOI8R::re_r=%s; %s%s="%s$Char::KOI8R::re_r$'"; 1 } : undef> :
6891              
6892             # 1 2 3 4 5 6 7 8
6893             q<(%s%s%s) ? 1 : CORE::eval{%s local $^W=0; local $Char::KOI8R::re_r=%s; %s%s="%s$Char::KOI8R::re_r$'"; undef }>,
6894              
6895             $variable, # 1
6896             $bind_operator, # 2
6897             ($delimiter1 eq "'") ? # 3
6898             e_s1_q('m', $delimiter1, $end_delimiter1, $pattern, $modifier) : # :
6899             e_s1 ('m', $delimiter1, $end_delimiter1, $pattern, $modifier), # :
6900             $s_matched, # 4
6901             $e_replacement, # 5
6902             '$Char::KOI8R::re_r=CORE::eval $Char::KOI8R::re_r; ' x $e_modifier, # 6
6903             $variable, # 7
6904             $prematch, # 8
6905             );
6906             }
6907             }
6908              
6909             # (my $foo = $bar) =~ s/// --> (my $foo = $bar, CORE::eval { ... })[1]
6910 0 0         if ($my ne '') {
6911 0           $sub = "($my, $sub)[1]";
6912             }
6913              
6914             # clear s/// variable
6915 0           $sub_variable = '';
6916 0           $bind_operator = '';
6917              
6918 0           return $sub;
6919             }
6920              
6921             #
6922             # escape regexp of split qr//
6923             #
6924             sub e_split {
6925 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6926 0   0       $modifier ||= '';
6927              
6928 0           $modifier =~ tr/p//d;
6929 0 0         if ($modifier =~ /([adlu])/oxms) {
6930 0           my $line = 0;
6931 0           for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
6932 0 0         if ($filename ne __FILE__) {
6933 0           $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
6934 0           last;
6935             }
6936             }
6937 0           die qq{Unsupported modifier "$1" used at line $line.\n};
6938             }
6939              
6940 0           $slash = 'div';
6941              
6942             # /b /B modifier
6943 0 0         if ($modifier =~ tr/bB//d) {
6944 0           return join '', 'split', $ope, $delimiter, $string, $end_delimiter, $modifier;
6945             }
6946              
6947 0 0         my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
6948 0           my $metachar = qr/[\@\\|[\]{^]/oxms;
6949              
6950             # split regexp
6951 0           my @char = $string =~ /\G(
6952             \\o\{ [0-7]+ \} |
6953             \\ [0-7]{2,3} |
6954             \\x\{ [0-9A-Fa-f]+ \} |
6955             \\x [0-9A-Fa-f]{1,2} |
6956             \\c [\x40-\x5F] |
6957             \\N\{ [^0-9\}][^\}]* \} |
6958             \\p\{ [^0-9\}][^\}]* \} |
6959             \\P\{ [^0-9\}][^\}]* \} |
6960             \\ (?:$q_char) |
6961             \$` | \$\{`\} | \$ \s* PREMATCH | \$ \s* \{ \s* PREMATCH \s* \} | \$ \s* \{\^PREMATCH\} |
6962             \$& | \$\{&\} | \$ \s* MATCH | \$ \s* \{ \s* MATCH \s* \} | \$ \s* \{\^MATCH\} |
6963             \$ \s* POSTMATCH | \$ \s* \{ \s* POSTMATCH \s* \} | \$ \s* \{\^POSTMATCH\} |
6964             [\$\@] $qq_variable |
6965             \$ \s* \d+ |
6966             \$ \s* \{ \s* \d+ \s* \} |
6967             \$ \$ (?![\w\{]) |
6968             \$ \s* \$ \s* $qq_variable |
6969             \[\:\^ (?:alnum|alpha|ascii|blank|cntrl|digit|graph|lower|print|punct|space|upper|word|xdigit) :\] |
6970             \[\: (?:alnum|alpha|ascii|blank|cntrl|digit|graph|lower|print|punct|space|upper|word|xdigit) :\] |
6971             \[\^ |
6972             \(\? |
6973             (?:$q_char)
6974             )/oxmsg;
6975              
6976 0           my $left_e = 0;
6977 0           my $right_e = 0;
6978 0           for (my $i=0; $i <= $#char; $i++) {
6979              
6980             # "\L\u" --> "\u\L"
6981 0 0 0       if (($char[$i] eq '\L') and ($char[$i+1] eq '\u')) {
    0 0        
    0          
    0          
    0          
    0          
    0          
    0          
6982 0           @char[$i,$i+1] = @char[$i+1,$i];
6983             }
6984              
6985             # "\U\l" --> "\l\U"
6986             elsif (($char[$i] eq '\U') and ($char[$i+1] eq '\l')) {
6987 0           @char[$i,$i+1] = @char[$i+1,$i];
6988             }
6989              
6990             # octal escape sequence
6991             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
6992 0           $char[$i] = Char::Ekoi8r::octchr($1);
6993             }
6994              
6995             # hexadecimal escape sequence
6996             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
6997 0           $char[$i] = Char::Ekoi8r::hexchr($1);
6998             }
6999              
7000             # \N{CHARNAME} --> N\{CHARNAME}
7001             elsif ($char[$i] =~ /\A \\ (N) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
7002 0           $char[$i] = $1 . '\\' . $2;
7003             }
7004              
7005             # \p{PROPERTY} --> p\{PROPERTY}
7006             elsif ($char[$i] =~ /\A \\ (p) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
7007 0           $char[$i] = $1 . '\\' . $2;
7008             }
7009              
7010             # \P{PROPERTY} --> P\{PROPERTY}
7011             elsif ($char[$i] =~ /\A \\ (P) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
7012 0           $char[$i] = $1 . '\\' . $2;
7013             }
7014              
7015             # \p, \P, \X --> p, P, X
7016             elsif ($char[$i] =~ /\A \\ ( [pPX] ) \z/oxms) {
7017 0           $char[$i] = $1;
7018             }
7019              
7020 0 0 0       if (0) {
    0 0        
    0 0        
    0 0        
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
7021             }
7022              
7023             # join separated multiple-octet
7024 0           elsif ($char[$i] =~ /\A (?: \\ [0-7]{2,3} | \\x [0-9A-Fa-f]{1,2}) \z/oxms) {
7025 0 0 0       if ( ($i+3 <= $#char) and (grep(/\A (?: \\ [0-7]{2,3} | \\x [0-9A-Fa-f]{1,2}) \z/oxms, @char[$i+1..$i+3]) == 3) and (CORE::eval(sprintf '"%s%s%s%s"', @char[$i..$i+3]) =~ /\A $q_char \z/oxms)) {
    0 0        
    0 0        
      0        
      0        
      0        
7026 0           $char[$i] .= join '', splice @char, $i+1, 3;
7027             }
7028             elsif (($i+2 <= $#char) and (grep(/\A (?: \\ [0-7]{2,3} | \\x [0-9A-Fa-f]{1,2}) \z/oxms, @char[$i+1..$i+2]) == 2) and (CORE::eval(sprintf '"%s%s%s"', @char[$i..$i+2]) =~ /\A $q_char \z/oxms)) {
7029 0           $char[$i] .= join '', splice @char, $i+1, 2;
7030             }
7031             elsif (($i+1 <= $#char) and (grep(/\A (?: \\ [0-7]{2,3} | \\x [0-9A-Fa-f]{1,2}) \z/oxms, $char[$i+1 ]) == 1) and (CORE::eval(sprintf '"%s%s"', @char[$i..$i+1]) =~ /\A $q_char \z/oxms)) {
7032 0           $char[$i] .= join '', splice @char, $i+1, 1;
7033             }
7034             }
7035              
7036             # open character class [...]
7037             elsif ($char[$i] eq '[') {
7038 0           my $left = $i;
7039 0 0         if ($char[$i+1] eq ']') {
7040 0           $i++;
7041             }
7042 0           while (1) {
7043 0 0         if (++$i > $#char) {
7044 0           die __FILE__, ": Unmatched [] in regexp";
7045             }
7046 0 0         if ($char[$i] eq ']') {
7047 0           my $right = $i;
7048              
7049             # [...]
7050 0 0         if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
7051 0           splice @char, $left, $right-$left+1, sprintf(q{@{[Char::Ekoi8r::charlist_qr(%s,'%s')]}}, join(',', map {qq_stuff($delimiter,$end_delimiter,$_)} @char[$left+1..$right-1]), $modifier);
  0            
7052             }
7053             else {
7054 0           splice @char, $left, $right-$left+1, Char::Ekoi8r::charlist_qr(@char[$left+1..$right-1], $modifier);
7055             }
7056              
7057 0           $i = $left;
7058 0           last;
7059             }
7060             }
7061             }
7062              
7063             # open character class [^...]
7064             elsif ($char[$i] eq '[^') {
7065 0           my $left = $i;
7066 0 0         if ($char[$i+1] eq ']') {
7067 0           $i++;
7068             }
7069 0           while (1) {
7070 0 0         if (++$i > $#char) {
7071 0           die __FILE__, ": Unmatched [] in regexp";
7072             }
7073 0 0         if ($char[$i] eq ']') {
7074 0           my $right = $i;
7075              
7076             # [^...]
7077 0 0         if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
7078 0           splice @char, $left, $right-$left+1, sprintf(q{@{[Char::Ekoi8r::charlist_not_qr(%s,'%s')]}}, join(',', map {qq_stuff($delimiter,$end_delimiter,$_)} @char[$left+1..$right-1]), $modifier);
  0            
7079             }
7080             else {
7081 0           splice @char, $left, $right-$left+1, Char::Ekoi8r::charlist_not_qr(@char[$left+1..$right-1], $modifier);
7082             }
7083              
7084 0           $i = $left;
7085 0           last;
7086             }
7087             }
7088             }
7089              
7090             # rewrite character class or escape character
7091             elsif (my $char = character_class($char[$i],$modifier)) {
7092 0           $char[$i] = $char;
7093             }
7094              
7095             # P.794 29.2.161. split
7096             # in Chapter 29: Functions
7097             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
7098              
7099             # P.951 split
7100             # in Chapter 27: Functions
7101             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
7102              
7103             # said "The //m modifier is assumed when you split on the pattern /^/",
7104             # but perl5.008 is not so. Therefore, this software adds //m.
7105             # (and so on)
7106              
7107             # split(m/^/) --> split(m/^/m)
7108             elsif (($char[$i] eq '^') and ($modifier !~ /m/oxms)) {
7109 0           $modifier .= 'm';
7110             }
7111              
7112             # /i modifier
7113             elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Char::Ekoi8r::uc($char[$i]) ne Char::Ekoi8r::fc($char[$i]))) {
7114 0 0         if (CORE::length(Char::Ekoi8r::fc($char[$i])) == 1) {
7115 0           $char[$i] = '[' . Char::Ekoi8r::uc($char[$i]) . Char::Ekoi8r::fc($char[$i]) . ']';
7116             }
7117             else {
7118 0           $char[$i] = '(?:' . Char::Ekoi8r::uc($char[$i]) . '|' . Char::Ekoi8r::fc($char[$i]) . ')';
7119             }
7120             }
7121              
7122             # \u \l \U \L \F \Q \E
7123             elsif ($char[$i] =~ /\A ([<>]) \z/oxms) {
7124 0 0         if ($right_e < $left_e) {
7125 0           $char[$i] = '\\' . $char[$i];
7126             }
7127             }
7128             elsif ($char[$i] eq '\u') {
7129 0           $char[$i] = '@{[Char::Ekoi8r::ucfirst qq<';
7130 0           $left_e++;
7131             }
7132             elsif ($char[$i] eq '\l') {
7133 0           $char[$i] = '@{[Char::Ekoi8r::lcfirst qq<';
7134 0           $left_e++;
7135             }
7136             elsif ($char[$i] eq '\U') {
7137 0           $char[$i] = '@{[Char::Ekoi8r::uc qq<';
7138 0           $left_e++;
7139             }
7140             elsif ($char[$i] eq '\L') {
7141 0           $char[$i] = '@{[Char::Ekoi8r::lc qq<';
7142 0           $left_e++;
7143             }
7144             elsif ($char[$i] eq '\F') {
7145 0           $char[$i] = '@{[Char::Ekoi8r::fc qq<';
7146 0           $left_e++;
7147             }
7148             elsif ($char[$i] eq '\Q') {
7149 0           $char[$i] = '@{[CORE::quotemeta qq<';
7150 0           $left_e++;
7151             }
7152             elsif ($char[$i] eq '\E') {
7153 0 0         if ($right_e < $left_e) {
7154 0           $char[$i] = '>]}';
7155 0           $right_e++;
7156             }
7157             else {
7158 0           $char[$i] = '';
7159             }
7160             }
7161             elsif ($char[$i] eq '\Q') {
7162 0           while (1) {
7163 0 0         if (++$i > $#char) {
7164 0           last;
7165             }
7166 0 0         if ($char[$i] eq '\E') {
7167 0           last;
7168             }
7169             }
7170             }
7171             elsif ($char[$i] eq '\E') {
7172             }
7173              
7174             # $0 --> $0
7175             elsif ($char[$i] =~ /\A \$ 0 \z/oxms) {
7176 0 0         if ($ignorecase) {
7177 0           $char[$i] = '@{[Char::Ekoi8r::ignorecase(' . $char[$i] . ')]}';
7178             }
7179             }
7180             elsif ($char[$i] =~ /\A \$ \{ \s* 0 \s* \} \z/oxms) {
7181 0 0         if ($ignorecase) {
7182 0           $char[$i] = '@{[Char::Ekoi8r::ignorecase(' . $char[$i] . ')]}';
7183             }
7184             }
7185              
7186             # $$ --> $$
7187             elsif ($char[$i] =~ /\A \$\$ \z/oxms) {
7188             }
7189              
7190             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
7191             # $1, $2, $3 --> $1, $2, $3 otherwise
7192             elsif ($char[$i] =~ /\A \$ ([1-9][0-9]*) \z/oxms) {
7193 0           $char[$i] = e_capture($1);
7194 0 0         if ($ignorecase) {
7195 0           $char[$i] = '@{[Char::Ekoi8r::ignorecase(' . $char[$i] . ')]}';
7196             }
7197             }
7198             elsif ($char[$i] =~ /\A \$ \{ \s* ([1-9][0-9]*) \s* \} \z/oxms) {
7199 0           $char[$i] = e_capture($1);
7200 0 0         if ($ignorecase) {
7201 0           $char[$i] = '@{[Char::Ekoi8r::ignorecase(' . $char[$i] . ')]}';
7202             }
7203             }
7204              
7205             # $$foo[ ... ] --> $ $foo->[ ... ]
7206             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) ( \[ (?:$qq_bracket)*? \] ) \z/oxms) {
7207 0           $char[$i] = e_capture($1.'->'.$2);
7208 0 0         if ($ignorecase) {
7209 0           $char[$i] = '@{[Char::Ekoi8r::ignorecase(' . $char[$i] . ')]}';
7210             }
7211             }
7212              
7213             # $$foo{ ... } --> $ $foo->{ ... }
7214             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) ( \{ (?:$qq_brace)*? \} ) \z/oxms) {
7215 0           $char[$i] = e_capture($1.'->'.$2);
7216 0 0         if ($ignorecase) {
7217 0           $char[$i] = '@{[Char::Ekoi8r::ignorecase(' . $char[$i] . ')]}';
7218             }
7219             }
7220              
7221             # $$foo
7222             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) \z/oxms) {
7223 0           $char[$i] = e_capture($1);
7224 0 0         if ($ignorecase) {
7225 0           $char[$i] = '@{[Char::Ekoi8r::ignorecase(' . $char[$i] . ')]}';
7226             }
7227             }
7228              
7229             # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Char::Ekoi8r::PREMATCH()
7230             elsif ($char[$i] =~ /\A ( \$` | \$\{`\} | \$ \s* PREMATCH | \$ \s* \{ \s* PREMATCH \s* \} | \$ \s* \{\^PREMATCH\} ) \z/oxmsgc) {
7231 0 0         if ($ignorecase) {
7232 0           $char[$i] = '@{[Char::Ekoi8r::ignorecase(Char::Ekoi8r::PREMATCH())]}';
7233             }
7234             else {
7235 0           $char[$i] = '@{[Char::Ekoi8r::PREMATCH()]}';
7236             }
7237             }
7238              
7239             # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Char::Ekoi8r::MATCH()
7240             elsif ($char[$i] =~ /\A ( \$& | \$\{&\} | \$ \s* MATCH | \$ \s* \{ \s* MATCH \s* \} | \$ \s* \{\^MATCH\} ) \z/oxmsgc) {
7241 0 0         if ($ignorecase) {
7242 0           $char[$i] = '@{[Char::Ekoi8r::ignorecase(Char::Ekoi8r::MATCH())]}';
7243             }
7244             else {
7245 0           $char[$i] = '@{[Char::Ekoi8r::MATCH()]}';
7246             }
7247             }
7248              
7249             # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Char::Ekoi8r::POSTMATCH()
7250             elsif ($char[$i] =~ /\A ( \$ \s* POSTMATCH | \$ \s* \{ \s* POSTMATCH \s* \} | \$ \s* \{\^POSTMATCH\} ) \z/oxmsgc) {
7251 0 0         if ($ignorecase) {
7252 0           $char[$i] = '@{[Char::Ekoi8r::ignorecase(Char::Ekoi8r::POSTMATCH())]}';
7253             }
7254             else {
7255 0           $char[$i] = '@{[Char::Ekoi8r::POSTMATCH()]}';
7256             }
7257             }
7258              
7259             # ${ foo }
7260             elsif ($char[$i] =~ /\A \$ \s* \{ ( \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* ) \} \z/oxms) {
7261 0 0         if ($ignorecase) {
7262 0           $char[$i] = '@{[Char::Ekoi8r::ignorecase(' . $1 . ')]}';
7263             }
7264             }
7265              
7266             # ${ ... }
7267             elsif ($char[$i] =~ /\A \$ \s* \{ \s* ( .+ ) \s* \} \z/oxms) {
7268 0           $char[$i] = e_capture($1);
7269 0 0         if ($ignorecase) {
7270 0           $char[$i] = '@{[Char::Ekoi8r::ignorecase(' . $char[$i] . ')]}';
7271             }
7272             }
7273              
7274             # $scalar or @array
7275             elsif ($char[$i] =~ /\A [\$\@].+ /oxms) {
7276 0           $char[$i] = e_string($char[$i]);
7277 0 0         if ($ignorecase) {
7278 0           $char[$i] = '@{[Char::Ekoi8r::ignorecase(' . $char[$i] . ')]}';
7279             }
7280             }
7281              
7282             # quote character before ? + * {
7283             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
7284 0 0         if ($char[$i-1] =~ /\A (?:\\[0-7]{2,3}|\\x[0-9-A-Fa-f]{1,2}) \z/oxms) {
7285             }
7286             else {
7287 0           $char[$i-1] = '(?:' . $char[$i-1] . ')';
7288             }
7289             }
7290             }
7291              
7292             # make regexp string
7293 0           $modifier =~ tr/i//d;
7294 0 0         if ($left_e > $right_e) {
7295 0           return join '', 'Char::Ekoi8r::split', $ope, $delimiter, @char, '>]}' x ($left_e - $right_e), $end_delimiter, $modifier;
7296             }
7297 0           return join '', 'Char::Ekoi8r::split', $ope, $delimiter, @char, $end_delimiter, $modifier;
7298             }
7299              
7300             #
7301             # escape regexp of split qr''
7302             #
7303             sub e_split_q {
7304 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
7305 0   0       $modifier ||= '';
7306              
7307 0           $modifier =~ tr/p//d;
7308 0 0         if ($modifier =~ /([adlu])/oxms) {
7309 0           my $line = 0;
7310 0           for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
7311 0 0         if ($filename ne __FILE__) {
7312 0           $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
7313 0           last;
7314             }
7315             }
7316 0           die qq{Unsupported modifier "$1" used at line $line.\n};
7317             }
7318              
7319 0           $slash = 'div';
7320              
7321             # /b /B modifier
7322 0 0         if ($modifier =~ tr/bB//d) {
7323 0           return join '', 'split', $ope, $delimiter, $string, $end_delimiter, $modifier;
7324             }
7325              
7326 0 0         my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
7327              
7328             # split regexp
7329 0           my @char = $string =~ /\G(
7330             \[\:\^ [a-z]+ \:\] |
7331             \[\: [a-z]+ \:\] |
7332             \[\^ |
7333             \\? (?:$q_char)
7334             )/oxmsg;
7335              
7336             # unescape character
7337 0           for (my $i=0; $i <= $#char; $i++) {
7338 0 0 0       if (0) {
    0 0        
    0 0        
    0 0        
    0          
    0          
7339             }
7340              
7341             # open character class [...]
7342 0           elsif ($char[$i] eq '[') {
7343 0           my $left = $i;
7344 0 0         if ($char[$i+1] eq ']') {
7345 0           $i++;
7346             }
7347 0           while (1) {
7348 0 0         if (++$i > $#char) {
7349 0           die __FILE__, ": Unmatched [] in regexp";
7350             }
7351 0 0         if ($char[$i] eq ']') {
7352 0           my $right = $i;
7353              
7354             # [...]
7355 0           splice @char, $left, $right-$left+1, Char::Ekoi8r::charlist_qr(@char[$left+1..$right-1], $modifier);
7356              
7357 0           $i = $left;
7358 0           last;
7359             }
7360             }
7361             }
7362              
7363             # open character class [^...]
7364             elsif ($char[$i] eq '[^') {
7365 0           my $left = $i;
7366 0 0         if ($char[$i+1] eq ']') {
7367 0           $i++;
7368             }
7369 0           while (1) {
7370 0 0         if (++$i > $#char) {
7371 0           die __FILE__, ": Unmatched [] in regexp";
7372             }
7373 0 0         if ($char[$i] eq ']') {
7374 0           my $right = $i;
7375              
7376             # [^...]
7377 0           splice @char, $left, $right-$left+1, Char::Ekoi8r::charlist_not_qr(@char[$left+1..$right-1], $modifier);
7378              
7379 0           $i = $left;
7380 0           last;
7381             }
7382             }
7383             }
7384              
7385             # rewrite character class or escape character
7386             elsif (my $char = character_class($char[$i],$modifier)) {
7387 0           $char[$i] = $char;
7388             }
7389              
7390             # split(m/^/) --> split(m/^/m)
7391             elsif (($char[$i] eq '^') and ($modifier !~ /m/oxms)) {
7392 0           $modifier .= 'm';
7393             }
7394              
7395             # /i modifier
7396             elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Char::Ekoi8r::uc($char[$i]) ne Char::Ekoi8r::fc($char[$i]))) {
7397 0 0         if (CORE::length(Char::Ekoi8r::fc($char[$i])) == 1) {
7398 0           $char[$i] = '[' . Char::Ekoi8r::uc($char[$i]) . Char::Ekoi8r::fc($char[$i]) . ']';
7399             }
7400             else {
7401 0           $char[$i] = '(?:' . Char::Ekoi8r::uc($char[$i]) . '|' . Char::Ekoi8r::fc($char[$i]) . ')';
7402             }
7403             }
7404              
7405             # quote character before ? + * {
7406             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
7407 0 0         if ($char[$i-1] =~ /\A [\x00-\xFF] \z/oxms) {
7408             }
7409             else {
7410 0           $char[$i-1] = '(?:' . $char[$i-1] . ')';
7411             }
7412             }
7413             }
7414              
7415 0           $modifier =~ tr/i//d;
7416 0           return join '', 'Char::Ekoi8r::split', $ope, $delimiter, @char, $end_delimiter, $modifier;
7417             }
7418              
7419             #
7420             # instead of Carp::carp
7421             #
7422             sub carp {
7423 0     0 0   my($package,$filename,$line) = caller(1);
7424 0           print STDERR "@_ at $filename line $line.\n";
7425             }
7426              
7427             #
7428             # instead of Carp::croak
7429             #
7430             sub croak {
7431 0     0 0   my($package,$filename,$line) = caller(1);
7432 0           print STDERR "@_ at $filename line $line.\n";
7433 0           die "\n";
7434             }
7435              
7436             #
7437             # instead of Carp::cluck
7438             #
7439             sub cluck {
7440 0     0 0   my $i = 0;
7441 0           my @cluck = ();
7442 0           while (my($package,$filename,$line,$subroutine) = caller($i)) {
7443 0           push @cluck, "[$i] $filename($line) $package::$subroutine\n";
7444 0           $i++;
7445             }
7446 0           print STDERR CORE::reverse @cluck;
7447 0           print STDERR "\n";
7448 0           carp @_;
7449             }
7450              
7451             #
7452             # instead of Carp::confess
7453             #
7454             sub confess {
7455 0     0 0   my $i = 0;
7456 0           my @confess = ();
7457 0           while (my($package,$filename,$line,$subroutine) = caller($i)) {
7458 0           push @confess, "[$i] $filename($line) $package::$subroutine\n";
7459 0           $i++;
7460             }
7461 0           print STDERR CORE::reverse @confess;
7462 0           print STDERR "\n";
7463 0           croak @_;
7464             }
7465              
7466             1;
7467              
7468             __END__