File Coverage

blib/lib/Ekoi8r.pm
Criterion Covered Total %
statement 83 3085 2.6
branch 4 2674 0.1
condition 1 373 0.2
subroutine 36 125 28.8
pod 7 74 9.4
total 131 6331 2.0


line stmt bran cond sub pod time code
1             package Ekoi8r;
2             ######################################################################
3             #
4             # Ekoi8r - Run-time routines for KOI8R.pm
5             #
6             # http://search.cpan.org/dist/Char-KOI8R/
7             #
8             # Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015 INABA Hitoshi
9             ######################################################################
10              
11 200     200   5438 use 5.00503; # Galapagos Consensus 1998 for primetools
  200         663  
  200         11911  
12             # use 5.008001; # Lancaster Consensus 2013 for toolchains
13              
14             # 12.3. Delaying use Until Runtime
15             # in Chapter 12. Packages, Libraries, and Modules
16             # of ISBN 0-596-00313-7 Perl Cookbook, 2nd Edition.
17             # (and so on)
18              
19             # Version numbers should be boring
20             # http://www.dagolden.com/index.php/369/version-numbers-should-be-boring/
21             # For the impatient, the disinterested or those who just want to follow
22             # a recipe, my advice for all modules is this:
23             # our $VERSION = "0.001"; # or "0.001_001" for a dev release
24             # $VERSION = eval $VERSION;
25              
26 200     200   17573 BEGIN { CORE::eval q{ use vars qw($VERSION) } }
  200     200   1271  
  200         2913  
  200         36291  
27             $VERSION = '1.05';
28             $VERSION = CORE::eval $VERSION;
29              
30             BEGIN {
31 200 50   200   1560 if ($^X =~ / jperl /oxmsi) {
32 0         0 die __FILE__, ": needs perl(not jperl) 5.00503 or later. (\$^X==$^X)\n";
33             }
34 200         350 if (CORE::ord('A') == 193) {
35             die __FILE__, ": is not US-ASCII script (may be EBCDIC or EBCDIK script).\n";
36             }
37 200         34490 if (CORE::ord('A') != 0x41) {
38             die __FILE__, ": is not US-ASCII script (must be US-ASCII script).\n";
39             }
40             }
41              
42             BEGIN {
43              
44             # instead of utf8.pm
45 200     200   15785 CORE::eval q{
  200     200   1388  
  200     72   769  
  200         34529  
  72         14217  
  59         11397  
  64         12009  
  85         17349  
  67         11270  
  53         10824  
46             no warnings qw(redefine);
47             *utf8::upgrade = sub { CORE::length $_[0] };
48             *utf8::downgrade = sub { 1 };
49             *utf8::encode = sub { };
50             *utf8::decode = sub { 1 };
51             *utf8::is_utf8 = sub { };
52             *utf8::valid = sub { 1 };
53             };
54 200 50       130383 if ($@) {
55 0         0 *utf8::upgrade = sub { CORE::length $_[0] };
  0         0  
56 0         0 *utf8::downgrade = sub { 1 };
  0         0  
57 0         0 *utf8::encode = sub { };
  0         0  
58 0         0 *utf8::decode = sub { 1 };
  0         0  
59 0         0 *utf8::is_utf8 = sub { };
  0         0  
60 0         0 *utf8::valid = sub { 1 };
  0         0  
61             }
62             }
63              
64             # instead of Symbol.pm
65             BEGIN {
66 200     200   548 my $genpkg = "Symbol::";
67 200         10381 my $genseq = 0;
68              
69             sub gensym () {
70 0     0 0 0 my $name = "GEN" . $genseq++;
71              
72             # here, no strict qw(refs); if strict.pm exists
73              
74 0         0 my $ref = \*{$genpkg . $name};
  0         0  
75 0         0 delete $$genpkg{$name};
76 0         0 return $ref;
77             }
78              
79             sub qualify ($;$) {
80 0     0 0 0 my ($name) = @_;
81 0 0 0     0 if (!ref($name) && (Ekoi8r::index($name, '::') == -1) && (Ekoi8r::index($name, "'") == -1)) {
      0        
82 0         0 my $pkg;
83 0         0 my %global = map {$_ => 1} qw(ARGV ARGVOUT ENV INC SIG STDERR STDIN STDOUT DATA);
  0         0  
84              
85             # Global names: special character, "^xyz", or other.
86 0 0 0     0 if ($name =~ /^(([^a-z])|(\^[a-z_]+))\z/i || $global{$name}) {
87             # RGS 2001-11-05 : translate leading ^X to control-char
88 0         0 $name =~ s/^\^([a-z_])/'qq(\c'.$1.')'/eei;
  0         0  
89 0         0 $pkg = "main";
90             }
91             else {
92 0 0       0 $pkg = (@_ > 1) ? $_[1] : caller;
93             }
94 0         0 $name = $pkg . "::" . $name;
95             }
96 0         0 return $name;
97             }
98              
99             sub qualify_to_ref ($;$) {
100              
101             # here, no strict qw(refs); if strict.pm exists
102              
103 0 0   0 0 0 return \*{ qualify $_[0], @_ > 1 ? $_[1] : caller };
  0         0  
104             }
105             }
106              
107             # Column: local $@
108             # in Chapter 9. Osaete okitai Perl no kiso
109             # of ISBN 10: 4798119172 | ISBN 13: 978-4798119175 MODAN Perl NYUMON
110             # (and so on)
111              
112             # use strict; if strict.pm exists
113             BEGIN {
114 200 50   200   436 if (CORE::eval { local $@; CORE::require strict }) {
  200         366  
  200         2235  
115 200         29761 strict::->import;
116             }
117             }
118              
119             # P.714 29.2.39. flock
120             # in Chapter 29: Functions
121             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
122              
123             # P.863 flock
124             # in Chapter 27: Functions
125             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
126              
127             sub LOCK_SH() {1}
128             sub LOCK_EX() {2}
129             sub LOCK_UN() {8}
130             sub LOCK_NB() {4}
131              
132             # instead of Carp.pm
133             sub carp;
134             sub croak;
135             sub cluck;
136             sub confess;
137              
138             # 6.18. Matching Multiple-Byte Characters
139             # in Chapter 6. Pattern Matching
140             # of ISBN 978-1-56592-243-3 Perl Perl Cookbook.
141             # (and so on)
142              
143             # regexp of character
144 200     200   15695 BEGIN { CORE::eval q{ use vars qw($your_char) } } $your_char = q{[\x00-\xFF]};
  200     200   1318  
  200         544  
  200         14786  
145 200     200   15371 BEGIN { CORE::eval q{ use vars qw($qq_char ) } } $qq_char = qr/\\c[\x40-\x5F]|\\?(?:$your_char)/oxms;
  200     200   1153  
  200         373  
  200         15112  
146 200     200   14538 BEGIN { CORE::eval q{ use vars qw($q_char ) } } $q_char = qr/$your_char/oxms;
  200     200   1237  
  200         322  
  200         16817  
147              
148             #
149             # KOI8-R character range per length
150             #
151             my %range_tr = ();
152              
153             #
154             # alias of encoding name
155             #
156 200     200   14259 BEGIN { CORE::eval q{ use vars qw($encoding_alias) } }
  200     200   1255  
  200         361  
  200         459266  
157              
158             #
159             # KOI8-R case conversion
160             #
161             my %lc = ();
162             @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)} =
163             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             my %uc = ();
165             @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)} =
166             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);
167             my %fc = ();
168             @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)} =
169             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);
170              
171             if (0) {
172             }
173              
174             elsif (__PACKAGE__ =~ / \b Ekoi8r \z/oxms) {
175             %range_tr = (
176             1 => [ [0x00..0xFF],
177             ],
178             );
179             $encoding_alias = qr/ \b (?: koi8-?r ) \b /oxmsi;
180              
181             %lc = (%lc,
182             "\xB3" => "\xA3", # CYRILLIC LETTER IO
183             "\xE0" => "\xC0", # CYRILLIC LETTER IU
184             "\xE1" => "\xC1", # CYRILLIC LETTER A
185             "\xE2" => "\xC2", # CYRILLIC LETTER BE
186             "\xE3" => "\xC3", # CYRILLIC LETTER TSE
187             "\xE4" => "\xC4", # CYRILLIC LETTER DE
188             "\xE5" => "\xC5", # CYRILLIC LETTER IE
189             "\xE6" => "\xC6", # CYRILLIC LETTER EF
190             "\xE7" => "\xC7", # CYRILLIC LETTER GE
191             "\xE8" => "\xC8", # CYRILLIC LETTER KHA
192             "\xE9" => "\xC9", # CYRILLIC LETTER II
193             "\xEA" => "\xCA", # CYRILLIC LETTER SHORT II
194             "\xEB" => "\xCB", # CYRILLIC LETTER KA
195             "\xEC" => "\xCC", # CYRILLIC LETTER EL
196             "\xED" => "\xCD", # CYRILLIC LETTER EM
197             "\xEE" => "\xCE", # CYRILLIC LETTER EN
198             "\xEF" => "\xCF", # CYRILLIC LETTER O
199             "\xF0" => "\xD0", # CYRILLIC LETTER PE
200             "\xF1" => "\xD1", # CYRILLIC LETTER IA
201             "\xF2" => "\xD2", # CYRILLIC LETTER ER
202             "\xF3" => "\xD3", # CYRILLIC LETTER ES
203             "\xF4" => "\xD4", # CYRILLIC LETTER TE
204             "\xF5" => "\xD5", # CYRILLIC LETTER U
205             "\xF6" => "\xD6", # CYRILLIC LETTER ZHE
206             "\xF7" => "\xD7", # CYRILLIC LETTER VE
207             "\xF8" => "\xD8", # CYRILLIC LETTER SOFT SIGN
208             "\xF9" => "\xD9", # CYRILLIC LETTER YERI
209             "\xFA" => "\xDA", # CYRILLIC LETTER ZE
210             "\xFB" => "\xDB", # CYRILLIC LETTER SHA
211             "\xFC" => "\xDC", # CYRILLIC LETTER REVERSED E
212             "\xFD" => "\xDD", # CYRILLIC LETTER SHCHA
213             "\xFE" => "\xDE", # CYRILLIC LETTER CHE
214             "\xFF" => "\xDF", # CYRILLIC LETTER HARD SIGN
215             );
216              
217             %uc = (%uc,
218             "\xA3" => "\xB3", # CYRILLIC LETTER IO
219             "\xC0" => "\xE0", # CYRILLIC LETTER IU
220             "\xC1" => "\xE1", # CYRILLIC LETTER A
221             "\xC2" => "\xE2", # CYRILLIC LETTER BE
222             "\xC3" => "\xE3", # CYRILLIC LETTER TSE
223             "\xC4" => "\xE4", # CYRILLIC LETTER DE
224             "\xC5" => "\xE5", # CYRILLIC LETTER IE
225             "\xC6" => "\xE6", # CYRILLIC LETTER EF
226             "\xC7" => "\xE7", # CYRILLIC LETTER GE
227             "\xC8" => "\xE8", # CYRILLIC LETTER KHA
228             "\xC9" => "\xE9", # CYRILLIC LETTER II
229             "\xCA" => "\xEA", # CYRILLIC LETTER SHORT II
230             "\xCB" => "\xEB", # CYRILLIC LETTER KA
231             "\xCC" => "\xEC", # CYRILLIC LETTER EL
232             "\xCD" => "\xED", # CYRILLIC LETTER EM
233             "\xCE" => "\xEE", # CYRILLIC LETTER EN
234             "\xCF" => "\xEF", # CYRILLIC LETTER O
235             "\xD0" => "\xF0", # CYRILLIC LETTER PE
236             "\xD1" => "\xF1", # CYRILLIC LETTER IA
237             "\xD2" => "\xF2", # CYRILLIC LETTER ER
238             "\xD3" => "\xF3", # CYRILLIC LETTER ES
239             "\xD4" => "\xF4", # CYRILLIC LETTER TE
240             "\xD5" => "\xF5", # CYRILLIC LETTER U
241             "\xD6" => "\xF6", # CYRILLIC LETTER ZHE
242             "\xD7" => "\xF7", # CYRILLIC LETTER VE
243             "\xD8" => "\xF8", # CYRILLIC LETTER SOFT SIGN
244             "\xD9" => "\xF9", # CYRILLIC LETTER YERI
245             "\xDA" => "\xFA", # CYRILLIC LETTER ZE
246             "\xDB" => "\xFB", # CYRILLIC LETTER SHA
247             "\xDC" => "\xFC", # CYRILLIC LETTER REVERSED E
248             "\xDD" => "\xFD", # CYRILLIC LETTER SHCHA
249             "\xDE" => "\xFE", # CYRILLIC LETTER CHE
250             "\xDF" => "\xFF", # CYRILLIC LETTER HARD SIGN
251             );
252              
253             %fc = (%fc,
254             "\xB3" => "\xA3", # CYRILLIC CAPITAL LETTER IO --> CYRILLIC SMALL LETTER IO
255             "\xE0" => "\xC0", # CYRILLIC CAPITAL LETTER YU --> CYRILLIC SMALL LETTER YU
256             "\xE1" => "\xC1", # CYRILLIC CAPITAL LETTER A --> CYRILLIC SMALL LETTER A
257             "\xE2" => "\xC2", # CYRILLIC CAPITAL LETTER BE --> CYRILLIC SMALL LETTER BE
258             "\xE3" => "\xC3", # CYRILLIC CAPITAL LETTER TSE --> CYRILLIC SMALL LETTER TSE
259             "\xE4" => "\xC4", # CYRILLIC CAPITAL LETTER DE --> CYRILLIC SMALL LETTER DE
260             "\xE5" => "\xC5", # CYRILLIC CAPITAL LETTER IE --> CYRILLIC SMALL LETTER IE
261             "\xE6" => "\xC6", # CYRILLIC CAPITAL LETTER EF --> CYRILLIC SMALL LETTER EF
262             "\xE7" => "\xC7", # CYRILLIC CAPITAL LETTER GHE --> CYRILLIC SMALL LETTER GHE
263             "\xE8" => "\xC8", # CYRILLIC CAPITAL LETTER HA --> CYRILLIC SMALL LETTER HA
264             "\xE9" => "\xC9", # CYRILLIC CAPITAL LETTER I --> CYRILLIC SMALL LETTER I
265             "\xEA" => "\xCA", # CYRILLIC CAPITAL LETTER SHORT I --> CYRILLIC SMALL LETTER SHORT I
266             "\xEB" => "\xCB", # CYRILLIC CAPITAL LETTER KA --> CYRILLIC SMALL LETTER KA
267             "\xEC" => "\xCC", # CYRILLIC CAPITAL LETTER EL --> CYRILLIC SMALL LETTER EL
268             "\xED" => "\xCD", # CYRILLIC CAPITAL LETTER EM --> CYRILLIC SMALL LETTER EM
269             "\xEE" => "\xCE", # CYRILLIC CAPITAL LETTER EN --> CYRILLIC SMALL LETTER EN
270             "\xEF" => "\xCF", # CYRILLIC CAPITAL LETTER O --> CYRILLIC SMALL LETTER O
271             "\xF0" => "\xD0", # CYRILLIC CAPITAL LETTER PE --> CYRILLIC SMALL LETTER PE
272             "\xF1" => "\xD1", # CYRILLIC CAPITAL LETTER YA --> CYRILLIC SMALL LETTER YA
273             "\xF2" => "\xD2", # CYRILLIC CAPITAL LETTER ER --> CYRILLIC SMALL LETTER ER
274             "\xF3" => "\xD3", # CYRILLIC CAPITAL LETTER ES --> CYRILLIC SMALL LETTER ES
275             "\xF4" => "\xD4", # CYRILLIC CAPITAL LETTER TE --> CYRILLIC SMALL LETTER TE
276             "\xF5" => "\xD5", # CYRILLIC CAPITAL LETTER U --> CYRILLIC SMALL LETTER U
277             "\xF6" => "\xD6", # CYRILLIC CAPITAL LETTER ZHE --> CYRILLIC SMALL LETTER ZHE
278             "\xF7" => "\xD7", # CYRILLIC CAPITAL LETTER VE --> CYRILLIC SMALL LETTER VE
279             "\xF8" => "\xD8", # CYRILLIC CAPITAL LETTER SOFT SIGN --> CYRILLIC SMALL LETTER SOFT SIGN
280             "\xF9" => "\xD9", # CYRILLIC CAPITAL LETTER YERU --> CYRILLIC SMALL LETTER YERU
281             "\xFA" => "\xDA", # CYRILLIC CAPITAL LETTER ZE --> CYRILLIC SMALL LETTER ZE
282             "\xFB" => "\xDB", # CYRILLIC CAPITAL LETTER SHA --> CYRILLIC SMALL LETTER SHA
283             "\xFC" => "\xDC", # CYRILLIC CAPITAL LETTER E --> CYRILLIC SMALL LETTER E
284             "\xFD" => "\xDD", # CYRILLIC CAPITAL LETTER SHCHA --> CYRILLIC SMALL LETTER SHCHA
285             "\xFE" => "\xDE", # CYRILLIC CAPITAL LETTER CHE --> CYRILLIC SMALL LETTER CHE
286             "\xFF" => "\xDF", # CYRILLIC CAPITAL LETTER HARD SIGN --> CYRILLIC SMALL LETTER HARD SIGN
287             );
288             }
289              
290             else {
291             croak "Don't know my package name '@{[__PACKAGE__]}'";
292             }
293              
294             #
295             # @ARGV wildcard globbing
296             #
297             sub import {
298              
299 0 0   0   0 if ($^O =~ /\A (?: MSWin32 | NetWare | symbian | dos ) \z/oxms) {
300 0         0 my @argv = ();
301 0         0 for (@ARGV) {
302              
303             # has space
304 0 0       0 if (/\A (?:$q_char)*? [ ] /oxms) {
    0          
305 0 0       0 if (my @glob = Ekoi8r::glob(qq{"$_"})) {
306 0         0 push @argv, @glob;
307             }
308             else {
309 0         0 push @argv, $_;
310             }
311             }
312              
313             # has wildcard metachar
314             elsif (/\A (?:$q_char)*? [*?] /oxms) {
315 0 0       0 if (my @glob = Ekoi8r::glob($_)) {
316 0         0 push @argv, @glob;
317             }
318             else {
319 0         0 push @argv, $_;
320             }
321             }
322              
323             # no wildcard globbing
324             else {
325 0         0 push @argv, $_;
326             }
327             }
328 0         0 @ARGV = @argv;
329             }
330              
331 0         0 *Char::ord = \&KOI8R::ord;
332 0         0 *Char::ord_ = \&KOI8R::ord_;
333 0         0 *Char::reverse = \&KOI8R::reverse;
334 0         0 *Char::getc = \&KOI8R::getc;
335 0         0 *Char::length = \&KOI8R::length;
336 0         0 *Char::substr = \&KOI8R::substr;
337 0         0 *Char::index = \&KOI8R::index;
338 0         0 *Char::rindex = \&KOI8R::rindex;
339 0         0 *Char::eval = \&KOI8R::eval;
340 0         0 *Char::escape = \&KOI8R::escape;
341 0         0 *Char::escape_token = \&KOI8R::escape_token;
342 0         0 *Char::escape_script = \&KOI8R::escape_script;
343             }
344              
345             # P.230 Care with Prototypes
346             # in Chapter 6: Subroutines
347             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
348             #
349             # If you aren't careful, you can get yourself into trouble with prototypes.
350             # But if you are careful, you can do a lot of neat things with them. This is
351             # all very powerful, of course, and should only be used in moderation to make
352             # the world a better place.
353              
354             # P.332 Care with Prototypes
355             # in Chapter 7: Subroutines
356             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
357             #
358             # If you aren't careful, you can get yourself into trouble with prototypes.
359             # But if you are careful, you can do a lot of neat things with them. This is
360             # all very powerful, of course, and should only be used in moderation to make
361             # the world a better place.
362              
363             #
364             # Prototypes of subroutines
365             #
366 0     0   0 sub unimport {}
367             sub Ekoi8r::split(;$$$);
368             sub Ekoi8r::tr($$$$;$);
369             sub Ekoi8r::chop(@);
370             sub Ekoi8r::index($$;$);
371             sub Ekoi8r::rindex($$;$);
372             sub Ekoi8r::lcfirst(@);
373             sub Ekoi8r::lcfirst_();
374             sub Ekoi8r::lc(@);
375             sub Ekoi8r::lc_();
376             sub Ekoi8r::ucfirst(@);
377             sub Ekoi8r::ucfirst_();
378             sub Ekoi8r::uc(@);
379             sub Ekoi8r::uc_();
380             sub Ekoi8r::fc(@);
381             sub Ekoi8r::fc_();
382             sub Ekoi8r::ignorecase;
383             sub Ekoi8r::classic_character_class;
384             sub Ekoi8r::capture;
385             sub Ekoi8r::chr(;$);
386             sub Ekoi8r::chr_();
387             sub Ekoi8r::glob($);
388             sub Ekoi8r::glob_();
389              
390             sub KOI8R::ord(;$);
391             sub KOI8R::ord_();
392             sub KOI8R::reverse(@);
393             sub KOI8R::getc(;*@);
394             sub KOI8R::length(;$);
395             sub KOI8R::substr($$;$$);
396             sub KOI8R::index($$;$);
397             sub KOI8R::rindex($$;$);
398             sub KOI8R::escape(;$);
399              
400             #
401             # Regexp work
402             #
403 200     200   18998 BEGIN { CORE::eval q{ use vars qw(
  200     200   1689  
  200         550  
  200         98543  
404             $KOI8R::re_a
405             $KOI8R::re_t
406             $KOI8R::re_n
407             $KOI8R::re_r
408             ) } }
409              
410             #
411             # Character class
412             #
413 200     200   18360 BEGIN { CORE::eval q{ use vars qw(
  200     200   1259  
  200         436  
  200         3553949  
414             $dot
415             $dot_s
416             $eD
417             $eS
418             $eW
419             $eH
420             $eV
421             $eR
422             $eN
423             $not_alnum
424             $not_alpha
425             $not_ascii
426             $not_blank
427             $not_cntrl
428             $not_digit
429             $not_graph
430             $not_lower
431             $not_lower_i
432             $not_print
433             $not_punct
434             $not_space
435             $not_upper
436             $not_upper_i
437             $not_word
438             $not_xdigit
439             $eb
440             $eB
441             ) } }
442              
443             ${Ekoi8r::dot} = qr{(?>[^\x0A])};
444             ${Ekoi8r::dot_s} = qr{(?>[\x00-\xFF])};
445             ${Ekoi8r::eD} = qr{(?>[^0-9])};
446              
447             # Vertical tabs are now whitespace
448             # \s in a regex now matches a vertical tab in all circumstances.
449             # http://search.cpan.org/dist/perl-5.18.0/pod/perldelta.pod#Vertical_tabs_are_now_whitespace
450             # ${Ekoi8r::eS} = qr{(?>[^\x09\x0A \x0C\x0D\x20])};
451             # ${Ekoi8r::eS} = qr{(?>[^\x09\x0A\x0B\x0C\x0D\x20])};
452             ${Ekoi8r::eS} = qr{(?>[^\s])};
453              
454             ${Ekoi8r::eW} = qr{(?>[^0-9A-Z_a-z])};
455             ${Ekoi8r::eH} = qr{(?>[^\x09\x20])};
456             ${Ekoi8r::eV} = qr{(?>[^\x0A\x0B\x0C\x0D])};
457             ${Ekoi8r::eR} = qr{(?>\x0D\x0A|[\x0A\x0D])};
458             ${Ekoi8r::eN} = qr{(?>[^\x0A])};
459             ${Ekoi8r::not_alnum} = qr{(?>[^\x30-\x39\x41-\x5A\x61-\x7A])};
460             ${Ekoi8r::not_alpha} = qr{(?>[^\x41-\x5A\x61-\x7A])};
461             ${Ekoi8r::not_ascii} = qr{(?>[^\x00-\x7F])};
462             ${Ekoi8r::not_blank} = qr{(?>[^\x09\x20])};
463             ${Ekoi8r::not_cntrl} = qr{(?>[^\x00-\x1F\x7F])};
464             ${Ekoi8r::not_digit} = qr{(?>[^\x30-\x39])};
465             ${Ekoi8r::not_graph} = qr{(?>[^\x21-\x7F])};
466             ${Ekoi8r::not_lower} = qr{(?>[^\x61-\x7A])};
467             ${Ekoi8r::not_lower_i} = qr{(?>[^\x41-\x5A\x61-\x7A])}; # Perl 5.16 compatible
468             # ${Ekoi8r::not_lower_i} = qr{(?>[\x00-\xFF])}; # older Perl compatible
469             ${Ekoi8r::not_print} = qr{(?>[^\x20-\x7F])};
470             ${Ekoi8r::not_punct} = qr{(?>[^\x21-\x2F\x3A-\x3F\x40\x5B-\x5F\x60\x7B-\x7E])};
471             ${Ekoi8r::not_space} = qr{(?>[^\s\x0B])};
472             ${Ekoi8r::not_upper} = qr{(?>[^\x41-\x5A])};
473             ${Ekoi8r::not_upper_i} = qr{(?>[^\x41-\x5A\x61-\x7A])}; # Perl 5.16 compatible
474             # ${Ekoi8r::not_upper_i} = qr{(?>[\x00-\xFF])}; # older Perl compatible
475             ${Ekoi8r::not_word} = qr{(?>[^\x30-\x39\x41-\x5A\x5F\x61-\x7A])};
476             ${Ekoi8r::not_xdigit} = qr{(?>[^\x30-\x39\x41-\x46\x61-\x66])};
477             ${Ekoi8r::eb} = qr{(?:\A(?=[0-9A-Z_a-z])|(?<=[\x00-\x2F\x40\x5B-\x5E\x60\x7B-\xFF])(?=[0-9A-Z_a-z])|(?<=[0-9A-Z_a-z])(?=[\x00-\x2F\x40\x5B-\x5E\x60\x7B-\xFF]|\z))};
478             ${Ekoi8r::eB} = qr{(?:(?<=[0-9A-Z_a-z])(?=[0-9A-Z_a-z])|(?<=[\x00-\x2F\x40\x5B-\x5E\x60\x7B-\xFF])(?=[\x00-\x2F\x40\x5B-\x5E\x60\x7B-\xFF]))};
479              
480             # avoid: Name "Ekoi8r::foo" used only once: possible typo at here.
481             ${Ekoi8r::dot} = ${Ekoi8r::dot};
482             ${Ekoi8r::dot_s} = ${Ekoi8r::dot_s};
483             ${Ekoi8r::eD} = ${Ekoi8r::eD};
484             ${Ekoi8r::eS} = ${Ekoi8r::eS};
485             ${Ekoi8r::eW} = ${Ekoi8r::eW};
486             ${Ekoi8r::eH} = ${Ekoi8r::eH};
487             ${Ekoi8r::eV} = ${Ekoi8r::eV};
488             ${Ekoi8r::eR} = ${Ekoi8r::eR};
489             ${Ekoi8r::eN} = ${Ekoi8r::eN};
490             ${Ekoi8r::not_alnum} = ${Ekoi8r::not_alnum};
491             ${Ekoi8r::not_alpha} = ${Ekoi8r::not_alpha};
492             ${Ekoi8r::not_ascii} = ${Ekoi8r::not_ascii};
493             ${Ekoi8r::not_blank} = ${Ekoi8r::not_blank};
494             ${Ekoi8r::not_cntrl} = ${Ekoi8r::not_cntrl};
495             ${Ekoi8r::not_digit} = ${Ekoi8r::not_digit};
496             ${Ekoi8r::not_graph} = ${Ekoi8r::not_graph};
497             ${Ekoi8r::not_lower} = ${Ekoi8r::not_lower};
498             ${Ekoi8r::not_lower_i} = ${Ekoi8r::not_lower_i};
499             ${Ekoi8r::not_print} = ${Ekoi8r::not_print};
500             ${Ekoi8r::not_punct} = ${Ekoi8r::not_punct};
501             ${Ekoi8r::not_space} = ${Ekoi8r::not_space};
502             ${Ekoi8r::not_upper} = ${Ekoi8r::not_upper};
503             ${Ekoi8r::not_upper_i} = ${Ekoi8r::not_upper_i};
504             ${Ekoi8r::not_word} = ${Ekoi8r::not_word};
505             ${Ekoi8r::not_xdigit} = ${Ekoi8r::not_xdigit};
506             ${Ekoi8r::eb} = ${Ekoi8r::eb};
507             ${Ekoi8r::eB} = ${Ekoi8r::eB};
508              
509             #
510             # KOI8-R split
511             #
512             sub Ekoi8r::split(;$$$) {
513              
514             # P.794 29.2.161. split
515             # in Chapter 29: Functions
516             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
517              
518             # P.951 split
519             # in Chapter 27: Functions
520             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
521              
522 0     0 0 0 my $pattern = $_[0];
523 0         0 my $string = $_[1];
524 0         0 my $limit = $_[2];
525              
526             # if $pattern is also omitted or is the literal space, " "
527 0 0       0 if (not defined $pattern) {
528 0         0 $pattern = ' ';
529             }
530              
531             # if $string is omitted, the function splits the $_ string
532 0 0       0 if (not defined $string) {
533 0 0       0 if (defined $_) {
534 0         0 $string = $_;
535             }
536             else {
537 0         0 $string = '';
538             }
539             }
540              
541 0         0 my @split = ();
542              
543             # when string is empty
544 0 0       0 if ($string eq '') {
    0          
545              
546             # resulting list value in list context
547 0 0       0 if (wantarray) {
548 0         0 return @split;
549             }
550              
551             # count of substrings in scalar context
552             else {
553 0 0       0 carp "Use of implicit split to \@_ is deprecated" if $^W;
554 0         0 @_ = @split;
555 0         0 return scalar @_;
556             }
557             }
558              
559             # split's first argument is more consistently interpreted
560             #
561             # After some changes earlier in v5.17, split's behavior has been simplified:
562             # if the PATTERN argument evaluates to a string containing one space, it is
563             # treated the way that a literal string containing one space once was.
564             # http://search.cpan.org/dist/perl-5.18.0/pod/perldelta.pod#split's_first_argument_is_more_consistently_interpreted
565              
566             # if $pattern is also omitted or is the literal space, " ", the function splits
567             # on whitespace, /\s+/, after skipping any leading whitespace
568             # (and so on)
569              
570             elsif ($pattern eq ' ') {
571 0 0       0 if (not defined $limit) {
572 0         0 return CORE::split(' ', $string);
573             }
574             else {
575 0         0 return CORE::split(' ', $string, $limit);
576             }
577             }
578              
579             # if $limit is negative, it is treated as if an arbitrarily large $limit has been specified
580 0 0 0     0 if ((not defined $limit) or ($limit <= 0)) {
    0          
581              
582             # a pattern capable of matching either the null string or something longer than the
583             # null string will split the value of $string into separate characters wherever it
584             # matches the null string between characters
585             # (and so on)
586              
587 0 0       0 if ('' =~ / \A $pattern \z /xms) {
588 0         0 my $last_subexpression_offsets = _last_subexpression_offsets($pattern);
589 0         0 my $limit = scalar(() = $string =~ /($pattern)/oxmsg);
590              
591             # P.1024 Appendix W.10 Multibyte Processing
592             # of ISBN 1-56592-224-7 CJKV Information Processing
593             # (and so on)
594              
595             # the //m modifier is assumed when you split on the pattern /^/
596             # (and so on)
597              
598             # V
599 0   0     0 while ((--$limit > 0) and ($string =~ s/\A((?:$q_char)+?)$pattern//m)) {
600              
601             # if the $pattern contains parentheses, then the substring matched by each pair of parentheses
602             # is included in the resulting list, interspersed with the fields that are ordinarily returned
603             # (and so on)
604              
605 0         0 local $@;
606 0         0 for (my $digit=1; $digit <= ($last_subexpression_offsets + 1); $digit++) {
607 0         0 push @split, CORE::eval('$' . $digit);
608             }
609             }
610             }
611              
612             else {
613 0         0 my $last_subexpression_offsets = _last_subexpression_offsets($pattern);
614              
615             # V
616 0         0 while ($string =~ s/\A((?:$q_char)*?)$pattern//m) {
617 0         0 local $@;
618 0         0 for (my $digit=1; $digit <= ($last_subexpression_offsets + 1); $digit++) {
619 0         0 push @split, CORE::eval('$' . $digit);
620             }
621             }
622             }
623             }
624              
625             elsif ($limit > 0) {
626 0 0       0 if ('' =~ / \A $pattern \z /xms) {
627 0         0 my $last_subexpression_offsets = _last_subexpression_offsets($pattern);
628 0   0     0 while ((--$limit > 0) and (CORE::length($string) > 0)) {
629              
630             # V
631 0 0       0 if ($string =~ s/\A((?:$q_char)+?)$pattern//m) {
632 0         0 local $@;
633 0         0 for (my $digit=1; $digit <= ($last_subexpression_offsets + 1); $digit++) {
634 0         0 push @split, CORE::eval('$' . $digit);
635             }
636             }
637             }
638             }
639             else {
640 0         0 my $last_subexpression_offsets = _last_subexpression_offsets($pattern);
641 0   0     0 while ((--$limit > 0) and (CORE::length($string) > 0)) {
642              
643             # V
644 0 0       0 if ($string =~ s/\A((?:$q_char)*?)$pattern//m) {
645 0         0 local $@;
646 0         0 for (my $digit=1; $digit <= ($last_subexpression_offsets + 1); $digit++) {
647 0         0 push @split, CORE::eval('$' . $digit);
648             }
649             }
650             }
651             }
652             }
653              
654 0 0       0 if (CORE::length($string) > 0) {
655 0         0 push @split, $string;
656             }
657              
658             # if $_[2] (NOT "$limit") is omitted or zero, trailing null fields are stripped from the result
659 0 0 0     0 if ((not defined $_[2]) or ($_[2] == 0)) {
660 0   0     0 while ((scalar(@split) >= 1) and ($split[-1] eq '')) {
661 0         0 pop @split;
662             }
663             }
664              
665             # resulting list value in list context
666 0 0       0 if (wantarray) {
667 0         0 return @split;
668             }
669              
670             # count of substrings in scalar context
671             else {
672 0 0       0 carp "Use of implicit split to \@_ is deprecated" if $^W;
673 0         0 @_ = @split;
674 0         0 return scalar @_;
675             }
676             }
677              
678             #
679             # get last subexpression offsets
680             #
681             sub _last_subexpression_offsets {
682 0     0   0 my $pattern = $_[0];
683              
684             # remove comment
685 0         0 $pattern =~ s/\(\?\# .*? \)//oxmsg;
686              
687 0         0 my $modifier = '';
688 0 0       0 if ($pattern =~ /\(\?\^? ([\-A-Za-z]+) :/oxms) {
689 0         0 $modifier = $1;
690 0         0 $modifier =~ s/-[A-Za-z]*//;
691             }
692              
693             # with /x modifier
694 0         0 my @char = ();
695 0 0       0 if ($modifier =~ /x/oxms) {
696 0         0 @char = $pattern =~ /\G((?>
697             [^\\\#\[\(] |
698             \\ $q_char |
699             \# (?>[^\n]*) $ |
700             \[ (?>(?:[^\\\]]|\\\\|\\\]|$q_char)+) \] |
701             \(\? |
702             $q_char
703             ))/oxmsg;
704             }
705              
706             # without /x modifier
707             else {
708 0         0 @char = $pattern =~ /\G((?>
709             [^\\\[\(] |
710             \\ $q_char |
711             \[ (?>(?:[^\\\]]|\\\\|\\\]|$q_char)+) \] |
712             \(\? |
713             $q_char
714             ))/oxmsg;
715             }
716              
717 0         0 return scalar grep { $_ eq '(' } @char;
  0         0  
718             }
719              
720             #
721             # KOI8-R transliteration (tr///)
722             #
723             sub Ekoi8r::tr($$$$;$) {
724              
725 0     0 0 0 my $bind_operator = $_[1];
726 0         0 my $searchlist = $_[2];
727 0         0 my $replacementlist = $_[3];
728 0   0     0 my $modifier = $_[4] || '';
729              
730 0 0       0 if ($modifier =~ /r/oxms) {
731 0 0       0 if ($bind_operator =~ / !~ /oxms) {
732 0         0 croak "Using !~ with tr///r doesn't make sense";
733             }
734             }
735              
736 0         0 my @char = $_[0] =~ /\G (?>$q_char) /oxmsg;
737 0         0 my @searchlist = _charlist_tr($searchlist);
738 0         0 my @replacementlist = _charlist_tr($replacementlist);
739              
740 0         0 my %tr = ();
741 0         0 for (my $i=0; $i <= $#searchlist; $i++) {
742 0 0       0 if (not exists $tr{$searchlist[$i]}) {
743 0 0 0     0 if (defined $replacementlist[$i] and ($replacementlist[$i] ne '')) {
    0 0        
    0          
744 0         0 $tr{$searchlist[$i]} = $replacementlist[$i];
745             }
746             elsif ($modifier =~ /d/oxms) {
747 0         0 $tr{$searchlist[$i]} = '';
748             }
749             elsif (defined $replacementlist[-1] and ($replacementlist[-1] ne '')) {
750 0         0 $tr{$searchlist[$i]} = $replacementlist[-1];
751             }
752             else {
753 0         0 $tr{$searchlist[$i]} = $searchlist[$i];
754             }
755             }
756             }
757              
758 0         0 my $tr = 0;
759 0         0 my $replaced = '';
760 0 0       0 if ($modifier =~ /c/oxms) {
761 0         0 while (defined(my $char = shift @char)) {
762 0 0       0 if (not exists $tr{$char}) {
763 0 0       0 if (defined $replacementlist[0]) {
764 0         0 $replaced .= $replacementlist[0];
765             }
766 0         0 $tr++;
767 0 0       0 if ($modifier =~ /s/oxms) {
768 0   0     0 while (@char and (not exists $tr{$char[0]})) {
769 0         0 shift @char;
770 0         0 $tr++;
771             }
772             }
773             }
774             else {
775 0         0 $replaced .= $char;
776             }
777             }
778             }
779             else {
780 0         0 while (defined(my $char = shift @char)) {
781 0 0       0 if (exists $tr{$char}) {
782 0         0 $replaced .= $tr{$char};
783 0         0 $tr++;
784 0 0       0 if ($modifier =~ /s/oxms) {
785 0   0     0 while (@char and (exists $tr{$char[0]}) and ($tr{$char[0]} eq $tr{$char})) {
      0        
786 0         0 shift @char;
787 0         0 $tr++;
788             }
789             }
790             }
791             else {
792 0         0 $replaced .= $char;
793             }
794             }
795             }
796              
797 0 0       0 if ($modifier =~ /r/oxms) {
798 0         0 return $replaced;
799             }
800             else {
801 0         0 $_[0] = $replaced;
802 0 0       0 if ($bind_operator =~ / !~ /oxms) {
803 0         0 return not $tr;
804             }
805             else {
806 0         0 return $tr;
807             }
808             }
809             }
810              
811             #
812             # KOI8-R chop
813             #
814             sub Ekoi8r::chop(@) {
815              
816 0     0 0 0 my $chop;
817 0 0       0 if (@_ == 0) {
818 0         0 my @char = /\G (?>$q_char) /oxmsg;
819 0         0 $chop = pop @char;
820 0         0 $_ = join '', @char;
821             }
822             else {
823 0         0 for (@_) {
824 0         0 my @char = /\G (?>$q_char) /oxmsg;
825 0         0 $chop = pop @char;
826 0         0 $_ = join '', @char;
827             }
828             }
829 0         0 return $chop;
830             }
831              
832             #
833             # KOI8-R index by octet
834             #
835             sub Ekoi8r::index($$;$) {
836              
837 0     0 1 0 my($str,$substr,$position) = @_;
838 0   0     0 $position ||= 0;
839 0         0 my $pos = 0;
840              
841 0         0 while ($pos < CORE::length($str)) {
842 0 0       0 if (CORE::substr($str,$pos,CORE::length($substr)) eq $substr) {
843 0 0       0 if ($pos >= $position) {
844 0         0 return $pos;
845             }
846             }
847 0 0       0 if (CORE::substr($str,$pos) =~ /\A ($q_char) /oxms) {
848 0         0 $pos += CORE::length($1);
849             }
850             else {
851 0         0 $pos += 1;
852             }
853             }
854 0         0 return -1;
855             }
856              
857             #
858             # KOI8-R reverse index
859             #
860             sub Ekoi8r::rindex($$;$) {
861              
862 0     0 0 0 my($str,$substr,$position) = @_;
863 0   0     0 $position ||= CORE::length($str) - 1;
864 0         0 my $pos = 0;
865 0         0 my $rindex = -1;
866              
867 0   0     0 while (($pos < CORE::length($str)) and ($pos <= $position)) {
868 0 0       0 if (CORE::substr($str,$pos,CORE::length($substr)) eq $substr) {
869 0         0 $rindex = $pos;
870             }
871 0 0       0 if (CORE::substr($str,$pos) =~ /\A ($q_char) /oxms) {
872 0         0 $pos += CORE::length($1);
873             }
874             else {
875 0         0 $pos += 1;
876             }
877             }
878 0         0 return $rindex;
879             }
880              
881             #
882             # KOI8-R lower case first with parameter
883             #
884             sub Ekoi8r::lcfirst(@) {
885 0 0   0 0 0 if (@_) {
886 0         0 my $s = shift @_;
887 0 0 0     0 if (@_ and wantarray) {
888 0         0 return Ekoi8r::lc(CORE::substr($s,0,1)) . CORE::substr($s,1), @_;
889             }
890             else {
891 0         0 return Ekoi8r::lc(CORE::substr($s,0,1)) . CORE::substr($s,1);
892             }
893             }
894             else {
895 0         0 return Ekoi8r::lc(CORE::substr($_,0,1)) . CORE::substr($_,1);
896             }
897             }
898              
899             #
900             # KOI8-R lower case first without parameter
901             #
902             sub Ekoi8r::lcfirst_() {
903 0     0 0 0 return Ekoi8r::lc(CORE::substr($_,0,1)) . CORE::substr($_,1);
904             }
905              
906             #
907             # KOI8-R lower case with parameter
908             #
909             sub Ekoi8r::lc(@) {
910 0 0   0 0 0 if (@_) {
911 0         0 my $s = shift @_;
912 0 0 0     0 if (@_ and wantarray) {
913 0 0       0 return join('', map {defined($lc{$_}) ? $lc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg)), @_;
  0         0  
914             }
915             else {
916 0 0       0 return join('', map {defined($lc{$_}) ? $lc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg));
  0         0  
917             }
918             }
919             else {
920 0         0 return Ekoi8r::lc_();
921             }
922             }
923              
924             #
925             # KOI8-R lower case without parameter
926             #
927             sub Ekoi8r::lc_() {
928 0     0 0 0 my $s = $_;
929 0 0       0 return join '', map {defined($lc{$_}) ? $lc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg);
  0         0  
930             }
931              
932             #
933             # KOI8-R upper case first with parameter
934             #
935             sub Ekoi8r::ucfirst(@) {
936 0 0   0 0 0 if (@_) {
937 0         0 my $s = shift @_;
938 0 0 0     0 if (@_ and wantarray) {
939 0         0 return Ekoi8r::uc(CORE::substr($s,0,1)) . CORE::substr($s,1), @_;
940             }
941             else {
942 0         0 return Ekoi8r::uc(CORE::substr($s,0,1)) . CORE::substr($s,1);
943             }
944             }
945             else {
946 0         0 return Ekoi8r::uc(CORE::substr($_,0,1)) . CORE::substr($_,1);
947             }
948             }
949              
950             #
951             # KOI8-R upper case first without parameter
952             #
953             sub Ekoi8r::ucfirst_() {
954 0     0 0 0 return Ekoi8r::uc(CORE::substr($_,0,1)) . CORE::substr($_,1);
955             }
956              
957             #
958             # KOI8-R upper case with parameter
959             #
960             sub Ekoi8r::uc(@) {
961 0 0   0 0 0 if (@_) {
962 0         0 my $s = shift @_;
963 0 0 0     0 if (@_ and wantarray) {
964 0 0       0 return join('', map {defined($uc{$_}) ? $uc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg)), @_;
  0         0  
965             }
966             else {
967 0 0       0 return join('', map {defined($uc{$_}) ? $uc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg));
  0         0  
968             }
969             }
970             else {
971 0         0 return Ekoi8r::uc_();
972             }
973             }
974              
975             #
976             # KOI8-R upper case without parameter
977             #
978             sub Ekoi8r::uc_() {
979 0     0 0 0 my $s = $_;
980 0 0       0 return join '', map {defined($uc{$_}) ? $uc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg);
  0         0  
981             }
982              
983             #
984             # KOI8-R fold case with parameter
985             #
986             sub Ekoi8r::fc(@) {
987 0 0   0 0 0 if (@_) {
988 0         0 my $s = shift @_;
989 0 0 0     0 if (@_ and wantarray) {
990 0 0       0 return join('', map {defined($fc{$_}) ? $fc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg)), @_;
  0         0  
991             }
992             else {
993 0 0       0 return join('', map {defined($fc{$_}) ? $fc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg));
  0         0  
994             }
995             }
996             else {
997 0         0 return Ekoi8r::fc_();
998             }
999             }
1000              
1001             #
1002             # KOI8-R fold case without parameter
1003             #
1004             sub Ekoi8r::fc_() {
1005 0     0 0 0 my $s = $_;
1006 0 0       0 return join '', map {defined($fc{$_}) ? $fc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg);
  0         0  
1007             }
1008              
1009             #
1010             # KOI8-R regexp capture
1011             #
1012             {
1013             sub Ekoi8r::capture {
1014 0     0 1 0 return $_[0];
1015             }
1016             }
1017              
1018             #
1019             # KOI8-R regexp ignore case modifier
1020             #
1021             sub Ekoi8r::ignorecase {
1022              
1023 0     0 0 0 my @string = @_;
1024 0         0 my $metachar = qr/[\@\\|[\]{]/oxms;
1025              
1026             # ignore case of $scalar or @array
1027 0         0 for my $string (@string) {
1028              
1029             # split regexp
1030 0         0 my @char = $string =~ /\G (?>\[\^|\\$q_char|$q_char) /oxmsg;
1031              
1032             # unescape character
1033 0         0 for (my $i=0; $i <= $#char; $i++) {
1034 0 0       0 next if not defined $char[$i];
1035              
1036             # open character class [...]
1037 0 0       0 if ($char[$i] eq '[') {
    0          
    0          
    0          
1038 0         0 my $left = $i;
1039              
1040             # [] make die "unmatched [] in regexp ...\n"
1041              
1042 0 0       0 if ($char[$i+1] eq ']') {
1043 0         0 $i++;
1044             }
1045              
1046 0         0 while (1) {
1047 0 0       0 if (++$i > $#char) {
1048 0         0 croak "Unmatched [] in regexp";
1049             }
1050 0 0       0 if ($char[$i] eq ']') {
1051 0         0 my $right = $i;
1052 0         0 my @charlist = charlist_qr(@char[$left+1..$right-1], 'i');
1053              
1054             # escape character
1055 0         0 for my $char (@charlist) {
1056 0 0       0 if (0) {
1057             }
1058              
1059 0         0 elsif ($char =~ /\A [.|)] \z/oxms) {
1060 0         0 $char = '\\' . $char;
1061             }
1062             }
1063              
1064             # [...]
1065 0         0 splice @char, $left, $right-$left+1, '(?:' . join('|', @charlist) . ')';
1066              
1067 0         0 $i = $left;
1068 0         0 last;
1069             }
1070             }
1071             }
1072              
1073             # open character class [^...]
1074             elsif ($char[$i] eq '[^') {
1075 0         0 my $left = $i;
1076              
1077             # [^] make die "unmatched [] in regexp ...\n"
1078              
1079 0 0       0 if ($char[$i+1] eq ']') {
1080 0         0 $i++;
1081             }
1082              
1083 0         0 while (1) {
1084 0 0       0 if (++$i > $#char) {
1085 0         0 croak "Unmatched [] in regexp";
1086             }
1087 0 0       0 if ($char[$i] eq ']') {
1088 0         0 my $right = $i;
1089 0         0 my @charlist = charlist_not_qr(@char[$left+1..$right-1], 'i');
1090              
1091             # escape character
1092 0         0 for my $char (@charlist) {
1093 0 0       0 if (0) {
1094             }
1095              
1096 0         0 elsif ($char =~ /\A [.|)] \z/oxms) {
1097 0         0 $char = '\\' . $char;
1098             }
1099             }
1100              
1101             # [^...]
1102 0         0 splice @char, $left, $right-$left+1, '(?!' . join('|', @charlist) . ")(?:$your_char)";
1103              
1104 0         0 $i = $left;
1105 0         0 last;
1106             }
1107             }
1108             }
1109              
1110             # rewrite classic character class or escape character
1111             elsif (my $char = classic_character_class($char[$i])) {
1112 0         0 $char[$i] = $char;
1113             }
1114              
1115             # with /i modifier
1116             elsif ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) {
1117 0         0 my $uc = Ekoi8r::uc($char[$i]);
1118 0         0 my $fc = Ekoi8r::fc($char[$i]);
1119 0 0       0 if ($uc ne $fc) {
1120 0 0       0 if (CORE::length($fc) == 1) {
1121 0         0 $char[$i] = '[' . $uc . $fc . ']';
1122             }
1123             else {
1124 0         0 $char[$i] = '(?:' . $uc . '|' . $fc . ')';
1125             }
1126             }
1127             }
1128             }
1129              
1130             # characterize
1131 0         0 for (my $i=0; $i <= $#char; $i++) {
1132 0 0       0 next if not defined $char[$i];
1133              
1134 0 0       0 if (0) {
1135             }
1136              
1137             # quote character before ? + * {
1138 0 0       0 elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
1139 0 0       0 if ($char[$i-1] !~ /\A [\x00-\xFF] \z/oxms) {
1140 0         0 $char[$i-1] = '(?:' . $char[$i-1] . ')';
1141             }
1142             }
1143             }
1144              
1145 0         0 $string = join '', @char;
1146             }
1147              
1148             # make regexp string
1149 0         0 return @string;
1150             }
1151              
1152             #
1153             # classic character class ( \D \S \W \d \s \w \C \X \H \V \h \v \R \N \b \B )
1154             #
1155             sub Ekoi8r::classic_character_class {
1156 0     0 0 0 my($char) = @_;
1157              
1158             return {
1159 0   0     0 '\D' => '${Ekoi8r::eD}',
1160             '\S' => '${Ekoi8r::eS}',
1161             '\W' => '${Ekoi8r::eW}',
1162             '\d' => '[0-9]',
1163              
1164             # Before Perl 5.6, \s only matched the five whitespace characters
1165             # tab, newline, form-feed, carriage return, and the space character
1166             # itself, which, taken together, is the character class [\t\n\f\r ].
1167              
1168             # Vertical tabs are now whitespace
1169             # \s in a regex now matches a vertical tab in all circumstances.
1170             # http://search.cpan.org/dist/perl-5.18.0/pod/perldelta.pod#Vertical_tabs_are_now_whitespace
1171             # \t \n \v \f \r space
1172             # '\s' => '[\x09\x0A \x0C\x0D\x20]',
1173             # '\s' => '[\x09\x0A\x0B\x0C\x0D\x20]',
1174             '\s' => '\s',
1175              
1176             '\w' => '[0-9A-Z_a-z]',
1177             '\C' => '[\x00-\xFF]',
1178             '\X' => 'X',
1179              
1180             # \h \v \H \V
1181              
1182             # P.114 Character Class Shortcuts
1183             # in Chapter 7: In the World of Regular Expressions
1184             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
1185              
1186             # P.357 13.2.3 Whitespace
1187             # in Chapter 13: perlrecharclass: Perl Regular Expression Character Classes
1188             # of ISBN-13: 978-1-906966-02-7 The Perl Language Reference Manual (for Perl version 5.12.1)
1189             #
1190             # 0x00009 CHARACTER TABULATION h s
1191             # 0x0000a LINE FEED (LF) vs
1192             # 0x0000b LINE TABULATION v
1193             # 0x0000c FORM FEED (FF) vs
1194             # 0x0000d CARRIAGE RETURN (CR) vs
1195             # 0x00020 SPACE h s
1196              
1197             # P.196 Table 5-9. Alphanumeric regex metasymbols
1198             # in Chapter 5. Pattern Matching
1199             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
1200              
1201             # (and so on)
1202              
1203             '\H' => '${Ekoi8r::eH}',
1204             '\V' => '${Ekoi8r::eV}',
1205             '\h' => '[\x09\x20]',
1206             '\v' => '[\x0A\x0B\x0C\x0D]',
1207             '\R' => '${Ekoi8r::eR}',
1208              
1209             # \N
1210             #
1211             # http://perldoc.perl.org/perlre.html
1212             # Character Classes and other Special Escapes
1213             # Any character but \n (experimental). Not affected by /s modifier
1214              
1215             '\N' => '${Ekoi8r::eN}',
1216              
1217             # \b \B
1218              
1219             # P.180 Boundaries: The \b and \B Assertions
1220             # in Chapter 5: Pattern Matching
1221             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
1222              
1223             # P.219 Boundaries: The \b and \B Assertions
1224             # in Chapter 5: Pattern Matching
1225             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
1226              
1227             # \b really means (?:(?<=\w)(?!\w)|(?
1228             # or (?:(?<=\A|\W)(?=\w)|(?<=\w)(?=\W|\z))
1229             '\b' => '${Ekoi8r::eb}',
1230              
1231             # \B really means (?:(?<=\w)(?=\w)|(?
1232             # or (?:(?<=\w)(?=\w)|(?<=\W)(?=\W))
1233             '\B' => '${Ekoi8r::eB}',
1234              
1235             }->{$char} || '';
1236             }
1237              
1238             #
1239             # prepare KOI8-R characters per length
1240             #
1241              
1242             # 1 octet characters
1243             my @chars1 = ();
1244             sub chars1 {
1245 0 0   0 0 0 if (@chars1) {
1246 0         0 return @chars1;
1247             }
1248 0 0       0 if (exists $range_tr{1}) {
1249 0         0 my @ranges = @{ $range_tr{1} };
  0         0  
1250 0         0 while (my @range = splice(@ranges,0,1)) {
1251 0         0 for my $oct0 (@{$range[0]}) {
  0         0  
1252 0         0 push @chars1, pack 'C', $oct0;
1253             }
1254             }
1255             }
1256 0         0 return @chars1;
1257             }
1258              
1259             # 2 octets characters
1260             my @chars2 = ();
1261             sub chars2 {
1262 0 0   0 0 0 if (@chars2) {
1263 0         0 return @chars2;
1264             }
1265 0 0       0 if (exists $range_tr{2}) {
1266 0         0 my @ranges = @{ $range_tr{2} };
  0         0  
1267 0         0 while (my @range = splice(@ranges,0,2)) {
1268 0         0 for my $oct0 (@{$range[0]}) {
  0         0  
1269 0         0 for my $oct1 (@{$range[1]}) {
  0         0  
1270 0         0 push @chars2, pack 'CC', $oct0,$oct1;
1271             }
1272             }
1273             }
1274             }
1275 0         0 return @chars2;
1276             }
1277              
1278             # 3 octets characters
1279             my @chars3 = ();
1280             sub chars3 {
1281 0 0   0 0 0 if (@chars3) {
1282 0         0 return @chars3;
1283             }
1284 0 0       0 if (exists $range_tr{3}) {
1285 0         0 my @ranges = @{ $range_tr{3} };
  0         0  
1286 0         0 while (my @range = splice(@ranges,0,3)) {
1287 0         0 for my $oct0 (@{$range[0]}) {
  0         0  
1288 0         0 for my $oct1 (@{$range[1]}) {
  0         0  
1289 0         0 for my $oct2 (@{$range[2]}) {
  0         0  
1290 0         0 push @chars3, pack 'CCC', $oct0,$oct1,$oct2;
1291             }
1292             }
1293             }
1294             }
1295             }
1296 0         0 return @chars3;
1297             }
1298              
1299             # 4 octets characters
1300             my @chars4 = ();
1301             sub chars4 {
1302 0 0   0 0 0 if (@chars4) {
1303 0         0 return @chars4;
1304             }
1305 0 0       0 if (exists $range_tr{4}) {
1306 0         0 my @ranges = @{ $range_tr{4} };
  0         0  
1307 0         0 while (my @range = splice(@ranges,0,4)) {
1308 0         0 for my $oct0 (@{$range[0]}) {
  0         0  
1309 0         0 for my $oct1 (@{$range[1]}) {
  0         0  
1310 0         0 for my $oct2 (@{$range[2]}) {
  0         0  
1311 0         0 for my $oct3 (@{$range[3]}) {
  0         0  
1312 0         0 push @chars4, pack 'CCCC', $oct0,$oct1,$oct2,$oct3;
1313             }
1314             }
1315             }
1316             }
1317             }
1318             }
1319 0         0 return @chars4;
1320             }
1321              
1322             #
1323             # KOI8-R open character list for tr
1324             #
1325             sub _charlist_tr {
1326              
1327 0     0   0 local $_ = shift @_;
1328              
1329             # unescape character
1330 0         0 my @char = ();
1331 0         0 while (not /\G \z/oxmsgc) {
1332 0 0       0 if (/\G (\\0?55|\\x2[Dd]|\\-) /oxmsgc) {
    0          
    0          
    0          
    0          
    0          
    0          
1333 0         0 push @char, '\-';
1334             }
1335             elsif (/\G \\ ([0-7]{2,3}) /oxmsgc) {
1336 0         0 push @char, CORE::chr(oct $1);
1337             }
1338             elsif (/\G \\x ([0-9A-Fa-f]{1,2}) /oxmsgc) {
1339 0         0 push @char, CORE::chr(hex $1);
1340             }
1341             elsif (/\G \\c ([\x40-\x5F]) /oxmsgc) {
1342 0         0 push @char, CORE::chr(CORE::ord($1) & 0x1F);
1343             }
1344             elsif (/\G (\\ [0nrtfbae]) /oxmsgc) {
1345 0         0 push @char, {
1346             '\0' => "\0",
1347             '\n' => "\n",
1348             '\r' => "\r",
1349             '\t' => "\t",
1350             '\f' => "\f",
1351             '\b' => "\x08", # \b means backspace in character class
1352             '\a' => "\a",
1353             '\e' => "\e",
1354             }->{$1};
1355             }
1356             elsif (/\G \\ ($q_char) /oxmsgc) {
1357 0         0 push @char, $1;
1358             }
1359             elsif (/\G ($q_char) /oxmsgc) {
1360 0         0 push @char, $1;
1361             }
1362             }
1363              
1364             # join separated multiple-octet
1365 0         0 @char = join('',@char) =~ /\G (?>\\-|$q_char) /oxmsg;
1366              
1367             # unescape '-'
1368 0         0 my @i = ();
1369 0         0 for my $i (0 .. $#char) {
1370 0 0       0 if ($char[$i] eq '\-') {
    0          
1371 0         0 $char[$i] = '-';
1372             }
1373             elsif ($char[$i] eq '-') {
1374 0 0 0     0 if ((0 < $i) and ($i < $#char)) {
1375 0         0 push @i, $i;
1376             }
1377             }
1378             }
1379              
1380             # open character list (reverse for splice)
1381 0         0 for my $i (CORE::reverse @i) {
1382 0         0 my @range = ();
1383              
1384             # range error
1385 0 0 0     0 if ((CORE::length($char[$i-1]) > CORE::length($char[$i+1])) or ($char[$i-1] gt $char[$i+1])) {
1386 0         0 croak "Invalid tr/// range \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1387             }
1388              
1389             # range of multiple-octet code
1390 0 0       0 if (CORE::length($char[$i-1]) == 1) {
    0          
    0          
    0          
1391 0 0       0 if (CORE::length($char[$i+1]) == 1) {
    0          
    0          
    0          
1392 0 0       0 push @range, grep {($char[$i-1] le $_) and ($_ le $char[$i+1])} chars1();
  0         0  
1393             }
1394             elsif (CORE::length($char[$i+1]) == 2) {
1395 0         0 push @range, grep {$char[$i-1] le $_} chars1();
  0         0  
1396 0         0 push @range, grep {$_ le $char[$i+1]} chars2();
  0         0  
1397             }
1398             elsif (CORE::length($char[$i+1]) == 3) {
1399 0         0 push @range, grep {$char[$i-1] le $_} chars1();
  0         0  
1400 0         0 push @range, chars2();
1401 0         0 push @range, grep {$_ le $char[$i+1]} chars3();
  0         0  
1402             }
1403             elsif (CORE::length($char[$i+1]) == 4) {
1404 0         0 push @range, grep {$char[$i-1] le $_} chars1();
  0         0  
1405 0         0 push @range, chars2();
1406 0         0 push @range, chars3();
1407 0         0 push @range, grep {$_ le $char[$i+1]} chars4();
  0         0  
1408             }
1409             else {
1410 0         0 croak "Invalid tr/// range (over 4octets) \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1411             }
1412             }
1413             elsif (CORE::length($char[$i-1]) == 2) {
1414 0 0       0 if (CORE::length($char[$i+1]) == 2) {
    0          
    0          
1415 0 0       0 push @range, grep {($char[$i-1] le $_) and ($_ le $char[$i+1])} chars2();
  0         0  
1416             }
1417             elsif (CORE::length($char[$i+1]) == 3) {
1418 0         0 push @range, grep {$char[$i-1] le $_} chars2();
  0         0  
1419 0         0 push @range, grep {$_ le $char[$i+1]} chars3();
  0         0  
1420             }
1421             elsif (CORE::length($char[$i+1]) == 4) {
1422 0         0 push @range, grep {$char[$i-1] le $_} chars2();
  0         0  
1423 0         0 push @range, chars3();
1424 0         0 push @range, grep {$_ le $char[$i+1]} chars4();
  0         0  
1425             }
1426             else {
1427 0         0 croak "Invalid tr/// range (over 4octets) \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1428             }
1429             }
1430             elsif (CORE::length($char[$i-1]) == 3) {
1431 0 0       0 if (CORE::length($char[$i+1]) == 3) {
    0          
1432 0 0       0 push @range, grep {($char[$i-1] le $_) and ($_ le $char[$i+1])} chars3();
  0         0  
1433             }
1434             elsif (CORE::length($char[$i+1]) == 4) {
1435 0         0 push @range, grep {$char[$i-1] le $_} chars3();
  0         0  
1436 0         0 push @range, grep {$_ le $char[$i+1]} chars4();
  0         0  
1437             }
1438             else {
1439 0         0 croak "Invalid tr/// range (over 4octets) \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1440             }
1441             }
1442             elsif (CORE::length($char[$i-1]) == 4) {
1443 0 0       0 if (CORE::length($char[$i+1]) == 4) {
1444 0 0       0 push @range, grep {($char[$i-1] le $_) and ($_ le $char[$i+1])} chars4();
  0         0  
1445             }
1446             else {
1447 0         0 croak "Invalid tr/// range (over 4octets) \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1448             }
1449             }
1450             else {
1451 0         0 croak "Invalid tr/// range (over 4octets) \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1452             }
1453              
1454 0         0 splice @char, $i-1, 3, @range;
1455             }
1456              
1457 0         0 return @char;
1458             }
1459              
1460             #
1461             # KOI8-R open character class
1462             #
1463             sub _cc {
1464 0 0   0   0 if (scalar(@_) == 0) {
    0          
    0          
1465 0         0 die __FILE__, ": subroutine cc got no parameter.\n";
1466             }
1467             elsif (scalar(@_) == 1) {
1468 0         0 return sprintf('\x%02X',$_[0]);
1469             }
1470             elsif (scalar(@_) == 2) {
1471 0 0       0 if ($_[0] > $_[1]) {
    0          
    0          
1472 0         0 die __FILE__, ": subroutine cc got \$_[0] > \$_[1] parameters).\n";
1473             }
1474             elsif ($_[0] == $_[1]) {
1475 0         0 return sprintf('\x%02X',$_[0]);
1476             }
1477             elsif (($_[0]+1) == $_[1]) {
1478 0         0 return sprintf('[\\x%02X\\x%02X]',$_[0],$_[1]);
1479             }
1480             else {
1481 0         0 return sprintf('[\\x%02X-\\x%02X]',$_[0],$_[1]);
1482             }
1483             }
1484             else {
1485 0         0 die __FILE__, ": subroutine cc got 3 or more parameters (@{[scalar(@_)]} parameters).\n";
  0         0  
1486             }
1487             }
1488              
1489             #
1490             # KOI8-R octet range
1491             #
1492             sub _octets {
1493 0     0   0 my $length = shift @_;
1494              
1495 0 0       0 if ($length == 1) {
1496 0         0 my($a1) = unpack 'C', $_[0];
1497 0         0 my($z1) = unpack 'C', $_[1];
1498              
1499 0 0       0 if ($a1 > $z1) {
1500 0         0 croak 'Invalid [] range in regexp (CORE::ord(A) > CORE::ord(B)) ' . '\x' . unpack('H*',$a1) . '-\x' . unpack('H*',$z1);
1501             }
1502              
1503 0 0       0 if ($a1 == $z1) {
    0          
1504 0         0 return sprintf('\x%02X',$a1);
1505             }
1506             elsif (($a1+1) == $z1) {
1507 0         0 return sprintf('\x%02X\x%02X',$a1,$z1);
1508             }
1509             else {
1510 0         0 return sprintf('\x%02X-\x%02X',$a1,$z1);
1511             }
1512             }
1513             else {
1514 0         0 die __FILE__, ": subroutine _octets got invalid length ($length).\n";
1515             }
1516             }
1517              
1518             #
1519             # KOI8-R range regexp
1520             #
1521             sub _range_regexp {
1522 0     0   0 my($length,$first,$last) = @_;
1523              
1524 0         0 my @range_regexp = ();
1525 0 0       0 if (not exists $range_tr{$length}) {
1526 0         0 return @range_regexp;
1527             }
1528              
1529 0         0 my @ranges = @{ $range_tr{$length} };
  0         0  
1530 0         0 while (my @range = splice(@ranges,0,$length)) {
1531 0         0 my $min = '';
1532 0         0 my $max = '';
1533 0         0 for (my $i=0; $i < $length; $i++) {
1534 0         0 $min .= pack 'C', $range[$i][0];
1535 0         0 $max .= pack 'C', $range[$i][-1];
1536             }
1537              
1538             # min___max
1539             # FIRST_____________LAST
1540             # (nothing)
1541              
1542 0 0 0     0 if ($max lt $first) {
    0 0        
    0 0        
    0 0        
    0 0        
    0 0        
    0 0        
1543             }
1544              
1545             # **********
1546             # min_________max
1547             # FIRST_____________LAST
1548             # **********
1549              
1550             elsif (($min le $first) and ($first le $max) and ($max le $last)) {
1551 0         0 push @range_regexp, _octets($length,$first,$max,$min,$max);
1552             }
1553              
1554             # **********************
1555             # min________________max
1556             # FIRST_____________LAST
1557             # **********************
1558              
1559             elsif (($min eq $first) and ($max eq $last)) {
1560 0         0 push @range_regexp, _octets($length,$first,$last,$min,$max);
1561             }
1562              
1563             # *********
1564             # min___max
1565             # FIRST_____________LAST
1566             # *********
1567              
1568             elsif (($first le $min) and ($max le $last)) {
1569 0         0 push @range_regexp, _octets($length,$min,$max,$min,$max);
1570             }
1571              
1572             # **********************
1573             # min__________________________max
1574             # FIRST_____________LAST
1575             # **********************
1576              
1577             elsif (($min le $first) and ($last le $max)) {
1578 0         0 push @range_regexp, _octets($length,$first,$last,$min,$max);
1579             }
1580              
1581             # *********
1582             # min________max
1583             # FIRST_____________LAST
1584             # *********
1585              
1586             elsif (($first le $min) and ($min le $last) and ($last le $max)) {
1587 0         0 push @range_regexp, _octets($length,$min,$last,$min,$max);
1588             }
1589              
1590             # min___max
1591             # FIRST_____________LAST
1592             # (nothing)
1593              
1594             elsif ($last lt $min) {
1595             }
1596              
1597             else {
1598 0         0 die __FILE__, ": subroutine _range_regexp panic.\n";
1599             }
1600             }
1601              
1602 0         0 return @range_regexp;
1603             }
1604              
1605             #
1606             # KOI8-R open character list for qr and not qr
1607             #
1608             sub _charlist {
1609              
1610 0     0   0 my $modifier = pop @_;
1611 0         0 my @char = @_;
1612              
1613 0 0       0 my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
1614              
1615             # unescape character
1616 0         0 for (my $i=0; $i <= $#char; $i++) {
1617              
1618             # escape - to ...
1619 0 0 0     0 if ($char[$i] eq '-') {
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
1620 0 0 0     0 if ((0 < $i) and ($i < $#char)) {
1621 0         0 $char[$i] = '...';
1622             }
1623             }
1624              
1625             # octal escape sequence
1626             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
1627 0         0 $char[$i] = octchr($1);
1628             }
1629              
1630             # hexadecimal escape sequence
1631             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
1632 0         0 $char[$i] = hexchr($1);
1633             }
1634              
1635             # \b{...} --> b\{...}
1636             # \B{...} --> B\{...}
1637             # \N{CHARNAME} --> N\{CHARNAME}
1638             # \p{PROPERTY} --> p\{PROPERTY}
1639             # \P{PROPERTY} --> P\{PROPERTY}
1640             elsif ($char[$i] =~ /\A \\ ([bBNpP]) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
1641 0         0 $char[$i] = $1 . '\\' . $2;
1642             }
1643              
1644             # \p, \P, \X --> p, P, X
1645             elsif ($char[$i] =~ /\A \\ ( [pPX] ) \z/oxms) {
1646 0         0 $char[$i] = $1;
1647             }
1648              
1649             elsif ($char[$i] =~ /\A \\ ([0-7]{2,3}) \z/oxms) {
1650 0         0 $char[$i] = CORE::chr oct $1;
1651             }
1652             elsif ($char[$i] =~ /\A \\x ([0-9A-Fa-f]{1,2}) \z/oxms) {
1653 0         0 $char[$i] = CORE::chr hex $1;
1654             }
1655             elsif ($char[$i] =~ /\A \\c ([\x40-\x5F]) \z/oxms) {
1656 0         0 $char[$i] = CORE::chr(CORE::ord($1) & 0x1F);
1657             }
1658             elsif ($char[$i] =~ /\A (\\ [0nrtfbaedswDSWHVhvR]) \z/oxms) {
1659 0         0 $char[$i] = {
1660             '\0' => "\0",
1661             '\n' => "\n",
1662             '\r' => "\r",
1663             '\t' => "\t",
1664             '\f' => "\f",
1665             '\b' => "\x08", # \b means backspace in character class
1666             '\a' => "\a",
1667             '\e' => "\e",
1668             '\d' => '[0-9]',
1669              
1670             # Vertical tabs are now whitespace
1671             # \s in a regex now matches a vertical tab in all circumstances.
1672             # http://search.cpan.org/dist/perl-5.18.0/pod/perldelta.pod#Vertical_tabs_are_now_whitespace
1673             # \t \n \v \f \r space
1674             # '\s' => '[\x09\x0A \x0C\x0D\x20]',
1675             # '\s' => '[\x09\x0A\x0B\x0C\x0D\x20]',
1676             '\s' => '\s',
1677              
1678             '\w' => '[0-9A-Z_a-z]',
1679             '\D' => '${Ekoi8r::eD}',
1680             '\S' => '${Ekoi8r::eS}',
1681             '\W' => '${Ekoi8r::eW}',
1682              
1683             '\H' => '${Ekoi8r::eH}',
1684             '\V' => '${Ekoi8r::eV}',
1685             '\h' => '[\x09\x20]',
1686             '\v' => '[\x0A\x0B\x0C\x0D]',
1687             '\R' => '${Ekoi8r::eR}',
1688              
1689             }->{$1};
1690             }
1691              
1692             # POSIX-style character classes
1693             elsif ($ignorecase and ($char[$i] =~ /\A ( \[\: \^? (?:lower|upper) :\] ) \z/oxms)) {
1694 0         0 $char[$i] = {
1695              
1696             '[:lower:]' => '[\x41-\x5A\x61-\x7A]',
1697             '[:upper:]' => '[\x41-\x5A\x61-\x7A]',
1698             '[:^lower:]' => '${Ekoi8r::not_lower_i}',
1699             '[:^upper:]' => '${Ekoi8r::not_upper_i}',
1700              
1701             }->{$1};
1702             }
1703             elsif ($char[$i] =~ /\A ( \[\: \^? (?:alnum|alpha|ascii|blank|cntrl|digit|graph|lower|print|punct|space|upper|word|xdigit) :\] ) \z/oxms) {
1704 0         0 $char[$i] = {
1705              
1706             '[:alnum:]' => '[\x30-\x39\x41-\x5A\x61-\x7A]',
1707             '[:alpha:]' => '[\x41-\x5A\x61-\x7A]',
1708             '[:ascii:]' => '[\x00-\x7F]',
1709             '[:blank:]' => '[\x09\x20]',
1710             '[:cntrl:]' => '[\x00-\x1F\x7F]',
1711             '[:digit:]' => '[\x30-\x39]',
1712             '[:graph:]' => '[\x21-\x7F]',
1713             '[:lower:]' => '[\x61-\x7A]',
1714             '[:print:]' => '[\x20-\x7F]',
1715             '[:punct:]' => '[\x21-\x2F\x3A-\x3F\x40\x5B-\x5F\x60\x7B-\x7E]',
1716              
1717             # P.174 POSIX-Style Character Classes
1718             # in Chapter 5: Pattern Matching
1719             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
1720              
1721             # P.311 11.2.4 Character Classes and other Special Escapes
1722             # in Chapter 11: perlre: Perl regular expressions
1723             # of ISBN-13: 978-1-906966-02-7 The Perl Language Reference Manual (for Perl version 5.12.1)
1724              
1725             # P.210 POSIX-Style Character Classes
1726             # in Chapter 5: Pattern Matching
1727             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
1728              
1729             '[:space:]' => '[\s\x0B]', # "\s" plus vertical tab ("\cK")
1730              
1731             '[:upper:]' => '[\x41-\x5A]',
1732             '[:word:]' => '[\x30-\x39\x41-\x5A\x5F\x61-\x7A]',
1733             '[:xdigit:]' => '[\x30-\x39\x41-\x46\x61-\x66]',
1734             '[:^alnum:]' => '${Ekoi8r::not_alnum}',
1735             '[:^alpha:]' => '${Ekoi8r::not_alpha}',
1736             '[:^ascii:]' => '${Ekoi8r::not_ascii}',
1737             '[:^blank:]' => '${Ekoi8r::not_blank}',
1738             '[:^cntrl:]' => '${Ekoi8r::not_cntrl}',
1739             '[:^digit:]' => '${Ekoi8r::not_digit}',
1740             '[:^graph:]' => '${Ekoi8r::not_graph}',
1741             '[:^lower:]' => '${Ekoi8r::not_lower}',
1742             '[:^print:]' => '${Ekoi8r::not_print}',
1743             '[:^punct:]' => '${Ekoi8r::not_punct}',
1744             '[:^space:]' => '${Ekoi8r::not_space}',
1745             '[:^upper:]' => '${Ekoi8r::not_upper}',
1746             '[:^word:]' => '${Ekoi8r::not_word}',
1747             '[:^xdigit:]' => '${Ekoi8r::not_xdigit}',
1748              
1749             }->{$1};
1750             }
1751             elsif ($char[$i] =~ /\A \\ ($q_char) \z/oxms) {
1752 0         0 $char[$i] = $1;
1753             }
1754             }
1755              
1756             # open character list
1757 0         0 my @singleoctet = ();
1758 0         0 my @multipleoctet = ();
1759 0         0 for (my $i=0; $i <= $#char; ) {
1760              
1761             # escaped -
1762 0 0 0     0 if (defined($char[$i+1]) and ($char[$i+1] eq '...')) {
    0          
    0          
    0          
    0          
    0          
1763 0         0 $i += 1;
1764 0         0 next;
1765             }
1766              
1767             # make range regexp
1768             elsif ($char[$i] eq '...') {
1769              
1770             # range error
1771 0 0       0 if (CORE::length($char[$i-1]) > CORE::length($char[$i+1])) {
    0          
1772 0         0 croak 'Invalid [] range in regexp (length(A) > length(B)) ' . '\x' . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]);
1773             }
1774             elsif (CORE::length($char[$i-1]) == CORE::length($char[$i+1])) {
1775 0 0       0 if ($char[$i-1] gt $char[$i+1]) {
1776 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]);
1777             }
1778             }
1779              
1780             # make range regexp per length
1781 0         0 for my $length (CORE::length($char[$i-1]) .. CORE::length($char[$i+1])) {
1782 0         0 my @regexp = ();
1783              
1784             # is first and last
1785 0 0 0     0 if (($length == CORE::length($char[$i-1])) and ($length == CORE::length($char[$i+1]))) {
    0 0        
    0          
    0          
1786 0         0 push @regexp, _range_regexp($length, $char[$i-1], $char[$i+1]);
1787             }
1788              
1789             # is first
1790             elsif ($length == CORE::length($char[$i-1])) {
1791 0         0 push @regexp, _range_regexp($length, $char[$i-1], "\xFF" x $length);
1792             }
1793              
1794             # is inside in first and last
1795             elsif ((CORE::length($char[$i-1]) < $length) and ($length < CORE::length($char[$i+1]))) {
1796 0         0 push @regexp, _range_regexp($length, "\x00" x $length, "\xFF" x $length);
1797             }
1798              
1799             # is last
1800             elsif ($length == CORE::length($char[$i+1])) {
1801 0         0 push @regexp, _range_regexp($length, "\x00" x $length, $char[$i+1]);
1802             }
1803              
1804             else {
1805 0         0 die __FILE__, ": subroutine make_regexp panic.\n";
1806             }
1807              
1808 0 0       0 if ($length == 1) {
1809 0         0 push @singleoctet, @regexp;
1810             }
1811             else {
1812 0         0 push @multipleoctet, @regexp;
1813             }
1814             }
1815              
1816 0         0 $i += 2;
1817             }
1818              
1819             # with /i modifier
1820             elsif ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) {
1821 0 0       0 if ($modifier =~ /i/oxms) {
1822 0         0 my $uc = Ekoi8r::uc($char[$i]);
1823 0         0 my $fc = Ekoi8r::fc($char[$i]);
1824 0 0       0 if ($uc ne $fc) {
1825 0 0       0 if (CORE::length($fc) == 1) {
1826 0         0 push @singleoctet, $uc, $fc;
1827             }
1828             else {
1829 0         0 push @singleoctet, $uc;
1830 0         0 push @multipleoctet, $fc;
1831             }
1832             }
1833             else {
1834 0         0 push @singleoctet, $char[$i];
1835             }
1836             }
1837             else {
1838 0         0 push @singleoctet, $char[$i];
1839             }
1840 0         0 $i += 1;
1841             }
1842              
1843             # single character of single octet code
1844             elsif ($char[$i] =~ /\A (?: \\h ) \z/oxms) {
1845 0         0 push @singleoctet, "\t", "\x20";
1846 0         0 $i += 1;
1847             }
1848             elsif ($char[$i] =~ /\A (?: \\v ) \z/oxms) {
1849 0         0 push @singleoctet, "\x0A", "\x0B", "\x0C", "\x0D";
1850 0         0 $i += 1;
1851             }
1852             elsif ($char[$i] =~ /\A (?: \\d | \\s | \\w ) \z/oxms) {
1853 0         0 push @singleoctet, $char[$i];
1854 0         0 $i += 1;
1855             }
1856              
1857             # single character of multiple-octet code
1858             else {
1859 0         0 push @multipleoctet, $char[$i];
1860 0         0 $i += 1;
1861             }
1862             }
1863              
1864             # quote metachar
1865 0         0 for (@singleoctet) {
1866 0 0       0 if ($_ eq '...') {
    0          
    0          
    0          
    0          
1867 0         0 $_ = '-';
1868             }
1869             elsif (/\A \n \z/oxms) {
1870 0         0 $_ = '\n';
1871             }
1872             elsif (/\A \r \z/oxms) {
1873 0         0 $_ = '\r';
1874             }
1875             elsif (/\A ([\x00-\x20\x7F-\xFF]) \z/oxms) {
1876 0         0 $_ = sprintf('\x%02X', CORE::ord $1);
1877             }
1878             elsif (/\A [\x00-\xFF] \z/oxms) {
1879 0         0 $_ = quotemeta $_;
1880             }
1881             }
1882              
1883             # return character list
1884 0         0 return \@singleoctet, \@multipleoctet;
1885             }
1886              
1887             #
1888             # KOI8-R octal escape sequence
1889             #
1890             sub octchr {
1891 0     0 0 0 my($octdigit) = @_;
1892              
1893 0         0 my @binary = ();
1894 0         0 for my $octal (split(//,$octdigit)) {
1895 0         0 push @binary, {
1896             '0' => '000',
1897             '1' => '001',
1898             '2' => '010',
1899             '3' => '011',
1900             '4' => '100',
1901             '5' => '101',
1902             '6' => '110',
1903             '7' => '111',
1904             }->{$octal};
1905             }
1906 0         0 my $binary = join '', @binary;
1907              
1908 0         0 my $octchr = {
1909             # 1234567
1910             1 => pack('B*', "0000000$binary"),
1911             2 => pack('B*', "000000$binary"),
1912             3 => pack('B*', "00000$binary"),
1913             4 => pack('B*', "0000$binary"),
1914             5 => pack('B*', "000$binary"),
1915             6 => pack('B*', "00$binary"),
1916             7 => pack('B*', "0$binary"),
1917             0 => pack('B*', "$binary"),
1918              
1919             }->{CORE::length($binary) % 8};
1920              
1921 0         0 return $octchr;
1922             }
1923              
1924             #
1925             # KOI8-R hexadecimal escape sequence
1926             #
1927             sub hexchr {
1928 0     0 0 0 my($hexdigit) = @_;
1929              
1930 0         0 my $hexchr = {
1931             1 => pack('H*', "0$hexdigit"),
1932             0 => pack('H*', "$hexdigit"),
1933              
1934             }->{CORE::length($_[0]) % 2};
1935              
1936 0         0 return $hexchr;
1937             }
1938              
1939             #
1940             # KOI8-R open character list for qr
1941             #
1942             sub charlist_qr {
1943              
1944 0     0 0 0 my $modifier = pop @_;
1945 0         0 my @char = @_;
1946              
1947 0         0 my($singleoctet, $multipleoctet) = _charlist(@char, $modifier);
1948 0         0 my @singleoctet = @$singleoctet;
1949 0         0 my @multipleoctet = @$multipleoctet;
1950              
1951             # return character list
1952 0 0       0 if (scalar(@singleoctet) >= 1) {
1953              
1954             # with /i modifier
1955 0 0       0 if ($modifier =~ m/i/oxms) {
1956 0         0 my %singleoctet_ignorecase = ();
1957 0         0 for (@singleoctet) {
1958 0   0     0 while (s/ \A \\x(..) - \\x(..) //oxms or s/ \A \\x((..)) //oxms) {
1959 0         0 for my $ord (hex($1) .. hex($2)) {
1960 0         0 my $char = CORE::chr($ord);
1961 0         0 my $uc = Ekoi8r::uc($char);
1962 0         0 my $fc = Ekoi8r::fc($char);
1963 0 0       0 if ($uc eq $fc) {
1964 0         0 $singleoctet_ignorecase{unpack 'C*', $char} = 1;
1965             }
1966             else {
1967 0 0       0 if (CORE::length($fc) == 1) {
1968 0         0 $singleoctet_ignorecase{unpack 'C*', $uc} = 1;
1969 0         0 $singleoctet_ignorecase{unpack 'C*', $fc} = 1;
1970             }
1971             else {
1972 0         0 $singleoctet_ignorecase{unpack 'C*', $uc} = 1;
1973 0         0 push @multipleoctet, join '', map {sprintf('\x%02X',$_)} unpack 'C*', $fc;
  0         0  
1974             }
1975             }
1976             }
1977             }
1978 0 0       0 if ($_ ne '') {
1979 0         0 $singleoctet_ignorecase{unpack 'C*', $_} = 1;
1980             }
1981             }
1982 0         0 my $i = 0;
1983 0         0 my @singleoctet_ignorecase = ();
1984 0         0 for my $ord (0 .. 255) {
1985 0 0       0 if (exists $singleoctet_ignorecase{$ord}) {
1986 0         0 push @{$singleoctet_ignorecase[$i]}, $ord;
  0         0  
1987             }
1988             else {
1989 0         0 $i++;
1990             }
1991             }
1992 0         0 @singleoctet = ();
1993 0         0 for my $range (@singleoctet_ignorecase) {
1994 0 0       0 if (ref $range) {
1995 0 0       0 if (scalar(@{$range}) == 1) {
  0 0       0  
  0         0  
1996 0         0 push @singleoctet, sprintf('\x%02X', @{$range}[0]);
  0         0  
1997             }
1998             elsif (scalar(@{$range}) == 2) {
1999 0         0 push @singleoctet, sprintf('\x%02X\x%02X', @{$range}[0], @{$range}[-1]);
  0         0  
  0         0  
2000             }
2001             else {
2002 0         0 push @singleoctet, sprintf('\x%02X-\x%02X', @{$range}[0], @{$range}[-1]);
  0         0  
  0         0  
2003             }
2004             }
2005             }
2006             }
2007              
2008 0         0 my $not_anchor = '';
2009              
2010 0         0 push @multipleoctet, join('', $not_anchor, '[', @singleoctet, ']' );
2011             }
2012 0 0       0 if (scalar(@multipleoctet) >= 2) {
2013 0         0 return '(?:' . join('|', @multipleoctet) . ')';
2014             }
2015             else {
2016 0         0 return $multipleoctet[0];
2017             }
2018             }
2019              
2020             #
2021             # KOI8-R open character list for not qr
2022             #
2023             sub charlist_not_qr {
2024              
2025 0     0 0 0 my $modifier = pop @_;
2026 0         0 my @char = @_;
2027              
2028 0         0 my($singleoctet, $multipleoctet) = _charlist(@char, $modifier);
2029 0         0 my @singleoctet = @$singleoctet;
2030 0         0 my @multipleoctet = @$multipleoctet;
2031              
2032             # with /i modifier
2033 0 0       0 if ($modifier =~ m/i/oxms) {
2034 0         0 my %singleoctet_ignorecase = ();
2035 0         0 for (@singleoctet) {
2036 0   0     0 while (s/ \A \\x(..) - \\x(..) //oxms or s/ \A \\x((..)) //oxms) {
2037 0         0 for my $ord (hex($1) .. hex($2)) {
2038 0         0 my $char = CORE::chr($ord);
2039 0         0 my $uc = Ekoi8r::uc($char);
2040 0         0 my $fc = Ekoi8r::fc($char);
2041 0 0       0 if ($uc eq $fc) {
2042 0         0 $singleoctet_ignorecase{unpack 'C*', $char} = 1;
2043             }
2044             else {
2045 0 0       0 if (CORE::length($fc) == 1) {
2046 0         0 $singleoctet_ignorecase{unpack 'C*', $uc} = 1;
2047 0         0 $singleoctet_ignorecase{unpack 'C*', $fc} = 1;
2048             }
2049             else {
2050 0         0 $singleoctet_ignorecase{unpack 'C*', $uc} = 1;
2051 0         0 push @multipleoctet, join '', map {sprintf('\x%02X',$_)} unpack 'C*', $fc;
  0         0  
2052             }
2053             }
2054             }
2055             }
2056 0 0       0 if ($_ ne '') {
2057 0         0 $singleoctet_ignorecase{unpack 'C*', $_} = 1;
2058             }
2059             }
2060 0         0 my $i = 0;
2061 0         0 my @singleoctet_ignorecase = ();
2062 0         0 for my $ord (0 .. 255) {
2063 0 0       0 if (exists $singleoctet_ignorecase{$ord}) {
2064 0         0 push @{$singleoctet_ignorecase[$i]}, $ord;
  0         0  
2065             }
2066             else {
2067 0         0 $i++;
2068             }
2069             }
2070 0         0 @singleoctet = ();
2071 0         0 for my $range (@singleoctet_ignorecase) {
2072 0 0       0 if (ref $range) {
2073 0 0       0 if (scalar(@{$range}) == 1) {
  0 0       0  
  0         0  
2074 0         0 push @singleoctet, sprintf('\x%02X', @{$range}[0]);
  0         0  
2075             }
2076             elsif (scalar(@{$range}) == 2) {
2077 0         0 push @singleoctet, sprintf('\x%02X\x%02X', @{$range}[0], @{$range}[-1]);
  0         0  
  0         0  
2078             }
2079             else {
2080 0         0 push @singleoctet, sprintf('\x%02X-\x%02X', @{$range}[0], @{$range}[-1]);
  0         0  
  0         0  
2081             }
2082             }
2083             }
2084             }
2085              
2086             # return character list
2087 0 0       0 if (scalar(@multipleoctet) >= 1) {
2088 0 0       0 if (scalar(@singleoctet) >= 1) {
2089              
2090             # any character other than multiple-octet and single octet character class
2091 0         0 return '(?!' . join('|', @multipleoctet) . ')(?:[^' . join('', @singleoctet) . '])';
2092             }
2093             else {
2094              
2095             # any character other than multiple-octet character class
2096 0         0 return '(?!' . join('|', @multipleoctet) . ")(?:$your_char)";
2097             }
2098             }
2099             else {
2100 0 0       0 if (scalar(@singleoctet) >= 1) {
2101              
2102             # any character other than single octet character class
2103 0         0 return '(?:[^' . join('', @singleoctet) . '])';
2104             }
2105             else {
2106              
2107             # any character
2108 0         0 return "(?:$your_char)";
2109             }
2110             }
2111             }
2112              
2113             #
2114             # open file in read mode
2115             #
2116             sub _open_r {
2117 200     200   663 my(undef,$file) = @_;
2118 200         898 $file =~ s#\A (\s) #./$1#oxms;
2119 200   33     17945 return CORE::eval(q{open($_[0],'<',$_[1])}) ||
2120             open($_[0],"< $file\0");
2121             }
2122              
2123             #
2124             # open file in write mode
2125             #
2126             sub _open_w {
2127 0     0   0 my(undef,$file) = @_;
2128 0         0 $file =~ s#\A (\s) #./$1#oxms;
2129 0   0     0 return CORE::eval(q{open($_[0],'>',$_[1])}) ||
2130             open($_[0],"> $file\0");
2131             }
2132              
2133             #
2134             # open file in append mode
2135             #
2136             sub _open_a {
2137 0     0   0 my(undef,$file) = @_;
2138 0         0 $file =~ s#\A (\s) #./$1#oxms;
2139 0   0     0 return CORE::eval(q{open($_[0],'>>',$_[1])}) ||
2140             open($_[0],">> $file\0");
2141             }
2142              
2143             #
2144             # safe system
2145             #
2146             sub _systemx {
2147              
2148             # P.707 29.2.33. exec
2149             # in Chapter 29: Functions
2150             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
2151             #
2152             # Be aware that in older releases of Perl, exec (and system) did not flush
2153             # your output buffer, so you needed to enable command buffering by setting $|
2154             # on one or more filehandles to avoid lost output in the case of exec, or
2155             # misordererd output in the case of system. This situation was largely remedied
2156             # in the 5.6 release of Perl. (So, 5.005 release not yet.)
2157              
2158             # P.855 exec
2159             # in Chapter 27: Functions
2160             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
2161             #
2162             # In very old release of Perl (before v5.6), exec (and system) did not flush
2163             # your output buffer, so you needed to enable command buffering by setting $|
2164             # on one or more filehandles to avoid lost output with exec or misordered
2165             # output with system.
2166              
2167 200     200   801 $| = 1;
2168              
2169             # P.565 23.1.2. Cleaning Up Your Environment
2170             # in Chapter 23: Security
2171             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
2172              
2173             # P.656 Cleaning Up Your Environment
2174             # in Chapter 20: Security
2175             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
2176              
2177             # local $ENV{'PATH'} = '.';
2178 200         2188 local @ENV{qw(IFS CDPATH ENV BASH_ENV)}; # Make %ENV safer
2179              
2180             # P.707 29.2.33. exec
2181             # in Chapter 29: Functions
2182             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
2183             #
2184             # As we mentioned earlier, exec treats a discrete list of arguments as an
2185             # indication that it should bypass shell processing. However, there is one
2186             # place where you might still get tripped up. The exec call (and system, too)
2187             # will not distinguish between a single scalar argument and an array containing
2188             # only one element.
2189             #
2190             # @args = ("echo surprise"); # just one element in list
2191             # exec @args # still subject to shell escapes
2192             # or die "exec: $!"; # because @args == 1
2193             #
2194             # To avoid this, you can use the PATHNAME syntax, explicitly duplicating the
2195             # first argument as the pathname, which forces the rest of the arguments to be
2196             # interpreted as a list, even if there is only one of them:
2197             #
2198             # exec { $args[0] } @args # safe even with one-argument list
2199             # or die "can't exec @args: $!";
2200              
2201             # P.855 exec
2202             # in Chapter 27: Functions
2203             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
2204             #
2205             # As we mentioned earlier, exec treats a discrete list of arguments as a
2206             # directive to bypass shell processing. However, there is one place where
2207             # you might still get tripped up. The exec call (and system, too) cannot
2208             # distinguish between a single scalar argument and an array containing
2209             # only one element.
2210             #
2211             # @args = ("echo surprise"); # just one element in list
2212             # exec @args # still subject to shell escapes
2213             # || die "exec: $!"; # because @args == 1
2214             #
2215             # To avoid this, use the PATHNAME syntax, explicitly duplicating the first
2216             # argument as the pathname, which forces the rest of the arguments to be
2217             # interpreted as a list, even if there is only one of them:
2218             #
2219             # exec { $args[0] } @args # safe even with one-argument list
2220             # || die "can't exec @args: $!";
2221              
2222 200         461 return CORE::system { $_[0] } @_; # safe even with one-argument list
  200         24588736  
2223             }
2224              
2225             #
2226             # KOI8-R order to character (with parameter)
2227             #
2228             sub Ekoi8r::chr(;$) {
2229              
2230 0 0   0 0   my $c = @_ ? $_[0] : $_;
2231              
2232 0 0         if ($c == 0x00) {
2233 0           return "\x00";
2234             }
2235             else {
2236 0           my @chr = ();
2237 0           while ($c > 0) {
2238 0           unshift @chr, ($c % 0x100);
2239 0           $c = int($c / 0x100);
2240             }
2241 0           return pack 'C*', @chr;
2242             }
2243             }
2244              
2245             #
2246             # KOI8-R order to character (without parameter)
2247             #
2248             sub Ekoi8r::chr_() {
2249              
2250 0     0 0   my $c = $_;
2251              
2252 0 0         if ($c == 0x00) {
2253 0           return "\x00";
2254             }
2255             else {
2256 0           my @chr = ();
2257 0           while ($c > 0) {
2258 0           unshift @chr, ($c % 0x100);
2259 0           $c = int($c / 0x100);
2260             }
2261 0           return pack 'C*', @chr;
2262             }
2263             }
2264              
2265             #
2266             # KOI8-R path globbing (with parameter)
2267             #
2268             sub Ekoi8r::glob($) {
2269              
2270 0 0   0 0   if (wantarray) {
2271 0           my @glob = _DOS_like_glob(@_);
2272 0           for my $glob (@glob) {
2273 0           $glob =~ s{ \A (?:\./)+ }{}oxms;
2274             }
2275 0           return @glob;
2276             }
2277             else {
2278 0           my $glob = _DOS_like_glob(@_);
2279 0           $glob =~ s{ \A (?:\./)+ }{}oxms;
2280 0           return $glob;
2281             }
2282             }
2283              
2284             #
2285             # KOI8-R path globbing (without parameter)
2286             #
2287             sub Ekoi8r::glob_() {
2288              
2289 0 0   0 0   if (wantarray) {
2290 0           my @glob = _DOS_like_glob();
2291 0           for my $glob (@glob) {
2292 0           $glob =~ s{ \A (?:\./)+ }{}oxms;
2293             }
2294 0           return @glob;
2295             }
2296             else {
2297 0           my $glob = _DOS_like_glob();
2298 0           $glob =~ s{ \A (?:\./)+ }{}oxms;
2299 0           return $glob;
2300             }
2301             }
2302              
2303             #
2304             # KOI8-R path globbing via File::DosGlob 1.10
2305             #
2306             # Often I confuse "_dosglob" and "_doglob".
2307             # So, I renamed "_dosglob" to "_DOS_like_glob".
2308             #
2309             my %iter;
2310             my %entries;
2311             sub _DOS_like_glob {
2312              
2313             # context (keyed by second cxix argument provided by core)
2314 0     0     my($expr,$cxix) = @_;
2315              
2316             # glob without args defaults to $_
2317 0 0         $expr = $_ if not defined $expr;
2318              
2319             # represents the current user's home directory
2320             #
2321             # 7.3. Expanding Tildes in Filenames
2322             # in Chapter 7. File Access
2323             # of ISBN 0-596-00313-7 Perl Cookbook, 2nd Edition.
2324             #
2325             # and File::HomeDir, File::HomeDir::Windows module
2326              
2327             # DOS-like system
2328 0 0         if ($^O =~ /\A (?: MSWin32 | NetWare | symbian | dos ) \z/oxms) {
2329 0           $expr =~ s{ \A ~ (?= [^/\\] ) }
2330 0           { my_home_MSWin32() }oxmse;
2331             }
2332              
2333             # UNIX-like system
2334             else {
2335 0           $expr =~ s{ \A ~ ( (?:[^/])* ) }
2336 0 0 0       { $1 ? (CORE::eval(q{(getpwnam($1))[7]})||my_home()) : my_home() }oxmse;
2337             }
2338              
2339             # assume global context if not provided one
2340 0 0         $cxix = '_G_' if not defined $cxix;
2341 0 0         $iter{$cxix} = 0 if not exists $iter{$cxix};
2342              
2343             # if we're just beginning, do it all first
2344 0 0         if ($iter{$cxix} == 0) {
2345 0           $entries{$cxix} = [ _do_glob(1, _parse_line($expr)) ];
2346             }
2347              
2348             # chuck it all out, quick or slow
2349 0 0         if (wantarray) {
2350 0           delete $iter{$cxix};
2351 0           return @{delete $entries{$cxix}};
  0            
2352             }
2353             else {
2354 0 0         if ($iter{$cxix} = scalar @{$entries{$cxix}}) {
  0            
2355 0           return shift @{$entries{$cxix}};
  0            
2356             }
2357             else {
2358             # return undef for EOL
2359 0           delete $iter{$cxix};
2360 0           delete $entries{$cxix};
2361 0           return undef;
2362             }
2363             }
2364             }
2365              
2366             #
2367             # KOI8-R path globbing subroutine
2368             #
2369             sub _do_glob {
2370              
2371 0     0     my($cond,@expr) = @_;
2372 0           my @glob = ();
2373 0           my $fix_drive_relative_paths = 0;
2374              
2375             OUTER:
2376 0           for my $expr (@expr) {
2377 0 0         next OUTER if not defined $expr;
2378 0 0         next OUTER if $expr eq '';
2379              
2380 0           my @matched = ();
2381 0           my @globdir = ();
2382 0           my $head = '.';
2383 0           my $pathsep = '/';
2384 0           my $tail;
2385              
2386             # if argument is within quotes strip em and do no globbing
2387 0 0         if ($expr =~ /\A " ((?:$q_char)*?) " \z/oxms) {
2388 0           $expr = $1;
2389 0 0         if ($cond eq 'd') {
2390 0 0         if (-d $expr) {
2391 0           push @glob, $expr;
2392             }
2393             }
2394             else {
2395 0 0         if (-e $expr) {
2396 0           push @glob, $expr;
2397             }
2398             }
2399 0           next OUTER;
2400             }
2401              
2402             # wildcards with a drive prefix such as h:*.pm must be changed
2403             # to h:./*.pm to expand correctly
2404 0 0         if ($^O =~ /\A (?: MSWin32 | NetWare | symbian | dos ) \z/oxms) {
2405 0 0         if ($expr =~ s# \A ((?:[A-Za-z]:)?) ([^/\\]) #$1./$2#oxms) {
2406 0           $fix_drive_relative_paths = 1;
2407             }
2408             }
2409              
2410 0 0         if (($head, $tail) = _parse_path($expr,$pathsep)) {
2411 0 0         if ($tail eq '') {
2412 0           push @glob, $expr;
2413 0           next OUTER;
2414             }
2415 0 0         if ($head =~ / \A (?:$q_char)*? [*?] /oxms) {
2416 0 0         if (@globdir = _do_glob('d', $head)) {
2417 0           push @glob, _do_glob($cond, map {"$_$pathsep$tail"} @globdir);
  0            
2418 0           next OUTER;
2419             }
2420             }
2421 0 0 0       if ($head eq '' or $head =~ /\A [A-Za-z]: \z/oxms) {
2422 0           $head .= $pathsep;
2423             }
2424 0           $expr = $tail;
2425             }
2426              
2427             # If file component has no wildcards, we can avoid opendir
2428 0 0         if ($expr !~ / \A (?:$q_char)*? [*?] /oxms) {
2429 0 0         if ($head eq '.') {
2430 0           $head = '';
2431             }
2432 0 0 0       if ($head ne '' and ($head =~ / \G ($q_char) /oxmsg)[-1] ne $pathsep) {
2433 0           $head .= $pathsep;
2434             }
2435 0           $head .= $expr;
2436 0 0         if ($cond eq 'd') {
2437 0 0         if (-d $head) {
2438 0           push @glob, $head;
2439             }
2440             }
2441             else {
2442 0 0         if (-e $head) {
2443 0           push @glob, $head;
2444             }
2445             }
2446 0           next OUTER;
2447             }
2448 0 0         opendir(*DIR, $head) or next OUTER;
2449 0           my @leaf = readdir DIR;
2450 0           closedir DIR;
2451              
2452 0 0         if ($head eq '.') {
2453 0           $head = '';
2454             }
2455 0 0 0       if ($head ne '' and ($head =~ / \G ($q_char) /oxmsg)[-1] ne $pathsep) {
2456 0           $head .= $pathsep;
2457             }
2458              
2459 0           my $pattern = '';
2460 0           while ($expr =~ / \G ($q_char) /oxgc) {
2461 0           my $char = $1;
2462              
2463             # 6.9. Matching Shell Globs as Regular Expressions
2464             # in Chapter 6. Pattern Matching
2465             # of ISBN 0-596-00313-7 Perl Cookbook, 2nd Edition.
2466             # (and so on)
2467              
2468 0 0         if ($char eq '*') {
    0          
    0          
2469 0           $pattern .= "(?:$your_char)*",
2470             }
2471             elsif ($char eq '?') {
2472 0           $pattern .= "(?:$your_char)?", # DOS style
2473             # $pattern .= "(?:$your_char)", # UNIX style
2474             }
2475             elsif ((my $fc = Ekoi8r::fc($char)) ne $char) {
2476 0           $pattern .= $fc;
2477             }
2478             else {
2479 0           $pattern .= quotemeta $char;
2480             }
2481             }
2482 0     0     my $matchsub = sub { Ekoi8r::fc($_[0]) =~ /\A $pattern \z/xms };
  0            
2483              
2484             # if ($@) {
2485             # print STDERR "$0: $@\n";
2486             # next OUTER;
2487             # }
2488              
2489             INNER:
2490 0           for my $leaf (@leaf) {
2491 0 0 0       if ($leaf eq '.' or $leaf eq '..') {
2492 0           next INNER;
2493             }
2494 0 0 0       if ($cond eq 'd' and not -d "$head$leaf") {
2495 0           next INNER;
2496             }
2497              
2498 0 0         if (&$matchsub($leaf)) {
2499 0           push @matched, "$head$leaf";
2500 0           next INNER;
2501             }
2502              
2503             # [DOS compatibility special case]
2504             # Failed, add a trailing dot and try again, but only...
2505              
2506 0 0 0       if (Ekoi8r::index($leaf,'.') == -1 and # if name does not have a dot in it *and*
      0        
2507             CORE::length($leaf) <= 8 and # name is shorter than or equal to 8 chars *and*
2508             Ekoi8r::index($pattern,'\\.') != -1 # pattern has a dot.
2509             ) {
2510 0 0         if (&$matchsub("$leaf.")) {
2511 0           push @matched, "$head$leaf";
2512 0           next INNER;
2513             }
2514             }
2515             }
2516 0 0         if (@matched) {
2517 0           push @glob, @matched;
2518             }
2519             }
2520 0 0         if ($fix_drive_relative_paths) {
2521 0           for my $glob (@glob) {
2522 0           $glob =~ s# \A ([A-Za-z]:) \./ #$1#oxms;
2523             }
2524             }
2525 0           return @glob;
2526             }
2527              
2528             #
2529             # KOI8-R parse line
2530             #
2531             sub _parse_line {
2532              
2533 0     0     my($line) = @_;
2534              
2535 0           $line .= ' ';
2536 0           my @piece = ();
2537 0           while ($line =~ /
2538             " ( (?>(?: [^"] )* ) ) " (?>\s+) |
2539             ( (?>(?: [^"\s] )* ) ) (?>\s+)
2540             /oxmsg
2541             ) {
2542 0 0         push @piece, defined($1) ? $1 : $2;
2543             }
2544 0           return @piece;
2545             }
2546              
2547             #
2548             # KOI8-R parse path
2549             #
2550             sub _parse_path {
2551              
2552 0     0     my($path,$pathsep) = @_;
2553              
2554 0           $path .= '/';
2555 0           my @subpath = ();
2556 0           while ($path =~ /
2557             ((?: [^\/\\] )+?) [\/\\]
2558             /oxmsg
2559             ) {
2560 0           push @subpath, $1;
2561             }
2562              
2563 0           my $tail = pop @subpath;
2564 0           my $head = join $pathsep, @subpath;
2565 0           return $head, $tail;
2566             }
2567              
2568             #
2569             # via File::HomeDir::Windows 1.00
2570             #
2571             sub my_home_MSWin32 {
2572              
2573             # A lot of unix people and unix-derived tools rely on
2574             # the ability to overload HOME. We will support it too
2575             # so that they can replace raw HOME calls with File::HomeDir.
2576 0 0 0 0 0   if (exists $ENV{'HOME'} and $ENV{'HOME'}) {
    0 0        
    0 0        
      0        
      0        
2577 0           return $ENV{'HOME'};
2578             }
2579              
2580             # Do we have a user profile?
2581             elsif (exists $ENV{'USERPROFILE'} and $ENV{'USERPROFILE'}) {
2582 0           return $ENV{'USERPROFILE'};
2583             }
2584              
2585             # Some Windows use something like $ENV{'HOME'}
2586             elsif (exists $ENV{'HOMEDRIVE'} and exists $ENV{'HOMEPATH'} and $ENV{'HOMEDRIVE'} and $ENV{'HOMEPATH'}) {
2587 0           return join '', $ENV{'HOMEDRIVE'}, $ENV{'HOMEPATH'};
2588             }
2589              
2590 0           return undef;
2591             }
2592              
2593             #
2594             # via File::HomeDir::Unix 1.00
2595             #
2596             sub my_home {
2597 0     0 0   my $home;
2598              
2599 0 0 0       if (exists $ENV{'HOME'} and defined $ENV{'HOME'}) {
    0 0        
2600 0           $home = $ENV{'HOME'};
2601             }
2602              
2603             # This is from the original code, but I'm guessing
2604             # it means "login directory" and exists on some Unixes.
2605             elsif (exists $ENV{'LOGDIR'} and $ENV{'LOGDIR'}) {
2606 0           $home = $ENV{'LOGDIR'};
2607             }
2608              
2609             ### More-desperate methods
2610              
2611             # Light desperation on any (Unixish) platform
2612             else {
2613 0           $home = CORE::eval q{ (getpwuid($<))[7] };
2614             }
2615              
2616             # On Unix in general, a non-existant home means "no home"
2617             # For example, "nobody"-like users might use /nonexistant
2618 0 0 0       if (defined $home and ! -d($home)) {
2619 0           $home = undef;
2620             }
2621 0           return $home;
2622             }
2623              
2624             #
2625             # ${^PREMATCH}, $PREMATCH, $` the string preceding what was matched
2626             #
2627             sub Ekoi8r::PREMATCH {
2628 0     0 0   return $`;
2629             }
2630              
2631             #
2632             # ${^MATCH}, $MATCH, $& the string that matched
2633             #
2634             sub Ekoi8r::MATCH {
2635 0     0 0   return $&;
2636             }
2637              
2638             #
2639             # ${^POSTMATCH}, $POSTMATCH, $' the string following what was matched
2640             #
2641             sub Ekoi8r::POSTMATCH {
2642 0     0 0   return $';
2643             }
2644              
2645             #
2646             # KOI8-R character to order (with parameter)
2647             #
2648             sub KOI8R::ord(;$) {
2649              
2650 0 0   0 1   local $_ = shift if @_;
2651              
2652 0 0         if (/\A ($q_char) /oxms) {
2653 0           my @ord = unpack 'C*', $1;
2654 0           my $ord = 0;
2655 0           while (my $o = shift @ord) {
2656 0           $ord = $ord * 0x100 + $o;
2657             }
2658 0           return $ord;
2659             }
2660             else {
2661 0           return CORE::ord $_;
2662             }
2663             }
2664              
2665             #
2666             # KOI8-R character to order (without parameter)
2667             #
2668             sub KOI8R::ord_() {
2669              
2670 0 0   0 0   if (/\A ($q_char) /oxms) {
2671 0           my @ord = unpack 'C*', $1;
2672 0           my $ord = 0;
2673 0           while (my $o = shift @ord) {
2674 0           $ord = $ord * 0x100 + $o;
2675             }
2676 0           return $ord;
2677             }
2678             else {
2679 0           return CORE::ord $_;
2680             }
2681             }
2682              
2683             #
2684             # KOI8-R reverse
2685             #
2686             sub KOI8R::reverse(@) {
2687              
2688 0 0   0 0   if (wantarray) {
2689 0           return CORE::reverse @_;
2690             }
2691             else {
2692              
2693             # One of us once cornered Larry in an elevator and asked him what
2694             # problem he was solving with this, but he looked as far off into
2695             # the distance as he could in an elevator and said, "It seemed like
2696             # a good idea at the time."
2697              
2698 0           return join '', CORE::reverse(join('',@_) =~ /\G ($q_char) /oxmsg);
2699             }
2700             }
2701              
2702             #
2703             # KOI8-R getc (with parameter, without parameter)
2704             #
2705             sub KOI8R::getc(;*@) {
2706              
2707 0     0 0   my($package) = caller;
2708 0 0         my $fh = @_ ? qualify_to_ref(shift,$package) : \*STDIN;
2709 0 0 0       croak 'Too many arguments for KOI8R::getc' if @_ and not wantarray;
2710              
2711 0           my @length = sort { $a <=> $b } keys %range_tr;
  0            
2712 0           my $getc = '';
2713 0           for my $length ($length[0] .. $length[-1]) {
2714 0           $getc .= CORE::getc($fh);
2715 0 0         if (exists $range_tr{CORE::length($getc)}) {
2716 0 0         if ($getc =~ /\A ${Ekoi8r::dot_s} \z/oxms) {
2717 0 0         return wantarray ? ($getc,@_) : $getc;
2718             }
2719             }
2720             }
2721 0 0         return wantarray ? ($getc,@_) : $getc;
2722             }
2723              
2724             #
2725             # KOI8-R length by character
2726             #
2727             sub KOI8R::length(;$) {
2728              
2729 0 0   0 1   local $_ = shift if @_;
2730              
2731 0           local @_ = /\G ($q_char) /oxmsg;
2732 0           return scalar @_;
2733             }
2734              
2735             #
2736             # KOI8-R substr by character
2737             #
2738             BEGIN {
2739              
2740             # P.232 The lvalue Attribute
2741             # in Chapter 6: Subroutines
2742             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
2743              
2744             # P.336 The lvalue Attribute
2745             # in Chapter 7: Subroutines
2746             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
2747              
2748             # P.144 8.4 Lvalue subroutines
2749             # in Chapter 8: perlsub: Perl subroutines
2750             # of ISBN-13: 978-1-906966-02-7 The Perl Language Reference Manual (for Perl version 5.12.1)
2751              
2752 200 50 0 200 1 157257 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            
2753             # vv----------------------*******
2754             sub KOI8R::substr($$;$$) %s {
2755              
2756             my @char = $_[0] =~ /\G (?>$q_char) /oxmsg;
2757              
2758             # If the substring is beyond either end of the string, substr() returns the undefined
2759             # value and produces a warning. When used as an lvalue, specifying a substring that
2760             # is entirely outside the string raises an exception.
2761             # http://perldoc.perl.org/functions/substr.html
2762              
2763             # A return with no argument returns the scalar value undef in scalar context,
2764             # an empty list () in list context, and (naturally) nothing at all in void
2765             # context.
2766              
2767             my $offset = $_[1];
2768             if (($offset > scalar(@char)) or ($offset < (-1 * scalar(@char)))) {
2769             return;
2770             }
2771              
2772             # substr($string,$offset,$length,$replacement)
2773             if (@_ == 4) {
2774             my(undef,undef,$length,$replacement) = @_;
2775             my $substr = join '', splice(@char, $offset, $length, $replacement);
2776             $_[0] = join '', @char;
2777              
2778             # return $substr; this doesn't work, don't say "return"
2779             $substr;
2780             }
2781              
2782             # substr($string,$offset,$length)
2783             elsif (@_ == 3) {
2784             my(undef,undef,$length) = @_;
2785             my $octet_offset = 0;
2786             my $octet_length = 0;
2787             if ($offset == 0) {
2788             $octet_offset = 0;
2789             }
2790             elsif ($offset > 0) {
2791             $octet_offset = CORE::length(join '', @char[0..$offset-1]);
2792             }
2793             else {
2794             $octet_offset = -1 * CORE::length(join '', @char[$#char+$offset+1..$#char]);
2795             }
2796             if ($length == 0) {
2797             $octet_length = 0;
2798             }
2799             elsif ($length > 0) {
2800             $octet_length = CORE::length(join '', @char[$offset..$offset+$length-1]);
2801             }
2802             else {
2803             $octet_length = -1 * CORE::length(join '', @char[$#char+$length+1..$#char]);
2804             }
2805             CORE::substr($_[0], $octet_offset, $octet_length);
2806             }
2807              
2808             # substr($string,$offset)
2809             else {
2810             my $octet_offset = 0;
2811             if ($offset == 0) {
2812             $octet_offset = 0;
2813             }
2814             elsif ($offset > 0) {
2815             $octet_offset = CORE::length(join '', @char[0..$offset-1]);
2816             }
2817             else {
2818             $octet_offset = -1 * CORE::length(join '', @char[$#char+$offset+1..$#char]);
2819             }
2820             CORE::substr($_[0], $octet_offset);
2821             }
2822             }
2823             END
2824             }
2825              
2826             #
2827             # KOI8-R index by character
2828             #
2829             sub KOI8R::index($$;$) {
2830              
2831 0     0 1   my $index;
2832 0 0         if (@_ == 3) {
2833 0           $index = Ekoi8r::index($_[0], $_[1], CORE::length(KOI8R::substr($_[0], 0, $_[2])));
2834             }
2835             else {
2836 0           $index = Ekoi8r::index($_[0], $_[1]);
2837             }
2838              
2839 0 0         if ($index == -1) {
2840 0           return -1;
2841             }
2842             else {
2843 0           return KOI8R::length(CORE::substr $_[0], 0, $index);
2844             }
2845             }
2846              
2847             #
2848             # KOI8-R rindex by character
2849             #
2850             sub KOI8R::rindex($$;$) {
2851              
2852 0     0 1   my $rindex;
2853 0 0         if (@_ == 3) {
2854 0           $rindex = Ekoi8r::rindex($_[0], $_[1], CORE::length(KOI8R::substr($_[0], 0, $_[2])));
2855             }
2856             else {
2857 0           $rindex = Ekoi8r::rindex($_[0], $_[1]);
2858             }
2859              
2860 0 0         if ($rindex == -1) {
2861 0           return -1;
2862             }
2863             else {
2864 0           return KOI8R::length(CORE::substr $_[0], 0, $rindex);
2865             }
2866             }
2867              
2868             # when 'm//', '/' means regexp match 'm//' and '?' means regexp match '??'
2869             # when 'div', '/' means division operator and '?' means conditional operator (condition ? then : else)
2870 200     200   20518 BEGIN { CORE::eval q{ use vars qw($slash) } } $slash = 'm//';
  200     200   2087  
  200         527  
  200         17468  
2871              
2872             # ord() to ord() or KOI8R::ord()
2873 200     200   14946 BEGIN { CORE::eval q{ use vars qw($function_ord) } } $function_ord = 'ord';
  200     200   1241  
  200         413  
  200         13192  
2874              
2875             # ord to ord or KOI8R::ord_
2876 200     200   19647 BEGIN { CORE::eval q{ use vars qw($function_ord_) } } $function_ord_ = 'ord';
  200     200   1536  
  200         551  
  200         13590  
2877              
2878             # reverse to reverse or KOI8R::reverse
2879 200     200   13919 BEGIN { CORE::eval q{ use vars qw($function_reverse) } } $function_reverse = 'reverse';
  200     200   1375  
  200         561  
  200         15710  
2880              
2881             # getc to getc or KOI8R::getc
2882 200     200   14960 BEGIN { CORE::eval q{ use vars qw($function_getc) } } $function_getc = 'getc';
  200     200   1271  
  200         409  
  200         19745  
2883              
2884             # P.1023 Appendix W.9 Multibyte Anchoring
2885             # of ISBN 1-56592-224-7 CJKV Information Processing
2886              
2887             my $anchor = '';
2888              
2889 200     200   15568 BEGIN { CORE::eval q{ use vars qw($nest) } }
  200     200   1296  
  200         342  
  200         13023793  
2890              
2891             # regexp of nested parens in qqXX
2892              
2893             # P.340 Matching Nested Constructs with Embedded Code
2894             # in Chapter 7: Perl
2895             # of ISBN 0-596-00289-0 Mastering Regular Expressions, Second edition
2896              
2897             my $qq_paren = qr{(?{local $nest=0}) (?>(?:
2898             [^\\()] |
2899             \( (?{$nest++}) |
2900             \) (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!)) |
2901             \\ [^c] |
2902             \\c[\x40-\x5F] |
2903             [\x00-\xFF]
2904             }xms;
2905              
2906             my $qq_brace = qr{(?{local $nest=0}) (?>(?:
2907             [^\\{}] |
2908             \{ (?{$nest++}) |
2909             \} (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!)) |
2910             \\ [^c] |
2911             \\c[\x40-\x5F] |
2912             [\x00-\xFF]
2913             }xms;
2914              
2915             my $qq_bracket = qr{(?{local $nest=0}) (?>(?:
2916             [^\\\[\]] |
2917             \[ (?{$nest++}) |
2918             \] (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!)) |
2919             \\ [^c] |
2920             \\c[\x40-\x5F] |
2921             [\x00-\xFF]
2922             }xms;
2923              
2924             my $qq_angle = qr{(?{local $nest=0}) (?>(?:
2925             [^\\<>] |
2926             \< (?{$nest++}) |
2927             \> (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!)) |
2928             \\ [^c] |
2929             \\c[\x40-\x5F] |
2930             [\x00-\xFF]
2931             }xms;
2932              
2933             my $qq_scalar = qr{(?: \{ (?:$qq_brace)*? \} |
2934             (?: ::)? (?:
2935             (?> [a-zA-Z_][a-zA-Z_0-9]* (?: ::[a-zA-Z_][a-zA-Z_0-9]*)* )
2936             (?>(?: \[ (?: \$\[ | \$\] | $qq_char )*? \] | \{ (?:$qq_brace)*? \} )*)
2937             (?>(?: (?: -> )? (?: [\$\@\%\&\*]\* | \$\#\* | [\@\%]? \[ (?: \$\[ | \$\] | $qq_char )*? \] | [\@\%\*]? \{ (?:$qq_brace)*? \} ) )*)
2938             ))
2939             }xms;
2940              
2941             my $qq_variable = qr{(?: \{ (?:$qq_brace)*? \} |
2942             (?: ::)? (?:
2943             (?>[0-9]+) |
2944             [^a-zA-Z_0-9\[\]] |
2945             ^[A-Z] |
2946             (?> [a-zA-Z_][a-zA-Z_0-9]* (?: ::[a-zA-Z_][a-zA-Z_0-9]*)* )
2947             (?>(?: \[ (?: \$\[ | \$\] | $qq_char )*? \] | \{ (?:$qq_brace)*? \} )*)
2948             (?>(?: (?: -> )? (?: [\$\@\%\&\*]\* | \$\#\* | [\@\%]? \[ (?: \$\[ | \$\] | $qq_char )*? \] | [\@\%\*]? \{ (?:$qq_brace)*? \} ) )*)
2949             ))
2950             }xms;
2951              
2952             my $qq_substr = qr{(?> Char::substr | KOI8R::substr | CORE::substr | substr ) (?>\s*) \( $qq_paren \)
2953             }xms;
2954              
2955             # regexp of nested parens in qXX
2956             my $q_paren = qr{(?{local $nest=0}) (?>(?:
2957             [^()] |
2958             \( (?{$nest++}) |
2959             \) (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!)) |
2960             [\x00-\xFF]
2961             }xms;
2962              
2963             my $q_brace = qr{(?{local $nest=0}) (?>(?:
2964             [^\{\}] |
2965             \{ (?{$nest++}) |
2966             \} (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!)) |
2967             [\x00-\xFF]
2968             }xms;
2969              
2970             my $q_bracket = qr{(?{local $nest=0}) (?>(?:
2971             [^\[\]] |
2972             \[ (?{$nest++}) |
2973             \] (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!)) |
2974             [\x00-\xFF]
2975             }xms;
2976              
2977             my $q_angle = qr{(?{local $nest=0}) (?>(?:
2978             [^<>] |
2979             \< (?{$nest++}) |
2980             \> (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!)) |
2981             [\x00-\xFF]
2982             }xms;
2983              
2984             my $matched = '';
2985             my $s_matched = '';
2986              
2987             my $tr_variable = ''; # variable of tr///
2988             my $sub_variable = ''; # variable of s///
2989             my $bind_operator = ''; # =~ or !~
2990              
2991             my @heredoc = (); # here document
2992             my @heredoc_delimiter = ();
2993             my $here_script = ''; # here script
2994              
2995             #
2996             # escape KOI8-R script
2997             #
2998             sub KOI8R::escape(;$) {
2999 0 0   0 0   local($_) = $_[0] if @_;
3000              
3001             # P.359 The Study Function
3002             # in Chapter 7: Perl
3003             # of ISBN 0-596-00289-0 Mastering Regular Expressions, Second edition
3004              
3005 0           study $_; # Yes, I studied study yesterday.
3006              
3007             # while all script
3008              
3009             # 6.14. Matching from Where the Last Pattern Left Off
3010             # in Chapter 6. Pattern Matching
3011             # of ISBN 0-596-00313-7 Perl Cookbook, 2nd Edition.
3012             # (and so on)
3013              
3014             # one member of Tag-team
3015             #
3016             # P.128 Start of match (or end of previous match): \G
3017             # P.130 Advanced Use of \G with Perl
3018             # in Chapter 3: Overview of Regular Expression Features and Flavors
3019             # P.255 Use leading anchors
3020             # P.256 Expose ^ and \G at the front expressions
3021             # in Chapter 6: Crafting an Efficient Expression
3022             # P.315 "Tag-team" matching with /gc
3023             # in Chapter 7: Perl
3024             # of ISBN 0-596-00289-0 Mastering Regular Expressions, Second edition
3025              
3026 0           my $e_script = '';
3027 0           while (not /\G \z/oxgc) { # member
3028 0           $e_script .= KOI8R::escape_token();
3029             }
3030              
3031 0           return $e_script;
3032             }
3033              
3034             #
3035             # escape KOI8-R token of script
3036             #
3037             sub KOI8R::escape_token {
3038              
3039             # \n output here document
3040              
3041 0     0 0   my $ignore_modules = join('|', qw(
3042             utf8
3043             bytes
3044             charnames
3045             I18N::Japanese
3046             I18N::Collate
3047             I18N::JExt
3048             File::DosGlob
3049             Wild
3050             Wildcard
3051             Japanese
3052             ));
3053              
3054             # another member of Tag-team
3055             #
3056             # P.315 "Tag-team" matching with /gc
3057             # in Chapter 7: Perl
3058             # of ISBN 0-596-00289-0 Mastering Regular Expressions, Second edition
3059              
3060 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          
    0          
    0          
    0          
    0          
    0          
3061 0           my $heredoc = '';
3062 0 0         if (scalar(@heredoc_delimiter) >= 1) {
3063 0           $slash = 'm//';
3064              
3065 0           $heredoc = join '', @heredoc;
3066 0           @heredoc = ();
3067              
3068             # skip here document
3069 0           for my $heredoc_delimiter (@heredoc_delimiter) {
3070 0           /\G .*? \n $heredoc_delimiter \n/xmsgc;
3071             }
3072 0           @heredoc_delimiter = ();
3073              
3074 0           $here_script = '';
3075             }
3076 0           return "\n" . $heredoc;
3077             }
3078              
3079             # ignore space, comment
3080 0           elsif (/\G ((?>\s+)|\#.*) /oxgc) { return $1; }
3081              
3082             # if (, elsif (, unless (, while (, until (, given (, and when (
3083              
3084             # given, when
3085              
3086             # P.225 The given Statement
3087             # in Chapter 15: Smart Matching and given-when
3088             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
3089              
3090             # P.133 The given Statement
3091             # in Chapter 4: Statements and Declarations
3092             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
3093              
3094             elsif (/\G ( (?: if | elsif | unless | while | until | given | when ) (?>\s*) \( ) /oxgc) {
3095 0           $slash = 'm//';
3096 0           return $1;
3097             }
3098              
3099             # scalar variable ($scalar = ...) =~ tr///;
3100             # scalar variable ($scalar = ...) =~ s///;
3101              
3102             # state
3103              
3104             # P.68 Persistent, Private Variables
3105             # in Chapter 4: Subroutines
3106             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
3107              
3108             # P.160 Persistent Lexically Scoped Variables: state
3109             # in Chapter 4: Statements and Declarations
3110             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
3111              
3112             # (and so on)
3113              
3114             elsif (/\G ( \( (?>\s*) (?: local \b | my \b | our \b | state \b )? (?>\s*) \$ $qq_scalar ) /oxgc) {
3115 0           my $e_string = e_string($1);
3116              
3117 0 0         if (/\G ( (?>\s*) = $qq_paren \) ) ( (?>\s*) (?: =~ | !~ ) (?>\s*) ) (?= (?: tr | y ) \b ) /oxgc) {
    0          
3118 0           $tr_variable = $e_string . e_string($1);
3119 0           $bind_operator = $2;
3120 0           $slash = 'm//';
3121 0           return '';
3122             }
3123             elsif (/\G ( (?>\s*) = $qq_paren \) ) ( (?>\s*) (?: =~ | !~ ) (?>\s*) ) (?= s \b ) /oxgc) {
3124 0           $sub_variable = $e_string . e_string($1);
3125 0           $bind_operator = $2;
3126 0           $slash = 'm//';
3127 0           return '';
3128             }
3129             else {
3130 0           $slash = 'div';
3131 0           return $e_string;
3132             }
3133             }
3134              
3135             # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Ekoi8r::PREMATCH()
3136             elsif (/\G ( \$` | \$\{`\} | \$ (?>\s*) PREMATCH \b | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} ) /oxmsgc) {
3137 0           $slash = 'div';
3138 0           return q{Ekoi8r::PREMATCH()};
3139             }
3140              
3141             # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Ekoi8r::MATCH()
3142             elsif (/\G ( \$& | \$\{&\} | \$ (?>\s*) MATCH \b | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} ) /oxmsgc) {
3143 0           $slash = 'div';
3144 0           return q{Ekoi8r::MATCH()};
3145             }
3146              
3147             # $', ${'} --> $', ${'}
3148             elsif (/\G ( \$' | \$\{'\} ) /oxmsgc) {
3149 0           $slash = 'div';
3150 0           return $1;
3151             }
3152              
3153             # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Ekoi8r::POSTMATCH()
3154             elsif (/\G ( \$ (?>\s*) POSTMATCH \b | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} ) /oxmsgc) {
3155 0           $slash = 'div';
3156 0           return q{Ekoi8r::POSTMATCH()};
3157             }
3158              
3159             # scalar variable $scalar =~ tr///;
3160             # scalar variable $scalar =~ s///;
3161             # substr() =~ tr///;
3162             # substr() =~ s///;
3163             elsif (/\G ( \$ $qq_scalar | $qq_substr ) /oxgc) {
3164 0           my $scalar = e_string($1);
3165              
3166 0 0         if (/\G ( (?>\s*) (?: =~ | !~ ) (?>\s*) ) (?= (?: tr | y ) \b ) /oxgc) {
    0          
3167 0           $tr_variable = $scalar;
3168 0           $bind_operator = $1;
3169 0           $slash = 'm//';
3170 0           return '';
3171             }
3172             elsif (/\G ( (?>\s*) (?: =~ | !~ ) (?>\s*) ) (?= s \b ) /oxgc) {
3173 0           $sub_variable = $scalar;
3174 0           $bind_operator = $1;
3175 0           $slash = 'm//';
3176 0           return '';
3177             }
3178             else {
3179 0           $slash = 'div';
3180 0           return $scalar;
3181             }
3182             }
3183              
3184             # end of statement
3185             elsif (/\G ( [,;] ) /oxgc) {
3186 0           $slash = 'm//';
3187              
3188             # clear tr/// variable
3189 0           $tr_variable = '';
3190              
3191             # clear s/// variable
3192 0           $sub_variable = '';
3193              
3194 0           $bind_operator = '';
3195              
3196 0           return $1;
3197             }
3198              
3199             # bareword
3200             elsif (/\G ( \{ (?>\s*) (?: tr | index | rindex | reverse ) (?>\s*) \} ) /oxmsgc) {
3201 0           return $1;
3202             }
3203              
3204             # $0 --> $0
3205             elsif (/\G ( \$ 0 ) /oxmsgc) {
3206 0           $slash = 'div';
3207 0           return $1;
3208             }
3209             elsif (/\G ( \$ \{ (?>\s*) 0 (?>\s*) \} ) /oxmsgc) {
3210 0           $slash = 'div';
3211 0           return $1;
3212             }
3213              
3214             # $$ --> $$
3215             elsif (/\G ( \$ \$ ) (?![\w\{]) /oxmsgc) {
3216 0           $slash = 'div';
3217 0           return $1;
3218             }
3219              
3220             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
3221             # $1, $2, $3 --> $1, $2, $3 otherwise
3222             elsif (/\G \$ ((?>[1-9][0-9]*)) /oxmsgc) {
3223 0           $slash = 'div';
3224 0           return e_capture($1);
3225             }
3226             elsif (/\G \$ \{ (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} /oxmsgc) {
3227 0           $slash = 'div';
3228 0           return e_capture($1);
3229             }
3230              
3231             # $$foo[ ... ] --> $ $foo->[ ... ]
3232             elsif (/\G \$ ( \$ (?> [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \[ .+? \] ) /oxmsgc) {
3233 0           $slash = 'div';
3234 0           return e_capture($1.'->'.$2);
3235             }
3236              
3237             # $$foo{ ... } --> $ $foo->{ ... }
3238             elsif (/\G \$ ( \$ (?> [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \{ .+? \} ) /oxmsgc) {
3239 0           $slash = 'div';
3240 0           return e_capture($1.'->'.$2);
3241             }
3242              
3243             # $$foo
3244             elsif (/\G \$ ( \$ (?> [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) /oxmsgc) {
3245 0           $slash = 'div';
3246 0           return e_capture($1);
3247             }
3248              
3249             # ${ foo }
3250             elsif (/\G \$ (?>\s*) \{ ( (?>\s*) (?> [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) (?>\s*) ) \} /oxmsgc) {
3251 0           $slash = 'div';
3252 0           return '${' . $1 . '}';
3253             }
3254              
3255             # ${ ... }
3256             elsif (/\G \$ (?>\s*) \{ (?>\s*) ( $qq_brace ) (?>\s*) \} /oxmsgc) {
3257 0           $slash = 'div';
3258 0           return e_capture($1);
3259             }
3260              
3261             # variable or function
3262             # $ @ % & * $ #
3263             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) {
3264 0           $slash = 'div';
3265 0           return $1;
3266             }
3267             # $ $ $ $ $ $ $ $ $ $ $ $ $ $
3268             # $ @ # \ ' " / ? ( ) [ ] < >
3269             elsif (/\G ( \$[\$\@\#\\\'\"\/\?\(\)\[\]\<\>] ) /oxmsgc) {
3270 0           $slash = 'div';
3271 0           return $1;
3272             }
3273              
3274             # while ()
3275             elsif (/\G \b (while (?>\s*) \( (?>\s*) <[\$]?[A-Za-z_][A-Za-z_0-9]*> (?>\s*) \)) \b /oxgc) {
3276 0           return $1;
3277             }
3278              
3279             # while () --- glob
3280              
3281             # avoid "Error: Runtime exception" of perl version 5.005_03
3282              
3283             elsif (/\G \b while (?>\s*) \( (?>\s*) < ((?:[^>\0\a\e\f\n\r\t])+?) > (?>\s*) \) \b /oxgc) {
3284 0           return 'while ($_ = Ekoi8r::glob("' . $1 . '"))';
3285             }
3286              
3287             # while (glob)
3288             elsif (/\G \b while (?>\s*) \( (?>\s*) glob (?>\s*) \) /oxgc) {
3289 0           return 'while ($_ = Ekoi8r::glob_)';
3290             }
3291              
3292             # while (glob(WILDCARD))
3293             elsif (/\G \b while (?>\s*) \( (?>\s*) glob \b /oxgc) {
3294 0           return 'while ($_ = Ekoi8r::glob';
3295             }
3296              
3297             # doit if, doit unless, doit while, doit until, doit for, doit when
3298 0           elsif (/\G \b ( if | unless | while | until | for | when ) \b /oxgc) { $slash = 'm//'; return $1; }
  0            
3299              
3300             # subroutines of package Ekoi8r
3301 0           elsif (/\G \b (CORE:: | ->(>?\s*) (?: atan2 | [a-z]{2,})) \b /oxgc) { $slash = 'm//'; return $1; }
  0            
3302 0           elsif (/\G \b Char::eval (?= (?>\s*) \{ ) /oxgc) { $slash = 'm//'; return 'eval'; }
  0            
3303 0           elsif (/\G \b KOI8R::eval (?= (?>\s*) \{ ) /oxgc) { $slash = 'm//'; return 'eval'; }
  0            
3304 0           elsif (/\G \b Char::eval \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'eval Char::escape'; }
  0            
3305 0           elsif (/\G \b KOI8R::eval \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'eval KOI8R::escape'; }
  0            
3306 0           elsif (/\G \b bytes::substr \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'substr'; }
  0            
3307 0           elsif (/\G \b chop \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Ekoi8r::chop'; }
  0            
3308 0           elsif (/\G \b bytes::index \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'index'; }
  0            
3309 0           elsif (/\G \b Char::index \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Char::index'; }
  0            
3310 0           elsif (/\G \b KOI8R::index \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'KOI8R::index'; }
  0            
3311 0           elsif (/\G \b index \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Ekoi8r::index'; }
  0            
3312 0           elsif (/\G \b bytes::rindex \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'rindex'; }
  0            
3313 0           elsif (/\G \b Char::rindex \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Char::rindex'; }
  0            
3314 0           elsif (/\G \b KOI8R::rindex \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'KOI8R::rindex'; }
  0            
3315 0           elsif (/\G \b rindex \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Ekoi8r::rindex'; }
  0            
3316 0           elsif (/\G \b lc (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Ekoi8r::lc'; }
  0            
3317 0           elsif (/\G \b lcfirst (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Ekoi8r::lcfirst'; }
  0            
3318 0           elsif (/\G \b uc (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Ekoi8r::uc'; }
  0            
3319 0           elsif (/\G \b ucfirst (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Ekoi8r::ucfirst'; }
  0            
3320 0           elsif (/\G \b fc (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Ekoi8r::fc'; }
  0            
3321              
3322             # "-s '' ..." means file test "-s 'filename' ..." (not means "- s/// ...")
3323 0           elsif (/\G -s (?>\s*) (\") ((?:$qq_char)+?) (\") /oxgc) { $slash = 'm//'; return '-s ' . e_qq('', $1,$3,$2); }
  0            
3324 0           elsif (/\G -s (?>\s+) qq (?>\s*) (\#) ((?:$qq_char)+?) (\#) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0            
3325 0           elsif (/\G -s (?>\s+) qq (?>\s*) (\() ((?:$qq_paren)+?) (\)) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0            
3326 0           elsif (/\G -s (?>\s+) qq (?>\s*) (\{) ((?:$qq_brace)+?) (\}) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0            
3327 0           elsif (/\G -s (?>\s+) qq (?>\s*) (\[) ((?:$qq_bracket)+?) (\]) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0            
3328 0           elsif (/\G -s (?>\s+) qq (?>\s*) (\<) ((?:$qq_angle)+?) (\>) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0            
3329 0           elsif (/\G -s (?>\s+) qq (?>\s*) (\S) ((?:$qq_char)+?) (\1) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0            
3330              
3331 0           elsif (/\G -s (?>\s*) (\') ((?:\\\'|\\\\|$q_char)+?) (\') /oxgc) { $slash = 'm//'; return '-s ' . e_q ('', $1,$3,$2); }
  0            
3332 0           elsif (/\G -s (?>\s+) q (?>\s*) (\#) ((?:\\\#|\\\\|$q_char)+?) (\#) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0            
3333 0           elsif (/\G -s (?>\s+) q (?>\s*) (\() ((?:\\\)|\\\\|$q_paren)+?) (\)) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0            
3334 0           elsif (/\G -s (?>\s+) q (?>\s*) (\{) ((?:\\\}|\\\\|$q_brace)+?) (\}) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0            
3335 0           elsif (/\G -s (?>\s+) q (?>\s*) (\[) ((?:\\\]|\\\\|$q_bracket)+?) (\]) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0            
3336 0           elsif (/\G -s (?>\s+) q (?>\s*) (\<) ((?:\\\>|\\\\|$q_angle)+?) (\>) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0            
3337 0           elsif (/\G -s (?>\s+) q (?>\s*) (\S) ((?:\\\1|\\\\|$q_char)+?) (\1) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0            
3338              
3339             elsif (/\G -s (?>\s*) (\$ (?> \w+ (?: ::\w+)* ) (?: (?: ->)? (?: [\$\@\%\&\*]\* | \$\#\* | \( (?:$qq_paren)*? \) | [\@\%\*]? \{ (?:$qq_brace)+? \} | [\@\%]? \[ (?:$qq_bracket)+? \] ) )*) /oxgc)
3340 0           { $slash = 'm//'; return "-s $1"; }
  0            
3341 0           elsif (/\G -s (?>\s*) \( ((?:$qq_paren)*?) \) /oxgc) { $slash = 'm//'; return "-s ($1)"; }
  0            
3342 0           elsif (/\G -s (?= (?>\s+) [a-z]+) /oxgc) { $slash = 'm//'; return '-s'; }
  0            
3343 0           elsif (/\G -s (?>\s+) ((?>\w+)) /oxgc) { $slash = 'm//'; return "-s $1"; }
  0            
3344              
3345 0           elsif (/\G \b bytes::length (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'length'; }
  0            
3346 0           elsif (/\G \b bytes::chr (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'chr'; }
  0            
3347 0           elsif (/\G \b chr (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Ekoi8r::chr'; }
  0            
3348 0           elsif (/\G \b bytes::ord (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'div'; return 'ord'; }
  0            
3349 0           elsif (/\G \b ord (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'div'; return $function_ord; }
  0            
3350 0           elsif (/\G \b glob (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Ekoi8r::glob'; }
  0            
3351 0           elsif (/\G \b lc \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Ekoi8r::lc_'; }
  0            
3352 0           elsif (/\G \b lcfirst \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Ekoi8r::lcfirst_'; }
  0            
3353 0           elsif (/\G \b uc \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Ekoi8r::uc_'; }
  0            
3354 0           elsif (/\G \b ucfirst \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Ekoi8r::ucfirst_'; }
  0            
3355 0           elsif (/\G \b fc \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Ekoi8r::fc_'; }
  0            
3356 0           elsif (/\G -s \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return '-s '; }
  0            
3357              
3358 0           elsif (/\G \b bytes::length \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'length'; }
  0            
3359 0           elsif (/\G \b bytes::chr \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'chr'; }
  0            
3360 0           elsif (/\G \b chr \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Ekoi8r::chr_'; }
  0            
3361 0           elsif (/\G \b bytes::ord \b (?! (?>\s*) => ) /oxgc) { $slash = 'div'; return 'ord'; }
  0            
3362 0           elsif (/\G \b ord \b (?! (?>\s*) => ) /oxgc) { $slash = 'div'; return $function_ord_; }
  0            
3363 0           elsif (/\G \b glob \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Ekoi8r::glob_'; }
  0            
3364 0           elsif (/\G \b reverse \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return $function_reverse; }
  0            
3365 0           elsif (/\G \b getc \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return $function_getc; }
  0            
3366             # split
3367             elsif (/\G \b (split) \b (?! (?>\s*) => ) /oxgc) {
3368 0           $slash = 'm//';
3369              
3370 0           my $e = '';
3371 0           while (/\G ( (?>\s+) | \( | \#.* ) /oxgc) {
3372 0           $e .= $1;
3373             }
3374              
3375             # end of split
3376 0 0         if (/\G (?= [,;\)\}\]] ) /oxgc) { return 'Ekoi8r::split' . $e; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
3377              
3378             # split scalar value
3379 0           elsif (/\G ( [\$\@\&\*] $qq_scalar ) /oxgc) { return 'Ekoi8r::split' . $e . e_string($1); }
3380              
3381             # split literal space
3382 0           elsif (/\G \b qq (\#) [ ] (\#) /oxgc) { return 'Ekoi8r::split' . $e . qq {qq$1 $2}; }
3383 0           elsif (/\G \b qq ((?>\s*)) (\() [ ] (\)) /oxgc) { return 'Ekoi8r::split' . $e . qq{$1qq$2 $3}; }
3384 0           elsif (/\G \b qq ((?>\s*)) (\{) [ ] (\}) /oxgc) { return 'Ekoi8r::split' . $e . qq{$1qq$2 $3}; }
3385 0           elsif (/\G \b qq ((?>\s*)) (\[) [ ] (\]) /oxgc) { return 'Ekoi8r::split' . $e . qq{$1qq$2 $3}; }
3386 0           elsif (/\G \b qq ((?>\s*)) (\<) [ ] (\>) /oxgc) { return 'Ekoi8r::split' . $e . qq{$1qq$2 $3}; }
3387 0           elsif (/\G \b qq ((?>\s*)) (\S) [ ] (\2) /oxgc) { return 'Ekoi8r::split' . $e . qq{$1qq$2 $3}; }
3388 0           elsif (/\G \b q (\#) [ ] (\#) /oxgc) { return 'Ekoi8r::split' . $e . qq {q$1 $2}; }
3389 0           elsif (/\G \b q ((?>\s*)) (\() [ ] (\)) /oxgc) { return 'Ekoi8r::split' . $e . qq {$1q$2 $3}; }
3390 0           elsif (/\G \b q ((?>\s*)) (\{) [ ] (\}) /oxgc) { return 'Ekoi8r::split' . $e . qq {$1q$2 $3}; }
3391 0           elsif (/\G \b q ((?>\s*)) (\[) [ ] (\]) /oxgc) { return 'Ekoi8r::split' . $e . qq {$1q$2 $3}; }
3392 0           elsif (/\G \b q ((?>\s*)) (\<) [ ] (\>) /oxgc) { return 'Ekoi8r::split' . $e . qq {$1q$2 $3}; }
3393 0           elsif (/\G \b q ((?>\s*)) (\S) [ ] (\2) /oxgc) { return 'Ekoi8r::split' . $e . qq {$1q$2 $3}; }
3394 0           elsif (/\G ' [ ] ' /oxgc) { return 'Ekoi8r::split' . $e . qq {' '}; }
3395 0           elsif (/\G " [ ] " /oxgc) { return 'Ekoi8r::split' . $e . qq {" "}; }
3396              
3397             # split qq//
3398             elsif (/\G \b (qq) \b /oxgc) {
3399 0 0         if (/\G (\#) ((?:$qq_char)*?) (\#) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq# # --> qr # #
  0            
3400             else {
3401 0           while (not /\G \z/oxgc) {
3402 0 0         if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
3403 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq ( ) --> qr ( )
3404 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq { } --> qr { }
3405 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq [ ] --> qr [ ]
3406 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq < > --> qr < >
3407 0           elsif (/\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) /oxgc) { return e_split($e.'qr','{','}',$2,''); } # qq | | --> qr { }
3408 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq * * --> qr * *
3409             }
3410 0           die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3411             }
3412             }
3413              
3414             # split qr//
3415             elsif (/\G \b (qr) \b /oxgc) {
3416 0 0         if (/\G (\#) ((?:$qq_char)*?) (\#) ([imosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1,$3,$2,$4); } # qr# #
  0            
3417             else {
3418 0           while (not /\G \z/oxgc) {
3419 0 0         if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
3420 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([imosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # qr ( )
3421 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([imosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # qr { }
3422 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([imosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # qr [ ]
3423 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([imosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # qr < >
3424 0           elsif (/\G (\') ((?:$qq_char)*?) (\') ([imosxpadlunbB]*) /oxgc) { return e_split_q($e.'qr',$1, $3, $2,$4); } # qr ' '
3425 0           elsif (/\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ([imosxpadlunbB]*) /oxgc) { return e_split ($e.'qr','{','}',$2,$4); } # qr | | --> qr { }
3426 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([imosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # qr * *
3427             }
3428 0           die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3429             }
3430             }
3431              
3432             # split q//
3433             elsif (/\G \b (q) \b /oxgc) {
3434 0 0         if (/\G (\#) ((?:\\\#|\\\\|$q_char)*?) (\#) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q# # --> qr # #
  0            
3435             else {
3436 0           while (not /\G \z/oxgc) {
3437 0 0         if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
3438 0           elsif (/\G (\() ((?:\\\\|\\\)|\\\(|$q_paren)*?) (\)) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q ( ) --> qr ( )
3439 0           elsif (/\G (\{) ((?:\\\\|\\\}|\\\{|$q_brace)*?) (\}) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q { } --> qr { }
3440 0           elsif (/\G (\[) ((?:\\\\|\\\]|\\\[|$q_bracket)*?) (\]) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q [ ] --> qr [ ]
3441 0           elsif (/\G (\<) ((?:\\\\|\\\>|\\\<|$q_angle)*?) (\>) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q < > --> qr < >
3442 0           elsif (/\G ([*\-:?\\^|]) ((?:$q_char)*?) (\1) /oxgc) { return e_split_q($e.'qr','{','}',$2,''); } # q | | --> qr { }
3443 0           elsif (/\G (\S) ((?:\\\\|\\\1| $q_char)*?) (\1) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q * * --> qr * *
3444             }
3445 0           die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3446             }
3447             }
3448              
3449             # split m//
3450             elsif (/\G \b (m) \b /oxgc) {
3451 0 0         if (/\G (\#) ((?:$qq_char)*?) (\#) ([cgimosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1,$3,$2,$4); } # m# # --> qr # #
  0            
3452             else {
3453 0           while (not /\G \z/oxgc) {
3454 0 0         if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
3455 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cgimosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # m ( ) --> qr ( )
3456 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cgimosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # m { } --> qr { }
3457 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cgimosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # m [ ] --> qr [ ]
3458 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cgimosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # m < > --> qr < >
3459 0           elsif (/\G (\') ((?:$qq_char)*?) (\') ([cgimosxpadlunbB]*) /oxgc) { return e_split_q($e.'qr',$1, $3, $2,$4); } # m ' ' --> qr ' '
3460 0           elsif (/\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ([cgimosxpadlunbB]*) /oxgc) { return e_split ($e.'qr','{','}',$2,$4); } # m | | --> qr { }
3461 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cgimosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # m * * --> qr * *
3462             }
3463 0           die __FILE__, ": Search pattern not terminated\n";
3464             }
3465             }
3466              
3467             # split ''
3468             elsif (/\G (\') /oxgc) {
3469 0           my $q_string = '';
3470 0           while (not /\G \z/oxgc) {
3471 0 0         if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0          
    0          
    0          
3472 0           elsif (/\G (\\\') /oxgc) { $q_string .= $1; } # splitqr'' --> split qr''
3473 0           elsif (/\G \' /oxgc) { return e_split_q($e.q{ qr},"'","'",$q_string,''); } # ' ' --> qr ' '
3474 0           elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3475             }
3476 0           die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3477             }
3478              
3479             # split ""
3480             elsif (/\G (\") /oxgc) {
3481 0           my $qq_string = '';
3482 0           while (not /\G \z/oxgc) {
3483 0 0         if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0          
    0          
    0          
3484 0           elsif (/\G (\\\") /oxgc) { $qq_string .= $1; } # splitqr"" --> split qr""
3485 0           elsif (/\G \" /oxgc) { return e_split($e.q{ qr},'"','"',$qq_string,''); } # " " --> qr " "
3486 0           elsif (/\G ($q_char) /oxgc) { $qq_string .= $1; }
3487             }
3488 0           die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3489             }
3490              
3491             # split //
3492             elsif (/\G (\/) /oxgc) {
3493 0           my $regexp = '';
3494 0           while (not /\G \z/oxgc) {
3495 0 0         if (/\G (\\\\) /oxgc) { $regexp .= $1; }
  0 0          
    0          
    0          
3496 0           elsif (/\G (\\\/) /oxgc) { $regexp .= $1; } # splitqr// --> split qr//
3497 0           elsif (/\G \/ ([cgimosxpadlunbB]*) /oxgc) { return e_split($e.q{ qr}, '/','/',$regexp,$1); } # / / --> qr / /
3498 0           elsif (/\G ($q_char) /oxgc) { $regexp .= $1; }
3499             }
3500 0           die __FILE__, ": Search pattern not terminated\n";
3501             }
3502             }
3503              
3504             # tr/// or y///
3505              
3506             # about [cdsrbB]* (/B modifier)
3507             #
3508             # P.559 appendix C
3509             # of ISBN 4-89052-384-7 Programming perl
3510             # (Japanese title is: Perl puroguramingu)
3511              
3512             elsif (/\G \b ( tr | y ) \b /oxgc) {
3513 0           my $ope = $1;
3514              
3515             # $1 $2 $3 $4 $5 $6
3516 0 0         if (/\G (\#) ((?:$qq_char)*?) (\#) ((?:$qq_char)*?) (\#) ([cdsrbB]*) /oxgc) { # tr# # #
3517 0           my @tr = ($tr_variable,$2);
3518 0           return e_tr(@tr,'',$4,$6);
3519             }
3520             else {
3521 0           my $e = '';
3522 0           while (not /\G \z/oxgc) {
3523 0 0         if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3524             elsif (/\G (\() ((?:$qq_paren)*?) (\)) /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\n";
3535             }
3536             elsif (/\G (\{) ((?:$qq_brace)*?) (\}) /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\n";
3547             }
3548             elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) {
3549 0           my @tr = ($tr_variable,$2);
3550 0           while (not /\G \z/oxgc) {
3551 0 0         if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3552 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr [ ] ( )
3553 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr [ ] { }
3554 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr [ ] [ ]
3555 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr [ ] < >
3556 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr [ ] * *
3557             }
3558 0           die __FILE__, ": Transliteration replacement not terminated\n";
3559             }
3560             elsif (/\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) {
3561 0           my @tr = ($tr_variable,$2);
3562 0           while (not /\G \z/oxgc) {
3563 0 0         if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3564 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr < > ( )
3565 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr < > { }
3566 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr < > [ ]
3567 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr < > < >
3568 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr < > * *
3569             }
3570 0           die __FILE__, ": Transliteration replacement not terminated\n";
3571             }
3572             # $1 $2 $3 $4 $5 $6
3573             elsif (/\G (\S) ((?:$qq_char)*?) (\1) ((?:$qq_char)*?) (\1) ([cdsrbB]*) /oxgc) { # tr * * *
3574 0           my @tr = ($tr_variable,$2);
3575 0           return e_tr(@tr,'',$4,$6);
3576             }
3577             }
3578 0           die __FILE__, ": Transliteration pattern not terminated\n";
3579             }
3580             }
3581              
3582             # qq//
3583             elsif (/\G \b (qq) \b /oxgc) {
3584 0           my $ope = $1;
3585              
3586             # if (/\G (\#) ((?:$qq_char)*?) (\#) /oxgc) { return e_qq($ope,$1,$3,$2); } # qq# #
3587 0 0         if (/\G (\#) /oxgc) { # qq# #
3588 0           my $qq_string = '';
3589 0           while (not /\G \z/oxgc) {
3590 0 0         if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0          
    0          
    0          
3591 0           elsif (/\G (\\\#) /oxgc) { $qq_string .= $1; }
3592 0           elsif (/\G (\#) /oxgc) { return e_qq($ope,'#','#',$qq_string); }
3593 0           elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3594             }
3595 0           die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3596             }
3597              
3598             else {
3599 0           my $e = '';
3600 0           while (not /\G \z/oxgc) {
3601 0 0         if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3602              
3603             # elsif (/\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qq ( )
3604             elsif (/\G (\() /oxgc) { # qq ( )
3605 0           my $qq_string = '';
3606 0           local $nest = 1;
3607 0           while (not /\G \z/oxgc) {
3608 0 0         if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0          
    0          
    0          
    0          
3609 0           elsif (/\G (\\\)) /oxgc) { $qq_string .= $1; }
3610 0           elsif (/\G (\() /oxgc) { $qq_string .= $1; $nest++; }
  0            
3611             elsif (/\G (\)) /oxgc) {
3612 0 0         if (--$nest == 0) { return $e . e_qq($ope,'(',')',$qq_string); }
  0            
3613 0           else { $qq_string .= $1; }
3614             }
3615 0           elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3616             }
3617 0           die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3618             }
3619              
3620             # elsif (/\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qq { }
3621             elsif (/\G (\{) /oxgc) { # qq { }
3622 0           my $qq_string = '';
3623 0           local $nest = 1;
3624 0           while (not /\G \z/oxgc) {
3625 0 0         if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0          
    0          
    0          
    0          
3626 0           elsif (/\G (\\\}) /oxgc) { $qq_string .= $1; }
3627 0           elsif (/\G (\{) /oxgc) { $qq_string .= $1; $nest++; }
  0            
3628             elsif (/\G (\}) /oxgc) {
3629 0 0         if (--$nest == 0) { return $e . e_qq($ope,'{','}',$qq_string); }
  0            
3630 0           else { $qq_string .= $1; }
3631             }
3632 0           elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3633             }
3634 0           die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3635             }
3636              
3637             # elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qq [ ]
3638             elsif (/\G (\[) /oxgc) { # qq [ ]
3639 0           my $qq_string = '';
3640 0           local $nest = 1;
3641 0           while (not /\G \z/oxgc) {
3642 0 0         if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0          
    0          
    0          
    0          
3643 0           elsif (/\G (\\\]) /oxgc) { $qq_string .= $1; }
3644 0           elsif (/\G (\[) /oxgc) { $qq_string .= $1; $nest++; }
  0            
3645             elsif (/\G (\]) /oxgc) {
3646 0 0         if (--$nest == 0) { return $e . e_qq($ope,'[',']',$qq_string); }
  0            
3647 0           else { $qq_string .= $1; }
3648             }
3649 0           elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3650             }
3651 0           die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3652             }
3653              
3654             # elsif (/\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qq < >
3655             elsif (/\G (\<) /oxgc) { # qq < >
3656 0           my $qq_string = '';
3657 0           local $nest = 1;
3658 0           while (not /\G \z/oxgc) {
3659 0 0         if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0          
    0          
    0          
    0          
3660 0           elsif (/\G (\\\>) /oxgc) { $qq_string .= $1; }
3661 0           elsif (/\G (\<) /oxgc) { $qq_string .= $1; $nest++; }
  0            
3662             elsif (/\G (\>) /oxgc) {
3663 0 0         if (--$nest == 0) { return $e . e_qq($ope,'<','>',$qq_string); }
  0            
3664 0           else { $qq_string .= $1; }
3665             }
3666 0           elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3667             }
3668 0           die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3669             }
3670              
3671             # elsif (/\G (\S) ((?:$qq_char)*?) (\1) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qq * *
3672             elsif (/\G (\S) /oxgc) { # qq * *
3673 0           my $delimiter = $1;
3674 0           my $qq_string = '';
3675 0           while (not /\G \z/oxgc) {
3676 0 0         if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0          
    0          
    0          
3677 0           elsif (/\G (\\\Q$delimiter\E) /oxgc) { $qq_string .= $1; }
3678 0           elsif (/\G (\Q$delimiter\E) /oxgc) { return $e . e_qq($ope,$delimiter,$delimiter,$qq_string); }
3679 0           elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3680             }
3681 0           die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3682             }
3683             }
3684 0           die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3685             }
3686             }
3687              
3688             # qr//
3689             elsif (/\G \b (qr) \b /oxgc) {
3690 0           my $ope = $1;
3691 0 0         if (/\G (\#) ((?:$qq_char)*?) (\#) ([imosxpadlunbB]*) /oxgc) { # qr# # #
3692 0           return e_qr($ope,$1,$3,$2,$4);
3693             }
3694             else {
3695 0           my $e = '';
3696 0           while (not /\G \z/oxgc) {
3697 0 0         if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
3698 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([imosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # qr ( )
3699 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([imosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # qr { }
3700 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([imosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # qr [ ]
3701 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([imosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # qr < >
3702 0           elsif (/\G (\') ((?:$qq_char)*?) (\') ([imosxpadlunbB]*) /oxgc) { return $e . e_qr_q($ope,$1, $3, $2,$4); } # qr ' '
3703 0           elsif (/\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ([imosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,'{','}',$2,$4); } # qr | | --> qr { }
3704 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([imosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # qr * *
3705             }
3706 0           die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3707             }
3708             }
3709              
3710             # qw//
3711             elsif (/\G \b (qw) \b /oxgc) {
3712 0           my $ope = $1;
3713 0 0         if (/\G (\#) (.*?) (\#) /oxmsgc) { # qw# #
3714 0           return e_qw($ope,$1,$3,$2);
3715             }
3716             else {
3717 0           my $e = '';
3718 0           while (not /\G \z/oxgc) {
3719 0 0         if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
3720              
3721 0           elsif (/\G (\() ([^(]*?) (\)) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw ( )
3722 0           elsif (/\G (\() ((?:$q_paren)*?) (\)) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw ( )
3723              
3724 0           elsif (/\G (\{) ([^{]*?) (\}) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw { }
3725 0           elsif (/\G (\{) ((?:$q_brace)*?) (\}) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw { }
3726              
3727 0           elsif (/\G (\[) ([^[]*?) (\]) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw [ ]
3728 0           elsif (/\G (\[) ((?:$q_bracket)*?) (\]) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw [ ]
3729              
3730 0           elsif (/\G (\<) ([^<]*?) (\>) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw < >
3731 0           elsif (/\G (\<) ((?:$q_angle)*?) (\>) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw < >
3732              
3733 0           elsif (/\G ([\x21-\x3F]) (.*?) (\1) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw * *
3734 0           elsif (/\G (\S) ((?:$q_char)*?) (\1) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw * *
3735             }
3736 0           die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3737             }
3738             }
3739              
3740             # qx//
3741             elsif (/\G \b (qx) \b /oxgc) {
3742 0           my $ope = $1;
3743 0 0         if (/\G (\#) ((?:$qq_char)*?) (\#) /oxgc) { # qx# #
3744 0           return e_qq($ope,$1,$3,$2);
3745             }
3746             else {
3747 0           my $e = '';
3748 0           while (not /\G \z/oxgc) {
3749 0 0         if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
3750 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qx ( )
3751 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qx { }
3752 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qx [ ]
3753 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qx < >
3754 0           elsif (/\G (\') ((?:$qq_char)*?) (\') /oxgc) { return $e . e_q ($ope,$1,$3,$2); } # qx ' '
3755 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qx * *
3756             }
3757 0           die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3758             }
3759             }
3760              
3761             # q//
3762             elsif (/\G \b (q) \b /oxgc) {
3763 0           my $ope = $1;
3764              
3765             # if (/\G (\#) ((?:\\\#|\\\\|$q_char)*?) (\#) /oxgc) { return e_q($ope,$1,$3,$2); } # q# #
3766              
3767             # avoid "Error: Runtime exception" of perl version 5.005_03
3768             # (and so on)
3769              
3770 0 0         if (/\G (\#) /oxgc) { # q# #
3771 0           my $q_string = '';
3772 0           while (not /\G \z/oxgc) {
3773 0 0         if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0          
    0          
    0          
3774 0           elsif (/\G (\\\#) /oxgc) { $q_string .= $1; }
3775 0           elsif (/\G (\#) /oxgc) { return e_q($ope,'#','#',$q_string); }
3776 0           elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3777             }
3778 0           die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3779             }
3780              
3781             else {
3782 0           my $e = '';
3783 0           while (not /\G \z/oxgc) {
3784 0 0         if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3785              
3786             # elsif (/\G (\() ((?:\\\)|\\\\|$q_paren)*?) (\)) /oxgc) { return $e . e_q($ope,$1,$3,$2); } # q ( )
3787             elsif (/\G (\() /oxgc) { # q ( )
3788 0           my $q_string = '';
3789 0           local $nest = 1;
3790 0           while (not /\G \z/oxgc) {
3791 0 0         if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3792 0           elsif (/\G (\\\)) /oxgc) { $q_string .= $1; }
3793 0           elsif (/\G (\\\() /oxgc) { $q_string .= $1; }
3794 0           elsif (/\G (\() /oxgc) { $q_string .= $1; $nest++; }
  0            
3795             elsif (/\G (\)) /oxgc) {
3796 0 0         if (--$nest == 0) { return $e . e_q($ope,'(',')',$q_string); }
  0            
3797 0           else { $q_string .= $1; }
3798             }
3799 0           elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3800             }
3801 0           die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3802             }
3803              
3804             # elsif (/\G (\{) ((?:\\\}|\\\\|$q_brace)*?) (\}) /oxgc) { return $e . e_q($ope,$1,$3,$2); } # q { }
3805             elsif (/\G (\{) /oxgc) { # q { }
3806 0           my $q_string = '';
3807 0           local $nest = 1;
3808 0           while (not /\G \z/oxgc) {
3809 0 0         if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3810 0           elsif (/\G (\\\}) /oxgc) { $q_string .= $1; }
3811 0           elsif (/\G (\\\{) /oxgc) { $q_string .= $1; }
3812 0           elsif (/\G (\{) /oxgc) { $q_string .= $1; $nest++; }
  0            
3813             elsif (/\G (\}) /oxgc) {
3814 0 0         if (--$nest == 0) { return $e . e_q($ope,'{','}',$q_string); }
  0            
3815 0           else { $q_string .= $1; }
3816             }
3817 0           elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3818             }
3819 0           die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3820             }
3821              
3822             # elsif (/\G (\[) ((?:\\\]|\\\\|$q_bracket)*?) (\]) /oxgc) { return $e . e_q($ope,$1,$3,$2); } # q [ ]
3823             elsif (/\G (\[) /oxgc) { # q [ ]
3824 0           my $q_string = '';
3825 0           local $nest = 1;
3826 0           while (not /\G \z/oxgc) {
3827 0 0         if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3828 0           elsif (/\G (\\\]) /oxgc) { $q_string .= $1; }
3829 0           elsif (/\G (\\\[) /oxgc) { $q_string .= $1; }
3830 0           elsif (/\G (\[) /oxgc) { $q_string .= $1; $nest++; }
  0            
3831             elsif (/\G (\]) /oxgc) {
3832 0 0         if (--$nest == 0) { return $e . e_q($ope,'[',']',$q_string); }
  0            
3833 0           else { $q_string .= $1; }
3834             }
3835 0           elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3836             }
3837 0           die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3838             }
3839              
3840             # elsif (/\G (\<) ((?:\\\>|\\\\|$q_angle)*?) (\>) /oxgc) { return $e . e_q($ope,$1,$3,$2); } # q < >
3841             elsif (/\G (\<) /oxgc) { # q < >
3842 0           my $q_string = '';
3843 0           local $nest = 1;
3844 0           while (not /\G \z/oxgc) {
3845 0 0         if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3846 0           elsif (/\G (\\\>) /oxgc) { $q_string .= $1; }
3847 0           elsif (/\G (\\\<) /oxgc) { $q_string .= $1; }
3848 0           elsif (/\G (\<) /oxgc) { $q_string .= $1; $nest++; }
  0            
3849             elsif (/\G (\>) /oxgc) {
3850 0 0         if (--$nest == 0) { return $e . e_q($ope,'<','>',$q_string); }
  0            
3851 0           else { $q_string .= $1; }
3852             }
3853 0           elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3854             }
3855 0           die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3856             }
3857              
3858             # elsif (/\G (\S) ((?:\\\1|\\\\|$q_char)*?) (\1) /oxgc) { return $e . e_q($ope,$1,$3,$2); } # q * *
3859             elsif (/\G (\S) /oxgc) { # q * *
3860 0           my $delimiter = $1;
3861 0           my $q_string = '';
3862 0           while (not /\G \z/oxgc) {
3863 0 0         if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0          
    0          
    0          
3864 0           elsif (/\G (\\\Q$delimiter\E) /oxgc) { $q_string .= $1; }
3865 0           elsif (/\G (\Q$delimiter\E) /oxgc) { return $e . e_q($ope,$delimiter,$delimiter,$q_string); }
3866 0           elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3867             }
3868 0           die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3869             }
3870             }
3871 0           die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3872             }
3873             }
3874              
3875             # m//
3876             elsif (/\G \b (m) \b /oxgc) {
3877 0           my $ope = $1;
3878 0 0         if (/\G (\#) ((?:$qq_char)*?) (\#) ([cgimosxpadlunbB]*) /oxgc) { # m# #
3879 0           return e_qr($ope,$1,$3,$2,$4);
3880             }
3881             else {
3882 0           my $e = '';
3883 0           while (not /\G \z/oxgc) {
3884 0 0         if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
3885 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cgimosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m ( )
3886 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cgimosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m { }
3887 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cgimosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m [ ]
3888 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cgimosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m < >
3889 0           elsif (/\G (\?) ((?:$qq_char)*?) (\?) ([cgimosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m ? ?
3890 0           elsif (/\G (\') ((?:$qq_char)*?) (\') ([cgimosxpadlunbB]*) /oxgc) { return $e . e_qr_q($ope,$1, $3, $2,$4); } # m ' '
3891 0           elsif (/\G ([*\-:\\^|]) ((?:$qq_char)*?) (\1) ([cgimosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,'{','}',$2,$4); } # m | | --> m { }
3892 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cgimosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m * *
3893             }
3894 0           die __FILE__, ": Search pattern not terminated\n";
3895             }
3896             }
3897              
3898             # s///
3899              
3900             # about [cegimosxpradlunbB]* (/cg modifier)
3901             #
3902             # P.67 Pattern-Matching Operators
3903             # of ISBN 0-596-00241-6 Perl in a Nutshell, Second Edition.
3904              
3905             elsif (/\G \b (s) \b /oxgc) {
3906 0           my $ope = $1;
3907              
3908             # $1 $2 $3 $4 $5 $6
3909 0 0         if (/\G (\#) ((?:$qq_char)*?) (\#) ((?:$qq_char)*?) (\#) ([cegimosxpradlunbB]*) /oxgc) { # s# # #
3910 0           return e_sub($sub_variable,$1,$2,$3,$3,$4,$5,$6);
3911             }
3912             else {
3913 0           my $e = '';
3914 0           while (not /\G \z/oxgc) {
3915 0 0         if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
3916             elsif (/\G (\() ((?:$qq_paren)*?) (\)) /oxgc) {
3917 0           my @s = ($1,$2,$3);
3918 0           while (not /\G \z/oxgc) {
3919 0 0         if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
3920             # $1 $2 $3 $4
3921 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3922 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3923 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3924 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3925 0           elsif (/\G (\') ((?:$qq_char)*?) (\') ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3926 0           elsif (/\G (\$) ((?:$qq_char)*?) (\$) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3927 0           elsif (/\G (\:) ((?:$qq_char)*?) (\:) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3928 0           elsif (/\G (\@) ((?:$qq_char)*?) (\@) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3929 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3930             }
3931 0           die __FILE__, ": Substitution replacement not terminated\n";
3932             }
3933             elsif (/\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) {
3934 0           my @s = ($1,$2,$3);
3935 0           while (not /\G \z/oxgc) {
3936 0 0         if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
3937             # $1 $2 $3 $4
3938 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3939 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3940 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3941 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3942 0           elsif (/\G (\') ((?:$qq_char)*?) (\') ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3943 0           elsif (/\G (\$) ((?:$qq_char)*?) (\$) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3944 0           elsif (/\G (\:) ((?:$qq_char)*?) (\:) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3945 0           elsif (/\G (\@) ((?:$qq_char)*?) (\@) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3946 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3947             }
3948 0           die __FILE__, ": Substitution replacement not terminated\n";
3949             }
3950             elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) {
3951 0           my @s = ($1,$2,$3);
3952 0           while (not /\G \z/oxgc) {
3953 0 0         if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
3954             # $1 $2 $3 $4
3955 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3956 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3957 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3958 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3959 0           elsif (/\G (\') ((?:$qq_char)*?) (\') ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3960 0           elsif (/\G (\$) ((?:$qq_char)*?) (\$) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3961 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3962             }
3963 0           die __FILE__, ": Substitution replacement not terminated\n";
3964             }
3965             elsif (/\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) {
3966 0           my @s = ($1,$2,$3);
3967 0           while (not /\G \z/oxgc) {
3968 0 0         if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
3969             # $1 $2 $3 $4
3970 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3971 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3972 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3973 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3974 0           elsif (/\G (\') ((?:$qq_char)*?) (\') ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3975 0           elsif (/\G (\$) ((?:$qq_char)*?) (\$) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3976 0           elsif (/\G (\:) ((?:$qq_char)*?) (\:) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3977 0           elsif (/\G (\@) ((?:$qq_char)*?) (\@) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3978 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3979             }
3980 0           die __FILE__, ": Substitution replacement not terminated\n";
3981             }
3982             # $1 $2 $3 $4 $5 $6
3983             elsif (/\G (\') ((?:$qq_char)*?) (\') ((?:$qq_char)*?) (\') ([cegimosxpradlunbB]*) /oxgc) {
3984 0           return e_sub($sub_variable,$1,$2,$3,$3,$4,$5,$6);
3985             }
3986             # $1 $2 $3 $4 $5 $6
3987             elsif (/\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ((?:$qq_char)*?) (\1) ([cegimosxpradlunbB]*) /oxgc) {
3988 0           return e_sub($sub_variable,'{',$2,'}','{',$4,'}',$6); # s | | | --> s { } { }
3989             }
3990             # $1 $2 $3 $4 $5 $6
3991             elsif (/\G (\$) ((?:$qq_char)*?) (\1) ((?:$qq_char)*?) (\1) ([cegimosxpradlunbB]*) /oxgc) {
3992 0           return e_sub($sub_variable,$1,$2,$3,$3,$4,$5,$6);
3993             }
3994             # $1 $2 $3 $4 $5 $6
3995             elsif (/\G (\S) ((?:$qq_char)*?) (\1) ((?:$qq_char)*?) (\1) ([cegimosxpradlunbB]*) /oxgc) {
3996 0           return e_sub($sub_variable,$1,$2,$3,$3,$4,$5,$6);
3997             }
3998             }
3999 0           die __FILE__, ": Substitution pattern not terminated\n";
4000             }
4001             }
4002              
4003             # require ignore module
4004 0           elsif (/\G \b require ((?>\s+) (?:$ignore_modules) .*? ;) ([ \t]* [#\n]) /oxmsgc) { return "# require$1$2"; }
4005 0           elsif (/\G \b require ((?>\s+) (?:$ignore_modules) .*? ;) ([ \t]* [^#]) /oxmsgc) { return "# require$1\n$2"; }
4006 0           elsif (/\G \b require ((?>\s+) (?:$ignore_modules)) \b /oxmsgc) { return "# require$1"; }
4007              
4008             # use strict; --> use strict; no strict qw(refs);
4009 0           elsif (/\G \b use ((?>\s+) strict .*? ;) ([ \t]* [#\n]) /oxmsgc) { return "use$1 no strict qw(refs);$2"; }
4010 0           elsif (/\G \b use ((?>\s+) strict .*? ;) ([ \t]* [^#]) /oxmsgc) { return "use$1 no strict qw(refs);\n$2"; }
4011 0           elsif (/\G \b use ((?>\s+) strict) \b /oxmsgc) { return "use$1; no strict qw(refs)"; }
4012              
4013             # use 5.12.0; --> use 5.12.0; no strict qw(refs);
4014             elsif (/\G \b use (?>\s+) ((?>([1-9][0-9_]*)(?:\.([0-9_]+))*)) (?>\s*) ; /oxmsgc) {
4015 0 0 0       if (($2 >= 6) or (($2 == 5) and ($3 ge '012'))) {
      0        
4016 0           return "use $1; no strict qw(refs);";
4017             }
4018             else {
4019 0           return "use $1;";
4020             }
4021             }
4022             elsif (/\G \b use (?>\s+) ((?>v([0-9][0-9_]*)(?:\.([0-9_]+))*)) (?>\s*) ; /oxmsgc) {
4023 0 0 0       if (($2 >= 6) or (($2 == 5) and ($3 >= 12))) {
      0        
4024 0           return "use $1; no strict qw(refs);";
4025             }
4026             else {
4027 0           return "use $1;";
4028             }
4029             }
4030              
4031             # ignore use module
4032 0           elsif (/\G \b use ((?>\s+) (?:$ignore_modules) .*? ;) ([ \t]* [#\n]) /oxmsgc) { return "# use$1$2"; }
4033 0           elsif (/\G \b use ((?>\s+) (?:$ignore_modules) .*? ;) ([ \t]* [^#]) /oxmsgc) { return "# use$1\n$2"; }
4034 0           elsif (/\G \b use ((?>\s+) (?:$ignore_modules)) \b /oxmsgc) { return "# use$1"; }
4035              
4036             # ignore no module
4037 0           elsif (/\G \b no ((?>\s+) (?:$ignore_modules) .*? ;) ([ \t]* [#\n]) /oxmsgc) { return "# no$1$2"; }
4038 0           elsif (/\G \b no ((?>\s+) (?:$ignore_modules) .*? ;) ([ \t]* [^#]) /oxmsgc) { return "# no$1\n$2"; }
4039 0           elsif (/\G \b no ((?>\s+) (?:$ignore_modules)) \b /oxmsgc) { return "# no$1"; }
4040              
4041             # use else
4042 0           elsif (/\G \b use \b /oxmsgc) { return "use"; }
4043              
4044             # use else
4045 0           elsif (/\G \b no \b /oxmsgc) { return "no"; }
4046              
4047             # ''
4048             elsif (/\G (?
4049 0           my $q_string = '';
4050 0           while (not /\G \z/oxgc) {
4051 0 0         if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0          
    0          
    0          
4052 0           elsif (/\G (\\\') /oxgc) { $q_string .= $1; }
4053 0           elsif (/\G \' /oxgc) { return e_q('', "'","'",$q_string); }
4054 0           elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
4055             }
4056 0           die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4057             }
4058              
4059             # ""
4060             elsif (/\G (\") /oxgc) {
4061 0           my $qq_string = '';
4062 0           while (not /\G \z/oxgc) {
4063 0 0         if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0          
    0          
    0          
4064 0           elsif (/\G (\\\") /oxgc) { $qq_string .= $1; }
4065 0           elsif (/\G \" /oxgc) { return e_qq('', '"','"',$qq_string); }
4066 0           elsif (/\G ($q_char) /oxgc) { $qq_string .= $1; }
4067             }
4068 0           die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4069             }
4070              
4071             # ``
4072             elsif (/\G (\`) /oxgc) {
4073 0           my $qx_string = '';
4074 0           while (not /\G \z/oxgc) {
4075 0 0         if (/\G (\\\\) /oxgc) { $qx_string .= $1; }
  0 0          
    0          
    0          
4076 0           elsif (/\G (\\\`) /oxgc) { $qx_string .= $1; }
4077 0           elsif (/\G \` /oxgc) { return e_qq('', '`','`',$qx_string); }
4078 0           elsif (/\G ($q_char) /oxgc) { $qx_string .= $1; }
4079             }
4080 0           die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4081             }
4082              
4083             # // --- not divide operator (num / num), not defined-or
4084             elsif (($slash eq 'm//') and /\G (\/) /oxgc) {
4085 0           my $regexp = '';
4086 0           while (not /\G \z/oxgc) {
4087 0 0         if (/\G (\\\\) /oxgc) { $regexp .= $1; }
  0 0          
    0          
    0          
4088 0           elsif (/\G (\\\/) /oxgc) { $regexp .= $1; }
4089 0           elsif (/\G \/ ([cgimosxpadlunbB]*) /oxgc) { return e_qr('', '/','/',$regexp,$1); }
4090 0           elsif (/\G ($q_char) /oxgc) { $regexp .= $1; }
4091             }
4092 0           die __FILE__, ": Search pattern not terminated\n";
4093             }
4094              
4095             # ?? --- not conditional operator (condition ? then : else)
4096             elsif (($slash eq 'm//') and /\G (\?) /oxgc) {
4097 0           my $regexp = '';
4098 0           while (not /\G \z/oxgc) {
4099 0 0         if (/\G (\\\\) /oxgc) { $regexp .= $1; }
  0 0          
    0          
    0          
4100 0           elsif (/\G (\\\?) /oxgc) { $regexp .= $1; }
4101 0           elsif (/\G \? ([cgimosxpadlunbB]*) /oxgc) { return e_qr('m','?','?',$regexp,$1); }
4102 0           elsif (/\G ($q_char) /oxgc) { $regexp .= $1; }
4103             }
4104 0           die __FILE__, ": Search pattern not terminated\n";
4105             }
4106              
4107             # <<>> (a safer ARGV)
4108 0           elsif (/\G ( <<>> ) /oxgc) { $slash = 'm//'; return $1; }
  0            
4109              
4110             # << (bit shift) --- not here document
4111 0           elsif (/\G ( << (?>\s*) ) (?= [0-9\$\@\&] ) /oxgc) { $slash = 'm//'; return $1; }
  0            
4112              
4113             # <<'HEREDOC'
4114             elsif (/\G ( << '([a-zA-Z_0-9]*)' ) /oxgc) {
4115 0           $slash = 'm//';
4116 0           my $here_quote = $1;
4117 0           my $delimiter = $2;
4118              
4119             # get here document
4120 0 0         if ($here_script eq '') {
4121 0           $here_script = CORE::substr $_, pos $_;
4122 0           $here_script =~ s/.*?\n//oxm;
4123             }
4124 0 0         if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4125 0           push @heredoc, $1 . qq{\n$delimiter\n};
4126 0           push @heredoc_delimiter, $delimiter;
4127             }
4128             else {
4129 0           die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4130             }
4131 0           return $here_quote;
4132             }
4133              
4134             # <<\HEREDOC
4135              
4136             # P.66 2.6.6. "Here" Documents
4137             # in Chapter 2: Bits and Pieces
4138             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
4139              
4140             # P.73 "Here" Documents
4141             # in Chapter 2: Bits and Pieces
4142             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
4143              
4144             elsif (/\G ( << \\([a-zA-Z_0-9]+) ) /oxgc) {
4145 0           $slash = 'm//';
4146 0           my $here_quote = $1;
4147 0           my $delimiter = $2;
4148              
4149             # get here document
4150 0 0         if ($here_script eq '') {
4151 0           $here_script = CORE::substr $_, pos $_;
4152 0           $here_script =~ s/.*?\n//oxm;
4153             }
4154 0 0         if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4155 0           push @heredoc, $1 . qq{\n$delimiter\n};
4156 0           push @heredoc_delimiter, $delimiter;
4157             }
4158             else {
4159 0           die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4160             }
4161 0           return $here_quote;
4162             }
4163              
4164             # <<"HEREDOC"
4165             elsif (/\G ( << "([a-zA-Z_0-9]*)" ) /oxgc) {
4166 0           $slash = 'm//';
4167 0           my $here_quote = $1;
4168 0           my $delimiter = $2;
4169              
4170             # get here document
4171 0 0         if ($here_script eq '') {
4172 0           $here_script = CORE::substr $_, pos $_;
4173 0           $here_script =~ s/.*?\n//oxm;
4174             }
4175 0 0         if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4176 0           push @heredoc, e_heredoc($1) . qq{\n$delimiter\n};
4177 0           push @heredoc_delimiter, $delimiter;
4178             }
4179             else {
4180 0           die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4181             }
4182 0           return $here_quote;
4183             }
4184              
4185             # <
4186             elsif (/\G ( << ([a-zA-Z_0-9]+) ) /oxgc) {
4187 0           $slash = 'm//';
4188 0           my $here_quote = $1;
4189 0           my $delimiter = $2;
4190              
4191             # get here document
4192 0 0         if ($here_script eq '') {
4193 0           $here_script = CORE::substr $_, pos $_;
4194 0           $here_script =~ s/.*?\n//oxm;
4195             }
4196 0 0         if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4197 0           push @heredoc, e_heredoc($1) . qq{\n$delimiter\n};
4198 0           push @heredoc_delimiter, $delimiter;
4199             }
4200             else {
4201 0           die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4202             }
4203 0           return $here_quote;
4204             }
4205              
4206             # <<`HEREDOC`
4207             elsif (/\G ( << `([a-zA-Z_0-9]*)` ) /oxgc) {
4208 0           $slash = 'm//';
4209 0           my $here_quote = $1;
4210 0           my $delimiter = $2;
4211              
4212             # get here document
4213 0 0         if ($here_script eq '') {
4214 0           $here_script = CORE::substr $_, pos $_;
4215 0           $here_script =~ s/.*?\n//oxm;
4216             }
4217 0 0         if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4218 0           push @heredoc, e_heredoc($1) . qq{\n$delimiter\n};
4219 0           push @heredoc_delimiter, $delimiter;
4220             }
4221             else {
4222 0           die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4223             }
4224 0           return $here_quote;
4225             }
4226              
4227             # <<= <=> <= < operator
4228             elsif (/\G ( <<= | <=> | <= | < ) (?= (?>\s*) [A-Za-z_0-9'"`\$\@\&\*\(\+\-] )/oxgc) {
4229 0           return $1;
4230             }
4231              
4232             #
4233             elsif (/\G (<[\$]?[A-Za-z_][A-Za-z_0-9]*>) /oxgc) {
4234 0           return $1;
4235             }
4236              
4237             # --- glob
4238              
4239             # avoid "Error: Runtime exception" of perl version 5.005_03
4240              
4241             elsif (/\G < ((?:[^>\0\a\e\f\n\r\t])+?) > /oxgc) {
4242 0           return 'Ekoi8r::glob("' . $1 . '")';
4243             }
4244              
4245             # __DATA__
4246 0           elsif (/\G ^ ( __DATA__ \n .*) \z /oxmsgc) { return $1; }
4247              
4248             # __END__
4249 0           elsif (/\G ^ ( __END__ \n .*) \z /oxmsgc) { return $1; }
4250              
4251             # \cD Control-D
4252              
4253             # P.68 2.6.8. Other Literal Tokens
4254             # in Chapter 2: Bits and Pieces
4255             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
4256              
4257             # P.76 Other Literal Tokens
4258             # in Chapter 2: Bits and Pieces
4259             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
4260              
4261 0           elsif (/\G ( \cD .*) \z /oxmsgc) { return $1; }
4262              
4263             # \cZ Control-Z
4264 0           elsif (/\G ( \cZ .*) \z /oxmsgc) { return $1; }
4265              
4266             # any operator before div
4267             elsif (/\G (
4268             -- | \+\+ |
4269             [\)\}\]]
4270              
4271 0           ) /oxgc) { $slash = 'div'; return $1; }
  0            
4272              
4273             # yada-yada or triple-dot operator
4274             elsif (/\G (
4275             \.\.\.
4276              
4277 0           ) /oxgc) { $slash = 'm//'; return q{die('Unimplemented')}; }
  0            
4278              
4279             # any operator before m//
4280              
4281             # //, //= (defined-or)
4282              
4283             # P.164 Logical Operators
4284             # in Chapter 10: More Control Structures
4285             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
4286              
4287             # P.119 C-Style Logical (Short-Circuit) Operators
4288             # in Chapter 3: Unary and Binary Operators
4289             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
4290              
4291             # (and so on)
4292              
4293             # ~~
4294              
4295             # P.221 The Smart Match Operator
4296             # in Chapter 15: Smart Matching and given-when
4297             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
4298              
4299             # P.112 Smartmatch Operator
4300             # in Chapter 3: Unary and Binary Operators
4301             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
4302              
4303             # (and so on)
4304              
4305             elsif (/\G ((?>
4306              
4307             !~~ | !~ | != | ! |
4308             %= | % |
4309             &&= | && | &= | &\.= | &\. | & |
4310             -= | -> | - |
4311             :(?>\s*)= |
4312             : |
4313             <<>> |
4314             <<= | <=> | <= | < |
4315             == | => | =~ | = |
4316             >>= | >> | >= | > |
4317             \*\*= | \*\* | \*= | \* |
4318             \+= | \+ |
4319             \.\. | \.= | \. |
4320             \/\/= | \/\/ |
4321             \/= | \/ |
4322             \? |
4323             \\ |
4324             \^= | \^\.= | \^\. | \^ |
4325             \b x= |
4326             \|\|= | \|\| | \|= | \|\.= | \|\. | \| |
4327             ~~ | ~\. | ~ |
4328             \b(?: and | cmp | eq | ge | gt | le | lt | ne | not | or | xor | x )\b |
4329             \b(?: print )\b |
4330              
4331             [,;\(\{\[]
4332              
4333 0           )) /oxgc) { $slash = 'm//'; return $1; }
  0            
4334              
4335             # other any character
4336 0           elsif (/\G ($q_char) /oxgc) { $slash = 'div'; return $1; }
  0            
4337              
4338             # system error
4339             else {
4340 0           die __FILE__, ": Oops, this shouldn't happen!\n";
4341             }
4342             }
4343              
4344             # escape KOI8-R string
4345             sub e_string {
4346 0     0 0   my($string) = @_;
4347 0           my $e_string = '';
4348              
4349 0           local $slash = 'm//';
4350              
4351             # P.1024 Appendix W.10 Multibyte Processing
4352             # of ISBN 1-56592-224-7 CJKV Information Processing
4353             # (and so on)
4354              
4355 0           my @char = $string =~ / \G (?>[^\\]|\\$q_char|$q_char) /oxmsg;
4356              
4357             # without { ... }
4358 0 0 0       if (not (grep(/\A \{ \z/xms, @char) and grep(/\A \} \z/xms, @char))) {
4359 0 0         if ($string !~ /<
4360 0           return $string;
4361             }
4362             }
4363              
4364             E_STRING_LOOP:
4365 0           while ($string !~ /\G \z/oxgc) {
4366 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          
    0          
    0          
    0          
    0          
    0          
4367             }
4368              
4369             # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> @{[Ekoi8r::PREMATCH()]}
4370 0           elsif ($string =~ /\G ( \$` | \$\{`\} | \$ (?>\s*) PREMATCH \b | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} ) /oxmsgc) {
4371 0           $e_string .= q{Ekoi8r::PREMATCH()};
4372 0           $slash = 'div';
4373             }
4374              
4375             # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> @{[Ekoi8r::MATCH()]}
4376             elsif ($string =~ /\G ( \$& | \$\{&\} | \$ (?>\s*) MATCH \b | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} ) /oxmsgc) {
4377 0           $e_string .= q{Ekoi8r::MATCH()};
4378 0           $slash = 'div';
4379             }
4380              
4381             # $', ${'} --> $', ${'}
4382             elsif ($string =~ /\G ( \$' | \$\{'\} ) /oxmsgc) {
4383 0           $e_string .= $1;
4384 0           $slash = 'div';
4385             }
4386              
4387             # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> @{[Ekoi8r::POSTMATCH()]}
4388             elsif ($string =~ /\G ( \$ (?>\s*) POSTMATCH \b | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} ) /oxmsgc) {
4389 0           $e_string .= q{Ekoi8r::POSTMATCH()};
4390 0           $slash = 'div';
4391             }
4392              
4393             # bareword
4394             elsif ($string =~ /\G ( \{ (?>\s*) (?: tr | index | rindex | reverse ) (?>\s*) \} ) /oxmsgc) {
4395 0           $e_string .= $1;
4396 0           $slash = 'div';
4397             }
4398              
4399             # $0 --> $0
4400             elsif ($string =~ /\G ( \$ 0 ) /oxmsgc) {
4401 0           $e_string .= $1;
4402 0           $slash = 'div';
4403             }
4404             elsif ($string =~ /\G ( \$ \{ (?>\s*) 0 (?>\s*) \} ) /oxmsgc) {
4405 0           $e_string .= $1;
4406 0           $slash = 'div';
4407             }
4408              
4409             # $$ --> $$
4410             elsif ($string =~ /\G ( \$ \$ ) (?![\w\{]) /oxmsgc) {
4411 0           $e_string .= $1;
4412 0           $slash = 'div';
4413             }
4414              
4415             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
4416             # $1, $2, $3 --> $1, $2, $3 otherwise
4417             elsif ($string =~ /\G \$ ((?>[1-9][0-9]*)) /oxmsgc) {
4418 0           $e_string .= e_capture($1);
4419 0           $slash = 'div';
4420             }
4421             elsif ($string =~ /\G \$ \{ (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} /oxmsgc) {
4422 0           $e_string .= e_capture($1);
4423 0           $slash = 'div';
4424             }
4425              
4426             # $$foo[ ... ] --> $ $foo->[ ... ]
4427             elsif ($string =~ /\G \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \[ .+? \] ) /oxmsgc) {
4428 0           $e_string .= e_capture($1.'->'.$2);
4429 0           $slash = 'div';
4430             }
4431              
4432             # $$foo{ ... } --> $ $foo->{ ... }
4433             elsif ($string =~ /\G \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \{ .+? \} ) /oxmsgc) {
4434 0           $e_string .= e_capture($1.'->'.$2);
4435 0           $slash = 'div';
4436             }
4437              
4438             # $$foo
4439             elsif ($string =~ /\G \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) /oxmsgc) {
4440 0           $e_string .= e_capture($1);
4441 0           $slash = 'div';
4442             }
4443              
4444             # ${ foo }
4445             elsif ($string =~ /\G \$ (?>\s*) \{ ((?> \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* )) \} /oxmsgc) {
4446 0           $e_string .= '${' . $1 . '}';
4447 0           $slash = 'div';
4448             }
4449              
4450             # ${ ... }
4451             elsif ($string =~ /\G \$ (?>\s*) \{ (?>\s*) ( $qq_brace ) (?>\s*) \} /oxmsgc) {
4452 0           $e_string .= e_capture($1);
4453 0           $slash = 'div';
4454             }
4455              
4456             # variable or function
4457             # $ @ % & * $ #
4458             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) {
4459 0           $e_string .= $1;
4460 0           $slash = 'div';
4461             }
4462             # $ $ $ $ $ $ $ $ $ $ $ $ $ $
4463             # $ @ # \ ' " / ? ( ) [ ] < >
4464             elsif ($string =~ /\G ( \$[\$\@\#\\\'\"\/\?\(\)\[\]\<\>] ) /oxmsgc) {
4465 0           $e_string .= $1;
4466 0           $slash = 'div';
4467             }
4468              
4469             # subroutines of package Ekoi8r
4470 0           elsif ($string =~ /\G \b (CORE:: | ->(>?\s*) (?: atan2 | [a-z]{2,})) \b /oxgc) { $e_string .= $1; $slash = 'm//'; }
  0            
4471 0           elsif ($string =~ /\G \b Char::eval (?= (?>\s*) \{ ) /oxgc) { $e_string .= 'eval'; $slash = 'm//'; }
  0            
4472 0           elsif ($string =~ /\G \b KOI8R::eval (?= (?>\s*) \{ ) /oxgc) { $e_string .= 'eval'; $slash = 'm//'; }
  0            
4473 0           elsif ($string =~ /\G \b Char::eval \b /oxgc) { $e_string .= 'eval Char::escape'; $slash = 'm//'; }
  0            
4474 0           elsif ($string =~ /\G \b KOI8R::eval \b /oxgc) { $e_string .= 'eval KOI8R::escape'; $slash = 'm//'; }
  0            
4475 0           elsif ($string =~ /\G \b bytes::substr \b /oxgc) { $e_string .= 'substr'; $slash = 'm//'; }
  0            
4476 0           elsif ($string =~ /\G \b chop \b /oxgc) { $e_string .= 'Ekoi8r::chop'; $slash = 'm//'; }
  0            
4477 0           elsif ($string =~ /\G \b bytes::index \b /oxgc) { $e_string .= 'index'; $slash = 'm//'; }
  0            
4478 0           elsif ($string =~ /\G \b Char::index \b /oxgc) { $e_string .= 'Char::index'; $slash = 'm//'; }
  0            
4479 0           elsif ($string =~ /\G \b KOI8R::index \b /oxgc) { $e_string .= 'KOI8R::index'; $slash = 'm//'; }
  0            
4480 0           elsif ($string =~ /\G \b index \b /oxgc) { $e_string .= 'Ekoi8r::index'; $slash = 'm//'; }
  0            
4481 0           elsif ($string =~ /\G \b bytes::rindex \b /oxgc) { $e_string .= 'rindex'; $slash = 'm//'; }
  0            
4482 0           elsif ($string =~ /\G \b Char::rindex \b /oxgc) { $e_string .= 'Char::rindex'; $slash = 'm//'; }
  0            
4483 0           elsif ($string =~ /\G \b KOI8R::rindex \b /oxgc) { $e_string .= 'KOI8R::rindex'; $slash = 'm//'; }
  0            
4484 0           elsif ($string =~ /\G \b rindex \b /oxgc) { $e_string .= 'Ekoi8r::rindex'; $slash = 'm//'; }
  0            
4485 0           elsif ($string =~ /\G \b lc (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Ekoi8r::lc'; $slash = 'm//'; }
  0            
4486 0           elsif ($string =~ /\G \b lcfirst (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Ekoi8r::lcfirst'; $slash = 'm//'; }
  0            
4487 0           elsif ($string =~ /\G \b uc (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Ekoi8r::uc'; $slash = 'm//'; }
  0            
4488 0           elsif ($string =~ /\G \b ucfirst (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Ekoi8r::ucfirst'; $slash = 'm//'; }
  0            
4489 0           elsif ($string =~ /\G \b fc (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Ekoi8r::fc'; $slash = 'm//'; }
  0            
4490              
4491             # "-s '' ..." means file test "-s 'filename' ..." (not means "- s/// ...")
4492 0           elsif ($string =~ /\G -s (?>\s*) (\") ((?:$qq_char)+?) (\") /oxgc) { $e_string .= '-s ' . e_qq('', $1,$3,$2); $slash = 'm//'; }
  0            
4493 0           elsif ($string =~ /\G -s (?>\s+) qq (?>\s*) (\#) ((?:$qq_char)+?) (\#) /oxgc) { $e_string .= '-s ' . e_qq('qq',$1,$3,$2); $slash = 'm//'; }
  0            
4494 0           elsif ($string =~ /\G -s (?>\s+) qq (?>\s*) (\() ((?:$qq_paren)+?) (\)) /oxgc) { $e_string .= '-s ' . e_qq('qq',$1,$3,$2); $slash = 'm//'; }
  0            
4495 0           elsif ($string =~ /\G -s (?>\s+) qq (?>\s*) (\{) ((?:$qq_brace)+?) (\}) /oxgc) { $e_string .= '-s ' . e_qq('qq',$1,$3,$2); $slash = 'm//'; }
  0            
4496 0           elsif ($string =~ /\G -s (?>\s+) qq (?>\s*) (\[) ((?:$qq_bracket)+?) (\]) /oxgc) { $e_string .= '-s ' . e_qq('qq',$1,$3,$2); $slash = 'm//'; }
  0            
4497 0           elsif ($string =~ /\G -s (?>\s+) qq (?>\s*) (\<) ((?:$qq_angle)+?) (\>) /oxgc) { $e_string .= '-s ' . e_qq('qq',$1,$3,$2); $slash = 'm//'; }
  0            
4498 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            
4499              
4500 0           elsif ($string =~ /\G -s (?>\s*) (\') ((?:\\\'|\\\\|$q_char)+?) (\') /oxgc) { $e_string .= '-s ' . e_q ('', $1,$3,$2); $slash = 'm//'; }
  0            
4501 0           elsif ($string =~ /\G -s (?>\s+) q (?>\s*) (\#) ((?:\\\#|\\\\|$q_char)+?) (\#) /oxgc) { $e_string .= '-s ' . e_q ('q', $1,$3,$2); $slash = 'm//'; }
  0            
4502 0           elsif ($string =~ /\G -s (?>\s+) q (?>\s*) (\() ((?:\\\)|\\\\|$q_paren)+?) (\)) /oxgc) { $e_string .= '-s ' . e_q ('q', $1,$3,$2); $slash = 'm//'; }
  0            
4503 0           elsif ($string =~ /\G -s (?>\s+) q (?>\s*) (\{) ((?:\\\}|\\\\|$q_brace)+?) (\}) /oxgc) { $e_string .= '-s ' . e_q ('q', $1,$3,$2); $slash = 'm//'; }
  0            
4504 0           elsif ($string =~ /\G -s (?>\s+) q (?>\s*) (\[) ((?:\\\]|\\\\|$q_bracket)+?) (\]) /oxgc) { $e_string .= '-s ' . e_q ('q', $1,$3,$2); $slash = 'm//'; }
  0            
4505 0           elsif ($string =~ /\G -s (?>\s+) q (?>\s*) (\<) ((?:\\\>|\\\\|$q_angle)+?) (\>) /oxgc) { $e_string .= '-s ' . e_q ('q', $1,$3,$2); $slash = 'm//'; }
  0            
4506 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            
4507              
4508             elsif ($string =~ /\G -s (?>\s*) (\$ (?> \w+ (?: ::\w+)*) (?: (?: ->)? (?: [\$\@\%\&\*]\* | \$\#\* | \( (?:$qq_paren)*? \) | [\@\%\*]? \{ (?:$qq_brace)+? \} | [\@\%]? \[ (?:$qq_bracket)+? \] ))*) /oxgc)
4509 0           { $e_string .= "-s $1"; $slash = 'm//'; }
  0            
4510 0           elsif ($string =~ /\G -s (?>\s*) \( ((?:$qq_paren)*?) \) /oxgc) { $e_string .= "-s ($1)"; $slash = 'm//'; }
  0            
4511 0           elsif ($string =~ /\G -s (?= (?>\s+) [a-z]+) /oxgc) { $e_string .= '-s'; $slash = 'm//'; }
  0            
4512 0           elsif ($string =~ /\G -s (?>\s+) ((?>\w+)) /oxgc) { $e_string .= "-s $1"; $slash = 'm//'; }
  0            
4513              
4514 0           elsif ($string =~ /\G \b bytes::length (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'length'; $slash = 'm//'; }
  0            
4515 0           elsif ($string =~ /\G \b bytes::chr (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'chr'; $slash = 'm//'; }
  0            
4516 0           elsif ($string =~ /\G \b chr (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Ekoi8r::chr'; $slash = 'm//'; }
  0            
4517 0           elsif ($string =~ /\G \b bytes::ord (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'ord'; $slash = 'div'; }
  0            
4518 0           elsif ($string =~ /\G \b ord (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $e_string .= $function_ord; $slash = 'div'; }
  0            
4519 0           elsif ($string =~ /\G \b glob (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Ekoi8r::glob'; $slash = 'm//'; }
  0            
4520 0           elsif ($string =~ /\G \b lc \b /oxgc) { $e_string .= 'Ekoi8r::lc_'; $slash = 'm//'; }
  0            
4521 0           elsif ($string =~ /\G \b lcfirst \b /oxgc) { $e_string .= 'Ekoi8r::lcfirst_'; $slash = 'm//'; }
  0            
4522 0           elsif ($string =~ /\G \b uc \b /oxgc) { $e_string .= 'Ekoi8r::uc_'; $slash = 'm//'; }
  0            
4523 0           elsif ($string =~ /\G \b ucfirst \b /oxgc) { $e_string .= 'Ekoi8r::ucfirst_'; $slash = 'm//'; }
  0            
4524 0           elsif ($string =~ /\G \b fc \b /oxgc) { $e_string .= 'Ekoi8r::fc_'; $slash = 'm//'; }
  0            
4525 0           elsif ($string =~ /\G -s \b /oxgc) { $e_string .= '-s '; $slash = 'm//'; }
  0            
4526              
4527 0           elsif ($string =~ /\G \b bytes::length \b /oxgc) { $e_string .= 'length'; $slash = 'm//'; }
  0            
4528 0           elsif ($string =~ /\G \b bytes::chr \b /oxgc) { $e_string .= 'chr'; $slash = 'm//'; }
  0            
4529 0           elsif ($string =~ /\G \b chr \b /oxgc) { $e_string .= 'Ekoi8r::chr_'; $slash = 'm//'; }
  0            
4530 0           elsif ($string =~ /\G \b bytes::ord \b /oxgc) { $e_string .= 'ord'; $slash = 'div'; }
  0            
4531 0           elsif ($string =~ /\G \b ord \b /oxgc) { $e_string .= $function_ord_; $slash = 'div'; }
  0            
4532 0           elsif ($string =~ /\G \b glob \b /oxgc) { $e_string .= 'Ekoi8r::glob_'; $slash = 'm//'; }
  0            
4533 0           elsif ($string =~ /\G \b reverse \b /oxgc) { $e_string .= $function_reverse; $slash = 'm//'; }
  0            
4534 0           elsif ($string =~ /\G \b getc \b /oxgc) { $e_string .= $function_getc; $slash = 'm//'; }
  0            
4535             # split
4536             elsif ($string =~ /\G \b (split) \b (?! (?>\s*) => ) /oxgc) {
4537 0           $slash = 'm//';
4538              
4539 0           my $e = '';
4540 0           while ($string =~ /\G ( (?>\s+) | \( | \#.* ) /oxgc) {
4541 0           $e .= $1;
4542             }
4543              
4544             # end of split
4545 0 0         if ($string =~ /\G (?= [,;\)\}\]] ) /oxgc) { return 'Ekoi8r::split' . $e; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
4546              
4547             # split scalar value
4548 0           elsif ($string =~ /\G ( [\$\@\&\*] $qq_scalar ) /oxgc) { $e_string .= 'Ekoi8r::split' . $e . e_string($1); next E_STRING_LOOP; }
  0            
4549              
4550             # split literal space
4551 0           elsif ($string =~ /\G \b qq (\#) [ ] (\#) /oxgc) { $e_string .= 'Ekoi8r::split' . $e . qq {qq$1 $2}; next E_STRING_LOOP; }
  0            
4552 0           elsif ($string =~ /\G \b qq ((?>\s*)) (\() [ ] (\)) /oxgc) { $e_string .= 'Ekoi8r::split' . $e . qq{$1qq$2 $3}; next E_STRING_LOOP; }
  0            
4553 0           elsif ($string =~ /\G \b qq ((?>\s*)) (\{) [ ] (\}) /oxgc) { $e_string .= 'Ekoi8r::split' . $e . qq{$1qq$2 $3}; next E_STRING_LOOP; }
  0            
4554 0           elsif ($string =~ /\G \b qq ((?>\s*)) (\[) [ ] (\]) /oxgc) { $e_string .= 'Ekoi8r::split' . $e . qq{$1qq$2 $3}; next E_STRING_LOOP; }
  0            
4555 0           elsif ($string =~ /\G \b qq ((?>\s*)) (\<) [ ] (\>) /oxgc) { $e_string .= 'Ekoi8r::split' . $e . qq{$1qq$2 $3}; next E_STRING_LOOP; }
  0            
4556 0           elsif ($string =~ /\G \b qq ((?>\s*)) (\S) [ ] (\2) /oxgc) { $e_string .= 'Ekoi8r::split' . $e . qq{$1qq$2 $3}; next E_STRING_LOOP; }
  0            
4557 0           elsif ($string =~ /\G \b q (\#) [ ] (\#) /oxgc) { $e_string .= 'Ekoi8r::split' . $e . qq {q$1 $2}; next E_STRING_LOOP; }
  0            
4558 0           elsif ($string =~ /\G \b q ((?>\s*)) (\() [ ] (\)) /oxgc) { $e_string .= 'Ekoi8r::split' . $e . qq {$1q$2 $3}; next E_STRING_LOOP; }
  0            
4559 0           elsif ($string =~ /\G \b q ((?>\s*)) (\{) [ ] (\}) /oxgc) { $e_string .= 'Ekoi8r::split' . $e . qq {$1q$2 $3}; next E_STRING_LOOP; }
  0            
4560 0           elsif ($string =~ /\G \b q ((?>\s*)) (\[) [ ] (\]) /oxgc) { $e_string .= 'Ekoi8r::split' . $e . qq {$1q$2 $3}; next E_STRING_LOOP; }
  0            
4561 0           elsif ($string =~ /\G \b q ((?>\s*)) (\<) [ ] (\>) /oxgc) { $e_string .= 'Ekoi8r::split' . $e . qq {$1q$2 $3}; next E_STRING_LOOP; }
  0            
4562 0           elsif ($string =~ /\G \b q ((?>\s*)) (\S) [ ] (\2) /oxgc) { $e_string .= 'Ekoi8r::split' . $e . qq {$1q$2 $3}; next E_STRING_LOOP; }
  0            
4563 0           elsif ($string =~ /\G ' [ ] ' /oxgc) { $e_string .= 'Ekoi8r::split' . $e . qq {' '}; next E_STRING_LOOP; }
  0            
4564 0           elsif ($string =~ /\G " [ ] " /oxgc) { $e_string .= 'Ekoi8r::split' . $e . qq {" "}; next E_STRING_LOOP; }
  0            
4565              
4566             # split qq//
4567             elsif ($string =~ /\G \b (qq) \b /oxgc) {
4568 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            
4569             else {
4570 0           while ($string !~ /\G \z/oxgc) {
4571 0 0         if ($string =~ /\G ((?>\s+)|\#.*) /oxgc) { $e_string .= $e . $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
4572 0           elsif ($string =~ /\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { $e_string .= e_split($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # qq ( ) --> qr ( )
  0            
4573 0           elsif ($string =~ /\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { $e_string .= e_split($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # qq { } --> qr { }
  0            
4574 0           elsif ($string =~ /\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { $e_string .= e_split($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # qq [ ] --> qr [ ]
  0            
4575 0           elsif ($string =~ /\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { $e_string .= e_split($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # qq < > --> qr < >
  0            
4576 0           elsif ($string =~ /\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) /oxgc) { $e_string .= e_split($e.'qr','{','}',$2,''); next E_STRING_LOOP; } # qq | | --> qr { }
  0            
4577 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            
4578             }
4579 0           die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4580             }
4581             }
4582              
4583             # split qr//
4584             elsif ($string =~ /\G \b (qr) \b /oxgc) {
4585 0 0         if ($string =~ /\G (\#) ((?:$qq_char)*?) (\#) ([imosxpadlunbB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1,$3,$2,$4); next E_STRING_LOOP; } # qr# #
  0            
  0            
4586             else {
4587 0           while ($string !~ /\G \z/oxgc) {
4588 0 0         if ($string =~ /\G ((?>\s+)|\#.*) /oxgc) { $e_string .= $e . $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
4589 0           elsif ($string =~ /\G (\() ((?:$qq_paren)*?) (\)) ([imosxpadlunbB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # qr ( )
  0            
4590 0           elsif ($string =~ /\G (\{) ((?:$qq_brace)*?) (\}) ([imosxpadlunbB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # qr { }
  0            
4591 0           elsif ($string =~ /\G (\[) ((?:$qq_bracket)*?) (\]) ([imosxpadlunbB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # qr [ ]
  0            
4592 0           elsif ($string =~ /\G (\<) ((?:$qq_angle)*?) (\>) ([imosxpadlunbB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # qr < >
  0            
4593 0           elsif ($string =~ /\G (\') ((?:$qq_char)*?) (\') ([imosxpadlunbB]*) /oxgc) { $e_string .= e_split_q($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # qr ' '
  0            
4594 0           elsif ($string =~ /\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ([imosxpadlunbB]*) /oxgc) { $e_string .= e_split ($e.'qr','{','}',$2,$4); next E_STRING_LOOP; } # qr | | --> qr { }
  0            
4595 0           elsif ($string =~ /\G (\S) ((?:$qq_char)*?) (\1) ([imosxpadlunbB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # qr * *
  0            
4596             }
4597 0           die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4598             }
4599             }
4600              
4601             # split q//
4602             elsif ($string =~ /\G \b (q) \b /oxgc) {
4603 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            
4604             else {
4605 0           while ($string !~ /\G \z/oxgc) {
4606 0 0         if ($string =~ /\G ((?>\s+)|\#.*) /oxgc) { $e_string .= $e . $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
4607 0           elsif ($string =~ /\G (\() ((?:\\\\|\\\)|\\\(|$q_paren)*?) (\)) /oxgc) { $e_string .= e_split_q($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # q ( ) --> qr ( )
  0            
4608 0           elsif ($string =~ /\G (\{) ((?:\\\\|\\\}|\\\{|$q_brace)*?) (\}) /oxgc) { $e_string .= e_split_q($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # q { } --> qr { }
  0            
4609 0           elsif ($string =~ /\G (\[) ((?:\\\\|\\\]|\\\[|$q_bracket)*?) (\]) /oxgc) { $e_string .= e_split_q($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # q [ ] --> qr [ ]
  0            
4610 0           elsif ($string =~ /\G (\<) ((?:\\\\|\\\>|\\\<|$q_angle)*?) (\>) /oxgc) { $e_string .= e_split_q($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # q < > --> qr < >
  0            
4611 0           elsif ($string =~ /\G ([*\-:?\\^|]) ((?:$q_char)*?) (\1) /oxgc) { $e_string .= e_split_q($e.'qr','{','}',$2,''); next E_STRING_LOOP; } # q | | --> qr { }
  0            
4612 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            
4613             }
4614 0           die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4615             }
4616             }
4617              
4618             # split m//
4619             elsif ($string =~ /\G \b (m) \b /oxgc) {
4620 0 0         if ($string =~ /\G (\#) ((?:$qq_char)*?) (\#) ([cgimosxpadlunbB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1,$3,$2,$4); next E_STRING_LOOP; } # m# # --> qr # #
  0            
  0            
4621             else {
4622 0           while ($string !~ /\G \z/oxgc) {
4623 0 0         if ($string =~ /\G ((?>\s+)|\#.*) /oxgc) { $e_string .= $e . $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
4624 0           elsif ($string =~ /\G (\() ((?:$qq_paren)*?) (\)) ([cgimosxpadlunbB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # m ( ) --> qr ( )
  0            
4625 0           elsif ($string =~ /\G (\{) ((?:$qq_brace)*?) (\}) ([cgimosxpadlunbB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # m { } --> qr { }
  0            
4626 0           elsif ($string =~ /\G (\[) ((?:$qq_bracket)*?) (\]) ([cgimosxpadlunbB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # m [ ] --> qr [ ]
  0            
4627 0           elsif ($string =~ /\G (\<) ((?:$qq_angle)*?) (\>) ([cgimosxpadlunbB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # m < > --> qr < >
  0            
4628 0           elsif ($string =~ /\G (\') ((?:$qq_char)*?) (\') ([cgimosxpadlunbB]*) /oxgc) { $e_string .= e_split_q($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # m ' ' --> qr ' '
  0            
4629 0           elsif ($string =~ /\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ([cgimosxpadlunbB]*) /oxgc) { $e_string .= e_split ($e.'qr','{','}',$2,$4); next E_STRING_LOOP; } # m | | --> qr { }
  0            
4630 0           elsif ($string =~ /\G (\S) ((?:$qq_char)*?) (\1) ([cgimosxpadlunbB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # m * * --> qr * *
  0            
4631             }
4632 0           die __FILE__, ": Search pattern not terminated\n";
4633             }
4634             }
4635              
4636             # split ''
4637             elsif ($string =~ /\G (\') /oxgc) {
4638 0           my $q_string = '';
4639 0           while ($string !~ /\G \z/oxgc) {
4640 0 0         if ($string =~ /\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0          
    0          
    0          
4641 0           elsif ($string =~ /\G (\\\') /oxgc) { $q_string .= $1; } # splitqr'' --> split qr''
4642 0           elsif ($string =~ /\G \' /oxgc) { $e_string .= e_split_q($e.q{ qr},"'","'",$q_string,''); next E_STRING_LOOP; } # ' ' --> qr ' '
  0            
4643 0           elsif ($string =~ /\G ($q_char) /oxgc) { $q_string .= $1; }
4644             }
4645 0           die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4646             }
4647              
4648             # split ""
4649             elsif ($string =~ /\G (\") /oxgc) {
4650 0           my $qq_string = '';
4651 0           while ($string !~ /\G \z/oxgc) {
4652 0 0         if ($string =~ /\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0          
    0          
    0          
4653 0           elsif ($string =~ /\G (\\\") /oxgc) { $qq_string .= $1; } # splitqr"" --> split qr""
4654 0           elsif ($string =~ /\G \" /oxgc) { $e_string .= e_split($e.q{ qr},'"','"',$qq_string,''); next E_STRING_LOOP; } # " " --> qr " "
  0            
4655 0           elsif ($string =~ /\G ($q_char) /oxgc) { $qq_string .= $1; }
4656             }
4657 0           die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4658             }
4659              
4660             # split //
4661             elsif ($string =~ /\G (\/) /oxgc) {
4662 0           my $regexp = '';
4663 0           while ($string !~ /\G \z/oxgc) {
4664 0 0         if ($string =~ /\G (\\\\) /oxgc) { $regexp .= $1; }
  0 0          
    0          
    0          
4665 0           elsif ($string =~ /\G (\\\/) /oxgc) { $regexp .= $1; } # splitqr// --> split qr//
4666 0           elsif ($string =~ /\G \/ ([cgimosxpadlunbB]*) /oxgc) { $e_string .= e_split($e.q{ qr}, '/','/',$regexp,$1); next E_STRING_LOOP; } # / / --> qr / /
  0            
4667 0           elsif ($string =~ /\G ($q_char) /oxgc) { $regexp .= $1; }
4668             }
4669 0           die __FILE__, ": Search pattern not terminated\n";
4670             }
4671             }
4672              
4673             # qq//
4674             elsif ($string =~ /\G \b (qq) \b /oxgc) {
4675 0           my $ope = $1;
4676 0 0         if ($string =~ /\G (\#) ((?:$qq_char)*?) (\#) /oxgc) { # qq# #
4677 0           $e_string .= e_qq($ope,$1,$3,$2);
4678             }
4679             else {
4680 0           my $e = '';
4681 0           while ($string !~ /\G \z/oxgc) {
4682 0 0         if ($string =~ /\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
4683 0           elsif ($string =~ /\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qq ( )
  0            
4684 0           elsif ($string =~ /\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qq { }
  0            
4685 0           elsif ($string =~ /\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qq [ ]
  0            
4686 0           elsif ($string =~ /\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qq < >
  0            
4687 0           elsif ($string =~ /\G (\S) ((?:$qq_char)*?) (\1) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qq * *
  0            
4688             }
4689 0           die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4690             }
4691             }
4692              
4693             # qx//
4694             elsif ($string =~ /\G \b (qx) \b /oxgc) {
4695 0           my $ope = $1;
4696 0 0         if ($string =~ /\G (\#) ((?:$qq_char)*?) (\#) /oxgc) { # qx# #
4697 0           $e_string .= e_qq($ope,$1,$3,$2);
4698             }
4699             else {
4700 0           my $e = '';
4701 0           while ($string !~ /\G \z/oxgc) {
4702 0 0         if ($string =~ /\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
4703 0           elsif ($string =~ /\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qx ( )
  0            
4704 0           elsif ($string =~ /\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qx { }
  0            
4705 0           elsif ($string =~ /\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qx [ ]
  0            
4706 0           elsif ($string =~ /\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qx < >
  0            
4707 0           elsif ($string =~ /\G (\') ((?:$qq_char)*?) (\') /oxgc) { $e_string .= $e . e_q ($ope,$1,$3,$2); next E_STRING_LOOP; } # qx ' '
  0            
4708 0           elsif ($string =~ /\G (\S) ((?:$qq_char)*?) (\1) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qx * *
  0            
4709             }
4710 0           die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4711             }
4712             }
4713              
4714             # q//
4715             elsif ($string =~ /\G \b (q) \b /oxgc) {
4716 0           my $ope = $1;
4717 0 0         if ($string =~ /\G (\#) ((?:\\\#|\\\\|$q_char)*?) (\#) /oxgc) { # q# #
4718 0           $e_string .= e_q($ope,$1,$3,$2);
4719             }
4720             else {
4721 0           my $e = '';
4722 0           while ($string !~ /\G \z/oxgc) {
4723 0 0         if ($string =~ /\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
4724 0           elsif ($string =~ /\G (\() ((?:\\\\|\\\)|\\\(|$q_paren)*?) (\)) /oxgc) { $e_string .= $e . e_q($ope,$1,$3,$2); next E_STRING_LOOP; } # q ( )
  0            
4725 0           elsif ($string =~ /\G (\{) ((?:\\\\|\\\}|\\\{|$q_brace)*?) (\}) /oxgc) { $e_string .= $e . e_q($ope,$1,$3,$2); next E_STRING_LOOP; } # q { }
  0            
4726 0           elsif ($string =~ /\G (\[) ((?:\\\\|\\\]|\\\[|$q_bracket)*?) (\]) /oxgc) { $e_string .= $e . e_q($ope,$1,$3,$2); next E_STRING_LOOP; } # q [ ]
  0            
4727 0           elsif ($string =~ /\G (\<) ((?:\\\\|\\\>|\\\<|$q_angle)*?) (\>) /oxgc) { $e_string .= $e . e_q($ope,$1,$3,$2); next E_STRING_LOOP; } # q < >
  0            
4728 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            
4729             }
4730 0           die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4731             }
4732             }
4733              
4734             # ''
4735 0           elsif ($string =~ /\G (?
4736              
4737             # ""
4738 0           elsif ($string =~ /\G (\") ((?:$qq_char)*?) (\") /oxgc) { $e_string .= e_qq('',$1,$3,$2); }
4739              
4740             # ``
4741 0           elsif ($string =~ /\G (\`) ((?:$qq_char)*?) (\`) /oxgc) { $e_string .= e_qq('',$1,$3,$2); }
4742              
4743             # <<>> (a safer ARGV)
4744 0           elsif ($string =~ /\G ( <<>> ) /oxgc) { $e_string .= $1; }
4745              
4746             # <<= <=> <= < operator
4747 0           elsif ($string =~ /\G ( <<= | <=> | <= | < ) (?= (?>\s*) [A-Za-z_0-9'"`\$\@\&\*\(\+\-] )/oxgc) { $e_string .= $1; }
4748              
4749             #
4750 0           elsif ($string =~ /\G (<[\$]?[A-Za-z_][A-Za-z_0-9]*>) /oxgc) { $e_string .= $1; }
4751              
4752             # --- glob
4753             elsif ($string =~ /\G < ((?:$q_char)+?) > /oxgc) {
4754 0           $e_string .= 'Ekoi8r::glob("' . $1 . '")';
4755             }
4756              
4757             # << (bit shift) --- not here document
4758 0           elsif ($string =~ /\G ( << (?>\s*) ) (?= [0-9\$\@\&] ) /oxgc) { $slash = 'm//'; $e_string .= $1; }
  0            
4759              
4760             # <<'HEREDOC'
4761             elsif ($string =~ /\G ( << '([a-zA-Z_0-9]*)' ) /oxgc) {
4762 0           $slash = 'm//';
4763 0           my $here_quote = $1;
4764 0           my $delimiter = $2;
4765              
4766             # get here document
4767 0 0         if ($here_script eq '') {
4768 0           $here_script = CORE::substr $_, pos $_;
4769 0           $here_script =~ s/.*?\n//oxm;
4770             }
4771 0 0         if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4772 0           push @heredoc, $1 . qq{\n$delimiter\n};
4773 0           push @heredoc_delimiter, $delimiter;
4774             }
4775             else {
4776 0           die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4777             }
4778 0           $e_string .= $here_quote;
4779             }
4780              
4781             # <<\HEREDOC
4782             elsif ($string =~ /\G ( << \\([a-zA-Z_0-9]+) ) /oxgc) {
4783 0           $slash = 'm//';
4784 0           my $here_quote = $1;
4785 0           my $delimiter = $2;
4786              
4787             # get here document
4788 0 0         if ($here_script eq '') {
4789 0           $here_script = CORE::substr $_, pos $_;
4790 0           $here_script =~ s/.*?\n//oxm;
4791             }
4792 0 0         if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4793 0           push @heredoc, $1 . qq{\n$delimiter\n};
4794 0           push @heredoc_delimiter, $delimiter;
4795             }
4796             else {
4797 0           die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4798             }
4799 0           $e_string .= $here_quote;
4800             }
4801              
4802             # <<"HEREDOC"
4803             elsif ($string =~ /\G ( << "([a-zA-Z_0-9]*)" ) /oxgc) {
4804 0           $slash = 'm//';
4805 0           my $here_quote = $1;
4806 0           my $delimiter = $2;
4807              
4808             # get here document
4809 0 0         if ($here_script eq '') {
4810 0           $here_script = CORE::substr $_, pos $_;
4811 0           $here_script =~ s/.*?\n//oxm;
4812             }
4813 0 0         if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4814 0           push @heredoc, e_heredoc($1) . qq{\n$delimiter\n};
4815 0           push @heredoc_delimiter, $delimiter;
4816             }
4817             else {
4818 0           die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4819             }
4820 0           $e_string .= $here_quote;
4821             }
4822              
4823             # <
4824             elsif ($string =~ /\G ( << ([a-zA-Z_0-9]+) ) /oxgc) {
4825 0           $slash = 'm//';
4826 0           my $here_quote = $1;
4827 0           my $delimiter = $2;
4828              
4829             # get here document
4830 0 0         if ($here_script eq '') {
4831 0           $here_script = CORE::substr $_, pos $_;
4832 0           $here_script =~ s/.*?\n//oxm;
4833             }
4834 0 0         if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4835 0           push @heredoc, e_heredoc($1) . qq{\n$delimiter\n};
4836 0           push @heredoc_delimiter, $delimiter;
4837             }
4838             else {
4839 0           die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4840             }
4841 0           $e_string .= $here_quote;
4842             }
4843              
4844             # <<`HEREDOC`
4845             elsif ($string =~ /\G ( << `([a-zA-Z_0-9]*)` ) /oxgc) {
4846 0           $slash = 'm//';
4847 0           my $here_quote = $1;
4848 0           my $delimiter = $2;
4849              
4850             # get here document
4851 0 0         if ($here_script eq '') {
4852 0           $here_script = CORE::substr $_, pos $_;
4853 0           $here_script =~ s/.*?\n//oxm;
4854             }
4855 0 0         if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4856 0           push @heredoc, e_heredoc($1) . qq{\n$delimiter\n};
4857 0           push @heredoc_delimiter, $delimiter;
4858             }
4859             else {
4860 0           die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4861             }
4862 0           $e_string .= $here_quote;
4863             }
4864              
4865             # any operator before div
4866             elsif ($string =~ /\G (
4867             -- | \+\+ |
4868             [\)\}\]]
4869              
4870 0           ) /oxgc) { $slash = 'div'; $e_string .= $1; }
  0            
4871              
4872             # yada-yada or triple-dot operator
4873             elsif ($string =~ /\G (
4874             \.\.\.
4875              
4876 0           ) /oxgc) { $slash = 'm//'; $e_string .= q{die('Unimplemented')}; }
  0            
4877              
4878             # any operator before m//
4879             elsif ($string =~ /\G ((?>
4880              
4881             !~~ | !~ | != | ! |
4882             %= | % |
4883             &&= | && | &= | &\.= | &\. | & |
4884             -= | -> | - |
4885             :(?>\s*)= |
4886             : |
4887             <<>> |
4888             <<= | <=> | <= | < |
4889             == | => | =~ | = |
4890             >>= | >> | >= | > |
4891             \*\*= | \*\* | \*= | \* |
4892             \+= | \+ |
4893             \.\. | \.= | \. |
4894             \/\/= | \/\/ |
4895             \/= | \/ |
4896             \? |
4897             \\ |
4898             \^= | \^\.= | \^\. | \^ |
4899             \b x= |
4900             \|\|= | \|\| | \|= | \|\.= | \|\. | \| |
4901             ~~ | ~\. | ~ |
4902             \b(?: and | cmp | eq | ge | gt | le | lt | ne | not | or | xor | x )\b |
4903             \b(?: print )\b |
4904              
4905             [,;\(\{\[]
4906              
4907 0           )) /oxgc) { $slash = 'm//'; $e_string .= $1; }
  0            
4908              
4909             # other any character
4910 0           elsif ($string =~ /\G ($q_char) /oxgc) { $e_string .= $1; }
4911              
4912             # system error
4913             else {
4914 0           die __FILE__, ": Oops, this shouldn't happen!\n";
4915             }
4916             }
4917              
4918 0           return $e_string;
4919             }
4920              
4921             #
4922             # character class
4923             #
4924             sub character_class {
4925 0     0 0   my($char,$modifier) = @_;
4926              
4927 0 0         if ($char eq '.') {
4928 0 0         if ($modifier =~ /s/) {
4929 0           return '${Ekoi8r::dot_s}';
4930             }
4931             else {
4932 0           return '${Ekoi8r::dot}';
4933             }
4934             }
4935             else {
4936 0           return Ekoi8r::classic_character_class($char);
4937             }
4938             }
4939              
4940             #
4941             # escape capture ($1, $2, $3, ...)
4942             #
4943             sub e_capture {
4944              
4945 0     0 0   return join '', '${', $_[0], '}';
4946             }
4947              
4948             #
4949             # escape transliteration (tr/// or y///)
4950             #
4951             sub e_tr {
4952 0     0 0   my($variable,$charclass,$e,$charclass2,$modifier) = @_;
4953 0           my $e_tr = '';
4954 0   0       $modifier ||= '';
4955              
4956 0           $slash = 'div';
4957              
4958             # quote character class 1
4959 0           $charclass = q_tr($charclass);
4960              
4961             # quote character class 2
4962 0           $charclass2 = q_tr($charclass2);
4963              
4964             # /b /B modifier
4965 0 0         if ($modifier =~ tr/bB//d) {
4966 0 0         if ($variable eq '') {
4967 0           $e_tr = qq{tr$charclass$e$charclass2$modifier};
4968             }
4969             else {
4970 0           $e_tr = qq{$variable${bind_operator}tr$charclass$e$charclass2$modifier};
4971             }
4972             }
4973             else {
4974 0 0         if ($variable eq '') {
4975 0           $e_tr = qq{Ekoi8r::tr(\$_,' =~ ',$charclass,$e$charclass2,'$modifier')};
4976             }
4977             else {
4978 0           $e_tr = qq{Ekoi8r::tr($variable,'$bind_operator',$charclass,$e$charclass2,'$modifier')};
4979             }
4980             }
4981              
4982             # clear tr/// variable
4983 0           $tr_variable = '';
4984 0           $bind_operator = '';
4985              
4986 0           return $e_tr;
4987             }
4988              
4989             #
4990             # quote for escape transliteration (tr/// or y///)
4991             #
4992             sub q_tr {
4993 0     0 0   my($charclass) = @_;
4994              
4995             # quote character class
4996 0 0         if ($charclass !~ /'/oxms) {
    0          
    0          
    0          
    0          
    0          
4997 0           return e_q('', "'", "'", $charclass); # --> q' '
4998             }
4999             elsif ($charclass !~ /\//oxms) {
5000 0           return e_q('q', '/', '/', $charclass); # --> q/ /
5001             }
5002             elsif ($charclass !~ /\#/oxms) {
5003 0           return e_q('q', '#', '#', $charclass); # --> q# #
5004             }
5005             elsif ($charclass !~ /[\<\>]/oxms) {
5006 0           return e_q('q', '<', '>', $charclass); # --> q< >
5007             }
5008             elsif ($charclass !~ /[\(\)]/oxms) {
5009 0           return e_q('q', '(', ')', $charclass); # --> q( )
5010             }
5011             elsif ($charclass !~ /[\{\}]/oxms) {
5012 0           return e_q('q', '{', '}', $charclass); # --> q{ }
5013             }
5014             else {
5015 0           for my $char (qw( ! " $ % & * + . : = ? @ ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
5016 0 0         if ($charclass !~ /\Q$char\E/xms) {
5017 0           return e_q('q', $char, $char, $charclass);
5018             }
5019             }
5020             }
5021              
5022 0           return e_q('q', '{', '}', $charclass);
5023             }
5024              
5025             #
5026             # escape q string (q//, '')
5027             #
5028             sub e_q {
5029 0     0 0   my($ope,$delimiter,$end_delimiter,$string) = @_;
5030              
5031 0           $slash = 'div';
5032              
5033 0           return join '', $ope, $delimiter, $string, $end_delimiter;
5034             }
5035              
5036             #
5037             # escape qq string (qq//, "", qx//, ``)
5038             #
5039             sub e_qq {
5040 0     0 0   my($ope,$delimiter,$end_delimiter,$string) = @_;
5041              
5042 0           $slash = 'div';
5043              
5044 0           my $left_e = 0;
5045 0           my $right_e = 0;
5046              
5047             # split regexp
5048 0           my @char = $string =~ /\G((?>
5049             [^\\\$] |
5050             \\x\{ (?>[0-9A-Fa-f]+) \} |
5051             \\o\{ (?>[0-7]+) \} |
5052             \\N\{ (?>[^0-9\}][^\}]*) \} |
5053             \\ $q_char |
5054             \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} |
5055             \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} |
5056             \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} |
5057             \$ (?>\s* [0-9]+) |
5058             \$ (?>\s*) \{ (?>\s* [0-9]+ \s*) \} |
5059             \$ \$ (?![\w\{]) |
5060             \$ (?>\s*) \$ (?>\s*) $qq_variable |
5061             $q_char
5062             ))/oxmsg;
5063              
5064 0           for (my $i=0; $i <= $#char; $i++) {
5065              
5066             # "\L\u" --> "\u\L"
5067 0 0 0       if (($char[$i] eq '\L') and ($char[$i+1] eq '\u')) {
    0 0        
    0          
    0          
    0          
5068 0           @char[$i,$i+1] = @char[$i+1,$i];
5069             }
5070              
5071             # "\U\l" --> "\l\U"
5072             elsif (($char[$i] eq '\U') and ($char[$i+1] eq '\l')) {
5073 0           @char[$i,$i+1] = @char[$i+1,$i];
5074             }
5075              
5076             # octal escape sequence
5077             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
5078 0           $char[$i] = Ekoi8r::octchr($1);
5079             }
5080              
5081             # hexadecimal escape sequence
5082             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
5083 0           $char[$i] = Ekoi8r::hexchr($1);
5084             }
5085              
5086             # \N{CHARNAME} --> N{CHARNAME}
5087             elsif ($char[$i] =~ /\A \\ ( N\{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
5088 0           $char[$i] = $1;
5089             }
5090              
5091 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          
5092             }
5093              
5094             # \F
5095             #
5096             # P.69 Table 2-6. Translation escapes
5097             # in Chapter 2: Bits and Pieces
5098             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
5099             # (and so on)
5100              
5101             # \u \l \U \L \F \Q \E
5102 0           elsif ($char[$i] =~ /\A ([<>]) \z/oxms) {
5103 0 0         if ($right_e < $left_e) {
5104 0           $char[$i] = '\\' . $char[$i];
5105             }
5106             }
5107             elsif ($char[$i] eq '\u') {
5108              
5109             # "STRING @{[ LIST EXPR ]} MORE STRING"
5110              
5111             # P.257 Other Tricks You Can Do with Hard References
5112             # in Chapter 8: References
5113             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
5114              
5115             # P.353 Other Tricks You Can Do with Hard References
5116             # in Chapter 8: References
5117             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
5118              
5119             # (and so on)
5120              
5121 0           $char[$i] = '@{[Ekoi8r::ucfirst qq<';
5122 0           $left_e++;
5123             }
5124             elsif ($char[$i] eq '\l') {
5125 0           $char[$i] = '@{[Ekoi8r::lcfirst qq<';
5126 0           $left_e++;
5127             }
5128             elsif ($char[$i] eq '\U') {
5129 0           $char[$i] = '@{[Ekoi8r::uc qq<';
5130 0           $left_e++;
5131             }
5132             elsif ($char[$i] eq '\L') {
5133 0           $char[$i] = '@{[Ekoi8r::lc qq<';
5134 0           $left_e++;
5135             }
5136             elsif ($char[$i] eq '\F') {
5137 0           $char[$i] = '@{[Ekoi8r::fc qq<';
5138 0           $left_e++;
5139             }
5140             elsif ($char[$i] eq '\Q') {
5141 0           $char[$i] = '@{[CORE::quotemeta qq<';
5142 0           $left_e++;
5143             }
5144             elsif ($char[$i] eq '\E') {
5145 0 0         if ($right_e < $left_e) {
5146 0           $char[$i] = '>]}';
5147 0           $right_e++;
5148             }
5149             else {
5150 0           $char[$i] = '';
5151             }
5152             }
5153             elsif ($char[$i] eq '\Q') {
5154 0           while (1) {
5155 0 0         if (++$i > $#char) {
5156 0           last;
5157             }
5158 0 0         if ($char[$i] eq '\E') {
5159 0           last;
5160             }
5161             }
5162             }
5163             elsif ($char[$i] eq '\E') {
5164             }
5165              
5166             # $0 --> $0
5167             elsif ($char[$i] =~ /\A \$ 0 \z/oxms) {
5168             }
5169             elsif ($char[$i] =~ /\A \$ \{ (?>\s*) 0 (?>\s*) \} \z/oxms) {
5170             }
5171              
5172             # $$ --> $$
5173             elsif ($char[$i] =~ /\A \$\$ \z/oxms) {
5174             }
5175              
5176             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
5177             # $1, $2, $3 --> $1, $2, $3 otherwise
5178             elsif ($char[$i] =~ /\A \$ ((?>[1-9][0-9]*)) \z/oxms) {
5179 0           $char[$i] = e_capture($1);
5180             }
5181             elsif ($char[$i] =~ /\A \$ \{ (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} \z/oxms) {
5182 0           $char[$i] = e_capture($1);
5183             }
5184              
5185             # $$foo[ ... ] --> $ $foo->[ ... ]
5186             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \[ (?:$qq_bracket)*? \] ) \z/oxms) {
5187 0           $char[$i] = e_capture($1.'->'.$2);
5188             }
5189              
5190             # $$foo{ ... } --> $ $foo->{ ... }
5191             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \{ (?:$qq_brace)*? \} ) \z/oxms) {
5192 0           $char[$i] = e_capture($1.'->'.$2);
5193             }
5194              
5195             # $$foo
5196             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) \z/oxms) {
5197 0           $char[$i] = e_capture($1);
5198             }
5199              
5200             # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Ekoi8r::PREMATCH()
5201             elsif ($char[$i] =~ /\A ( \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} ) \z/oxmsgc) {
5202 0           $char[$i] = '@{[Ekoi8r::PREMATCH()]}';
5203             }
5204              
5205             # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Ekoi8r::MATCH()
5206             elsif ($char[$i] =~ /\A ( \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} ) \z/oxmsgc) {
5207 0           $char[$i] = '@{[Ekoi8r::MATCH()]}';
5208             }
5209              
5210             # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Ekoi8r::POSTMATCH()
5211             elsif ($char[$i] =~ /\A ( \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} ) \z/oxmsgc) {
5212 0           $char[$i] = '@{[Ekoi8r::POSTMATCH()]}';
5213             }
5214              
5215             # ${ foo } --> ${ foo }
5216             elsif ($char[$i] =~ /\A \$ (?>\s*) \{ (?> \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* ) \} \z/oxms) {
5217             }
5218              
5219             # ${ ... }
5220             elsif ($char[$i] =~ /\A \$ (?>\s*) \{ ( .+ ) \} \z/oxms) {
5221 0           $char[$i] = e_capture($1);
5222             }
5223             }
5224              
5225             # return string
5226 0 0         if ($left_e > $right_e) {
5227 0           return join '', $ope, $delimiter, @char, '>]}' x ($left_e - $right_e), $end_delimiter;
5228             }
5229 0           return join '', $ope, $delimiter, @char, $end_delimiter;
5230             }
5231              
5232             #
5233             # escape qw string (qw//)
5234             #
5235             sub e_qw {
5236 0     0 0   my($ope,$delimiter,$end_delimiter,$string) = @_;
5237              
5238 0           $slash = 'div';
5239              
5240             # choice again delimiter
5241 0           my %octet = map {$_ => 1} ($string =~ /\G ([\x00-\xFF]) /oxmsg);
  0            
5242 0 0         if (not $octet{$end_delimiter}) {
    0          
    0          
    0          
    0          
5243 0           return join '', $ope, $delimiter, $string, $end_delimiter;
5244             }
5245             elsif (not $octet{')'}) {
5246 0           return join '', $ope, '(', $string, ')';
5247             }
5248             elsif (not $octet{'}'}) {
5249 0           return join '', $ope, '{', $string, '}';
5250             }
5251             elsif (not $octet{']'}) {
5252 0           return join '', $ope, '[', $string, ']';
5253             }
5254             elsif (not $octet{'>'}) {
5255 0           return join '', $ope, '<', $string, '>';
5256             }
5257             else {
5258 0           for my $char (qw( ! " $ % & * + - . / : = ? @ ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
5259 0 0         if (not $octet{$char}) {
5260 0           return join '', $ope, $char, $string, $char;
5261             }
5262             }
5263             }
5264              
5265             # qw/AAA BBB C'CC/ --> ('AAA', 'BBB', 'C\'CC')
5266 0           my @string = CORE::split(/\s+/, $string);
5267 0           for my $string (@string) {
5268 0           my @octet = $string =~ /\G ([\x00-\xFF]) /oxmsg;
5269 0           for my $octet (@octet) {
5270 0 0         if ($octet =~ /\A (['\\]) \z/oxms) {
5271 0           $octet = '\\' . $1;
5272             }
5273             }
5274 0           $string = join '', @octet;
5275             }
5276 0           return join '', '(', (join ', ', map { "'$_'" } @string), ')';
  0            
5277             }
5278              
5279             #
5280             # escape here document (<<"HEREDOC", <
5281             #
5282             sub e_heredoc {
5283 0     0 0   my($string) = @_;
5284              
5285 0           $slash = 'm//';
5286              
5287 0           my $metachar = qr/[\@\\|]/oxms; # '|' is for <<`HEREDOC`
5288              
5289 0           my $left_e = 0;
5290 0           my $right_e = 0;
5291              
5292             # split regexp
5293 0           my @char = $string =~ /\G((?>
5294             [^\\\$] |
5295             \\x\{ (?>[0-9A-Fa-f]+) \} |
5296             \\o\{ (?>[0-7]+) \} |
5297             \\N\{ (?>[^0-9\}][^\}]*) \} |
5298             \\ $q_char |
5299             \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} |
5300             \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} |
5301             \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} |
5302             \$ (?>\s* [0-9]+) |
5303             \$ (?>\s*) \{ (?>\s* [0-9]+ \s*) \} |
5304             \$ \$ (?![\w\{]) |
5305             \$ (?>\s*) \$ (?>\s*) $qq_variable |
5306             $q_char
5307             ))/oxmsg;
5308              
5309 0           for (my $i=0; $i <= $#char; $i++) {
5310              
5311             # "\L\u" --> "\u\L"
5312 0 0 0       if (($char[$i] eq '\L') and ($char[$i+1] eq '\u')) {
    0 0        
    0          
    0          
    0          
5313 0           @char[$i,$i+1] = @char[$i+1,$i];
5314             }
5315              
5316             # "\U\l" --> "\l\U"
5317             elsif (($char[$i] eq '\U') and ($char[$i+1] eq '\l')) {
5318 0           @char[$i,$i+1] = @char[$i+1,$i];
5319             }
5320              
5321             # octal escape sequence
5322             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
5323 0           $char[$i] = Ekoi8r::octchr($1);
5324             }
5325              
5326             # hexadecimal escape sequence
5327             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
5328 0           $char[$i] = Ekoi8r::hexchr($1);
5329             }
5330              
5331             # \N{CHARNAME} --> N{CHARNAME}
5332             elsif ($char[$i] =~ /\A \\ ( N\{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
5333 0           $char[$i] = $1;
5334             }
5335              
5336 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          
5337             }
5338              
5339             # \u \l \U \L \F \Q \E
5340 0           elsif ($char[$i] =~ /\A ([<>]) \z/oxms) {
5341 0 0         if ($right_e < $left_e) {
5342 0           $char[$i] = '\\' . $char[$i];
5343             }
5344             }
5345             elsif ($char[$i] eq '\u') {
5346 0           $char[$i] = '@{[Ekoi8r::ucfirst qq<';
5347 0           $left_e++;
5348             }
5349             elsif ($char[$i] eq '\l') {
5350 0           $char[$i] = '@{[Ekoi8r::lcfirst qq<';
5351 0           $left_e++;
5352             }
5353             elsif ($char[$i] eq '\U') {
5354 0           $char[$i] = '@{[Ekoi8r::uc qq<';
5355 0           $left_e++;
5356             }
5357             elsif ($char[$i] eq '\L') {
5358 0           $char[$i] = '@{[Ekoi8r::lc qq<';
5359 0           $left_e++;
5360             }
5361             elsif ($char[$i] eq '\F') {
5362 0           $char[$i] = '@{[Ekoi8r::fc qq<';
5363 0           $left_e++;
5364             }
5365             elsif ($char[$i] eq '\Q') {
5366 0           $char[$i] = '@{[CORE::quotemeta qq<';
5367 0           $left_e++;
5368             }
5369             elsif ($char[$i] eq '\E') {
5370 0 0         if ($right_e < $left_e) {
5371 0           $char[$i] = '>]}';
5372 0           $right_e++;
5373             }
5374             else {
5375 0           $char[$i] = '';
5376             }
5377             }
5378             elsif ($char[$i] eq '\Q') {
5379 0           while (1) {
5380 0 0         if (++$i > $#char) {
5381 0           last;
5382             }
5383 0 0         if ($char[$i] eq '\E') {
5384 0           last;
5385             }
5386             }
5387             }
5388             elsif ($char[$i] eq '\E') {
5389             }
5390              
5391             # $0 --> $0
5392             elsif ($char[$i] =~ /\A \$ 0 \z/oxms) {
5393             }
5394             elsif ($char[$i] =~ /\A \$ \{ (?>\s*) 0 (?>\s*) \} \z/oxms) {
5395             }
5396              
5397             # $$ --> $$
5398             elsif ($char[$i] =~ /\A \$\$ \z/oxms) {
5399             }
5400              
5401             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
5402             # $1, $2, $3 --> $1, $2, $3 otherwise
5403             elsif ($char[$i] =~ /\A \$ ((?>[1-9][0-9]*)) \z/oxms) {
5404 0           $char[$i] = e_capture($1);
5405             }
5406             elsif ($char[$i] =~ /\A \$ \{ (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} \z/oxms) {
5407 0           $char[$i] = e_capture($1);
5408             }
5409              
5410             # $$foo[ ... ] --> $ $foo->[ ... ]
5411             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \[ (?:$qq_bracket)*? \] ) \z/oxms) {
5412 0           $char[$i] = e_capture($1.'->'.$2);
5413             }
5414              
5415             # $$foo{ ... } --> $ $foo->{ ... }
5416             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \{ (?:$qq_brace)*? \} ) \z/oxms) {
5417 0           $char[$i] = e_capture($1.'->'.$2);
5418             }
5419              
5420             # $$foo
5421             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) \z/oxms) {
5422 0           $char[$i] = e_capture($1);
5423             }
5424              
5425             # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Ekoi8r::PREMATCH()
5426             elsif ($char[$i] =~ /\A ( \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} ) \z/oxmsgc) {
5427 0           $char[$i] = '@{[Ekoi8r::PREMATCH()]}';
5428             }
5429              
5430             # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Ekoi8r::MATCH()
5431             elsif ($char[$i] =~ /\A ( \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} ) \z/oxmsgc) {
5432 0           $char[$i] = '@{[Ekoi8r::MATCH()]}';
5433             }
5434              
5435             # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Ekoi8r::POSTMATCH()
5436             elsif ($char[$i] =~ /\A ( \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} ) \z/oxmsgc) {
5437 0           $char[$i] = '@{[Ekoi8r::POSTMATCH()]}';
5438             }
5439              
5440             # ${ foo } --> ${ foo }
5441             elsif ($char[$i] =~ /\A \$ (?>\s*) \{ (?> \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* ) \} \z/oxms) {
5442             }
5443              
5444             # ${ ... }
5445             elsif ($char[$i] =~ /\A \$ (?>\s*) \{ ( .+ ) \} \z/oxms) {
5446 0           $char[$i] = e_capture($1);
5447             }
5448             }
5449              
5450             # return string
5451 0 0         if ($left_e > $right_e) {
5452 0           return join '', @char, '>]}' x ($left_e - $right_e);
5453             }
5454 0           return join '', @char;
5455             }
5456              
5457             #
5458             # escape regexp (m//, qr//)
5459             #
5460             sub e_qr {
5461 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
5462 0   0       $modifier ||= '';
5463              
5464 0           $modifier =~ tr/p//d;
5465 0 0         if ($modifier =~ /([adlu])/oxms) {
5466 0           my $line = 0;
5467 0           for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
5468 0 0         if ($filename ne __FILE__) {
5469 0           $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
5470 0           last;
5471             }
5472             }
5473 0           die qq{Unsupported modifier "$1" used at line $line.\n};
5474             }
5475              
5476 0           $slash = 'div';
5477              
5478             # literal null string pattern
5479 0 0         if ($string eq '') {
    0          
5480 0           $modifier =~ tr/bB//d;
5481 0           $modifier =~ tr/i//d;
5482 0           return join '', $ope, $delimiter, $end_delimiter, $modifier;
5483             }
5484              
5485             # /b /B modifier
5486             elsif ($modifier =~ tr/bB//d) {
5487              
5488             # choice again delimiter
5489 0 0         if ($delimiter =~ / [\@:] /oxms) {
5490 0           my @char = $string =~ /\G ([\x00-\xFF]) /oxmsg;
5491 0           my %octet = map {$_ => 1} @char;
  0            
5492 0 0         if (not $octet{')'}) {
    0          
    0          
    0          
5493 0           $delimiter = '(';
5494 0           $end_delimiter = ')';
5495             }
5496             elsif (not $octet{'}'}) {
5497 0           $delimiter = '{';
5498 0           $end_delimiter = '}';
5499             }
5500             elsif (not $octet{']'}) {
5501 0           $delimiter = '[';
5502 0           $end_delimiter = ']';
5503             }
5504             elsif (not $octet{'>'}) {
5505 0           $delimiter = '<';
5506 0           $end_delimiter = '>';
5507             }
5508             else {
5509 0           for my $char (qw( ! " $ % & * + - . / = ? ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
5510 0 0         if (not $octet{$char}) {
5511 0           $delimiter = $char;
5512 0           $end_delimiter = $char;
5513 0           last;
5514             }
5515             }
5516             }
5517             }
5518              
5519 0 0 0       if (($ope =~ /\A m? \z/oxms) and ($delimiter eq '?')) {
5520 0           return join '', $ope, $delimiter, $string, $matched, $end_delimiter, $modifier;
5521             }
5522             else {
5523 0           return join '', $ope, $delimiter, '(?:', $string, ')', $matched, $end_delimiter, $modifier;
5524             }
5525             }
5526              
5527 0 0         my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
5528 0           my $metachar = qr/[\@\\|[\]{^]/oxms;
5529              
5530             # split regexp
5531 0           my @char = $string =~ /\G((?>
5532             [^\\\$\@\[\(] |
5533             \\x (?>[0-9A-Fa-f]{1,2}) |
5534             \\ (?>[0-7]{2,3}) |
5535             \\c [\x40-\x5F] |
5536             \\x\{ (?>[0-9A-Fa-f]+) \} |
5537             \\o\{ (?>[0-7]+) \} |
5538             \\[bBNpP]\{ (?>[^0-9\}][^\}]*) \} |
5539             \\ $q_char |
5540             \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} |
5541             \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} |
5542             \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} |
5543             [\$\@] $qq_variable |
5544             \$ (?>\s* [0-9]+) |
5545             \$ (?>\s*) \{ (?>\s* [0-9]+ \s*) \} |
5546             \$ \$ (?![\w\{]) |
5547             \$ (?>\s*) \$ (?>\s*) $qq_variable |
5548             \[\^ |
5549             \[\: (?>[a-z]+) :\] |
5550             \[\:\^ (?>[a-z]+) :\] |
5551             \(\? |
5552             $q_char
5553             ))/oxmsg;
5554              
5555             # choice again delimiter
5556 0 0         if ($delimiter =~ / [\@:] /oxms) {
5557 0           my %octet = map {$_ => 1} @char;
  0            
5558 0 0         if (not $octet{')'}) {
    0          
    0          
    0          
5559 0           $delimiter = '(';
5560 0           $end_delimiter = ')';
5561             }
5562             elsif (not $octet{'}'}) {
5563 0           $delimiter = '{';
5564 0           $end_delimiter = '}';
5565             }
5566             elsif (not $octet{']'}) {
5567 0           $delimiter = '[';
5568 0           $end_delimiter = ']';
5569             }
5570             elsif (not $octet{'>'}) {
5571 0           $delimiter = '<';
5572 0           $end_delimiter = '>';
5573             }
5574             else {
5575 0           for my $char (qw( ! " $ % & * + - . / = ? ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
5576 0 0         if (not $octet{$char}) {
5577 0           $delimiter = $char;
5578 0           $end_delimiter = $char;
5579 0           last;
5580             }
5581             }
5582             }
5583             }
5584              
5585 0           my $left_e = 0;
5586 0           my $right_e = 0;
5587 0           for (my $i=0; $i <= $#char; $i++) {
5588              
5589             # "\L\u" --> "\u\L"
5590 0 0 0       if (($char[$i] eq '\L') and ($char[$i+1] eq '\u')) {
    0 0        
    0          
    0          
    0          
    0          
5591 0           @char[$i,$i+1] = @char[$i+1,$i];
5592             }
5593              
5594             # "\U\l" --> "\l\U"
5595             elsif (($char[$i] eq '\U') and ($char[$i+1] eq '\l')) {
5596 0           @char[$i,$i+1] = @char[$i+1,$i];
5597             }
5598              
5599             # octal escape sequence
5600             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
5601 0           $char[$i] = Ekoi8r::octchr($1);
5602             }
5603              
5604             # hexadecimal escape sequence
5605             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
5606 0           $char[$i] = Ekoi8r::hexchr($1);
5607             }
5608              
5609             # \b{...} --> b\{...}
5610             # \B{...} --> B\{...}
5611             # \N{CHARNAME} --> N\{CHARNAME}
5612             # \p{PROPERTY} --> p\{PROPERTY}
5613             # \P{PROPERTY} --> P\{PROPERTY}
5614             elsif ($char[$i] =~ /\A \\ ([bBNpP]) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
5615 0           $char[$i] = $1 . '\\' . $2;
5616             }
5617              
5618             # \p, \P, \X --> p, P, X
5619             elsif ($char[$i] =~ /\A \\ ( [pPX] ) \z/oxms) {
5620 0           $char[$i] = $1;
5621             }
5622              
5623 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          
5624             }
5625              
5626             # join separated multiple-octet
5627 0           elsif ($char[$i] =~ /\A (?: \\ [0-7]{2,3} | \\x [0-9A-Fa-f]{1,2}) \z/oxms) {
5628 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        
5629 0           $char[$i] .= join '', splice @char, $i+1, 3;
5630             }
5631             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)) {
5632 0           $char[$i] .= join '', splice @char, $i+1, 2;
5633             }
5634             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)) {
5635 0           $char[$i] .= join '', splice @char, $i+1, 1;
5636             }
5637             }
5638              
5639             # open character class [...]
5640             elsif ($char[$i] eq '[') {
5641 0           my $left = $i;
5642              
5643             # [] make die "Unmatched [] in regexp ...\n"
5644             # (and so on)
5645              
5646 0 0         if ($char[$i+1] eq ']') {
5647 0           $i++;
5648             }
5649              
5650 0           while (1) {
5651 0 0         if (++$i > $#char) {
5652 0           die __FILE__, ": Unmatched [] in regexp\n";
5653             }
5654 0 0         if ($char[$i] eq ']') {
5655 0           my $right = $i;
5656              
5657             # [...]
5658 0 0         if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
5659 0           splice @char, $left, $right-$left+1, sprintf(q{@{[Ekoi8r::charlist_qr(%s,'%s')]}}, join(',', map {qq_stuff($delimiter,$end_delimiter,$_)} @char[$left+1..$right-1]), $modifier);
  0            
5660             }
5661             else {
5662 0           splice @char, $left, $right-$left+1, Ekoi8r::charlist_qr(@char[$left+1..$right-1], $modifier);
5663             }
5664              
5665 0           $i = $left;
5666 0           last;
5667             }
5668             }
5669             }
5670              
5671             # open character class [^...]
5672             elsif ($char[$i] eq '[^') {
5673 0           my $left = $i;
5674              
5675             # [^] make die "Unmatched [] in regexp ...\n"
5676             # (and so on)
5677              
5678 0 0         if ($char[$i+1] eq ']') {
5679 0           $i++;
5680             }
5681              
5682 0           while (1) {
5683 0 0         if (++$i > $#char) {
5684 0           die __FILE__, ": Unmatched [] in regexp\n";
5685             }
5686 0 0         if ($char[$i] eq ']') {
5687 0           my $right = $i;
5688              
5689             # [^...]
5690 0 0         if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
5691 0           splice @char, $left, $right-$left+1, sprintf(q{@{[Ekoi8r::charlist_not_qr(%s,'%s')]}}, join(',', map {qq_stuff($delimiter,$end_delimiter,$_)} @char[$left+1..$right-1]), $modifier);
  0            
5692             }
5693             else {
5694 0           splice @char, $left, $right-$left+1, Ekoi8r::charlist_not_qr(@char[$left+1..$right-1], $modifier);
5695             }
5696              
5697 0           $i = $left;
5698 0           last;
5699             }
5700             }
5701             }
5702              
5703             # rewrite character class or escape character
5704             elsif (my $char = character_class($char[$i],$modifier)) {
5705 0           $char[$i] = $char;
5706             }
5707              
5708             # /i modifier
5709             elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Ekoi8r::uc($char[$i]) ne Ekoi8r::fc($char[$i]))) {
5710 0 0         if (CORE::length(Ekoi8r::fc($char[$i])) == 1) {
5711 0           $char[$i] = '[' . Ekoi8r::uc($char[$i]) . Ekoi8r::fc($char[$i]) . ']';
5712             }
5713             else {
5714 0           $char[$i] = '(?:' . Ekoi8r::uc($char[$i]) . '|' . Ekoi8r::fc($char[$i]) . ')';
5715             }
5716             }
5717              
5718             # \u \l \U \L \F \Q \E
5719             elsif ($char[$i] =~ /\A [<>] \z/oxms) {
5720 0 0         if ($right_e < $left_e) {
5721 0           $char[$i] = '\\' . $char[$i];
5722             }
5723             }
5724             elsif ($char[$i] eq '\u') {
5725 0           $char[$i] = '@{[Ekoi8r::ucfirst qq<';
5726 0           $left_e++;
5727             }
5728             elsif ($char[$i] eq '\l') {
5729 0           $char[$i] = '@{[Ekoi8r::lcfirst qq<';
5730 0           $left_e++;
5731             }
5732             elsif ($char[$i] eq '\U') {
5733 0           $char[$i] = '@{[Ekoi8r::uc qq<';
5734 0           $left_e++;
5735             }
5736             elsif ($char[$i] eq '\L') {
5737 0           $char[$i] = '@{[Ekoi8r::lc qq<';
5738 0           $left_e++;
5739             }
5740             elsif ($char[$i] eq '\F') {
5741 0           $char[$i] = '@{[Ekoi8r::fc qq<';
5742 0           $left_e++;
5743             }
5744             elsif ($char[$i] eq '\Q') {
5745 0           $char[$i] = '@{[CORE::quotemeta qq<';
5746 0           $left_e++;
5747             }
5748             elsif ($char[$i] eq '\E') {
5749 0 0         if ($right_e < $left_e) {
5750 0           $char[$i] = '>]}';
5751 0           $right_e++;
5752             }
5753             else {
5754 0           $char[$i] = '';
5755             }
5756             }
5757             elsif ($char[$i] eq '\Q') {
5758 0           while (1) {
5759 0 0         if (++$i > $#char) {
5760 0           last;
5761             }
5762 0 0         if ($char[$i] eq '\E') {
5763 0           last;
5764             }
5765             }
5766             }
5767             elsif ($char[$i] eq '\E') {
5768             }
5769              
5770             # $0 --> $0
5771             elsif ($char[$i] =~ /\A \$ 0 \z/oxms) {
5772 0 0         if ($ignorecase) {
5773 0           $char[$i] = '@{[Ekoi8r::ignorecase(' . $char[$i] . ')]}';
5774             }
5775             }
5776             elsif ($char[$i] =~ /\A \$ \{ (?>\s*) 0 (?>\s*) \} \z/oxms) {
5777 0 0         if ($ignorecase) {
5778 0           $char[$i] = '@{[Ekoi8r::ignorecase(' . $char[$i] . ')]}';
5779             }
5780             }
5781              
5782             # $$ --> $$
5783             elsif ($char[$i] =~ /\A \$\$ \z/oxms) {
5784             }
5785              
5786             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
5787             # $1, $2, $3 --> $1, $2, $3 otherwise
5788             elsif ($char[$i] =~ /\A \$ ((?>[1-9][0-9]*)) \z/oxms) {
5789 0           $char[$i] = e_capture($1);
5790 0 0         if ($ignorecase) {
5791 0           $char[$i] = '@{[Ekoi8r::ignorecase(' . $char[$i] . ')]}';
5792             }
5793             }
5794             elsif ($char[$i] =~ /\A \$ \{ (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} \z/oxms) {
5795 0           $char[$i] = e_capture($1);
5796 0 0         if ($ignorecase) {
5797 0           $char[$i] = '@{[Ekoi8r::ignorecase(' . $char[$i] . ')]}';
5798             }
5799             }
5800              
5801             # $$foo[ ... ] --> $ $foo->[ ... ]
5802             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \[ (?:$qq_bracket)*? \] ) \z/oxms) {
5803 0           $char[$i] = e_capture($1.'->'.$2);
5804 0 0         if ($ignorecase) {
5805 0           $char[$i] = '@{[Ekoi8r::ignorecase(' . $char[$i] . ')]}';
5806             }
5807             }
5808              
5809             # $$foo{ ... } --> $ $foo->{ ... }
5810             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \{ (?:$qq_brace)*? \} ) \z/oxms) {
5811 0           $char[$i] = e_capture($1.'->'.$2);
5812 0 0         if ($ignorecase) {
5813 0           $char[$i] = '@{[Ekoi8r::ignorecase(' . $char[$i] . ')]}';
5814             }
5815             }
5816              
5817             # $$foo
5818             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) \z/oxms) {
5819 0           $char[$i] = e_capture($1);
5820 0 0         if ($ignorecase) {
5821 0           $char[$i] = '@{[Ekoi8r::ignorecase(' . $char[$i] . ')]}';
5822             }
5823             }
5824              
5825             # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Ekoi8r::PREMATCH()
5826             elsif ($char[$i] =~ /\A ( \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} ) \z/oxmsgc) {
5827 0 0         if ($ignorecase) {
5828 0           $char[$i] = '@{[Ekoi8r::ignorecase(Ekoi8r::PREMATCH())]}';
5829             }
5830             else {
5831 0           $char[$i] = '@{[Ekoi8r::PREMATCH()]}';
5832             }
5833             }
5834              
5835             # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Ekoi8r::MATCH()
5836             elsif ($char[$i] =~ /\A ( \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} ) \z/oxmsgc) {
5837 0 0         if ($ignorecase) {
5838 0           $char[$i] = '@{[Ekoi8r::ignorecase(Ekoi8r::MATCH())]}';
5839             }
5840             else {
5841 0           $char[$i] = '@{[Ekoi8r::MATCH()]}';
5842             }
5843             }
5844              
5845             # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Ekoi8r::POSTMATCH()
5846             elsif ($char[$i] =~ /\A ( \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} ) \z/oxmsgc) {
5847 0 0         if ($ignorecase) {
5848 0           $char[$i] = '@{[Ekoi8r::ignorecase(Ekoi8r::POSTMATCH())]}';
5849             }
5850             else {
5851 0           $char[$i] = '@{[Ekoi8r::POSTMATCH()]}';
5852             }
5853             }
5854              
5855             # ${ foo }
5856             elsif ($char[$i] =~ /\A \$ (?>\s*) \{ ((?> \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* )) \} \z/oxms) {
5857 0 0         if ($ignorecase) {
5858 0           $char[$i] = '@{[Ekoi8r::ignorecase(' . $char[$i] . ')]}';
5859             }
5860             }
5861              
5862             # ${ ... }
5863             elsif ($char[$i] =~ /\A \$ (?>\s*) \{ ( .+ ) \} \z/oxms) {
5864 0           $char[$i] = e_capture($1);
5865 0 0         if ($ignorecase) {
5866 0           $char[$i] = '@{[Ekoi8r::ignorecase(' . $char[$i] . ')]}';
5867             }
5868             }
5869              
5870             # $scalar or @array
5871             elsif ($char[$i] =~ /\A [\$\@].+ /oxms) {
5872 0           $char[$i] = e_string($char[$i]);
5873 0 0         if ($ignorecase) {
5874 0           $char[$i] = '@{[Ekoi8r::ignorecase(' . $char[$i] . ')]}';
5875             }
5876             }
5877              
5878             # quote character before ? + * {
5879             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
5880 0 0 0       if ($char[$i-1] =~ /\A (?:[\x00-\xFF]|\\[0-7]{2,3}|\\x[0-9-A-Fa-f]{1,2}) \z/oxms) {
    0          
5881             }
5882             elsif (($ope =~ /\A m? \z/oxms) and ($delimiter eq '?')) {
5883 0           my $char = $char[$i-1];
5884 0 0         if ($char[$i] eq '{') {
5885 0           die __FILE__, qq{: "MULTIBYTE{n}" should be "(MULTIBYTE){n}" in m?? (and shift \$1,\$2,\$3,...) ($char){n}\n};
5886             }
5887             else {
5888 0           die __FILE__, qq{: "MULTIBYTE$char[$i]" should be "(MULTIBYTE)$char[$i]" in m?? (and shift \$1,\$2,\$3,...) ($char)$char[$i]\n};
5889             }
5890             }
5891             else {
5892 0           $char[$i-1] = '(?:' . $char[$i-1] . ')';
5893             }
5894             }
5895             }
5896              
5897             # make regexp string
5898 0           $modifier =~ tr/i//d;
5899 0 0         if ($left_e > $right_e) {
5900 0 0 0       if (($ope =~ /\A m? \z/oxms) and ($delimiter eq '?')) {
5901 0           return join '', $ope, $delimiter, $anchor, @char, '>]}' x ($left_e - $right_e), $matched, $end_delimiter, $modifier;
5902             }
5903             else {
5904 0           return join '', $ope, $delimiter, $anchor, '(?:', @char, '>]}' x ($left_e - $right_e), ')', $matched, $end_delimiter, $modifier;
5905             }
5906             }
5907 0 0 0       if (($ope =~ /\A m? \z/oxms) and ($delimiter eq '?')) {
5908 0           return join '', $ope, $delimiter, $anchor, @char, $matched, $end_delimiter, $modifier;
5909             }
5910             else {
5911 0           return join '', $ope, $delimiter, $anchor, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
5912             }
5913             }
5914              
5915             #
5916             # double quote stuff
5917             #
5918             sub qq_stuff {
5919 0     0 0   my($delimiter,$end_delimiter,$stuff) = @_;
5920              
5921             # scalar variable or array variable
5922 0 0         if ($stuff =~ /\A [\$\@] /oxms) {
5923 0           return $stuff;
5924             }
5925              
5926             # quote by delimiter
5927 0           my %octet = map {$_ => 1} ($stuff =~ /\G ([\x00-\xFF]) /oxmsg);
  0            
5928 0           for my $char (qw( ! " $ % & * + - . / : = ? @ ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
5929 0 0         next if $char eq $delimiter;
5930 0 0         next if $char eq $end_delimiter;
5931 0 0         if (not $octet{$char}) {
5932 0           return join '', 'qq', $char, $stuff, $char;
5933             }
5934             }
5935 0           return join '', 'qq', '<', $stuff, '>';
5936             }
5937              
5938             #
5939             # escape regexp (m'', qr'', and m''b, qr''b)
5940             #
5941             sub e_qr_q {
5942 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
5943 0   0       $modifier ||= '';
5944              
5945 0           $modifier =~ tr/p//d;
5946 0 0         if ($modifier =~ /([adlu])/oxms) {
5947 0           my $line = 0;
5948 0           for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
5949 0 0         if ($filename ne __FILE__) {
5950 0           $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
5951 0           last;
5952             }
5953             }
5954 0           die qq{Unsupported modifier "$1" used at line $line.\n};
5955             }
5956              
5957 0           $slash = 'div';
5958              
5959             # literal null string pattern
5960 0 0         if ($string eq '') {
    0          
5961 0           $modifier =~ tr/bB//d;
5962 0           $modifier =~ tr/i//d;
5963 0           return join '', $ope, $delimiter, $end_delimiter, $modifier;
5964             }
5965              
5966             # with /b /B modifier
5967             elsif ($modifier =~ tr/bB//d) {
5968 0           return e_qr_qb($ope,$delimiter,$end_delimiter,$string,$modifier);
5969             }
5970              
5971             # without /b /B modifier
5972             else {
5973 0           return e_qr_qt($ope,$delimiter,$end_delimiter,$string,$modifier);
5974             }
5975             }
5976              
5977             #
5978             # escape regexp (m'', qr'')
5979             #
5980             sub e_qr_qt {
5981 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
5982              
5983 0 0         my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
5984              
5985             # split regexp
5986 0           my @char = $string =~ /\G((?>
5987             [^\\\[\$\@\/] |
5988             [\x00-\xFF] |
5989             \[\^ |
5990             \[\: (?>[a-z]+) \:\] |
5991             \[\:\^ (?>[a-z]+) \:\] |
5992             [\$\@\/] |
5993             \\ (?:$q_char) |
5994             (?:$q_char)
5995             ))/oxmsg;
5996              
5997             # unescape character
5998 0           for (my $i=0; $i <= $#char; $i++) {
5999 0 0 0       if (0) {
    0 0        
    0 0        
    0          
    0          
    0          
6000             }
6001              
6002             # open character class [...]
6003 0           elsif ($char[$i] eq '[') {
6004 0           my $left = $i;
6005 0 0         if ($char[$i+1] eq ']') {
6006 0           $i++;
6007             }
6008 0           while (1) {
6009 0 0         if (++$i > $#char) {
6010 0           die __FILE__, ": Unmatched [] in regexp\n";
6011             }
6012 0 0         if ($char[$i] eq ']') {
6013 0           my $right = $i;
6014              
6015             # [...]
6016 0           splice @char, $left, $right-$left+1, Ekoi8r::charlist_qr(@char[$left+1..$right-1], $modifier);
6017              
6018 0           $i = $left;
6019 0           last;
6020             }
6021             }
6022             }
6023              
6024             # open character class [^...]
6025             elsif ($char[$i] eq '[^') {
6026 0           my $left = $i;
6027 0 0         if ($char[$i+1] eq ']') {
6028 0           $i++;
6029             }
6030 0           while (1) {
6031 0 0         if (++$i > $#char) {
6032 0           die __FILE__, ": Unmatched [] in regexp\n";
6033             }
6034 0 0         if ($char[$i] eq ']') {
6035 0           my $right = $i;
6036              
6037             # [^...]
6038 0           splice @char, $left, $right-$left+1, Ekoi8r::charlist_not_qr(@char[$left+1..$right-1], $modifier);
6039              
6040 0           $i = $left;
6041 0           last;
6042             }
6043             }
6044             }
6045              
6046             # escape $ @ / and \
6047             elsif ($char[$i] =~ /\A [\$\@\/\\] \z/oxms) {
6048 0           $char[$i] = '\\' . $char[$i];
6049             }
6050              
6051             # rewrite character class or escape character
6052             elsif (my $char = character_class($char[$i],$modifier)) {
6053 0           $char[$i] = $char;
6054             }
6055              
6056             # /i modifier
6057             elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Ekoi8r::uc($char[$i]) ne Ekoi8r::fc($char[$i]))) {
6058 0 0         if (CORE::length(Ekoi8r::fc($char[$i])) == 1) {
6059 0           $char[$i] = '[' . Ekoi8r::uc($char[$i]) . Ekoi8r::fc($char[$i]) . ']';
6060             }
6061             else {
6062 0           $char[$i] = '(?:' . Ekoi8r::uc($char[$i]) . '|' . Ekoi8r::fc($char[$i]) . ')';
6063             }
6064             }
6065              
6066             # quote character before ? + * {
6067             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
6068 0 0         if ($char[$i-1] =~ /\A [\x00-\xFF] \z/oxms) {
6069             }
6070             else {
6071 0           $char[$i-1] = '(?:' . $char[$i-1] . ')';
6072             }
6073             }
6074             }
6075              
6076 0           $delimiter = '/';
6077 0           $end_delimiter = '/';
6078              
6079 0           $modifier =~ tr/i//d;
6080 0           return join '', $ope, $delimiter, $anchor, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
6081             }
6082              
6083             #
6084             # escape regexp (m''b, qr''b)
6085             #
6086             sub e_qr_qb {
6087 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6088              
6089             # split regexp
6090 0           my @char = $string =~ /\G ((?>[^\\]|\\\\)) /oxmsg;
6091              
6092             # unescape character
6093 0           for (my $i=0; $i <= $#char; $i++) {
6094 0 0         if (0) {
    0          
6095             }
6096              
6097             # remain \\
6098 0           elsif ($char[$i] eq '\\\\') {
6099             }
6100              
6101             # escape $ @ / and \
6102             elsif ($char[$i] =~ /\A [\$\@\/\\] \z/oxms) {
6103 0           $char[$i] = '\\' . $char[$i];
6104             }
6105             }
6106              
6107 0           $delimiter = '/';
6108 0           $end_delimiter = '/';
6109 0           return join '', $ope, $delimiter, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
6110             }
6111              
6112             #
6113             # escape regexp (s/here//)
6114             #
6115             sub e_s1 {
6116 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6117 0   0       $modifier ||= '';
6118              
6119 0           $modifier =~ tr/p//d;
6120 0 0         if ($modifier =~ /([adlu])/oxms) {
6121 0           my $line = 0;
6122 0           for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
6123 0 0         if ($filename ne __FILE__) {
6124 0           $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
6125 0           last;
6126             }
6127             }
6128 0           die qq{Unsupported modifier "$1" used at line $line.\n};
6129             }
6130              
6131 0           $slash = 'div';
6132              
6133             # literal null string pattern
6134 0 0         if ($string eq '') {
    0          
6135 0           $modifier =~ tr/bB//d;
6136 0           $modifier =~ tr/i//d;
6137 0           return join '', $ope, $delimiter, $end_delimiter, $modifier;
6138             }
6139              
6140             # /b /B modifier
6141             elsif ($modifier =~ tr/bB//d) {
6142              
6143             # choice again delimiter
6144 0 0         if ($delimiter =~ / [\@:] /oxms) {
6145 0           my @char = $string =~ /\G ([\x00-\xFF]) /oxmsg;
6146 0           my %octet = map {$_ => 1} @char;
  0            
6147 0 0         if (not $octet{')'}) {
    0          
    0          
    0          
6148 0           $delimiter = '(';
6149 0           $end_delimiter = ')';
6150             }
6151             elsif (not $octet{'}'}) {
6152 0           $delimiter = '{';
6153 0           $end_delimiter = '}';
6154             }
6155             elsif (not $octet{']'}) {
6156 0           $delimiter = '[';
6157 0           $end_delimiter = ']';
6158             }
6159             elsif (not $octet{'>'}) {
6160 0           $delimiter = '<';
6161 0           $end_delimiter = '>';
6162             }
6163             else {
6164 0           for my $char (qw( ! " $ % & * + - . / = ? ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
6165 0 0         if (not $octet{$char}) {
6166 0           $delimiter = $char;
6167 0           $end_delimiter = $char;
6168 0           last;
6169             }
6170             }
6171             }
6172             }
6173              
6174 0           my $prematch = '';
6175 0           return join '', $ope, $delimiter, $prematch, '(?:', $string, ')', $matched, $end_delimiter, $modifier;
6176             }
6177              
6178 0 0         my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
6179 0           my $metachar = qr/[\@\\|[\]{^]/oxms;
6180              
6181             # split regexp
6182 0           my @char = $string =~ /\G((?>
6183             [^\\\$\@\[\(] |
6184             \\ (?>[1-9][0-9]*) |
6185             \\g (?>\s*) (?>[1-9][0-9]*) |
6186             \\g (?>\s*) \{ (?>\s*) (?>[1-9][0-9]*) (?>\s*) \} |
6187             \\g (?>\s*) \{ (?>\s*) - (?>\s*) (?>[1-9][0-9]*) (?>\s*) \} |
6188             \\x (?>[0-9A-Fa-f]{1,2}) |
6189             \\ (?>[0-7]{2,3}) |
6190             \\c [\x40-\x5F] |
6191             \\x\{ (?>[0-9A-Fa-f]+) \} |
6192             \\o\{ (?>[0-7]+) \} |
6193             \\[bBNpP]\{ (?>[^0-9\}][^\}]*) \} |
6194             \\ $q_char |
6195             \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} |
6196             \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} |
6197             \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} |
6198             [\$\@] $qq_variable |
6199             \$ (?>\s* [0-9]+) |
6200             \$ (?>\s*) \{ (?>\s* [0-9]+ \s*) \} |
6201             \$ \$ (?![\w\{]) |
6202             \$ (?>\s*) \$ (?>\s*) $qq_variable |
6203             \[\^ |
6204             \[\: (?>[a-z]+) :\] |
6205             \[\:\^ (?>[a-z]+) :\] |
6206             \(\? |
6207             $q_char
6208             ))/oxmsg;
6209              
6210             # choice again delimiter
6211 0 0         if ($delimiter =~ / [\@:] /oxms) {
6212 0           my %octet = map {$_ => 1} @char;
  0            
6213 0 0         if (not $octet{')'}) {
    0          
    0          
    0          
6214 0           $delimiter = '(';
6215 0           $end_delimiter = ')';
6216             }
6217             elsif (not $octet{'}'}) {
6218 0           $delimiter = '{';
6219 0           $end_delimiter = '}';
6220             }
6221             elsif (not $octet{']'}) {
6222 0           $delimiter = '[';
6223 0           $end_delimiter = ']';
6224             }
6225             elsif (not $octet{'>'}) {
6226 0           $delimiter = '<';
6227 0           $end_delimiter = '>';
6228             }
6229             else {
6230 0           for my $char (qw( ! " $ % & * + - . / = ? ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
6231 0 0         if (not $octet{$char}) {
6232 0           $delimiter = $char;
6233 0           $end_delimiter = $char;
6234 0           last;
6235             }
6236             }
6237             }
6238             }
6239              
6240             # count '('
6241 0           my $parens = grep { $_ eq '(' } @char;
  0            
6242              
6243 0           my $left_e = 0;
6244 0           my $right_e = 0;
6245 0           for (my $i=0; $i <= $#char; $i++) {
6246              
6247             # "\L\u" --> "\u\L"
6248 0 0 0       if (($char[$i] eq '\L') and ($char[$i+1] eq '\u')) {
    0 0        
    0          
    0          
    0          
    0          
6249 0           @char[$i,$i+1] = @char[$i+1,$i];
6250             }
6251              
6252             # "\U\l" --> "\l\U"
6253             elsif (($char[$i] eq '\U') and ($char[$i+1] eq '\l')) {
6254 0           @char[$i,$i+1] = @char[$i+1,$i];
6255             }
6256              
6257             # octal escape sequence
6258             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
6259 0           $char[$i] = Ekoi8r::octchr($1);
6260             }
6261              
6262             # hexadecimal escape sequence
6263             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
6264 0           $char[$i] = Ekoi8r::hexchr($1);
6265             }
6266              
6267             # \b{...} --> b\{...}
6268             # \B{...} --> B\{...}
6269             # \N{CHARNAME} --> N\{CHARNAME}
6270             # \p{PROPERTY} --> p\{PROPERTY}
6271             # \P{PROPERTY} --> P\{PROPERTY}
6272             elsif ($char[$i] =~ /\A \\ ([bBNpP]) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
6273 0           $char[$i] = $1 . '\\' . $2;
6274             }
6275              
6276             # \p, \P, \X --> p, P, X
6277             elsif ($char[$i] =~ /\A \\ ( [pPX] ) \z/oxms) {
6278 0           $char[$i] = $1;
6279             }
6280              
6281 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          
6282             }
6283              
6284             # join separated multiple-octet
6285 0           elsif ($char[$i] =~ /\A (?: \\ [0-7]{2,3} | \\x [0-9A-Fa-f]{1,2}) \z/oxms) {
6286 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        
6287 0           $char[$i] .= join '', splice @char, $i+1, 3;
6288             }
6289             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)) {
6290 0           $char[$i] .= join '', splice @char, $i+1, 2;
6291             }
6292             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)) {
6293 0           $char[$i] .= join '', splice @char, $i+1, 1;
6294             }
6295             }
6296              
6297             # open character class [...]
6298             elsif ($char[$i] eq '[') {
6299 0           my $left = $i;
6300 0 0         if ($char[$i+1] eq ']') {
6301 0           $i++;
6302             }
6303 0           while (1) {
6304 0 0         if (++$i > $#char) {
6305 0           die __FILE__, ": Unmatched [] in regexp\n";
6306             }
6307 0 0         if ($char[$i] eq ']') {
6308 0           my $right = $i;
6309              
6310             # [...]
6311 0 0         if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
6312 0           splice @char, $left, $right-$left+1, sprintf(q{@{[Ekoi8r::charlist_qr(%s,'%s')]}}, join(',', map {qq_stuff($delimiter,$end_delimiter,$_)} @char[$left+1..$right-1]), $modifier);
  0            
6313             }
6314             else {
6315 0           splice @char, $left, $right-$left+1, Ekoi8r::charlist_qr(@char[$left+1..$right-1], $modifier);
6316             }
6317              
6318 0           $i = $left;
6319 0           last;
6320             }
6321             }
6322             }
6323              
6324             # open character class [^...]
6325             elsif ($char[$i] eq '[^') {
6326 0           my $left = $i;
6327 0 0         if ($char[$i+1] eq ']') {
6328 0           $i++;
6329             }
6330 0           while (1) {
6331 0 0         if (++$i > $#char) {
6332 0           die __FILE__, ": Unmatched [] in regexp\n";
6333             }
6334 0 0         if ($char[$i] eq ']') {
6335 0           my $right = $i;
6336              
6337             # [^...]
6338 0 0         if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
6339 0           splice @char, $left, $right-$left+1, sprintf(q{@{[Ekoi8r::charlist_not_qr(%s,'%s')]}}, join(',', map {qq_stuff($delimiter,$end_delimiter,$_)} @char[$left+1..$right-1]), $modifier);
  0            
6340             }
6341             else {
6342 0           splice @char, $left, $right-$left+1, Ekoi8r::charlist_not_qr(@char[$left+1..$right-1], $modifier);
6343             }
6344              
6345 0           $i = $left;
6346 0           last;
6347             }
6348             }
6349             }
6350              
6351             # rewrite character class or escape character
6352             elsif (my $char = character_class($char[$i],$modifier)) {
6353 0           $char[$i] = $char;
6354             }
6355              
6356             # /i modifier
6357             elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Ekoi8r::uc($char[$i]) ne Ekoi8r::fc($char[$i]))) {
6358 0 0         if (CORE::length(Ekoi8r::fc($char[$i])) == 1) {
6359 0           $char[$i] = '[' . Ekoi8r::uc($char[$i]) . Ekoi8r::fc($char[$i]) . ']';
6360             }
6361             else {
6362 0           $char[$i] = '(?:' . Ekoi8r::uc($char[$i]) . '|' . Ekoi8r::fc($char[$i]) . ')';
6363             }
6364             }
6365              
6366             # \u \l \U \L \F \Q \E
6367             elsif ($char[$i] =~ /\A [<>] \z/oxms) {
6368 0 0         if ($right_e < $left_e) {
6369 0           $char[$i] = '\\' . $char[$i];
6370             }
6371             }
6372             elsif ($char[$i] eq '\u') {
6373 0           $char[$i] = '@{[Ekoi8r::ucfirst qq<';
6374 0           $left_e++;
6375             }
6376             elsif ($char[$i] eq '\l') {
6377 0           $char[$i] = '@{[Ekoi8r::lcfirst qq<';
6378 0           $left_e++;
6379             }
6380             elsif ($char[$i] eq '\U') {
6381 0           $char[$i] = '@{[Ekoi8r::uc qq<';
6382 0           $left_e++;
6383             }
6384             elsif ($char[$i] eq '\L') {
6385 0           $char[$i] = '@{[Ekoi8r::lc qq<';
6386 0           $left_e++;
6387             }
6388             elsif ($char[$i] eq '\F') {
6389 0           $char[$i] = '@{[Ekoi8r::fc qq<';
6390 0           $left_e++;
6391             }
6392             elsif ($char[$i] eq '\Q') {
6393 0           $char[$i] = '@{[CORE::quotemeta qq<';
6394 0           $left_e++;
6395             }
6396             elsif ($char[$i] eq '\E') {
6397 0 0         if ($right_e < $left_e) {
6398 0           $char[$i] = '>]}';
6399 0           $right_e++;
6400             }
6401             else {
6402 0           $char[$i] = '';
6403             }
6404             }
6405             elsif ($char[$i] eq '\Q') {
6406 0           while (1) {
6407 0 0         if (++$i > $#char) {
6408 0           last;
6409             }
6410 0 0         if ($char[$i] eq '\E') {
6411 0           last;
6412             }
6413             }
6414             }
6415             elsif ($char[$i] eq '\E') {
6416             }
6417              
6418             # \0 --> \0
6419             elsif ($char[$i] =~ /\A \\ (?>\s*) 0 \z/oxms) {
6420             }
6421              
6422             # \g{N}, \g{-N}
6423              
6424             # P.108 Using Simple Patterns
6425             # in Chapter 7: In the World of Regular Expressions
6426             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
6427              
6428             # P.221 Capturing
6429             # in Chapter 5: Pattern Matching
6430             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
6431              
6432             # \g{-1}, \g{-2}, \g{-3} --> \g{-1}, \g{-2}, \g{-3}
6433             elsif ($char[$i] =~ /\A \\g (?>\s*) \{ (?>\s*) - (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} \z/oxms) {
6434             }
6435              
6436             # \g{1}, \g{2}, \g{3} --> \g{2}, \g{3}, \g{4} (only when multibyte anchoring is enable)
6437             elsif ($char[$i] =~ /\A \\g (?>\s*) \{ (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} \z/oxms) {
6438             }
6439              
6440             # \g1, \g2, \g3 --> \g2, \g3, \g4 (only when multibyte anchoring is enable)
6441             elsif ($char[$i] =~ /\A \\g (?>\s*) ((?>[1-9][0-9]*)) \z/oxms) {
6442             }
6443              
6444             # \1, \2, \3 --> \2, \3, \4 (only when multibyte anchoring is enable)
6445             elsif ($char[$i] =~ /\A \\ (?>\s*) ((?>[1-9][0-9]*)) \z/oxms) {
6446             }
6447              
6448             # $0 --> $0
6449             elsif ($char[$i] =~ /\A \$ 0 \z/oxms) {
6450 0 0         if ($ignorecase) {
6451 0           $char[$i] = '@{[Ekoi8r::ignorecase(' . $char[$i] . ')]}';
6452             }
6453             }
6454             elsif ($char[$i] =~ /\A \$ \{ (?>\s*) 0 (?>\s*) \} \z/oxms) {
6455 0 0         if ($ignorecase) {
6456 0           $char[$i] = '@{[Ekoi8r::ignorecase(' . $char[$i] . ')]}';
6457             }
6458             }
6459              
6460             # $$ --> $$
6461             elsif ($char[$i] =~ /\A \$\$ \z/oxms) {
6462             }
6463              
6464             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
6465             # $1, $2, $3 --> $1, $2, $3 otherwise
6466             elsif ($char[$i] =~ /\A \$ ((?>[1-9][0-9]*)) \z/oxms) {
6467 0           $char[$i] = e_capture($1);
6468 0 0         if ($ignorecase) {
6469 0           $char[$i] = '@{[Ekoi8r::ignorecase(' . $char[$i] . ')]}';
6470             }
6471             }
6472             elsif ($char[$i] =~ /\A \$ \{ (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} \z/oxms) {
6473 0           $char[$i] = e_capture($1);
6474 0 0         if ($ignorecase) {
6475 0           $char[$i] = '@{[Ekoi8r::ignorecase(' . $char[$i] . ')]}';
6476             }
6477             }
6478              
6479             # $$foo[ ... ] --> $ $foo->[ ... ]
6480             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \[ (?:$qq_bracket)*? \] ) \z/oxms) {
6481 0           $char[$i] = e_capture($1.'->'.$2);
6482 0 0         if ($ignorecase) {
6483 0           $char[$i] = '@{[Ekoi8r::ignorecase(' . $char[$i] . ')]}';
6484             }
6485             }
6486              
6487             # $$foo{ ... } --> $ $foo->{ ... }
6488             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \{ (?:$qq_brace)*? \} ) \z/oxms) {
6489 0           $char[$i] = e_capture($1.'->'.$2);
6490 0 0         if ($ignorecase) {
6491 0           $char[$i] = '@{[Ekoi8r::ignorecase(' . $char[$i] . ')]}';
6492             }
6493             }
6494              
6495             # $$foo
6496             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) \z/oxms) {
6497 0           $char[$i] = e_capture($1);
6498 0 0         if ($ignorecase) {
6499 0           $char[$i] = '@{[Ekoi8r::ignorecase(' . $char[$i] . ')]}';
6500             }
6501             }
6502              
6503             # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Ekoi8r::PREMATCH()
6504             elsif ($char[$i] =~ /\A ( \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} ) \z/oxmsgc) {
6505 0 0         if ($ignorecase) {
6506 0           $char[$i] = '@{[Ekoi8r::ignorecase(Ekoi8r::PREMATCH())]}';
6507             }
6508             else {
6509 0           $char[$i] = '@{[Ekoi8r::PREMATCH()]}';
6510             }
6511             }
6512              
6513             # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Ekoi8r::MATCH()
6514             elsif ($char[$i] =~ /\A ( \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} ) \z/oxmsgc) {
6515 0 0         if ($ignorecase) {
6516 0           $char[$i] = '@{[Ekoi8r::ignorecase(Ekoi8r::MATCH())]}';
6517             }
6518             else {
6519 0           $char[$i] = '@{[Ekoi8r::MATCH()]}';
6520             }
6521             }
6522              
6523             # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Ekoi8r::POSTMATCH()
6524             elsif ($char[$i] =~ /\A ( \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} ) \z/oxmsgc) {
6525 0 0         if ($ignorecase) {
6526 0           $char[$i] = '@{[Ekoi8r::ignorecase(Ekoi8r::POSTMATCH())]}';
6527             }
6528             else {
6529 0           $char[$i] = '@{[Ekoi8r::POSTMATCH()]}';
6530             }
6531             }
6532              
6533             # ${ foo }
6534             elsif ($char[$i] =~ /\A \$ (?>\s*) \{ ((?> \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* )) \} \z/oxms) {
6535 0 0         if ($ignorecase) {
6536 0           $char[$i] = '@{[Ekoi8r::ignorecase(' . $char[$i] . ')]}';
6537             }
6538             }
6539              
6540             # ${ ... }
6541             elsif ($char[$i] =~ /\A \$ (?>\s*) \{ ( .+ ) \} \z/oxms) {
6542 0           $char[$i] = e_capture($1);
6543 0 0         if ($ignorecase) {
6544 0           $char[$i] = '@{[Ekoi8r::ignorecase(' . $char[$i] . ')]}';
6545             }
6546             }
6547              
6548             # $scalar or @array
6549             elsif ($char[$i] =~ /\A [\$\@].+ /oxms) {
6550 0           $char[$i] = e_string($char[$i]);
6551 0 0         if ($ignorecase) {
6552 0           $char[$i] = '@{[Ekoi8r::ignorecase(' . $char[$i] . ')]}';
6553             }
6554             }
6555              
6556             # quote character before ? + * {
6557             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
6558 0 0         if ($char[$i-1] =~ /\A (?:[\x00-\xFF]|\\[0-7]{2,3}|\\x[0-9-A-Fa-f]{1,2}) \z/oxms) {
6559             }
6560             else {
6561 0           $char[$i-1] = '(?:' . $char[$i-1] . ')';
6562             }
6563             }
6564             }
6565              
6566             # make regexp string
6567 0           my $prematch = '';
6568 0           $modifier =~ tr/i//d;
6569 0 0         if ($left_e > $right_e) {
6570 0           return join '', $ope, $delimiter, $prematch, '(?:', @char, '>]}' x ($left_e - $right_e), ')', $matched, $end_delimiter, $modifier;
6571             }
6572 0           return join '', $ope, $delimiter, $prematch, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
6573             }
6574              
6575             #
6576             # escape regexp (s'here'' or s'here''b)
6577             #
6578             sub e_s1_q {
6579 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6580 0   0       $modifier ||= '';
6581              
6582 0           $modifier =~ tr/p//d;
6583 0 0         if ($modifier =~ /([adlu])/oxms) {
6584 0           my $line = 0;
6585 0           for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
6586 0 0         if ($filename ne __FILE__) {
6587 0           $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
6588 0           last;
6589             }
6590             }
6591 0           die qq{Unsupported modifier "$1" used at line $line.\n};
6592             }
6593              
6594 0           $slash = 'div';
6595              
6596             # literal null string pattern
6597 0 0         if ($string eq '') {
    0          
6598 0           $modifier =~ tr/bB//d;
6599 0           $modifier =~ tr/i//d;
6600 0           return join '', $ope, $delimiter, $end_delimiter, $modifier;
6601             }
6602              
6603             # with /b /B modifier
6604             elsif ($modifier =~ tr/bB//d) {
6605 0           return e_s1_qb($ope,$delimiter,$end_delimiter,$string,$modifier);
6606             }
6607              
6608             # without /b /B modifier
6609             else {
6610 0           return e_s1_qt($ope,$delimiter,$end_delimiter,$string,$modifier);
6611             }
6612             }
6613              
6614             #
6615             # escape regexp (s'here'')
6616             #
6617             sub e_s1_qt {
6618 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6619              
6620 0 0         my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
6621              
6622             # split regexp
6623 0           my @char = $string =~ /\G((?>
6624             [^\\\[\$\@\/] |
6625             [\x00-\xFF] |
6626             \[\^ |
6627             \[\: (?>[a-z]+) \:\] |
6628             \[\:\^ (?>[a-z]+) \:\] |
6629             [\$\@\/] |
6630             \\ (?:$q_char) |
6631             (?:$q_char)
6632             ))/oxmsg;
6633              
6634             # unescape character
6635 0           for (my $i=0; $i <= $#char; $i++) {
6636 0 0 0       if (0) {
    0 0        
    0 0        
    0          
    0          
    0          
6637             }
6638              
6639             # open character class [...]
6640 0           elsif ($char[$i] eq '[') {
6641 0           my $left = $i;
6642 0 0         if ($char[$i+1] eq ']') {
6643 0           $i++;
6644             }
6645 0           while (1) {
6646 0 0         if (++$i > $#char) {
6647 0           die __FILE__, ": Unmatched [] in regexp\n";
6648             }
6649 0 0         if ($char[$i] eq ']') {
6650 0           my $right = $i;
6651              
6652             # [...]
6653 0           splice @char, $left, $right-$left+1, Ekoi8r::charlist_qr(@char[$left+1..$right-1], $modifier);
6654              
6655 0           $i = $left;
6656 0           last;
6657             }
6658             }
6659             }
6660              
6661             # open character class [^...]
6662             elsif ($char[$i] eq '[^') {
6663 0           my $left = $i;
6664 0 0         if ($char[$i+1] eq ']') {
6665 0           $i++;
6666             }
6667 0           while (1) {
6668 0 0         if (++$i > $#char) {
6669 0           die __FILE__, ": Unmatched [] in regexp\n";
6670             }
6671 0 0         if ($char[$i] eq ']') {
6672 0           my $right = $i;
6673              
6674             # [^...]
6675 0           splice @char, $left, $right-$left+1, Ekoi8r::charlist_not_qr(@char[$left+1..$right-1], $modifier);
6676              
6677 0           $i = $left;
6678 0           last;
6679             }
6680             }
6681             }
6682              
6683             # escape $ @ / and \
6684             elsif ($char[$i] =~ /\A [\$\@\/\\] \z/oxms) {
6685 0           $char[$i] = '\\' . $char[$i];
6686             }
6687              
6688             # rewrite character class or escape character
6689             elsif (my $char = character_class($char[$i],$modifier)) {
6690 0           $char[$i] = $char;
6691             }
6692              
6693             # /i modifier
6694             elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Ekoi8r::uc($char[$i]) ne Ekoi8r::fc($char[$i]))) {
6695 0 0         if (CORE::length(Ekoi8r::fc($char[$i])) == 1) {
6696 0           $char[$i] = '[' . Ekoi8r::uc($char[$i]) . Ekoi8r::fc($char[$i]) . ']';
6697             }
6698             else {
6699 0           $char[$i] = '(?:' . Ekoi8r::uc($char[$i]) . '|' . Ekoi8r::fc($char[$i]) . ')';
6700             }
6701             }
6702              
6703             # quote character before ? + * {
6704             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
6705 0 0         if ($char[$i-1] =~ /\A [\x00-\xFF] \z/oxms) {
6706             }
6707             else {
6708 0           $char[$i-1] = '(?:' . $char[$i-1] . ')';
6709             }
6710             }
6711             }
6712              
6713 0           $modifier =~ tr/i//d;
6714 0           $delimiter = '/';
6715 0           $end_delimiter = '/';
6716 0           my $prematch = '';
6717 0           return join '', $ope, $delimiter, $prematch, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
6718             }
6719              
6720             #
6721             # escape regexp (s'here''b)
6722             #
6723             sub e_s1_qb {
6724 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6725              
6726             # split regexp
6727 0           my @char = $string =~ /\G (?>[^\\]|\\\\) /oxmsg;
6728              
6729             # unescape character
6730 0           for (my $i=0; $i <= $#char; $i++) {
6731 0 0         if (0) {
    0          
6732             }
6733              
6734             # remain \\
6735 0           elsif ($char[$i] eq '\\\\') {
6736             }
6737              
6738             # escape $ @ / and \
6739             elsif ($char[$i] =~ /\A [\$\@\/\\] \z/oxms) {
6740 0           $char[$i] = '\\' . $char[$i];
6741             }
6742             }
6743              
6744 0           $delimiter = '/';
6745 0           $end_delimiter = '/';
6746 0           my $prematch = '';
6747 0           return join '', $ope, $delimiter, $prematch, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
6748             }
6749              
6750             #
6751             # escape regexp (s''here')
6752             #
6753             sub e_s2_q {
6754 0     0 0   my($ope,$delimiter,$end_delimiter,$string) = @_;
6755              
6756 0           $slash = 'div';
6757              
6758 0           my @char = $string =~ / \G (?>[^\\]|\\\\|$q_char) /oxmsg;
6759 0           for (my $i=0; $i <= $#char; $i++) {
6760 0 0         if (0) {
    0          
6761             }
6762              
6763             # not escape \\
6764 0           elsif ($char[$i] =~ /\A \\\\ \z/oxms) {
6765             }
6766              
6767             # escape $ @ / and \
6768             elsif ($char[$i] =~ /\A [\$\@\/\\] \z/oxms) {
6769 0           $char[$i] = '\\' . $char[$i];
6770             }
6771             }
6772              
6773 0           return join '', $ope, $delimiter, @char, $end_delimiter;
6774             }
6775              
6776             #
6777             # escape regexp (s/here/and here/modifier)
6778             #
6779             sub e_sub {
6780 0     0 0   my($variable,$delimiter1,$pattern,$end_delimiter1,$delimiter2,$replacement,$end_delimiter2,$modifier) = @_;
6781 0   0       $modifier ||= '';
6782              
6783 0           $modifier =~ tr/p//d;
6784 0 0         if ($modifier =~ /([adlu])/oxms) {
6785 0           my $line = 0;
6786 0           for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
6787 0 0         if ($filename ne __FILE__) {
6788 0           $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
6789 0           last;
6790             }
6791             }
6792 0           die qq{Unsupported modifier "$1" used at line $line.\n};
6793             }
6794              
6795 0 0         if ($variable eq '') {
6796 0           $variable = '$_';
6797 0           $bind_operator = ' =~ ';
6798             }
6799              
6800 0           $slash = 'div';
6801              
6802             # P.128 Start of match (or end of previous match): \G
6803             # P.130 Advanced Use of \G with Perl
6804             # in Chapter 3: Overview of Regular Expression Features and Flavors
6805             # P.312 Iterative Matching: Scalar Context, with /g
6806             # in Chapter 7: Perl
6807             # of ISBN 0-596-00289-0 Mastering Regular Expressions, Second edition
6808              
6809             # P.181 Where You Left Off: The \G Assertion
6810             # in Chapter 5: Pattern Matching
6811             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
6812              
6813             # P.220 Where You Left Off: The \G Assertion
6814             # in Chapter 5: Pattern Matching
6815             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
6816              
6817 0           my $e_modifier = $modifier =~ tr/e//d;
6818 0           my $r_modifier = $modifier =~ tr/r//d;
6819              
6820 0           my $my = '';
6821 0 0         if ($variable =~ s/\A \( (?>\s*) ( (?>(?: local \b | my \b | our \b | state \b )?) .+ ) \) \z/$1/oxms) {
6822 0           $my = $variable;
6823 0           $variable =~ s/ (?: local \b | my \b | our \b | state \b ) (?>\s*) //oxms;
6824 0           $variable =~ s/ = .+ \z//oxms;
6825             }
6826              
6827 0           (my $variable_basename = $variable) =~ s/ [\[\{].* \z//oxms;
6828 0           $variable_basename =~ s/ \s+ \z//oxms;
6829              
6830             # quote replacement string
6831 0           my $e_replacement = '';
6832 0 0         if ($e_modifier >= 1) {
6833 0           $e_replacement = e_qq('', '', '', $replacement);
6834 0           $e_modifier--;
6835             }
6836             else {
6837 0 0         if ($delimiter2 eq "'") {
6838 0           $e_replacement = e_s2_q('qq', '/', '/', $replacement);
6839             }
6840             else {
6841 0           $e_replacement = e_qq ('qq', $delimiter2, $end_delimiter2, $replacement);
6842             }
6843             }
6844              
6845 0           my $sub = '';
6846              
6847             # with /r
6848 0 0         if ($r_modifier) {
6849 0 0         if (0) {
6850             }
6851              
6852             # s///gr without multibyte anchoring
6853 0           elsif ($modifier =~ /g/oxms) {
6854 0 0         $sub = sprintf(
6855             # 1 2 3 4 5
6856             q,
6857              
6858             $variable, # 1
6859             ($delimiter1 eq "'") ? # 2
6860             e_s1_q('m', $delimiter1, $end_delimiter1, $pattern, $modifier) : # :
6861             e_s1 ('m', $delimiter1, $end_delimiter1, $pattern, $modifier), # :
6862             $s_matched, # 3
6863             $e_replacement, # 4
6864             '$KOI8R::re_r=CORE::eval $KOI8R::re_r; ' x $e_modifier, # 5
6865             );
6866             }
6867              
6868             # s///r
6869             else {
6870              
6871 0           my $prematch = q{$`};
6872              
6873 0 0         $sub = sprintf(
6874             # 1 2 3 4 5 6 7
6875             q<(%s =~ %s) ? CORE::eval{%s local $^W=0; local $KOI8R::re_r=%s; %s"%s$KOI8R::re_r$'" } : %s>,
6876              
6877             $variable, # 1
6878             ($delimiter1 eq "'") ? # 2
6879             e_s1_q('m', $delimiter1, $end_delimiter1, $pattern, $modifier) : # :
6880             e_s1 ('m', $delimiter1, $end_delimiter1, $pattern, $modifier), # :
6881             $s_matched, # 3
6882             $e_replacement, # 4
6883             '$KOI8R::re_r=CORE::eval $KOI8R::re_r; ' x $e_modifier, # 5
6884             $prematch, # 6
6885             $variable, # 7
6886             );
6887             }
6888              
6889             # $var !~ s///r doesn't make sense
6890 0 0         if ($bind_operator =~ / !~ /oxms) {
6891 0           $sub = q{die("$0: Using !~ with s///r doesn't make sense"), } . $sub;
6892             }
6893             }
6894              
6895             # without /r
6896             else {
6897 0 0         if (0) {
6898             }
6899              
6900             # s///g without multibyte anchoring
6901 0           elsif ($modifier =~ /g/oxms) {
6902 0 0         $sub = sprintf(
    0          
6903             # 1 2 3 4 5 6 7 8
6904             q,
6905              
6906             $variable, # 1
6907             ($delimiter1 eq "'") ? # 2
6908             e_s1_q('m', $delimiter1, $end_delimiter1, $pattern, $modifier) : # :
6909             e_s1 ('m', $delimiter1, $end_delimiter1, $pattern, $modifier), # :
6910             $s_matched, # 3
6911             $e_replacement, # 4
6912             '$KOI8R::re_r=CORE::eval $KOI8R::re_r; ' x $e_modifier, # 5
6913             $variable, # 6
6914             $variable, # 7
6915             ($bind_operator =~ / !~ /oxms) ? '!' : '', # 8
6916             );
6917             }
6918              
6919             # s///
6920             else {
6921              
6922 0           my $prematch = q{$`};
6923              
6924 0 0         $sub = sprintf(
    0          
6925              
6926             ($bind_operator =~ / =~ /oxms) ?
6927              
6928             # 1 2 3 4 5 6 7 8
6929             q<(%s%s%s) ? CORE::eval{%s local $^W=0; local $KOI8R::re_r=%s; %s%s="%s$KOI8R::re_r$'"; 1 } : undef> :
6930              
6931             # 1 2 3 4 5 6 7 8
6932             q<(%s%s%s) ? 1 : CORE::eval{%s local $^W=0; local $KOI8R::re_r=%s; %s%s="%s$KOI8R::re_r$'"; undef }>,
6933              
6934             $variable, # 1
6935             $bind_operator, # 2
6936             ($delimiter1 eq "'") ? # 3
6937             e_s1_q('m', $delimiter1, $end_delimiter1, $pattern, $modifier) : # :
6938             e_s1 ('m', $delimiter1, $end_delimiter1, $pattern, $modifier), # :
6939             $s_matched, # 4
6940             $e_replacement, # 5
6941             '$KOI8R::re_r=CORE::eval $KOI8R::re_r; ' x $e_modifier, # 6
6942             $variable, # 7
6943             $prematch, # 8
6944             );
6945             }
6946             }
6947              
6948             # (my $foo = $bar) =~ s/// --> (my $foo = $bar, CORE::eval { ... })[1]
6949 0 0         if ($my ne '') {
6950 0           $sub = "($my, $sub)[1]";
6951             }
6952              
6953             # clear s/// variable
6954 0           $sub_variable = '';
6955 0           $bind_operator = '';
6956              
6957 0           return $sub;
6958             }
6959              
6960             #
6961             # escape regexp of split qr//
6962             #
6963             sub e_split {
6964 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6965 0   0       $modifier ||= '';
6966              
6967 0           $modifier =~ tr/p//d;
6968 0 0         if ($modifier =~ /([adlu])/oxms) {
6969 0           my $line = 0;
6970 0           for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
6971 0 0         if ($filename ne __FILE__) {
6972 0           $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
6973 0           last;
6974             }
6975             }
6976 0           die qq{Unsupported modifier "$1" used at line $line.\n};
6977             }
6978              
6979 0           $slash = 'div';
6980              
6981             # /b /B modifier
6982 0 0         if ($modifier =~ tr/bB//d) {
6983 0           return join '', 'split', $ope, $delimiter, $string, $end_delimiter, $modifier;
6984             }
6985              
6986 0 0         my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
6987 0           my $metachar = qr/[\@\\|[\]{^]/oxms;
6988              
6989             # split regexp
6990 0           my @char = $string =~ /\G((?>
6991             [^\\\$\@\[\(] |
6992             \\x (?>[0-9A-Fa-f]{1,2}) |
6993             \\ (?>[0-7]{2,3}) |
6994             \\c [\x40-\x5F] |
6995             \\x\{ (?>[0-9A-Fa-f]+) \} |
6996             \\o\{ (?>[0-7]+) \} |
6997             \\[bBNpP]\{ (?>[^0-9\}][^\}]*) \} |
6998             \\ $q_char |
6999             \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} |
7000             \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} |
7001             \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} |
7002             [\$\@] $qq_variable |
7003             \$ (?>\s* [0-9]+) |
7004             \$ (?>\s*) \{ (?>\s* [0-9]+ \s*) \} |
7005             \$ \$ (?![\w\{]) |
7006             \$ (?>\s*) \$ (?>\s*) $qq_variable |
7007             \[\^ |
7008             \[\: (?>[a-z]+) :\] |
7009             \[\:\^ (?>[a-z]+) :\] |
7010             \(\? |
7011             $q_char
7012             ))/oxmsg;
7013              
7014 0           my $left_e = 0;
7015 0           my $right_e = 0;
7016 0           for (my $i=0; $i <= $#char; $i++) {
7017              
7018             # "\L\u" --> "\u\L"
7019 0 0 0       if (($char[$i] eq '\L') and ($char[$i+1] eq '\u')) {
    0 0        
    0          
    0          
    0          
    0          
7020 0           @char[$i,$i+1] = @char[$i+1,$i];
7021             }
7022              
7023             # "\U\l" --> "\l\U"
7024             elsif (($char[$i] eq '\U') and ($char[$i+1] eq '\l')) {
7025 0           @char[$i,$i+1] = @char[$i+1,$i];
7026             }
7027              
7028             # octal escape sequence
7029             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
7030 0           $char[$i] = Ekoi8r::octchr($1);
7031             }
7032              
7033             # hexadecimal escape sequence
7034             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
7035 0           $char[$i] = Ekoi8r::hexchr($1);
7036             }
7037              
7038             # \b{...} --> b\{...}
7039             # \B{...} --> B\{...}
7040             # \N{CHARNAME} --> N\{CHARNAME}
7041             # \p{PROPERTY} --> p\{PROPERTY}
7042             # \P{PROPERTY} --> P\{PROPERTY}
7043             elsif ($char[$i] =~ /\A \\ ([bBNpP]) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
7044 0           $char[$i] = $1 . '\\' . $2;
7045             }
7046              
7047             # \p, \P, \X --> p, P, X
7048             elsif ($char[$i] =~ /\A \\ ( [pPX] ) \z/oxms) {
7049 0           $char[$i] = $1;
7050             }
7051              
7052 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          
7053             }
7054              
7055             # join separated multiple-octet
7056 0           elsif ($char[$i] =~ /\A (?: \\ [0-7]{2,3} | \\x [0-9A-Fa-f]{1,2}) \z/oxms) {
7057 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        
7058 0           $char[$i] .= join '', splice @char, $i+1, 3;
7059             }
7060             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)) {
7061 0           $char[$i] .= join '', splice @char, $i+1, 2;
7062             }
7063             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)) {
7064 0           $char[$i] .= join '', splice @char, $i+1, 1;
7065             }
7066             }
7067              
7068             # open character class [...]
7069             elsif ($char[$i] eq '[') {
7070 0           my $left = $i;
7071 0 0         if ($char[$i+1] eq ']') {
7072 0           $i++;
7073             }
7074 0           while (1) {
7075 0 0         if (++$i > $#char) {
7076 0           die __FILE__, ": Unmatched [] in regexp\n";
7077             }
7078 0 0         if ($char[$i] eq ']') {
7079 0           my $right = $i;
7080              
7081             # [...]
7082 0 0         if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
7083 0           splice @char, $left, $right-$left+1, sprintf(q{@{[Ekoi8r::charlist_qr(%s,'%s')]}}, join(',', map {qq_stuff($delimiter,$end_delimiter,$_)} @char[$left+1..$right-1]), $modifier);
  0            
7084             }
7085             else {
7086 0           splice @char, $left, $right-$left+1, Ekoi8r::charlist_qr(@char[$left+1..$right-1], $modifier);
7087             }
7088              
7089 0           $i = $left;
7090 0           last;
7091             }
7092             }
7093             }
7094              
7095             # open character class [^...]
7096             elsif ($char[$i] eq '[^') {
7097 0           my $left = $i;
7098 0 0         if ($char[$i+1] eq ']') {
7099 0           $i++;
7100             }
7101 0           while (1) {
7102 0 0         if (++$i > $#char) {
7103 0           die __FILE__, ": Unmatched [] in regexp\n";
7104             }
7105 0 0         if ($char[$i] eq ']') {
7106 0           my $right = $i;
7107              
7108             # [^...]
7109 0 0         if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
7110 0           splice @char, $left, $right-$left+1, sprintf(q{@{[Ekoi8r::charlist_not_qr(%s,'%s')]}}, join(',', map {qq_stuff($delimiter,$end_delimiter,$_)} @char[$left+1..$right-1]), $modifier);
  0            
7111             }
7112             else {
7113 0           splice @char, $left, $right-$left+1, Ekoi8r::charlist_not_qr(@char[$left+1..$right-1], $modifier);
7114             }
7115              
7116 0           $i = $left;
7117 0           last;
7118             }
7119             }
7120             }
7121              
7122             # rewrite character class or escape character
7123             elsif (my $char = character_class($char[$i],$modifier)) {
7124 0           $char[$i] = $char;
7125             }
7126              
7127             # P.794 29.2.161. split
7128             # in Chapter 29: Functions
7129             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
7130              
7131             # P.951 split
7132             # in Chapter 27: Functions
7133             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
7134              
7135             # said "The //m modifier is assumed when you split on the pattern /^/",
7136             # but perl5.008 is not so. Therefore, this software adds //m.
7137             # (and so on)
7138              
7139             # split(m/^/) --> split(m/^/m)
7140             elsif (($char[$i] eq '^') and ($modifier !~ /m/oxms)) {
7141 0           $modifier .= 'm';
7142             }
7143              
7144             # /i modifier
7145             elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Ekoi8r::uc($char[$i]) ne Ekoi8r::fc($char[$i]))) {
7146 0 0         if (CORE::length(Ekoi8r::fc($char[$i])) == 1) {
7147 0           $char[$i] = '[' . Ekoi8r::uc($char[$i]) . Ekoi8r::fc($char[$i]) . ']';
7148             }
7149             else {
7150 0           $char[$i] = '(?:' . Ekoi8r::uc($char[$i]) . '|' . Ekoi8r::fc($char[$i]) . ')';
7151             }
7152             }
7153              
7154             # \u \l \U \L \F \Q \E
7155             elsif ($char[$i] =~ /\A ([<>]) \z/oxms) {
7156 0 0         if ($right_e < $left_e) {
7157 0           $char[$i] = '\\' . $char[$i];
7158             }
7159             }
7160             elsif ($char[$i] eq '\u') {
7161 0           $char[$i] = '@{[Ekoi8r::ucfirst qq<';
7162 0           $left_e++;
7163             }
7164             elsif ($char[$i] eq '\l') {
7165 0           $char[$i] = '@{[Ekoi8r::lcfirst qq<';
7166 0           $left_e++;
7167             }
7168             elsif ($char[$i] eq '\U') {
7169 0           $char[$i] = '@{[Ekoi8r::uc qq<';
7170 0           $left_e++;
7171             }
7172             elsif ($char[$i] eq '\L') {
7173 0           $char[$i] = '@{[Ekoi8r::lc qq<';
7174 0           $left_e++;
7175             }
7176             elsif ($char[$i] eq '\F') {
7177 0           $char[$i] = '@{[Ekoi8r::fc qq<';
7178 0           $left_e++;
7179             }
7180             elsif ($char[$i] eq '\Q') {
7181 0           $char[$i] = '@{[CORE::quotemeta qq<';
7182 0           $left_e++;
7183             }
7184             elsif ($char[$i] eq '\E') {
7185 0 0         if ($right_e < $left_e) {
7186 0           $char[$i] = '>]}';
7187 0           $right_e++;
7188             }
7189             else {
7190 0           $char[$i] = '';
7191             }
7192             }
7193             elsif ($char[$i] eq '\Q') {
7194 0           while (1) {
7195 0 0         if (++$i > $#char) {
7196 0           last;
7197             }
7198 0 0         if ($char[$i] eq '\E') {
7199 0           last;
7200             }
7201             }
7202             }
7203             elsif ($char[$i] eq '\E') {
7204             }
7205              
7206             # $0 --> $0
7207             elsif ($char[$i] =~ /\A \$ 0 \z/oxms) {
7208 0 0         if ($ignorecase) {
7209 0           $char[$i] = '@{[Ekoi8r::ignorecase(' . $char[$i] . ')]}';
7210             }
7211             }
7212             elsif ($char[$i] =~ /\A \$ \{ (?>\s*) 0 (?>\s*) \} \z/oxms) {
7213 0 0         if ($ignorecase) {
7214 0           $char[$i] = '@{[Ekoi8r::ignorecase(' . $char[$i] . ')]}';
7215             }
7216             }
7217              
7218             # $$ --> $$
7219             elsif ($char[$i] =~ /\A \$\$ \z/oxms) {
7220             }
7221              
7222             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
7223             # $1, $2, $3 --> $1, $2, $3 otherwise
7224             elsif ($char[$i] =~ /\A \$ ((?>[1-9][0-9]*)) \z/oxms) {
7225 0           $char[$i] = e_capture($1);
7226 0 0         if ($ignorecase) {
7227 0           $char[$i] = '@{[Ekoi8r::ignorecase(' . $char[$i] . ')]}';
7228             }
7229             }
7230             elsif ($char[$i] =~ /\A \$ \{ (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} \z/oxms) {
7231 0           $char[$i] = e_capture($1);
7232 0 0         if ($ignorecase) {
7233 0           $char[$i] = '@{[Ekoi8r::ignorecase(' . $char[$i] . ')]}';
7234             }
7235             }
7236              
7237             # $$foo[ ... ] --> $ $foo->[ ... ]
7238             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \[ (?:$qq_bracket)*? \] ) \z/oxms) {
7239 0           $char[$i] = e_capture($1.'->'.$2);
7240 0 0         if ($ignorecase) {
7241 0           $char[$i] = '@{[Ekoi8r::ignorecase(' . $char[$i] . ')]}';
7242             }
7243             }
7244              
7245             # $$foo{ ... } --> $ $foo->{ ... }
7246             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \{ (?:$qq_brace)*? \} ) \z/oxms) {
7247 0           $char[$i] = e_capture($1.'->'.$2);
7248 0 0         if ($ignorecase) {
7249 0           $char[$i] = '@{[Ekoi8r::ignorecase(' . $char[$i] . ')]}';
7250             }
7251             }
7252              
7253             # $$foo
7254             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) \z/oxms) {
7255 0           $char[$i] = e_capture($1);
7256 0 0         if ($ignorecase) {
7257 0           $char[$i] = '@{[Ekoi8r::ignorecase(' . $char[$i] . ')]}';
7258             }
7259             }
7260              
7261             # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Ekoi8r::PREMATCH()
7262             elsif ($char[$i] =~ /\A ( \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} ) \z/oxmsgc) {
7263 0 0         if ($ignorecase) {
7264 0           $char[$i] = '@{[Ekoi8r::ignorecase(Ekoi8r::PREMATCH())]}';
7265             }
7266             else {
7267 0           $char[$i] = '@{[Ekoi8r::PREMATCH()]}';
7268             }
7269             }
7270              
7271             # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Ekoi8r::MATCH()
7272             elsif ($char[$i] =~ /\A ( \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} ) \z/oxmsgc) {
7273 0 0         if ($ignorecase) {
7274 0           $char[$i] = '@{[Ekoi8r::ignorecase(Ekoi8r::MATCH())]}';
7275             }
7276             else {
7277 0           $char[$i] = '@{[Ekoi8r::MATCH()]}';
7278             }
7279             }
7280              
7281             # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Ekoi8r::POSTMATCH()
7282             elsif ($char[$i] =~ /\A ( \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} ) \z/oxmsgc) {
7283 0 0         if ($ignorecase) {
7284 0           $char[$i] = '@{[Ekoi8r::ignorecase(Ekoi8r::POSTMATCH())]}';
7285             }
7286             else {
7287 0           $char[$i] = '@{[Ekoi8r::POSTMATCH()]}';
7288             }
7289             }
7290              
7291             # ${ foo }
7292             elsif ($char[$i] =~ /\A \$ (?>\s*) \{ ((?> \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* )) \} \z/oxms) {
7293 0 0         if ($ignorecase) {
7294 0           $char[$i] = '@{[Ekoi8r::ignorecase(' . $1 . ')]}';
7295             }
7296             }
7297              
7298             # ${ ... }
7299             elsif ($char[$i] =~ /\A \$ (?>\s*) \{ ( .+ ) \} \z/oxms) {
7300 0           $char[$i] = e_capture($1);
7301 0 0         if ($ignorecase) {
7302 0           $char[$i] = '@{[Ekoi8r::ignorecase(' . $char[$i] . ')]}';
7303             }
7304             }
7305              
7306             # $scalar or @array
7307             elsif ($char[$i] =~ /\A [\$\@].+ /oxms) {
7308 0           $char[$i] = e_string($char[$i]);
7309 0 0         if ($ignorecase) {
7310 0           $char[$i] = '@{[Ekoi8r::ignorecase(' . $char[$i] . ')]}';
7311             }
7312             }
7313              
7314             # quote character before ? + * {
7315             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
7316 0 0         if ($char[$i-1] =~ /\A (?:[\x00-\xFF]|\\[0-7]{2,3}|\\x[0-9-A-Fa-f]{1,2}) \z/oxms) {
7317             }
7318             else {
7319 0           $char[$i-1] = '(?:' . $char[$i-1] . ')';
7320             }
7321             }
7322             }
7323              
7324             # make regexp string
7325 0           $modifier =~ tr/i//d;
7326 0 0         if ($left_e > $right_e) {
7327 0           return join '', 'Ekoi8r::split', $ope, $delimiter, @char, '>]}' x ($left_e - $right_e), $end_delimiter, $modifier;
7328             }
7329 0           return join '', 'Ekoi8r::split', $ope, $delimiter, @char, $end_delimiter, $modifier;
7330             }
7331              
7332             #
7333             # escape regexp of split qr''
7334             #
7335             sub e_split_q {
7336 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
7337 0   0       $modifier ||= '';
7338              
7339 0           $modifier =~ tr/p//d;
7340 0 0         if ($modifier =~ /([adlu])/oxms) {
7341 0           my $line = 0;
7342 0           for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
7343 0 0         if ($filename ne __FILE__) {
7344 0           $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
7345 0           last;
7346             }
7347             }
7348 0           die qq{Unsupported modifier "$1" used at line $line.\n};
7349             }
7350              
7351 0           $slash = 'div';
7352              
7353             # /b /B modifier
7354 0 0         if ($modifier =~ tr/bB//d) {
7355 0           return join '', 'split', $ope, $delimiter, $string, $end_delimiter, $modifier;
7356             }
7357              
7358 0 0         my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
7359              
7360             # split regexp
7361 0           my @char = $string =~ /\G((?>
7362             [^\\\[] |
7363             [\x00-\xFF] |
7364             \[\^ |
7365             \[\: (?>[a-z]+) \:\] |
7366             \[\:\^ (?>[a-z]+) \:\] |
7367             \\ (?:$q_char) |
7368             (?:$q_char)
7369             ))/oxmsg;
7370              
7371             # unescape character
7372 0           for (my $i=0; $i <= $#char; $i++) {
7373 0 0 0       if (0) {
    0 0        
    0 0        
    0 0        
    0          
    0          
7374             }
7375              
7376             # open character class [...]
7377 0           elsif ($char[$i] eq '[') {
7378 0           my $left = $i;
7379 0 0         if ($char[$i+1] eq ']') {
7380 0           $i++;
7381             }
7382 0           while (1) {
7383 0 0         if (++$i > $#char) {
7384 0           die __FILE__, ": Unmatched [] in regexp\n";
7385             }
7386 0 0         if ($char[$i] eq ']') {
7387 0           my $right = $i;
7388              
7389             # [...]
7390 0           splice @char, $left, $right-$left+1, Ekoi8r::charlist_qr(@char[$left+1..$right-1], $modifier);
7391              
7392 0           $i = $left;
7393 0           last;
7394             }
7395             }
7396             }
7397              
7398             # open character class [^...]
7399             elsif ($char[$i] eq '[^') {
7400 0           my $left = $i;
7401 0 0         if ($char[$i+1] eq ']') {
7402 0           $i++;
7403             }
7404 0           while (1) {
7405 0 0         if (++$i > $#char) {
7406 0           die __FILE__, ": Unmatched [] in regexp\n";
7407             }
7408 0 0         if ($char[$i] eq ']') {
7409 0           my $right = $i;
7410              
7411             # [^...]
7412 0           splice @char, $left, $right-$left+1, Ekoi8r::charlist_not_qr(@char[$left+1..$right-1], $modifier);
7413              
7414 0           $i = $left;
7415 0           last;
7416             }
7417             }
7418             }
7419              
7420             # rewrite character class or escape character
7421             elsif (my $char = character_class($char[$i],$modifier)) {
7422 0           $char[$i] = $char;
7423             }
7424              
7425             # split(m/^/) --> split(m/^/m)
7426             elsif (($char[$i] eq '^') and ($modifier !~ /m/oxms)) {
7427 0           $modifier .= 'm';
7428             }
7429              
7430             # /i modifier
7431             elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Ekoi8r::uc($char[$i]) ne Ekoi8r::fc($char[$i]))) {
7432 0 0         if (CORE::length(Ekoi8r::fc($char[$i])) == 1) {
7433 0           $char[$i] = '[' . Ekoi8r::uc($char[$i]) . Ekoi8r::fc($char[$i]) . ']';
7434             }
7435             else {
7436 0           $char[$i] = '(?:' . Ekoi8r::uc($char[$i]) . '|' . Ekoi8r::fc($char[$i]) . ')';
7437             }
7438             }
7439              
7440             # quote character before ? + * {
7441             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
7442 0 0         if ($char[$i-1] =~ /\A [\x00-\xFF] \z/oxms) {
7443             }
7444             else {
7445 0           $char[$i-1] = '(?:' . $char[$i-1] . ')';
7446             }
7447             }
7448             }
7449              
7450 0           $modifier =~ tr/i//d;
7451 0           return join '', 'Ekoi8r::split', $ope, $delimiter, @char, $end_delimiter, $modifier;
7452             }
7453              
7454             #
7455             # instead of Carp::carp
7456             #
7457             sub carp {
7458 0     0 0   my($package,$filename,$line) = caller(1);
7459 0           print STDERR "@_ at $filename line $line.\n";
7460             }
7461              
7462             #
7463             # instead of Carp::croak
7464             #
7465             sub croak {
7466 0     0 0   my($package,$filename,$line) = caller(1);
7467 0           print STDERR "@_ at $filename line $line.\n";
7468 0           die "\n";
7469             }
7470              
7471             #
7472             # instead of Carp::cluck
7473             #
7474             sub cluck {
7475 0     0 0   my $i = 0;
7476 0           my @cluck = ();
7477 0           while (my($package,$filename,$line,$subroutine) = caller($i)) {
7478 0           push @cluck, "[$i] $filename($line) $package::$subroutine\n";
7479 0           $i++;
7480             }
7481 0           print STDERR CORE::reverse @cluck;
7482 0           print STDERR "\n";
7483 0           carp @_;
7484             }
7485              
7486             #
7487             # instead of Carp::confess
7488             #
7489             sub confess {
7490 0     0 0   my $i = 0;
7491 0           my @confess = ();
7492 0           while (my($package,$filename,$line,$subroutine) = caller($i)) {
7493 0           push @confess, "[$i] $filename($line) $package::$subroutine\n";
7494 0           $i++;
7495             }
7496 0           print STDERR CORE::reverse @confess;
7497 0           print STDERR "\n";
7498 0           croak @_;
7499             }
7500              
7501             1;
7502              
7503             __END__