File Coverage

Char/Ekoi8u.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::Ekoi8u;
5             ######################################################################
6             #
7             # Char::Ekoi8u - Run-time routines for Char/KOI8U.pm
8             #
9             # http://search.cpan.org/dist/Char-KOI8U/
10             #
11             # Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015 INABA Hitoshi
12             ######################################################################
13              
14 197     197   4730 use 5.00503; # Galapagos Consensus 1998 for primetools
  197         639  
  197         11176  
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   15926 BEGIN { CORE::eval q{ use vars qw($VERSION) } }
  197     197   1165  
  197         348  
  197         38676  
23             $VERSION = sprintf '%d.%02d', q$Revision: 1.02 $ =~ /(\d+)/xmsg;
24              
25             BEGIN {
26 197 50   197   1451 if ($^X =~ / jperl /oxmsi) {
27 0         0 die __FILE__, ": needs perl(not jperl) 5.00503 or later. (\$^X==$^X)";
28             }
29 197         558 if (CORE::ord('A') == 193) {
30             die __FILE__, ": is not US-ASCII script (may be EBCDIC or EBCDIK script).";
31             }
32 197         30413 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   13454 CORE::eval q{
  197     197   1381  
  197     70   328  
  197         34181  
  70         12106  
  67         13079  
  78         12346  
  64         12517  
  60         10587  
  55         10536  
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       142789 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   515 my $genpkg = "Symbol::";
62 197         10109 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::Ekoi8u::index($name, '::') == -1) && (Char::Ekoi8u::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   620 if (CORE::eval { local $@; CORE::require strict }) {
  197         437  
  197         2205  
110 197         32115 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   13487 BEGIN { CORE::eval q{ use vars qw($your_char) } } $your_char = q{[\x00-\xFF]};
  197     197   1419  
  197         325  
  197         13701  
140 197     197   11607 BEGIN { CORE::eval q{ use vars qw($qq_char ) } } $qq_char = qr/\\c[\x40-\x5F]|\\?(?:$your_char)/oxms;
  197     197   1115  
  197         463  
  197         13773  
141 197     197   11534 BEGIN { CORE::eval q{ use vars qw($q_char ) } } $q_char = qr/$your_char/oxms;
  197     197   1284  
  197         328  
  197         16302  
142              
143             #
144             # KOI8-U character range per length
145             #
146             my %range_tr = ();
147              
148             #
149             # alias of encoding name
150             #
151 197     197   29963 BEGIN { CORE::eval q{ use vars qw($encoding_alias) } }
  197     197   1239  
  197         331  
  197         397313  
152              
153             #
154             # KOI8-U 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 Ekoi8u \z/oxms) {
170             %range_tr = (
171             1 => [ [0x00..0xFF],
172             ],
173             );
174             $encoding_alias = qr/ \b (?: koi8-?u ) \b /oxmsi;
175              
176             %lc = (%lc,
177             "\xB3" => "\xA3", # CYRILLIC LETTER IO
178             "\xB4" => "\xA4", # CYRILLIC LETTER UKRAINIAN IE
179             "\xB6" => "\xA6", # CYRILLIC LETTER BYELORUSSIAN-UKRAINIAN I
180             "\xB7" => "\xA7", # CYRILLIC LETTER YI (UKRAINIAN)
181             "\xBD" => "\xAD", # CYRILLIC LETTER GHE WITH UPTURN
182             "\xE0" => "\xC0", # CYRILLIC LETTER YU
183             "\xE1" => "\xC1", # CYRILLIC LETTER A
184             "\xE2" => "\xC2", # CYRILLIC LETTER BE
185             "\xE3" => "\xC3", # CYRILLIC LETTER TSE
186             "\xE4" => "\xC4", # CYRILLIC LETTER DE
187             "\xE5" => "\xC5", # CYRILLIC LETTER IE
188             "\xE6" => "\xC6", # CYRILLIC LETTER EF
189             "\xE7" => "\xC7", # CYRILLIC LETTER GHE
190             "\xE8" => "\xC8", # CYRILLIC LETTER KHA
191             "\xE9" => "\xC9", # CYRILLIC LETTER I
192             "\xEA" => "\xCA", # CYRILLIC LETTER SHORT I
193             "\xEB" => "\xCB", # CYRILLIC LETTER KA
194             "\xEC" => "\xCC", # CYRILLIC LETTER EL
195             "\xED" => "\xCD", # CYRILLIC LETTER EM
196             "\xEE" => "\xCE", # CYRILLIC LETTER EN
197             "\xEF" => "\xCF", # CYRILLIC LETTER O
198             "\xF0" => "\xD0", # CYRILLIC LETTER PE
199             "\xF1" => "\xD1", # CYRILLIC LETTER YA
200             "\xF2" => "\xD2", # CYRILLIC LETTER ER
201             "\xF3" => "\xD3", # CYRILLIC LETTER ES
202             "\xF4" => "\xD4", # CYRILLIC LETTER TE
203             "\xF5" => "\xD5", # CYRILLIC LETTER U
204             "\xF6" => "\xD6", # CYRILLIC LETTER ZHE
205             "\xF7" => "\xD7", # CYRILLIC LETTER VE
206             "\xF8" => "\xD8", # CYRILLIC LETTER SOFT SIGN
207             "\xF9" => "\xD9", # CYRILLIC LETTER YERU
208             "\xFA" => "\xDA", # CYRILLIC LETTER ZE
209             "\xFB" => "\xDB", # CYRILLIC LETTER SHA
210             "\xFC" => "\xDC", # CYRILLIC LETTER E
211             "\xFD" => "\xDD", # CYRILLIC LETTER SHCHA
212             "\xFE" => "\xDE", # CYRILLIC LETTER CHE
213             "\xFF" => "\xDF", # CYRILLIC LETTER HARD SIGN
214             );
215              
216             %uc = (%uc,
217             "\xA3" => "\xB3", # CYRILLIC LETTER IO
218             "\xA4" => "\xB4", # CYRILLIC LETTER UKRAINIAN IE
219             "\xA6" => "\xB6", # CYRILLIC LETTER BYELORUSSIAN-UKRAINIAN I
220             "\xA7" => "\xB7", # CYRILLIC LETTER YI (UKRAINIAN)
221             "\xAD" => "\xBD", # CYRILLIC LETTER GHE WITH UPTURN
222             "\xC0" => "\xE0", # CYRILLIC LETTER YU
223             "\xC1" => "\xE1", # CYRILLIC LETTER A
224             "\xC2" => "\xE2", # CYRILLIC LETTER BE
225             "\xC3" => "\xE3", # CYRILLIC LETTER TSE
226             "\xC4" => "\xE4", # CYRILLIC LETTER DE
227             "\xC5" => "\xE5", # CYRILLIC LETTER IE
228             "\xC6" => "\xE6", # CYRILLIC LETTER EF
229             "\xC7" => "\xE7", # CYRILLIC LETTER GHE
230             "\xC8" => "\xE8", # CYRILLIC LETTER KHA
231             "\xC9" => "\xE9", # CYRILLIC LETTER I
232             "\xCA" => "\xEA", # CYRILLIC LETTER SHORT I
233             "\xCB" => "\xEB", # CYRILLIC LETTER KA
234             "\xCC" => "\xEC", # CYRILLIC LETTER EL
235             "\xCD" => "\xED", # CYRILLIC LETTER EM
236             "\xCE" => "\xEE", # CYRILLIC LETTER EN
237             "\xCF" => "\xEF", # CYRILLIC LETTER O
238             "\xD0" => "\xF0", # CYRILLIC LETTER PE
239             "\xD1" => "\xF1", # CYRILLIC LETTER YA
240             "\xD2" => "\xF2", # CYRILLIC LETTER ER
241             "\xD3" => "\xF3", # CYRILLIC LETTER ES
242             "\xD4" => "\xF4", # CYRILLIC LETTER TE
243             "\xD5" => "\xF5", # CYRILLIC LETTER U
244             "\xD6" => "\xF6", # CYRILLIC LETTER ZHE
245             "\xD7" => "\xF7", # CYRILLIC LETTER VE
246             "\xD8" => "\xF8", # CYRILLIC LETTER SOFT SIGN
247             "\xD9" => "\xF9", # CYRILLIC LETTER YERU
248             "\xDA" => "\xFA", # CYRILLIC LETTER ZE
249             "\xDB" => "\xFB", # CYRILLIC LETTER SHA
250             "\xDC" => "\xFC", # CYRILLIC LETTER E
251             "\xDD" => "\xFD", # CYRILLIC LETTER SHCHA
252             "\xDE" => "\xFE", # CYRILLIC LETTER CHE
253             "\xDF" => "\xFF", # CYRILLIC LETTER HARD SIGN
254             );
255              
256             %fc = (%fc,
257             "\xB3" => "\xA3", # CYRILLIC CAPITAL LETTER IO --> CYRILLIC SMALL LETTER IO
258             "\xB4" => "\xA4", # CYRILLIC CAPITAL LETTER UKRAINIAN IE --> CYRILLIC SMALL LETTER UKRAINIAN IE
259             "\xB6" => "\xA6", # CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I --> CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I
260             "\xB7" => "\xA7", # CYRILLIC CAPITAL LETTER YI --> CYRILLIC SMALL LETTER YI
261             "\xBD" => "\xAD", # CYRILLIC CAPITAL LETTER GHE WITH UPTURN --> CYRILLIC SMALL LETTER GHE WITH UPTURN
262             "\xE0" => "\xC0", # CYRILLIC CAPITAL LETTER YU --> CYRILLIC SMALL LETTER YU
263             "\xE1" => "\xC1", # CYRILLIC CAPITAL LETTER A --> CYRILLIC SMALL LETTER A
264             "\xE2" => "\xC2", # CYRILLIC CAPITAL LETTER BE --> CYRILLIC SMALL LETTER BE
265             "\xE3" => "\xC3", # CYRILLIC CAPITAL LETTER TSE --> CYRILLIC SMALL LETTER TSE
266             "\xE4" => "\xC4", # CYRILLIC CAPITAL LETTER DE --> CYRILLIC SMALL LETTER DE
267             "\xE5" => "\xC5", # CYRILLIC CAPITAL LETTER IE --> CYRILLIC SMALL LETTER IE
268             "\xE6" => "\xC6", # CYRILLIC CAPITAL LETTER EF --> CYRILLIC SMALL LETTER EF
269             "\xE7" => "\xC7", # CYRILLIC CAPITAL LETTER GHE --> CYRILLIC SMALL LETTER GHE
270             "\xE8" => "\xC8", # CYRILLIC CAPITAL LETTER HA --> CYRILLIC SMALL LETTER HA
271             "\xE9" => "\xC9", # CYRILLIC CAPITAL LETTER I --> CYRILLIC SMALL LETTER I
272             "\xEA" => "\xCA", # CYRILLIC CAPITAL LETTER SHORT I --> CYRILLIC SMALL LETTER SHORT I
273             "\xEB" => "\xCB", # CYRILLIC CAPITAL LETTER KA --> CYRILLIC SMALL LETTER KA
274             "\xEC" => "\xCC", # CYRILLIC CAPITAL LETTER EL --> CYRILLIC SMALL LETTER EL
275             "\xED" => "\xCD", # CYRILLIC CAPITAL LETTER EM --> CYRILLIC SMALL LETTER EM
276             "\xEE" => "\xCE", # CYRILLIC CAPITAL LETTER EN --> CYRILLIC SMALL LETTER EN
277             "\xEF" => "\xCF", # CYRILLIC CAPITAL LETTER O --> CYRILLIC SMALL LETTER O
278             "\xF0" => "\xD0", # CYRILLIC CAPITAL LETTER PE --> CYRILLIC SMALL LETTER PE
279             "\xF1" => "\xD1", # CYRILLIC CAPITAL LETTER YA --> CYRILLIC SMALL LETTER YA
280             "\xF2" => "\xD2", # CYRILLIC CAPITAL LETTER ER --> CYRILLIC SMALL LETTER ER
281             "\xF3" => "\xD3", # CYRILLIC CAPITAL LETTER ES --> CYRILLIC SMALL LETTER ES
282             "\xF4" => "\xD4", # CYRILLIC CAPITAL LETTER TE --> CYRILLIC SMALL LETTER TE
283             "\xF5" => "\xD5", # CYRILLIC CAPITAL LETTER U --> CYRILLIC SMALL LETTER U
284             "\xF6" => "\xD6", # CYRILLIC CAPITAL LETTER ZHE --> CYRILLIC SMALL LETTER ZHE
285             "\xF7" => "\xD7", # CYRILLIC CAPITAL LETTER VE --> CYRILLIC SMALL LETTER VE
286             "\xF8" => "\xD8", # CYRILLIC CAPITAL LETTER SOFT SIGN --> CYRILLIC SMALL LETTER SOFT SIGN
287             "\xF9" => "\xD9", # CYRILLIC CAPITAL LETTER YERU --> CYRILLIC SMALL LETTER YERU
288             "\xFA" => "\xDA", # CYRILLIC CAPITAL LETTER ZE --> CYRILLIC SMALL LETTER ZE
289             "\xFB" => "\xDB", # CYRILLIC CAPITAL LETTER SHA --> CYRILLIC SMALL LETTER SHA
290             "\xFC" => "\xDC", # CYRILLIC CAPITAL LETTER E --> CYRILLIC SMALL LETTER E
291             "\xFD" => "\xDD", # CYRILLIC CAPITAL LETTER SHCHA --> CYRILLIC SMALL LETTER SHCHA
292             "\xFE" => "\xDE", # CYRILLIC CAPITAL LETTER CHE --> CYRILLIC SMALL LETTER CHE
293             "\xFF" => "\xDF", # CYRILLIC CAPITAL LETTER HARD SIGN --> CYRILLIC SMALL LETTER HARD SIGN
294             );
295             }
296              
297             else {
298             croak "Don't know my package name '@{[__PACKAGE__]}'";
299             }
300              
301             #
302             # @ARGV wildcard globbing
303             #
304             sub import {
305              
306 0 0   0   0 if ($^O =~ /\A (?: MSWin32 | NetWare | symbian | dos ) \z/oxms) {
307 0         0 my @argv = ();
308 0         0 for (@ARGV) {
309              
310             # has space
311 0 0       0 if (/\A (?:$q_char)*? [ ] /oxms) {
    0          
312 0 0       0 if (my @glob = Char::Ekoi8u::glob(qq{"$_"})) {
313 0         0 push @argv, @glob;
314             }
315             else {
316 0         0 push @argv, $_;
317             }
318             }
319              
320             # has wildcard metachar
321             elsif (/\A (?:$q_char)*? [*?] /oxms) {
322 0 0       0 if (my @glob = Char::Ekoi8u::glob($_)) {
323 0         0 push @argv, @glob;
324             }
325             else {
326 0         0 push @argv, $_;
327             }
328             }
329              
330             # no wildcard globbing
331             else {
332 0         0 push @argv, $_;
333             }
334             }
335 0         0 @ARGV = @argv;
336             }
337             }
338              
339             # P.230 Care with Prototypes
340             # in Chapter 6: Subroutines
341             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
342             #
343             # If you aren't careful, you can get yourself into trouble with prototypes.
344             # But if you are careful, you can do a lot of neat things with them. This is
345             # all very powerful, of course, and should only be used in moderation to make
346             # the world a better place.
347              
348             # P.332 Care with Prototypes
349             # in Chapter 7: Subroutines
350             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
351             #
352             # If you aren't careful, you can get yourself into trouble with prototypes.
353             # But if you are careful, you can do a lot of neat things with them. This is
354             # all very powerful, of course, and should only be used in moderation to make
355             # the world a better place.
356              
357             #
358             # Prototypes of subroutines
359             #
360 0     0   0 sub unimport {}
361             sub Char::Ekoi8u::split(;$$$);
362             sub Char::Ekoi8u::tr($$$$;$);
363             sub Char::Ekoi8u::chop(@);
364             sub Char::Ekoi8u::index($$;$);
365             sub Char::Ekoi8u::rindex($$;$);
366             sub Char::Ekoi8u::lcfirst(@);
367             sub Char::Ekoi8u::lcfirst_();
368             sub Char::Ekoi8u::lc(@);
369             sub Char::Ekoi8u::lc_();
370             sub Char::Ekoi8u::ucfirst(@);
371             sub Char::Ekoi8u::ucfirst_();
372             sub Char::Ekoi8u::uc(@);
373             sub Char::Ekoi8u::uc_();
374             sub Char::Ekoi8u::fc(@);
375             sub Char::Ekoi8u::fc_();
376             sub Char::Ekoi8u::ignorecase;
377             sub Char::Ekoi8u::classic_character_class;
378             sub Char::Ekoi8u::capture;
379             sub Char::Ekoi8u::chr(;$);
380             sub Char::Ekoi8u::chr_();
381             sub Char::Ekoi8u::glob($);
382             sub Char::Ekoi8u::glob_();
383              
384             sub Char::KOI8U::ord(;$);
385             sub Char::KOI8U::ord_();
386             sub Char::KOI8U::reverse(@);
387             sub Char::KOI8U::getc(;*@);
388             sub Char::KOI8U::length(;$);
389             sub Char::KOI8U::substr($$;$$);
390             sub Char::KOI8U::index($$;$);
391             sub Char::KOI8U::rindex($$;$);
392             sub Char::KOI8U::escape(;$);
393              
394             #
395             # Regexp work
396             #
397 197     197   16441 BEGIN { CORE::eval q{ use vars qw(
  197     197   1360  
  197         418  
  197         87027  
398             $Char::KOI8U::re_a
399             $Char::KOI8U::re_t
400             $Char::KOI8U::re_n
401             $Char::KOI8U::re_r
402             ) } }
403              
404             #
405             # Character class
406             #
407 197     197   15942 BEGIN { CORE::eval q{ use vars qw(
  197     197   1210  
  197         329  
  197         3232279  
408             $dot
409             $dot_s
410             $eD
411             $eS
412             $eW
413             $eH
414             $eV
415             $eR
416             $eN
417             $not_alnum
418             $not_alpha
419             $not_ascii
420             $not_blank
421             $not_cntrl
422             $not_digit
423             $not_graph
424             $not_lower
425             $not_lower_i
426             $not_print
427             $not_punct
428             $not_space
429             $not_upper
430             $not_upper_i
431             $not_word
432             $not_xdigit
433             $eb
434             $eB
435             ) } }
436              
437             ${Char::Ekoi8u::dot} = qr{(?:[^\x0A])};
438             ${Char::Ekoi8u::dot_s} = qr{(?:[\x00-\xFF])};
439             ${Char::Ekoi8u::eD} = qr{(?:[^0-9])};
440              
441             # Vertical tabs are now whitespace
442             # \s in a regex now matches a vertical tab in all circumstances.
443             # http://search.cpan.org/dist/perl-5.18.0/pod/perldelta.pod#Vertical_tabs_are_now_whitespace
444             # ${Char::Ekoi8u::eS} = qr{(?:[^\x09\x0A \x0C\x0D\x20])};
445             # ${Char::Ekoi8u::eS} = qr{(?:[^\x09\x0A\x0B\x0C\x0D\x20])};
446             ${Char::Ekoi8u::eS} = qr{(?:[^\s])};
447              
448             ${Char::Ekoi8u::eW} = qr{(?:[^0-9A-Z_a-z])};
449             ${Char::Ekoi8u::eH} = qr{(?:[^\x09\x20])};
450             ${Char::Ekoi8u::eV} = qr{(?:[^\x0A\x0B\x0C\x0D])};
451             ${Char::Ekoi8u::eR} = qr{(?:\x0D\x0A|[\x0A\x0D])};
452             ${Char::Ekoi8u::eN} = qr{(?:[^\x0A])};
453             ${Char::Ekoi8u::not_alnum} = qr{(?:[^\x30-\x39\x41-\x5A\x61-\x7A])};
454             ${Char::Ekoi8u::not_alpha} = qr{(?:[^\x41-\x5A\x61-\x7A])};
455             ${Char::Ekoi8u::not_ascii} = qr{(?:[^\x00-\x7F])};
456             ${Char::Ekoi8u::not_blank} = qr{(?:[^\x09\x20])};
457             ${Char::Ekoi8u::not_cntrl} = qr{(?:[^\x00-\x1F\x7F])};
458             ${Char::Ekoi8u::not_digit} = qr{(?:[^\x30-\x39])};
459             ${Char::Ekoi8u::not_graph} = qr{(?:[^\x21-\x7F])};
460             ${Char::Ekoi8u::not_lower} = qr{(?:[^\x61-\x7A])};
461             ${Char::Ekoi8u::not_lower_i} = qr{(?:[\x00-\xFF])};
462             ${Char::Ekoi8u::not_print} = qr{(?:[^\x20-\x7F])};
463             ${Char::Ekoi8u::not_punct} = qr{(?:[^\x21-\x2F\x3A-\x3F\x40\x5B-\x5F\x60\x7B-\x7E])};
464             ${Char::Ekoi8u::not_space} = qr{(?:[^\s\x0B])};
465             ${Char::Ekoi8u::not_upper} = qr{(?:[^\x41-\x5A])};
466             ${Char::Ekoi8u::not_upper_i} = qr{(?:[\x00-\xFF])};
467             ${Char::Ekoi8u::not_word} = qr{(?:[^\x30-\x39\x41-\x5A\x5F\x61-\x7A])};
468             ${Char::Ekoi8u::not_xdigit} = qr{(?:[^\x30-\x39\x41-\x46\x61-\x66])};
469             ${Char::Ekoi8u::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))};
470             ${Char::Ekoi8u::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]))};
471              
472             # avoid: Name "Char::Ekoi8u::foo" used only once: possible typo at here.
473             ${Char::Ekoi8u::dot} = ${Char::Ekoi8u::dot};
474             ${Char::Ekoi8u::dot_s} = ${Char::Ekoi8u::dot_s};
475             ${Char::Ekoi8u::eD} = ${Char::Ekoi8u::eD};
476             ${Char::Ekoi8u::eS} = ${Char::Ekoi8u::eS};
477             ${Char::Ekoi8u::eW} = ${Char::Ekoi8u::eW};
478             ${Char::Ekoi8u::eH} = ${Char::Ekoi8u::eH};
479             ${Char::Ekoi8u::eV} = ${Char::Ekoi8u::eV};
480             ${Char::Ekoi8u::eR} = ${Char::Ekoi8u::eR};
481             ${Char::Ekoi8u::eN} = ${Char::Ekoi8u::eN};
482             ${Char::Ekoi8u::not_alnum} = ${Char::Ekoi8u::not_alnum};
483             ${Char::Ekoi8u::not_alpha} = ${Char::Ekoi8u::not_alpha};
484             ${Char::Ekoi8u::not_ascii} = ${Char::Ekoi8u::not_ascii};
485             ${Char::Ekoi8u::not_blank} = ${Char::Ekoi8u::not_blank};
486             ${Char::Ekoi8u::not_cntrl} = ${Char::Ekoi8u::not_cntrl};
487             ${Char::Ekoi8u::not_digit} = ${Char::Ekoi8u::not_digit};
488             ${Char::Ekoi8u::not_graph} = ${Char::Ekoi8u::not_graph};
489             ${Char::Ekoi8u::not_lower} = ${Char::Ekoi8u::not_lower};
490             ${Char::Ekoi8u::not_lower_i} = ${Char::Ekoi8u::not_lower_i};
491             ${Char::Ekoi8u::not_print} = ${Char::Ekoi8u::not_print};
492             ${Char::Ekoi8u::not_punct} = ${Char::Ekoi8u::not_punct};
493             ${Char::Ekoi8u::not_space} = ${Char::Ekoi8u::not_space};
494             ${Char::Ekoi8u::not_upper} = ${Char::Ekoi8u::not_upper};
495             ${Char::Ekoi8u::not_upper_i} = ${Char::Ekoi8u::not_upper_i};
496             ${Char::Ekoi8u::not_word} = ${Char::Ekoi8u::not_word};
497             ${Char::Ekoi8u::not_xdigit} = ${Char::Ekoi8u::not_xdigit};
498             ${Char::Ekoi8u::eb} = ${Char::Ekoi8u::eb};
499             ${Char::Ekoi8u::eB} = ${Char::Ekoi8u::eB};
500              
501             #
502             # KOI8-U split
503             #
504             sub Char::Ekoi8u::split(;$$$) {
505              
506             # P.794 29.2.161. split
507             # in Chapter 29: Functions
508             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
509              
510             # P.951 split
511             # in Chapter 27: Functions
512             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
513              
514 0     0 0 0 my $pattern = $_[0];
515 0         0 my $string = $_[1];
516 0         0 my $limit = $_[2];
517              
518             # if $pattern is also omitted or is the literal space, " "
519 0 0       0 if (not defined $pattern) {
520 0         0 $pattern = ' ';
521             }
522              
523             # if $string is omitted, the function splits the $_ string
524 0 0       0 if (not defined $string) {
525 0 0       0 if (defined $_) {
526 0         0 $string = $_;
527             }
528             else {
529 0         0 $string = '';
530             }
531             }
532              
533 0         0 my @split = ();
534              
535             # when string is empty
536 0 0       0 if ($string eq '') {
    0          
537              
538             # resulting list value in list context
539 0 0       0 if (wantarray) {
540 0         0 return @split;
541             }
542              
543             # count of substrings in scalar context
544             else {
545 0 0       0 carp "Use of implicit split to \@_ is deprecated" if $^W;
546 0         0 @_ = @split;
547 0         0 return scalar @_;
548             }
549             }
550              
551             # split's first argument is more consistently interpreted
552             #
553             # After some changes earlier in v5.17, split's behavior has been simplified:
554             # if the PATTERN argument evaluates to a string containing one space, it is
555             # treated the way that a literal string containing one space once was.
556             # http://search.cpan.org/dist/perl-5.18.0/pod/perldelta.pod#split's_first_argument_is_more_consistently_interpreted
557              
558             # if $pattern is also omitted or is the literal space, " ", the function splits
559             # on whitespace, /\s+/, after skipping any leading whitespace
560             # (and so on)
561              
562             elsif ($pattern eq ' ') {
563 0 0       0 if (not defined $limit) {
564 0         0 return CORE::split(' ', $string);
565             }
566             else {
567 0         0 return CORE::split(' ', $string, $limit);
568             }
569             }
570              
571             # if $limit is negative, it is treated as if an arbitrarily large $limit has been specified
572 0 0 0     0 if ((not defined $limit) or ($limit <= 0)) {
    0          
573              
574             # a pattern capable of matching either the null string or something longer than the
575             # null string will split the value of $string into separate characters wherever it
576             # matches the null string between characters
577             # (and so on)
578              
579 0 0       0 if ('' =~ / \A $pattern \z /xms) {
580 0         0 my $last_subexpression_offsets = _last_subexpression_offsets($pattern);
581 0         0 my $limit = scalar(() = $string =~ /($pattern)/oxmsg);
582              
583             # P.1024 Appendix W.10 Multibyte Processing
584             # of ISBN 1-56592-224-7 CJKV Information Processing
585             # (and so on)
586              
587             # the //m modifier is assumed when you split on the pattern /^/
588             # (and so on)
589              
590             # V
591 0   0     0 while ((--$limit > 0) and ($string =~ s/\A((?:$q_char)+?)$pattern//m)) {
592              
593             # if the $pattern contains parentheses, then the substring matched by each pair of parentheses
594             # is included in the resulting list, interspersed with the fields that are ordinarily returned
595             # (and so on)
596              
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             else {
605 0         0 my $last_subexpression_offsets = _last_subexpression_offsets($pattern);
606              
607             # V
608 0         0 while ($string =~ s/\A((?:$q_char)*?)$pattern//m) {
609 0         0 local $@;
610 0         0 for (my $digit=1; $digit <= ($last_subexpression_offsets + 1); $digit++) {
611 0         0 push @split, CORE::eval('$' . $digit);
612             }
613             }
614             }
615             }
616              
617             elsif ($limit > 0) {
618 0 0       0 if ('' =~ / \A $pattern \z /xms) {
619 0         0 my $last_subexpression_offsets = _last_subexpression_offsets($pattern);
620 0   0     0 while ((--$limit > 0) and (CORE::length($string) > 0)) {
621              
622             # V
623 0 0       0 if ($string =~ s/\A((?:$q_char)+?)$pattern//m) {
624 0         0 local $@;
625 0         0 for (my $digit=1; $digit <= ($last_subexpression_offsets + 1); $digit++) {
626 0         0 push @split, CORE::eval('$' . $digit);
627             }
628             }
629             }
630             }
631             else {
632 0         0 my $last_subexpression_offsets = _last_subexpression_offsets($pattern);
633 0   0     0 while ((--$limit > 0) and (CORE::length($string) > 0)) {
634              
635             # V
636 0 0       0 if ($string =~ s/\A((?:$q_char)*?)$pattern//m) {
637 0         0 local $@;
638 0         0 for (my $digit=1; $digit <= ($last_subexpression_offsets + 1); $digit++) {
639 0         0 push @split, CORE::eval('$' . $digit);
640             }
641             }
642             }
643             }
644             }
645              
646 0 0       0 if (CORE::length($string) > 0) {
647 0         0 push @split, $string;
648             }
649              
650             # if $_[2] (NOT "$limit") is omitted or zero, trailing null fields are stripped from the result
651 0 0 0     0 if ((not defined $_[2]) or ($_[2] == 0)) {
652 0   0     0 while ((scalar(@split) >= 1) and ($split[-1] eq '')) {
653 0         0 pop @split;
654             }
655             }
656              
657             # resulting list value in list context
658 0 0       0 if (wantarray) {
659 0         0 return @split;
660             }
661              
662             # count of substrings in scalar context
663             else {
664 0 0       0 carp "Use of implicit split to \@_ is deprecated" if $^W;
665 0         0 @_ = @split;
666 0         0 return scalar @_;
667             }
668             }
669              
670             #
671             # get last subexpression offsets
672             #
673             sub _last_subexpression_offsets {
674 0     0   0 my $pattern = $_[0];
675              
676             # remove comment
677 0         0 $pattern =~ s/\(\?\# .*? \)//oxmsg;
678              
679 0         0 my $modifier = '';
680 0 0       0 if ($pattern =~ /\(\?\^? ([\-A-Za-z]+) :/oxms) {
681 0         0 $modifier = $1;
682 0         0 $modifier =~ s/-[A-Za-z]*//;
683             }
684              
685             # with /x modifier
686 0         0 my @char = ();
687 0 0       0 if ($modifier =~ /x/oxms) {
688 0         0 @char = $pattern =~ /\G(
689             \\ (?:$q_char) |
690             \# (?:$q_char)*? $ |
691             \[ (?: \\\] | (?:$q_char))+? \] |
692             \(\? |
693             (?:$q_char)
694             )/oxmsg;
695             }
696              
697             # without /x modifier
698             else {
699 0         0 @char = $pattern =~ /\G(
700             \\ (?:$q_char) |
701             \[ (?: \\\] | (?:$q_char))+? \] |
702             \(\? |
703             (?:$q_char)
704             )/oxmsg;
705             }
706              
707 0         0 return scalar grep { $_ eq '(' } @char;
  0         0  
708             }
709              
710             #
711             # KOI8-U transliteration (tr///)
712             #
713             sub Char::Ekoi8u::tr($$$$;$) {
714              
715 0     0 0 0 my $bind_operator = $_[1];
716 0         0 my $searchlist = $_[2];
717 0         0 my $replacementlist = $_[3];
718 0   0     0 my $modifier = $_[4] || '';
719              
720 0 0       0 if ($modifier =~ /r/oxms) {
721 0 0       0 if ($bind_operator =~ / !~ /oxms) {
722 0         0 croak "Using !~ with tr///r doesn't make sense";
723             }
724             }
725              
726 0         0 my @char = $_[0] =~ /\G ($q_char) /oxmsg;
727 0         0 my @searchlist = _charlist_tr($searchlist);
728 0         0 my @replacementlist = _charlist_tr($replacementlist);
729              
730 0         0 my %tr = ();
731 0         0 for (my $i=0; $i <= $#searchlist; $i++) {
732 0 0       0 if (not exists $tr{$searchlist[$i]}) {
733 0 0 0     0 if (defined $replacementlist[$i] and ($replacementlist[$i] ne '')) {
    0 0        
    0          
734 0         0 $tr{$searchlist[$i]} = $replacementlist[$i];
735             }
736             elsif ($modifier =~ /d/oxms) {
737 0         0 $tr{$searchlist[$i]} = '';
738             }
739             elsif (defined $replacementlist[-1] and ($replacementlist[-1] ne '')) {
740 0         0 $tr{$searchlist[$i]} = $replacementlist[-1];
741             }
742             else {
743 0         0 $tr{$searchlist[$i]} = $searchlist[$i];
744             }
745             }
746             }
747              
748 0         0 my $tr = 0;
749 0         0 my $replaced = '';
750 0 0       0 if ($modifier =~ /c/oxms) {
751 0         0 while (defined(my $char = shift @char)) {
752 0 0       0 if (not exists $tr{$char}) {
753 0 0       0 if (defined $replacementlist[0]) {
754 0         0 $replaced .= $replacementlist[0];
755             }
756 0         0 $tr++;
757 0 0       0 if ($modifier =~ /s/oxms) {
758 0   0     0 while (@char and (not exists $tr{$char[0]})) {
759 0         0 shift @char;
760 0         0 $tr++;
761             }
762             }
763             }
764             else {
765 0         0 $replaced .= $char;
766             }
767             }
768             }
769             else {
770 0         0 while (defined(my $char = shift @char)) {
771 0 0       0 if (exists $tr{$char}) {
772 0         0 $replaced .= $tr{$char};
773 0         0 $tr++;
774 0 0       0 if ($modifier =~ /s/oxms) {
775 0   0     0 while (@char and (exists $tr{$char[0]}) and ($tr{$char[0]} eq $tr{$char})) {
      0        
776 0         0 shift @char;
777 0         0 $tr++;
778             }
779             }
780             }
781             else {
782 0         0 $replaced .= $char;
783             }
784             }
785             }
786              
787 0 0       0 if ($modifier =~ /r/oxms) {
788 0         0 return $replaced;
789             }
790             else {
791 0         0 $_[0] = $replaced;
792 0 0       0 if ($bind_operator =~ / !~ /oxms) {
793 0         0 return not $tr;
794             }
795             else {
796 0         0 return $tr;
797             }
798             }
799             }
800              
801             #
802             # KOI8-U chop
803             #
804             sub Char::Ekoi8u::chop(@) {
805              
806 0     0 0 0 my $chop;
807 0 0       0 if (@_ == 0) {
808 0         0 my @char = /\G ($q_char) /oxmsg;
809 0         0 $chop = pop @char;
810 0         0 $_ = join '', @char;
811             }
812             else {
813 0         0 for (@_) {
814 0         0 my @char = /\G ($q_char) /oxmsg;
815 0         0 $chop = pop @char;
816 0         0 $_ = join '', @char;
817             }
818             }
819 0         0 return $chop;
820             }
821              
822             #
823             # KOI8-U index by octet
824             #
825             sub Char::Ekoi8u::index($$;$) {
826              
827 0     0 1 0 my($str,$substr,$position) = @_;
828 0   0     0 $position ||= 0;
829 0         0 my $pos = 0;
830              
831 0         0 while ($pos < CORE::length($str)) {
832 0 0       0 if (CORE::substr($str,$pos,CORE::length($substr)) eq $substr) {
833 0 0       0 if ($pos >= $position) {
834 0         0 return $pos;
835             }
836             }
837 0 0       0 if (CORE::substr($str,$pos) =~ /\A ($q_char) /oxms) {
838 0         0 $pos += CORE::length($1);
839             }
840             else {
841 0         0 $pos += 1;
842             }
843             }
844 0         0 return -1;
845             }
846              
847             #
848             # KOI8-U reverse index
849             #
850             sub Char::Ekoi8u::rindex($$;$) {
851              
852 0     0 0 0 my($str,$substr,$position) = @_;
853 0   0     0 $position ||= CORE::length($str) - 1;
854 0         0 my $pos = 0;
855 0         0 my $rindex = -1;
856              
857 0   0     0 while (($pos < CORE::length($str)) and ($pos <= $position)) {
858 0 0       0 if (CORE::substr($str,$pos,CORE::length($substr)) eq $substr) {
859 0         0 $rindex = $pos;
860             }
861 0 0       0 if (CORE::substr($str,$pos) =~ /\A ($q_char) /oxms) {
862 0         0 $pos += CORE::length($1);
863             }
864             else {
865 0         0 $pos += 1;
866             }
867             }
868 0         0 return $rindex;
869             }
870              
871             #
872             # KOI8-U lower case first with parameter
873             #
874             sub Char::Ekoi8u::lcfirst(@) {
875 0 0   0 0 0 if (@_) {
876 0         0 my $s = shift @_;
877 0 0 0     0 if (@_ and wantarray) {
878 0         0 return Char::Ekoi8u::lc(CORE::substr($s,0,1)) . CORE::substr($s,1), @_;
879             }
880             else {
881 0         0 return Char::Ekoi8u::lc(CORE::substr($s,0,1)) . CORE::substr($s,1);
882             }
883             }
884             else {
885 0         0 return Char::Ekoi8u::lc(CORE::substr($_,0,1)) . CORE::substr($_,1);
886             }
887             }
888              
889             #
890             # KOI8-U lower case first without parameter
891             #
892             sub Char::Ekoi8u::lcfirst_() {
893 0     0 0 0 return Char::Ekoi8u::lc(CORE::substr($_,0,1)) . CORE::substr($_,1);
894             }
895              
896             #
897             # KOI8-U lower case with parameter
898             #
899             sub Char::Ekoi8u::lc(@) {
900 0 0   0 0 0 if (@_) {
901 0         0 my $s = shift @_;
902 0 0 0     0 if (@_ and wantarray) {
903 0 0       0 return join('', map {defined($lc{$_}) ? $lc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg)), @_;
  0         0  
904             }
905             else {
906 0 0       0 return join('', map {defined($lc{$_}) ? $lc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg));
  0         0  
907             }
908             }
909             else {
910 0         0 return Char::Ekoi8u::lc_();
911             }
912             }
913              
914             #
915             # KOI8-U lower case without parameter
916             #
917             sub Char::Ekoi8u::lc_() {
918 0     0 0 0 my $s = $_;
919 0 0       0 return join '', map {defined($lc{$_}) ? $lc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg);
  0         0  
920             }
921              
922             #
923             # KOI8-U upper case first with parameter
924             #
925             sub Char::Ekoi8u::ucfirst(@) {
926 0 0   0 0 0 if (@_) {
927 0         0 my $s = shift @_;
928 0 0 0     0 if (@_ and wantarray) {
929 0         0 return Char::Ekoi8u::uc(CORE::substr($s,0,1)) . CORE::substr($s,1), @_;
930             }
931             else {
932 0         0 return Char::Ekoi8u::uc(CORE::substr($s,0,1)) . CORE::substr($s,1);
933             }
934             }
935             else {
936 0         0 return Char::Ekoi8u::uc(CORE::substr($_,0,1)) . CORE::substr($_,1);
937             }
938             }
939              
940             #
941             # KOI8-U upper case first without parameter
942             #
943             sub Char::Ekoi8u::ucfirst_() {
944 0     0 0 0 return Char::Ekoi8u::uc(CORE::substr($_,0,1)) . CORE::substr($_,1);
945             }
946              
947             #
948             # KOI8-U upper case with parameter
949             #
950             sub Char::Ekoi8u::uc(@) {
951 0 0   0 0 0 if (@_) {
952 0         0 my $s = shift @_;
953 0 0 0     0 if (@_ and wantarray) {
954 0 0       0 return join('', map {defined($uc{$_}) ? $uc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg)), @_;
  0         0  
955             }
956             else {
957 0 0       0 return join('', map {defined($uc{$_}) ? $uc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg));
  0         0  
958             }
959             }
960             else {
961 0         0 return Char::Ekoi8u::uc_();
962             }
963             }
964              
965             #
966             # KOI8-U upper case without parameter
967             #
968             sub Char::Ekoi8u::uc_() {
969 0     0 0 0 my $s = $_;
970 0 0       0 return join '', map {defined($uc{$_}) ? $uc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg);
  0         0  
971             }
972              
973             #
974             # KOI8-U fold case with parameter
975             #
976             sub Char::Ekoi8u::fc(@) {
977 0 0   0 0 0 if (@_) {
978 0         0 my $s = shift @_;
979 0 0 0     0 if (@_ and wantarray) {
980 0 0       0 return join('', map {defined($fc{$_}) ? $fc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg)), @_;
  0         0  
981             }
982             else {
983 0 0       0 return join('', map {defined($fc{$_}) ? $fc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg));
  0         0  
984             }
985             }
986             else {
987 0         0 return Char::Ekoi8u::fc_();
988             }
989             }
990              
991             #
992             # KOI8-U fold case without parameter
993             #
994             sub Char::Ekoi8u::fc_() {
995 0     0 0 0 my $s = $_;
996 0 0       0 return join '', map {defined($fc{$_}) ? $fc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg);
  0         0  
997             }
998              
999             #
1000             # KOI8-U regexp capture
1001             #
1002             {
1003             sub Char::Ekoi8u::capture {
1004 0     0 1 0 return $_[0];
1005             }
1006             }
1007              
1008             #
1009             # KOI8-U regexp ignore case modifier
1010             #
1011             sub Char::Ekoi8u::ignorecase {
1012              
1013 0     0 0 0 my @string = @_;
1014 0         0 my $metachar = qr/[\@\\|[\]{]/oxms;
1015              
1016             # ignore case of $scalar or @array
1017 0         0 for my $string (@string) {
1018              
1019             # split regexp
1020 0         0 my @char = $string =~ /\G(
1021             \[\^ |
1022             \\? (?:$q_char)
1023             )/oxmsg;
1024              
1025             # unescape character
1026 0         0 for (my $i=0; $i <= $#char; $i++) {
1027 0 0       0 next if not defined $char[$i];
1028              
1029             # open character class [...]
1030 0 0       0 if ($char[$i] eq '[') {
    0          
    0          
    0          
1031 0         0 my $left = $i;
1032              
1033             # [] make die "unmatched [] in regexp ..."
1034              
1035 0 0       0 if ($char[$i+1] eq ']') {
1036 0         0 $i++;
1037             }
1038              
1039 0         0 while (1) {
1040 0 0       0 if (++$i > $#char) {
1041 0         0 croak "Unmatched [] in regexp";
1042             }
1043 0 0       0 if ($char[$i] eq ']') {
1044 0         0 my $right = $i;
1045 0         0 my @charlist = charlist_qr(@char[$left+1..$right-1], 'i');
1046              
1047             # escape character
1048 0         0 for my $char (@charlist) {
1049 0 0       0 if (0) {
1050             }
1051              
1052 0         0 elsif ($char =~ /\A [.|)] \z/oxms) {
1053 0         0 $char = $1 . '\\' . $char;
1054             }
1055             }
1056              
1057             # [...]
1058 0         0 splice @char, $left, $right-$left+1, '(?:' . join('|', @charlist) . ')';
1059              
1060 0         0 $i = $left;
1061 0         0 last;
1062             }
1063             }
1064             }
1065              
1066             # open character class [^...]
1067             elsif ($char[$i] eq '[^') {
1068 0         0 my $left = $i;
1069              
1070             # [^] make die "unmatched [] in regexp ..."
1071              
1072 0 0       0 if ($char[$i+1] eq ']') {
1073 0         0 $i++;
1074             }
1075              
1076 0         0 while (1) {
1077 0 0       0 if (++$i > $#char) {
1078 0         0 croak "Unmatched [] in regexp";
1079             }
1080 0 0       0 if ($char[$i] eq ']') {
1081 0         0 my $right = $i;
1082 0         0 my @charlist = charlist_not_qr(@char[$left+1..$right-1], 'i');
1083              
1084             # escape character
1085 0         0 for my $char (@charlist) {
1086 0 0       0 if (0) {
1087             }
1088              
1089 0         0 elsif ($char =~ /\A [.|)] \z/oxms) {
1090 0         0 $char = '\\' . $char;
1091             }
1092             }
1093              
1094             # [^...]
1095 0         0 splice @char, $left, $right-$left+1, '(?!' . join('|', @charlist) . ")(?:$your_char)";
1096              
1097 0         0 $i = $left;
1098 0         0 last;
1099             }
1100             }
1101             }
1102              
1103             # rewrite classic character class or escape character
1104             elsif (my $char = classic_character_class($char[$i])) {
1105 0         0 $char[$i] = $char;
1106             }
1107              
1108             # with /i modifier
1109             elsif ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) {
1110 0         0 my $uc = Char::Ekoi8u::uc($char[$i]);
1111 0         0 my $fc = Char::Ekoi8u::fc($char[$i]);
1112 0 0       0 if ($uc ne $fc) {
1113 0 0       0 if (CORE::length($fc) == 1) {
1114 0         0 $char[$i] = '[' . $uc . $fc . ']';
1115             }
1116             else {
1117 0         0 $char[$i] = '(?:' . $uc . '|' . $fc . ')';
1118             }
1119             }
1120             }
1121             }
1122              
1123             # characterize
1124 0         0 for (my $i=0; $i <= $#char; $i++) {
1125 0 0       0 next if not defined $char[$i];
1126              
1127 0 0       0 if (0) {
1128             }
1129              
1130             # quote character before ? + * {
1131 0 0       0 elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
1132 0 0       0 if ($char[$i-1] !~ /\A [\x00-\xFF] \z/oxms) {
1133 0         0 $char[$i-1] = '(?:' . $char[$i-1] . ')';
1134             }
1135             }
1136             }
1137              
1138 0         0 $string = join '', @char;
1139             }
1140              
1141             # make regexp string
1142 0         0 return @string;
1143             }
1144              
1145             #
1146             # classic character class ( \D \S \W \d \s \w \C \X \H \V \h \v \R \N \b \B )
1147             #
1148             sub Char::Ekoi8u::classic_character_class {
1149 0     0 0 0 my($char) = @_;
1150              
1151             return {
1152 0   0     0 '\D' => '${Char::Ekoi8u::eD}',
1153             '\S' => '${Char::Ekoi8u::eS}',
1154             '\W' => '${Char::Ekoi8u::eW}',
1155             '\d' => '[0-9]',
1156              
1157             # Before Perl 5.6, \s only matched the five whitespace characters
1158             # tab, newline, form-feed, carriage return, and the space character
1159             # itself, which, taken together, is the character class [\t\n\f\r ].
1160              
1161             # Vertical tabs are now whitespace
1162             # \s in a regex now matches a vertical tab in all circumstances.
1163             # http://search.cpan.org/dist/perl-5.18.0/pod/perldelta.pod#Vertical_tabs_are_now_whitespace
1164             # \t \n \v \f \r space
1165             # '\s' => '[\x09\x0A \x0C\x0D\x20]',
1166             # '\s' => '[\x09\x0A\x0B\x0C\x0D\x20]',
1167             '\s' => '\s',
1168              
1169             '\w' => '[0-9A-Z_a-z]',
1170             '\C' => '[\x00-\xFF]',
1171             '\X' => 'X',
1172              
1173             # \h \v \H \V
1174              
1175             # P.114 Character Class Shortcuts
1176             # in Chapter 7: In the World of Regular Expressions
1177             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
1178              
1179             # P.357 13.2.3 Whitespace
1180             # in Chapter 13: perlrecharclass: Perl Regular Expression Character Classes
1181             # of ISBN-13: 978-1-906966-02-7 The Perl Language Reference Manual (for Perl version 5.12.1)
1182             #
1183             # 0x00009 CHARACTER TABULATION h s
1184             # 0x0000a LINE FEED (LF) vs
1185             # 0x0000b LINE TABULATION v
1186             # 0x0000c FORM FEED (FF) vs
1187             # 0x0000d CARRIAGE RETURN (CR) vs
1188             # 0x00020 SPACE h s
1189              
1190             # P.196 Table 5-9. Alphanumeric regex metasymbols
1191             # in Chapter 5. Pattern Matching
1192             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
1193              
1194             # (and so on)
1195              
1196             '\H' => '${Char::Ekoi8u::eH}',
1197             '\V' => '${Char::Ekoi8u::eV}',
1198             '\h' => '[\x09\x20]',
1199             '\v' => '[\x0A\x0B\x0C\x0D]',
1200             '\R' => '${Char::Ekoi8u::eR}',
1201              
1202             # \N
1203             #
1204             # http://perldoc.perl.org/perlre.html
1205             # Character Classes and other Special Escapes
1206             # Any character but \n (experimental). Not affected by /s modifier
1207              
1208             '\N' => '${Char::Ekoi8u::eN}',
1209              
1210             # \b \B
1211              
1212             # P.180 Boundaries: The \b and \B Assertions
1213             # in Chapter 5: Pattern Matching
1214             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
1215              
1216             # P.219 Boundaries: The \b and \B Assertions
1217             # in Chapter 5: Pattern Matching
1218             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
1219              
1220             # '\b' => '(?:(?<=\A|\W)(?=\w)|(?<=\w)(?=\W|\z))',
1221             '\b' => '${Char::Ekoi8u::eb}',
1222              
1223             # '\B' => '(?:(?<=\w)(?=\w)|(?<=\W)(?=\W))',
1224             '\B' => '${Char::Ekoi8u::eB}',
1225              
1226             }->{$char} || '';
1227             }
1228              
1229             #
1230             # prepare KOI8-U characters per length
1231             #
1232              
1233             # 1 octet characters
1234             my @chars1 = ();
1235             sub chars1 {
1236 0 0   0 0 0 if (@chars1) {
1237 0         0 return @chars1;
1238             }
1239 0 0       0 if (exists $range_tr{1}) {
1240 0         0 my @ranges = @{ $range_tr{1} };
  0         0  
1241 0         0 while (my @range = splice(@ranges,0,1)) {
1242 0         0 for my $oct0 (@{$range[0]}) {
  0         0  
1243 0         0 push @chars1, pack 'C', $oct0;
1244             }
1245             }
1246             }
1247 0         0 return @chars1;
1248             }
1249              
1250             # 2 octets characters
1251             my @chars2 = ();
1252             sub chars2 {
1253 0 0   0 0 0 if (@chars2) {
1254 0         0 return @chars2;
1255             }
1256 0 0       0 if (exists $range_tr{2}) {
1257 0         0 my @ranges = @{ $range_tr{2} };
  0         0  
1258 0         0 while (my @range = splice(@ranges,0,2)) {
1259 0         0 for my $oct0 (@{$range[0]}) {
  0         0  
1260 0         0 for my $oct1 (@{$range[1]}) {
  0         0  
1261 0         0 push @chars2, pack 'CC', $oct0,$oct1;
1262             }
1263             }
1264             }
1265             }
1266 0         0 return @chars2;
1267             }
1268              
1269             # 3 octets characters
1270             my @chars3 = ();
1271             sub chars3 {
1272 0 0   0 0 0 if (@chars3) {
1273 0         0 return @chars3;
1274             }
1275 0 0       0 if (exists $range_tr{3}) {
1276 0         0 my @ranges = @{ $range_tr{3} };
  0         0  
1277 0         0 while (my @range = splice(@ranges,0,3)) {
1278 0         0 for my $oct0 (@{$range[0]}) {
  0         0  
1279 0         0 for my $oct1 (@{$range[1]}) {
  0         0  
1280 0         0 for my $oct2 (@{$range[2]}) {
  0         0  
1281 0         0 push @chars3, pack 'CCC', $oct0,$oct1,$oct2;
1282             }
1283             }
1284             }
1285             }
1286             }
1287 0         0 return @chars3;
1288             }
1289              
1290             # 4 octets characters
1291             my @chars4 = ();
1292             sub chars4 {
1293 0 0   0 0 0 if (@chars4) {
1294 0         0 return @chars4;
1295             }
1296 0 0       0 if (exists $range_tr{4}) {
1297 0         0 my @ranges = @{ $range_tr{4} };
  0         0  
1298 0         0 while (my @range = splice(@ranges,0,4)) {
1299 0         0 for my $oct0 (@{$range[0]}) {
  0         0  
1300 0         0 for my $oct1 (@{$range[1]}) {
  0         0  
1301 0         0 for my $oct2 (@{$range[2]}) {
  0         0  
1302 0         0 for my $oct3 (@{$range[3]}) {
  0         0  
1303 0         0 push @chars4, pack 'CCCC', $oct0,$oct1,$oct2,$oct3;
1304             }
1305             }
1306             }
1307             }
1308             }
1309             }
1310 0         0 return @chars4;
1311             }
1312              
1313             #
1314             # KOI8-U open character list for tr
1315             #
1316             sub _charlist_tr {
1317              
1318 0     0   0 local $_ = shift @_;
1319              
1320             # unescape character
1321 0         0 my @char = ();
1322 0         0 while (not /\G \z/oxmsgc) {
1323 0 0       0 if (/\G (\\0?55|\\x2[Dd]|\\-) /oxmsgc) {
    0          
    0          
    0          
    0          
    0          
    0          
1324 0         0 push @char, '\-';
1325             }
1326             elsif (/\G \\ ([0-7]{2,3}) /oxmsgc) {
1327 0         0 push @char, CORE::chr(oct $1);
1328             }
1329             elsif (/\G \\x ([0-9A-Fa-f]{1,2}) /oxmsgc) {
1330 0         0 push @char, CORE::chr(hex $1);
1331             }
1332             elsif (/\G \\c ([\x40-\x5F]) /oxmsgc) {
1333 0         0 push @char, CORE::chr(CORE::ord($1) & 0x1F);
1334             }
1335             elsif (/\G (\\ [0nrtfbae]) /oxmsgc) {
1336 0         0 push @char, {
1337             '\0' => "\0",
1338             '\n' => "\n",
1339             '\r' => "\r",
1340             '\t' => "\t",
1341             '\f' => "\f",
1342             '\b' => "\x08", # \b means backspace in character class
1343             '\a' => "\a",
1344             '\e' => "\e",
1345             }->{$1};
1346             }
1347             elsif (/\G \\ ($q_char) /oxmsgc) {
1348 0         0 push @char, $1;
1349             }
1350             elsif (/\G ($q_char) /oxmsgc) {
1351 0         0 push @char, $1;
1352             }
1353             }
1354              
1355             # join separated multiple-octet
1356 0         0 @char = join('',@char) =~ /\G (\\-|$q_char) /oxmsg;
1357              
1358             # unescape '-'
1359 0         0 my @i = ();
1360 0         0 for my $i (0 .. $#char) {
1361 0 0       0 if ($char[$i] eq '\-') {
    0          
1362 0         0 $char[$i] = '-';
1363             }
1364             elsif ($char[$i] eq '-') {
1365 0 0 0     0 if ((0 < $i) and ($i < $#char)) {
1366 0         0 push @i, $i;
1367             }
1368             }
1369             }
1370              
1371             # open character list (reverse for splice)
1372 0         0 for my $i (CORE::reverse @i) {
1373 0         0 my @range = ();
1374              
1375             # range error
1376 0 0 0     0 if ((CORE::length($char[$i-1]) > CORE::length($char[$i+1])) or ($char[$i-1] gt $char[$i+1])) {
1377 0         0 croak "Invalid tr/// range \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1378             }
1379              
1380             # range of multiple-octet code
1381 0 0       0 if (CORE::length($char[$i-1]) == 1) {
    0          
    0          
    0          
1382 0 0       0 if (CORE::length($char[$i+1]) == 1) {
    0          
    0          
    0          
1383 0 0       0 push @range, grep {($char[$i-1] le $_) and ($_ le $char[$i+1])} chars1();
  0         0  
1384             }
1385             elsif (CORE::length($char[$i+1]) == 2) {
1386 0         0 push @range, grep {$char[$i-1] le $_} chars1();
  0         0  
1387 0         0 push @range, grep {$_ le $char[$i+1]} chars2();
  0         0  
1388             }
1389             elsif (CORE::length($char[$i+1]) == 3) {
1390 0         0 push @range, grep {$char[$i-1] le $_} chars1();
  0         0  
1391 0         0 push @range, chars2();
1392 0         0 push @range, grep {$_ le $char[$i+1]} chars3();
  0         0  
1393             }
1394             elsif (CORE::length($char[$i+1]) == 4) {
1395 0         0 push @range, grep {$char[$i-1] le $_} chars1();
  0         0  
1396 0         0 push @range, chars2();
1397 0         0 push @range, chars3();
1398 0         0 push @range, grep {$_ le $char[$i+1]} chars4();
  0         0  
1399             }
1400             else {
1401 0         0 croak "Invalid tr/// range (over 4octets) \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1402             }
1403             }
1404             elsif (CORE::length($char[$i-1]) == 2) {
1405 0 0       0 if (CORE::length($char[$i+1]) == 2) {
    0          
    0          
1406 0 0       0 push @range, grep {($char[$i-1] le $_) and ($_ le $char[$i+1])} chars2();
  0         0  
1407             }
1408             elsif (CORE::length($char[$i+1]) == 3) {
1409 0         0 push @range, grep {$char[$i-1] le $_} chars2();
  0         0  
1410 0         0 push @range, grep {$_ le $char[$i+1]} chars3();
  0         0  
1411             }
1412             elsif (CORE::length($char[$i+1]) == 4) {
1413 0         0 push @range, grep {$char[$i-1] le $_} chars2();
  0         0  
1414 0         0 push @range, chars3();
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]) == 3) {
1422 0 0       0 if (CORE::length($char[$i+1]) == 3) {
    0          
1423 0 0       0 push @range, grep {($char[$i-1] le $_) and ($_ le $char[$i+1])} chars3();
  0         0  
1424             }
1425             elsif (CORE::length($char[$i+1]) == 4) {
1426 0         0 push @range, grep {$char[$i-1] le $_} chars3();
  0         0  
1427 0         0 push @range, grep {$_ le $char[$i+1]} chars4();
  0         0  
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             elsif (CORE::length($char[$i-1]) == 4) {
1434 0 0       0 if (CORE::length($char[$i+1]) == 4) {
1435 0 0       0 push @range, grep {($char[$i-1] le $_) and ($_ le $char[$i+1])} chars4();
  0         0  
1436             }
1437             else {
1438 0         0 croak "Invalid tr/// range (over 4octets) \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1439             }
1440             }
1441             else {
1442 0         0 croak "Invalid tr/// range (over 4octets) \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1443             }
1444              
1445 0         0 splice @char, $i-1, 3, @range;
1446             }
1447              
1448 0         0 return @char;
1449             }
1450              
1451             #
1452             # KOI8-U open character class
1453             #
1454             sub _cc {
1455 0 0   0   0 if (scalar(@_) == 0) {
    0          
    0          
1456 0         0 die __FILE__, ": subroutine cc got no parameter.";
1457             }
1458             elsif (scalar(@_) == 1) {
1459 0         0 return sprintf('\x%02X',$_[0]);
1460             }
1461             elsif (scalar(@_) == 2) {
1462 0 0       0 if ($_[0] > $_[1]) {
    0          
    0          
1463 0         0 die __FILE__, ": subroutine cc got \$_[0] > \$_[1] parameters).";
1464             }
1465             elsif ($_[0] == $_[1]) {
1466 0         0 return sprintf('\x%02X',$_[0]);
1467             }
1468             elsif (($_[0]+1) == $_[1]) {
1469 0         0 return sprintf('[\\x%02X\\x%02X]',$_[0],$_[1]);
1470             }
1471             else {
1472 0         0 return sprintf('[\\x%02X-\\x%02X]',$_[0],$_[1]);
1473             }
1474             }
1475             else {
1476 0         0 die __FILE__, ": subroutine cc got 3 or more parameters (@{[scalar(@_)]} parameters).";
  0         0  
1477             }
1478             }
1479              
1480             #
1481             # KOI8-U octet range
1482             #
1483             sub _octets {
1484 0     0   0 my $length = shift @_;
1485              
1486 0 0       0 if ($length == 1) {
1487 0         0 my($a1) = unpack 'C', $_[0];
1488 0         0 my($z1) = unpack 'C', $_[1];
1489              
1490 0 0       0 if ($a1 > $z1) {
1491 0         0 croak 'Invalid [] range in regexp (CORE::ord(A) > CORE::ord(B)) ' . '\x' . unpack('H*',$a1) . '-\x' . unpack('H*',$z1);
1492             }
1493              
1494 0 0       0 if ($a1 == $z1) {
    0          
1495 0         0 return sprintf('\x%02X',$a1);
1496             }
1497             elsif (($a1+1) == $z1) {
1498 0         0 return sprintf('\x%02X\x%02X',$a1,$z1);
1499             }
1500             else {
1501 0         0 return sprintf('\x%02X-\x%02X',$a1,$z1);
1502             }
1503             }
1504             else {
1505 0         0 die __FILE__, ": subroutine _octets got invalid length ($length).";
1506             }
1507             }
1508              
1509             #
1510             # KOI8-U range regexp
1511             #
1512             sub _range_regexp {
1513 0     0   0 my($length,$first,$last) = @_;
1514              
1515 0         0 my @range_regexp = ();
1516 0 0       0 if (not exists $range_tr{$length}) {
1517 0         0 return @range_regexp;
1518             }
1519              
1520 0         0 my @ranges = @{ $range_tr{$length} };
  0         0  
1521 0         0 while (my @range = splice(@ranges,0,$length)) {
1522 0         0 my $min = '';
1523 0         0 my $max = '';
1524 0         0 for (my $i=0; $i < $length; $i++) {
1525 0         0 $min .= pack 'C', $range[$i][0];
1526 0         0 $max .= pack 'C', $range[$i][-1];
1527             }
1528              
1529             # min___max
1530             # FIRST_____________LAST
1531             # (nothing)
1532              
1533 0 0 0     0 if ($max lt $first) {
    0 0        
    0 0        
    0 0        
    0 0        
    0 0        
    0 0        
1534             }
1535              
1536             # **********
1537             # min_________max
1538             # FIRST_____________LAST
1539             # **********
1540              
1541             elsif (($min le $first) and ($first le $max) and ($max le $last)) {
1542 0         0 push @range_regexp, _octets($length,$first,$max,$min,$max);
1543             }
1544              
1545             # **********************
1546             # min________________max
1547             # FIRST_____________LAST
1548             # **********************
1549              
1550             elsif (($min eq $first) and ($max eq $last)) {
1551 0         0 push @range_regexp, _octets($length,$first,$last,$min,$max);
1552             }
1553              
1554             # *********
1555             # min___max
1556             # FIRST_____________LAST
1557             # *********
1558              
1559             elsif (($first le $min) and ($max le $last)) {
1560 0         0 push @range_regexp, _octets($length,$min,$max,$min,$max);
1561             }
1562              
1563             # **********************
1564             # min__________________________max
1565             # FIRST_____________LAST
1566             # **********************
1567              
1568             elsif (($min le $first) and ($last le $max)) {
1569 0         0 push @range_regexp, _octets($length,$first,$last,$min,$max);
1570             }
1571              
1572             # *********
1573             # min________max
1574             # FIRST_____________LAST
1575             # *********
1576              
1577             elsif (($first le $min) and ($min le $last) and ($last le $max)) {
1578 0         0 push @range_regexp, _octets($length,$min,$last,$min,$max);
1579             }
1580              
1581             # min___max
1582             # FIRST_____________LAST
1583             # (nothing)
1584              
1585             elsif ($last lt $min) {
1586             }
1587              
1588             else {
1589 0         0 die __FILE__, ": subroutine _range_regexp panic.";
1590             }
1591             }
1592              
1593 0         0 return @range_regexp;
1594             }
1595              
1596             #
1597             # KOI8-U open character list for qr and not qr
1598             #
1599             sub _charlist {
1600              
1601 0     0   0 my $modifier = pop @_;
1602 0         0 my @char = @_;
1603              
1604 0 0       0 my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
1605              
1606             # unescape character
1607 0         0 for (my $i=0; $i <= $#char; $i++) {
1608              
1609             # escape - to ...
1610 0 0 0     0 if ($char[$i] eq '-') {
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
1611 0 0 0     0 if ((0 < $i) and ($i < $#char)) {
1612 0         0 $char[$i] = '...';
1613             }
1614             }
1615              
1616             # octal escape sequence
1617             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
1618 0         0 $char[$i] = octchr($1);
1619             }
1620              
1621             # hexadecimal escape sequence
1622             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
1623 0         0 $char[$i] = hexchr($1);
1624             }
1625              
1626             # \N{CHARNAME} --> N\{CHARNAME}
1627             elsif ($char[$i] =~ /\A \\ (N) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
1628 0         0 $char[$i] = $1 . '\\' . $2;
1629             }
1630              
1631             # \p{PROPERTY} --> p\{PROPERTY}
1632             elsif ($char[$i] =~ /\A \\ (p) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
1633 0         0 $char[$i] = $1 . '\\' . $2;
1634             }
1635              
1636             # \P{PROPERTY} --> P\{PROPERTY}
1637             elsif ($char[$i] =~ /\A \\ (P) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
1638 0         0 $char[$i] = $1 . '\\' . $2;
1639             }
1640              
1641             # \p, \P, \X --> p, P, X
1642             elsif ($char[$i] =~ /\A \\ ( [pPX] ) \z/oxms) {
1643 0         0 $char[$i] = $1;
1644             }
1645              
1646             elsif ($char[$i] =~ /\A \\ ([0-7]{2,3}) \z/oxms) {
1647 0         0 $char[$i] = CORE::chr oct $1;
1648             }
1649             elsif ($char[$i] =~ /\A \\x ([0-9A-Fa-f]{1,2}) \z/oxms) {
1650 0         0 $char[$i] = CORE::chr hex $1;
1651             }
1652             elsif ($char[$i] =~ /\A \\c ([\x40-\x5F]) \z/oxms) {
1653 0         0 $char[$i] = CORE::chr(CORE::ord($1) & 0x1F);
1654             }
1655             elsif ($char[$i] =~ /\A (\\ [0nrtfbaedswDSWHVhvR]) \z/oxms) {
1656 0         0 $char[$i] = {
1657             '\0' => "\0",
1658             '\n' => "\n",
1659             '\r' => "\r",
1660             '\t' => "\t",
1661             '\f' => "\f",
1662             '\b' => "\x08", # \b means backspace in character class
1663             '\a' => "\a",
1664             '\e' => "\e",
1665             '\d' => '[0-9]',
1666              
1667             # Vertical tabs are now whitespace
1668             # \s in a regex now matches a vertical tab in all circumstances.
1669             # http://search.cpan.org/dist/perl-5.18.0/pod/perldelta.pod#Vertical_tabs_are_now_whitespace
1670             # \t \n \v \f \r space
1671             # '\s' => '[\x09\x0A \x0C\x0D\x20]',
1672             # '\s' => '[\x09\x0A\x0B\x0C\x0D\x20]',
1673             '\s' => '\s',
1674              
1675             '\w' => '[0-9A-Z_a-z]',
1676             '\D' => '${Char::Ekoi8u::eD}',
1677             '\S' => '${Char::Ekoi8u::eS}',
1678             '\W' => '${Char::Ekoi8u::eW}',
1679              
1680             '\H' => '${Char::Ekoi8u::eH}',
1681             '\V' => '${Char::Ekoi8u::eV}',
1682             '\h' => '[\x09\x20]',
1683             '\v' => '[\x0A\x0B\x0C\x0D]',
1684             '\R' => '${Char::Ekoi8u::eR}',
1685              
1686             }->{$1};
1687             }
1688              
1689             # POSIX-style character classes
1690             elsif ($ignorecase and ($char[$i] =~ /\A ( \[\: \^? (?:lower|upper) :\] ) \z/oxms)) {
1691 0         0 $char[$i] = {
1692              
1693             '[:lower:]' => '[\x41-\x5A\x61-\x7A]',
1694             '[:upper:]' => '[\x41-\x5A\x61-\x7A]',
1695             '[:^lower:]' => '${Char::Ekoi8u::not_lower_i}',
1696             '[:^upper:]' => '${Char::Ekoi8u::not_upper_i}',
1697              
1698             }->{$1};
1699             }
1700             elsif ($char[$i] =~ /\A ( \[\: \^? (?:alnum|alpha|ascii|blank|cntrl|digit|graph|lower|print|punct|space|upper|word|xdigit) :\] ) \z/oxms) {
1701 0         0 $char[$i] = {
1702              
1703             '[:alnum:]' => '[\x30-\x39\x41-\x5A\x61-\x7A]',
1704             '[:alpha:]' => '[\x41-\x5A\x61-\x7A]',
1705             '[:ascii:]' => '[\x00-\x7F]',
1706             '[:blank:]' => '[\x09\x20]',
1707             '[:cntrl:]' => '[\x00-\x1F\x7F]',
1708             '[:digit:]' => '[\x30-\x39]',
1709             '[:graph:]' => '[\x21-\x7F]',
1710             '[:lower:]' => '[\x61-\x7A]',
1711             '[:print:]' => '[\x20-\x7F]',
1712             '[:punct:]' => '[\x21-\x2F\x3A-\x3F\x40\x5B-\x5F\x60\x7B-\x7E]',
1713              
1714             # P.174 POSIX-Style Character Classes
1715             # in Chapter 5: Pattern Matching
1716             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
1717              
1718             # P.311 11.2.4 Character Classes and other Special Escapes
1719             # in Chapter 11: perlre: Perl regular expressions
1720             # of ISBN-13: 978-1-906966-02-7 The Perl Language Reference Manual (for Perl version 5.12.1)
1721              
1722             # P.210 POSIX-Style Character Classes
1723             # in Chapter 5: Pattern Matching
1724             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
1725              
1726             '[:space:]' => '[\s\x0B]', # "\s" plus vertical tab ("\cK")
1727              
1728             '[:upper:]' => '[\x41-\x5A]',
1729             '[:word:]' => '[\x30-\x39\x41-\x5A\x5F\x61-\x7A]',
1730             '[:xdigit:]' => '[\x30-\x39\x41-\x46\x61-\x66]',
1731             '[:^alnum:]' => '${Char::Ekoi8u::not_alnum}',
1732             '[:^alpha:]' => '${Char::Ekoi8u::not_alpha}',
1733             '[:^ascii:]' => '${Char::Ekoi8u::not_ascii}',
1734             '[:^blank:]' => '${Char::Ekoi8u::not_blank}',
1735             '[:^cntrl:]' => '${Char::Ekoi8u::not_cntrl}',
1736             '[:^digit:]' => '${Char::Ekoi8u::not_digit}',
1737             '[:^graph:]' => '${Char::Ekoi8u::not_graph}',
1738             '[:^lower:]' => '${Char::Ekoi8u::not_lower}',
1739             '[:^print:]' => '${Char::Ekoi8u::not_print}',
1740             '[:^punct:]' => '${Char::Ekoi8u::not_punct}',
1741             '[:^space:]' => '${Char::Ekoi8u::not_space}',
1742             '[:^upper:]' => '${Char::Ekoi8u::not_upper}',
1743             '[:^word:]' => '${Char::Ekoi8u::not_word}',
1744             '[:^xdigit:]' => '${Char::Ekoi8u::not_xdigit}',
1745              
1746             }->{$1};
1747             }
1748             elsif ($char[$i] =~ /\A \\ ($q_char) \z/oxms) {
1749 0         0 $char[$i] = $1;
1750             }
1751             }
1752              
1753             # open character list
1754 0         0 my @singleoctet = ();
1755 0         0 my @multipleoctet = ();
1756 0         0 for (my $i=0; $i <= $#char; ) {
1757              
1758             # escaped -
1759 0 0 0     0 if (defined($char[$i+1]) and ($char[$i+1] eq '...')) {
    0          
    0          
    0          
    0          
    0          
1760 0         0 $i += 1;
1761 0         0 next;
1762             }
1763              
1764             # make range regexp
1765             elsif ($char[$i] eq '...') {
1766              
1767             # range error
1768 0 0       0 if (CORE::length($char[$i-1]) > CORE::length($char[$i+1])) {
    0          
1769 0         0 croak 'Invalid [] range in regexp (length(A) > length(B)) ' . '\x' . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]);
1770             }
1771             elsif (CORE::length($char[$i-1]) == CORE::length($char[$i+1])) {
1772 0 0       0 if ($char[$i-1] gt $char[$i+1]) {
1773 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]);
1774             }
1775             }
1776              
1777             # make range regexp per length
1778 0         0 for my $length (CORE::length($char[$i-1]) .. CORE::length($char[$i+1])) {
1779 0         0 my @regexp = ();
1780              
1781             # is first and last
1782 0 0 0     0 if (($length == CORE::length($char[$i-1])) and ($length == CORE::length($char[$i+1]))) {
    0 0        
    0          
    0          
1783 0         0 push @regexp, _range_regexp($length, $char[$i-1], $char[$i+1]);
1784             }
1785              
1786             # is first
1787             elsif ($length == CORE::length($char[$i-1])) {
1788 0         0 push @regexp, _range_regexp($length, $char[$i-1], "\xFF" x $length);
1789             }
1790              
1791             # is inside in first and last
1792             elsif ((CORE::length($char[$i-1]) < $length) and ($length < CORE::length($char[$i+1]))) {
1793 0         0 push @regexp, _range_regexp($length, "\x00" x $length, "\xFF" x $length);
1794             }
1795              
1796             # is last
1797             elsif ($length == CORE::length($char[$i+1])) {
1798 0         0 push @regexp, _range_regexp($length, "\x00" x $length, $char[$i+1]);
1799             }
1800              
1801             else {
1802 0         0 die __FILE__, ": subroutine make_regexp panic.";
1803             }
1804              
1805 0 0       0 if ($length == 1) {
1806 0         0 push @singleoctet, @regexp;
1807             }
1808             else {
1809 0         0 push @multipleoctet, @regexp;
1810             }
1811             }
1812              
1813 0         0 $i += 2;
1814             }
1815              
1816             # with /i modifier
1817             elsif ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) {
1818 0 0       0 if ($modifier =~ /i/oxms) {
1819 0         0 my $uc = Char::Ekoi8u::uc($char[$i]);
1820 0         0 my $fc = Char::Ekoi8u::fc($char[$i]);
1821 0 0       0 if ($uc ne $fc) {
1822 0 0       0 if (CORE::length($fc) == 1) {
1823 0         0 push @singleoctet, $uc, $fc;
1824             }
1825             else {
1826 0         0 push @singleoctet, $uc;
1827 0         0 push @multipleoctet, $fc;
1828             }
1829             }
1830             else {
1831 0         0 push @singleoctet, $char[$i];
1832             }
1833             }
1834             else {
1835 0         0 push @singleoctet, $char[$i];
1836             }
1837 0         0 $i += 1;
1838             }
1839              
1840             # single character of single octet code
1841             elsif ($char[$i] =~ /\A (?: \\h ) \z/oxms) {
1842 0         0 push @singleoctet, "\t", "\x20";
1843 0         0 $i += 1;
1844             }
1845             elsif ($char[$i] =~ /\A (?: \\v ) \z/oxms) {
1846 0         0 push @singleoctet, "\x0A", "\x0B", "\x0C", "\x0D";
1847 0         0 $i += 1;
1848             }
1849             elsif ($char[$i] =~ /\A (?: \\d | \\s | \\w ) \z/oxms) {
1850 0         0 push @singleoctet, $char[$i];
1851 0         0 $i += 1;
1852             }
1853              
1854             # single character of multiple-octet code
1855             else {
1856 0         0 push @multipleoctet, $char[$i];
1857 0         0 $i += 1;
1858             }
1859             }
1860              
1861             # quote metachar
1862 0         0 for (@singleoctet) {
1863 0 0       0 if ($_ eq '...') {
    0          
    0          
    0          
    0          
1864 0         0 $_ = '-';
1865             }
1866             elsif (/\A \n \z/oxms) {
1867 0         0 $_ = '\n';
1868             }
1869             elsif (/\A \r \z/oxms) {
1870 0         0 $_ = '\r';
1871             }
1872             elsif (/\A ([\x00-\x20\x7F-\xFF]) \z/oxms) {
1873 0         0 $_ = sprintf('\x%02X', CORE::ord $1);
1874             }
1875             elsif (/\A [\x00-\xFF] \z/oxms) {
1876 0         0 $_ = quotemeta $_;
1877             }
1878             }
1879              
1880             # return character list
1881 0         0 return \@singleoctet, \@multipleoctet;
1882             }
1883              
1884             #
1885             # KOI8-U octal escape sequence
1886             #
1887             sub octchr {
1888 0     0 0 0 my($octdigit) = @_;
1889              
1890 0         0 my @binary = ();
1891 0         0 for my $octal (split(//,$octdigit)) {
1892 0         0 push @binary, {
1893             '0' => '000',
1894             '1' => '001',
1895             '2' => '010',
1896             '3' => '011',
1897             '4' => '100',
1898             '5' => '101',
1899             '6' => '110',
1900             '7' => '111',
1901             }->{$octal};
1902             }
1903 0         0 my $binary = join '', @binary;
1904              
1905 0         0 my $octchr = {
1906             # 1234567
1907             1 => pack('B*', "0000000$binary"),
1908             2 => pack('B*', "000000$binary"),
1909             3 => pack('B*', "00000$binary"),
1910             4 => pack('B*', "0000$binary"),
1911             5 => pack('B*', "000$binary"),
1912             6 => pack('B*', "00$binary"),
1913             7 => pack('B*', "0$binary"),
1914             0 => pack('B*', "$binary"),
1915              
1916             }->{CORE::length($binary) % 8};
1917              
1918 0         0 return $octchr;
1919             }
1920              
1921             #
1922             # KOI8-U hexadecimal escape sequence
1923             #
1924             sub hexchr {
1925 0     0 0 0 my($hexdigit) = @_;
1926              
1927 0         0 my $hexchr = {
1928             1 => pack('H*', "0$hexdigit"),
1929             0 => pack('H*', "$hexdigit"),
1930              
1931             }->{CORE::length($_[0]) % 2};
1932              
1933 0         0 return $hexchr;
1934             }
1935              
1936             #
1937             # KOI8-U open character list for qr
1938             #
1939             sub charlist_qr {
1940              
1941 0     0 0 0 my $modifier = pop @_;
1942 0         0 my @char = @_;
1943              
1944 0         0 my($singleoctet, $multipleoctet) = _charlist(@char, $modifier);
1945 0         0 my @singleoctet = @$singleoctet;
1946 0         0 my @multipleoctet = @$multipleoctet;
1947              
1948             # return character list
1949 0 0       0 if (scalar(@singleoctet) >= 1) {
1950              
1951             # with /i modifier
1952 0 0       0 if ($modifier =~ m/i/oxms) {
1953 0         0 my %singleoctet_ignorecase = ();
1954 0         0 for (@singleoctet) {
1955 0   0     0 while (s/ \A \\x(..) - \\x(..) //oxms or s/ \A \\x((..)) //oxms) {
1956 0         0 for my $ord (hex($1) .. hex($2)) {
1957 0         0 my $char = CORE::chr($ord);
1958 0         0 my $uc = Char::Ekoi8u::uc($char);
1959 0         0 my $fc = Char::Ekoi8u::fc($char);
1960 0 0       0 if ($uc eq $fc) {
1961 0         0 $singleoctet_ignorecase{unpack 'C*', $char} = 1;
1962             }
1963             else {
1964 0 0       0 if (CORE::length($fc) == 1) {
1965 0         0 $singleoctet_ignorecase{unpack 'C*', $uc} = 1;
1966 0         0 $singleoctet_ignorecase{unpack 'C*', $fc} = 1;
1967             }
1968             else {
1969 0         0 $singleoctet_ignorecase{unpack 'C*', $uc} = 1;
1970 0         0 push @multipleoctet, join '', map {sprintf('\x%02X',$_)} unpack 'C*', $fc;
  0         0  
1971             }
1972             }
1973             }
1974             }
1975 0 0       0 if ($_ ne '') {
1976 0         0 $singleoctet_ignorecase{unpack 'C*', $_} = 1;
1977             }
1978             }
1979 0         0 my $i = 0;
1980 0         0 my @singleoctet_ignorecase = ();
1981 0         0 for my $ord (0 .. 255) {
1982 0 0       0 if (exists $singleoctet_ignorecase{$ord}) {
1983 0         0 push @{$singleoctet_ignorecase[$i]}, $ord;
  0         0  
1984             }
1985             else {
1986 0         0 $i++;
1987             }
1988             }
1989 0         0 @singleoctet = ();
1990 0         0 for my $range (@singleoctet_ignorecase) {
1991 0 0       0 if (ref $range) {
1992 0 0       0 if (scalar(@{$range}) == 1) {
  0 0       0  
  0         0  
1993 0         0 push @singleoctet, sprintf('\x%02X', @{$range}[0]);
  0         0  
1994             }
1995             elsif (scalar(@{$range}) == 2) {
1996 0         0 push @singleoctet, sprintf('\x%02X\x%02X', @{$range}[0], @{$range}[-1]);
  0         0  
  0         0  
1997             }
1998             else {
1999 0         0 push @singleoctet, sprintf('\x%02X-\x%02X', @{$range}[0], @{$range}[-1]);
  0         0  
  0         0  
2000             }
2001             }
2002             }
2003             }
2004              
2005 0         0 my $not_anchor = '';
2006              
2007 0         0 push @multipleoctet, join('', $not_anchor, '[', @singleoctet, ']' );
2008             }
2009 0 0       0 if (scalar(@multipleoctet) >= 2) {
2010 0         0 return '(?:' . join('|', @multipleoctet) . ')';
2011             }
2012             else {
2013 0         0 return $multipleoctet[0];
2014             }
2015             }
2016              
2017             #
2018             # KOI8-U open character list for not qr
2019             #
2020             sub charlist_not_qr {
2021              
2022 0     0 0 0 my $modifier = pop @_;
2023 0         0 my @char = @_;
2024              
2025 0         0 my($singleoctet, $multipleoctet) = _charlist(@char, $modifier);
2026 0         0 my @singleoctet = @$singleoctet;
2027 0         0 my @multipleoctet = @$multipleoctet;
2028              
2029             # with /i modifier
2030 0 0       0 if ($modifier =~ m/i/oxms) {
2031 0         0 my %singleoctet_ignorecase = ();
2032 0         0 for (@singleoctet) {
2033 0   0     0 while (s/ \A \\x(..) - \\x(..) //oxms or s/ \A \\x((..)) //oxms) {
2034 0         0 for my $ord (hex($1) .. hex($2)) {
2035 0         0 my $char = CORE::chr($ord);
2036 0         0 my $uc = Char::Ekoi8u::uc($char);
2037 0         0 my $fc = Char::Ekoi8u::fc($char);
2038 0 0       0 if ($uc eq $fc) {
2039 0         0 $singleoctet_ignorecase{unpack 'C*', $char} = 1;
2040             }
2041             else {
2042 0 0       0 if (CORE::length($fc) == 1) {
2043 0         0 $singleoctet_ignorecase{unpack 'C*', $uc} = 1;
2044 0         0 $singleoctet_ignorecase{unpack 'C*', $fc} = 1;
2045             }
2046             else {
2047 0         0 $singleoctet_ignorecase{unpack 'C*', $uc} = 1;
2048 0         0 push @multipleoctet, join '', map {sprintf('\x%02X',$_)} unpack 'C*', $fc;
  0         0  
2049             }
2050             }
2051             }
2052             }
2053 0 0       0 if ($_ ne '') {
2054 0         0 $singleoctet_ignorecase{unpack 'C*', $_} = 1;
2055             }
2056             }
2057 0         0 my $i = 0;
2058 0         0 my @singleoctet_ignorecase = ();
2059 0         0 for my $ord (0 .. 255) {
2060 0 0       0 if (exists $singleoctet_ignorecase{$ord}) {
2061 0         0 push @{$singleoctet_ignorecase[$i]}, $ord;
  0         0  
2062             }
2063             else {
2064 0         0 $i++;
2065             }
2066             }
2067 0         0 @singleoctet = ();
2068 0         0 for my $range (@singleoctet_ignorecase) {
2069 0 0       0 if (ref $range) {
2070 0 0       0 if (scalar(@{$range}) == 1) {
  0 0       0  
  0         0  
2071 0         0 push @singleoctet, sprintf('\x%02X', @{$range}[0]);
  0         0  
2072             }
2073             elsif (scalar(@{$range}) == 2) {
2074 0         0 push @singleoctet, sprintf('\x%02X\x%02X', @{$range}[0], @{$range}[-1]);
  0         0  
  0         0  
2075             }
2076             else {
2077 0         0 push @singleoctet, sprintf('\x%02X-\x%02X', @{$range}[0], @{$range}[-1]);
  0         0  
  0         0  
2078             }
2079             }
2080             }
2081             }
2082              
2083             # return character list
2084 0 0       0 if (scalar(@multipleoctet) >= 1) {
2085 0 0       0 if (scalar(@singleoctet) >= 1) {
2086              
2087             # any character other than multiple-octet and single octet character class
2088 0         0 return '(?!' . join('|', @multipleoctet) . ')(?:[^' . join('', @singleoctet) . '])';
2089             }
2090             else {
2091              
2092             # any character other than multiple-octet character class
2093 0         0 return '(?!' . join('|', @multipleoctet) . ")(?:$your_char)";
2094             }
2095             }
2096             else {
2097 0 0       0 if (scalar(@singleoctet) >= 1) {
2098              
2099             # any character other than single octet character class
2100 0         0 return '(?:[^' . join('', @singleoctet) . '])';
2101             }
2102             else {
2103              
2104             # any character
2105 0         0 return "(?:$your_char)";
2106             }
2107             }
2108             }
2109              
2110             #
2111             # open file in read mode
2112             #
2113             sub _open_r {
2114 197     197   628 my(undef,$file) = @_;
2115 197         808 $file =~ s#\A (\s) #./$1#oxms;
2116 197   33     24580 return CORE::eval(q{open($_[0],'<',$_[1])}) ||
2117             open($_[0],"< $file\0");
2118             }
2119              
2120             #
2121             # open file in write mode
2122             #
2123             sub _open_w {
2124 0     0   0 my(undef,$file) = @_;
2125 0         0 $file =~ s#\A (\s) #./$1#oxms;
2126 0   0     0 return CORE::eval(q{open($_[0],'>',$_[1])}) ||
2127             open($_[0],"> $file\0");
2128             }
2129              
2130             #
2131             # open file in append mode
2132             #
2133             sub _open_a {
2134 0     0   0 my(undef,$file) = @_;
2135 0         0 $file =~ s#\A (\s) #./$1#oxms;
2136 0   0     0 return CORE::eval(q{open($_[0],'>>',$_[1])}) ||
2137             open($_[0],">> $file\0");
2138             }
2139              
2140             #
2141             # safe system
2142             #
2143             sub _systemx {
2144              
2145             # P.707 29.2.33. exec
2146             # in Chapter 29: Functions
2147             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
2148             #
2149             # Be aware that in older releases of Perl, exec (and system) did not flush
2150             # your output buffer, so you needed to enable command buffering by setting $|
2151             # on one or more filehandles to avoid lost output in the case of exec, or
2152             # misordererd output in the case of system. This situation was largely remedied
2153             # in the 5.6 release of Perl. (So, 5.005 release not yet.)
2154              
2155             # P.855 exec
2156             # in Chapter 27: Functions
2157             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
2158             #
2159             # In very old release of Perl (before v5.6), exec (and system) did not flush
2160             # your output buffer, so you needed to enable command buffering by setting $|
2161             # on one or more filehandles to avoid lost output with exec or misordered
2162             # output with system.
2163              
2164 197     197   730 $| = 1;
2165              
2166             # P.565 23.1.2. Cleaning Up Your Environment
2167             # in Chapter 23: Security
2168             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
2169              
2170             # P.656 Cleaning Up Your Environment
2171             # in Chapter 20: Security
2172             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
2173              
2174             # local $ENV{'PATH'} = '.';
2175 197         1985 local @ENV{qw(IFS CDPATH ENV BASH_ENV)}; # Make %ENV safer
2176              
2177             # P.707 29.2.33. exec
2178             # in Chapter 29: Functions
2179             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
2180             #
2181             # As we mentioned earlier, exec treats a discrete list of arguments as an
2182             # indication that it should bypass shell processing. However, there is one
2183             # place where you might still get tripped up. The exec call (and system, too)
2184             # will not distinguish between a single scalar argument and an array containing
2185             # only one element.
2186             #
2187             # @args = ("echo surprise"); # just one element in list
2188             # exec @args # still subject to shell escapes
2189             # or die "exec: $!"; # because @args == 1
2190             #
2191             # To avoid this, you can use the PATHNAME syntax, explicitly duplicating the
2192             # first argument as the pathname, which forces the rest of the arguments to be
2193             # interpreted as a list, even if there is only one of them:
2194             #
2195             # exec { $args[0] } @args # safe even with one-argument list
2196             # or die "can't exec @args: $!";
2197              
2198             # P.855 exec
2199             # in Chapter 27: Functions
2200             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
2201             #
2202             # As we mentioned earlier, exec treats a discrete list of arguments as a
2203             # directive to bypass shell processing. However, there is one place where
2204             # you might still get tripped up. The exec call (and system, too) cannot
2205             # distinguish between a single scalar argument and an array containing
2206             # only one element.
2207             #
2208             # @args = ("echo surprise"); # just one element in list
2209             # exec @args # still subject to shell escapes
2210             # || die "exec: $!"; # because @args == 1
2211             #
2212             # To avoid this, use the PATHNAME syntax, explicitly duplicating the first
2213             # argument as the pathname, which forces the rest of the arguments to be
2214             # interpreted as a list, even if there is only one of them:
2215             #
2216             # exec { $args[0] } @args # safe even with one-argument list
2217             # || die "can't exec @args: $!";
2218              
2219 197         399 return CORE::system { $_[0] } @_; # safe even with one-argument list
  197         23338702  
2220             }
2221              
2222             #
2223             # KOI8-U order to character (with parameter)
2224             #
2225             sub Char::Ekoi8u::chr(;$) {
2226              
2227 0 0   0 0   my $c = @_ ? $_[0] : $_;
2228              
2229 0 0         if ($c == 0x00) {
2230 0           return "\x00";
2231             }
2232             else {
2233 0           my @chr = ();
2234 0           while ($c > 0) {
2235 0           unshift @chr, ($c % 0x100);
2236 0           $c = int($c / 0x100);
2237             }
2238 0           return pack 'C*', @chr;
2239             }
2240             }
2241              
2242             #
2243             # KOI8-U order to character (without parameter)
2244             #
2245             sub Char::Ekoi8u::chr_() {
2246              
2247 0     0 0   my $c = $_;
2248              
2249 0 0         if ($c == 0x00) {
2250 0           return "\x00";
2251             }
2252             else {
2253 0           my @chr = ();
2254 0           while ($c > 0) {
2255 0           unshift @chr, ($c % 0x100);
2256 0           $c = int($c / 0x100);
2257             }
2258 0           return pack 'C*', @chr;
2259             }
2260             }
2261              
2262             #
2263             # KOI8-U path globbing (with parameter)
2264             #
2265             sub Char::Ekoi8u::glob($) {
2266              
2267 0 0   0 0   if (wantarray) {
2268 0           my @glob = _DOS_like_glob(@_);
2269 0           for my $glob (@glob) {
2270 0           $glob =~ s{ \A (?:\./)+ }{}oxms;
2271             }
2272 0           return @glob;
2273             }
2274             else {
2275 0           my $glob = _DOS_like_glob(@_);
2276 0           $glob =~ s{ \A (?:\./)+ }{}oxms;
2277 0           return $glob;
2278             }
2279             }
2280              
2281             #
2282             # KOI8-U path globbing (without parameter)
2283             #
2284             sub Char::Ekoi8u::glob_() {
2285              
2286 0 0   0 0   if (wantarray) {
2287 0           my @glob = _DOS_like_glob();
2288 0           for my $glob (@glob) {
2289 0           $glob =~ s{ \A (?:\./)+ }{}oxms;
2290             }
2291 0           return @glob;
2292             }
2293             else {
2294 0           my $glob = _DOS_like_glob();
2295 0           $glob =~ s{ \A (?:\./)+ }{}oxms;
2296 0           return $glob;
2297             }
2298             }
2299              
2300             #
2301             # KOI8-U path globbing via File::DosGlob 1.10
2302             #
2303             # Often I confuse "_dosglob" and "_doglob".
2304             # So, I renamed "_dosglob" to "_DOS_like_glob".
2305             #
2306             my %iter;
2307             my %entries;
2308             sub _DOS_like_glob {
2309              
2310             # context (keyed by second cxix argument provided by core)
2311 0     0     my($expr,$cxix) = @_;
2312              
2313             # glob without args defaults to $_
2314 0 0         $expr = $_ if not defined $expr;
2315              
2316             # represents the current user's home directory
2317             #
2318             # 7.3. Expanding Tildes in Filenames
2319             # in Chapter 7. File Access
2320             # of ISBN 0-596-00313-7 Perl Cookbook, 2nd Edition.
2321             #
2322             # and File::HomeDir, File::HomeDir::Windows module
2323              
2324             # DOS-like system
2325 0 0         if ($^O =~ /\A (?: MSWin32 | NetWare | symbian | dos ) \z/oxms) {
2326 0           $expr =~ s{ \A ~ (?= [^/\\] ) }
2327 0           { my_home_MSWin32() }oxmse;
2328             }
2329              
2330             # UNIX-like system
2331             else {
2332 0           $expr =~ s{ \A ~ ( (?:[^/])* ) }
2333 0 0 0       { $1 ? (CORE::eval(q{(getpwnam($1))[7]})||my_home()) : my_home() }oxmse;
2334             }
2335              
2336             # assume global context if not provided one
2337 0 0         $cxix = '_G_' if not defined $cxix;
2338 0 0         $iter{$cxix} = 0 if not exists $iter{$cxix};
2339              
2340             # if we're just beginning, do it all first
2341 0 0         if ($iter{$cxix} == 0) {
2342 0           $entries{$cxix} = [ _do_glob(1, _parse_line($expr)) ];
2343             }
2344              
2345             # chuck it all out, quick or slow
2346 0 0         if (wantarray) {
2347 0           delete $iter{$cxix};
2348 0           return @{delete $entries{$cxix}};
  0            
2349             }
2350             else {
2351 0 0         if ($iter{$cxix} = scalar @{$entries{$cxix}}) {
  0            
2352 0           return shift @{$entries{$cxix}};
  0            
2353             }
2354             else {
2355             # return undef for EOL
2356 0           delete $iter{$cxix};
2357 0           delete $entries{$cxix};
2358 0           return undef;
2359             }
2360             }
2361             }
2362              
2363             #
2364             # KOI8-U path globbing subroutine
2365             #
2366             sub _do_glob {
2367              
2368 0     0     my($cond,@expr) = @_;
2369 0           my @glob = ();
2370 0           my $fix_drive_relative_paths = 0;
2371              
2372             OUTER:
2373 0           for my $expr (@expr) {
2374 0 0         next OUTER if not defined $expr;
2375 0 0         next OUTER if $expr eq '';
2376              
2377 0           my @matched = ();
2378 0           my @globdir = ();
2379 0           my $head = '.';
2380 0           my $pathsep = '/';
2381 0           my $tail;
2382              
2383             # if argument is within quotes strip em and do no globbing
2384 0 0         if ($expr =~ /\A " ((?:$q_char)*) " \z/oxms) {
2385 0           $expr = $1;
2386 0 0         if ($cond eq 'd') {
2387 0 0         if (-d $expr) {
2388 0           push @glob, $expr;
2389             }
2390             }
2391             else {
2392 0 0         if (-e $expr) {
2393 0           push @glob, $expr;
2394             }
2395             }
2396 0           next OUTER;
2397             }
2398              
2399             # wildcards with a drive prefix such as h:*.pm must be changed
2400             # to h:./*.pm to expand correctly
2401 0 0         if ($^O =~ /\A (?: MSWin32 | NetWare | symbian | dos ) \z/oxms) {
2402 0 0         if ($expr =~ s# \A ((?:[A-Za-z]:)?) ([^/\\]) #$1./$2#oxms) {
2403 0           $fix_drive_relative_paths = 1;
2404             }
2405             }
2406              
2407 0 0         if (($head, $tail) = _parse_path($expr,$pathsep)) {
2408 0 0         if ($tail eq '') {
2409 0           push @glob, $expr;
2410 0           next OUTER;
2411             }
2412 0 0         if ($head =~ / \A (?:$q_char)*? [*?] /oxms) {
2413 0 0         if (@globdir = _do_glob('d', $head)) {
2414 0           push @glob, _do_glob($cond, map {"$_$pathsep$tail"} @globdir);
  0            
2415 0           next OUTER;
2416             }
2417             }
2418 0 0 0       if ($head eq '' or $head =~ /\A [A-Za-z]: \z/oxms) {
2419 0           $head .= $pathsep;
2420             }
2421 0           $expr = $tail;
2422             }
2423              
2424             # If file component has no wildcards, we can avoid opendir
2425 0 0         if ($expr !~ / \A (?:$q_char)*? [*?] /oxms) {
2426 0 0         if ($head eq '.') {
2427 0           $head = '';
2428             }
2429 0 0 0       if ($head ne '' and ($head =~ / \G ($q_char) /oxmsg)[-1] ne $pathsep) {
2430 0           $head .= $pathsep;
2431             }
2432 0           $head .= $expr;
2433 0 0         if ($cond eq 'd') {
2434 0 0         if (-d $head) {
2435 0           push @glob, $head;
2436             }
2437             }
2438             else {
2439 0 0         if (-e $head) {
2440 0           push @glob, $head;
2441             }
2442             }
2443 0           next OUTER;
2444             }
2445 0 0         opendir(*DIR, $head) or next OUTER;
2446 0           my @leaf = readdir DIR;
2447 0           closedir DIR;
2448              
2449 0 0         if ($head eq '.') {
2450 0           $head = '';
2451             }
2452 0 0 0       if ($head ne '' and ($head =~ / \G ($q_char) /oxmsg)[-1] ne $pathsep) {
2453 0           $head .= $pathsep;
2454             }
2455              
2456 0           my $pattern = '';
2457 0           while ($expr =~ / \G ($q_char) /oxgc) {
2458 0           my $char = $1;
2459              
2460             # 6.9. Matching Shell Globs as Regular Expressions
2461             # in Chapter 6. Pattern Matching
2462             # of ISBN 0-596-00313-7 Perl Cookbook, 2nd Edition.
2463             # (and so on)
2464              
2465 0 0         if ($char eq '*') {
    0          
    0          
2466 0           $pattern .= "(?:$your_char)*",
2467             }
2468             elsif ($char eq '?') {
2469 0           $pattern .= "(?:$your_char)?", # DOS style
2470             # $pattern .= "(?:$your_char)", # UNIX style
2471             }
2472             elsif ((my $fc = Char::Ekoi8u::fc($char)) ne $char) {
2473 0           $pattern .= $fc;
2474             }
2475             else {
2476 0           $pattern .= quotemeta $char;
2477             }
2478             }
2479 0     0     my $matchsub = sub { Char::Ekoi8u::fc($_[0]) =~ /\A $pattern \z/xms };
  0            
2480              
2481             # if ($@) {
2482             # print STDERR "$0: $@\n";
2483             # next OUTER;
2484             # }
2485              
2486             INNER:
2487 0           for my $leaf (@leaf) {
2488 0 0 0       if ($leaf eq '.' or $leaf eq '..') {
2489 0           next INNER;
2490             }
2491 0 0 0       if ($cond eq 'd' and not -d "$head$leaf") {
2492 0           next INNER;
2493             }
2494              
2495 0 0         if (&$matchsub($leaf)) {
2496 0           push @matched, "$head$leaf";
2497 0           next INNER;
2498             }
2499              
2500             # [DOS compatibility special case]
2501             # Failed, add a trailing dot and try again, but only...
2502              
2503 0 0 0       if (Char::Ekoi8u::index($leaf,'.') == -1 and # if name does not have a dot in it *and*
      0        
2504             CORE::length($leaf) <= 8 and # name is shorter than or equal to 8 chars *and*
2505             Char::Ekoi8u::index($pattern,'\\.') != -1 # pattern has a dot.
2506             ) {
2507 0 0         if (&$matchsub("$leaf.")) {
2508 0           push @matched, "$head$leaf";
2509 0           next INNER;
2510             }
2511             }
2512             }
2513 0 0         if (@matched) {
2514 0           push @glob, @matched;
2515             }
2516             }
2517 0 0         if ($fix_drive_relative_paths) {
2518 0           for my $glob (@glob) {
2519 0           $glob =~ s# \A ([A-Za-z]:) \./ #$1#oxms;
2520             }
2521             }
2522 0           return @glob;
2523             }
2524              
2525             #
2526             # KOI8-U parse line
2527             #
2528             sub _parse_line {
2529              
2530 0     0     my($line) = @_;
2531              
2532 0           $line .= ' ';
2533 0           my @piece = ();
2534 0           while ($line =~ /
2535             " ( (?: [^"] )* ) " \s+ |
2536             ( (?: [^"\s] )* ) \s+
2537             /oxmsg
2538             ) {
2539 0 0         push @piece, defined($1) ? $1 : $2;
2540             }
2541 0           return @piece;
2542             }
2543              
2544             #
2545             # KOI8-U parse path
2546             #
2547             sub _parse_path {
2548              
2549 0     0     my($path,$pathsep) = @_;
2550              
2551 0           $path .= '/';
2552 0           my @subpath = ();
2553 0           while ($path =~ /
2554             ((?: [^\/\\] )+?) [\/\\]
2555             /oxmsg
2556             ) {
2557 0           push @subpath, $1;
2558             }
2559              
2560 0           my $tail = pop @subpath;
2561 0           my $head = join $pathsep, @subpath;
2562 0           return $head, $tail;
2563             }
2564              
2565             #
2566             # via File::HomeDir::Windows 1.00
2567             #
2568             sub my_home_MSWin32 {
2569              
2570             # A lot of unix people and unix-derived tools rely on
2571             # the ability to overload HOME. We will support it too
2572             # so that they can replace raw HOME calls with File::HomeDir.
2573 0 0 0 0 0   if (exists $ENV{'HOME'} and $ENV{'HOME'}) {
    0 0        
    0 0        
      0        
      0        
2574 0           return $ENV{'HOME'};
2575             }
2576              
2577             # Do we have a user profile?
2578             elsif (exists $ENV{'USERPROFILE'} and $ENV{'USERPROFILE'}) {
2579 0           return $ENV{'USERPROFILE'};
2580             }
2581              
2582             # Some Windows use something like $ENV{'HOME'}
2583             elsif (exists $ENV{'HOMEDRIVE'} and exists $ENV{'HOMEPATH'} and $ENV{'HOMEDRIVE'} and $ENV{'HOMEPATH'}) {
2584 0           return join '', $ENV{'HOMEDRIVE'}, $ENV{'HOMEPATH'};
2585             }
2586              
2587 0           return undef;
2588             }
2589              
2590             #
2591             # via File::HomeDir::Unix 1.00
2592             #
2593             sub my_home {
2594 0     0 0   my $home;
2595              
2596 0 0 0       if (exists $ENV{'HOME'} and defined $ENV{'HOME'}) {
    0 0        
2597 0           $home = $ENV{'HOME'};
2598             }
2599              
2600             # This is from the original code, but I'm guessing
2601             # it means "login directory" and exists on some Unixes.
2602             elsif (exists $ENV{'LOGDIR'} and $ENV{'LOGDIR'}) {
2603 0           $home = $ENV{'LOGDIR'};
2604             }
2605              
2606             ### More-desperate methods
2607              
2608             # Light desperation on any (Unixish) platform
2609             else {
2610 0           $home = CORE::eval q{ (getpwuid($<))[7] };
2611             }
2612              
2613             # On Unix in general, a non-existant home means "no home"
2614             # For example, "nobody"-like users might use /nonexistant
2615 0 0 0       if (defined $home and ! -d($home)) {
2616 0           $home = undef;
2617             }
2618 0           return $home;
2619             }
2620              
2621             #
2622             # ${^PREMATCH}, $PREMATCH, $` the string preceding what was matched
2623             #
2624             sub Char::Ekoi8u::PREMATCH {
2625 0     0 0   return $`;
2626             }
2627              
2628             #
2629             # ${^MATCH}, $MATCH, $& the string that matched
2630             #
2631             sub Char::Ekoi8u::MATCH {
2632 0     0 0   return $&;
2633             }
2634              
2635             #
2636             # ${^POSTMATCH}, $POSTMATCH, $' the string following what was matched
2637             #
2638             sub Char::Ekoi8u::POSTMATCH {
2639 0     0 0   return $';
2640             }
2641              
2642             #
2643             # KOI8-U character to order (with parameter)
2644             #
2645             sub Char::KOI8U::ord(;$) {
2646              
2647 0 0   0 1   local $_ = shift if @_;
2648              
2649 0 0         if (/\A ($q_char) /oxms) {
2650 0           my @ord = unpack 'C*', $1;
2651 0           my $ord = 0;
2652 0           while (my $o = shift @ord) {
2653 0           $ord = $ord * 0x100 + $o;
2654             }
2655 0           return $ord;
2656             }
2657             else {
2658 0           return CORE::ord $_;
2659             }
2660             }
2661              
2662             #
2663             # KOI8-U character to order (without parameter)
2664             #
2665             sub Char::KOI8U::ord_() {
2666              
2667 0 0   0 0   if (/\A ($q_char) /oxms) {
2668 0           my @ord = unpack 'C*', $1;
2669 0           my $ord = 0;
2670 0           while (my $o = shift @ord) {
2671 0           $ord = $ord * 0x100 + $o;
2672             }
2673 0           return $ord;
2674             }
2675             else {
2676 0           return CORE::ord $_;
2677             }
2678             }
2679              
2680             #
2681             # KOI8-U reverse
2682             #
2683             sub Char::KOI8U::reverse(@) {
2684              
2685 0 0   0 0   if (wantarray) {
2686 0           return CORE::reverse @_;
2687             }
2688             else {
2689              
2690             # One of us once cornered Larry in an elevator and asked him what
2691             # problem he was solving with this, but he looked as far off into
2692             # the distance as he could in an elevator and said, "It seemed like
2693             # a good idea at the time."
2694              
2695 0           return join '', CORE::reverse(join('',@_) =~ /\G ($q_char) /oxmsg);
2696             }
2697             }
2698              
2699             #
2700             # KOI8-U getc (with parameter, without parameter)
2701             #
2702             sub Char::KOI8U::getc(;*@) {
2703              
2704 0     0 0   my($package) = caller;
2705 0 0         my $fh = @_ ? qualify_to_ref(shift,$package) : \*STDIN;
2706 0 0 0       croak 'Too many arguments for Char::KOI8U::getc' if @_ and not wantarray;
2707              
2708 0           my @length = sort { $a <=> $b } keys %range_tr;
  0            
2709 0           my $getc = '';
2710 0           for my $length ($length[0] .. $length[-1]) {
2711 0           $getc .= CORE::getc($fh);
2712 0 0         if (exists $range_tr{CORE::length($getc)}) {
2713 0 0         if ($getc =~ /\A ${Char::Ekoi8u::dot_s} \z/oxms) {
2714 0 0         return wantarray ? ($getc,@_) : $getc;
2715             }
2716             }
2717             }
2718 0 0         return wantarray ? ($getc,@_) : $getc;
2719             }
2720              
2721             #
2722             # KOI8-U length by character
2723             #
2724             sub Char::KOI8U::length(;$) {
2725              
2726 0 0   0 1   local $_ = shift if @_;
2727              
2728 0           local @_ = /\G ($q_char) /oxmsg;
2729 0           return scalar @_;
2730             }
2731              
2732             #
2733             # KOI8-U substr by character
2734             #
2735             BEGIN {
2736              
2737             # P.232 The lvalue Attribute
2738             # in Chapter 6: Subroutines
2739             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
2740              
2741             # P.336 The lvalue Attribute
2742             # in Chapter 7: Subroutines
2743             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
2744              
2745             # P.144 8.4 Lvalue subroutines
2746             # in Chapter 8: perlsub: Perl subroutines
2747             # of ISBN-13: 978-1-906966-02-7 The Perl Language Reference Manual (for Perl version 5.12.1)
2748              
2749 197 50 0 197 1 154195 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            
2750             # vv----------------*******
2751             sub Char::KOI8U::substr($$;$$) %s {
2752              
2753             my @char = $_[0] =~ /\G ($q_char) /oxmsg;
2754              
2755             # If the substring is beyond either end of the string, substr() returns the undefined
2756             # value and produces a warning. When used as an lvalue, specifying a substring that
2757             # is entirely outside the string raises an exception.
2758             # http://perldoc.perl.org/functions/substr.html
2759              
2760             # A return with no argument returns the scalar value undef in scalar context,
2761             # an empty list () in list context, and (naturally) nothing at all in void
2762             # context.
2763              
2764             my $offset = $_[1];
2765             if (($offset > scalar(@char)) or ($offset < (-1 * scalar(@char)))) {
2766             return;
2767             }
2768              
2769             # substr($string,$offset,$length,$replacement)
2770             if (@_ == 4) {
2771             my(undef,undef,$length,$replacement) = @_;
2772             my $substr = join '', splice(@char, $offset, $length, $replacement);
2773             $_[0] = join '', @char;
2774              
2775             # return $substr; this doesn't work, don't say "return"
2776             $substr;
2777             }
2778              
2779             # substr($string,$offset,$length)
2780             elsif (@_ == 3) {
2781             my(undef,undef,$length) = @_;
2782             my $octet_offset = 0;
2783             my $octet_length = 0;
2784             if ($offset == 0) {
2785             $octet_offset = 0;
2786             }
2787             elsif ($offset > 0) {
2788             $octet_offset = CORE::length(join '', @char[0..$offset-1]);
2789             }
2790             else {
2791             $octet_offset = -1 * CORE::length(join '', @char[$#char+$offset+1..$#char]);
2792             }
2793             if ($length == 0) {
2794             $octet_length = 0;
2795             }
2796             elsif ($length > 0) {
2797             $octet_length = CORE::length(join '', @char[$offset..$offset+$length-1]);
2798             }
2799             else {
2800             $octet_length = -1 * CORE::length(join '', @char[$#char+$length+1..$#char]);
2801             }
2802             CORE::substr($_[0], $octet_offset, $octet_length);
2803             }
2804              
2805             # substr($string,$offset)
2806             else {
2807             my $octet_offset = 0;
2808             if ($offset == 0) {
2809             $octet_offset = 0;
2810             }
2811             elsif ($offset > 0) {
2812             $octet_offset = CORE::length(join '', @char[0..$offset-1]);
2813             }
2814             else {
2815             $octet_offset = -1 * CORE::length(join '', @char[$#char+$offset+1..$#char]);
2816             }
2817             CORE::substr($_[0], $octet_offset);
2818             }
2819             }
2820             END
2821             }
2822              
2823             #
2824             # KOI8-U index by character
2825             #
2826             sub Char::KOI8U::index($$;$) {
2827              
2828 0     0 1   my $index;
2829 0 0         if (@_ == 3) {
2830 0           $index = Char::Ekoi8u::index($_[0], $_[1], CORE::length(Char::KOI8U::substr($_[0], 0, $_[2])));
2831             }
2832             else {
2833 0           $index = Char::Ekoi8u::index($_[0], $_[1]);
2834             }
2835              
2836 0 0         if ($index == -1) {
2837 0           return -1;
2838             }
2839             else {
2840 0           return Char::KOI8U::length(CORE::substr $_[0], 0, $index);
2841             }
2842             }
2843              
2844             #
2845             # KOI8-U rindex by character
2846             #
2847             sub Char::KOI8U::rindex($$;$) {
2848              
2849 0     0 1   my $rindex;
2850 0 0         if (@_ == 3) {
2851 0           $rindex = Char::Ekoi8u::rindex($_[0], $_[1], CORE::length(Char::KOI8U::substr($_[0], 0, $_[2])));
2852             }
2853             else {
2854 0           $rindex = Char::Ekoi8u::rindex($_[0], $_[1]);
2855             }
2856              
2857 0 0         if ($rindex == -1) {
2858 0           return -1;
2859             }
2860             else {
2861 0           return Char::KOI8U::length(CORE::substr $_[0], 0, $rindex);
2862             }
2863             }
2864              
2865             # when 'm//', '/' means regexp match 'm//' and '?' means regexp match '??'
2866             # when 'div', '/' means division operator and '?' means conditional operator (condition ? then : else)
2867 197     197   16427 BEGIN { CORE::eval q{ use vars qw($slash) } } $slash = 'm//';
  197     197   2057  
  197         412  
  197         16107  
2868              
2869             # ord() to ord() or Char::KOI8U::ord()
2870 197     197   14038 BEGIN { CORE::eval q{ use vars qw($function_ord) } } $function_ord = 'ord';
  197     197   1342  
  197         404  
  197         12255  
2871              
2872             # ord to ord or Char::KOI8U::ord_
2873 197     197   11720 BEGIN { CORE::eval q{ use vars qw($function_ord_) } } $function_ord_ = 'ord';
  197     197   1120  
  197         389  
  197         13165  
2874              
2875             # reverse to reverse or Char::KOI8U::reverse
2876 197     197   12076 BEGIN { CORE::eval q{ use vars qw($function_reverse) } } $function_reverse = 'reverse';
  197     197   1111  
  197         406  
  197         12597  
2877              
2878             # getc to getc or Char::KOI8U::getc
2879 197     197   11979 BEGIN { CORE::eval q{ use vars qw($function_getc) } } $function_getc = 'getc';
  197     197   1106  
  197         1057  
  197         14705  
2880              
2881             # P.1023 Appendix W.9 Multibyte Anchoring
2882             # of ISBN 1-56592-224-7 CJKV Information Processing
2883              
2884             my $anchor = '';
2885              
2886 197     197   12571 BEGIN { CORE::eval q{ use vars qw($nest) } }
  197     197   1126  
  197         356  
  197         12280096  
2887              
2888             # regexp of nested parens in qqXX
2889              
2890             # P.340 Matching Nested Constructs with Embedded Code
2891             # in Chapter 7: Perl
2892             # of ISBN 0-596-00289-0 Mastering Regular Expressions, Second edition
2893              
2894             my $qq_paren = qr{(?{local $nest=0}) (?>(?:
2895             \\c[\x40-\x5F] |
2896             \\ [\x00-\xFF] |
2897             [^()] |
2898             \( (?{$nest++}) |
2899             \) (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!))
2900             }xms;
2901             my $qq_brace = qr{(?{local $nest=0}) (?>(?:
2902             \\c[\x40-\x5F] |
2903             \\ [\x00-\xFF] |
2904             [^{}] |
2905             \{ (?{$nest++}) |
2906             \} (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!))
2907             }xms;
2908             my $qq_bracket = qr{(?{local $nest=0}) (?>(?:
2909             \\c[\x40-\x5F] |
2910             \\ [\x00-\xFF] |
2911             [^[\]] |
2912             \[ (?{$nest++}) |
2913             \] (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!))
2914             }xms;
2915             my $qq_angle = qr{(?{local $nest=0}) (?>(?:
2916             \\c[\x40-\x5F] |
2917             \\ [\x00-\xFF] |
2918             [^<>] |
2919             \< (?{$nest++}) |
2920             \> (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!))
2921             }xms;
2922             my $qq_scalar = qr{(?: \{ (?:$qq_brace)*? \} |
2923             (?: ::)? (?:
2924             [a-zA-Z_][a-zA-Z_0-9]*
2925             (?: ::[a-zA-Z_][a-zA-Z_0-9]* )* (?: \[ (?: \$\[ | \$\] | $qq_char )*? \] | \{ (?:$qq_brace)*? \} )*
2926             (?: (?: -> )? (?: [\$\@\%\&\*]\* | \$\#\* | [\@\%]? \[ (?: \$\[ | \$\] | $qq_char )*? \] | [\@\%\*]? \{ (?:$qq_brace)*? \} ) )*
2927             ))
2928             }xms;
2929             my $qq_variable = qr{(?: \{ (?:$qq_brace)*? \} |
2930             (?: ::)? (?:
2931             [0-9]+ |
2932             [^a-zA-Z_0-9\[\]] |
2933             ^[A-Z] |
2934             [a-zA-Z_][a-zA-Z_0-9]*
2935             (?: ::[a-zA-Z_][a-zA-Z_0-9]* )* (?: \[ (?: \$\[ | \$\] | $qq_char )*? \] | \{ (?:$qq_brace)*? \} )*
2936             (?: (?: -> )? (?: [\$\@\%\&\*]\* | \$\#\* | [\@\%]? \[ (?: \$\[ | \$\] | $qq_char )*? \] | [\@\%\*]? \{ (?:$qq_brace)*? \} ) )*
2937             ))
2938             }xms;
2939             my $qq_substr = qr{(?: Char::KOI8U::substr | CORE::substr | substr ) \( $qq_paren \)
2940             }xms;
2941              
2942             # regexp of nested parens in qXX
2943             my $q_paren = qr{(?{local $nest=0}) (?>(?:
2944             [^()] |
2945             \( (?{$nest++}) |
2946             \) (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!))
2947             }xms;
2948             my $q_brace = qr{(?{local $nest=0}) (?>(?:
2949             [^{}] |
2950             \{ (?{$nest++}) |
2951             \} (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!))
2952             }xms;
2953             my $q_bracket = qr{(?{local $nest=0}) (?>(?:
2954             [^[\]] |
2955             \[ (?{$nest++}) |
2956             \] (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!))
2957             }xms;
2958             my $q_angle = qr{(?{local $nest=0}) (?>(?:
2959             [^<>] |
2960             \< (?{$nest++}) |
2961             \> (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!))
2962             }xms;
2963              
2964             my $matched = '';
2965             my $s_matched = '';
2966              
2967             my $tr_variable = ''; # variable of tr///
2968             my $sub_variable = ''; # variable of s///
2969             my $bind_operator = ''; # =~ or !~
2970              
2971             my @heredoc = (); # here document
2972             my @heredoc_delimiter = ();
2973             my $here_script = ''; # here script
2974              
2975             #
2976             # escape KOI8-U script
2977             #
2978             sub Char::KOI8U::escape(;$) {
2979 0 0   0 0   local($_) = $_[0] if @_;
2980              
2981             # P.359 The Study Function
2982             # in Chapter 7: Perl
2983             # of ISBN 0-596-00289-0 Mastering Regular Expressions, Second edition
2984              
2985 0           study $_; # Yes, I studied study yesterday.
2986              
2987             # while all script
2988              
2989             # 6.14. Matching from Where the Last Pattern Left Off
2990             # in Chapter 6. Pattern Matching
2991             # of ISBN 0-596-00313-7 Perl Cookbook, 2nd Edition.
2992             # (and so on)
2993              
2994             # one member of Tag-team
2995             #
2996             # P.128 Start of match (or end of previous match): \G
2997             # P.130 Advanced Use of \G with Perl
2998             # in Chapter 3: Overview of Regular Expression Features and Flavors
2999             # P.255 Use leading anchors
3000             # P.256 Expose ^ and \G at the front expressions
3001             # in Chapter 6: Crafting an Efficient Expression
3002             # P.315 "Tag-team" matching with /gc
3003             # in Chapter 7: Perl
3004             # of ISBN 0-596-00289-0 Mastering Regular Expressions, Second edition
3005              
3006 0           my $e_script = '';
3007 0           while (not /\G \z/oxgc) { # member
3008 0           $e_script .= Char::KOI8U::escape_token();
3009             }
3010              
3011 0           return $e_script;
3012             }
3013              
3014             #
3015             # escape KOI8-U token of script
3016             #
3017             sub Char::KOI8U::escape_token {
3018              
3019             # \n output here document
3020              
3021 0     0 0   my $ignore_modules = join('|', qw(
3022             utf8
3023             bytes
3024             charnames
3025             I18N::Japanese
3026             I18N::Collate
3027             I18N::JExt
3028             File::DosGlob
3029             Wild
3030             Wildcard
3031             Japanese
3032             ));
3033              
3034             # another member of Tag-team
3035             #
3036             # P.315 "Tag-team" matching with /gc
3037             # in Chapter 7: Perl
3038             # of ISBN 0-596-00289-0 Mastering Regular Expressions, Second edition
3039              
3040 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          
3041 0           my $heredoc = '';
3042 0 0         if (scalar(@heredoc_delimiter) >= 1) {
3043 0           $slash = 'm//';
3044              
3045 0           $heredoc = join '', @heredoc;
3046 0           @heredoc = ();
3047              
3048             # skip here document
3049 0           for my $heredoc_delimiter (@heredoc_delimiter) {
3050 0           /\G .*? \n $heredoc_delimiter \n/xmsgc;
3051             }
3052 0           @heredoc_delimiter = ();
3053              
3054 0           $here_script = '';
3055             }
3056 0           return "\n" . $heredoc;
3057             }
3058              
3059             # ignore space, comment
3060 0           elsif (/\G (\s+|\#.*) /oxgc) { return $1; }
3061              
3062             # if (, elsif (, unless (, while (, until (, given (, and when (
3063              
3064             # given, when
3065              
3066             # P.225 The given Statement
3067             # in Chapter 15: Smart Matching and given-when
3068             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
3069              
3070             # P.133 The given Statement
3071             # in Chapter 4: Statements and Declarations
3072             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
3073              
3074             elsif (/\G ( (?: if | elsif | unless | while | until | given | when ) \s* \( ) /oxgc) {
3075 0           $slash = 'm//';
3076 0           return $1;
3077             }
3078              
3079             # scalar variable ($scalar = ...) =~ tr///;
3080             # scalar variable ($scalar = ...) =~ s///;
3081              
3082             # state
3083              
3084             # P.68 Persistent, Private Variables
3085             # in Chapter 4: Subroutines
3086             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
3087              
3088             # P.160 Persistent Lexically Scoped Variables: state
3089             # in Chapter 4: Statements and Declarations
3090             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
3091              
3092             # (and so on)
3093              
3094             elsif (/\G ( \( \s* (?: local \b | my \b | our \b | state \b )? \s* \$ $qq_scalar ) /oxgc) {
3095 0           my $e_string = e_string($1);
3096              
3097 0 0         if (/\G ( \s* = $qq_paren \) ) ( \s* (?: =~ | !~ ) \s* ) (?= (?: tr | y ) \b ) /oxgc) {
    0          
3098 0           $tr_variable = $e_string . e_string($1);
3099 0           $bind_operator = $2;
3100 0           $slash = 'm//';
3101 0           return '';
3102             }
3103             elsif (/\G ( \s* = $qq_paren \) ) ( \s* (?: =~ | !~ ) \s* ) (?= s \b ) /oxgc) {
3104 0           $sub_variable = $e_string . e_string($1);
3105 0           $bind_operator = $2;
3106 0           $slash = 'm//';
3107 0           return '';
3108             }
3109             else {
3110 0           $slash = 'div';
3111 0           return $e_string;
3112             }
3113             }
3114              
3115             # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Char::Ekoi8u::PREMATCH()
3116             elsif (/\G ( \$` | \$\{`\} | \$ \s* PREMATCH \b | \$ \s* \{ \s* PREMATCH \s* \} | \$ \s* \{\^PREMATCH\} ) /oxmsgc) {
3117 0           $slash = 'div';
3118 0           return q{Char::Ekoi8u::PREMATCH()};
3119             }
3120              
3121             # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Char::Ekoi8u::MATCH()
3122             elsif (/\G ( \$& | \$\{&\} | \$ \s* MATCH \b | \$ \s* \{ \s* MATCH \s* \} | \$ \s* \{\^MATCH\} ) /oxmsgc) {
3123 0           $slash = 'div';
3124 0           return q{Char::Ekoi8u::MATCH()};
3125             }
3126              
3127             # $', ${'} --> $', ${'}
3128             elsif (/\G ( \$' | \$\{'\} ) /oxmsgc) {
3129 0           $slash = 'div';
3130 0           return $1;
3131             }
3132              
3133             # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Char::Ekoi8u::POSTMATCH()
3134             elsif (/\G ( \$ \s* POSTMATCH \b | \$ \s* \{ \s* POSTMATCH \s* \} | \$ \s* \{\^POSTMATCH\} ) /oxmsgc) {
3135 0           $slash = 'div';
3136 0           return q{Char::Ekoi8u::POSTMATCH()};
3137             }
3138              
3139             # scalar variable $scalar =~ tr///;
3140             # scalar variable $scalar =~ s///;
3141             # substr() =~ tr///;
3142             # substr() =~ s///;
3143             elsif (/\G ( \$ $qq_scalar | $qq_substr ) /oxgc) {
3144 0           my $scalar = e_string($1);
3145              
3146 0 0         if (/\G ( \s* (?: =~ | !~ ) \s* ) (?= (?: tr | y ) \b ) /oxgc) {
    0          
3147 0           $tr_variable = $scalar;
3148 0           $bind_operator = $1;
3149 0           $slash = 'm//';
3150 0           return '';
3151             }
3152             elsif (/\G ( \s* (?: =~ | !~ ) \s* ) (?= s \b ) /oxgc) {
3153 0           $sub_variable = $scalar;
3154 0           $bind_operator = $1;
3155 0           $slash = 'm//';
3156 0           return '';
3157             }
3158             else {
3159 0           $slash = 'div';
3160 0           return $scalar;
3161             }
3162             }
3163              
3164             # end of statement
3165             elsif (/\G ( [,;] ) /oxgc) {
3166 0           $slash = 'm//';
3167              
3168             # clear tr/// variable
3169 0           $tr_variable = '';
3170              
3171             # clear s/// variable
3172 0           $sub_variable = '';
3173              
3174 0           $bind_operator = '';
3175              
3176 0           return $1;
3177             }
3178              
3179             # bareword
3180             elsif (/\G ( \{ \s* (?: tr | index | rindex | reverse ) \s* \} ) /oxmsgc) {
3181 0           return $1;
3182             }
3183              
3184             # $0 --> $0
3185             elsif (/\G ( \$ 0 ) /oxmsgc) {
3186 0           $slash = 'div';
3187 0           return $1;
3188             }
3189             elsif (/\G ( \$ \{ \s* 0 \s* \} ) /oxmsgc) {
3190 0           $slash = 'div';
3191 0           return $1;
3192             }
3193              
3194             # $$ --> $$
3195             elsif (/\G ( \$ \$ ) (?![\w\{]) /oxmsgc) {
3196 0           $slash = 'div';
3197 0           return $1;
3198             }
3199              
3200             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
3201             # $1, $2, $3 --> $1, $2, $3 otherwise
3202             elsif (/\G \$ ([1-9][0-9]*) /oxmsgc) {
3203 0           $slash = 'div';
3204 0           return e_capture($1);
3205             }
3206             elsif (/\G \$ \{ \s* ([1-9][0-9]*) \s* \} /oxmsgc) {
3207 0           $slash = 'div';
3208 0           return e_capture($1);
3209             }
3210              
3211             # $$foo[ ... ] --> $ $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.'->'.$2);
3215             }
3216              
3217             # $$foo{ ... } --> $ $foo->{ ... }
3218             elsif (/\G \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) ( \{ .+? \} ) /oxmsgc) {
3219 0           $slash = 'div';
3220 0           return e_capture($1.'->'.$2);
3221             }
3222              
3223             # $$foo
3224             elsif (/\G \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) /oxmsgc) {
3225 0           $slash = 'div';
3226 0           return e_capture($1);
3227             }
3228              
3229             # ${ foo }
3230             elsif (/\G \$ \s* \{ ( \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* ) \} /oxmsgc) {
3231 0           $slash = 'div';
3232 0           return '${' . $1 . '}';
3233             }
3234              
3235             # ${ ... }
3236             elsif (/\G \$ \s* \{ \s* ( $qq_brace ) \s* \} /oxmsgc) {
3237 0           $slash = 'div';
3238 0           return e_capture($1);
3239             }
3240              
3241             # variable or function
3242             # $ @ % & * $ #
3243             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) {
3244 0           $slash = 'div';
3245 0           return $1;
3246             }
3247             # $ $ $ $ $ $ $ $ $ $ $ $ $ $
3248             # $ @ # \ ' " / ? ( ) [ ] < >
3249             elsif (/\G ( \$[\$\@\#\\\'\"\/\?\(\)\[\]\<\>] ) /oxmsgc) {
3250 0           $slash = 'div';
3251 0           return $1;
3252             }
3253              
3254             # while ()
3255             elsif (/\G \b (while \s* \( \s* <[\$]?[A-Za-z_][A-Za-z_0-9]*> \s* \)) \b /oxgc) {
3256 0           return $1;
3257             }
3258              
3259             # while () --- glob
3260              
3261             # avoid "Error: Runtime exception" of perl version 5.005_03
3262              
3263             elsif (/\G \b while \s* \( \s* < ((?:[^>\0\a\e\f\n\r\t])+?) > \s* \) \b /oxgc) {
3264 0           return 'while ($_ = Char::Ekoi8u::glob("' . $1 . '"))';
3265             }
3266              
3267             # while (glob)
3268             elsif (/\G \b while \s* \( \s* glob \s* \) /oxgc) {
3269 0           return 'while ($_ = Char::Ekoi8u::glob_)';
3270             }
3271              
3272             # while (glob(WILDCARD))
3273             elsif (/\G \b while \s* \( \s* glob \b /oxgc) {
3274 0           return 'while ($_ = Char::Ekoi8u::glob';
3275             }
3276              
3277             # doit if, doit unless, doit while, doit until, doit for, doit when
3278 0           elsif (/\G \b ( if | unless | while | until | for | when ) \b /oxgc) { $slash = 'm//'; return $1; }
  0            
3279              
3280             # subroutines of package Char::Ekoi8u
3281 0           elsif (/\G \b (CORE:: | ->[ ]* (?: atan2 | [a-z]{2,})) \b /oxgc) { $slash = 'm//'; return $1; }
  0            
3282 0           elsif (/\G \b Char::KOI8U::eval (?= \s* \{ ) /oxgc) { $slash = 'm//'; return 'eval'; }
  0            
3283 0           elsif (/\G \b Char::KOI8U::eval \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'eval Char::KOI8U::escape'; }
  0            
3284 0           elsif (/\G \b bytes::substr \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'substr'; }
  0            
3285 0           elsif (/\G \b chop \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'Char::Ekoi8u::chop'; }
  0            
3286 0           elsif (/\G \b bytes::index \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'index'; }
  0            
3287 0           elsif (/\G \b Char::KOI8U::index \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'Char::KOI8U::index'; }
  0            
3288 0           elsif (/\G \b index \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'Char::Ekoi8u::index'; }
  0            
3289 0           elsif (/\G \b bytes::rindex \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'rindex'; }
  0            
3290 0           elsif (/\G \b Char::KOI8U::rindex \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'Char::KOI8U::rindex'; }
  0            
3291 0           elsif (/\G \b rindex \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'Char::Ekoi8u::rindex'; }
  0            
3292 0           elsif (/\G \b lc (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Char::Ekoi8u::lc'; }
  0            
3293 0           elsif (/\G \b lcfirst (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Char::Ekoi8u::lcfirst'; }
  0            
3294 0           elsif (/\G \b uc (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Char::Ekoi8u::uc'; }
  0            
3295 0           elsif (/\G \b ucfirst (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Char::Ekoi8u::ucfirst'; }
  0            
3296 0           elsif (/\G \b fc (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Char::Ekoi8u::fc'; }
  0            
3297              
3298             # "-s '' ..." means file test "-s 'filename' ..." (not means "- s/// ...")
3299 0           elsif (/\G -s \s+ \s* (\") ((?:$qq_char)+?) (\") /oxgc) { $slash = 'm//'; return '-s ' . e_qq('', $1,$3,$2); }
  0            
3300 0           elsif (/\G -s \s+ qq \s* (\#) ((?:$qq_char)+?) (\#) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0            
3301 0           elsif (/\G -s \s+ qq \s* (\() ((?:$qq_paren)+?) (\)) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0            
3302 0           elsif (/\G -s \s+ qq \s* (\{) ((?:$qq_brace)+?) (\}) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0            
3303 0           elsif (/\G -s \s+ qq \s* (\[) ((?:$qq_bracket)+?) (\]) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0            
3304 0           elsif (/\G -s \s+ qq \s* (\<) ((?:$qq_angle)+?) (\>) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0            
3305 0           elsif (/\G -s \s+ qq \s* (\S) ((?:$qq_char)+?) (\1) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0            
3306              
3307 0           elsif (/\G -s \s+ \s* (\') ((?:\\\'|\\\\|$q_char)+?) (\') /oxgc) { $slash = 'm//'; return '-s ' . e_q ('', $1,$3,$2); }
  0            
3308 0           elsif (/\G -s \s+ q \s* (\#) ((?:\\\#|\\\\|$q_char)+?) (\#) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0            
3309 0           elsif (/\G -s \s+ q \s* (\() ((?:\\\)|\\\\|$q_paren)+?) (\)) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0            
3310 0           elsif (/\G -s \s+ q \s* (\{) ((?:\\\}|\\\\|$q_brace)+?) (\}) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0            
3311 0           elsif (/\G -s \s+ q \s* (\[) ((?:\\\]|\\\\|$q_bracket)+?) (\]) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0            
3312 0           elsif (/\G -s \s+ q \s* (\<) ((?:\\\>|\\\\|$q_angle)+?) (\>) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0            
3313 0           elsif (/\G -s \s+ q \s* (\S) ((?:\\\1|\\\\|$q_char)+?) (\1) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0            
3314              
3315             elsif (/\G -s \s* (\$ \w+(?: ::\w+)* (?: (?: ->)? (?: [\$\@\%\&\*]\* | \$\#\* | \( (?:$qq_paren)*? \) | [\@\%\*]? \{ (?:$qq_brace)+? \} | [\@\%]? \[ (?:$qq_bracket)+? \] ) )*) /oxgc)
3316 0           { $slash = 'm//'; return "-s $1"; }
  0            
3317 0           elsif (/\G -s \s* \( ((?:$qq_paren)*?) \) /oxgc) { $slash = 'm//'; return "-s ($1)"; }
  0            
3318 0           elsif (/\G -s (?= \s+ [a-z]+) /oxgc) { $slash = 'm//'; return '-s'; }
  0            
3319 0           elsif (/\G -s \s+ (\w+) /oxgc) { $slash = 'm//'; return "-s $1"; }
  0            
3320              
3321 0           elsif (/\G \b bytes::length (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'length'; }
  0            
3322 0           elsif (/\G \b bytes::chr (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'chr'; }
  0            
3323 0           elsif (/\G \b chr (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Char::Ekoi8u::chr'; }
  0            
3324 0           elsif (/\G \b bytes::ord (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $slash = 'div'; return 'ord'; }
  0            
3325 0           elsif (/\G \b ord (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $slash = 'div'; return $function_ord; }
  0            
3326 0           elsif (/\G \b glob (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Char::Ekoi8u::glob'; }
  0            
3327 0           elsif (/\G \b lc \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'Char::Ekoi8u::lc_'; }
  0            
3328 0           elsif (/\G \b lcfirst \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'Char::Ekoi8u::lcfirst_'; }
  0            
3329 0           elsif (/\G \b uc \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'Char::Ekoi8u::uc_'; }
  0            
3330 0           elsif (/\G \b ucfirst \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'Char::Ekoi8u::ucfirst_'; }
  0            
3331 0           elsif (/\G \b fc \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'Char::Ekoi8u::fc_'; }
  0            
3332 0           elsif (/\G -s \b (?! \s* => ) /oxgc) { $slash = 'm//'; return '-s '; }
  0            
3333              
3334 0           elsif (/\G \b bytes::length \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'length'; }
  0            
3335 0           elsif (/\G \b bytes::chr \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'chr'; }
  0            
3336 0           elsif (/\G \b chr \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'Char::Ekoi8u::chr_'; }
  0            
3337 0           elsif (/\G \b bytes::ord \b (?! \s* => ) /oxgc) { $slash = 'div'; return 'ord'; }
  0            
3338 0           elsif (/\G \b ord \b (?! \s* => ) /oxgc) { $slash = 'div'; return $function_ord_; }
  0            
3339 0           elsif (/\G \b glob \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'Char::Ekoi8u::glob_'; }
  0            
3340 0           elsif (/\G \b reverse \b (?! \s* => ) /oxgc) { $slash = 'm//'; return $function_reverse; }
  0            
3341 0           elsif (/\G \b getc \b (?! \s* => ) /oxgc) { $slash = 'm//'; return $function_getc; }
  0            
3342             # split
3343             elsif (/\G \b (split) \b (?! \s* => ) /oxgc) {
3344 0           $slash = 'm//';
3345              
3346 0           my $e = '';
3347 0           while (/\G ( \s+ | \( | \#.* ) /oxgc) {
3348 0           $e .= $1;
3349             }
3350              
3351             # end of split
3352 0 0         if (/\G (?= [,;\)\}\]] ) /oxgc) { return 'Char::Ekoi8u::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          
3353              
3354             # split scalar value
3355 0           elsif (/\G ( [\$\@\&\*] $qq_scalar ) /oxgc) { return 'Char::Ekoi8u::split' . $e . e_string($1); }
3356              
3357             # split literal space
3358 0           elsif (/\G \b qq (\#) [ ] (\#) /oxgc) { return 'Char::Ekoi8u::split' . $e . qq {qq$1 $2}; }
3359 0           elsif (/\G \b qq (\s*) (\() [ ] (\)) /oxgc) { return 'Char::Ekoi8u::split' . $e . qq{$1qq$2 $3}; }
3360 0           elsif (/\G \b qq (\s*) (\{) [ ] (\}) /oxgc) { return 'Char::Ekoi8u::split' . $e . qq{$1qq$2 $3}; }
3361 0           elsif (/\G \b qq (\s*) (\[) [ ] (\]) /oxgc) { return 'Char::Ekoi8u::split' . $e . qq{$1qq$2 $3}; }
3362 0           elsif (/\G \b qq (\s*) (\<) [ ] (\>) /oxgc) { return 'Char::Ekoi8u::split' . $e . qq{$1qq$2 $3}; }
3363 0           elsif (/\G \b qq (\s*) (\S) [ ] (\2) /oxgc) { return 'Char::Ekoi8u::split' . $e . qq{$1qq$2 $3}; }
3364 0           elsif (/\G \b q (\#) [ ] (\#) /oxgc) { return 'Char::Ekoi8u::split' . $e . qq {q$1 $2}; }
3365 0           elsif (/\G \b q (\s*) (\() [ ] (\)) /oxgc) { return 'Char::Ekoi8u::split' . $e . qq {$1q$2 $3}; }
3366 0           elsif (/\G \b q (\s*) (\{) [ ] (\}) /oxgc) { return 'Char::Ekoi8u::split' . $e . qq {$1q$2 $3}; }
3367 0           elsif (/\G \b q (\s*) (\[) [ ] (\]) /oxgc) { return 'Char::Ekoi8u::split' . $e . qq {$1q$2 $3}; }
3368 0           elsif (/\G \b q (\s*) (\<) [ ] (\>) /oxgc) { return 'Char::Ekoi8u::split' . $e . qq {$1q$2 $3}; }
3369 0           elsif (/\G \b q (\s*) (\S) [ ] (\2) /oxgc) { return 'Char::Ekoi8u::split' . $e . qq {$1q$2 $3}; }
3370 0           elsif (/\G ' [ ] ' /oxgc) { return 'Char::Ekoi8u::split' . $e . qq {' '}; }
3371 0           elsif (/\G " [ ] " /oxgc) { return 'Char::Ekoi8u::split' . $e . qq {" "}; }
3372              
3373             # split qq//
3374             elsif (/\G \b (qq) \b /oxgc) {
3375 0 0         if (/\G (\#) ((?:$qq_char)*?) (\#) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq# # --> qr # #
  0            
3376             else {
3377 0           while (not /\G \z/oxgc) {
3378 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
3379 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq ( ) --> qr ( )
3380 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq { } --> qr { }
3381 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq [ ] --> qr [ ]
3382 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq < > --> qr < >
3383 0           elsif (/\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) /oxgc) { return e_split($e.'qr','{','}',$2,''); } # qq | | --> qr { }
3384 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq * * --> qr * *
3385             }
3386 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3387             }
3388             }
3389              
3390             # split qr//
3391             elsif (/\G \b (qr) \b /oxgc) {
3392 0 0         if (/\G (\#) ((?:$qq_char)*?) (\#) ([imosxpadlubB]*) /oxgc) { return e_split ($e.'qr',$1,$3,$2,$4); } # qr# #
  0            
3393             else {
3394 0           while (not /\G \z/oxgc) {
3395 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
3396 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([imosxpadlubB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # qr ( )
3397 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([imosxpadlubB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # qr { }
3398 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([imosxpadlubB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # qr [ ]
3399 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([imosxpadlubB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # qr < >
3400 0           elsif (/\G (\') ((?:$qq_char)*?) (\') ([imosxpadlubB]*) /oxgc) { return e_split_q($e.'qr',$1, $3, $2,$4); } # qr ' '
3401 0           elsif (/\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ([imosxpadlubB]*) /oxgc) { return e_split ($e.'qr','{','}',$2,$4); } # qr | | --> qr { }
3402 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([imosxpadlubB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # qr * *
3403             }
3404 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3405             }
3406             }
3407              
3408             # split q//
3409             elsif (/\G \b (q) \b /oxgc) {
3410 0 0         if (/\G (\#) ((?:\\\#|\\\\|$q_char)*?) (\#) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q# # --> qr # #
  0            
3411             else {
3412 0           while (not /\G \z/oxgc) {
3413 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
3414 0           elsif (/\G (\() ((?:\\\\|\\\)|\\\(|$q_paren)*?) (\)) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q ( ) --> qr ( )
3415 0           elsif (/\G (\{) ((?:\\\\|\\\}|\\\{|$q_brace)*?) (\}) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q { } --> qr { }
3416 0           elsif (/\G (\[) ((?:\\\\|\\\]|\\\[|$q_bracket)*?) (\]) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q [ ] --> qr [ ]
3417 0           elsif (/\G (\<) ((?:\\\\|\\\>|\\\<|$q_angle)*?) (\>) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q < > --> qr < >
3418 0           elsif (/\G ([*\-:?\\^|]) ((?:$q_char)*?) (\1) /oxgc) { return e_split_q($e.'qr','{','}',$2,''); } # q | | --> qr { }
3419 0           elsif (/\G (\S) ((?:\\\\|\\\1| $q_char)*?) (\1) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q * * --> qr * *
3420             }
3421 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3422             }
3423             }
3424              
3425             # split m//
3426             elsif (/\G \b (m) \b /oxgc) {
3427 0 0         if (/\G (\#) ((?:$qq_char)*?) (\#) ([cgimosxpadlubB]*) /oxgc) { return e_split ($e.'qr',$1,$3,$2,$4); } # m# # --> qr # #
  0            
3428             else {
3429 0           while (not /\G \z/oxgc) {
3430 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
3431 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cgimosxpadlubB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # m ( ) --> qr ( )
3432 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cgimosxpadlubB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # m { } --> qr { }
3433 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cgimosxpadlubB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # m [ ] --> qr [ ]
3434 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cgimosxpadlubB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # m < > --> qr < >
3435 0           elsif (/\G (\') ((?:$qq_char)*?) (\') ([cgimosxpadlubB]*) /oxgc) { return e_split_q($e.'qr',$1, $3, $2,$4); } # m ' ' --> qr ' '
3436 0           elsif (/\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ([cgimosxpadlubB]*) /oxgc) { return e_split ($e.'qr','{','}',$2,$4); } # m | | --> qr { }
3437 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cgimosxpadlubB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # m * * --> qr * *
3438             }
3439 0           die __FILE__, ": Search pattern not terminated";
3440             }
3441             }
3442              
3443             # split ''
3444             elsif (/\G (\') /oxgc) {
3445 0           my $q_string = '';
3446 0           while (not /\G \z/oxgc) {
3447 0 0         if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0          
    0          
    0          
3448 0           elsif (/\G (\\\') /oxgc) { $q_string .= $1; } # splitqr'' --> split qr''
3449 0           elsif (/\G \' /oxgc) { return e_split_q($e.q{ qr},"'","'",$q_string,''); } # ' ' --> qr ' '
3450 0           elsif (/\G ($q_char) /oxgc) { $q_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 $qq_string = '';
3458 0           while (not /\G \z/oxgc) {
3459 0 0         if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0          
    0          
    0          
3460 0           elsif (/\G (\\\") /oxgc) { $qq_string .= $1; } # splitqr"" --> split qr""
3461 0           elsif (/\G \" /oxgc) { return e_split($e.q{ qr},'"','"',$qq_string,''); } # " " --> qr " "
3462 0           elsif (/\G ($q_char) /oxgc) { $qq_string .= $1; }
3463             }
3464 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3465             }
3466              
3467             # split //
3468             elsif (/\G (\/) /oxgc) {
3469 0           my $regexp = '';
3470 0           while (not /\G \z/oxgc) {
3471 0 0         if (/\G (\\\\) /oxgc) { $regexp .= $1; }
  0 0          
    0          
    0          
3472 0           elsif (/\G (\\\/) /oxgc) { $regexp .= $1; } # splitqr// --> split qr//
3473 0           elsif (/\G \/ ([cgimosxpadlubB]*) /oxgc) { return e_split($e.q{ qr}, '/','/',$regexp,$1); } # / / --> qr / /
3474 0           elsif (/\G ($q_char) /oxgc) { $regexp .= $1; }
3475             }
3476 0           die __FILE__, ": Search pattern not terminated";
3477             }
3478             }
3479              
3480             # tr/// or y///
3481              
3482             # about [cdsrbB]* (/B modifier)
3483             #
3484             # P.559 appendix C
3485             # of ISBN 4-89052-384-7 Programming perl
3486             # (Japanese title is: Perl puroguramingu)
3487              
3488             elsif (/\G \b ( tr | y ) \b /oxgc) {
3489 0           my $ope = $1;
3490              
3491             # $1 $2 $3 $4 $5 $6
3492 0 0         if (/\G (\#) ((?:$qq_char)*?) (\#) ((?:$qq_char)*?) (\#) ([cdsrbB]*) /oxgc) { # tr# # #
3493 0           my @tr = ($tr_variable,$2);
3494 0           return e_tr(@tr,'',$4,$6);
3495             }
3496             else {
3497 0           my $e = '';
3498 0           while (not /\G \z/oxgc) {
3499 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3500             elsif (/\G (\() ((?:$qq_paren)*?) (\)) /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_brace)*?) (\}) /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_bracket)*?) (\]) /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             elsif (/\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) {
3537 0           my @tr = ($tr_variable,$2);
3538 0           while (not /\G \z/oxgc) {
3539 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3540 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr < > ( )
3541 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr < > { }
3542 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr < > [ ]
3543 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr < > < >
3544 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr < > * *
3545             }
3546 0           die __FILE__, ": Transliteration replacement not terminated";
3547             }
3548             # $1 $2 $3 $4 $5 $6
3549             elsif (/\G (\S) ((?:$qq_char)*?) (\1) ((?:$qq_char)*?) (\1) ([cdsrbB]*) /oxgc) { # tr * * *
3550 0           my @tr = ($tr_variable,$2);
3551 0           return e_tr(@tr,'',$4,$6);
3552             }
3553             }
3554 0           die __FILE__, ": Transliteration pattern not terminated";
3555             }
3556             }
3557              
3558             # qq//
3559             elsif (/\G \b (qq) \b /oxgc) {
3560 0           my $ope = $1;
3561              
3562             # if (/\G (\#) ((?:$qq_char)*?) (\#) /oxgc) { return e_qq($ope,$1,$3,$2); } # qq# #
3563 0 0         if (/\G (\#) /oxgc) { # qq# #
3564 0           my $qq_string = '';
3565 0           while (not /\G \z/oxgc) {
3566 0 0         if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0          
    0          
    0          
3567 0           elsif (/\G (\\\#) /oxgc) { $qq_string .= $1; }
3568 0           elsif (/\G (\#) /oxgc) { return e_qq($ope,'#','#',$qq_string); }
3569 0           elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3570             }
3571 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3572             }
3573              
3574             else {
3575 0           my $e = '';
3576 0           while (not /\G \z/oxgc) {
3577 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3578              
3579             # elsif (/\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qq ( )
3580             elsif (/\G (\() /oxgc) { # qq ( )
3581 0           my $qq_string = '';
3582 0           local $nest = 1;
3583 0           while (not /\G \z/oxgc) {
3584 0 0         if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0          
    0          
    0          
    0          
3585 0           elsif (/\G (\\\)) /oxgc) { $qq_string .= $1; }
3586 0           elsif (/\G (\() /oxgc) { $qq_string .= $1; $nest++; }
  0            
3587             elsif (/\G (\)) /oxgc) {
3588 0 0         if (--$nest == 0) { return $e . e_qq($ope,'(',')',$qq_string); }
  0            
3589 0           else { $qq_string .= $1; }
3590             }
3591 0           elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3592             }
3593 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3594             }
3595              
3596             # elsif (/\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qq { }
3597             elsif (/\G (\{) /oxgc) { # qq { }
3598 0           my $qq_string = '';
3599 0           local $nest = 1;
3600 0           while (not /\G \z/oxgc) {
3601 0 0         if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0          
    0          
    0          
    0          
3602 0           elsif (/\G (\\\}) /oxgc) { $qq_string .= $1; }
3603 0           elsif (/\G (\{) /oxgc) { $qq_string .= $1; $nest++; }
  0            
3604             elsif (/\G (\}) /oxgc) {
3605 0 0         if (--$nest == 0) { return $e . e_qq($ope,'{','}',$qq_string); }
  0            
3606 0           else { $qq_string .= $1; }
3607             }
3608 0           elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3609             }
3610 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3611             }
3612              
3613             # elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qq [ ]
3614             elsif (/\G (\[) /oxgc) { # qq [ ]
3615 0           my $qq_string = '';
3616 0           local $nest = 1;
3617 0           while (not /\G \z/oxgc) {
3618 0 0         if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0          
    0          
    0          
    0          
3619 0           elsif (/\G (\\\]) /oxgc) { $qq_string .= $1; }
3620 0           elsif (/\G (\[) /oxgc) { $qq_string .= $1; $nest++; }
  0            
3621             elsif (/\G (\]) /oxgc) {
3622 0 0         if (--$nest == 0) { return $e . e_qq($ope,'[',']',$qq_string); }
  0            
3623 0           else { $qq_string .= $1; }
3624             }
3625 0           elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3626             }
3627 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3628             }
3629              
3630             # elsif (/\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qq < >
3631             elsif (/\G (\<) /oxgc) { # qq < >
3632 0           my $qq_string = '';
3633 0           local $nest = 1;
3634 0           while (not /\G \z/oxgc) {
3635 0 0         if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0          
    0          
    0          
    0          
3636 0           elsif (/\G (\\\>) /oxgc) { $qq_string .= $1; }
3637 0           elsif (/\G (\<) /oxgc) { $qq_string .= $1; $nest++; }
  0            
3638             elsif (/\G (\>) /oxgc) {
3639 0 0         if (--$nest == 0) { return $e . e_qq($ope,'<','>',$qq_string); }
  0            
3640 0           else { $qq_string .= $1; }
3641             }
3642 0           elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3643             }
3644 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3645             }
3646              
3647             # elsif (/\G (\S) ((?:$qq_char)*?) (\1) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qq * *
3648             elsif (/\G (\S) /oxgc) { # qq * *
3649 0           my $delimiter = $1;
3650 0           my $qq_string = '';
3651 0           while (not /\G \z/oxgc) {
3652 0 0         if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0          
    0          
    0          
3653 0           elsif (/\G (\\\Q$delimiter\E) /oxgc) { $qq_string .= $1; }
3654 0           elsif (/\G (\Q$delimiter\E) /oxgc) { return $e . e_qq($ope,$delimiter,$delimiter,$qq_string); }
3655 0           elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3656             }
3657 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3658             }
3659             }
3660 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3661             }
3662             }
3663              
3664             # qr//
3665             elsif (/\G \b (qr) \b /oxgc) {
3666 0           my $ope = $1;
3667 0 0         if (/\G (\#) ((?:$qq_char)*?) (\#) ([imosxpadlubB]*) /oxgc) { # qr# # #
3668 0           return e_qr($ope,$1,$3,$2,$4);
3669             }
3670             else {
3671 0           my $e = '';
3672 0           while (not /\G \z/oxgc) {
3673 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
3674 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([imosxpadlubB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # qr ( )
3675 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([imosxpadlubB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # qr { }
3676 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([imosxpadlubB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # qr [ ]
3677 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([imosxpadlubB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # qr < >
3678 0           elsif (/\G (\') ((?:$qq_char)*?) (\') ([imosxpadlubB]*) /oxgc) { return $e . e_qr_q($ope,$1, $3, $2,$4); } # qr ' '
3679 0           elsif (/\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ([imosxpadlubB]*) /oxgc) { return $e . e_qr ($ope,'{','}',$2,$4); } # qr | | --> qr { }
3680 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([imosxpadlubB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # qr * *
3681             }
3682 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3683             }
3684             }
3685              
3686             # qw//
3687             elsif (/\G \b (qw) \b /oxgc) {
3688 0           my $ope = $1;
3689 0 0         if (/\G (\#) (.*?) (\#) /oxmsgc) { # qw# #
3690 0           return e_qw($ope,$1,$3,$2);
3691             }
3692             else {
3693 0           my $e = '';
3694 0           while (not /\G \z/oxgc) {
3695 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
3696              
3697 0           elsif (/\G (\() ([^(]*?) (\)) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw ( )
3698 0           elsif (/\G (\() ((?:$q_paren)*?) (\)) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw ( )
3699              
3700 0           elsif (/\G (\{) ([^{]*?) (\}) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw { }
3701 0           elsif (/\G (\{) ((?:$q_brace)*?) (\}) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw { }
3702              
3703 0           elsif (/\G (\[) ([^[]*?) (\]) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw [ ]
3704 0           elsif (/\G (\[) ((?:$q_bracket)*?) (\]) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw [ ]
3705              
3706 0           elsif (/\G (\<) ([^<]*?) (\>) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw < >
3707 0           elsif (/\G (\<) ((?:$q_angle)*?) (\>) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw < >
3708              
3709 0           elsif (/\G ([\x21-\x3F]) (.*?) (\1) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw * *
3710 0           elsif (/\G (\S) ((?:$q_char)*?) (\1) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw * *
3711             }
3712 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3713             }
3714             }
3715              
3716             # qx//
3717             elsif (/\G \b (qx) \b /oxgc) {
3718 0           my $ope = $1;
3719 0 0         if (/\G (\#) ((?:$qq_char)*?) (\#) /oxgc) { # qx# #
3720 0           return e_qq($ope,$1,$3,$2);
3721             }
3722             else {
3723 0           my $e = '';
3724 0           while (not /\G \z/oxgc) {
3725 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
3726 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qx ( )
3727 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qx { }
3728 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qx [ ]
3729 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qx < >
3730 0           elsif (/\G (\') ((?:$qq_char)*?) (\') /oxgc) { return $e . e_q ($ope,$1,$3,$2); } # qx ' '
3731 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qx * *
3732             }
3733 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3734             }
3735             }
3736              
3737             # q//
3738             elsif (/\G \b (q) \b /oxgc) {
3739 0           my $ope = $1;
3740              
3741             # if (/\G (\#) ((?:\\\#|\\\\|$q_char)*?) (\#) /oxgc) { return e_q($ope,$1,$3,$2); } # q# #
3742              
3743             # avoid "Error: Runtime exception" of perl version 5.005_03
3744             # (and so on)
3745              
3746 0 0         if (/\G (\#) /oxgc) { # q# #
3747 0           my $q_string = '';
3748 0           while (not /\G \z/oxgc) {
3749 0 0         if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0          
    0          
    0          
3750 0           elsif (/\G (\\\#) /oxgc) { $q_string .= $1; }
3751 0           elsif (/\G (\#) /oxgc) { return e_q($ope,'#','#',$q_string); }
3752 0           elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3753             }
3754 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3755             }
3756              
3757             else {
3758 0           my $e = '';
3759 0           while (not /\G \z/oxgc) {
3760 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3761              
3762             # elsif (/\G (\() ((?:\\\)|\\\\|$q_paren)*?) (\)) /oxgc) { return $e . e_q($ope,$1,$3,$2); } # q ( )
3763             elsif (/\G (\() /oxgc) { # q ( )
3764 0           my $q_string = '';
3765 0           local $nest = 1;
3766 0           while (not /\G \z/oxgc) {
3767 0 0         if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3768 0           elsif (/\G (\\\)) /oxgc) { $q_string .= $1; }
3769 0           elsif (/\G (\\\() /oxgc) { $q_string .= $1; }
3770 0           elsif (/\G (\() /oxgc) { $q_string .= $1; $nest++; }
  0            
3771             elsif (/\G (\)) /oxgc) {
3772 0 0         if (--$nest == 0) { return $e . e_q($ope,'(',')',$q_string); }
  0            
3773 0           else { $q_string .= $1; }
3774             }
3775 0           elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3776             }
3777 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3778             }
3779              
3780             # elsif (/\G (\{) ((?:\\\}|\\\\|$q_brace)*?) (\}) /oxgc) { return $e . e_q($ope,$1,$3,$2); } # q { }
3781             elsif (/\G (\{) /oxgc) { # q { }
3782 0           my $q_string = '';
3783 0           local $nest = 1;
3784 0           while (not /\G \z/oxgc) {
3785 0 0         if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3786 0           elsif (/\G (\\\}) /oxgc) { $q_string .= $1; }
3787 0           elsif (/\G (\\\{) /oxgc) { $q_string .= $1; }
3788 0           elsif (/\G (\{) /oxgc) { $q_string .= $1; $nest++; }
  0            
3789             elsif (/\G (\}) /oxgc) {
3790 0 0         if (--$nest == 0) { return $e . e_q($ope,'{','}',$q_string); }
  0            
3791 0           else { $q_string .= $1; }
3792             }
3793 0           elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3794             }
3795 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3796             }
3797              
3798             # elsif (/\G (\[) ((?:\\\]|\\\\|$q_bracket)*?) (\]) /oxgc) { return $e . e_q($ope,$1,$3,$2); } # q [ ]
3799             elsif (/\G (\[) /oxgc) { # q [ ]
3800 0           my $q_string = '';
3801 0           local $nest = 1;
3802 0           while (not /\G \z/oxgc) {
3803 0 0         if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3804 0           elsif (/\G (\\\]) /oxgc) { $q_string .= $1; }
3805 0           elsif (/\G (\\\[) /oxgc) { $q_string .= $1; }
3806 0           elsif (/\G (\[) /oxgc) { $q_string .= $1; $nest++; }
  0            
3807             elsif (/\G (\]) /oxgc) {
3808 0 0         if (--$nest == 0) { return $e . e_q($ope,'[',']',$q_string); }
  0            
3809 0           else { $q_string .= $1; }
3810             }
3811 0           elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3812             }
3813 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3814             }
3815              
3816             # elsif (/\G (\<) ((?:\\\>|\\\\|$q_angle)*?) (\>) /oxgc) { return $e . e_q($ope,$1,$3,$2); } # q < >
3817             elsif (/\G (\<) /oxgc) { # q < >
3818 0           my $q_string = '';
3819 0           local $nest = 1;
3820 0           while (not /\G \z/oxgc) {
3821 0 0         if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3822 0           elsif (/\G (\\\>) /oxgc) { $q_string .= $1; }
3823 0           elsif (/\G (\\\<) /oxgc) { $q_string .= $1; }
3824 0           elsif (/\G (\<) /oxgc) { $q_string .= $1; $nest++; }
  0            
3825             elsif (/\G (\>) /oxgc) {
3826 0 0         if (--$nest == 0) { return $e . e_q($ope,'<','>',$q_string); }
  0            
3827 0           else { $q_string .= $1; }
3828             }
3829 0           elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3830             }
3831 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3832             }
3833              
3834             # elsif (/\G (\S) ((?:\\\1|\\\\|$q_char)*?) (\1) /oxgc) { return $e . e_q($ope,$1,$3,$2); } # q * *
3835             elsif (/\G (\S) /oxgc) { # q * *
3836 0           my $delimiter = $1;
3837 0           my $q_string = '';
3838 0           while (not /\G \z/oxgc) {
3839 0 0         if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0          
    0          
    0          
3840 0           elsif (/\G (\\\Q$delimiter\E) /oxgc) { $q_string .= $1; }
3841 0           elsif (/\G (\Q$delimiter\E) /oxgc) { return $e . e_q($ope,$delimiter,$delimiter,$q_string); }
3842 0           elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3843             }
3844 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3845             }
3846             }
3847 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3848             }
3849             }
3850              
3851             # m//
3852             elsif (/\G \b (m) \b /oxgc) {
3853 0           my $ope = $1;
3854 0 0         if (/\G (\#) ((?:$qq_char)*?) (\#) ([cgimosxpadlubB]*) /oxgc) { # m# #
3855 0           return e_qr($ope,$1,$3,$2,$4);
3856             }
3857             else {
3858 0           my $e = '';
3859 0           while (not /\G \z/oxgc) {
3860 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
3861 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cgimosxpadlubB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m ( )
3862 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cgimosxpadlubB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m { }
3863 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cgimosxpadlubB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m [ ]
3864 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cgimosxpadlubB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m < >
3865 0           elsif (/\G (\?) ((?:$qq_char)*?) (\?) ([cgimosxpadlubB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m ? ?
3866 0           elsif (/\G (\') ((?:$qq_char)*?) (\') ([cgimosxpadlubB]*) /oxgc) { return $e . e_qr_q($ope,$1, $3, $2,$4); } # m ' '
3867 0           elsif (/\G ([*\-:\\^|]) ((?:$qq_char)*?) (\1) ([cgimosxpadlubB]*) /oxgc) { return $e . e_qr ($ope,'{','}',$2,$4); } # m | | --> m { }
3868 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cgimosxpadlubB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m * *
3869             }
3870 0           die __FILE__, ": Search pattern not terminated";
3871             }
3872             }
3873              
3874             # s///
3875              
3876             # about [cegimosxpradlubB]* (/cg modifier)
3877             #
3878             # P.67 Pattern-Matching Operators
3879             # of ISBN 0-596-00241-6 Perl in a Nutshell, Second Edition.
3880              
3881             elsif (/\G \b (s) \b /oxgc) {
3882 0           my $ope = $1;
3883              
3884             # $1 $2 $3 $4 $5 $6
3885 0 0         if (/\G (\#) ((?:$qq_char)*?) (\#) ((?:$qq_char)*?) (\#) ([cegimosxpradlubB]*) /oxgc) { # s# # #
3886 0           return e_sub($sub_variable,$1,$2,$3,$3,$4,$5,$6);
3887             }
3888             else {
3889 0           my $e = '';
3890 0           while (not /\G \z/oxgc) {
3891 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
3892             elsif (/\G (\() ((?:$qq_paren)*?) (\)) /oxgc) {
3893 0           my @s = ($1,$2,$3);
3894 0           while (not /\G \z/oxgc) {
3895 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
3896             # $1 $2 $3 $4
3897 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3898 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3899 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3900 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3901 0           elsif (/\G (\') ((?:$qq_char)*?) (\') ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3902 0           elsif (/\G (\$) ((?:$qq_char)*?) (\$) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3903 0           elsif (/\G (\:) ((?:$qq_char)*?) (\:) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3904 0           elsif (/\G (\@) ((?:$qq_char)*?) (\@) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3905 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3906             }
3907 0           die __FILE__, ": Substitution replacement not terminated";
3908             }
3909             elsif (/\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) {
3910 0           my @s = ($1,$2,$3);
3911 0           while (not /\G \z/oxgc) {
3912 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
3913             # $1 $2 $3 $4
3914 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3915 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3916 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3917 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3918 0           elsif (/\G (\') ((?:$qq_char)*?) (\') ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3919 0           elsif (/\G (\$) ((?:$qq_char)*?) (\$) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3920 0           elsif (/\G (\:) ((?:$qq_char)*?) (\:) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3921 0           elsif (/\G (\@) ((?:$qq_char)*?) (\@) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3922 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3923             }
3924 0           die __FILE__, ": Substitution replacement not terminated";
3925             }
3926             elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) {
3927 0           my @s = ($1,$2,$3);
3928 0           while (not /\G \z/oxgc) {
3929 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
3930             # $1 $2 $3 $4
3931 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3932 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3933 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3934 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3935 0           elsif (/\G (\') ((?:$qq_char)*?) (\') ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3936 0           elsif (/\G (\$) ((?:$qq_char)*?) (\$) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3937 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3938             }
3939 0           die __FILE__, ": Substitution replacement not terminated";
3940             }
3941             elsif (/\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) {
3942 0           my @s = ($1,$2,$3);
3943 0           while (not /\G \z/oxgc) {
3944 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
3945             # $1 $2 $3 $4
3946 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3947 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3948 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3949 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3950 0           elsif (/\G (\') ((?:$qq_char)*?) (\') ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3951 0           elsif (/\G (\$) ((?:$qq_char)*?) (\$) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3952 0           elsif (/\G (\:) ((?:$qq_char)*?) (\:) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3953 0           elsif (/\G (\@) ((?:$qq_char)*?) (\@) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3954 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3955             }
3956 0           die __FILE__, ": Substitution replacement not terminated";
3957             }
3958             # $1 $2 $3 $4 $5 $6
3959             elsif (/\G (\') ((?:$qq_char)*?) (\') ((?:$qq_char)*?) (\') ([cegimosxpradlubB]*) /oxgc) {
3960 0           return e_sub($sub_variable,$1,$2,$3,$3,$4,$5,$6);
3961             }
3962             # $1 $2 $3 $4 $5 $6
3963             elsif (/\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ((?:$qq_char)*?) (\1) ([cegimosxpradlubB]*) /oxgc) {
3964 0           return e_sub($sub_variable,'{',$2,'}','{',$4,'}',$6); # s | | | --> s { } { }
3965             }
3966             # $1 $2 $3 $4 $5 $6
3967             elsif (/\G (\$) ((?:$qq_char)*?) (\1) ((?:$qq_char)*?) (\1) ([cegimosxpradlubB]*) /oxgc) {
3968 0           return e_sub($sub_variable,$1,$2,$3,$3,$4,$5,$6);
3969             }
3970             # $1 $2 $3 $4 $5 $6
3971             elsif (/\G (\S) ((?:$qq_char)*?) (\1) ((?:$qq_char)*?) (\1) ([cegimosxpradlubB]*) /oxgc) {
3972 0           return e_sub($sub_variable,$1,$2,$3,$3,$4,$5,$6);
3973             }
3974             }
3975 0           die __FILE__, ": Substitution pattern not terminated";
3976             }
3977             }
3978              
3979             # require ignore module
3980 0           elsif (/\G \b require (\s+ (?:$ignore_modules) .*? ;) ([ \t]* [#\n]) /oxmsgc) { return "# require$1$2"; }
3981 0           elsif (/\G \b require (\s+ (?:$ignore_modules) .*? ;) ([ \t]* [^#]) /oxmsgc) { return "# require$1\n$2"; }
3982 0           elsif (/\G \b require (\s+ (?:$ignore_modules)) \b /oxmsgc) { return "# require$1"; }
3983              
3984             # use strict; --> use strict; no strict qw(refs);
3985 0           elsif (/\G \b use (\s+ strict .*? ;) ([ \t]* [#\n]) /oxmsgc) { return "use$1 no strict qw(refs);$2"; }
3986 0           elsif (/\G \b use (\s+ strict .*? ;) ([ \t]* [^#]) /oxmsgc) { return "use$1 no strict qw(refs);\n$2"; }
3987 0           elsif (/\G \b use (\s+ strict) \b /oxmsgc) { return "use$1; no strict qw(refs)"; }
3988              
3989             # use 5.12.0; --> use 5.12.0; no strict qw(refs);
3990             elsif (/\G \b use \s+ (([1-9][0-9_]*)(?:\.([0-9_]+))*) \s* ; /oxmsgc) {
3991 0 0 0       if (($2 >= 6) or (($2 == 5) and ($3 ge '012'))) {
      0        
3992 0           return "use $1; no strict qw(refs);";
3993             }
3994             else {
3995 0           return "use $1;";
3996             }
3997             }
3998             elsif (/\G \b use \s+ (v([0-9][0-9_]*)(?:\.([0-9_]+))*) \s* ; /oxmsgc) {
3999 0 0 0       if (($2 >= 6) or (($2 == 5) and ($3 >= 12))) {
      0        
4000 0           return "use $1; no strict qw(refs);";
4001             }
4002             else {
4003 0           return "use $1;";
4004             }
4005             }
4006              
4007             # ignore use module
4008 0           elsif (/\G \b use (\s+ (?:$ignore_modules) .*? ;) ([ \t]* [#\n]) /oxmsgc) { return "# use$1$2"; }
4009 0           elsif (/\G \b use (\s+ (?:$ignore_modules) .*? ;) ([ \t]* [^#]) /oxmsgc) { return "# use$1\n$2"; }
4010 0           elsif (/\G \b use (\s+ (?:$ignore_modules)) \b /oxmsgc) { return "# use$1"; }
4011              
4012             # ignore no module
4013 0           elsif (/\G \b no (\s+ (?:$ignore_modules) .*? ;) ([ \t]* [#\n]) /oxmsgc) { return "# no$1$2"; }
4014 0           elsif (/\G \b no (\s+ (?:$ignore_modules) .*? ;) ([ \t]* [^#]) /oxmsgc) { return "# no$1\n$2"; }
4015 0           elsif (/\G \b no (\s+ (?:$ignore_modules)) \b /oxmsgc) { return "# no$1"; }
4016              
4017             # use else
4018 0           elsif (/\G \b use \b /oxmsgc) { return "use"; }
4019              
4020             # use else
4021 0           elsif (/\G \b no \b /oxmsgc) { return "no"; }
4022              
4023             # ''
4024             elsif (/\G (?
4025 0           my $q_string = '';
4026 0           while (not /\G \z/oxgc) {
4027 0 0         if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0          
    0          
    0          
4028 0           elsif (/\G (\\\') /oxgc) { $q_string .= $1; }
4029 0           elsif (/\G \' /oxgc) { return e_q('', "'","'",$q_string); }
4030 0           elsif (/\G ($q_char) /oxgc) { $q_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 $qq_string = '';
4038 0           while (not /\G \z/oxgc) {
4039 0 0         if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0          
    0          
    0          
4040 0           elsif (/\G (\\\") /oxgc) { $qq_string .= $1; }
4041 0           elsif (/\G \" /oxgc) { return e_qq('', '"','"',$qq_string); }
4042 0           elsif (/\G ($q_char) /oxgc) { $qq_string .= $1; }
4043             }
4044 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
4045             }
4046              
4047             # ``
4048             elsif (/\G (\`) /oxgc) {
4049 0           my $qx_string = '';
4050 0           while (not /\G \z/oxgc) {
4051 0 0         if (/\G (\\\\) /oxgc) { $qx_string .= $1; }
  0 0          
    0          
    0          
4052 0           elsif (/\G (\\\`) /oxgc) { $qx_string .= $1; }
4053 0           elsif (/\G \` /oxgc) { return e_qq('', '`','`',$qx_string); }
4054 0           elsif (/\G ($q_char) /oxgc) { $qx_string .= $1; }
4055             }
4056 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
4057             }
4058              
4059             # // --- not divide operator (num / num), not defined-or
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('', '/','/',$regexp,$1); }
4066 0           elsif (/\G ($q_char) /oxgc) { $regexp .= $1; }
4067             }
4068 0           die __FILE__, ": Search pattern not terminated";
4069             }
4070              
4071             # ?? --- not conditional operator (condition ? then : else)
4072             elsif (($slash eq 'm//') and /\G (\?) /oxgc) {
4073 0           my $regexp = '';
4074 0           while (not /\G \z/oxgc) {
4075 0 0         if (/\G (\\\\) /oxgc) { $regexp .= $1; }
  0 0          
    0          
    0          
4076 0           elsif (/\G (\\\?) /oxgc) { $regexp .= $1; }
4077 0           elsif (/\G \? ([cgimosxpadlubB]*) /oxgc) { return e_qr('m','?','?',$regexp,$1); }
4078 0           elsif (/\G ($q_char) /oxgc) { $regexp .= $1; }
4079             }
4080 0           die __FILE__, ": Search pattern not terminated";
4081             }
4082              
4083             # << (bit shift) --- not here document
4084 0           elsif (/\G ( << \s* ) (?= [0-9\$\@\&] ) /oxgc) { $slash = 'm//'; return $1; }
  0            
4085              
4086             # <<'HEREDOC'
4087             elsif (/\G ( << '([a-zA-Z_0-9]*)' ) /oxgc) {
4088 0           $slash = 'm//';
4089 0           my $here_quote = $1;
4090 0           my $delimiter = $2;
4091              
4092             # get here document
4093 0 0         if ($here_script eq '') {
4094 0           $here_script = CORE::substr $_, pos $_;
4095 0           $here_script =~ s/.*?\n//oxm;
4096             }
4097 0 0         if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4098 0           push @heredoc, $1 . qq{\n$delimiter\n};
4099 0           push @heredoc_delimiter, $delimiter;
4100             }
4101             else {
4102 0           die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF";
4103             }
4104 0           return $here_quote;
4105             }
4106              
4107             # <<\HEREDOC
4108              
4109             # P.66 2.6.6. "Here" Documents
4110             # in Chapter 2: Bits and Pieces
4111             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
4112              
4113             # P.73 "Here" Documents
4114             # in Chapter 2: Bits and Pieces
4115             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
4116              
4117             elsif (/\G ( << \\([a-zA-Z_0-9]+) ) /oxgc) {
4118 0           $slash = 'm//';
4119 0           my $here_quote = $1;
4120 0           my $delimiter = $2;
4121              
4122             # get here document
4123 0 0         if ($here_script eq '') {
4124 0           $here_script = CORE::substr $_, pos $_;
4125 0           $here_script =~ s/.*?\n//oxm;
4126             }
4127 0 0         if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4128 0           push @heredoc, $1 . qq{\n$delimiter\n};
4129 0           push @heredoc_delimiter, $delimiter;
4130             }
4131             else {
4132 0           die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF";
4133             }
4134 0           return $here_quote;
4135             }
4136              
4137             # <<"HEREDOC"
4138             elsif (/\G ( << "([a-zA-Z_0-9]*)" ) /oxgc) {
4139 0           $slash = 'm//';
4140 0           my $here_quote = $1;
4141 0           my $delimiter = $2;
4142              
4143             # get here document
4144 0 0         if ($here_script eq '') {
4145 0           $here_script = CORE::substr $_, pos $_;
4146 0           $here_script =~ s/.*?\n//oxm;
4147             }
4148 0 0         if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4149 0           push @heredoc, e_heredoc($1) . qq{\n$delimiter\n};
4150 0           push @heredoc_delimiter, $delimiter;
4151             }
4152             else {
4153 0           die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF";
4154             }
4155 0           return $here_quote;
4156             }
4157              
4158             # <
4159             elsif (/\G ( << ([a-zA-Z_0-9]+) ) /oxgc) {
4160 0           $slash = 'm//';
4161 0           my $here_quote = $1;
4162 0           my $delimiter = $2;
4163              
4164             # get here document
4165 0 0         if ($here_script eq '') {
4166 0           $here_script = CORE::substr $_, pos $_;
4167 0           $here_script =~ s/.*?\n//oxm;
4168             }
4169 0 0         if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4170 0           push @heredoc, e_heredoc($1) . qq{\n$delimiter\n};
4171 0           push @heredoc_delimiter, $delimiter;
4172             }
4173             else {
4174 0           die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF";
4175             }
4176 0           return $here_quote;
4177             }
4178              
4179             # <<`HEREDOC`
4180             elsif (/\G ( << `([a-zA-Z_0-9]*)` ) /oxgc) {
4181 0           $slash = 'm//';
4182 0           my $here_quote = $1;
4183 0           my $delimiter = $2;
4184              
4185             # get here document
4186 0 0         if ($here_script eq '') {
4187 0           $here_script = CORE::substr $_, pos $_;
4188 0           $here_script =~ s/.*?\n//oxm;
4189             }
4190 0 0         if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4191 0           push @heredoc, e_heredoc($1) . qq{\n$delimiter\n};
4192 0           push @heredoc_delimiter, $delimiter;
4193             }
4194             else {
4195 0           die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF";
4196             }
4197 0           return $here_quote;
4198             }
4199              
4200             # <<= <=> <= < operator
4201             elsif (/\G ( <<= | <=> | <= | < ) (?= \s* [A-Za-z_0-9'"`\$\@\&\*\(\+\-] )/oxgc) {
4202 0           return $1;
4203             }
4204              
4205             #
4206             elsif (/\G (<[\$]?[A-Za-z_][A-Za-z_0-9]*>) /oxgc) {
4207 0           return $1;
4208             }
4209              
4210             # --- glob
4211              
4212             # avoid "Error: Runtime exception" of perl version 5.005_03
4213              
4214             elsif (/\G < ((?:[^>\0\a\e\f\n\r\t])+?) > /oxgc) {
4215 0           return 'Char::Ekoi8u::glob("' . $1 . '")';
4216             }
4217              
4218             # __DATA__
4219 0           elsif (/\G ^ ( __DATA__ \n .*) \z /oxmsgc) { return $1; }
4220              
4221             # __END__
4222 0           elsif (/\G ^ ( __END__ \n .*) \z /oxmsgc) { return $1; }
4223              
4224             # \cD Control-D
4225              
4226             # P.68 2.6.8. Other Literal Tokens
4227             # in Chapter 2: Bits and Pieces
4228             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
4229              
4230             # P.76 Other Literal Tokens
4231             # in Chapter 2: Bits and Pieces
4232             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
4233              
4234 0           elsif (/\G ( \cD .*) \z /oxmsgc) { return $1; }
4235              
4236             # \cZ Control-Z
4237 0           elsif (/\G ( \cZ .*) \z /oxmsgc) { return $1; }
4238              
4239             # any operator before div
4240             elsif (/\G (
4241             -- | \+\+ |
4242             [\)\}\]]
4243              
4244 0           ) /oxgc) { $slash = 'div'; return $1; }
  0            
4245              
4246             # yada-yada or triple-dot operator
4247             elsif (/\G (
4248             \.\.\.
4249              
4250 0           ) /oxgc) { $slash = 'm//'; return q{die('Unimplemented')}; }
  0            
4251              
4252             # any operator before m//
4253              
4254             # //, //= (defined-or)
4255              
4256             # P.164 Logical Operators
4257             # in Chapter 10: More Control Structures
4258             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
4259              
4260             # P.119 C-Style Logical (Short-Circuit) Operators
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             # ~~
4267              
4268             # P.221 The Smart Match Operator
4269             # in Chapter 15: Smart Matching and given-when
4270             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
4271              
4272             # P.112 Smartmatch Operator
4273             # in Chapter 3: Unary and Binary Operators
4274             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
4275              
4276             # (and so on)
4277              
4278             elsif (/\G (
4279              
4280             !~~ | !~ | != | ! |
4281             %= | % |
4282             &&= | && | &= | & |
4283             -= | -> | - |
4284             :\s*= |
4285             : |
4286             <<= | <=> | <= | < |
4287             == | => | =~ | = |
4288             >>= | >> | >= | > |
4289             \*\*= | \*\* | \*= | \* |
4290             \+= | \+ |
4291             \.\. | \.= | \. |
4292             \/\/= | \/\/ |
4293             \/= | \/ |
4294             \? |
4295             \\ |
4296             \^= | \^ |
4297             \b x= |
4298             \|\|= | \|\| | \|= | \| |
4299             ~~ | ~ |
4300             \b(?: and | cmp | eq | ge | gt | le | lt | ne | not | or | xor | x )\b |
4301             \b(?: print )\b |
4302              
4303             [,;\(\{\[]
4304              
4305 0           ) /oxgc) { $slash = 'm//'; return $1; }
  0            
4306              
4307             # other any character
4308 0           elsif (/\G ($q_char) /oxgc) { $slash = 'div'; return $1; }
  0            
4309              
4310             # system error
4311             else {
4312 0           die __FILE__, ": Oops, this shouldn't happen!";
4313             }
4314             }
4315              
4316             # escape KOI8-U string
4317             sub e_string {
4318 0     0 0   my($string) = @_;
4319 0           my $e_string = '';
4320              
4321 0           local $slash = 'm//';
4322              
4323             # P.1024 Appendix W.10 Multibyte Processing
4324             # of ISBN 1-56592-224-7 CJKV Information Processing
4325             # (and so on)
4326              
4327 0           my @char = $string =~ / \G (\\?(?:$q_char)) /oxmsg;
4328              
4329             # without { ... }
4330 0 0 0       if (not (grep(/\A \{ \z/xms, @char) and grep(/\A \} \z/xms, @char))) {
4331 0 0         if ($string !~ /<
4332 0           return $string;
4333             }
4334             }
4335              
4336             E_STRING_LOOP:
4337 0           while ($string !~ /\G \z/oxgc) {
4338 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          
4339             }
4340              
4341             # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> @{[Char::Ekoi8u::PREMATCH()]}
4342 0           elsif ($string =~ /\G ( \$` | \$\{`\} | \$ \s* PREMATCH \b | \$ \s* \{ \s* PREMATCH \s* \} | \$ \s* \{\^PREMATCH\} ) /oxmsgc) {
4343 0           $e_string .= q{Char::Ekoi8u::PREMATCH()};
4344 0           $slash = 'div';
4345             }
4346              
4347             # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> @{[Char::Ekoi8u::MATCH()]}
4348             elsif ($string =~ /\G ( \$& | \$\{&\} | \$ \s* MATCH \b | \$ \s* \{ \s* MATCH \s* \} | \$ \s* \{\^MATCH\} ) /oxmsgc) {
4349 0           $e_string .= q{Char::Ekoi8u::MATCH()};
4350 0           $slash = 'div';
4351             }
4352              
4353             # $', ${'} --> $', ${'}
4354             elsif ($string =~ /\G ( \$' | \$\{'\} ) /oxmsgc) {
4355 0           $e_string .= $1;
4356 0           $slash = 'div';
4357             }
4358              
4359             # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> @{[Char::Ekoi8u::POSTMATCH()]}
4360             elsif ($string =~ /\G ( \$ \s* POSTMATCH \b | \$ \s* \{ \s* POSTMATCH \s* \} | \$ \s* \{\^POSTMATCH\} ) /oxmsgc) {
4361 0           $e_string .= q{Char::Ekoi8u::POSTMATCH()};
4362 0           $slash = 'div';
4363             }
4364              
4365             # bareword
4366             elsif ($string =~ /\G ( \{ \s* (?: tr | index | rindex | reverse ) \s* \} ) /oxmsgc) {
4367 0           $e_string .= $1;
4368 0           $slash = 'div';
4369             }
4370              
4371             # $0 --> $0
4372             elsif ($string =~ /\G ( \$ 0 ) /oxmsgc) {
4373 0           $e_string .= $1;
4374 0           $slash = 'div';
4375             }
4376             elsif ($string =~ /\G ( \$ \{ \s* 0 \s* \} ) /oxmsgc) {
4377 0           $e_string .= $1;
4378 0           $slash = 'div';
4379             }
4380              
4381             # $$ --> $$
4382             elsif ($string =~ /\G ( \$ \$ ) (?![\w\{]) /oxmsgc) {
4383 0           $e_string .= $1;
4384 0           $slash = 'div';
4385             }
4386              
4387             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
4388             # $1, $2, $3 --> $1, $2, $3 otherwise
4389             elsif ($string =~ /\G \$ ([1-9][0-9]*) /oxmsgc) {
4390 0           $e_string .= e_capture($1);
4391 0           $slash = 'div';
4392             }
4393             elsif ($string =~ /\G \$ \{ \s* ([1-9][0-9]*) \s* \} /oxmsgc) {
4394 0           $e_string .= e_capture($1);
4395 0           $slash = 'div';
4396             }
4397              
4398             # $$foo[ ... ] --> $ $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.'->'.$2);
4401 0           $slash = 'div';
4402             }
4403              
4404             # $$foo{ ... } --> $ $foo->{ ... }
4405             elsif ($string =~ /\G \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) ( \{ .+? \} ) /oxmsgc) {
4406 0           $e_string .= e_capture($1.'->'.$2);
4407 0           $slash = 'div';
4408             }
4409              
4410             # $$foo
4411             elsif ($string =~ /\G \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) /oxmsgc) {
4412 0           $e_string .= e_capture($1);
4413 0           $slash = 'div';
4414             }
4415              
4416             # ${ foo }
4417             elsif ($string =~ /\G \$ \s* \{ ( \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* ) \} /oxmsgc) {
4418 0           $e_string .= '${' . $1 . '}';
4419 0           $slash = 'div';
4420             }
4421              
4422             # ${ ... }
4423             elsif ($string =~ /\G \$ \s* \{ \s* ( $qq_brace ) \s* \} /oxmsgc) {
4424 0           $e_string .= e_capture($1);
4425 0           $slash = 'div';
4426             }
4427              
4428             # variable or function
4429             # $ @ % & * $ #
4430             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) {
4431 0           $e_string .= $1;
4432 0           $slash = 'div';
4433             }
4434             # $ $ $ $ $ $ $ $ $ $ $ $ $ $
4435             # $ @ # \ ' " / ? ( ) [ ] < >
4436             elsif ($string =~ /\G ( \$[\$\@\#\\\'\"\/\?\(\)\[\]\<\>] ) /oxmsgc) {
4437 0           $e_string .= $1;
4438 0           $slash = 'div';
4439             }
4440              
4441             # subroutines of package Char::Ekoi8u
4442 0           elsif ($string =~ /\G \b (CORE:: | ->[ ]* (?: atan2 | [a-z]{2,})) \b /oxgc) { $e_string .= $1; $slash = 'm//'; }
  0            
4443 0           elsif ($string =~ /\G \b Char::KOI8U::eval (?= \s* \{ ) /oxgc) { $e_string .= 'eval'; $slash = 'm//'; }
  0            
4444 0           elsif ($string =~ /\G \b Char::KOI8U::eval \b /oxgc) { $e_string .= 'eval Char::KOI8U::escape'; $slash = 'm//'; }
  0            
4445 0           elsif ($string =~ /\G \b bytes::substr \b /oxgc) { $e_string .= 'substr'; $slash = 'm//'; }
  0            
4446 0           elsif ($string =~ /\G \b chop \b /oxgc) { $e_string .= 'Char::Ekoi8u::chop'; $slash = 'm//'; }
  0            
4447 0           elsif ($string =~ /\G \b bytes::index \b /oxgc) { $e_string .= 'index'; $slash = 'm//'; }
  0            
4448 0           elsif ($string =~ /\G \b Char::KOI8U::index \b /oxgc) { $e_string .= 'Char::KOI8U::index'; $slash = 'm//'; }
  0            
4449 0           elsif ($string =~ /\G \b index \b /oxgc) { $e_string .= 'Char::Ekoi8u::index'; $slash = 'm//'; }
  0            
4450 0           elsif ($string =~ /\G \b bytes::rindex \b /oxgc) { $e_string .= 'rindex'; $slash = 'm//'; }
  0            
4451 0           elsif ($string =~ /\G \b Char::KOI8U::rindex \b /oxgc) { $e_string .= 'Char::KOI8U::rindex'; $slash = 'm//'; }
  0            
4452 0           elsif ($string =~ /\G \b rindex \b /oxgc) { $e_string .= 'Char::Ekoi8u::rindex'; $slash = 'm//'; }
  0            
4453 0           elsif ($string =~ /\G \b lc (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Char::Ekoi8u::lc'; $slash = 'm//'; }
  0            
4454 0           elsif ($string =~ /\G \b lcfirst (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Char::Ekoi8u::lcfirst'; $slash = 'm//'; }
  0            
4455 0           elsif ($string =~ /\G \b uc (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Char::Ekoi8u::uc'; $slash = 'm//'; }
  0            
4456 0           elsif ($string =~ /\G \b ucfirst (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Char::Ekoi8u::ucfirst'; $slash = 'm//'; }
  0            
4457 0           elsif ($string =~ /\G \b fc (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Char::Ekoi8u::fc'; $slash = 'm//'; }
  0            
4458              
4459             # "-s '' ..." means file test "-s 'filename' ..." (not means "- s/// ...")
4460 0           elsif ($string =~ /\G -s \s+ \s* (\") ((?:$qq_char)+?) (\") /oxgc) { $e_string .= '-s ' . e_qq('', $1,$3,$2); $slash = 'm//'; }
  0            
4461 0           elsif ($string =~ /\G -s \s+ qq \s* (\#) ((?:$qq_char)+?) (\#) /oxgc) { $e_string .= '-s ' . e_qq('qq',$1,$3,$2); $slash = 'm//'; }
  0            
4462 0           elsif ($string =~ /\G -s \s+ qq \s* (\() ((?:$qq_paren)+?) (\)) /oxgc) { $e_string .= '-s ' . e_qq('qq',$1,$3,$2); $slash = 'm//'; }
  0            
4463 0           elsif ($string =~ /\G -s \s+ qq \s* (\{) ((?:$qq_brace)+?) (\}) /oxgc) { $e_string .= '-s ' . e_qq('qq',$1,$3,$2); $slash = 'm//'; }
  0            
4464 0           elsif ($string =~ /\G -s \s+ qq \s* (\[) ((?:$qq_bracket)+?) (\]) /oxgc) { $e_string .= '-s ' . e_qq('qq',$1,$3,$2); $slash = 'm//'; }
  0            
4465 0           elsif ($string =~ /\G -s \s+ qq \s* (\<) ((?:$qq_angle)+?) (\>) /oxgc) { $e_string .= '-s ' . e_qq('qq',$1,$3,$2); $slash = 'm//'; }
  0            
4466 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            
4467              
4468 0           elsif ($string =~ /\G -s \s+ \s* (\') ((?:\\\'|\\\\|$q_char)+?) (\') /oxgc) { $e_string .= '-s ' . e_q ('', $1,$3,$2); $slash = 'm//'; }
  0            
4469 0           elsif ($string =~ /\G -s \s+ q \s* (\#) ((?:\\\#|\\\\|$q_char)+?) (\#) /oxgc) { $e_string .= '-s ' . e_q ('q', $1,$3,$2); $slash = 'm//'; }
  0            
4470 0           elsif ($string =~ /\G -s \s+ q \s* (\() ((?:\\\)|\\\\|$q_paren)+?) (\)) /oxgc) { $e_string .= '-s ' . e_q ('q', $1,$3,$2); $slash = 'm//'; }
  0            
4471 0           elsif ($string =~ /\G -s \s+ q \s* (\{) ((?:\\\}|\\\\|$q_brace)+?) (\}) /oxgc) { $e_string .= '-s ' . e_q ('q', $1,$3,$2); $slash = 'm//'; }
  0            
4472 0           elsif ($string =~ /\G -s \s+ q \s* (\[) ((?:\\\]|\\\\|$q_bracket)+?) (\]) /oxgc) { $e_string .= '-s ' . e_q ('q', $1,$3,$2); $slash = 'm//'; }
  0            
4473 0           elsif ($string =~ /\G -s \s+ q \s* (\<) ((?:\\\>|\\\\|$q_angle)+?) (\>) /oxgc) { $e_string .= '-s ' . e_q ('q', $1,$3,$2); $slash = 'm//'; }
  0            
4474 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            
4475              
4476             elsif ($string =~ /\G -s \s* (\$ \w+(?: ::\w+)* (?: (?: ->)? (?: [\$\@\%\&\*]\* | \$\#\* | \( (?:$qq_paren)*? \) | [\@\%\*]? \{ (?:$qq_brace)+? \} | [\@\%]? \[ (?:$qq_bracket)+? \] ) )*) /oxgc)
4477 0           { $e_string .= "-s $1"; $slash = 'm//'; }
  0            
4478 0           elsif ($string =~ /\G -s \s* \( ((?:$qq_paren)*?) \) /oxgc) { $e_string .= "-s ($1)"; $slash = 'm//'; }
  0            
4479 0           elsif ($string =~ /\G -s (?= \s+ [a-z]+) /oxgc) { $e_string .= '-s'; $slash = 'm//'; }
  0            
4480 0           elsif ($string =~ /\G -s \s+ (\w+) /oxgc) { $e_string .= "-s $1"; $slash = 'm//'; }
  0            
4481              
4482 0           elsif ($string =~ /\G \b bytes::length (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'length'; $slash = 'm//'; }
  0            
4483 0           elsif ($string =~ /\G \b bytes::chr (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'chr'; $slash = 'm//'; }
  0            
4484 0           elsif ($string =~ /\G \b chr (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Char::Ekoi8u::chr'; $slash = 'm//'; }
  0            
4485 0           elsif ($string =~ /\G \b bytes::ord (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'ord'; $slash = 'div'; }
  0            
4486 0           elsif ($string =~ /\G \b ord (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $e_string .= $function_ord; $slash = 'div'; }
  0            
4487 0           elsif ($string =~ /\G \b glob (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Char::Ekoi8u::glob'; $slash = 'm//'; }
  0            
4488 0           elsif ($string =~ /\G \b lc \b /oxgc) { $e_string .= 'Char::Ekoi8u::lc_'; $slash = 'm//'; }
  0            
4489 0           elsif ($string =~ /\G \b lcfirst \b /oxgc) { $e_string .= 'Char::Ekoi8u::lcfirst_'; $slash = 'm//'; }
  0            
4490 0           elsif ($string =~ /\G \b uc \b /oxgc) { $e_string .= 'Char::Ekoi8u::uc_'; $slash = 'm//'; }
  0            
4491 0           elsif ($string =~ /\G \b ucfirst \b /oxgc) { $e_string .= 'Char::Ekoi8u::ucfirst_'; $slash = 'm//'; }
  0            
4492 0           elsif ($string =~ /\G \b fc \b /oxgc) { $e_string .= 'Char::Ekoi8u::fc_'; $slash = 'm//'; }
  0            
4493 0           elsif ($string =~ /\G -s \b /oxgc) { $e_string .= '-s '; $slash = 'm//'; }
  0            
4494              
4495 0           elsif ($string =~ /\G \b bytes::length \b /oxgc) { $e_string .= 'length'; $slash = 'm//'; }
  0            
4496 0           elsif ($string =~ /\G \b bytes::chr \b /oxgc) { $e_string .= 'chr'; $slash = 'm//'; }
  0            
4497 0           elsif ($string =~ /\G \b chr \b /oxgc) { $e_string .= 'Char::Ekoi8u::chr_'; $slash = 'm//'; }
  0            
4498 0           elsif ($string =~ /\G \b bytes::ord \b /oxgc) { $e_string .= 'ord'; $slash = 'div'; }
  0            
4499 0           elsif ($string =~ /\G \b ord \b /oxgc) { $e_string .= $function_ord_; $slash = 'div'; }
  0            
4500 0           elsif ($string =~ /\G \b glob \b /oxgc) { $e_string .= 'Char::Ekoi8u::glob_'; $slash = 'm//'; }
  0            
4501 0           elsif ($string =~ /\G \b reverse \b /oxgc) { $e_string .= $function_reverse; $slash = 'm//'; }
  0            
4502 0           elsif ($string =~ /\G \b getc \b /oxgc) { $e_string .= $function_getc; $slash = 'm//'; }
  0            
4503             # split
4504             elsif ($string =~ /\G \b (split) \b (?! \s* => ) /oxgc) {
4505 0           $slash = 'm//';
4506              
4507 0           my $e = '';
4508 0           while ($string =~ /\G ( \s+ | \( | \#.* ) /oxgc) {
4509 0           $e .= $1;
4510             }
4511              
4512             # end of split
4513 0 0         if ($string =~ /\G (?= [,;\)\}\]] ) /oxgc) { return 'Char::Ekoi8u::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          
4514              
4515             # split scalar value
4516 0           elsif ($string =~ /\G ( [\$\@\&\*] $qq_scalar ) /oxgc) { $e_string .= 'Char::Ekoi8u::split' . $e . e_string($1); next E_STRING_LOOP; }
  0            
4517              
4518             # split literal space
4519 0           elsif ($string =~ /\G \b qq (\#) [ ] (\#) /oxgc) { $e_string .= 'Char::Ekoi8u::split' . $e . qq {qq$1 $2}; next E_STRING_LOOP; }
  0            
4520 0           elsif ($string =~ /\G \b qq (\s*) (\() [ ] (\)) /oxgc) { $e_string .= 'Char::Ekoi8u::split' . $e . qq{$1qq$2 $3}; next E_STRING_LOOP; }
  0            
4521 0           elsif ($string =~ /\G \b qq (\s*) (\{) [ ] (\}) /oxgc) { $e_string .= 'Char::Ekoi8u::split' . $e . qq{$1qq$2 $3}; next E_STRING_LOOP; }
  0            
4522 0           elsif ($string =~ /\G \b qq (\s*) (\[) [ ] (\]) /oxgc) { $e_string .= 'Char::Ekoi8u::split' . $e . qq{$1qq$2 $3}; next E_STRING_LOOP; }
  0            
4523 0           elsif ($string =~ /\G \b qq (\s*) (\<) [ ] (\>) /oxgc) { $e_string .= 'Char::Ekoi8u::split' . $e . qq{$1qq$2 $3}; next E_STRING_LOOP; }
  0            
4524 0           elsif ($string =~ /\G \b qq (\s*) (\S) [ ] (\2) /oxgc) { $e_string .= 'Char::Ekoi8u::split' . $e . qq{$1qq$2 $3}; next E_STRING_LOOP; }
  0            
4525 0           elsif ($string =~ /\G \b q (\#) [ ] (\#) /oxgc) { $e_string .= 'Char::Ekoi8u::split' . $e . qq {q$1 $2}; next E_STRING_LOOP; }
  0            
4526 0           elsif ($string =~ /\G \b q (\s*) (\() [ ] (\)) /oxgc) { $e_string .= 'Char::Ekoi8u::split' . $e . qq {$1q$2 $3}; next E_STRING_LOOP; }
  0            
4527 0           elsif ($string =~ /\G \b q (\s*) (\{) [ ] (\}) /oxgc) { $e_string .= 'Char::Ekoi8u::split' . $e . qq {$1q$2 $3}; next E_STRING_LOOP; }
  0            
4528 0           elsif ($string =~ /\G \b q (\s*) (\[) [ ] (\]) /oxgc) { $e_string .= 'Char::Ekoi8u::split' . $e . qq {$1q$2 $3}; next E_STRING_LOOP; }
  0            
4529 0           elsif ($string =~ /\G \b q (\s*) (\<) [ ] (\>) /oxgc) { $e_string .= 'Char::Ekoi8u::split' . $e . qq {$1q$2 $3}; next E_STRING_LOOP; }
  0            
4530 0           elsif ($string =~ /\G \b q (\s*) (\S) [ ] (\2) /oxgc) { $e_string .= 'Char::Ekoi8u::split' . $e . qq {$1q$2 $3}; next E_STRING_LOOP; }
  0            
4531 0           elsif ($string =~ /\G ' [ ] ' /oxgc) { $e_string .= 'Char::Ekoi8u::split' . $e . qq {' '}; next E_STRING_LOOP; }
  0            
4532 0           elsif ($string =~ /\G " [ ] " /oxgc) { $e_string .= 'Char::Ekoi8u::split' . $e . qq {" "}; next E_STRING_LOOP; }
  0            
4533              
4534             # split qq//
4535             elsif ($string =~ /\G \b (qq) \b /oxgc) {
4536 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            
4537             else {
4538 0           while ($string !~ /\G \z/oxgc) {
4539 0 0         if ($string =~ /\G (\s+|\#.*) /oxgc) { $e_string .= $e . $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
4540 0           elsif ($string =~ /\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { $e_string .= e_split($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # qq ( ) --> qr ( )
  0            
4541 0           elsif ($string =~ /\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { $e_string .= e_split($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # qq { } --> qr { }
  0            
4542 0           elsif ($string =~ /\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { $e_string .= e_split($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # qq [ ] --> qr [ ]
  0            
4543 0           elsif ($string =~ /\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { $e_string .= e_split($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # qq < > --> qr < >
  0            
4544 0           elsif ($string =~ /\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) /oxgc) { $e_string .= e_split($e.'qr','{','}',$2,''); next E_STRING_LOOP; } # qq | | --> qr { }
  0            
4545 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            
4546             }
4547 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
4548             }
4549             }
4550              
4551             # split qr//
4552             elsif ($string =~ /\G \b (qr) \b /oxgc) {
4553 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            
4554             else {
4555 0           while ($string !~ /\G \z/oxgc) {
4556 0 0         if ($string =~ /\G (\s+|\#.*) /oxgc) { $e_string .= $e . $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
4557 0           elsif ($string =~ /\G (\() ((?:$qq_paren)*?) (\)) ([imosxpadlubB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # qr ( )
  0            
4558 0           elsif ($string =~ /\G (\{) ((?:$qq_brace)*?) (\}) ([imosxpadlubB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # qr { }
  0            
4559 0           elsif ($string =~ /\G (\[) ((?:$qq_bracket)*?) (\]) ([imosxpadlubB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # qr [ ]
  0            
4560 0           elsif ($string =~ /\G (\<) ((?:$qq_angle)*?) (\>) ([imosxpadlubB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # qr < >
  0            
4561 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            
4562 0           elsif ($string =~ /\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ([imosxpadlubB]*) /oxgc) { $e_string .= e_split ($e.'qr','{','}',$2,$4); next E_STRING_LOOP; } # qr | | --> qr { }
  0            
4563 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            
4564             }
4565 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
4566             }
4567             }
4568              
4569             # split q//
4570             elsif ($string =~ /\G \b (q) \b /oxgc) {
4571 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            
4572             else {
4573 0           while ($string !~ /\G \z/oxgc) {
4574 0 0         if ($string =~ /\G (\s+|\#.*) /oxgc) { $e_string .= $e . $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
4575 0           elsif ($string =~ /\G (\() ((?:\\\\|\\\)|\\\(|$q_paren)*?) (\)) /oxgc) { $e_string .= e_split_q($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # q ( ) --> qr ( )
  0            
4576 0           elsif ($string =~ /\G (\{) ((?:\\\\|\\\}|\\\{|$q_brace)*?) (\}) /oxgc) { $e_string .= e_split_q($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # q { } --> qr { }
  0            
4577 0           elsif ($string =~ /\G (\[) ((?:\\\\|\\\]|\\\[|$q_bracket)*?) (\]) /oxgc) { $e_string .= e_split_q($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # q [ ] --> qr [ ]
  0            
4578 0           elsif ($string =~ /\G (\<) ((?:\\\\|\\\>|\\\<|$q_angle)*?) (\>) /oxgc) { $e_string .= e_split_q($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # q < > --> qr < >
  0            
4579 0           elsif ($string =~ /\G ([*\-:?\\^|]) ((?:$q_char)*?) (\1) /oxgc) { $e_string .= e_split_q($e.'qr','{','}',$2,''); next E_STRING_LOOP; } # q | | --> qr { }
  0            
4580 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            
4581             }
4582 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
4583             }
4584             }
4585              
4586             # split m//
4587             elsif ($string =~ /\G \b (m) \b /oxgc) {
4588 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            
4589             else {
4590 0           while ($string !~ /\G \z/oxgc) {
4591 0 0         if ($string =~ /\G (\s+|\#.*) /oxgc) { $e_string .= $e . $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
4592 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            
4593 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            
4594 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            
4595 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            
4596 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            
4597 0           elsif ($string =~ /\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ([cgimosxpadlubB]*) /oxgc) { $e_string .= e_split ($e.'qr','{','}',$2,$4); next E_STRING_LOOP; } # m | | --> qr { }
  0            
4598 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            
4599             }
4600 0           die __FILE__, ": Search pattern not terminated";
4601             }
4602             }
4603              
4604             # split ''
4605             elsif ($string =~ /\G (\') /oxgc) {
4606 0           my $q_string = '';
4607 0           while ($string !~ /\G \z/oxgc) {
4608 0 0         if ($string =~ /\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0          
    0          
    0          
4609 0           elsif ($string =~ /\G (\\\') /oxgc) { $q_string .= $1; } # splitqr'' --> split qr''
4610 0           elsif ($string =~ /\G \' /oxgc) { $e_string .= e_split_q($e.q{ qr},"'","'",$q_string,''); next E_STRING_LOOP; } # ' ' --> qr ' '
  0            
4611 0           elsif ($string =~ /\G ($q_char) /oxgc) { $q_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 $qq_string = '';
4619 0           while ($string !~ /\G \z/oxgc) {
4620 0 0         if ($string =~ /\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0          
    0          
    0          
4621 0           elsif ($string =~ /\G (\\\") /oxgc) { $qq_string .= $1; } # splitqr"" --> split qr""
4622 0           elsif ($string =~ /\G \" /oxgc) { $e_string .= e_split($e.q{ qr},'"','"',$qq_string,''); next E_STRING_LOOP; } # " " --> qr " "
  0            
4623 0           elsif ($string =~ /\G ($q_char) /oxgc) { $qq_string .= $1; }
4624             }
4625 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
4626             }
4627              
4628             # split //
4629             elsif ($string =~ /\G (\/) /oxgc) {
4630 0           my $regexp = '';
4631 0           while ($string !~ /\G \z/oxgc) {
4632 0 0         if ($string =~ /\G (\\\\) /oxgc) { $regexp .= $1; }
  0 0          
    0          
    0          
4633 0           elsif ($string =~ /\G (\\\/) /oxgc) { $regexp .= $1; } # splitqr// --> split qr//
4634 0           elsif ($string =~ /\G \/ ([cgimosxpadlubB]*) /oxgc) { $e_string .= e_split($e.q{ qr}, '/','/',$regexp,$1); next E_STRING_LOOP; } # / / --> qr / /
  0            
4635 0           elsif ($string =~ /\G ($q_char) /oxgc) { $regexp .= $1; }
4636             }
4637 0           die __FILE__, ": Search pattern not terminated";
4638             }
4639             }
4640              
4641             # qq//
4642             elsif ($string =~ /\G \b (qq) \b /oxgc) {
4643 0           my $ope = $1;
4644 0 0         if ($string =~ /\G (\#) ((?:$qq_char)*?) (\#) /oxgc) { # qq# #
4645 0           $e_string .= e_qq($ope,$1,$3,$2);
4646             }
4647             else {
4648 0           my $e = '';
4649 0           while ($string !~ /\G \z/oxgc) {
4650 0 0         if ($string =~ /\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
4651 0           elsif ($string =~ /\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qq ( )
  0            
4652 0           elsif ($string =~ /\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qq { }
  0            
4653 0           elsif ($string =~ /\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qq [ ]
  0            
4654 0           elsif ($string =~ /\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qq < >
  0            
4655 0           elsif ($string =~ /\G (\S) ((?:$qq_char)*?) (\1) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qq * *
  0            
4656             }
4657 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
4658             }
4659             }
4660              
4661             # qx//
4662             elsif ($string =~ /\G \b (qx) \b /oxgc) {
4663 0           my $ope = $1;
4664 0 0         if ($string =~ /\G (\#) ((?:$qq_char)*?) (\#) /oxgc) { # qx# #
4665 0           $e_string .= e_qq($ope,$1,$3,$2);
4666             }
4667             else {
4668 0           my $e = '';
4669 0           while ($string !~ /\G \z/oxgc) {
4670 0 0         if ($string =~ /\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
4671 0           elsif ($string =~ /\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qx ( )
  0            
4672 0           elsif ($string =~ /\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qx { }
  0            
4673 0           elsif ($string =~ /\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qx [ ]
  0            
4674 0           elsif ($string =~ /\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qx < >
  0            
4675 0           elsif ($string =~ /\G (\') ((?:$qq_char)*?) (\') /oxgc) { $e_string .= $e . e_q ($ope,$1,$3,$2); next E_STRING_LOOP; } # qx ' '
  0            
4676 0           elsif ($string =~ /\G (\S) ((?:$qq_char)*?) (\1) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qx * *
  0            
4677             }
4678 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
4679             }
4680             }
4681              
4682             # q//
4683             elsif ($string =~ /\G \b (q) \b /oxgc) {
4684 0           my $ope = $1;
4685 0 0         if ($string =~ /\G (\#) ((?:\\\#|\\\\|$q_char)*?) (\#) /oxgc) { # q# #
4686 0           $e_string .= e_q($ope,$1,$3,$2);
4687             }
4688             else {
4689 0           my $e = '';
4690 0           while ($string !~ /\G \z/oxgc) {
4691 0 0         if ($string =~ /\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
4692 0           elsif ($string =~ /\G (\() ((?:\\\\|\\\)|\\\(|$q_paren)*?) (\)) /oxgc) { $e_string .= $e . e_q($ope,$1,$3,$2); next E_STRING_LOOP; } # q ( )
  0            
4693 0           elsif ($string =~ /\G (\{) ((?:\\\\|\\\}|\\\{|$q_brace)*?) (\}) /oxgc) { $e_string .= $e . e_q($ope,$1,$3,$2); next E_STRING_LOOP; } # q { }
  0            
4694 0           elsif ($string =~ /\G (\[) ((?:\\\\|\\\]|\\\[|$q_bracket)*?) (\]) /oxgc) { $e_string .= $e . e_q($ope,$1,$3,$2); next E_STRING_LOOP; } # q [ ]
  0            
4695 0           elsif ($string =~ /\G (\<) ((?:\\\\|\\\>|\\\<|$q_angle)*?) (\>) /oxgc) { $e_string .= $e . e_q($ope,$1,$3,$2); next E_STRING_LOOP; } # q < >
  0            
4696 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            
4697             }
4698 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
4699             }
4700             }
4701              
4702             # ''
4703 0           elsif ($string =~ /\G (?
4704              
4705             # ""
4706 0           elsif ($string =~ /\G (\") ((?:$qq_char)*?) (\") /oxgc) { $e_string .= e_qq('',$1,$3,$2); }
4707              
4708             # ``
4709 0           elsif ($string =~ /\G (\`) ((?:$qq_char)*?) (\`) /oxgc) { $e_string .= e_qq('',$1,$3,$2); }
4710              
4711             # <<= <=> <= < operator
4712             elsif ($string =~ /\G ( <<= | <=> | <= | < ) (?= \s* [A-Za-z_0-9'"`\$\@\&\*\(\+\-] )/oxgc)
4713 0           { $e_string .= $1; }
4714              
4715             #
4716 0           elsif ($string =~ /\G (<[\$]?[A-Za-z_][A-Za-z_0-9]*>) /oxgc) { $e_string .= $1; }
4717              
4718             # --- glob
4719             elsif ($string =~ /\G < ((?:$q_char)+?) > /oxgc) {
4720 0           $e_string .= 'Char::Ekoi8u::glob("' . $1 . '")';
4721             }
4722              
4723             # << (bit shift) --- not here document
4724 0           elsif ($string =~ /\G ( << \s* ) (?= [0-9\$\@\&] ) /oxgc) { $slash = 'm//'; $e_string .= $1; }
  0            
4725              
4726             # <<'HEREDOC'
4727             elsif ($string =~ /\G ( << '([a-zA-Z_0-9]*)' ) /oxgc) {
4728 0           $slash = 'm//';
4729 0           my $here_quote = $1;
4730 0           my $delimiter = $2;
4731              
4732             # get here document
4733 0 0         if ($here_script eq '') {
4734 0           $here_script = CORE::substr $_, pos $_;
4735 0           $here_script =~ s/.*?\n//oxm;
4736             }
4737 0 0         if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4738 0           push @heredoc, $1 . qq{\n$delimiter\n};
4739 0           push @heredoc_delimiter, $delimiter;
4740             }
4741             else {
4742 0           die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF";
4743             }
4744 0           $e_string .= $here_quote;
4745             }
4746              
4747             # <<\HEREDOC
4748             elsif ($string =~ /\G ( << \\([a-zA-Z_0-9]+) ) /oxgc) {
4749 0           $slash = 'm//';
4750 0           my $here_quote = $1;
4751 0           my $delimiter = $2;
4752              
4753             # get here document
4754 0 0         if ($here_script eq '') {
4755 0           $here_script = CORE::substr $_, pos $_;
4756 0           $here_script =~ s/.*?\n//oxm;
4757             }
4758 0 0         if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4759 0           push @heredoc, $1 . qq{\n$delimiter\n};
4760 0           push @heredoc_delimiter, $delimiter;
4761             }
4762             else {
4763 0           die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF";
4764             }
4765 0           $e_string .= $here_quote;
4766             }
4767              
4768             # <<"HEREDOC"
4769             elsif ($string =~ /\G ( << "([a-zA-Z_0-9]*)" ) /oxgc) {
4770 0           $slash = 'm//';
4771 0           my $here_quote = $1;
4772 0           my $delimiter = $2;
4773              
4774             # get here document
4775 0 0         if ($here_script eq '') {
4776 0           $here_script = CORE::substr $_, pos $_;
4777 0           $here_script =~ s/.*?\n//oxm;
4778             }
4779 0 0         if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4780 0           push @heredoc, e_heredoc($1) . qq{\n$delimiter\n};
4781 0           push @heredoc_delimiter, $delimiter;
4782             }
4783             else {
4784 0           die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF";
4785             }
4786 0           $e_string .= $here_quote;
4787             }
4788              
4789             # <
4790             elsif ($string =~ /\G ( << ([a-zA-Z_0-9]+) ) /oxgc) {
4791 0           $slash = 'm//';
4792 0           my $here_quote = $1;
4793 0           my $delimiter = $2;
4794              
4795             # get here document
4796 0 0         if ($here_script eq '') {
4797 0           $here_script = CORE::substr $_, pos $_;
4798 0           $here_script =~ s/.*?\n//oxm;
4799             }
4800 0 0         if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4801 0           push @heredoc, e_heredoc($1) . qq{\n$delimiter\n};
4802 0           push @heredoc_delimiter, $delimiter;
4803             }
4804             else {
4805 0           die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF";
4806             }
4807 0           $e_string .= $here_quote;
4808             }
4809              
4810             # <<`HEREDOC`
4811             elsif ($string =~ /\G ( << `([a-zA-Z_0-9]*)` ) /oxgc) {
4812 0           $slash = 'm//';
4813 0           my $here_quote = $1;
4814 0           my $delimiter = $2;
4815              
4816             # get here document
4817 0 0         if ($here_script eq '') {
4818 0           $here_script = CORE::substr $_, pos $_;
4819 0           $here_script =~ s/.*?\n//oxm;
4820             }
4821 0 0         if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4822 0           push @heredoc, e_heredoc($1) . qq{\n$delimiter\n};
4823 0           push @heredoc_delimiter, $delimiter;
4824             }
4825             else {
4826 0           die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF";
4827             }
4828 0           $e_string .= $here_quote;
4829             }
4830              
4831             # any operator before div
4832             elsif ($string =~ /\G (
4833             -- | \+\+ |
4834             [\)\}\]]
4835              
4836 0           ) /oxgc) { $slash = 'div'; $e_string .= $1; }
  0            
4837              
4838             # yada-yada or triple-dot operator
4839             elsif ($string =~ /\G (
4840             \.\.\.
4841              
4842 0           ) /oxgc) { $slash = 'm//'; $e_string .= q{die('Unimplemented')}; }
  0            
4843              
4844             # any operator before m//
4845             elsif ($string =~ /\G (
4846              
4847             !~~ | !~ | != | ! |
4848             %= | % |
4849             &&= | && | &= | & |
4850             -= | -> | - |
4851             :\s*= |
4852             : |
4853             <<= | <=> | <= | < |
4854             == | => | =~ | = |
4855             >>= | >> | >= | > |
4856             \*\*= | \*\* | \*= | \* |
4857             \+= | \+ |
4858             \.\. | \.= | \. |
4859             \/\/= | \/\/ |
4860             \/= | \/ |
4861             \? |
4862             \\ |
4863             \^= | \^ |
4864             \b x= |
4865             \|\|= | \|\| | \|= | \| |
4866             ~~ | ~ |
4867             \b(?: and | cmp | eq | ge | gt | le | lt | ne | not | or | xor | x )\b |
4868             \b(?: print )\b |
4869              
4870             [,;\(\{\[]
4871              
4872 0           ) /oxgc) { $slash = 'm//'; $e_string .= $1; }
  0            
4873              
4874             # other any character
4875 0           elsif ($string =~ /\G ($q_char) /oxgc) { $e_string .= $1; }
4876              
4877             # system error
4878             else {
4879 0           die __FILE__, ": Oops, this shouldn't happen!";
4880             }
4881             }
4882              
4883 0           return $e_string;
4884             }
4885              
4886             #
4887             # character class
4888             #
4889             sub character_class {
4890 0     0 0   my($char,$modifier) = @_;
4891              
4892 0 0         if ($char eq '.') {
4893 0 0         if ($modifier =~ /s/) {
4894 0           return '${Char::Ekoi8u::dot_s}';
4895             }
4896             else {
4897 0           return '${Char::Ekoi8u::dot}';
4898             }
4899             }
4900             else {
4901 0           return Char::Ekoi8u::classic_character_class($char);
4902             }
4903             }
4904              
4905             #
4906             # escape capture ($1, $2, $3, ...)
4907             #
4908             sub e_capture {
4909              
4910 0     0 0   return join '', '${', $_[0], '}';
4911             }
4912              
4913             #
4914             # escape transliteration (tr/// or y///)
4915             #
4916             sub e_tr {
4917 0     0 0   my($variable,$charclass,$e,$charclass2,$modifier) = @_;
4918 0           my $e_tr = '';
4919 0   0       $modifier ||= '';
4920              
4921 0           $slash = 'div';
4922              
4923             # quote character class 1
4924 0           $charclass = q_tr($charclass);
4925              
4926             # quote character class 2
4927 0           $charclass2 = q_tr($charclass2);
4928              
4929             # /b /B modifier
4930 0 0         if ($modifier =~ tr/bB//d) {
4931 0 0         if ($variable eq '') {
4932 0           $e_tr = qq{tr$charclass$e$charclass2$modifier};
4933             }
4934             else {
4935 0           $e_tr = qq{$variable${bind_operator}tr$charclass$e$charclass2$modifier};
4936             }
4937             }
4938             else {
4939 0 0         if ($variable eq '') {
4940 0           $e_tr = qq{Char::Ekoi8u::tr(\$_,' =~ ',$charclass,$e$charclass2,'$modifier')};
4941             }
4942             else {
4943 0           $e_tr = qq{Char::Ekoi8u::tr($variable,'$bind_operator',$charclass,$e$charclass2,'$modifier')};
4944             }
4945             }
4946              
4947             # clear tr/// variable
4948 0           $tr_variable = '';
4949 0           $bind_operator = '';
4950              
4951 0           return $e_tr;
4952             }
4953              
4954             #
4955             # quote for escape transliteration (tr/// or y///)
4956             #
4957             sub q_tr {
4958 0     0 0   my($charclass) = @_;
4959              
4960             # quote character class
4961 0 0         if ($charclass !~ /'/oxms) {
    0          
    0          
    0          
    0          
    0          
4962 0           return e_q('', "'", "'", $charclass); # --> q' '
4963             }
4964             elsif ($charclass !~ /\//oxms) {
4965 0           return e_q('q', '/', '/', $charclass); # --> q/ /
4966             }
4967             elsif ($charclass !~ /\#/oxms) {
4968 0           return e_q('q', '#', '#', $charclass); # --> q# #
4969             }
4970             elsif ($charclass !~ /[\<\>]/oxms) {
4971 0           return e_q('q', '<', '>', $charclass); # --> q< >
4972             }
4973             elsif ($charclass !~ /[\(\)]/oxms) {
4974 0           return e_q('q', '(', ')', $charclass); # --> q( )
4975             }
4976             elsif ($charclass !~ /[\{\}]/oxms) {
4977 0           return e_q('q', '{', '}', $charclass); # --> q{ }
4978             }
4979             else {
4980 0           for my $char (qw( ! " $ % & * + . : = ? @ ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
4981 0 0         if ($charclass !~ /\Q$char\E/xms) {
4982 0           return e_q('q', $char, $char, $charclass);
4983             }
4984             }
4985             }
4986              
4987 0           return e_q('q', '{', '}', $charclass);
4988             }
4989              
4990             #
4991             # escape q string (q//, '')
4992             #
4993             sub e_q {
4994 0     0 0   my($ope,$delimiter,$end_delimiter,$string) = @_;
4995              
4996 0           $slash = 'div';
4997              
4998 0           return join '', $ope, $delimiter, $string, $end_delimiter;
4999             }
5000              
5001             #
5002             # escape qq string (qq//, "", qx//, ``)
5003             #
5004             sub e_qq {
5005 0     0 0   my($ope,$delimiter,$end_delimiter,$string) = @_;
5006              
5007 0           $slash = 'div';
5008              
5009 0           my $left_e = 0;
5010 0           my $right_e = 0;
5011 0           my @char = $string =~ /\G(
5012             \\o\{ [0-7]+ \} |
5013             \\x\{ [0-9A-Fa-f]+ \} |
5014             \\N\{ [^0-9\}][^\}]* \} |
5015             \$` | \$\{`\} | \$ \s* PREMATCH | \$ \s* \{ \s* PREMATCH \s* \} | \$ \s* \{\^PREMATCH\} |
5016             \$& | \$\{&\} | \$ \s* MATCH | \$ \s* \{ \s* MATCH \s* \} | \$ \s* \{\^MATCH\} |
5017             \$ \s* POSTMATCH | \$ \s* \{ \s* POSTMATCH \s* \} | \$ \s* \{\^POSTMATCH\} |
5018             \$ \s* \d+ |
5019             \$ \s* \{ \s* \d+ \s* \} |
5020             \$ \$ (?![\w\{]) |
5021             \$ \s* \$ \s* $qq_variable |
5022             \\?(?:$q_char)
5023             )/oxmsg;
5024              
5025 0           for (my $i=0; $i <= $#char; $i++) {
5026              
5027             # "\L\u" --> "\u\L"
5028 0 0 0       if (($char[$i] eq '\L') and ($char[$i+1] eq '\u')) {
    0 0        
    0          
    0          
    0          
5029 0           @char[$i,$i+1] = @char[$i+1,$i];
5030             }
5031              
5032             # "\U\l" --> "\l\U"
5033             elsif (($char[$i] eq '\U') and ($char[$i+1] eq '\l')) {
5034 0           @char[$i,$i+1] = @char[$i+1,$i];
5035             }
5036              
5037             # octal escape sequence
5038             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
5039 0           $char[$i] = Char::Ekoi8u::octchr($1);
5040             }
5041              
5042             # hexadecimal escape sequence
5043             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
5044 0           $char[$i] = Char::Ekoi8u::hexchr($1);
5045             }
5046              
5047             # \N{CHARNAME} --> N{CHARNAME}
5048             elsif ($char[$i] =~ /\A \\ ( N\{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
5049 0           $char[$i] = $1;
5050             }
5051              
5052 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          
5053             }
5054              
5055             # \F
5056             #
5057             # P.69 Table 2-6. Translation escapes
5058             # in Chapter 2: Bits and Pieces
5059             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
5060             # (and so on)
5061              
5062             # \u \l \U \L \F \Q \E
5063 0           elsif ($char[$i] =~ /\A ([<>]) \z/oxms) {
5064 0 0         if ($right_e < $left_e) {
5065 0           $char[$i] = '\\' . $char[$i];
5066             }
5067             }
5068             elsif ($char[$i] eq '\u') {
5069              
5070             # "STRING @{[ LIST EXPR ]} MORE STRING"
5071              
5072             # P.257 Other Tricks You Can Do with Hard References
5073             # in Chapter 8: References
5074             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
5075              
5076             # P.353 Other Tricks You Can Do with Hard References
5077             # in Chapter 8: References
5078             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
5079              
5080             # (and so on)
5081              
5082 0           $char[$i] = '@{[Char::Ekoi8u::ucfirst qq<';
5083 0           $left_e++;
5084             }
5085             elsif ($char[$i] eq '\l') {
5086 0           $char[$i] = '@{[Char::Ekoi8u::lcfirst qq<';
5087 0           $left_e++;
5088             }
5089             elsif ($char[$i] eq '\U') {
5090 0           $char[$i] = '@{[Char::Ekoi8u::uc qq<';
5091 0           $left_e++;
5092             }
5093             elsif ($char[$i] eq '\L') {
5094 0           $char[$i] = '@{[Char::Ekoi8u::lc qq<';
5095 0           $left_e++;
5096             }
5097             elsif ($char[$i] eq '\F') {
5098 0           $char[$i] = '@{[Char::Ekoi8u::fc qq<';
5099 0           $left_e++;
5100             }
5101             elsif ($char[$i] eq '\Q') {
5102 0           $char[$i] = '@{[CORE::quotemeta qq<';
5103 0           $left_e++;
5104             }
5105             elsif ($char[$i] eq '\E') {
5106 0 0         if ($right_e < $left_e) {
5107 0           $char[$i] = '>]}';
5108 0           $right_e++;
5109             }
5110             else {
5111 0           $char[$i] = '';
5112             }
5113             }
5114             elsif ($char[$i] eq '\Q') {
5115 0           while (1) {
5116 0 0         if (++$i > $#char) {
5117 0           last;
5118             }
5119 0 0         if ($char[$i] eq '\E') {
5120 0           last;
5121             }
5122             }
5123             }
5124             elsif ($char[$i] eq '\E') {
5125             }
5126              
5127             # $0 --> $0
5128             elsif ($char[$i] =~ /\A \$ 0 \z/oxms) {
5129             }
5130             elsif ($char[$i] =~ /\A \$ \{ \s* 0 \s* \} \z/oxms) {
5131             }
5132              
5133             # $$ --> $$
5134             elsif ($char[$i] =~ /\A \$\$ \z/oxms) {
5135             }
5136              
5137             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
5138             # $1, $2, $3 --> $1, $2, $3 otherwise
5139             elsif ($char[$i] =~ /\A \$ ([1-9][0-9]*) \z/oxms) {
5140 0           $char[$i] = e_capture($1);
5141             }
5142             elsif ($char[$i] =~ /\A \$ \{ \s* ([1-9][0-9]*) \s* \} \z/oxms) {
5143 0           $char[$i] = e_capture($1);
5144             }
5145              
5146             # $$foo[ ... ] --> $ $foo->[ ... ]
5147             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) ( \[ (?:$qq_bracket)*? \] ) \z/oxms) {
5148 0           $char[$i] = e_capture($1.'->'.$2);
5149             }
5150              
5151             # $$foo{ ... } --> $ $foo->{ ... }
5152             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) ( \{ (?:$qq_brace)*? \} ) \z/oxms) {
5153 0           $char[$i] = e_capture($1.'->'.$2);
5154             }
5155              
5156             # $$foo
5157             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) \z/oxms) {
5158 0           $char[$i] = e_capture($1);
5159             }
5160              
5161             # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Char::Ekoi8u::PREMATCH()
5162             elsif ($char[$i] =~ /\A ( \$` | \$\{`\} | \$ \s* PREMATCH | \$ \s* \{ \s* PREMATCH \s* \} | \$ \s* \{\^PREMATCH\} ) \z/oxmsgc) {
5163 0           $char[$i] = '@{[Char::Ekoi8u::PREMATCH()]}';
5164             }
5165              
5166             # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Char::Ekoi8u::MATCH()
5167             elsif ($char[$i] =~ /\A ( \$& | \$\{&\} | \$ \s* MATCH | \$ \s* \{ \s* MATCH \s* \} | \$ \s* \{\^MATCH\} ) \z/oxmsgc) {
5168 0           $char[$i] = '@{[Char::Ekoi8u::MATCH()]}';
5169             }
5170              
5171             # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Char::Ekoi8u::POSTMATCH()
5172             elsif ($char[$i] =~ /\A ( \$ \s* POSTMATCH | \$ \s* \{ \s* POSTMATCH \s* \} | \$ \s* \{\^POSTMATCH\} ) \z/oxmsgc) {
5173 0           $char[$i] = '@{[Char::Ekoi8u::POSTMATCH()]}';
5174             }
5175              
5176             # ${ foo } --> ${ foo }
5177             elsif ($char[$i] =~ /\A \$ \s* \{ \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* \} \z/oxms) {
5178             }
5179              
5180             # ${ ... }
5181             elsif ($char[$i] =~ /\A \$ \s* \{ \s* ( .+ ) \s* \} \z/oxms) {
5182 0           $char[$i] = e_capture($1);
5183             }
5184             }
5185              
5186             # return string
5187 0 0         if ($left_e > $right_e) {
5188 0           return join '', $ope, $delimiter, @char, '>]}' x ($left_e - $right_e), $end_delimiter;
5189             }
5190 0           return join '', $ope, $delimiter, @char, $end_delimiter;
5191             }
5192              
5193             #
5194             # escape qw string (qw//)
5195             #
5196             sub e_qw {
5197 0     0 0   my($ope,$delimiter,$end_delimiter,$string) = @_;
5198              
5199 0           $slash = 'div';
5200              
5201             # choice again delimiter
5202 0           my %octet = map {$_ => 1} ($string =~ /\G ([\x00-\xFF]) /oxmsg);
  0            
5203 0 0         if (not $octet{$end_delimiter}) {
    0          
    0          
    0          
    0          
5204 0           return join '', $ope, $delimiter, $string, $end_delimiter;
5205             }
5206             elsif (not $octet{')'}) {
5207 0           return join '', $ope, '(', $string, ')';
5208             }
5209             elsif (not $octet{'}'}) {
5210 0           return join '', $ope, '{', $string, '}';
5211             }
5212             elsif (not $octet{']'}) {
5213 0           return join '', $ope, '[', $string, ']';
5214             }
5215             elsif (not $octet{'>'}) {
5216 0           return join '', $ope, '<', $string, '>';
5217             }
5218             else {
5219 0           for my $char (qw( ! " $ % & * + - . / : = ? @ ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
5220 0 0         if (not $octet{$char}) {
5221 0           return join '', $ope, $char, $string, $char;
5222             }
5223             }
5224             }
5225              
5226             # qw/AAA BBB C'CC/ --> ('AAA', 'BBB', 'C\'CC')
5227 0           my @string = CORE::split(/\s+/, $string);
5228 0           for my $string (@string) {
5229 0           my @octet = $string =~ /\G ([\x00-\xFF]) /oxmsg;
5230 0           for my $octet (@octet) {
5231 0 0         if ($octet =~ /\A (['\\]) \z/oxms) {
5232 0           $octet = '\\' . $1;
5233             }
5234             }
5235 0           $string = join '', @octet;
5236             }
5237 0           return join '', '(', (join ', ', map { "'$_'" } @string), ')';
  0            
5238             }
5239              
5240             #
5241             # escape here document (<<"HEREDOC", <
5242             #
5243             sub e_heredoc {
5244 0     0 0   my($string) = @_;
5245              
5246 0           $slash = 'm//';
5247              
5248 0           my $metachar = qr/[\@\\|]/oxms; # '|' is for <<`HEREDOC`
5249              
5250 0           my $left_e = 0;
5251 0           my $right_e = 0;
5252 0           my @char = $string =~ /\G(
5253             \\o\{ [0-7]+ \} |
5254             \\x\{ [0-9A-Fa-f]+ \} |
5255             \\N\{ [^0-9\}][^\}]* \} |
5256             \$` | \$\{`\} | \$ \s* PREMATCH | \$ \s* \{ \s* PREMATCH \s* \} | \$ \s* \{\^PREMATCH\} |
5257             \$& | \$\{&\} | \$ \s* MATCH | \$ \s* \{ \s* MATCH \s* \} | \$ \s* \{\^MATCH\} |
5258             \$ \s* POSTMATCH | \$ \s* \{ \s* POSTMATCH \s* \} | \$ \s* \{\^POSTMATCH\} |
5259             \$ \s* \d+ |
5260             \$ \s* \{ \s* \d+ \s* \} |
5261             \$ \$ (?![\w\{]) |
5262             \$ \s* \$ \s* $qq_variable |
5263             \\?(?:$q_char)
5264             )/oxmsg;
5265              
5266 0           for (my $i=0; $i <= $#char; $i++) {
5267              
5268             # "\L\u" --> "\u\L"
5269 0 0 0       if (($char[$i] eq '\L') and ($char[$i+1] eq '\u')) {
    0 0        
    0          
    0          
    0          
5270 0           @char[$i,$i+1] = @char[$i+1,$i];
5271             }
5272              
5273             # "\U\l" --> "\l\U"
5274             elsif (($char[$i] eq '\U') and ($char[$i+1] eq '\l')) {
5275 0           @char[$i,$i+1] = @char[$i+1,$i];
5276             }
5277              
5278             # octal escape sequence
5279             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
5280 0           $char[$i] = Char::Ekoi8u::octchr($1);
5281             }
5282              
5283             # hexadecimal escape sequence
5284             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
5285 0           $char[$i] = Char::Ekoi8u::hexchr($1);
5286             }
5287              
5288             # \N{CHARNAME} --> N{CHARNAME}
5289             elsif ($char[$i] =~ /\A \\ ( N\{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
5290 0           $char[$i] = $1;
5291             }
5292              
5293 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          
5294             }
5295              
5296             # \u \l \U \L \F \Q \E
5297 0           elsif ($char[$i] =~ /\A ([<>]) \z/oxms) {
5298 0 0         if ($right_e < $left_e) {
5299 0           $char[$i] = '\\' . $char[$i];
5300             }
5301             }
5302             elsif ($char[$i] eq '\u') {
5303 0           $char[$i] = '@{[Char::Ekoi8u::ucfirst qq<';
5304 0           $left_e++;
5305             }
5306             elsif ($char[$i] eq '\l') {
5307 0           $char[$i] = '@{[Char::Ekoi8u::lcfirst qq<';
5308 0           $left_e++;
5309             }
5310             elsif ($char[$i] eq '\U') {
5311 0           $char[$i] = '@{[Char::Ekoi8u::uc qq<';
5312 0           $left_e++;
5313             }
5314             elsif ($char[$i] eq '\L') {
5315 0           $char[$i] = '@{[Char::Ekoi8u::lc qq<';
5316 0           $left_e++;
5317             }
5318             elsif ($char[$i] eq '\F') {
5319 0           $char[$i] = '@{[Char::Ekoi8u::fc qq<';
5320 0           $left_e++;
5321             }
5322             elsif ($char[$i] eq '\Q') {
5323 0           $char[$i] = '@{[CORE::quotemeta qq<';
5324 0           $left_e++;
5325             }
5326             elsif ($char[$i] eq '\E') {
5327 0 0         if ($right_e < $left_e) {
5328 0           $char[$i] = '>]}';
5329 0           $right_e++;
5330             }
5331             else {
5332 0           $char[$i] = '';
5333             }
5334             }
5335             elsif ($char[$i] eq '\Q') {
5336 0           while (1) {
5337 0 0         if (++$i > $#char) {
5338 0           last;
5339             }
5340 0 0         if ($char[$i] eq '\E') {
5341 0           last;
5342             }
5343             }
5344             }
5345             elsif ($char[$i] eq '\E') {
5346             }
5347              
5348             # $0 --> $0
5349             elsif ($char[$i] =~ /\A \$ 0 \z/oxms) {
5350             }
5351             elsif ($char[$i] =~ /\A \$ \{ \s* 0 \s* \} \z/oxms) {
5352             }
5353              
5354             # $$ --> $$
5355             elsif ($char[$i] =~ /\A \$\$ \z/oxms) {
5356             }
5357              
5358             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
5359             # $1, $2, $3 --> $1, $2, $3 otherwise
5360             elsif ($char[$i] =~ /\A \$ ([1-9][0-9]*) \z/oxms) {
5361 0           $char[$i] = e_capture($1);
5362             }
5363             elsif ($char[$i] =~ /\A \$ \{ \s* ([1-9][0-9]*) \s* \} \z/oxms) {
5364 0           $char[$i] = e_capture($1);
5365             }
5366              
5367             # $$foo[ ... ] --> $ $foo->[ ... ]
5368             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) ( \[ (?:$qq_bracket)*? \] ) \z/oxms) {
5369 0           $char[$i] = e_capture($1.'->'.$2);
5370             }
5371              
5372             # $$foo{ ... } --> $ $foo->{ ... }
5373             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) ( \{ (?:$qq_brace)*? \} ) \z/oxms) {
5374 0           $char[$i] = e_capture($1.'->'.$2);
5375             }
5376              
5377             # $$foo
5378             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) \z/oxms) {
5379 0           $char[$i] = e_capture($1);
5380             }
5381              
5382             # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Char::Ekoi8u::PREMATCH()
5383             elsif ($char[$i] =~ /\A ( \$` | \$\{`\} | \$ \s* PREMATCH | \$ \s* \{ \s* PREMATCH \s* \} | \$ \s* \{\^PREMATCH\} ) \z/oxmsgc) {
5384 0           $char[$i] = '@{[Char::Ekoi8u::PREMATCH()]}';
5385             }
5386              
5387             # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Char::Ekoi8u::MATCH()
5388             elsif ($char[$i] =~ /\A ( \$& | \$\{&\} | \$ \s* MATCH | \$ \s* \{ \s* MATCH \s* \} | \$ \s* \{\^MATCH\} ) \z/oxmsgc) {
5389 0           $char[$i] = '@{[Char::Ekoi8u::MATCH()]}';
5390             }
5391              
5392             # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Char::Ekoi8u::POSTMATCH()
5393             elsif ($char[$i] =~ /\A ( \$ \s* POSTMATCH | \$ \s* \{ \s* POSTMATCH \s* \} | \$ \s* \{\^POSTMATCH\} ) \z/oxmsgc) {
5394 0           $char[$i] = '@{[Char::Ekoi8u::POSTMATCH()]}';
5395             }
5396              
5397             # ${ foo } --> ${ foo }
5398             elsif ($char[$i] =~ /\A \$ \s* \{ \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* \} \z/oxms) {
5399             }
5400              
5401             # ${ ... }
5402             elsif ($char[$i] =~ /\A \$ \s* \{ \s* ( .+ ) \s* \} \z/oxms) {
5403 0           $char[$i] = e_capture($1);
5404             }
5405             }
5406              
5407             # return string
5408 0 0         if ($left_e > $right_e) {
5409 0           return join '', @char, '>]}' x ($left_e - $right_e);
5410             }
5411 0           return join '', @char;
5412             }
5413              
5414             #
5415             # escape regexp (m//, qr//)
5416             #
5417             sub e_qr {
5418 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
5419 0   0       $modifier ||= '';
5420              
5421 0           $modifier =~ tr/p//d;
5422 0 0         if ($modifier =~ /([adlu])/oxms) {
5423 0           my $line = 0;
5424 0           for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
5425 0 0         if ($filename ne __FILE__) {
5426 0           $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
5427 0           last;
5428             }
5429             }
5430 0           die qq{Unsupported modifier "$1" used at line $line.\n};
5431             }
5432              
5433 0           $slash = 'div';
5434              
5435             # literal null string pattern
5436 0 0         if ($string eq '') {
    0          
5437 0           $modifier =~ tr/bB//d;
5438 0           $modifier =~ tr/i//d;
5439 0           return join '', $ope, $delimiter, $end_delimiter, $modifier;
5440             }
5441              
5442             # /b /B modifier
5443             elsif ($modifier =~ tr/bB//d) {
5444              
5445             # choice again delimiter
5446 0 0         if ($delimiter =~ / [\@:] /oxms) {
5447 0           my @char = $string =~ /\G([\x00-\xFF])/oxmsg;
5448 0           my %octet = map {$_ => 1} @char;
  0            
5449 0 0         if (not $octet{')'}) {
    0          
    0          
    0          
5450 0           $delimiter = '(';
5451 0           $end_delimiter = ')';
5452             }
5453             elsif (not $octet{'}'}) {
5454 0           $delimiter = '{';
5455 0           $end_delimiter = '}';
5456             }
5457             elsif (not $octet{']'}) {
5458 0           $delimiter = '[';
5459 0           $end_delimiter = ']';
5460             }
5461             elsif (not $octet{'>'}) {
5462 0           $delimiter = '<';
5463 0           $end_delimiter = '>';
5464             }
5465             else {
5466 0           for my $char (qw( ! " $ % & * + - . / = ? ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
5467 0 0         if (not $octet{$char}) {
5468 0           $delimiter = $char;
5469 0           $end_delimiter = $char;
5470 0           last;
5471             }
5472             }
5473             }
5474             }
5475              
5476 0 0 0       if (($ope =~ /\A m? \z/oxms) and ($delimiter eq '?')) {
5477 0           return join '', $ope, $delimiter, $string, $matched, $end_delimiter, $modifier;
5478             }
5479             else {
5480 0           return join '', $ope, $delimiter, '(?:', $string, ')', $matched, $end_delimiter, $modifier;
5481             }
5482             }
5483              
5484 0 0         my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
5485 0           my $metachar = qr/[\@\\|[\]{^]/oxms;
5486              
5487             # split regexp
5488 0           my @char = $string =~ /\G(
5489             \\o\{ [0-7]+ \} |
5490             \\ [0-7]{2,3} |
5491             \\x\{ [0-9A-Fa-f]+ \} |
5492             \\x [0-9A-Fa-f]{1,2} |
5493             \\c [\x40-\x5F] |
5494             \\N\{ [^0-9\}][^\}]* \} |
5495             \\p\{ [^0-9\}][^\}]* \} |
5496             \\P\{ [^0-9\}][^\}]* \} |
5497             \\ (?:$q_char) |
5498             \$` | \$\{`\} | \$ \s* PREMATCH | \$ \s* \{ \s* PREMATCH \s* \} | \$ \s* \{\^PREMATCH\} |
5499             \$& | \$\{&\} | \$ \s* MATCH | \$ \s* \{ \s* MATCH \s* \} | \$ \s* \{\^MATCH\} |
5500             \$ \s* POSTMATCH | \$ \s* \{ \s* POSTMATCH \s* \} | \$ \s* \{\^POSTMATCH\} |
5501             [\$\@] $qq_variable |
5502             \$ \s* \d+ |
5503             \$ \s* \{ \s* \d+ \s* \} |
5504             \$ \$ (?![\w\{]) |
5505             \$ \s* \$ \s* $qq_variable |
5506             \[\:\^ (?:alnum|alpha|ascii|blank|cntrl|digit|graph|lower|print|punct|space|upper|word|xdigit) :\] |
5507             \[\: (?:alnum|alpha|ascii|blank|cntrl|digit|graph|lower|print|punct|space|upper|word|xdigit) :\] |
5508             \[\^ |
5509             \(\? |
5510             (?:$q_char)
5511             )/oxmsg;
5512              
5513             # choice again delimiter
5514 0 0         if ($delimiter =~ / [\@:] /oxms) {
5515 0           my %octet = map {$_ => 1} @char;
  0            
5516 0 0         if (not $octet{')'}) {
    0          
    0          
    0          
5517 0           $delimiter = '(';
5518 0           $end_delimiter = ')';
5519             }
5520             elsif (not $octet{'}'}) {
5521 0           $delimiter = '{';
5522 0           $end_delimiter = '}';
5523             }
5524             elsif (not $octet{']'}) {
5525 0           $delimiter = '[';
5526 0           $end_delimiter = ']';
5527             }
5528             elsif (not $octet{'>'}) {
5529 0           $delimiter = '<';
5530 0           $end_delimiter = '>';
5531             }
5532             else {
5533 0           for my $char (qw( ! " $ % & * + - . / = ? ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
5534 0 0         if (not $octet{$char}) {
5535 0           $delimiter = $char;
5536 0           $end_delimiter = $char;
5537 0           last;
5538             }
5539             }
5540             }
5541             }
5542              
5543 0           my $left_e = 0;
5544 0           my $right_e = 0;
5545 0           for (my $i=0; $i <= $#char; $i++) {
5546              
5547             # "\L\u" --> "\u\L"
5548 0 0 0       if (($char[$i] eq '\L') and ($char[$i+1] eq '\u')) {
    0 0        
    0          
    0          
    0          
    0          
    0          
    0          
5549 0           @char[$i,$i+1] = @char[$i+1,$i];
5550             }
5551              
5552             # "\U\l" --> "\l\U"
5553             elsif (($char[$i] eq '\U') and ($char[$i+1] eq '\l')) {
5554 0           @char[$i,$i+1] = @char[$i+1,$i];
5555             }
5556              
5557             # octal escape sequence
5558             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
5559 0           $char[$i] = Char::Ekoi8u::octchr($1);
5560             }
5561              
5562             # hexadecimal escape sequence
5563             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
5564 0           $char[$i] = Char::Ekoi8u::hexchr($1);
5565             }
5566              
5567             # \N{CHARNAME} --> N\{CHARNAME}
5568             elsif ($char[$i] =~ /\A \\ (N) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
5569 0           $char[$i] = $1 . '\\' . $2;
5570             }
5571              
5572             # \p{PROPERTY} --> p\{PROPERTY}
5573             elsif ($char[$i] =~ /\A \\ (p) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
5574 0           $char[$i] = $1 . '\\' . $2;
5575             }
5576              
5577             # \P{PROPERTY} --> P\{PROPERTY}
5578             elsif ($char[$i] =~ /\A \\ (P) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
5579 0           $char[$i] = $1 . '\\' . $2;
5580             }
5581              
5582             # \p, \P, \X --> p, P, X
5583             elsif ($char[$i] =~ /\A \\ ( [pPX] ) \z/oxms) {
5584 0           $char[$i] = $1;
5585             }
5586              
5587 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          
5588             }
5589              
5590             # join separated multiple-octet
5591 0           elsif ($char[$i] =~ /\A (?: \\ [0-7]{2,3} | \\x [0-9A-Fa-f]{1,2}) \z/oxms) {
5592 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        
5593 0           $char[$i] .= join '', splice @char, $i+1, 3;
5594             }
5595             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)) {
5596 0           $char[$i] .= join '', splice @char, $i+1, 2;
5597             }
5598             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)) {
5599 0           $char[$i] .= join '', splice @char, $i+1, 1;
5600             }
5601             }
5602              
5603             # open character class [...]
5604             elsif ($char[$i] eq '[') {
5605 0           my $left = $i;
5606              
5607             # [] make die "Unmatched [] in regexp ..."
5608             # (and so on)
5609              
5610 0 0         if ($char[$i+1] eq ']') {
5611 0           $i++;
5612             }
5613              
5614 0           while (1) {
5615 0 0         if (++$i > $#char) {
5616 0           die __FILE__, ": Unmatched [] in regexp";
5617             }
5618 0 0         if ($char[$i] eq ']') {
5619 0           my $right = $i;
5620              
5621             # [...]
5622 0 0         if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
5623 0           splice @char, $left, $right-$left+1, sprintf(q{@{[Char::Ekoi8u::charlist_qr(%s,'%s')]}}, join(',', map {qq_stuff($delimiter,$end_delimiter,$_)} @char[$left+1..$right-1]), $modifier);
  0            
5624             }
5625             else {
5626 0           splice @char, $left, $right-$left+1, Char::Ekoi8u::charlist_qr(@char[$left+1..$right-1], $modifier);
5627             }
5628              
5629 0           $i = $left;
5630 0           last;
5631             }
5632             }
5633             }
5634              
5635             # open character class [^...]
5636             elsif ($char[$i] eq '[^') {
5637 0           my $left = $i;
5638              
5639             # [^] make die "Unmatched [] in regexp ..."
5640             # (and so on)
5641              
5642 0 0         if ($char[$i+1] eq ']') {
5643 0           $i++;
5644             }
5645              
5646 0           while (1) {
5647 0 0         if (++$i > $#char) {
5648 0           die __FILE__, ": Unmatched [] in regexp";
5649             }
5650 0 0         if ($char[$i] eq ']') {
5651 0           my $right = $i;
5652              
5653             # [^...]
5654 0 0         if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
5655 0           splice @char, $left, $right-$left+1, sprintf(q{@{[Char::Ekoi8u::charlist_not_qr(%s,'%s')]}}, join(',', map {qq_stuff($delimiter,$end_delimiter,$_)} @char[$left+1..$right-1]), $modifier);
  0            
5656             }
5657             else {
5658 0           splice @char, $left, $right-$left+1, Char::Ekoi8u::charlist_not_qr(@char[$left+1..$right-1], $modifier);
5659             }
5660              
5661 0           $i = $left;
5662 0           last;
5663             }
5664             }
5665             }
5666              
5667             # rewrite character class or escape character
5668             elsif (my $char = character_class($char[$i],$modifier)) {
5669 0           $char[$i] = $char;
5670             }
5671              
5672             # /i modifier
5673             elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Char::Ekoi8u::uc($char[$i]) ne Char::Ekoi8u::fc($char[$i]))) {
5674 0 0         if (CORE::length(Char::Ekoi8u::fc($char[$i])) == 1) {
5675 0           $char[$i] = '[' . Char::Ekoi8u::uc($char[$i]) . Char::Ekoi8u::fc($char[$i]) . ']';
5676             }
5677             else {
5678 0           $char[$i] = '(?:' . Char::Ekoi8u::uc($char[$i]) . '|' . Char::Ekoi8u::fc($char[$i]) . ')';
5679             }
5680             }
5681              
5682             # \u \l \U \L \F \Q \E
5683             elsif ($char[$i] =~ /\A [<>] \z/oxms) {
5684 0 0         if ($right_e < $left_e) {
5685 0           $char[$i] = '\\' . $char[$i];
5686             }
5687             }
5688             elsif ($char[$i] eq '\u') {
5689 0           $char[$i] = '@{[Char::Ekoi8u::ucfirst qq<';
5690 0           $left_e++;
5691             }
5692             elsif ($char[$i] eq '\l') {
5693 0           $char[$i] = '@{[Char::Ekoi8u::lcfirst qq<';
5694 0           $left_e++;
5695             }
5696             elsif ($char[$i] eq '\U') {
5697 0           $char[$i] = '@{[Char::Ekoi8u::uc qq<';
5698 0           $left_e++;
5699             }
5700             elsif ($char[$i] eq '\L') {
5701 0           $char[$i] = '@{[Char::Ekoi8u::lc qq<';
5702 0           $left_e++;
5703             }
5704             elsif ($char[$i] eq '\F') {
5705 0           $char[$i] = '@{[Char::Ekoi8u::fc qq<';
5706 0           $left_e++;
5707             }
5708             elsif ($char[$i] eq '\Q') {
5709 0           $char[$i] = '@{[CORE::quotemeta qq<';
5710 0           $left_e++;
5711             }
5712             elsif ($char[$i] eq '\E') {
5713 0 0         if ($right_e < $left_e) {
5714 0           $char[$i] = '>]}';
5715 0           $right_e++;
5716             }
5717             else {
5718 0           $char[$i] = '';
5719             }
5720             }
5721             elsif ($char[$i] eq '\Q') {
5722 0           while (1) {
5723 0 0         if (++$i > $#char) {
5724 0           last;
5725             }
5726 0 0         if ($char[$i] eq '\E') {
5727 0           last;
5728             }
5729             }
5730             }
5731             elsif ($char[$i] eq '\E') {
5732             }
5733              
5734             # $0 --> $0
5735             elsif ($char[$i] =~ /\A \$ 0 \z/oxms) {
5736 0 0         if ($ignorecase) {
5737 0           $char[$i] = '@{[Char::Ekoi8u::ignorecase(' . $char[$i] . ')]}';
5738             }
5739             }
5740             elsif ($char[$i] =~ /\A \$ \{ \s* 0 \s* \} \z/oxms) {
5741 0 0         if ($ignorecase) {
5742 0           $char[$i] = '@{[Char::Ekoi8u::ignorecase(' . $char[$i] . ')]}';
5743             }
5744             }
5745              
5746             # $$ --> $$
5747             elsif ($char[$i] =~ /\A \$\$ \z/oxms) {
5748             }
5749              
5750             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
5751             # $1, $2, $3 --> $1, $2, $3 otherwise
5752             elsif ($char[$i] =~ /\A \$ ([1-9][0-9]*) \z/oxms) {
5753 0           $char[$i] = e_capture($1);
5754 0 0         if ($ignorecase) {
5755 0           $char[$i] = '@{[Char::Ekoi8u::ignorecase(' . $char[$i] . ')]}';
5756             }
5757             }
5758             elsif ($char[$i] =~ /\A \$ \{ \s* ([1-9][0-9]*) \s* \} \z/oxms) {
5759 0           $char[$i] = e_capture($1);
5760 0 0         if ($ignorecase) {
5761 0           $char[$i] = '@{[Char::Ekoi8u::ignorecase(' . $char[$i] . ')]}';
5762             }
5763             }
5764              
5765             # $$foo[ ... ] --> $ $foo->[ ... ]
5766             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) ( \[ (?:$qq_bracket)*? \] ) \z/oxms) {
5767 0           $char[$i] = e_capture($1.'->'.$2);
5768 0 0         if ($ignorecase) {
5769 0           $char[$i] = '@{[Char::Ekoi8u::ignorecase(' . $char[$i] . ')]}';
5770             }
5771             }
5772              
5773             # $$foo{ ... } --> $ $foo->{ ... }
5774             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) ( \{ (?:$qq_brace)*? \} ) \z/oxms) {
5775 0           $char[$i] = e_capture($1.'->'.$2);
5776 0 0         if ($ignorecase) {
5777 0           $char[$i] = '@{[Char::Ekoi8u::ignorecase(' . $char[$i] . ')]}';
5778             }
5779             }
5780              
5781             # $$foo
5782             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) \z/oxms) {
5783 0           $char[$i] = e_capture($1);
5784 0 0         if ($ignorecase) {
5785 0           $char[$i] = '@{[Char::Ekoi8u::ignorecase(' . $char[$i] . ')]}';
5786             }
5787             }
5788              
5789             # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Char::Ekoi8u::PREMATCH()
5790             elsif ($char[$i] =~ /\A ( \$` | \$\{`\} | \$ \s* PREMATCH | \$ \s* \{ \s* PREMATCH \s* \} | \$ \s* \{\^PREMATCH\} ) \z/oxmsgc) {
5791 0 0         if ($ignorecase) {
5792 0           $char[$i] = '@{[Char::Ekoi8u::ignorecase(Char::Ekoi8u::PREMATCH())]}';
5793             }
5794             else {
5795 0           $char[$i] = '@{[Char::Ekoi8u::PREMATCH()]}';
5796             }
5797             }
5798              
5799             # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Char::Ekoi8u::MATCH()
5800             elsif ($char[$i] =~ /\A ( \$& | \$\{&\} | \$ \s* MATCH | \$ \s* \{ \s* MATCH \s* \} | \$ \s* \{\^MATCH\} ) \z/oxmsgc) {
5801 0 0         if ($ignorecase) {
5802 0           $char[$i] = '@{[Char::Ekoi8u::ignorecase(Char::Ekoi8u::MATCH())]}';
5803             }
5804             else {
5805 0           $char[$i] = '@{[Char::Ekoi8u::MATCH()]}';
5806             }
5807             }
5808              
5809             # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Char::Ekoi8u::POSTMATCH()
5810             elsif ($char[$i] =~ /\A ( \$ \s* POSTMATCH | \$ \s* \{ \s* POSTMATCH \s* \} | \$ \s* \{\^POSTMATCH\} ) \z/oxmsgc) {
5811 0 0         if ($ignorecase) {
5812 0           $char[$i] = '@{[Char::Ekoi8u::ignorecase(Char::Ekoi8u::POSTMATCH())]}';
5813             }
5814             else {
5815 0           $char[$i] = '@{[Char::Ekoi8u::POSTMATCH()]}';
5816             }
5817             }
5818              
5819             # ${ foo }
5820             elsif ($char[$i] =~ /\A \$ \s* \{ ( \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* ) \} \z/oxms) {
5821 0 0         if ($ignorecase) {
5822 0           $char[$i] = '@{[Char::Ekoi8u::ignorecase(' . $char[$i] . ')]}';
5823             }
5824             }
5825              
5826             # ${ ... }
5827             elsif ($char[$i] =~ /\A \$ \s* \{ \s* ( .+ ) \s* \} \z/oxms) {
5828 0           $char[$i] = e_capture($1);
5829 0 0         if ($ignorecase) {
5830 0           $char[$i] = '@{[Char::Ekoi8u::ignorecase(' . $char[$i] . ')]}';
5831             }
5832             }
5833              
5834             # $scalar or @array
5835             elsif ($char[$i] =~ /\A [\$\@].+ /oxms) {
5836 0           $char[$i] = e_string($char[$i]);
5837 0 0         if ($ignorecase) {
5838 0           $char[$i] = '@{[Char::Ekoi8u::ignorecase(' . $char[$i] . ')]}';
5839             }
5840             }
5841              
5842             # quote character before ? + * {
5843             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
5844 0 0 0       if ($char[$i-1] =~ /\A (?:\\[0-7]{2,3}|\\x[0-9-A-Fa-f]{1,2}) \z/oxms) {
    0          
5845             }
5846             elsif (($ope =~ /\A m? \z/oxms) and ($delimiter eq '?')) {
5847 0           my $char = $char[$i-1];
5848 0 0         if ($char[$i] eq '{') {
5849 0           die __FILE__, qq{: "MULTIBYTE{n}" should be "(MULTIBYTE){n}" in m?? (and shift \$1,\$2,\$3,...) ($char){n}};
5850             }
5851             else {
5852 0           die __FILE__, qq{: "MULTIBYTE$char[$i]" should be "(MULTIBYTE)$char[$i]" in m?? (and shift \$1,\$2,\$3,...) ($char)$char[$i]};
5853             }
5854             }
5855             else {
5856 0           $char[$i-1] = '(?:' . $char[$i-1] . ')';
5857             }
5858             }
5859             }
5860              
5861             # make regexp string
5862 0           $modifier =~ tr/i//d;
5863 0 0         if ($left_e > $right_e) {
5864 0 0 0       if (($ope =~ /\A m? \z/oxms) and ($delimiter eq '?')) {
5865 0           return join '', $ope, $delimiter, $anchor, @char, '>]}' x ($left_e - $right_e), $matched, $end_delimiter, $modifier;
5866             }
5867             else {
5868 0           return join '', $ope, $delimiter, $anchor, '(?:', @char, '>]}' x ($left_e - $right_e), ')', $matched, $end_delimiter, $modifier;
5869             }
5870             }
5871 0 0 0       if (($ope =~ /\A m? \z/oxms) and ($delimiter eq '?')) {
5872 0           return join '', $ope, $delimiter, $anchor, @char, $matched, $end_delimiter, $modifier;
5873             }
5874             else {
5875 0           return join '', $ope, $delimiter, $anchor, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
5876             }
5877             }
5878              
5879             #
5880             # double quote stuff
5881             #
5882             sub qq_stuff {
5883 0     0 0   my($delimiter,$end_delimiter,$stuff) = @_;
5884              
5885             # scalar variable or array variable
5886 0 0         if ($stuff =~ /\A [\$\@] /oxms) {
5887 0           return $stuff;
5888             }
5889              
5890             # quote by delimiter
5891 0           my %octet = map {$_ => 1} ($stuff =~ /\G ([\x00-\xFF]) /oxmsg);
  0            
5892 0           for my $char (qw( ! " $ % & * + - . / : = ? @ ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
5893 0 0         next if $char eq $delimiter;
5894 0 0         next if $char eq $end_delimiter;
5895 0 0         if (not $octet{$char}) {
5896 0           return join '', 'qq', $char, $stuff, $char;
5897             }
5898             }
5899 0           return join '', 'qq', '<', $stuff, '>';
5900             }
5901              
5902             #
5903             # escape regexp (m'', qr'', and m''b, qr''b)
5904             #
5905             sub e_qr_q {
5906 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
5907 0   0       $modifier ||= '';
5908              
5909 0           $modifier =~ tr/p//d;
5910 0 0         if ($modifier =~ /([adlu])/oxms) {
5911 0           my $line = 0;
5912 0           for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
5913 0 0         if ($filename ne __FILE__) {
5914 0           $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
5915 0           last;
5916             }
5917             }
5918 0           die qq{Unsupported modifier "$1" used at line $line.\n};
5919             }
5920              
5921 0           $slash = 'div';
5922              
5923             # literal null string pattern
5924 0 0         if ($string eq '') {
    0          
5925 0           $modifier =~ tr/bB//d;
5926 0           $modifier =~ tr/i//d;
5927 0           return join '', $ope, $delimiter, $end_delimiter, $modifier;
5928             }
5929              
5930             # with /b /B modifier
5931             elsif ($modifier =~ tr/bB//d) {
5932 0           return e_qr_qb($ope,$delimiter,$end_delimiter,$string,$modifier);
5933             }
5934              
5935             # without /b /B modifier
5936             else {
5937 0           return e_qr_qt($ope,$delimiter,$end_delimiter,$string,$modifier);
5938             }
5939             }
5940              
5941             #
5942             # escape regexp (m'', qr'')
5943             #
5944             sub e_qr_qt {
5945 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
5946              
5947 0 0         my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
5948              
5949             # split regexp
5950 0           my @char = $string =~ /\G(
5951             \[\:\^ [a-z]+ \:\] |
5952             \[\: [a-z]+ \:\] |
5953             \[\^ |
5954             [\$\@\/\\] |
5955             \\? (?:$q_char)
5956             )/oxmsg;
5957              
5958             # unescape character
5959 0           for (my $i=0; $i <= $#char; $i++) {
5960 0 0 0       if (0) {
    0 0        
    0 0        
    0          
    0          
    0          
5961             }
5962              
5963             # open character class [...]
5964 0           elsif ($char[$i] eq '[') {
5965 0           my $left = $i;
5966 0 0         if ($char[$i+1] eq ']') {
5967 0           $i++;
5968             }
5969 0           while (1) {
5970 0 0         if (++$i > $#char) {
5971 0           die __FILE__, ": Unmatched [] in regexp";
5972             }
5973 0 0         if ($char[$i] eq ']') {
5974 0           my $right = $i;
5975              
5976             # [...]
5977 0           splice @char, $left, $right-$left+1, Char::Ekoi8u::charlist_qr(@char[$left+1..$right-1], $modifier);
5978              
5979 0           $i = $left;
5980 0           last;
5981             }
5982             }
5983             }
5984              
5985             # open character class [^...]
5986             elsif ($char[$i] eq '[^') {
5987 0           my $left = $i;
5988 0 0         if ($char[$i+1] eq ']') {
5989 0           $i++;
5990             }
5991 0           while (1) {
5992 0 0         if (++$i > $#char) {
5993 0           die __FILE__, ": Unmatched [] in regexp";
5994             }
5995 0 0         if ($char[$i] eq ']') {
5996 0           my $right = $i;
5997              
5998             # [^...]
5999 0           splice @char, $left, $right-$left+1, Char::Ekoi8u::charlist_not_qr(@char[$left+1..$right-1], $modifier);
6000              
6001 0           $i = $left;
6002 0           last;
6003             }
6004             }
6005             }
6006              
6007             # escape $ @ / and \
6008             elsif ($char[$i] =~ /\A [\$\@\/\\] \z/oxms) {
6009 0           $char[$i] = '\\' . $char[$i];
6010             }
6011              
6012             # rewrite character class or escape character
6013             elsif (my $char = character_class($char[$i],$modifier)) {
6014 0           $char[$i] = $char;
6015             }
6016              
6017             # /i modifier
6018             elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Char::Ekoi8u::uc($char[$i]) ne Char::Ekoi8u::fc($char[$i]))) {
6019 0 0         if (CORE::length(Char::Ekoi8u::fc($char[$i])) == 1) {
6020 0           $char[$i] = '[' . Char::Ekoi8u::uc($char[$i]) . Char::Ekoi8u::fc($char[$i]) . ']';
6021             }
6022             else {
6023 0           $char[$i] = '(?:' . Char::Ekoi8u::uc($char[$i]) . '|' . Char::Ekoi8u::fc($char[$i]) . ')';
6024             }
6025             }
6026              
6027             # quote character before ? + * {
6028             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
6029 0 0         if ($char[$i-1] =~ /\A [\x00-\xFF] \z/oxms) {
6030             }
6031             else {
6032 0           $char[$i-1] = '(?:' . $char[$i-1] . ')';
6033             }
6034             }
6035             }
6036              
6037 0           $delimiter = '/';
6038 0           $end_delimiter = '/';
6039              
6040 0           $modifier =~ tr/i//d;
6041 0           return join '', $ope, $delimiter, $anchor, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
6042             }
6043              
6044             #
6045             # escape regexp (m''b, qr''b)
6046             #
6047             sub e_qr_qb {
6048 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6049              
6050             # split regexp
6051 0           my @char = $string =~ /\G(
6052             \\\\ |
6053             [\$\@\/\\] |
6054             [\x00-\xFF]
6055             )/oxmsg;
6056              
6057             # unescape character
6058 0           for (my $i=0; $i <= $#char; $i++) {
6059 0 0         if (0) {
    0          
6060             }
6061              
6062             # remain \\
6063 0           elsif ($char[$i] eq '\\\\') {
6064             }
6065              
6066             # escape $ @ / and \
6067             elsif ($char[$i] =~ /\A [\$\@\/\\] \z/oxms) {
6068 0           $char[$i] = '\\' . $char[$i];
6069             }
6070             }
6071              
6072 0           $delimiter = '/';
6073 0           $end_delimiter = '/';
6074 0           return join '', $ope, $delimiter, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
6075             }
6076              
6077             #
6078             # escape regexp (s/here//)
6079             #
6080             sub e_s1 {
6081 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6082 0   0       $modifier ||= '';
6083              
6084 0           $modifier =~ tr/p//d;
6085 0 0         if ($modifier =~ /([adlu])/oxms) {
6086 0           my $line = 0;
6087 0           for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
6088 0 0         if ($filename ne __FILE__) {
6089 0           $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
6090 0           last;
6091             }
6092             }
6093 0           die qq{Unsupported modifier "$1" used at line $line.\n};
6094             }
6095              
6096 0           $slash = 'div';
6097              
6098             # literal null string pattern
6099 0 0         if ($string eq '') {
    0          
6100 0           $modifier =~ tr/bB//d;
6101 0           $modifier =~ tr/i//d;
6102 0           return join '', $ope, $delimiter, $end_delimiter, $modifier;
6103             }
6104              
6105             # /b /B modifier
6106             elsif ($modifier =~ tr/bB//d) {
6107              
6108             # choice again delimiter
6109 0 0         if ($delimiter =~ / [\@:] /oxms) {
6110 0           my @char = $string =~ /\G([\x00-\xFF])/oxmsg;
6111 0           my %octet = map {$_ => 1} @char;
  0            
6112 0 0         if (not $octet{')'}) {
    0          
    0          
    0          
6113 0           $delimiter = '(';
6114 0           $end_delimiter = ')';
6115             }
6116             elsif (not $octet{'}'}) {
6117 0           $delimiter = '{';
6118 0           $end_delimiter = '}';
6119             }
6120             elsif (not $octet{']'}) {
6121 0           $delimiter = '[';
6122 0           $end_delimiter = ']';
6123             }
6124             elsif (not $octet{'>'}) {
6125 0           $delimiter = '<';
6126 0           $end_delimiter = '>';
6127             }
6128             else {
6129 0           for my $char (qw( ! " $ % & * + - . / = ? ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
6130 0 0         if (not $octet{$char}) {
6131 0           $delimiter = $char;
6132 0           $end_delimiter = $char;
6133 0           last;
6134             }
6135             }
6136             }
6137             }
6138              
6139 0           my $prematch = '';
6140 0           return join '', $ope, $delimiter, $prematch, '(?:', $string, ')', $matched, $end_delimiter, $modifier;
6141             }
6142              
6143 0 0         my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
6144 0           my $metachar = qr/[\@\\|[\]{^]/oxms;
6145              
6146             # split regexp
6147 0           my @char = $string =~ /\G(
6148             \\g \s* \{ \s* - \s* [1-9][0-9]* \s* \} |
6149             \\g \s* \{ \s* [1-9][0-9]* \s* \} |
6150             \\g \s* [1-9][0-9]* |
6151             \\o\{ [0-7]+ \} |
6152             \\ [1-9][0-9]* |
6153             \\ [0-7]{2,3} |
6154             \\x\{ [0-9A-Fa-f]+ \} |
6155             \\x [0-9A-Fa-f]{1,2} |
6156             \\c [\x40-\x5F] |
6157             \\N\{ [^0-9\}][^\}]* \} |
6158             \\p\{ [^0-9\}][^\}]* \} |
6159             \\P\{ [^0-9\}][^\}]* \} |
6160             \\ (?:$q_char) |
6161             \$` | \$\{`\} | \$ \s* PREMATCH | \$ \s* \{ \s* PREMATCH \s* \} | \$ \s* \{\^PREMATCH\} |
6162             \$& | \$\{&\} | \$ \s* MATCH | \$ \s* \{ \s* MATCH \s* \} | \$ \s* \{\^MATCH\} |
6163             \$ \s* POSTMATCH | \$ \s* \{ \s* POSTMATCH \s* \} | \$ \s* \{\^POSTMATCH\} |
6164             [\$\@] $qq_variable |
6165             \$ \s* \d+ |
6166             \$ \s* \{ \s* \d+ \s* \} |
6167             \$ \$ (?![\w\{]) |
6168             \$ \s* \$ \s* $qq_variable |
6169             \[\:\^ (?:alnum|alpha|ascii|blank|cntrl|digit|graph|lower|print|punct|space|upper|word|xdigit) :\] |
6170             \[\: (?:alnum|alpha|ascii|blank|cntrl|digit|graph|lower|print|punct|space|upper|word|xdigit) :\] |
6171             \[\^ |
6172             \(\? |
6173             (?:$q_char)
6174             )/oxmsg;
6175              
6176             # choice again delimiter
6177 0 0         if ($delimiter =~ / [\@:] /oxms) {
6178 0           my %octet = map {$_ => 1} @char;
  0            
6179 0 0         if (not $octet{')'}) {
    0          
    0          
    0          
6180 0           $delimiter = '(';
6181 0           $end_delimiter = ')';
6182             }
6183             elsif (not $octet{'}'}) {
6184 0           $delimiter = '{';
6185 0           $end_delimiter = '}';
6186             }
6187             elsif (not $octet{']'}) {
6188 0           $delimiter = '[';
6189 0           $end_delimiter = ']';
6190             }
6191             elsif (not $octet{'>'}) {
6192 0           $delimiter = '<';
6193 0           $end_delimiter = '>';
6194             }
6195             else {
6196 0           for my $char (qw( ! " $ % & * + - . / = ? ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
6197 0 0         if (not $octet{$char}) {
6198 0           $delimiter = $char;
6199 0           $end_delimiter = $char;
6200 0           last;
6201             }
6202             }
6203             }
6204             }
6205              
6206             # count '('
6207 0           my $parens = grep { $_ eq '(' } @char;
  0            
6208              
6209 0           my $left_e = 0;
6210 0           my $right_e = 0;
6211 0           for (my $i=0; $i <= $#char; $i++) {
6212              
6213             # "\L\u" --> "\u\L"
6214 0 0 0       if (($char[$i] eq '\L') and ($char[$i+1] eq '\u')) {
    0 0        
    0          
    0          
    0          
    0          
    0          
    0          
6215 0           @char[$i,$i+1] = @char[$i+1,$i];
6216             }
6217              
6218             # "\U\l" --> "\l\U"
6219             elsif (($char[$i] eq '\U') and ($char[$i+1] eq '\l')) {
6220 0           @char[$i,$i+1] = @char[$i+1,$i];
6221             }
6222              
6223             # octal escape sequence
6224             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
6225 0           $char[$i] = Char::Ekoi8u::octchr($1);
6226             }
6227              
6228             # hexadecimal escape sequence
6229             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
6230 0           $char[$i] = Char::Ekoi8u::hexchr($1);
6231             }
6232              
6233             # \N{CHARNAME} --> N\{CHARNAME}
6234             elsif ($char[$i] =~ /\A \\ (N) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
6235 0           $char[$i] = $1 . '\\' . $2;
6236             }
6237              
6238             # \p{PROPERTY} --> p\{PROPERTY}
6239             elsif ($char[$i] =~ /\A \\ (p) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
6240 0           $char[$i] = $1 . '\\' . $2;
6241             }
6242              
6243             # \P{PROPERTY} --> P\{PROPERTY}
6244             elsif ($char[$i] =~ /\A \\ (P) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
6245 0           $char[$i] = $1 . '\\' . $2;
6246             }
6247              
6248             # \p, \P, \X --> p, P, X
6249             elsif ($char[$i] =~ /\A \\ ( [pPX] ) \z/oxms) {
6250 0           $char[$i] = $1;
6251             }
6252              
6253 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          
6254             }
6255              
6256             # join separated multiple-octet
6257 0           elsif ($char[$i] =~ /\A (?: \\ [0-7]{2,3} | \\x [0-9A-Fa-f]{1,2}) \z/oxms) {
6258 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        
6259 0           $char[$i] .= join '', splice @char, $i+1, 3;
6260             }
6261             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)) {
6262 0           $char[$i] .= join '', splice @char, $i+1, 2;
6263             }
6264             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)) {
6265 0           $char[$i] .= join '', splice @char, $i+1, 1;
6266             }
6267             }
6268              
6269             # open character class [...]
6270             elsif ($char[$i] eq '[') {
6271 0           my $left = $i;
6272 0 0         if ($char[$i+1] eq ']') {
6273 0           $i++;
6274             }
6275 0           while (1) {
6276 0 0         if (++$i > $#char) {
6277 0           die __FILE__, ": Unmatched [] in regexp";
6278             }
6279 0 0         if ($char[$i] eq ']') {
6280 0           my $right = $i;
6281              
6282             # [...]
6283 0 0         if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
6284 0           splice @char, $left, $right-$left+1, sprintf(q{@{[Char::Ekoi8u::charlist_qr(%s,'%s')]}}, join(',', map {qq_stuff($delimiter,$end_delimiter,$_)} @char[$left+1..$right-1]), $modifier);
  0            
6285             }
6286             else {
6287 0           splice @char, $left, $right-$left+1, Char::Ekoi8u::charlist_qr(@char[$left+1..$right-1], $modifier);
6288             }
6289              
6290 0           $i = $left;
6291 0           last;
6292             }
6293             }
6294             }
6295              
6296             # open character class [^...]
6297             elsif ($char[$i] eq '[^') {
6298 0           my $left = $i;
6299 0 0         if ($char[$i+1] eq ']') {
6300 0           $i++;
6301             }
6302 0           while (1) {
6303 0 0         if (++$i > $#char) {
6304 0           die __FILE__, ": Unmatched [] in regexp";
6305             }
6306 0 0         if ($char[$i] eq ']') {
6307 0           my $right = $i;
6308              
6309             # [^...]
6310 0 0         if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
6311 0           splice @char, $left, $right-$left+1, sprintf(q{@{[Char::Ekoi8u::charlist_not_qr(%s,'%s')]}}, join(',', map {qq_stuff($delimiter,$end_delimiter,$_)} @char[$left+1..$right-1]), $modifier);
  0            
6312             }
6313             else {
6314 0           splice @char, $left, $right-$left+1, Char::Ekoi8u::charlist_not_qr(@char[$left+1..$right-1], $modifier);
6315             }
6316              
6317 0           $i = $left;
6318 0           last;
6319             }
6320             }
6321             }
6322              
6323             # rewrite character class or escape character
6324             elsif (my $char = character_class($char[$i],$modifier)) {
6325 0           $char[$i] = $char;
6326             }
6327              
6328             # /i modifier
6329             elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Char::Ekoi8u::uc($char[$i]) ne Char::Ekoi8u::fc($char[$i]))) {
6330 0 0         if (CORE::length(Char::Ekoi8u::fc($char[$i])) == 1) {
6331 0           $char[$i] = '[' . Char::Ekoi8u::uc($char[$i]) . Char::Ekoi8u::fc($char[$i]) . ']';
6332             }
6333             else {
6334 0           $char[$i] = '(?:' . Char::Ekoi8u::uc($char[$i]) . '|' . Char::Ekoi8u::fc($char[$i]) . ')';
6335             }
6336             }
6337              
6338             # \u \l \U \L \F \Q \E
6339             elsif ($char[$i] =~ /\A [<>] \z/oxms) {
6340 0 0         if ($right_e < $left_e) {
6341 0           $char[$i] = '\\' . $char[$i];
6342             }
6343             }
6344             elsif ($char[$i] eq '\u') {
6345 0           $char[$i] = '@{[Char::Ekoi8u::ucfirst qq<';
6346 0           $left_e++;
6347             }
6348             elsif ($char[$i] eq '\l') {
6349 0           $char[$i] = '@{[Char::Ekoi8u::lcfirst qq<';
6350 0           $left_e++;
6351             }
6352             elsif ($char[$i] eq '\U') {
6353 0           $char[$i] = '@{[Char::Ekoi8u::uc qq<';
6354 0           $left_e++;
6355             }
6356             elsif ($char[$i] eq '\L') {
6357 0           $char[$i] = '@{[Char::Ekoi8u::lc qq<';
6358 0           $left_e++;
6359             }
6360             elsif ($char[$i] eq '\F') {
6361 0           $char[$i] = '@{[Char::Ekoi8u::fc qq<';
6362 0           $left_e++;
6363             }
6364             elsif ($char[$i] eq '\Q') {
6365 0           $char[$i] = '@{[CORE::quotemeta qq<';
6366 0           $left_e++;
6367             }
6368             elsif ($char[$i] eq '\E') {
6369 0 0         if ($right_e < $left_e) {
6370 0           $char[$i] = '>]}';
6371 0           $right_e++;
6372             }
6373             else {
6374 0           $char[$i] = '';
6375             }
6376             }
6377             elsif ($char[$i] eq '\Q') {
6378 0           while (1) {
6379 0 0         if (++$i > $#char) {
6380 0           last;
6381             }
6382 0 0         if ($char[$i] eq '\E') {
6383 0           last;
6384             }
6385             }
6386             }
6387             elsif ($char[$i] eq '\E') {
6388             }
6389              
6390             # \0 --> \0
6391             elsif ($char[$i] =~ /\A \\ \s* 0 \z/oxms) {
6392             }
6393              
6394             # \g{N}, \g{-N}
6395              
6396             # P.108 Using Simple Patterns
6397             # in Chapter 7: In the World of Regular Expressions
6398             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
6399              
6400             # P.221 Capturing
6401             # in Chapter 5: Pattern Matching
6402             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
6403              
6404             # \g{-1}, \g{-2}, \g{-3} --> \g{-1}, \g{-2}, \g{-3}
6405             elsif ($char[$i] =~ /\A \\g \s* \{ \s* - \s* ([1-9][0-9]*) \s* \} \z/oxms) {
6406             }
6407              
6408             # \g{1}, \g{2}, \g{3} --> \g{2}, \g{3}, \g{4} (only when multibyte anchoring is enable)
6409             elsif ($char[$i] =~ /\A \\g \s* \{ \s* ([1-9][0-9]*) \s* \} \z/oxms) {
6410             }
6411              
6412             # \g1, \g2, \g3 --> \g2, \g3, \g4 (only when multibyte anchoring is enable)
6413             elsif ($char[$i] =~ /\A \\g \s* ([1-9][0-9]*) \z/oxms) {
6414             }
6415              
6416             # \1, \2, \3 --> \2, \3, \4 (only when multibyte anchoring is enable)
6417             elsif ($char[$i] =~ /\A \\ \s* ([1-9][0-9]*) \z/oxms) {
6418             }
6419              
6420             # $0 --> $0
6421             elsif ($char[$i] =~ /\A \$ 0 \z/oxms) {
6422 0 0         if ($ignorecase) {
6423 0           $char[$i] = '@{[Char::Ekoi8u::ignorecase(' . $char[$i] . ')]}';
6424             }
6425             }
6426             elsif ($char[$i] =~ /\A \$ \{ \s* 0 \s* \} \z/oxms) {
6427 0 0         if ($ignorecase) {
6428 0           $char[$i] = '@{[Char::Ekoi8u::ignorecase(' . $char[$i] . ')]}';
6429             }
6430             }
6431              
6432             # $$ --> $$
6433             elsif ($char[$i] =~ /\A \$\$ \z/oxms) {
6434             }
6435              
6436             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
6437             # $1, $2, $3 --> $1, $2, $3 otherwise
6438             elsif ($char[$i] =~ /\A \$ ([1-9][0-9]*) \z/oxms) {
6439 0           $char[$i] = e_capture($1);
6440 0 0         if ($ignorecase) {
6441 0           $char[$i] = '@{[Char::Ekoi8u::ignorecase(' . $char[$i] . ')]}';
6442             }
6443             }
6444             elsif ($char[$i] =~ /\A \$ \{ \s* ([1-9][0-9]*) \s* \} \z/oxms) {
6445 0           $char[$i] = e_capture($1);
6446 0 0         if ($ignorecase) {
6447 0           $char[$i] = '@{[Char::Ekoi8u::ignorecase(' . $char[$i] . ')]}';
6448             }
6449             }
6450              
6451             # $$foo[ ... ] --> $ $foo->[ ... ]
6452             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) ( \[ (?:$qq_bracket)*? \] ) \z/oxms) {
6453 0           $char[$i] = e_capture($1.'->'.$2);
6454 0 0         if ($ignorecase) {
6455 0           $char[$i] = '@{[Char::Ekoi8u::ignorecase(' . $char[$i] . ')]}';
6456             }
6457             }
6458              
6459             # $$foo{ ... } --> $ $foo->{ ... }
6460             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) ( \{ (?:$qq_brace)*? \} ) \z/oxms) {
6461 0           $char[$i] = e_capture($1.'->'.$2);
6462 0 0         if ($ignorecase) {
6463 0           $char[$i] = '@{[Char::Ekoi8u::ignorecase(' . $char[$i] . ')]}';
6464             }
6465             }
6466              
6467             # $$foo
6468             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) \z/oxms) {
6469 0           $char[$i] = e_capture($1);
6470 0 0         if ($ignorecase) {
6471 0           $char[$i] = '@{[Char::Ekoi8u::ignorecase(' . $char[$i] . ')]}';
6472             }
6473             }
6474              
6475             # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Char::Ekoi8u::PREMATCH()
6476             elsif ($char[$i] =~ /\A ( \$` | \$\{`\} | \$ \s* PREMATCH | \$ \s* \{ \s* PREMATCH \s* \} | \$ \s* \{\^PREMATCH\} ) \z/oxmsgc) {
6477 0 0         if ($ignorecase) {
6478 0           $char[$i] = '@{[Char::Ekoi8u::ignorecase(Char::Ekoi8u::PREMATCH())]}';
6479             }
6480             else {
6481 0           $char[$i] = '@{[Char::Ekoi8u::PREMATCH()]}';
6482             }
6483             }
6484              
6485             # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Char::Ekoi8u::MATCH()
6486             elsif ($char[$i] =~ /\A ( \$& | \$\{&\} | \$ \s* MATCH | \$ \s* \{ \s* MATCH \s* \} | \$ \s* \{\^MATCH\} ) \z/oxmsgc) {
6487 0 0         if ($ignorecase) {
6488 0           $char[$i] = '@{[Char::Ekoi8u::ignorecase(Char::Ekoi8u::MATCH())]}';
6489             }
6490             else {
6491 0           $char[$i] = '@{[Char::Ekoi8u::MATCH()]}';
6492             }
6493             }
6494              
6495             # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Char::Ekoi8u::POSTMATCH()
6496             elsif ($char[$i] =~ /\A ( \$ \s* POSTMATCH | \$ \s* \{ \s* POSTMATCH \s* \} | \$ \s* \{\^POSTMATCH\} ) \z/oxmsgc) {
6497 0 0         if ($ignorecase) {
6498 0           $char[$i] = '@{[Char::Ekoi8u::ignorecase(Char::Ekoi8u::POSTMATCH())]}';
6499             }
6500             else {
6501 0           $char[$i] = '@{[Char::Ekoi8u::POSTMATCH()]}';
6502             }
6503             }
6504              
6505             # ${ foo }
6506             elsif ($char[$i] =~ /\A \$ \s* \{ ( \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* ) \} \z/oxms) {
6507 0 0         if ($ignorecase) {
6508 0           $char[$i] = '@{[Char::Ekoi8u::ignorecase(' . $char[$i] . ')]}';
6509             }
6510             }
6511              
6512             # ${ ... }
6513             elsif ($char[$i] =~ /\A \$ \s* \{ \s* ( .+ ) \s* \} \z/oxms) {
6514 0           $char[$i] = e_capture($1);
6515 0 0         if ($ignorecase) {
6516 0           $char[$i] = '@{[Char::Ekoi8u::ignorecase(' . $char[$i] . ')]}';
6517             }
6518             }
6519              
6520             # $scalar or @array
6521             elsif ($char[$i] =~ /\A [\$\@].+ /oxms) {
6522 0           $char[$i] = e_string($char[$i]);
6523 0 0         if ($ignorecase) {
6524 0           $char[$i] = '@{[Char::Ekoi8u::ignorecase(' . $char[$i] . ')]}';
6525             }
6526             }
6527              
6528             # quote character before ? + * {
6529             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
6530 0 0         if ($char[$i-1] =~ /\A (?:\\[0-7]{2,3}|\\x[0-9-A-Fa-f]{1,2}) \z/oxms) {
6531             }
6532             else {
6533 0           $char[$i-1] = '(?:' . $char[$i-1] . ')';
6534             }
6535             }
6536             }
6537              
6538             # make regexp string
6539 0           my $prematch = '';
6540 0           $modifier =~ tr/i//d;
6541 0 0         if ($left_e > $right_e) {
6542 0           return join '', $ope, $delimiter, $prematch, '(?:', @char, '>]}' x ($left_e - $right_e), ')', $matched, $end_delimiter, $modifier;
6543             }
6544 0           return join '', $ope, $delimiter, $prematch, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
6545             }
6546              
6547             #
6548             # escape regexp (s'here'' or s'here''b)
6549             #
6550             sub e_s1_q {
6551 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6552 0   0       $modifier ||= '';
6553              
6554 0           $modifier =~ tr/p//d;
6555 0 0         if ($modifier =~ /([adlu])/oxms) {
6556 0           my $line = 0;
6557 0           for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
6558 0 0         if ($filename ne __FILE__) {
6559 0           $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
6560 0           last;
6561             }
6562             }
6563 0           die qq{Unsupported modifier "$1" used at line $line.\n};
6564             }
6565              
6566 0           $slash = 'div';
6567              
6568             # literal null string pattern
6569 0 0         if ($string eq '') {
    0          
6570 0           $modifier =~ tr/bB//d;
6571 0           $modifier =~ tr/i//d;
6572 0           return join '', $ope, $delimiter, $end_delimiter, $modifier;
6573             }
6574              
6575             # with /b /B modifier
6576             elsif ($modifier =~ tr/bB//d) {
6577 0           return e_s1_qb($ope,$delimiter,$end_delimiter,$string,$modifier);
6578             }
6579              
6580             # without /b /B modifier
6581             else {
6582 0           return e_s1_qt($ope,$delimiter,$end_delimiter,$string,$modifier);
6583             }
6584             }
6585              
6586             #
6587             # escape regexp (s'here'')
6588             #
6589             sub e_s1_qt {
6590 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6591              
6592 0 0         my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
6593              
6594             # split regexp
6595 0           my @char = $string =~ /\G(
6596             \[\:\^ [a-z]+ \:\] |
6597             \[\: [a-z]+ \:\] |
6598             \[\^ |
6599             [\$\@\/\\] |
6600             \\? (?:$q_char)
6601             )/oxmsg;
6602              
6603             # unescape character
6604 0           for (my $i=0; $i <= $#char; $i++) {
6605 0 0 0       if (0) {
    0 0        
    0 0        
    0          
    0          
    0          
6606             }
6607              
6608             # open character class [...]
6609 0           elsif ($char[$i] eq '[') {
6610 0           my $left = $i;
6611 0 0         if ($char[$i+1] eq ']') {
6612 0           $i++;
6613             }
6614 0           while (1) {
6615 0 0         if (++$i > $#char) {
6616 0           die __FILE__, ": Unmatched [] in regexp";
6617             }
6618 0 0         if ($char[$i] eq ']') {
6619 0           my $right = $i;
6620              
6621             # [...]
6622 0           splice @char, $left, $right-$left+1, Char::Ekoi8u::charlist_qr(@char[$left+1..$right-1], $modifier);
6623              
6624 0           $i = $left;
6625 0           last;
6626             }
6627             }
6628             }
6629              
6630             # open character class [^...]
6631             elsif ($char[$i] eq '[^') {
6632 0           my $left = $i;
6633 0 0         if ($char[$i+1] eq ']') {
6634 0           $i++;
6635             }
6636 0           while (1) {
6637 0 0         if (++$i > $#char) {
6638 0           die __FILE__, ": Unmatched [] in regexp";
6639             }
6640 0 0         if ($char[$i] eq ']') {
6641 0           my $right = $i;
6642              
6643             # [^...]
6644 0           splice @char, $left, $right-$left+1, Char::Ekoi8u::charlist_not_qr(@char[$left+1..$right-1], $modifier);
6645              
6646 0           $i = $left;
6647 0           last;
6648             }
6649             }
6650             }
6651              
6652             # escape $ @ / and \
6653             elsif ($char[$i] =~ /\A [\$\@\/\\] \z/oxms) {
6654 0           $char[$i] = '\\' . $char[$i];
6655             }
6656              
6657             # rewrite character class or escape character
6658             elsif (my $char = character_class($char[$i],$modifier)) {
6659 0           $char[$i] = $char;
6660             }
6661              
6662             # /i modifier
6663             elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Char::Ekoi8u::uc($char[$i]) ne Char::Ekoi8u::fc($char[$i]))) {
6664 0 0         if (CORE::length(Char::Ekoi8u::fc($char[$i])) == 1) {
6665 0           $char[$i] = '[' . Char::Ekoi8u::uc($char[$i]) . Char::Ekoi8u::fc($char[$i]) . ']';
6666             }
6667             else {
6668 0           $char[$i] = '(?:' . Char::Ekoi8u::uc($char[$i]) . '|' . Char::Ekoi8u::fc($char[$i]) . ')';
6669             }
6670             }
6671              
6672             # quote character before ? + * {
6673             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
6674 0 0         if ($char[$i-1] =~ /\A [\x00-\xFF] \z/oxms) {
6675             }
6676             else {
6677 0           $char[$i-1] = '(?:' . $char[$i-1] . ')';
6678             }
6679             }
6680             }
6681              
6682 0           $modifier =~ tr/i//d;
6683 0           $delimiter = '/';
6684 0           $end_delimiter = '/';
6685 0           my $prematch = '';
6686 0           return join '', $ope, $delimiter, $prematch, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
6687             }
6688              
6689             #
6690             # escape regexp (s'here''b)
6691             #
6692             sub e_s1_qb {
6693 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6694              
6695             # split regexp
6696 0           my @char = $string =~ /\G(
6697             \\\\ |
6698             [\$\@\/\\] |
6699             [\x00-\xFF]
6700             )/oxmsg;
6701              
6702             # unescape character
6703 0           for (my $i=0; $i <= $#char; $i++) {
6704 0 0         if (0) {
    0          
6705             }
6706              
6707             # remain \\
6708 0           elsif ($char[$i] eq '\\\\') {
6709             }
6710              
6711             # escape $ @ / and \
6712             elsif ($char[$i] =~ /\A [\$\@\/\\] \z/oxms) {
6713 0           $char[$i] = '\\' . $char[$i];
6714             }
6715             }
6716              
6717 0           $delimiter = '/';
6718 0           $end_delimiter = '/';
6719 0           my $prematch = '';
6720 0           return join '', $ope, $delimiter, $prematch, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
6721             }
6722              
6723             #
6724             # escape regexp (s''here')
6725             #
6726             sub e_s2_q {
6727 0     0 0   my($ope,$delimiter,$end_delimiter,$string) = @_;
6728              
6729 0           $slash = 'div';
6730              
6731 0           my @char = $string =~ / \G (\\\\|[\$\@\/\\]|$q_char) /oxmsg;
6732 0           for (my $i=0; $i <= $#char; $i++) {
6733 0 0         if (0) {
    0          
6734             }
6735              
6736             # not escape \\
6737 0           elsif ($char[$i] =~ /\A \\\\ \z/oxms) {
6738             }
6739              
6740             # escape $ @ / and \
6741             elsif ($char[$i] =~ /\A [\$\@\/\\] \z/oxms) {
6742 0           $char[$i] = '\\' . $char[$i];
6743             }
6744             }
6745              
6746 0           return join '', $ope, $delimiter, @char, $end_delimiter;
6747             }
6748              
6749             #
6750             # escape regexp (s/here/and here/modifier)
6751             #
6752             sub e_sub {
6753 0     0 0   my($variable,$delimiter1,$pattern,$end_delimiter1,$delimiter2,$replacement,$end_delimiter2,$modifier) = @_;
6754 0   0       $modifier ||= '';
6755              
6756 0           $modifier =~ tr/p//d;
6757 0 0         if ($modifier =~ /([adlu])/oxms) {
6758 0           my $line = 0;
6759 0           for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
6760 0 0         if ($filename ne __FILE__) {
6761 0           $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
6762 0           last;
6763             }
6764             }
6765 0           die qq{Unsupported modifier "$1" used at line $line.\n};
6766             }
6767              
6768 0 0         if ($variable eq '') {
6769 0           $variable = '$_';
6770 0           $bind_operator = ' =~ ';
6771             }
6772              
6773 0           $slash = 'div';
6774              
6775             # P.128 Start of match (or end of previous match): \G
6776             # P.130 Advanced Use of \G with Perl
6777             # in Chapter 3: Overview of Regular Expression Features and Flavors
6778             # P.312 Iterative Matching: Scalar Context, with /g
6779             # in Chapter 7: Perl
6780             # of ISBN 0-596-00289-0 Mastering Regular Expressions, Second edition
6781              
6782             # P.181 Where You Left Off: The \G Assertion
6783             # in Chapter 5: Pattern Matching
6784             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
6785              
6786             # P.220 Where You Left Off: The \G Assertion
6787             # in Chapter 5: Pattern Matching
6788             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
6789              
6790 0           my $e_modifier = $modifier =~ tr/e//d;
6791 0           my $r_modifier = $modifier =~ tr/r//d;
6792              
6793 0           my $my = '';
6794 0 0         if ($variable =~ s/\A \( \s* ( (?: local \b | my \b | our \b | state \b )? .+ ) \) \z/$1/oxms) {
6795 0           $my = $variable;
6796 0           $variable =~ s/ (?: local \b | my \b | our \b | state \b ) \s* //oxms;
6797 0           $variable =~ s/ = .+ \z//oxms;
6798             }
6799              
6800 0           (my $variable_basename = $variable) =~ s/ [\[\{].* \z//oxms;
6801 0           $variable_basename =~ s/ \s+ \z//oxms;
6802              
6803             # quote replacement string
6804 0           my $e_replacement = '';
6805 0 0         if ($e_modifier >= 1) {
6806 0           $e_replacement = e_qq('', '', '', $replacement);
6807 0           $e_modifier--;
6808             }
6809             else {
6810 0 0         if ($delimiter2 eq "'") {
6811 0           $e_replacement = e_s2_q('qq', '/', '/', $replacement);
6812             }
6813             else {
6814 0           $e_replacement = e_qq ('qq', $delimiter2, $end_delimiter2, $replacement);
6815             }
6816             }
6817              
6818 0           my $sub = '';
6819              
6820             # with /r
6821 0 0         if ($r_modifier) {
6822 0 0         if (0) {
6823             }
6824              
6825             # s///gr without multibyte anchoring
6826 0           elsif ($modifier =~ /g/oxms) {
6827 0 0         $sub = sprintf(
6828             # 1 2 3 4 5
6829             q,
6830              
6831             $variable, # 1
6832             ($delimiter1 eq "'") ? # 2
6833             e_s1_q('m', $delimiter1, $end_delimiter1, $pattern, $modifier) : # :
6834             e_s1 ('m', $delimiter1, $end_delimiter1, $pattern, $modifier), # :
6835             $s_matched, # 3
6836             $e_replacement, # 4
6837             '$Char::KOI8U::re_r=CORE::eval $Char::KOI8U::re_r; ' x $e_modifier, # 5
6838             );
6839             }
6840              
6841             # s///r
6842             else {
6843              
6844 0           my $prematch = q{$`};
6845              
6846 0 0         $sub = sprintf(
6847             # 1 2 3 4 5 6 7
6848             q<(%s =~ %s) ? CORE::eval{%s local $^W=0; local $Char::KOI8U::re_r=%s; %s"%s$Char::KOI8U::re_r$'" } : %s>,
6849              
6850             $variable, # 1
6851             ($delimiter1 eq "'") ? # 2
6852             e_s1_q('m', $delimiter1, $end_delimiter1, $pattern, $modifier) : # :
6853             e_s1 ('m', $delimiter1, $end_delimiter1, $pattern, $modifier), # :
6854             $s_matched, # 3
6855             $e_replacement, # 4
6856             '$Char::KOI8U::re_r=CORE::eval $Char::KOI8U::re_r; ' x $e_modifier, # 5
6857             $prematch, # 6
6858             $variable, # 7
6859             );
6860             }
6861              
6862             # $var !~ s///r doesn't make sense
6863 0 0         if ($bind_operator =~ / !~ /oxms) {
6864 0           $sub = q{die("$0: Using !~ with s///r doesn't make sense"), } . $sub;
6865             }
6866             }
6867              
6868             # without /r
6869             else {
6870 0 0         if (0) {
6871             }
6872              
6873             # s///g without multibyte anchoring
6874 0           elsif ($modifier =~ /g/oxms) {
6875 0 0         $sub = sprintf(
    0          
6876             # 1 2 3 4 5 6 7 8
6877             q,
6878              
6879             $variable, # 1
6880             ($delimiter1 eq "'") ? # 2
6881             e_s1_q('m', $delimiter1, $end_delimiter1, $pattern, $modifier) : # :
6882             e_s1 ('m', $delimiter1, $end_delimiter1, $pattern, $modifier), # :
6883             $s_matched, # 3
6884             $e_replacement, # 4
6885             '$Char::KOI8U::re_r=CORE::eval $Char::KOI8U::re_r; ' x $e_modifier, # 5
6886             $variable, # 6
6887             $variable, # 7
6888             ($bind_operator =~ / !~ /oxms) ? '!' : '', # 8
6889             );
6890             }
6891              
6892             # s///
6893             else {
6894              
6895 0           my $prematch = q{$`};
6896              
6897 0 0         $sub = sprintf(
    0          
6898              
6899             ($bind_operator =~ / =~ /oxms) ?
6900              
6901             # 1 2 3 4 5 6 7 8
6902             q<(%s%s%s) ? CORE::eval{%s local $^W=0; local $Char::KOI8U::re_r=%s; %s%s="%s$Char::KOI8U::re_r$'"; 1 } : undef> :
6903              
6904             # 1 2 3 4 5 6 7 8
6905             q<(%s%s%s) ? 1 : CORE::eval{%s local $^W=0; local $Char::KOI8U::re_r=%s; %s%s="%s$Char::KOI8U::re_r$'"; undef }>,
6906              
6907             $variable, # 1
6908             $bind_operator, # 2
6909             ($delimiter1 eq "'") ? # 3
6910             e_s1_q('m', $delimiter1, $end_delimiter1, $pattern, $modifier) : # :
6911             e_s1 ('m', $delimiter1, $end_delimiter1, $pattern, $modifier), # :
6912             $s_matched, # 4
6913             $e_replacement, # 5
6914             '$Char::KOI8U::re_r=CORE::eval $Char::KOI8U::re_r; ' x $e_modifier, # 6
6915             $variable, # 7
6916             $prematch, # 8
6917             );
6918             }
6919             }
6920              
6921             # (my $foo = $bar) =~ s/// --> (my $foo = $bar, CORE::eval { ... })[1]
6922 0 0         if ($my ne '') {
6923 0           $sub = "($my, $sub)[1]";
6924             }
6925              
6926             # clear s/// variable
6927 0           $sub_variable = '';
6928 0           $bind_operator = '';
6929              
6930 0           return $sub;
6931             }
6932              
6933             #
6934             # escape regexp of split qr//
6935             #
6936             sub e_split {
6937 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6938 0   0       $modifier ||= '';
6939              
6940 0           $modifier =~ tr/p//d;
6941 0 0         if ($modifier =~ /([adlu])/oxms) {
6942 0           my $line = 0;
6943 0           for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
6944 0 0         if ($filename ne __FILE__) {
6945 0           $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
6946 0           last;
6947             }
6948             }
6949 0           die qq{Unsupported modifier "$1" used at line $line.\n};
6950             }
6951              
6952 0           $slash = 'div';
6953              
6954             # /b /B modifier
6955 0 0         if ($modifier =~ tr/bB//d) {
6956 0           return join '', 'split', $ope, $delimiter, $string, $end_delimiter, $modifier;
6957             }
6958              
6959 0 0         my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
6960 0           my $metachar = qr/[\@\\|[\]{^]/oxms;
6961              
6962             # split regexp
6963 0           my @char = $string =~ /\G(
6964             \\o\{ [0-7]+ \} |
6965             \\ [0-7]{2,3} |
6966             \\x\{ [0-9A-Fa-f]+ \} |
6967             \\x [0-9A-Fa-f]{1,2} |
6968             \\c [\x40-\x5F] |
6969             \\N\{ [^0-9\}][^\}]* \} |
6970             \\p\{ [^0-9\}][^\}]* \} |
6971             \\P\{ [^0-9\}][^\}]* \} |
6972             \\ (?:$q_char) |
6973             \$` | \$\{`\} | \$ \s* PREMATCH | \$ \s* \{ \s* PREMATCH \s* \} | \$ \s* \{\^PREMATCH\} |
6974             \$& | \$\{&\} | \$ \s* MATCH | \$ \s* \{ \s* MATCH \s* \} | \$ \s* \{\^MATCH\} |
6975             \$ \s* POSTMATCH | \$ \s* \{ \s* POSTMATCH \s* \} | \$ \s* \{\^POSTMATCH\} |
6976             [\$\@] $qq_variable |
6977             \$ \s* \d+ |
6978             \$ \s* \{ \s* \d+ \s* \} |
6979             \$ \$ (?![\w\{]) |
6980             \$ \s* \$ \s* $qq_variable |
6981             \[\:\^ (?:alnum|alpha|ascii|blank|cntrl|digit|graph|lower|print|punct|space|upper|word|xdigit) :\] |
6982             \[\: (?:alnum|alpha|ascii|blank|cntrl|digit|graph|lower|print|punct|space|upper|word|xdigit) :\] |
6983             \[\^ |
6984             \(\? |
6985             (?:$q_char)
6986             )/oxmsg;
6987              
6988 0           my $left_e = 0;
6989 0           my $right_e = 0;
6990 0           for (my $i=0; $i <= $#char; $i++) {
6991              
6992             # "\L\u" --> "\u\L"
6993 0 0 0       if (($char[$i] eq '\L') and ($char[$i+1] eq '\u')) {
    0 0        
    0          
    0          
    0          
    0          
    0          
    0          
6994 0           @char[$i,$i+1] = @char[$i+1,$i];
6995             }
6996              
6997             # "\U\l" --> "\l\U"
6998             elsif (($char[$i] eq '\U') and ($char[$i+1] eq '\l')) {
6999 0           @char[$i,$i+1] = @char[$i+1,$i];
7000             }
7001              
7002             # octal escape sequence
7003             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
7004 0           $char[$i] = Char::Ekoi8u::octchr($1);
7005             }
7006              
7007             # hexadecimal escape sequence
7008             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
7009 0           $char[$i] = Char::Ekoi8u::hexchr($1);
7010             }
7011              
7012             # \N{CHARNAME} --> N\{CHARNAME}
7013             elsif ($char[$i] =~ /\A \\ (N) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
7014 0           $char[$i] = $1 . '\\' . $2;
7015             }
7016              
7017             # \p{PROPERTY} --> p\{PROPERTY}
7018             elsif ($char[$i] =~ /\A \\ (p) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
7019 0           $char[$i] = $1 . '\\' . $2;
7020             }
7021              
7022             # \P{PROPERTY} --> P\{PROPERTY}
7023             elsif ($char[$i] =~ /\A \\ (P) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
7024 0           $char[$i] = $1 . '\\' . $2;
7025             }
7026              
7027             # \p, \P, \X --> p, P, X
7028             elsif ($char[$i] =~ /\A \\ ( [pPX] ) \z/oxms) {
7029 0           $char[$i] = $1;
7030             }
7031              
7032 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          
7033             }
7034              
7035             # join separated multiple-octet
7036 0           elsif ($char[$i] =~ /\A (?: \\ [0-7]{2,3} | \\x [0-9A-Fa-f]{1,2}) \z/oxms) {
7037 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        
7038 0           $char[$i] .= join '', splice @char, $i+1, 3;
7039             }
7040             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)) {
7041 0           $char[$i] .= join '', splice @char, $i+1, 2;
7042             }
7043             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)) {
7044 0           $char[$i] .= join '', splice @char, $i+1, 1;
7045             }
7046             }
7047              
7048             # open character class [...]
7049             elsif ($char[$i] eq '[') {
7050 0           my $left = $i;
7051 0 0         if ($char[$i+1] eq ']') {
7052 0           $i++;
7053             }
7054 0           while (1) {
7055 0 0         if (++$i > $#char) {
7056 0           die __FILE__, ": Unmatched [] in regexp";
7057             }
7058 0 0         if ($char[$i] eq ']') {
7059 0           my $right = $i;
7060              
7061             # [...]
7062 0 0         if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
7063 0           splice @char, $left, $right-$left+1, sprintf(q{@{[Char::Ekoi8u::charlist_qr(%s,'%s')]}}, join(',', map {qq_stuff($delimiter,$end_delimiter,$_)} @char[$left+1..$right-1]), $modifier);
  0            
7064             }
7065             else {
7066 0           splice @char, $left, $right-$left+1, Char::Ekoi8u::charlist_qr(@char[$left+1..$right-1], $modifier);
7067             }
7068              
7069 0           $i = $left;
7070 0           last;
7071             }
7072             }
7073             }
7074              
7075             # open character class [^...]
7076             elsif ($char[$i] eq '[^') {
7077 0           my $left = $i;
7078 0 0         if ($char[$i+1] eq ']') {
7079 0           $i++;
7080             }
7081 0           while (1) {
7082 0 0         if (++$i > $#char) {
7083 0           die __FILE__, ": Unmatched [] in regexp";
7084             }
7085 0 0         if ($char[$i] eq ']') {
7086 0           my $right = $i;
7087              
7088             # [^...]
7089 0 0         if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
7090 0           splice @char, $left, $right-$left+1, sprintf(q{@{[Char::Ekoi8u::charlist_not_qr(%s,'%s')]}}, join(',', map {qq_stuff($delimiter,$end_delimiter,$_)} @char[$left+1..$right-1]), $modifier);
  0            
7091             }
7092             else {
7093 0           splice @char, $left, $right-$left+1, Char::Ekoi8u::charlist_not_qr(@char[$left+1..$right-1], $modifier);
7094             }
7095              
7096 0           $i = $left;
7097 0           last;
7098             }
7099             }
7100             }
7101              
7102             # rewrite character class or escape character
7103             elsif (my $char = character_class($char[$i],$modifier)) {
7104 0           $char[$i] = $char;
7105             }
7106              
7107             # P.794 29.2.161. split
7108             # in Chapter 29: Functions
7109             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
7110              
7111             # P.951 split
7112             # in Chapter 27: Functions
7113             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
7114              
7115             # said "The //m modifier is assumed when you split on the pattern /^/",
7116             # but perl5.008 is not so. Therefore, this software adds //m.
7117             # (and so on)
7118              
7119             # split(m/^/) --> split(m/^/m)
7120             elsif (($char[$i] eq '^') and ($modifier !~ /m/oxms)) {
7121 0           $modifier .= 'm';
7122             }
7123              
7124             # /i modifier
7125             elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Char::Ekoi8u::uc($char[$i]) ne Char::Ekoi8u::fc($char[$i]))) {
7126 0 0         if (CORE::length(Char::Ekoi8u::fc($char[$i])) == 1) {
7127 0           $char[$i] = '[' . Char::Ekoi8u::uc($char[$i]) . Char::Ekoi8u::fc($char[$i]) . ']';
7128             }
7129             else {
7130 0           $char[$i] = '(?:' . Char::Ekoi8u::uc($char[$i]) . '|' . Char::Ekoi8u::fc($char[$i]) . ')';
7131             }
7132             }
7133              
7134             # \u \l \U \L \F \Q \E
7135             elsif ($char[$i] =~ /\A ([<>]) \z/oxms) {
7136 0 0         if ($right_e < $left_e) {
7137 0           $char[$i] = '\\' . $char[$i];
7138             }
7139             }
7140             elsif ($char[$i] eq '\u') {
7141 0           $char[$i] = '@{[Char::Ekoi8u::ucfirst qq<';
7142 0           $left_e++;
7143             }
7144             elsif ($char[$i] eq '\l') {
7145 0           $char[$i] = '@{[Char::Ekoi8u::lcfirst qq<';
7146 0           $left_e++;
7147             }
7148             elsif ($char[$i] eq '\U') {
7149 0           $char[$i] = '@{[Char::Ekoi8u::uc qq<';
7150 0           $left_e++;
7151             }
7152             elsif ($char[$i] eq '\L') {
7153 0           $char[$i] = '@{[Char::Ekoi8u::lc qq<';
7154 0           $left_e++;
7155             }
7156             elsif ($char[$i] eq '\F') {
7157 0           $char[$i] = '@{[Char::Ekoi8u::fc qq<';
7158 0           $left_e++;
7159             }
7160             elsif ($char[$i] eq '\Q') {
7161 0           $char[$i] = '@{[CORE::quotemeta qq<';
7162 0           $left_e++;
7163             }
7164             elsif ($char[$i] eq '\E') {
7165 0 0         if ($right_e < $left_e) {
7166 0           $char[$i] = '>]}';
7167 0           $right_e++;
7168             }
7169             else {
7170 0           $char[$i] = '';
7171             }
7172             }
7173             elsif ($char[$i] eq '\Q') {
7174 0           while (1) {
7175 0 0         if (++$i > $#char) {
7176 0           last;
7177             }
7178 0 0         if ($char[$i] eq '\E') {
7179 0           last;
7180             }
7181             }
7182             }
7183             elsif ($char[$i] eq '\E') {
7184             }
7185              
7186             # $0 --> $0
7187             elsif ($char[$i] =~ /\A \$ 0 \z/oxms) {
7188 0 0         if ($ignorecase) {
7189 0           $char[$i] = '@{[Char::Ekoi8u::ignorecase(' . $char[$i] . ')]}';
7190             }
7191             }
7192             elsif ($char[$i] =~ /\A \$ \{ \s* 0 \s* \} \z/oxms) {
7193 0 0         if ($ignorecase) {
7194 0           $char[$i] = '@{[Char::Ekoi8u::ignorecase(' . $char[$i] . ')]}';
7195             }
7196             }
7197              
7198             # $$ --> $$
7199             elsif ($char[$i] =~ /\A \$\$ \z/oxms) {
7200             }
7201              
7202             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
7203             # $1, $2, $3 --> $1, $2, $3 otherwise
7204             elsif ($char[$i] =~ /\A \$ ([1-9][0-9]*) \z/oxms) {
7205 0           $char[$i] = e_capture($1);
7206 0 0         if ($ignorecase) {
7207 0           $char[$i] = '@{[Char::Ekoi8u::ignorecase(' . $char[$i] . ')]}';
7208             }
7209             }
7210             elsif ($char[$i] =~ /\A \$ \{ \s* ([1-9][0-9]*) \s* \} \z/oxms) {
7211 0           $char[$i] = e_capture($1);
7212 0 0         if ($ignorecase) {
7213 0           $char[$i] = '@{[Char::Ekoi8u::ignorecase(' . $char[$i] . ')]}';
7214             }
7215             }
7216              
7217             # $$foo[ ... ] --> $ $foo->[ ... ]
7218             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) ( \[ (?:$qq_bracket)*? \] ) \z/oxms) {
7219 0           $char[$i] = e_capture($1.'->'.$2);
7220 0 0         if ($ignorecase) {
7221 0           $char[$i] = '@{[Char::Ekoi8u::ignorecase(' . $char[$i] . ')]}';
7222             }
7223             }
7224              
7225             # $$foo{ ... } --> $ $foo->{ ... }
7226             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) ( \{ (?:$qq_brace)*? \} ) \z/oxms) {
7227 0           $char[$i] = e_capture($1.'->'.$2);
7228 0 0         if ($ignorecase) {
7229 0           $char[$i] = '@{[Char::Ekoi8u::ignorecase(' . $char[$i] . ')]}';
7230             }
7231             }
7232              
7233             # $$foo
7234             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) \z/oxms) {
7235 0           $char[$i] = e_capture($1);
7236 0 0         if ($ignorecase) {
7237 0           $char[$i] = '@{[Char::Ekoi8u::ignorecase(' . $char[$i] . ')]}';
7238             }
7239             }
7240              
7241             # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Char::Ekoi8u::PREMATCH()
7242             elsif ($char[$i] =~ /\A ( \$` | \$\{`\} | \$ \s* PREMATCH | \$ \s* \{ \s* PREMATCH \s* \} | \$ \s* \{\^PREMATCH\} ) \z/oxmsgc) {
7243 0 0         if ($ignorecase) {
7244 0           $char[$i] = '@{[Char::Ekoi8u::ignorecase(Char::Ekoi8u::PREMATCH())]}';
7245             }
7246             else {
7247 0           $char[$i] = '@{[Char::Ekoi8u::PREMATCH()]}';
7248             }
7249             }
7250              
7251             # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Char::Ekoi8u::MATCH()
7252             elsif ($char[$i] =~ /\A ( \$& | \$\{&\} | \$ \s* MATCH | \$ \s* \{ \s* MATCH \s* \} | \$ \s* \{\^MATCH\} ) \z/oxmsgc) {
7253 0 0         if ($ignorecase) {
7254 0           $char[$i] = '@{[Char::Ekoi8u::ignorecase(Char::Ekoi8u::MATCH())]}';
7255             }
7256             else {
7257 0           $char[$i] = '@{[Char::Ekoi8u::MATCH()]}';
7258             }
7259             }
7260              
7261             # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Char::Ekoi8u::POSTMATCH()
7262             elsif ($char[$i] =~ /\A ( \$ \s* POSTMATCH | \$ \s* \{ \s* POSTMATCH \s* \} | \$ \s* \{\^POSTMATCH\} ) \z/oxmsgc) {
7263 0 0         if ($ignorecase) {
7264 0           $char[$i] = '@{[Char::Ekoi8u::ignorecase(Char::Ekoi8u::POSTMATCH())]}';
7265             }
7266             else {
7267 0           $char[$i] = '@{[Char::Ekoi8u::POSTMATCH()]}';
7268             }
7269             }
7270              
7271             # ${ foo }
7272             elsif ($char[$i] =~ /\A \$ \s* \{ ( \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* ) \} \z/oxms) {
7273 0 0         if ($ignorecase) {
7274 0           $char[$i] = '@{[Char::Ekoi8u::ignorecase(' . $1 . ')]}';
7275             }
7276             }
7277              
7278             # ${ ... }
7279             elsif ($char[$i] =~ /\A \$ \s* \{ \s* ( .+ ) \s* \} \z/oxms) {
7280 0           $char[$i] = e_capture($1);
7281 0 0         if ($ignorecase) {
7282 0           $char[$i] = '@{[Char::Ekoi8u::ignorecase(' . $char[$i] . ')]}';
7283             }
7284             }
7285              
7286             # $scalar or @array
7287             elsif ($char[$i] =~ /\A [\$\@].+ /oxms) {
7288 0           $char[$i] = e_string($char[$i]);
7289 0 0         if ($ignorecase) {
7290 0           $char[$i] = '@{[Char::Ekoi8u::ignorecase(' . $char[$i] . ')]}';
7291             }
7292             }
7293              
7294             # quote character before ? + * {
7295             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
7296 0 0         if ($char[$i-1] =~ /\A (?:\\[0-7]{2,3}|\\x[0-9-A-Fa-f]{1,2}) \z/oxms) {
7297             }
7298             else {
7299 0           $char[$i-1] = '(?:' . $char[$i-1] . ')';
7300             }
7301             }
7302             }
7303              
7304             # make regexp string
7305 0           $modifier =~ tr/i//d;
7306 0 0         if ($left_e > $right_e) {
7307 0           return join '', 'Char::Ekoi8u::split', $ope, $delimiter, @char, '>]}' x ($left_e - $right_e), $end_delimiter, $modifier;
7308             }
7309 0           return join '', 'Char::Ekoi8u::split', $ope, $delimiter, @char, $end_delimiter, $modifier;
7310             }
7311              
7312             #
7313             # escape regexp of split qr''
7314             #
7315             sub e_split_q {
7316 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
7317 0   0       $modifier ||= '';
7318              
7319 0           $modifier =~ tr/p//d;
7320 0 0         if ($modifier =~ /([adlu])/oxms) {
7321 0           my $line = 0;
7322 0           for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
7323 0 0         if ($filename ne __FILE__) {
7324 0           $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
7325 0           last;
7326             }
7327             }
7328 0           die qq{Unsupported modifier "$1" used at line $line.\n};
7329             }
7330              
7331 0           $slash = 'div';
7332              
7333             # /b /B modifier
7334 0 0         if ($modifier =~ tr/bB//d) {
7335 0           return join '', 'split', $ope, $delimiter, $string, $end_delimiter, $modifier;
7336             }
7337              
7338 0 0         my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
7339              
7340             # split regexp
7341 0           my @char = $string =~ /\G(
7342             \[\:\^ [a-z]+ \:\] |
7343             \[\: [a-z]+ \:\] |
7344             \[\^ |
7345             \\? (?:$q_char)
7346             )/oxmsg;
7347              
7348             # unescape character
7349 0           for (my $i=0; $i <= $#char; $i++) {
7350 0 0 0       if (0) {
    0 0        
    0 0        
    0 0        
    0          
    0          
7351             }
7352              
7353             # open character class [...]
7354 0           elsif ($char[$i] eq '[') {
7355 0           my $left = $i;
7356 0 0         if ($char[$i+1] eq ']') {
7357 0           $i++;
7358             }
7359 0           while (1) {
7360 0 0         if (++$i > $#char) {
7361 0           die __FILE__, ": Unmatched [] in regexp";
7362             }
7363 0 0         if ($char[$i] eq ']') {
7364 0           my $right = $i;
7365              
7366             # [...]
7367 0           splice @char, $left, $right-$left+1, Char::Ekoi8u::charlist_qr(@char[$left+1..$right-1], $modifier);
7368              
7369 0           $i = $left;
7370 0           last;
7371             }
7372             }
7373             }
7374              
7375             # open character class [^...]
7376             elsif ($char[$i] eq '[^') {
7377 0           my $left = $i;
7378 0 0         if ($char[$i+1] eq ']') {
7379 0           $i++;
7380             }
7381 0           while (1) {
7382 0 0         if (++$i > $#char) {
7383 0           die __FILE__, ": Unmatched [] in regexp";
7384             }
7385 0 0         if ($char[$i] eq ']') {
7386 0           my $right = $i;
7387              
7388             # [^...]
7389 0           splice @char, $left, $right-$left+1, Char::Ekoi8u::charlist_not_qr(@char[$left+1..$right-1], $modifier);
7390              
7391 0           $i = $left;
7392 0           last;
7393             }
7394             }
7395             }
7396              
7397             # rewrite character class or escape character
7398             elsif (my $char = character_class($char[$i],$modifier)) {
7399 0           $char[$i] = $char;
7400             }
7401              
7402             # split(m/^/) --> split(m/^/m)
7403             elsif (($char[$i] eq '^') and ($modifier !~ /m/oxms)) {
7404 0           $modifier .= 'm';
7405             }
7406              
7407             # /i modifier
7408             elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Char::Ekoi8u::uc($char[$i]) ne Char::Ekoi8u::fc($char[$i]))) {
7409 0 0         if (CORE::length(Char::Ekoi8u::fc($char[$i])) == 1) {
7410 0           $char[$i] = '[' . Char::Ekoi8u::uc($char[$i]) . Char::Ekoi8u::fc($char[$i]) . ']';
7411             }
7412             else {
7413 0           $char[$i] = '(?:' . Char::Ekoi8u::uc($char[$i]) . '|' . Char::Ekoi8u::fc($char[$i]) . ')';
7414             }
7415             }
7416              
7417             # quote character before ? + * {
7418             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
7419 0 0         if ($char[$i-1] =~ /\A [\x00-\xFF] \z/oxms) {
7420             }
7421             else {
7422 0           $char[$i-1] = '(?:' . $char[$i-1] . ')';
7423             }
7424             }
7425             }
7426              
7427 0           $modifier =~ tr/i//d;
7428 0           return join '', 'Char::Ekoi8u::split', $ope, $delimiter, @char, $end_delimiter, $modifier;
7429             }
7430              
7431             #
7432             # instead of Carp::carp
7433             #
7434             sub carp {
7435 0     0 0   my($package,$filename,$line) = caller(1);
7436 0           print STDERR "@_ at $filename line $line.\n";
7437             }
7438              
7439             #
7440             # instead of Carp::croak
7441             #
7442             sub croak {
7443 0     0 0   my($package,$filename,$line) = caller(1);
7444 0           print STDERR "@_ at $filename line $line.\n";
7445 0           die "\n";
7446             }
7447              
7448             #
7449             # instead of Carp::cluck
7450             #
7451             sub cluck {
7452 0     0 0   my $i = 0;
7453 0           my @cluck = ();
7454 0           while (my($package,$filename,$line,$subroutine) = caller($i)) {
7455 0           push @cluck, "[$i] $filename($line) $package::$subroutine\n";
7456 0           $i++;
7457             }
7458 0           print STDERR CORE::reverse @cluck;
7459 0           print STDERR "\n";
7460 0           carp @_;
7461             }
7462              
7463             #
7464             # instead of Carp::confess
7465             #
7466             sub confess {
7467 0     0 0   my $i = 0;
7468 0           my @confess = ();
7469 0           while (my($package,$filename,$line,$subroutine) = caller($i)) {
7470 0           push @confess, "[$i] $filename($line) $package::$subroutine\n";
7471 0           $i++;
7472             }
7473 0           print STDERR CORE::reverse @confess;
7474 0           print STDERR "\n";
7475 0           croak @_;
7476             }
7477              
7478             1;
7479              
7480             __END__