File Coverage

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


line stmt bran cond sub pod time code
1             #
2             # This file is *** FOR CPAN USE ONLY ***.
3             #
4             package Char::Ecyrillic;
5             ######################################################################
6             #
7             # Char::Ecyrillic - Run-time routines for Char/Cyrillic.pm
8             #
9             # http://search.cpan.org/dist/Char-Cyrillic/
10             #
11             # Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015 INABA Hitoshi
12             ######################################################################
13              
14 197     197   5371 use 5.00503; # Galapagos Consensus 1998 for primetools
  197         656  
  197         11820  
15             # use 5.008001; # Lancaster Consensus 2013 for toolchains
16              
17             # 12.3. Delaying use Until Runtime
18             # in Chapter 12. Packages, Libraries, and Modules
19             # of ISBN 0-596-00313-7 Perl Cookbook, 2nd Edition.
20             # (and so on)
21              
22 197     197   15285 BEGIN { CORE::eval q{ use vars qw($VERSION) } }
  197     197   1234  
  197         511  
  197         47774  
23             $VERSION = sprintf '%d.%02d', q$Revision: 1.02 $ =~ /(\d+)/xmsg;
24              
25             BEGIN {
26 197 50   197   1586 if ($^X =~ / jperl /oxmsi) {
27 0         0 die __FILE__, ": needs perl(not jperl) 5.00503 or later. (\$^X==$^X)";
28             }
29 197         485 if (CORE::ord('A') == 193) {
30             die __FILE__, ": is not US-ASCII script (may be EBCDIC or EBCDIK script).";
31             }
32 197         50130 if (CORE::ord('A') != 0x41) {
33             die __FILE__, ": is not US-ASCII script (must be US-ASCII script).";
34             }
35             }
36              
37             BEGIN {
38              
39             # instead of utf8.pm
40 197     197   14900 CORE::eval q{
  197     197   1424  
  197     55   359  
  197         35603  
  55         10546  
  63         12514  
  84         15792  
  63         12301  
  57         10902  
  72         14575  
41             no warnings qw(redefine);
42             *utf8::upgrade = sub { CORE::length $_[0] };
43             *utf8::downgrade = sub { 1 };
44             *utf8::encode = sub { };
45             *utf8::decode = sub { 1 };
46             *utf8::is_utf8 = sub { };
47             *utf8::valid = sub { 1 };
48             };
49 197 50       139266 if ($@) {
50 0         0 *utf8::upgrade = sub { CORE::length $_[0] };
  0         0  
51 0         0 *utf8::downgrade = sub { 1 };
  0         0  
52 0         0 *utf8::encode = sub { };
  0         0  
53 0         0 *utf8::decode = sub { 1 };
  0         0  
54 0         0 *utf8::is_utf8 = sub { };
  0         0  
55 0         0 *utf8::valid = sub { 1 };
  0         0  
56             }
57             }
58              
59             # instead of Symbol.pm
60             BEGIN {
61 197     197   529 my $genpkg = "Symbol::";
62 197         11983 my $genseq = 0;
63              
64             sub gensym () {
65 0     0 0 0 my $name = "GEN" . $genseq++;
66              
67             # here, no strict qw(refs); if strict.pm exists
68              
69 0         0 my $ref = \*{$genpkg . $name};
  0         0  
70 0         0 delete $$genpkg{$name};
71 0         0 return $ref;
72             }
73              
74             sub qualify ($;$) {
75 0     0 0 0 my ($name) = @_;
76 0 0 0     0 if (!ref($name) && (Char::Ecyrillic::index($name, '::') == -1) && (Char::Ecyrillic::index($name, "'") == -1)) {
      0        
77 0         0 my $pkg;
78 0         0 my %global = map {$_ => 1} qw(ARGV ARGVOUT ENV INC SIG STDERR STDIN STDOUT DATA);
  0         0  
79              
80             # Global names: special character, "^xyz", or other.
81 0 0 0     0 if ($name =~ /^(([^a-z])|(\^[a-z_]+))\z/i || $global{$name}) {
82             # RGS 2001-11-05 : translate leading ^X to control-char
83 0         0 $name =~ s/^\^([a-z_])/'qq(\c'.$1.')'/eei;
  0         0  
84 0         0 $pkg = "main";
85             }
86             else {
87 0 0       0 $pkg = (@_ > 1) ? $_[1] : caller;
88             }
89 0         0 $name = $pkg . "::" . $name;
90             }
91 0         0 return $name;
92             }
93              
94             sub qualify_to_ref ($;$) {
95              
96             # here, no strict qw(refs); if strict.pm exists
97              
98 0 0   0 0 0 return \*{ qualify $_[0], @_ > 1 ? $_[1] : caller };
  0         0  
99             }
100             }
101              
102             # Column: local $@
103             # in Chapter 9. Osaete okitai Perl no kiso
104             # of ISBN 10: 4798119172 | ISBN 13: 978-4798119175 MODAN Perl NYUMON
105             # (and so on)
106              
107             # use strict; if strict.pm exists
108             BEGIN {
109 197 50   197   436 if (CORE::eval { local $@; CORE::require strict }) {
  197         382  
  197         3347  
110 197         29527 strict::->import;
111             }
112             }
113              
114             # P.714 29.2.39. flock
115             # in Chapter 29: Functions
116             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
117              
118             # P.863 flock
119             # in Chapter 27: Functions
120             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
121              
122             sub LOCK_SH() {1}
123             sub LOCK_EX() {2}
124             sub LOCK_UN() {8}
125             sub LOCK_NB() {4}
126              
127             # instead of Carp.pm
128             sub carp;
129             sub croak;
130             sub cluck;
131             sub confess;
132              
133             # 6.18. Matching Multiple-Byte Characters
134             # in Chapter 6. Pattern Matching
135             # of ISBN 978-1-56592-243-3 Perl Perl Cookbook.
136             # (and so on)
137              
138             # regexp of character
139 197     197   16580 BEGIN { CORE::eval q{ use vars qw($your_char) } } $your_char = q{[\x00-\xFF]};
  197     197   1599  
  197         333  
  197         13922  
140 197     197   12431 BEGIN { CORE::eval q{ use vars qw($qq_char ) } } $qq_char = qr/\\c[\x40-\x5F]|\\?(?:$your_char)/oxms;
  197     197   1373  
  197         314  
  197         20982  
141 197     197   14667 BEGIN { CORE::eval q{ use vars qw($q_char ) } } $q_char = qr/$your_char/oxms;
  197     197   1221  
  197         323  
  197         23008  
142              
143             #
144             # Cyrillic character range per length
145             #
146             my %range_tr = ();
147              
148             #
149             # alias of encoding name
150             #
151 197     197   33936 BEGIN { CORE::eval q{ use vars qw($encoding_alias) } }
  197     197   1417  
  197         438  
  197         527427  
152              
153             #
154             # Cyrillic case conversion
155             #
156             my %lc = ();
157             @lc{qw(A B C D E F G H I J K L M N O P Q R S T U V W X Y Z)} =
158             qw(a b c d e f g h i j k l m n o p q r s t u v w x y z);
159             my %uc = ();
160             @uc{qw(a b c d e f g h i j k l m n o p q r s t u v w x y z)} =
161             qw(A B C D E F G H I J K L M N O P Q R S T U V W X Y Z);
162             my %fc = ();
163             @fc{qw(A B C D E F G H I J K L M N O P Q R S T U V W X Y Z)} =
164             qw(a b c d e f g h i j k l m n o p q r s t u v w x y z);
165              
166             if (0) {
167             }
168              
169             elsif (__PACKAGE__ =~ / \b Ecyrillic \z/oxms) {
170             %range_tr = (
171             1 => [ [0x00..0xFF],
172             ],
173             );
174             $encoding_alias = qr/ \b (?: iso[-_ ]?8859-5 | iec[- ]?8859-5 | cyrillic ) \b /oxmsi;
175              
176             %lc = (%lc,
177             "\xA1" => "\xF1", # CYRILLIC LETTER IO
178             "\xA2" => "\xF2", # CYRILLIC LETTER DJE
179             "\xA3" => "\xF3", # CYRILLIC LETTER GJE
180             "\xA4" => "\xF4", # CYRILLIC LETTER UKRAINIAN IE
181             "\xA5" => "\xF5", # CYRILLIC LETTER DZE
182             "\xA6" => "\xF6", # CYRILLIC LETTER BYELORUSSIAN-UKRAINIAN I
183             "\xA7" => "\xF7", # CYRILLIC LETTER YI
184             "\xA8" => "\xF8", # CYRILLIC LETTER JE
185             "\xA9" => "\xF9", # CYRILLIC LETTER LJE
186             "\xAA" => "\xFA", # CYRILLIC LETTER NJE
187             "\xAB" => "\xFB", # CYRILLIC LETTER TSHE
188             "\xAC" => "\xFC", # CYRILLIC LETTER KJE
189             "\xAE" => "\xFE", # CYRILLIC LETTER SHORT U
190             "\xAF" => "\xFF", # CYRILLIC LETTER DZHE
191             "\xB0" => "\xD0", # CYRILLIC LETTER A
192             "\xB1" => "\xD1", # CYRILLIC LETTER BE
193             "\xB2" => "\xD2", # CYRILLIC LETTER VE
194             "\xB3" => "\xD3", # CYRILLIC LETTER GHE
195             "\xB4" => "\xD4", # CYRILLIC LETTER DE
196             "\xB5" => "\xD5", # CYRILLIC LETTER IE
197             "\xB6" => "\xD6", # CYRILLIC LETTER ZHE
198             "\xB7" => "\xD7", # CYRILLIC LETTER ZE
199             "\xB8" => "\xD8", # CYRILLIC LETTER I
200             "\xB9" => "\xD9", # CYRILLIC LETTER SHORT I
201             "\xBA" => "\xDA", # CYRILLIC LETTER KA
202             "\xBB" => "\xDB", # CYRILLIC LETTER EL
203             "\xBC" => "\xDC", # CYRILLIC LETTER EM
204             "\xBD" => "\xDD", # CYRILLIC LETTER EN
205             "\xBE" => "\xDE", # CYRILLIC LETTER O
206             "\xBF" => "\xDF", # CYRILLIC LETTER PE
207             "\xC0" => "\xE0", # CYRILLIC LETTER ER
208             "\xC1" => "\xE1", # CYRILLIC LETTER ES
209             "\xC2" => "\xE2", # CYRILLIC LETTER TE
210             "\xC3" => "\xE3", # CYRILLIC LETTER U
211             "\xC4" => "\xE4", # CYRILLIC LETTER EF
212             "\xC5" => "\xE5", # CYRILLIC LETTER HA
213             "\xC6" => "\xE6", # CYRILLIC LETTER TSE
214             "\xC7" => "\xE7", # CYRILLIC LETTER CHE
215             "\xC8" => "\xE8", # CYRILLIC LETTER SHA
216             "\xC9" => "\xE9", # CYRILLIC LETTER SHCHA
217             "\xCA" => "\xEA", # CYRILLIC LETTER HARD SIGN
218             "\xCB" => "\xEB", # CYRILLIC LETTER YERU
219             "\xCC" => "\xEC", # CYRILLIC LETTER SOFT SIGN
220             "\xCD" => "\xED", # CYRILLIC LETTER E
221             "\xCE" => "\xEE", # CYRILLIC LETTER YU
222             "\xCF" => "\xEF", # CYRILLIC LETTER YA
223             );
224              
225             %uc = (%uc,
226             "\xD0" => "\xB0", # CYRILLIC LETTER A
227             "\xD1" => "\xB1", # CYRILLIC LETTER BE
228             "\xD2" => "\xB2", # CYRILLIC LETTER VE
229             "\xD3" => "\xB3", # CYRILLIC LETTER GHE
230             "\xD4" => "\xB4", # CYRILLIC LETTER DE
231             "\xD5" => "\xB5", # CYRILLIC LETTER IE
232             "\xD6" => "\xB6", # CYRILLIC LETTER ZHE
233             "\xD7" => "\xB7", # CYRILLIC LETTER ZE
234             "\xD8" => "\xB8", # CYRILLIC LETTER I
235             "\xD9" => "\xB9", # CYRILLIC LETTER SHORT I
236             "\xDA" => "\xBA", # CYRILLIC LETTER KA
237             "\xDB" => "\xBB", # CYRILLIC LETTER EL
238             "\xDC" => "\xBC", # CYRILLIC LETTER EM
239             "\xDD" => "\xBD", # CYRILLIC LETTER EN
240             "\xDE" => "\xBE", # CYRILLIC LETTER O
241             "\xDF" => "\xBF", # CYRILLIC LETTER PE
242             "\xE0" => "\xC0", # CYRILLIC LETTER ER
243             "\xE1" => "\xC1", # CYRILLIC LETTER ES
244             "\xE2" => "\xC2", # CYRILLIC LETTER TE
245             "\xE3" => "\xC3", # CYRILLIC LETTER U
246             "\xE4" => "\xC4", # CYRILLIC LETTER EF
247             "\xE5" => "\xC5", # CYRILLIC LETTER HA
248             "\xE6" => "\xC6", # CYRILLIC LETTER TSE
249             "\xE7" => "\xC7", # CYRILLIC LETTER CHE
250             "\xE8" => "\xC8", # CYRILLIC LETTER SHA
251             "\xE9" => "\xC9", # CYRILLIC LETTER SHCHA
252             "\xEA" => "\xCA", # CYRILLIC LETTER HARD SIGN
253             "\xEB" => "\xCB", # CYRILLIC LETTER YERU
254             "\xEC" => "\xCC", # CYRILLIC LETTER SOFT SIGN
255             "\xED" => "\xCD", # CYRILLIC LETTER E
256             "\xEE" => "\xCE", # CYRILLIC LETTER YU
257             "\xEF" => "\xCF", # CYRILLIC LETTER YA
258             "\xF1" => "\xA1", # CYRILLIC LETTER IO
259             "\xF2" => "\xA2", # CYRILLIC LETTER DJE
260             "\xF3" => "\xA3", # CYRILLIC LETTER GJE
261             "\xF4" => "\xA4", # CYRILLIC LETTER UKRAINIAN IE
262             "\xF5" => "\xA5", # CYRILLIC LETTER DZE
263             "\xF6" => "\xA6", # CYRILLIC LETTER BYELORUSSIAN-UKRAINIAN I
264             "\xF7" => "\xA7", # CYRILLIC LETTER YI
265             "\xF8" => "\xA8", # CYRILLIC LETTER JE
266             "\xF9" => "\xA9", # CYRILLIC LETTER LJE
267             "\xFA" => "\xAA", # CYRILLIC LETTER NJE
268             "\xFB" => "\xAB", # CYRILLIC LETTER TSHE
269             "\xFC" => "\xAC", # CYRILLIC LETTER KJE
270             "\xFE" => "\xAE", # CYRILLIC LETTER SHORT U
271             "\xFF" => "\xAF", # CYRILLIC LETTER DZHE
272             );
273              
274             %fc = (%fc,
275             "\xA1" => "\xF1", # CYRILLIC CAPITAL LETTER IO --> CYRILLIC SMALL LETTER IO
276             "\xA2" => "\xF2", # CYRILLIC CAPITAL LETTER DJE --> CYRILLIC SMALL LETTER DJE
277             "\xA3" => "\xF3", # CYRILLIC CAPITAL LETTER GJE --> CYRILLIC SMALL LETTER GJE
278             "\xA4" => "\xF4", # CYRILLIC CAPITAL LETTER UKRAINIAN IE --> CYRILLIC SMALL LETTER UKRAINIAN IE
279             "\xA5" => "\xF5", # CYRILLIC CAPITAL LETTER DZE --> CYRILLIC SMALL LETTER DZE
280             "\xA6" => "\xF6", # CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I --> CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I
281             "\xA7" => "\xF7", # CYRILLIC CAPITAL LETTER YI --> CYRILLIC SMALL LETTER YI
282             "\xA8" => "\xF8", # CYRILLIC CAPITAL LETTER JE --> CYRILLIC SMALL LETTER JE
283             "\xA9" => "\xF9", # CYRILLIC CAPITAL LETTER LJE --> CYRILLIC SMALL LETTER LJE
284             "\xAA" => "\xFA", # CYRILLIC CAPITAL LETTER NJE --> CYRILLIC SMALL LETTER NJE
285             "\xAB" => "\xFB", # CYRILLIC CAPITAL LETTER TSHE --> CYRILLIC SMALL LETTER TSHE
286             "\xAC" => "\xFC", # CYRILLIC CAPITAL LETTER KJE --> CYRILLIC SMALL LETTER KJE
287             "\xAE" => "\xFE", # CYRILLIC CAPITAL LETTER SHORT U --> CYRILLIC SMALL LETTER SHORT U
288             "\xAF" => "\xFF", # CYRILLIC CAPITAL LETTER DZHE --> CYRILLIC SMALL LETTER DZHE
289             "\xB0" => "\xD0", # CYRILLIC CAPITAL LETTER A --> CYRILLIC SMALL LETTER A
290             "\xB1" => "\xD1", # CYRILLIC CAPITAL LETTER BE --> CYRILLIC SMALL LETTER BE
291             "\xB2" => "\xD2", # CYRILLIC CAPITAL LETTER VE --> CYRILLIC SMALL LETTER VE
292             "\xB3" => "\xD3", # CYRILLIC CAPITAL LETTER GHE --> CYRILLIC SMALL LETTER GHE
293             "\xB4" => "\xD4", # CYRILLIC CAPITAL LETTER DE --> CYRILLIC SMALL LETTER DE
294             "\xB5" => "\xD5", # CYRILLIC CAPITAL LETTER IE --> CYRILLIC SMALL LETTER IE
295             "\xB6" => "\xD6", # CYRILLIC CAPITAL LETTER ZHE --> CYRILLIC SMALL LETTER ZHE
296             "\xB7" => "\xD7", # CYRILLIC CAPITAL LETTER ZE --> CYRILLIC SMALL LETTER ZE
297             "\xB8" => "\xD8", # CYRILLIC CAPITAL LETTER I --> CYRILLIC SMALL LETTER I
298             "\xB9" => "\xD9", # CYRILLIC CAPITAL LETTER SHORT I --> CYRILLIC SMALL LETTER SHORT I
299             "\xBA" => "\xDA", # CYRILLIC CAPITAL LETTER KA --> CYRILLIC SMALL LETTER KA
300             "\xBB" => "\xDB", # CYRILLIC CAPITAL LETTER EL --> CYRILLIC SMALL LETTER EL
301             "\xBC" => "\xDC", # CYRILLIC CAPITAL LETTER EM --> CYRILLIC SMALL LETTER EM
302             "\xBD" => "\xDD", # CYRILLIC CAPITAL LETTER EN --> CYRILLIC SMALL LETTER EN
303             "\xBE" => "\xDE", # CYRILLIC CAPITAL LETTER O --> CYRILLIC SMALL LETTER O
304             "\xBF" => "\xDF", # CYRILLIC CAPITAL LETTER PE --> CYRILLIC SMALL LETTER PE
305             "\xC0" => "\xE0", # CYRILLIC CAPITAL LETTER ER --> CYRILLIC SMALL LETTER ER
306             "\xC1" => "\xE1", # CYRILLIC CAPITAL LETTER ES --> CYRILLIC SMALL LETTER ES
307             "\xC2" => "\xE2", # CYRILLIC CAPITAL LETTER TE --> CYRILLIC SMALL LETTER TE
308             "\xC3" => "\xE3", # CYRILLIC CAPITAL LETTER U --> CYRILLIC SMALL LETTER U
309             "\xC4" => "\xE4", # CYRILLIC CAPITAL LETTER EF --> CYRILLIC SMALL LETTER EF
310             "\xC5" => "\xE5", # CYRILLIC CAPITAL LETTER HA --> CYRILLIC SMALL LETTER HA
311             "\xC6" => "\xE6", # CYRILLIC CAPITAL LETTER TSE --> CYRILLIC SMALL LETTER TSE
312             "\xC7" => "\xE7", # CYRILLIC CAPITAL LETTER CHE --> CYRILLIC SMALL LETTER CHE
313             "\xC8" => "\xE8", # CYRILLIC CAPITAL LETTER SHA --> CYRILLIC SMALL LETTER SHA
314             "\xC9" => "\xE9", # CYRILLIC CAPITAL LETTER SHCHA --> CYRILLIC SMALL LETTER SHCHA
315             "\xCA" => "\xEA", # CYRILLIC CAPITAL LETTER HARD SIGN --> CYRILLIC SMALL LETTER HARD SIGN
316             "\xCB" => "\xEB", # CYRILLIC CAPITAL LETTER YERU --> CYRILLIC SMALL LETTER YERU
317             "\xCC" => "\xEC", # CYRILLIC CAPITAL LETTER SOFT SIGN --> CYRILLIC SMALL LETTER SOFT SIGN
318             "\xCD" => "\xED", # CYRILLIC CAPITAL LETTER E --> CYRILLIC SMALL LETTER E
319             "\xCE" => "\xEE", # CYRILLIC CAPITAL LETTER YU --> CYRILLIC SMALL LETTER YU
320             "\xCF" => "\xEF", # CYRILLIC CAPITAL LETTER YA --> CYRILLIC SMALL LETTER YA
321             );
322             }
323              
324             else {
325             croak "Don't know my package name '@{[__PACKAGE__]}'";
326             }
327              
328             #
329             # @ARGV wildcard globbing
330             #
331             sub import {
332              
333 0 0   0   0 if ($^O =~ /\A (?: MSWin32 | NetWare | symbian | dos ) \z/oxms) {
334 0         0 my @argv = ();
335 0         0 for (@ARGV) {
336              
337             # has space
338 0 0       0 if (/\A (?:$q_char)*? [ ] /oxms) {
    0          
339 0 0       0 if (my @glob = Char::Ecyrillic::glob(qq{"$_"})) {
340 0         0 push @argv, @glob;
341             }
342             else {
343 0         0 push @argv, $_;
344             }
345             }
346              
347             # has wildcard metachar
348             elsif (/\A (?:$q_char)*? [*?] /oxms) {
349 0 0       0 if (my @glob = Char::Ecyrillic::glob($_)) {
350 0         0 push @argv, @glob;
351             }
352             else {
353 0         0 push @argv, $_;
354             }
355             }
356              
357             # no wildcard globbing
358             else {
359 0         0 push @argv, $_;
360             }
361             }
362 0         0 @ARGV = @argv;
363             }
364             }
365              
366             # P.230 Care with Prototypes
367             # in Chapter 6: Subroutines
368             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
369             #
370             # If you aren't careful, you can get yourself into trouble with prototypes.
371             # But if you are careful, you can do a lot of neat things with them. This is
372             # all very powerful, of course, and should only be used in moderation to make
373             # the world a better place.
374              
375             # P.332 Care with Prototypes
376             # in Chapter 7: Subroutines
377             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
378             #
379             # If you aren't careful, you can get yourself into trouble with prototypes.
380             # But if you are careful, you can do a lot of neat things with them. This is
381             # all very powerful, of course, and should only be used in moderation to make
382             # the world a better place.
383              
384             #
385             # Prototypes of subroutines
386             #
387 0     0   0 sub unimport {}
388             sub Char::Ecyrillic::split(;$$$);
389             sub Char::Ecyrillic::tr($$$$;$);
390             sub Char::Ecyrillic::chop(@);
391             sub Char::Ecyrillic::index($$;$);
392             sub Char::Ecyrillic::rindex($$;$);
393             sub Char::Ecyrillic::lcfirst(@);
394             sub Char::Ecyrillic::lcfirst_();
395             sub Char::Ecyrillic::lc(@);
396             sub Char::Ecyrillic::lc_();
397             sub Char::Ecyrillic::ucfirst(@);
398             sub Char::Ecyrillic::ucfirst_();
399             sub Char::Ecyrillic::uc(@);
400             sub Char::Ecyrillic::uc_();
401             sub Char::Ecyrillic::fc(@);
402             sub Char::Ecyrillic::fc_();
403             sub Char::Ecyrillic::ignorecase;
404             sub Char::Ecyrillic::classic_character_class;
405             sub Char::Ecyrillic::capture;
406             sub Char::Ecyrillic::chr(;$);
407             sub Char::Ecyrillic::chr_();
408             sub Char::Ecyrillic::glob($);
409             sub Char::Ecyrillic::glob_();
410              
411             sub Char::Cyrillic::ord(;$);
412             sub Char::Cyrillic::ord_();
413             sub Char::Cyrillic::reverse(@);
414             sub Char::Cyrillic::getc(;*@);
415             sub Char::Cyrillic::length(;$);
416             sub Char::Cyrillic::substr($$;$$);
417             sub Char::Cyrillic::index($$;$);
418             sub Char::Cyrillic::rindex($$;$);
419             sub Char::Cyrillic::escape(;$);
420              
421             #
422             # Regexp work
423             #
424 197     197   22674 BEGIN { CORE::eval q{ use vars qw(
  197     197   1703  
  197         369  
  197         93869  
425             $Char::Cyrillic::re_a
426             $Char::Cyrillic::re_t
427             $Char::Cyrillic::re_n
428             $Char::Cyrillic::re_r
429             ) } }
430              
431             #
432             # Character class
433             #
434 197     197   26577 BEGIN { CORE::eval q{ use vars qw(
  197     197   2484  
  197         439  
  197         3907483  
435             $dot
436             $dot_s
437             $eD
438             $eS
439             $eW
440             $eH
441             $eV
442             $eR
443             $eN
444             $not_alnum
445             $not_alpha
446             $not_ascii
447             $not_blank
448             $not_cntrl
449             $not_digit
450             $not_graph
451             $not_lower
452             $not_lower_i
453             $not_print
454             $not_punct
455             $not_space
456             $not_upper
457             $not_upper_i
458             $not_word
459             $not_xdigit
460             $eb
461             $eB
462             ) } }
463              
464             ${Char::Ecyrillic::dot} = qr{(?:[^\x0A])};
465             ${Char::Ecyrillic::dot_s} = qr{(?:[\x00-\xFF])};
466             ${Char::Ecyrillic::eD} = qr{(?:[^0-9])};
467              
468             # Vertical tabs are now whitespace
469             # \s in a regex now matches a vertical tab in all circumstances.
470             # http://search.cpan.org/dist/perl-5.18.0/pod/perldelta.pod#Vertical_tabs_are_now_whitespace
471             # ${Char::Ecyrillic::eS} = qr{(?:[^\x09\x0A \x0C\x0D\x20])};
472             # ${Char::Ecyrillic::eS} = qr{(?:[^\x09\x0A\x0B\x0C\x0D\x20])};
473             ${Char::Ecyrillic::eS} = qr{(?:[^\s])};
474              
475             ${Char::Ecyrillic::eW} = qr{(?:[^0-9A-Z_a-z])};
476             ${Char::Ecyrillic::eH} = qr{(?:[^\x09\x20])};
477             ${Char::Ecyrillic::eV} = qr{(?:[^\x0A\x0B\x0C\x0D])};
478             ${Char::Ecyrillic::eR} = qr{(?:\x0D\x0A|[\x0A\x0D])};
479             ${Char::Ecyrillic::eN} = qr{(?:[^\x0A])};
480             ${Char::Ecyrillic::not_alnum} = qr{(?:[^\x30-\x39\x41-\x5A\x61-\x7A])};
481             ${Char::Ecyrillic::not_alpha} = qr{(?:[^\x41-\x5A\x61-\x7A])};
482             ${Char::Ecyrillic::not_ascii} = qr{(?:[^\x00-\x7F])};
483             ${Char::Ecyrillic::not_blank} = qr{(?:[^\x09\x20])};
484             ${Char::Ecyrillic::not_cntrl} = qr{(?:[^\x00-\x1F\x7F])};
485             ${Char::Ecyrillic::not_digit} = qr{(?:[^\x30-\x39])};
486             ${Char::Ecyrillic::not_graph} = qr{(?:[^\x21-\x7F])};
487             ${Char::Ecyrillic::not_lower} = qr{(?:[^\x61-\x7A])};
488             ${Char::Ecyrillic::not_lower_i} = qr{(?:[\x00-\xFF])};
489             ${Char::Ecyrillic::not_print} = qr{(?:[^\x20-\x7F])};
490             ${Char::Ecyrillic::not_punct} = qr{(?:[^\x21-\x2F\x3A-\x3F\x40\x5B-\x5F\x60\x7B-\x7E])};
491             ${Char::Ecyrillic::not_space} = qr{(?:[^\s\x0B])};
492             ${Char::Ecyrillic::not_upper} = qr{(?:[^\x41-\x5A])};
493             ${Char::Ecyrillic::not_upper_i} = qr{(?:[\x00-\xFF])};
494             ${Char::Ecyrillic::not_word} = qr{(?:[^\x30-\x39\x41-\x5A\x5F\x61-\x7A])};
495             ${Char::Ecyrillic::not_xdigit} = qr{(?:[^\x30-\x39\x41-\x46\x61-\x66])};
496             ${Char::Ecyrillic::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))};
497             ${Char::Ecyrillic::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]))};
498              
499             # avoid: Name "Char::Ecyrillic::foo" used only once: possible typo at here.
500             ${Char::Ecyrillic::dot} = ${Char::Ecyrillic::dot};
501             ${Char::Ecyrillic::dot_s} = ${Char::Ecyrillic::dot_s};
502             ${Char::Ecyrillic::eD} = ${Char::Ecyrillic::eD};
503             ${Char::Ecyrillic::eS} = ${Char::Ecyrillic::eS};
504             ${Char::Ecyrillic::eW} = ${Char::Ecyrillic::eW};
505             ${Char::Ecyrillic::eH} = ${Char::Ecyrillic::eH};
506             ${Char::Ecyrillic::eV} = ${Char::Ecyrillic::eV};
507             ${Char::Ecyrillic::eR} = ${Char::Ecyrillic::eR};
508             ${Char::Ecyrillic::eN} = ${Char::Ecyrillic::eN};
509             ${Char::Ecyrillic::not_alnum} = ${Char::Ecyrillic::not_alnum};
510             ${Char::Ecyrillic::not_alpha} = ${Char::Ecyrillic::not_alpha};
511             ${Char::Ecyrillic::not_ascii} = ${Char::Ecyrillic::not_ascii};
512             ${Char::Ecyrillic::not_blank} = ${Char::Ecyrillic::not_blank};
513             ${Char::Ecyrillic::not_cntrl} = ${Char::Ecyrillic::not_cntrl};
514             ${Char::Ecyrillic::not_digit} = ${Char::Ecyrillic::not_digit};
515             ${Char::Ecyrillic::not_graph} = ${Char::Ecyrillic::not_graph};
516             ${Char::Ecyrillic::not_lower} = ${Char::Ecyrillic::not_lower};
517             ${Char::Ecyrillic::not_lower_i} = ${Char::Ecyrillic::not_lower_i};
518             ${Char::Ecyrillic::not_print} = ${Char::Ecyrillic::not_print};
519             ${Char::Ecyrillic::not_punct} = ${Char::Ecyrillic::not_punct};
520             ${Char::Ecyrillic::not_space} = ${Char::Ecyrillic::not_space};
521             ${Char::Ecyrillic::not_upper} = ${Char::Ecyrillic::not_upper};
522             ${Char::Ecyrillic::not_upper_i} = ${Char::Ecyrillic::not_upper_i};
523             ${Char::Ecyrillic::not_word} = ${Char::Ecyrillic::not_word};
524             ${Char::Ecyrillic::not_xdigit} = ${Char::Ecyrillic::not_xdigit};
525             ${Char::Ecyrillic::eb} = ${Char::Ecyrillic::eb};
526             ${Char::Ecyrillic::eB} = ${Char::Ecyrillic::eB};
527              
528             #
529             # Cyrillic split
530             #
531             sub Char::Ecyrillic::split(;$$$) {
532              
533             # P.794 29.2.161. split
534             # in Chapter 29: Functions
535             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
536              
537             # P.951 split
538             # in Chapter 27: Functions
539             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
540              
541 0     0 0 0 my $pattern = $_[0];
542 0         0 my $string = $_[1];
543 0         0 my $limit = $_[2];
544              
545             # if $pattern is also omitted or is the literal space, " "
546 0 0       0 if (not defined $pattern) {
547 0         0 $pattern = ' ';
548             }
549              
550             # if $string is omitted, the function splits the $_ string
551 0 0       0 if (not defined $string) {
552 0 0       0 if (defined $_) {
553 0         0 $string = $_;
554             }
555             else {
556 0         0 $string = '';
557             }
558             }
559              
560 0         0 my @split = ();
561              
562             # when string is empty
563 0 0       0 if ($string eq '') {
    0          
564              
565             # resulting list value in list context
566 0 0       0 if (wantarray) {
567 0         0 return @split;
568             }
569              
570             # count of substrings in scalar context
571             else {
572 0 0       0 carp "Use of implicit split to \@_ is deprecated" if $^W;
573 0         0 @_ = @split;
574 0         0 return scalar @_;
575             }
576             }
577              
578             # split's first argument is more consistently interpreted
579             #
580             # After some changes earlier in v5.17, split's behavior has been simplified:
581             # if the PATTERN argument evaluates to a string containing one space, it is
582             # treated the way that a literal string containing one space once was.
583             # http://search.cpan.org/dist/perl-5.18.0/pod/perldelta.pod#split's_first_argument_is_more_consistently_interpreted
584              
585             # if $pattern is also omitted or is the literal space, " ", the function splits
586             # on whitespace, /\s+/, after skipping any leading whitespace
587             # (and so on)
588              
589             elsif ($pattern eq ' ') {
590 0 0       0 if (not defined $limit) {
591 0         0 return CORE::split(' ', $string);
592             }
593             else {
594 0         0 return CORE::split(' ', $string, $limit);
595             }
596             }
597              
598             # if $limit is negative, it is treated as if an arbitrarily large $limit has been specified
599 0 0 0     0 if ((not defined $limit) or ($limit <= 0)) {
    0          
600              
601             # a pattern capable of matching either the null string or something longer than the
602             # null string will split the value of $string into separate characters wherever it
603             # matches the null string between characters
604             # (and so on)
605              
606 0 0       0 if ('' =~ / \A $pattern \z /xms) {
607 0         0 my $last_subexpression_offsets = _last_subexpression_offsets($pattern);
608 0         0 my $limit = scalar(() = $string =~ /($pattern)/oxmsg);
609              
610             # P.1024 Appendix W.10 Multibyte Processing
611             # of ISBN 1-56592-224-7 CJKV Information Processing
612             # (and so on)
613              
614             # the //m modifier is assumed when you split on the pattern /^/
615             # (and so on)
616              
617             # V
618 0   0     0 while ((--$limit > 0) and ($string =~ s/\A((?:$q_char)+?)$pattern//m)) {
619              
620             # if the $pattern contains parentheses, then the substring matched by each pair of parentheses
621             # is included in the resulting list, interspersed with the fields that are ordinarily returned
622             # (and so on)
623              
624 0         0 local $@;
625 0         0 for (my $digit=1; $digit <= ($last_subexpression_offsets + 1); $digit++) {
626 0         0 push @split, CORE::eval('$' . $digit);
627             }
628             }
629             }
630              
631             else {
632 0         0 my $last_subexpression_offsets = _last_subexpression_offsets($pattern);
633              
634             # V
635 0         0 while ($string =~ s/\A((?:$q_char)*?)$pattern//m) {
636 0         0 local $@;
637 0         0 for (my $digit=1; $digit <= ($last_subexpression_offsets + 1); $digit++) {
638 0         0 push @split, CORE::eval('$' . $digit);
639             }
640             }
641             }
642             }
643              
644             elsif ($limit > 0) {
645 0 0       0 if ('' =~ / \A $pattern \z /xms) {
646 0         0 my $last_subexpression_offsets = _last_subexpression_offsets($pattern);
647 0   0     0 while ((--$limit > 0) and (CORE::length($string) > 0)) {
648              
649             # V
650 0 0       0 if ($string =~ s/\A((?:$q_char)+?)$pattern//m) {
651 0         0 local $@;
652 0         0 for (my $digit=1; $digit <= ($last_subexpression_offsets + 1); $digit++) {
653 0         0 push @split, CORE::eval('$' . $digit);
654             }
655             }
656             }
657             }
658             else {
659 0         0 my $last_subexpression_offsets = _last_subexpression_offsets($pattern);
660 0   0     0 while ((--$limit > 0) and (CORE::length($string) > 0)) {
661              
662             # V
663 0 0       0 if ($string =~ s/\A((?:$q_char)*?)$pattern//m) {
664 0         0 local $@;
665 0         0 for (my $digit=1; $digit <= ($last_subexpression_offsets + 1); $digit++) {
666 0         0 push @split, CORE::eval('$' . $digit);
667             }
668             }
669             }
670             }
671             }
672              
673 0 0       0 if (CORE::length($string) > 0) {
674 0         0 push @split, $string;
675             }
676              
677             # if $_[2] (NOT "$limit") is omitted or zero, trailing null fields are stripped from the result
678 0 0 0     0 if ((not defined $_[2]) or ($_[2] == 0)) {
679 0   0     0 while ((scalar(@split) >= 1) and ($split[-1] eq '')) {
680 0         0 pop @split;
681             }
682             }
683              
684             # resulting list value in list context
685 0 0       0 if (wantarray) {
686 0         0 return @split;
687             }
688              
689             # count of substrings in scalar context
690             else {
691 0 0       0 carp "Use of implicit split to \@_ is deprecated" if $^W;
692 0         0 @_ = @split;
693 0         0 return scalar @_;
694             }
695             }
696              
697             #
698             # get last subexpression offsets
699             #
700             sub _last_subexpression_offsets {
701 0     0   0 my $pattern = $_[0];
702              
703             # remove comment
704 0         0 $pattern =~ s/\(\?\# .*? \)//oxmsg;
705              
706 0         0 my $modifier = '';
707 0 0       0 if ($pattern =~ /\(\?\^? ([\-A-Za-z]+) :/oxms) {
708 0         0 $modifier = $1;
709 0         0 $modifier =~ s/-[A-Za-z]*//;
710             }
711              
712             # with /x modifier
713 0         0 my @char = ();
714 0 0       0 if ($modifier =~ /x/oxms) {
715 0         0 @char = $pattern =~ /\G(
716             \\ (?:$q_char) |
717             \# (?:$q_char)*? $ |
718             \[ (?: \\\] | (?:$q_char))+? \] |
719             \(\? |
720             (?:$q_char)
721             )/oxmsg;
722             }
723              
724             # without /x modifier
725             else {
726 0         0 @char = $pattern =~ /\G(
727             \\ (?:$q_char) |
728             \[ (?: \\\] | (?:$q_char))+? \] |
729             \(\? |
730             (?:$q_char)
731             )/oxmsg;
732             }
733              
734 0         0 return scalar grep { $_ eq '(' } @char;
  0         0  
735             }
736              
737             #
738             # Cyrillic transliteration (tr///)
739             #
740             sub Char::Ecyrillic::tr($$$$;$) {
741              
742 0     0 0 0 my $bind_operator = $_[1];
743 0         0 my $searchlist = $_[2];
744 0         0 my $replacementlist = $_[3];
745 0   0     0 my $modifier = $_[4] || '';
746              
747 0 0       0 if ($modifier =~ /r/oxms) {
748 0 0       0 if ($bind_operator =~ / !~ /oxms) {
749 0         0 croak "Using !~ with tr///r doesn't make sense";
750             }
751             }
752              
753 0         0 my @char = $_[0] =~ /\G ($q_char) /oxmsg;
754 0         0 my @searchlist = _charlist_tr($searchlist);
755 0         0 my @replacementlist = _charlist_tr($replacementlist);
756              
757 0         0 my %tr = ();
758 0         0 for (my $i=0; $i <= $#searchlist; $i++) {
759 0 0       0 if (not exists $tr{$searchlist[$i]}) {
760 0 0 0     0 if (defined $replacementlist[$i] and ($replacementlist[$i] ne '')) {
    0 0        
    0          
761 0         0 $tr{$searchlist[$i]} = $replacementlist[$i];
762             }
763             elsif ($modifier =~ /d/oxms) {
764 0         0 $tr{$searchlist[$i]} = '';
765             }
766             elsif (defined $replacementlist[-1] and ($replacementlist[-1] ne '')) {
767 0         0 $tr{$searchlist[$i]} = $replacementlist[-1];
768             }
769             else {
770 0         0 $tr{$searchlist[$i]} = $searchlist[$i];
771             }
772             }
773             }
774              
775 0         0 my $tr = 0;
776 0         0 my $replaced = '';
777 0 0       0 if ($modifier =~ /c/oxms) {
778 0         0 while (defined(my $char = shift @char)) {
779 0 0       0 if (not exists $tr{$char}) {
780 0 0       0 if (defined $replacementlist[0]) {
781 0         0 $replaced .= $replacementlist[0];
782             }
783 0         0 $tr++;
784 0 0       0 if ($modifier =~ /s/oxms) {
785 0   0     0 while (@char and (not exists $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             else {
797 0         0 while (defined(my $char = shift @char)) {
798 0 0       0 if (exists $tr{$char}) {
799 0         0 $replaced .= $tr{$char};
800 0         0 $tr++;
801 0 0       0 if ($modifier =~ /s/oxms) {
802 0   0     0 while (@char and (exists $tr{$char[0]}) and ($tr{$char[0]} eq $tr{$char})) {
      0        
803 0         0 shift @char;
804 0         0 $tr++;
805             }
806             }
807             }
808             else {
809 0         0 $replaced .= $char;
810             }
811             }
812             }
813              
814 0 0       0 if ($modifier =~ /r/oxms) {
815 0         0 return $replaced;
816             }
817             else {
818 0         0 $_[0] = $replaced;
819 0 0       0 if ($bind_operator =~ / !~ /oxms) {
820 0         0 return not $tr;
821             }
822             else {
823 0         0 return $tr;
824             }
825             }
826             }
827              
828             #
829             # Cyrillic chop
830             #
831             sub Char::Ecyrillic::chop(@) {
832              
833 0     0 0 0 my $chop;
834 0 0       0 if (@_ == 0) {
835 0         0 my @char = /\G ($q_char) /oxmsg;
836 0         0 $chop = pop @char;
837 0         0 $_ = join '', @char;
838             }
839             else {
840 0         0 for (@_) {
841 0         0 my @char = /\G ($q_char) /oxmsg;
842 0         0 $chop = pop @char;
843 0         0 $_ = join '', @char;
844             }
845             }
846 0         0 return $chop;
847             }
848              
849             #
850             # Cyrillic index by octet
851             #
852             sub Char::Ecyrillic::index($$;$) {
853              
854 0     0 1 0 my($str,$substr,$position) = @_;
855 0   0     0 $position ||= 0;
856 0         0 my $pos = 0;
857              
858 0         0 while ($pos < CORE::length($str)) {
859 0 0       0 if (CORE::substr($str,$pos,CORE::length($substr)) eq $substr) {
860 0 0       0 if ($pos >= $position) {
861 0         0 return $pos;
862             }
863             }
864 0 0       0 if (CORE::substr($str,$pos) =~ /\A ($q_char) /oxms) {
865 0         0 $pos += CORE::length($1);
866             }
867             else {
868 0         0 $pos += 1;
869             }
870             }
871 0         0 return -1;
872             }
873              
874             #
875             # Cyrillic reverse index
876             #
877             sub Char::Ecyrillic::rindex($$;$) {
878              
879 0     0 0 0 my($str,$substr,$position) = @_;
880 0   0     0 $position ||= CORE::length($str) - 1;
881 0         0 my $pos = 0;
882 0         0 my $rindex = -1;
883              
884 0   0     0 while (($pos < CORE::length($str)) and ($pos <= $position)) {
885 0 0       0 if (CORE::substr($str,$pos,CORE::length($substr)) eq $substr) {
886 0         0 $rindex = $pos;
887             }
888 0 0       0 if (CORE::substr($str,$pos) =~ /\A ($q_char) /oxms) {
889 0         0 $pos += CORE::length($1);
890             }
891             else {
892 0         0 $pos += 1;
893             }
894             }
895 0         0 return $rindex;
896             }
897              
898             #
899             # Cyrillic lower case first with parameter
900             #
901             sub Char::Ecyrillic::lcfirst(@) {
902 0 0   0 0 0 if (@_) {
903 0         0 my $s = shift @_;
904 0 0 0     0 if (@_ and wantarray) {
905 0         0 return Char::Ecyrillic::lc(CORE::substr($s,0,1)) . CORE::substr($s,1), @_;
906             }
907             else {
908 0         0 return Char::Ecyrillic::lc(CORE::substr($s,0,1)) . CORE::substr($s,1);
909             }
910             }
911             else {
912 0         0 return Char::Ecyrillic::lc(CORE::substr($_,0,1)) . CORE::substr($_,1);
913             }
914             }
915              
916             #
917             # Cyrillic lower case first without parameter
918             #
919             sub Char::Ecyrillic::lcfirst_() {
920 0     0 0 0 return Char::Ecyrillic::lc(CORE::substr($_,0,1)) . CORE::substr($_,1);
921             }
922              
923             #
924             # Cyrillic lower case with parameter
925             #
926             sub Char::Ecyrillic::lc(@) {
927 0 0   0 0 0 if (@_) {
928 0         0 my $s = shift @_;
929 0 0 0     0 if (@_ and wantarray) {
930 0 0       0 return join('', map {defined($lc{$_}) ? $lc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg)), @_;
  0         0  
931             }
932             else {
933 0 0       0 return join('', map {defined($lc{$_}) ? $lc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg));
  0         0  
934             }
935             }
936             else {
937 0         0 return Char::Ecyrillic::lc_();
938             }
939             }
940              
941             #
942             # Cyrillic lower case without parameter
943             #
944             sub Char::Ecyrillic::lc_() {
945 0     0 0 0 my $s = $_;
946 0 0       0 return join '', map {defined($lc{$_}) ? $lc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg);
  0         0  
947             }
948              
949             #
950             # Cyrillic upper case first with parameter
951             #
952             sub Char::Ecyrillic::ucfirst(@) {
953 0 0   0 0 0 if (@_) {
954 0         0 my $s = shift @_;
955 0 0 0     0 if (@_ and wantarray) {
956 0         0 return Char::Ecyrillic::uc(CORE::substr($s,0,1)) . CORE::substr($s,1), @_;
957             }
958             else {
959 0         0 return Char::Ecyrillic::uc(CORE::substr($s,0,1)) . CORE::substr($s,1);
960             }
961             }
962             else {
963 0         0 return Char::Ecyrillic::uc(CORE::substr($_,0,1)) . CORE::substr($_,1);
964             }
965             }
966              
967             #
968             # Cyrillic upper case first without parameter
969             #
970             sub Char::Ecyrillic::ucfirst_() {
971 0     0 0 0 return Char::Ecyrillic::uc(CORE::substr($_,0,1)) . CORE::substr($_,1);
972             }
973              
974             #
975             # Cyrillic upper case with parameter
976             #
977             sub Char::Ecyrillic::uc(@) {
978 0 0   0 0 0 if (@_) {
979 0         0 my $s = shift @_;
980 0 0 0     0 if (@_ and wantarray) {
981 0 0       0 return join('', map {defined($uc{$_}) ? $uc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg)), @_;
  0         0  
982             }
983             else {
984 0 0       0 return join('', map {defined($uc{$_}) ? $uc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg));
  0         0  
985             }
986             }
987             else {
988 0         0 return Char::Ecyrillic::uc_();
989             }
990             }
991              
992             #
993             # Cyrillic upper case without parameter
994             #
995             sub Char::Ecyrillic::uc_() {
996 0     0 0 0 my $s = $_;
997 0 0       0 return join '', map {defined($uc{$_}) ? $uc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg);
  0         0  
998             }
999              
1000             #
1001             # Cyrillic fold case with parameter
1002             #
1003             sub Char::Ecyrillic::fc(@) {
1004 0 0   0 0 0 if (@_) {
1005 0         0 my $s = shift @_;
1006 0 0 0     0 if (@_ and wantarray) {
1007 0 0       0 return join('', map {defined($fc{$_}) ? $fc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg)), @_;
  0         0  
1008             }
1009             else {
1010 0 0       0 return join('', map {defined($fc{$_}) ? $fc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg));
  0         0  
1011             }
1012             }
1013             else {
1014 0         0 return Char::Ecyrillic::fc_();
1015             }
1016             }
1017              
1018             #
1019             # Cyrillic fold case without parameter
1020             #
1021             sub Char::Ecyrillic::fc_() {
1022 0     0 0 0 my $s = $_;
1023 0 0       0 return join '', map {defined($fc{$_}) ? $fc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg);
  0         0  
1024             }
1025              
1026             #
1027             # Cyrillic regexp capture
1028             #
1029             {
1030             sub Char::Ecyrillic::capture {
1031 0     0 1 0 return $_[0];
1032             }
1033             }
1034              
1035             #
1036             # Cyrillic regexp ignore case modifier
1037             #
1038             sub Char::Ecyrillic::ignorecase {
1039              
1040 0     0 0 0 my @string = @_;
1041 0         0 my $metachar = qr/[\@\\|[\]{]/oxms;
1042              
1043             # ignore case of $scalar or @array
1044 0         0 for my $string (@string) {
1045              
1046             # split regexp
1047 0         0 my @char = $string =~ /\G(
1048             \[\^ |
1049             \\? (?:$q_char)
1050             )/oxmsg;
1051              
1052             # unescape character
1053 0         0 for (my $i=0; $i <= $#char; $i++) {
1054 0 0       0 next if not defined $char[$i];
1055              
1056             # open character class [...]
1057 0 0       0 if ($char[$i] eq '[') {
    0          
    0          
    0          
1058 0         0 my $left = $i;
1059              
1060             # [] make die "unmatched [] in regexp ..."
1061              
1062 0 0       0 if ($char[$i+1] eq ']') {
1063 0         0 $i++;
1064             }
1065              
1066 0         0 while (1) {
1067 0 0       0 if (++$i > $#char) {
1068 0         0 croak "Unmatched [] in regexp";
1069             }
1070 0 0       0 if ($char[$i] eq ']') {
1071 0         0 my $right = $i;
1072 0         0 my @charlist = charlist_qr(@char[$left+1..$right-1], 'i');
1073              
1074             # escape character
1075 0         0 for my $char (@charlist) {
1076 0 0       0 if (0) {
1077             }
1078              
1079 0         0 elsif ($char =~ /\A [.|)] \z/oxms) {
1080 0         0 $char = $1 . '\\' . $char;
1081             }
1082             }
1083              
1084             # [...]
1085 0         0 splice @char, $left, $right-$left+1, '(?:' . join('|', @charlist) . ')';
1086              
1087 0         0 $i = $left;
1088 0         0 last;
1089             }
1090             }
1091             }
1092              
1093             # open character class [^...]
1094             elsif ($char[$i] eq '[^') {
1095 0         0 my $left = $i;
1096              
1097             # [^] make die "unmatched [] in regexp ..."
1098              
1099 0 0       0 if ($char[$i+1] eq ']') {
1100 0         0 $i++;
1101             }
1102              
1103 0         0 while (1) {
1104 0 0       0 if (++$i > $#char) {
1105 0         0 croak "Unmatched [] in regexp";
1106             }
1107 0 0       0 if ($char[$i] eq ']') {
1108 0         0 my $right = $i;
1109 0         0 my @charlist = charlist_not_qr(@char[$left+1..$right-1], 'i');
1110              
1111             # escape character
1112 0         0 for my $char (@charlist) {
1113 0 0       0 if (0) {
1114             }
1115              
1116 0         0 elsif ($char =~ /\A [.|)] \z/oxms) {
1117 0         0 $char = '\\' . $char;
1118             }
1119             }
1120              
1121             # [^...]
1122 0         0 splice @char, $left, $right-$left+1, '(?!' . join('|', @charlist) . ")(?:$your_char)";
1123              
1124 0         0 $i = $left;
1125 0         0 last;
1126             }
1127             }
1128             }
1129              
1130             # rewrite classic character class or escape character
1131             elsif (my $char = classic_character_class($char[$i])) {
1132 0         0 $char[$i] = $char;
1133             }
1134              
1135             # with /i modifier
1136             elsif ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) {
1137 0         0 my $uc = Char::Ecyrillic::uc($char[$i]);
1138 0         0 my $fc = Char::Ecyrillic::fc($char[$i]);
1139 0 0       0 if ($uc ne $fc) {
1140 0 0       0 if (CORE::length($fc) == 1) {
1141 0         0 $char[$i] = '[' . $uc . $fc . ']';
1142             }
1143             else {
1144 0         0 $char[$i] = '(?:' . $uc . '|' . $fc . ')';
1145             }
1146             }
1147             }
1148             }
1149              
1150             # characterize
1151 0         0 for (my $i=0; $i <= $#char; $i++) {
1152 0 0       0 next if not defined $char[$i];
1153              
1154 0 0       0 if (0) {
1155             }
1156              
1157             # quote character before ? + * {
1158 0 0       0 elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
1159 0 0       0 if ($char[$i-1] !~ /\A [\x00-\xFF] \z/oxms) {
1160 0         0 $char[$i-1] = '(?:' . $char[$i-1] . ')';
1161             }
1162             }
1163             }
1164              
1165 0         0 $string = join '', @char;
1166             }
1167              
1168             # make regexp string
1169 0         0 return @string;
1170             }
1171              
1172             #
1173             # classic character class ( \D \S \W \d \s \w \C \X \H \V \h \v \R \N \b \B )
1174             #
1175             sub Char::Ecyrillic::classic_character_class {
1176 0     0 0 0 my($char) = @_;
1177              
1178             return {
1179 0   0     0 '\D' => '${Char::Ecyrillic::eD}',
1180             '\S' => '${Char::Ecyrillic::eS}',
1181             '\W' => '${Char::Ecyrillic::eW}',
1182             '\d' => '[0-9]',
1183              
1184             # Before Perl 5.6, \s only matched the five whitespace characters
1185             # tab, newline, form-feed, carriage return, and the space character
1186             # itself, which, taken together, is the character class [\t\n\f\r ].
1187              
1188             # Vertical tabs are now whitespace
1189             # \s in a regex now matches a vertical tab in all circumstances.
1190             # http://search.cpan.org/dist/perl-5.18.0/pod/perldelta.pod#Vertical_tabs_are_now_whitespace
1191             # \t \n \v \f \r space
1192             # '\s' => '[\x09\x0A \x0C\x0D\x20]',
1193             # '\s' => '[\x09\x0A\x0B\x0C\x0D\x20]',
1194             '\s' => '\s',
1195              
1196             '\w' => '[0-9A-Z_a-z]',
1197             '\C' => '[\x00-\xFF]',
1198             '\X' => 'X',
1199              
1200             # \h \v \H \V
1201              
1202             # P.114 Character Class Shortcuts
1203             # in Chapter 7: In the World of Regular Expressions
1204             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
1205              
1206             # P.357 13.2.3 Whitespace
1207             # in Chapter 13: perlrecharclass: Perl Regular Expression Character Classes
1208             # of ISBN-13: 978-1-906966-02-7 The Perl Language Reference Manual (for Perl version 5.12.1)
1209             #
1210             # 0x00009 CHARACTER TABULATION h s
1211             # 0x0000a LINE FEED (LF) vs
1212             # 0x0000b LINE TABULATION v
1213             # 0x0000c FORM FEED (FF) vs
1214             # 0x0000d CARRIAGE RETURN (CR) vs
1215             # 0x00020 SPACE h s
1216              
1217             # P.196 Table 5-9. Alphanumeric regex metasymbols
1218             # in Chapter 5. Pattern Matching
1219             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
1220              
1221             # (and so on)
1222              
1223             '\H' => '${Char::Ecyrillic::eH}',
1224             '\V' => '${Char::Ecyrillic::eV}',
1225             '\h' => '[\x09\x20]',
1226             '\v' => '[\x0A\x0B\x0C\x0D]',
1227             '\R' => '${Char::Ecyrillic::eR}',
1228              
1229             # \N
1230             #
1231             # http://perldoc.perl.org/perlre.html
1232             # Character Classes and other Special Escapes
1233             # Any character but \n (experimental). Not affected by /s modifier
1234              
1235             '\N' => '${Char::Ecyrillic::eN}',
1236              
1237             # \b \B
1238              
1239             # P.180 Boundaries: The \b and \B Assertions
1240             # in Chapter 5: Pattern Matching
1241             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
1242              
1243             # P.219 Boundaries: The \b and \B Assertions
1244             # in Chapter 5: Pattern Matching
1245             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
1246              
1247             # '\b' => '(?:(?<=\A|\W)(?=\w)|(?<=\w)(?=\W|\z))',
1248             '\b' => '${Char::Ecyrillic::eb}',
1249              
1250             # '\B' => '(?:(?<=\w)(?=\w)|(?<=\W)(?=\W))',
1251             '\B' => '${Char::Ecyrillic::eB}',
1252              
1253             }->{$char} || '';
1254             }
1255              
1256             #
1257             # prepare Cyrillic characters per length
1258             #
1259              
1260             # 1 octet characters
1261             my @chars1 = ();
1262             sub chars1 {
1263 0 0   0 0 0 if (@chars1) {
1264 0         0 return @chars1;
1265             }
1266 0 0       0 if (exists $range_tr{1}) {
1267 0         0 my @ranges = @{ $range_tr{1} };
  0         0  
1268 0         0 while (my @range = splice(@ranges,0,1)) {
1269 0         0 for my $oct0 (@{$range[0]}) {
  0         0  
1270 0         0 push @chars1, pack 'C', $oct0;
1271             }
1272             }
1273             }
1274 0         0 return @chars1;
1275             }
1276              
1277             # 2 octets characters
1278             my @chars2 = ();
1279             sub chars2 {
1280 0 0   0 0 0 if (@chars2) {
1281 0         0 return @chars2;
1282             }
1283 0 0       0 if (exists $range_tr{2}) {
1284 0         0 my @ranges = @{ $range_tr{2} };
  0         0  
1285 0         0 while (my @range = splice(@ranges,0,2)) {
1286 0         0 for my $oct0 (@{$range[0]}) {
  0         0  
1287 0         0 for my $oct1 (@{$range[1]}) {
  0         0  
1288 0         0 push @chars2, pack 'CC', $oct0,$oct1;
1289             }
1290             }
1291             }
1292             }
1293 0         0 return @chars2;
1294             }
1295              
1296             # 3 octets characters
1297             my @chars3 = ();
1298             sub chars3 {
1299 0 0   0 0 0 if (@chars3) {
1300 0         0 return @chars3;
1301             }
1302 0 0       0 if (exists $range_tr{3}) {
1303 0         0 my @ranges = @{ $range_tr{3} };
  0         0  
1304 0         0 while (my @range = splice(@ranges,0,3)) {
1305 0         0 for my $oct0 (@{$range[0]}) {
  0         0  
1306 0         0 for my $oct1 (@{$range[1]}) {
  0         0  
1307 0         0 for my $oct2 (@{$range[2]}) {
  0         0  
1308 0         0 push @chars3, pack 'CCC', $oct0,$oct1,$oct2;
1309             }
1310             }
1311             }
1312             }
1313             }
1314 0         0 return @chars3;
1315             }
1316              
1317             # 4 octets characters
1318             my @chars4 = ();
1319             sub chars4 {
1320 0 0   0 0 0 if (@chars4) {
1321 0         0 return @chars4;
1322             }
1323 0 0       0 if (exists $range_tr{4}) {
1324 0         0 my @ranges = @{ $range_tr{4} };
  0         0  
1325 0         0 while (my @range = splice(@ranges,0,4)) {
1326 0         0 for my $oct0 (@{$range[0]}) {
  0         0  
1327 0         0 for my $oct1 (@{$range[1]}) {
  0         0  
1328 0         0 for my $oct2 (@{$range[2]}) {
  0         0  
1329 0         0 for my $oct3 (@{$range[3]}) {
  0         0  
1330 0         0 push @chars4, pack 'CCCC', $oct0,$oct1,$oct2,$oct3;
1331             }
1332             }
1333             }
1334             }
1335             }
1336             }
1337 0         0 return @chars4;
1338             }
1339              
1340             #
1341             # Cyrillic open character list for tr
1342             #
1343             sub _charlist_tr {
1344              
1345 0     0   0 local $_ = shift @_;
1346              
1347             # unescape character
1348 0         0 my @char = ();
1349 0         0 while (not /\G \z/oxmsgc) {
1350 0 0       0 if (/\G (\\0?55|\\x2[Dd]|\\-) /oxmsgc) {
    0          
    0          
    0          
    0          
    0          
    0          
1351 0         0 push @char, '\-';
1352             }
1353             elsif (/\G \\ ([0-7]{2,3}) /oxmsgc) {
1354 0         0 push @char, CORE::chr(oct $1);
1355             }
1356             elsif (/\G \\x ([0-9A-Fa-f]{1,2}) /oxmsgc) {
1357 0         0 push @char, CORE::chr(hex $1);
1358             }
1359             elsif (/\G \\c ([\x40-\x5F]) /oxmsgc) {
1360 0         0 push @char, CORE::chr(CORE::ord($1) & 0x1F);
1361             }
1362             elsif (/\G (\\ [0nrtfbae]) /oxmsgc) {
1363 0         0 push @char, {
1364             '\0' => "\0",
1365             '\n' => "\n",
1366             '\r' => "\r",
1367             '\t' => "\t",
1368             '\f' => "\f",
1369             '\b' => "\x08", # \b means backspace in character class
1370             '\a' => "\a",
1371             '\e' => "\e",
1372             }->{$1};
1373             }
1374             elsif (/\G \\ ($q_char) /oxmsgc) {
1375 0         0 push @char, $1;
1376             }
1377             elsif (/\G ($q_char) /oxmsgc) {
1378 0         0 push @char, $1;
1379             }
1380             }
1381              
1382             # join separated multiple-octet
1383 0         0 @char = join('',@char) =~ /\G (\\-|$q_char) /oxmsg;
1384              
1385             # unescape '-'
1386 0         0 my @i = ();
1387 0         0 for my $i (0 .. $#char) {
1388 0 0       0 if ($char[$i] eq '\-') {
    0          
1389 0         0 $char[$i] = '-';
1390             }
1391             elsif ($char[$i] eq '-') {
1392 0 0 0     0 if ((0 < $i) and ($i < $#char)) {
1393 0         0 push @i, $i;
1394             }
1395             }
1396             }
1397              
1398             # open character list (reverse for splice)
1399 0         0 for my $i (CORE::reverse @i) {
1400 0         0 my @range = ();
1401              
1402             # range error
1403 0 0 0     0 if ((CORE::length($char[$i-1]) > CORE::length($char[$i+1])) or ($char[$i-1] gt $char[$i+1])) {
1404 0         0 croak "Invalid tr/// range \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1405             }
1406              
1407             # range of multiple-octet code
1408 0 0       0 if (CORE::length($char[$i-1]) == 1) {
    0          
    0          
    0          
1409 0 0       0 if (CORE::length($char[$i+1]) == 1) {
    0          
    0          
    0          
1410 0 0       0 push @range, grep {($char[$i-1] le $_) and ($_ le $char[$i+1])} chars1();
  0         0  
1411             }
1412             elsif (CORE::length($char[$i+1]) == 2) {
1413 0         0 push @range, grep {$char[$i-1] le $_} chars1();
  0         0  
1414 0         0 push @range, grep {$_ le $char[$i+1]} chars2();
  0         0  
1415             }
1416             elsif (CORE::length($char[$i+1]) == 3) {
1417 0         0 push @range, grep {$char[$i-1] le $_} chars1();
  0         0  
1418 0         0 push @range, chars2();
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 $_} chars1();
  0         0  
1423 0         0 push @range, chars2();
1424 0         0 push @range, chars3();
1425 0         0 push @range, grep {$_ le $char[$i+1]} chars4();
  0         0  
1426             }
1427             else {
1428 0         0 croak "Invalid tr/// range (over 4octets) \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1429             }
1430             }
1431             elsif (CORE::length($char[$i-1]) == 2) {
1432 0 0       0 if (CORE::length($char[$i+1]) == 2) {
    0          
    0          
1433 0 0       0 push @range, grep {($char[$i-1] le $_) and ($_ le $char[$i+1])} chars2();
  0         0  
1434             }
1435             elsif (CORE::length($char[$i+1]) == 3) {
1436 0         0 push @range, grep {$char[$i-1] le $_} chars2();
  0         0  
1437 0         0 push @range, grep {$_ le $char[$i+1]} chars3();
  0         0  
1438             }
1439             elsif (CORE::length($char[$i+1]) == 4) {
1440 0         0 push @range, grep {$char[$i-1] le $_} chars2();
  0         0  
1441 0         0 push @range, chars3();
1442 0         0 push @range, grep {$_ le $char[$i+1]} chars4();
  0         0  
1443             }
1444             else {
1445 0         0 croak "Invalid tr/// range (over 4octets) \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1446             }
1447             }
1448             elsif (CORE::length($char[$i-1]) == 3) {
1449 0 0       0 if (CORE::length($char[$i+1]) == 3) {
    0          
1450 0 0       0 push @range, grep {($char[$i-1] le $_) and ($_ le $char[$i+1])} chars3();
  0         0  
1451             }
1452             elsif (CORE::length($char[$i+1]) == 4) {
1453 0         0 push @range, grep {$char[$i-1] le $_} chars3();
  0         0  
1454 0         0 push @range, grep {$_ le $char[$i+1]} chars4();
  0         0  
1455             }
1456             else {
1457 0         0 croak "Invalid tr/// range (over 4octets) \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1458             }
1459             }
1460             elsif (CORE::length($char[$i-1]) == 4) {
1461 0 0       0 if (CORE::length($char[$i+1]) == 4) {
1462 0 0       0 push @range, grep {($char[$i-1] le $_) and ($_ le $char[$i+1])} chars4();
  0         0  
1463             }
1464             else {
1465 0         0 croak "Invalid tr/// range (over 4octets) \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1466             }
1467             }
1468             else {
1469 0         0 croak "Invalid tr/// range (over 4octets) \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1470             }
1471              
1472 0         0 splice @char, $i-1, 3, @range;
1473             }
1474              
1475 0         0 return @char;
1476             }
1477              
1478             #
1479             # Cyrillic open character class
1480             #
1481             sub _cc {
1482 0 0   0   0 if (scalar(@_) == 0) {
    0          
    0          
1483 0         0 die __FILE__, ": subroutine cc got no parameter.";
1484             }
1485             elsif (scalar(@_) == 1) {
1486 0         0 return sprintf('\x%02X',$_[0]);
1487             }
1488             elsif (scalar(@_) == 2) {
1489 0 0       0 if ($_[0] > $_[1]) {
    0          
    0          
1490 0         0 die __FILE__, ": subroutine cc got \$_[0] > \$_[1] parameters).";
1491             }
1492             elsif ($_[0] == $_[1]) {
1493 0         0 return sprintf('\x%02X',$_[0]);
1494             }
1495             elsif (($_[0]+1) == $_[1]) {
1496 0         0 return sprintf('[\\x%02X\\x%02X]',$_[0],$_[1]);
1497             }
1498             else {
1499 0         0 return sprintf('[\\x%02X-\\x%02X]',$_[0],$_[1]);
1500             }
1501             }
1502             else {
1503 0         0 die __FILE__, ": subroutine cc got 3 or more parameters (@{[scalar(@_)]} parameters).";
  0         0  
1504             }
1505             }
1506              
1507             #
1508             # Cyrillic octet range
1509             #
1510             sub _octets {
1511 0     0   0 my $length = shift @_;
1512              
1513 0 0       0 if ($length == 1) {
1514 0         0 my($a1) = unpack 'C', $_[0];
1515 0         0 my($z1) = unpack 'C', $_[1];
1516              
1517 0 0       0 if ($a1 > $z1) {
1518 0         0 croak 'Invalid [] range in regexp (CORE::ord(A) > CORE::ord(B)) ' . '\x' . unpack('H*',$a1) . '-\x' . unpack('H*',$z1);
1519             }
1520              
1521 0 0       0 if ($a1 == $z1) {
    0          
1522 0         0 return sprintf('\x%02X',$a1);
1523             }
1524             elsif (($a1+1) == $z1) {
1525 0         0 return sprintf('\x%02X\x%02X',$a1,$z1);
1526             }
1527             else {
1528 0         0 return sprintf('\x%02X-\x%02X',$a1,$z1);
1529             }
1530             }
1531             else {
1532 0         0 die __FILE__, ": subroutine _octets got invalid length ($length).";
1533             }
1534             }
1535              
1536             #
1537             # Cyrillic range regexp
1538             #
1539             sub _range_regexp {
1540 0     0   0 my($length,$first,$last) = @_;
1541              
1542 0         0 my @range_regexp = ();
1543 0 0       0 if (not exists $range_tr{$length}) {
1544 0         0 return @range_regexp;
1545             }
1546              
1547 0         0 my @ranges = @{ $range_tr{$length} };
  0         0  
1548 0         0 while (my @range = splice(@ranges,0,$length)) {
1549 0         0 my $min = '';
1550 0         0 my $max = '';
1551 0         0 for (my $i=0; $i < $length; $i++) {
1552 0         0 $min .= pack 'C', $range[$i][0];
1553 0         0 $max .= pack 'C', $range[$i][-1];
1554             }
1555              
1556             # min___max
1557             # FIRST_____________LAST
1558             # (nothing)
1559              
1560 0 0 0     0 if ($max lt $first) {
    0 0        
    0 0        
    0 0        
    0 0        
    0 0        
    0 0        
1561             }
1562              
1563             # **********
1564             # min_________max
1565             # FIRST_____________LAST
1566             # **********
1567              
1568             elsif (($min le $first) and ($first le $max) and ($max le $last)) {
1569 0         0 push @range_regexp, _octets($length,$first,$max,$min,$max);
1570             }
1571              
1572             # **********************
1573             # min________________max
1574             # FIRST_____________LAST
1575             # **********************
1576              
1577             elsif (($min eq $first) and ($max eq $last)) {
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 ($max le $last)) {
1587 0         0 push @range_regexp, _octets($length,$min,$max,$min,$max);
1588             }
1589              
1590             # **********************
1591             # min__________________________max
1592             # FIRST_____________LAST
1593             # **********************
1594              
1595             elsif (($min le $first) and ($last le $max)) {
1596 0         0 push @range_regexp, _octets($length,$first,$last,$min,$max);
1597             }
1598              
1599             # *********
1600             # min________max
1601             # FIRST_____________LAST
1602             # *********
1603              
1604             elsif (($first le $min) and ($min le $last) and ($last le $max)) {
1605 0         0 push @range_regexp, _octets($length,$min,$last,$min,$max);
1606             }
1607              
1608             # min___max
1609             # FIRST_____________LAST
1610             # (nothing)
1611              
1612             elsif ($last lt $min) {
1613             }
1614              
1615             else {
1616 0         0 die __FILE__, ": subroutine _range_regexp panic.";
1617             }
1618             }
1619              
1620 0         0 return @range_regexp;
1621             }
1622              
1623             #
1624             # Cyrillic open character list for qr and not qr
1625             #
1626             sub _charlist {
1627              
1628 0     0   0 my $modifier = pop @_;
1629 0         0 my @char = @_;
1630              
1631 0 0       0 my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
1632              
1633             # unescape character
1634 0         0 for (my $i=0; $i <= $#char; $i++) {
1635              
1636             # escape - to ...
1637 0 0 0     0 if ($char[$i] eq '-') {
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
1638 0 0 0     0 if ((0 < $i) and ($i < $#char)) {
1639 0         0 $char[$i] = '...';
1640             }
1641             }
1642              
1643             # octal escape sequence
1644             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
1645 0         0 $char[$i] = octchr($1);
1646             }
1647              
1648             # hexadecimal escape sequence
1649             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
1650 0         0 $char[$i] = hexchr($1);
1651             }
1652              
1653             # \N{CHARNAME} --> N\{CHARNAME}
1654             elsif ($char[$i] =~ /\A \\ (N) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
1655 0         0 $char[$i] = $1 . '\\' . $2;
1656             }
1657              
1658             # \p{PROPERTY} --> p\{PROPERTY}
1659             elsif ($char[$i] =~ /\A \\ (p) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
1660 0         0 $char[$i] = $1 . '\\' . $2;
1661             }
1662              
1663             # \P{PROPERTY} --> P\{PROPERTY}
1664             elsif ($char[$i] =~ /\A \\ (P) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
1665 0         0 $char[$i] = $1 . '\\' . $2;
1666             }
1667              
1668             # \p, \P, \X --> p, P, X
1669             elsif ($char[$i] =~ /\A \\ ( [pPX] ) \z/oxms) {
1670 0         0 $char[$i] = $1;
1671             }
1672              
1673             elsif ($char[$i] =~ /\A \\ ([0-7]{2,3}) \z/oxms) {
1674 0         0 $char[$i] = CORE::chr oct $1;
1675             }
1676             elsif ($char[$i] =~ /\A \\x ([0-9A-Fa-f]{1,2}) \z/oxms) {
1677 0         0 $char[$i] = CORE::chr hex $1;
1678             }
1679             elsif ($char[$i] =~ /\A \\c ([\x40-\x5F]) \z/oxms) {
1680 0         0 $char[$i] = CORE::chr(CORE::ord($1) & 0x1F);
1681             }
1682             elsif ($char[$i] =~ /\A (\\ [0nrtfbaedswDSWHVhvR]) \z/oxms) {
1683 0         0 $char[$i] = {
1684             '\0' => "\0",
1685             '\n' => "\n",
1686             '\r' => "\r",
1687             '\t' => "\t",
1688             '\f' => "\f",
1689             '\b' => "\x08", # \b means backspace in character class
1690             '\a' => "\a",
1691             '\e' => "\e",
1692             '\d' => '[0-9]',
1693              
1694             # Vertical tabs are now whitespace
1695             # \s in a regex now matches a vertical tab in all circumstances.
1696             # http://search.cpan.org/dist/perl-5.18.0/pod/perldelta.pod#Vertical_tabs_are_now_whitespace
1697             # \t \n \v \f \r space
1698             # '\s' => '[\x09\x0A \x0C\x0D\x20]',
1699             # '\s' => '[\x09\x0A\x0B\x0C\x0D\x20]',
1700             '\s' => '\s',
1701              
1702             '\w' => '[0-9A-Z_a-z]',
1703             '\D' => '${Char::Ecyrillic::eD}',
1704             '\S' => '${Char::Ecyrillic::eS}',
1705             '\W' => '${Char::Ecyrillic::eW}',
1706              
1707             '\H' => '${Char::Ecyrillic::eH}',
1708             '\V' => '${Char::Ecyrillic::eV}',
1709             '\h' => '[\x09\x20]',
1710             '\v' => '[\x0A\x0B\x0C\x0D]',
1711             '\R' => '${Char::Ecyrillic::eR}',
1712              
1713             }->{$1};
1714             }
1715              
1716             # POSIX-style character classes
1717             elsif ($ignorecase and ($char[$i] =~ /\A ( \[\: \^? (?:lower|upper) :\] ) \z/oxms)) {
1718 0         0 $char[$i] = {
1719              
1720             '[:lower:]' => '[\x41-\x5A\x61-\x7A]',
1721             '[:upper:]' => '[\x41-\x5A\x61-\x7A]',
1722             '[:^lower:]' => '${Char::Ecyrillic::not_lower_i}',
1723             '[:^upper:]' => '${Char::Ecyrillic::not_upper_i}',
1724              
1725             }->{$1};
1726             }
1727             elsif ($char[$i] =~ /\A ( \[\: \^? (?:alnum|alpha|ascii|blank|cntrl|digit|graph|lower|print|punct|space|upper|word|xdigit) :\] ) \z/oxms) {
1728 0         0 $char[$i] = {
1729              
1730             '[:alnum:]' => '[\x30-\x39\x41-\x5A\x61-\x7A]',
1731             '[:alpha:]' => '[\x41-\x5A\x61-\x7A]',
1732             '[:ascii:]' => '[\x00-\x7F]',
1733             '[:blank:]' => '[\x09\x20]',
1734             '[:cntrl:]' => '[\x00-\x1F\x7F]',
1735             '[:digit:]' => '[\x30-\x39]',
1736             '[:graph:]' => '[\x21-\x7F]',
1737             '[:lower:]' => '[\x61-\x7A]',
1738             '[:print:]' => '[\x20-\x7F]',
1739             '[:punct:]' => '[\x21-\x2F\x3A-\x3F\x40\x5B-\x5F\x60\x7B-\x7E]',
1740              
1741             # P.174 POSIX-Style Character Classes
1742             # in Chapter 5: Pattern Matching
1743             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
1744              
1745             # P.311 11.2.4 Character Classes and other Special Escapes
1746             # in Chapter 11: perlre: Perl regular expressions
1747             # of ISBN-13: 978-1-906966-02-7 The Perl Language Reference Manual (for Perl version 5.12.1)
1748              
1749             # P.210 POSIX-Style Character Classes
1750             # in Chapter 5: Pattern Matching
1751             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
1752              
1753             '[:space:]' => '[\s\x0B]', # "\s" plus vertical tab ("\cK")
1754              
1755             '[:upper:]' => '[\x41-\x5A]',
1756             '[:word:]' => '[\x30-\x39\x41-\x5A\x5F\x61-\x7A]',
1757             '[:xdigit:]' => '[\x30-\x39\x41-\x46\x61-\x66]',
1758             '[:^alnum:]' => '${Char::Ecyrillic::not_alnum}',
1759             '[:^alpha:]' => '${Char::Ecyrillic::not_alpha}',
1760             '[:^ascii:]' => '${Char::Ecyrillic::not_ascii}',
1761             '[:^blank:]' => '${Char::Ecyrillic::not_blank}',
1762             '[:^cntrl:]' => '${Char::Ecyrillic::not_cntrl}',
1763             '[:^digit:]' => '${Char::Ecyrillic::not_digit}',
1764             '[:^graph:]' => '${Char::Ecyrillic::not_graph}',
1765             '[:^lower:]' => '${Char::Ecyrillic::not_lower}',
1766             '[:^print:]' => '${Char::Ecyrillic::not_print}',
1767             '[:^punct:]' => '${Char::Ecyrillic::not_punct}',
1768             '[:^space:]' => '${Char::Ecyrillic::not_space}',
1769             '[:^upper:]' => '${Char::Ecyrillic::not_upper}',
1770             '[:^word:]' => '${Char::Ecyrillic::not_word}',
1771             '[:^xdigit:]' => '${Char::Ecyrillic::not_xdigit}',
1772              
1773             }->{$1};
1774             }
1775             elsif ($char[$i] =~ /\A \\ ($q_char) \z/oxms) {
1776 0         0 $char[$i] = $1;
1777             }
1778             }
1779              
1780             # open character list
1781 0         0 my @singleoctet = ();
1782 0         0 my @multipleoctet = ();
1783 0         0 for (my $i=0; $i <= $#char; ) {
1784              
1785             # escaped -
1786 0 0 0     0 if (defined($char[$i+1]) and ($char[$i+1] eq '...')) {
    0          
    0          
    0          
    0          
    0          
1787 0         0 $i += 1;
1788 0         0 next;
1789             }
1790              
1791             # make range regexp
1792             elsif ($char[$i] eq '...') {
1793              
1794             # range error
1795 0 0       0 if (CORE::length($char[$i-1]) > CORE::length($char[$i+1])) {
    0          
1796 0         0 croak 'Invalid [] range in regexp (length(A) > length(B)) ' . '\x' . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]);
1797             }
1798             elsif (CORE::length($char[$i-1]) == CORE::length($char[$i+1])) {
1799 0 0       0 if ($char[$i-1] gt $char[$i+1]) {
1800 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]);
1801             }
1802             }
1803              
1804             # make range regexp per length
1805 0         0 for my $length (CORE::length($char[$i-1]) .. CORE::length($char[$i+1])) {
1806 0         0 my @regexp = ();
1807              
1808             # is first and last
1809 0 0 0     0 if (($length == CORE::length($char[$i-1])) and ($length == CORE::length($char[$i+1]))) {
    0 0        
    0          
    0          
1810 0         0 push @regexp, _range_regexp($length, $char[$i-1], $char[$i+1]);
1811             }
1812              
1813             # is first
1814             elsif ($length == CORE::length($char[$i-1])) {
1815 0         0 push @regexp, _range_regexp($length, $char[$i-1], "\xFF" x $length);
1816             }
1817              
1818             # is inside in first and last
1819             elsif ((CORE::length($char[$i-1]) < $length) and ($length < CORE::length($char[$i+1]))) {
1820 0         0 push @regexp, _range_regexp($length, "\x00" x $length, "\xFF" x $length);
1821             }
1822              
1823             # is last
1824             elsif ($length == CORE::length($char[$i+1])) {
1825 0         0 push @regexp, _range_regexp($length, "\x00" x $length, $char[$i+1]);
1826             }
1827              
1828             else {
1829 0         0 die __FILE__, ": subroutine make_regexp panic.";
1830             }
1831              
1832 0 0       0 if ($length == 1) {
1833 0         0 push @singleoctet, @regexp;
1834             }
1835             else {
1836 0         0 push @multipleoctet, @regexp;
1837             }
1838             }
1839              
1840 0         0 $i += 2;
1841             }
1842              
1843             # with /i modifier
1844             elsif ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) {
1845 0 0       0 if ($modifier =~ /i/oxms) {
1846 0         0 my $uc = Char::Ecyrillic::uc($char[$i]);
1847 0         0 my $fc = Char::Ecyrillic::fc($char[$i]);
1848 0 0       0 if ($uc ne $fc) {
1849 0 0       0 if (CORE::length($fc) == 1) {
1850 0         0 push @singleoctet, $uc, $fc;
1851             }
1852             else {
1853 0         0 push @singleoctet, $uc;
1854 0         0 push @multipleoctet, $fc;
1855             }
1856             }
1857             else {
1858 0         0 push @singleoctet, $char[$i];
1859             }
1860             }
1861             else {
1862 0         0 push @singleoctet, $char[$i];
1863             }
1864 0         0 $i += 1;
1865             }
1866              
1867             # single character of single octet code
1868             elsif ($char[$i] =~ /\A (?: \\h ) \z/oxms) {
1869 0         0 push @singleoctet, "\t", "\x20";
1870 0         0 $i += 1;
1871             }
1872             elsif ($char[$i] =~ /\A (?: \\v ) \z/oxms) {
1873 0         0 push @singleoctet, "\x0A", "\x0B", "\x0C", "\x0D";
1874 0         0 $i += 1;
1875             }
1876             elsif ($char[$i] =~ /\A (?: \\d | \\s | \\w ) \z/oxms) {
1877 0         0 push @singleoctet, $char[$i];
1878 0         0 $i += 1;
1879             }
1880              
1881             # single character of multiple-octet code
1882             else {
1883 0         0 push @multipleoctet, $char[$i];
1884 0         0 $i += 1;
1885             }
1886             }
1887              
1888             # quote metachar
1889 0         0 for (@singleoctet) {
1890 0 0       0 if ($_ eq '...') {
    0          
    0          
    0          
    0          
1891 0         0 $_ = '-';
1892             }
1893             elsif (/\A \n \z/oxms) {
1894 0         0 $_ = '\n';
1895             }
1896             elsif (/\A \r \z/oxms) {
1897 0         0 $_ = '\r';
1898             }
1899             elsif (/\A ([\x00-\x20\x7F-\xFF]) \z/oxms) {
1900 0         0 $_ = sprintf('\x%02X', CORE::ord $1);
1901             }
1902             elsif (/\A [\x00-\xFF] \z/oxms) {
1903 0         0 $_ = quotemeta $_;
1904             }
1905             }
1906              
1907             # return character list
1908 0         0 return \@singleoctet, \@multipleoctet;
1909             }
1910              
1911             #
1912             # Cyrillic octal escape sequence
1913             #
1914             sub octchr {
1915 0     0 0 0 my($octdigit) = @_;
1916              
1917 0         0 my @binary = ();
1918 0         0 for my $octal (split(//,$octdigit)) {
1919 0         0 push @binary, {
1920             '0' => '000',
1921             '1' => '001',
1922             '2' => '010',
1923             '3' => '011',
1924             '4' => '100',
1925             '5' => '101',
1926             '6' => '110',
1927             '7' => '111',
1928             }->{$octal};
1929             }
1930 0         0 my $binary = join '', @binary;
1931              
1932 0         0 my $octchr = {
1933             # 1234567
1934             1 => pack('B*', "0000000$binary"),
1935             2 => pack('B*', "000000$binary"),
1936             3 => pack('B*', "00000$binary"),
1937             4 => pack('B*', "0000$binary"),
1938             5 => pack('B*', "000$binary"),
1939             6 => pack('B*', "00$binary"),
1940             7 => pack('B*', "0$binary"),
1941             0 => pack('B*', "$binary"),
1942              
1943             }->{CORE::length($binary) % 8};
1944              
1945 0         0 return $octchr;
1946             }
1947              
1948             #
1949             # Cyrillic hexadecimal escape sequence
1950             #
1951             sub hexchr {
1952 0     0 0 0 my($hexdigit) = @_;
1953              
1954 0         0 my $hexchr = {
1955             1 => pack('H*', "0$hexdigit"),
1956             0 => pack('H*', "$hexdigit"),
1957              
1958             }->{CORE::length($_[0]) % 2};
1959              
1960 0         0 return $hexchr;
1961             }
1962              
1963             #
1964             # Cyrillic open character list for qr
1965             #
1966             sub charlist_qr {
1967              
1968 0     0 0 0 my $modifier = pop @_;
1969 0         0 my @char = @_;
1970              
1971 0         0 my($singleoctet, $multipleoctet) = _charlist(@char, $modifier);
1972 0         0 my @singleoctet = @$singleoctet;
1973 0         0 my @multipleoctet = @$multipleoctet;
1974              
1975             # return character list
1976 0 0       0 if (scalar(@singleoctet) >= 1) {
1977              
1978             # with /i modifier
1979 0 0       0 if ($modifier =~ m/i/oxms) {
1980 0         0 my %singleoctet_ignorecase = ();
1981 0         0 for (@singleoctet) {
1982 0   0     0 while (s/ \A \\x(..) - \\x(..) //oxms or s/ \A \\x((..)) //oxms) {
1983 0         0 for my $ord (hex($1) .. hex($2)) {
1984 0         0 my $char = CORE::chr($ord);
1985 0         0 my $uc = Char::Ecyrillic::uc($char);
1986 0         0 my $fc = Char::Ecyrillic::fc($char);
1987 0 0       0 if ($uc eq $fc) {
1988 0         0 $singleoctet_ignorecase{unpack 'C*', $char} = 1;
1989             }
1990             else {
1991 0 0       0 if (CORE::length($fc) == 1) {
1992 0         0 $singleoctet_ignorecase{unpack 'C*', $uc} = 1;
1993 0         0 $singleoctet_ignorecase{unpack 'C*', $fc} = 1;
1994             }
1995             else {
1996 0         0 $singleoctet_ignorecase{unpack 'C*', $uc} = 1;
1997 0         0 push @multipleoctet, join '', map {sprintf('\x%02X',$_)} unpack 'C*', $fc;
  0         0  
1998             }
1999             }
2000             }
2001             }
2002 0 0       0 if ($_ ne '') {
2003 0         0 $singleoctet_ignorecase{unpack 'C*', $_} = 1;
2004             }
2005             }
2006 0         0 my $i = 0;
2007 0         0 my @singleoctet_ignorecase = ();
2008 0         0 for my $ord (0 .. 255) {
2009 0 0       0 if (exists $singleoctet_ignorecase{$ord}) {
2010 0         0 push @{$singleoctet_ignorecase[$i]}, $ord;
  0         0  
2011             }
2012             else {
2013 0         0 $i++;
2014             }
2015             }
2016 0         0 @singleoctet = ();
2017 0         0 for my $range (@singleoctet_ignorecase) {
2018 0 0       0 if (ref $range) {
2019 0 0       0 if (scalar(@{$range}) == 1) {
  0 0       0  
  0         0  
2020 0         0 push @singleoctet, sprintf('\x%02X', @{$range}[0]);
  0         0  
2021             }
2022             elsif (scalar(@{$range}) == 2) {
2023 0         0 push @singleoctet, sprintf('\x%02X\x%02X', @{$range}[0], @{$range}[-1]);
  0         0  
  0         0  
2024             }
2025             else {
2026 0         0 push @singleoctet, sprintf('\x%02X-\x%02X', @{$range}[0], @{$range}[-1]);
  0         0  
  0         0  
2027             }
2028             }
2029             }
2030             }
2031              
2032 0         0 my $not_anchor = '';
2033              
2034 0         0 push @multipleoctet, join('', $not_anchor, '[', @singleoctet, ']' );
2035             }
2036 0 0       0 if (scalar(@multipleoctet) >= 2) {
2037 0         0 return '(?:' . join('|', @multipleoctet) . ')';
2038             }
2039             else {
2040 0         0 return $multipleoctet[0];
2041             }
2042             }
2043              
2044             #
2045             # Cyrillic open character list for not qr
2046             #
2047             sub charlist_not_qr {
2048              
2049 0     0 0 0 my $modifier = pop @_;
2050 0         0 my @char = @_;
2051              
2052 0         0 my($singleoctet, $multipleoctet) = _charlist(@char, $modifier);
2053 0         0 my @singleoctet = @$singleoctet;
2054 0         0 my @multipleoctet = @$multipleoctet;
2055              
2056             # with /i modifier
2057 0 0       0 if ($modifier =~ m/i/oxms) {
2058 0         0 my %singleoctet_ignorecase = ();
2059 0         0 for (@singleoctet) {
2060 0   0     0 while (s/ \A \\x(..) - \\x(..) //oxms or s/ \A \\x((..)) //oxms) {
2061 0         0 for my $ord (hex($1) .. hex($2)) {
2062 0         0 my $char = CORE::chr($ord);
2063 0         0 my $uc = Char::Ecyrillic::uc($char);
2064 0         0 my $fc = Char::Ecyrillic::fc($char);
2065 0 0       0 if ($uc eq $fc) {
2066 0         0 $singleoctet_ignorecase{unpack 'C*', $char} = 1;
2067             }
2068             else {
2069 0 0       0 if (CORE::length($fc) == 1) {
2070 0         0 $singleoctet_ignorecase{unpack 'C*', $uc} = 1;
2071 0         0 $singleoctet_ignorecase{unpack 'C*', $fc} = 1;
2072             }
2073             else {
2074 0         0 $singleoctet_ignorecase{unpack 'C*', $uc} = 1;
2075 0         0 push @multipleoctet, join '', map {sprintf('\x%02X',$_)} unpack 'C*', $fc;
  0         0  
2076             }
2077             }
2078             }
2079             }
2080 0 0       0 if ($_ ne '') {
2081 0         0 $singleoctet_ignorecase{unpack 'C*', $_} = 1;
2082             }
2083             }
2084 0         0 my $i = 0;
2085 0         0 my @singleoctet_ignorecase = ();
2086 0         0 for my $ord (0 .. 255) {
2087 0 0       0 if (exists $singleoctet_ignorecase{$ord}) {
2088 0         0 push @{$singleoctet_ignorecase[$i]}, $ord;
  0         0  
2089             }
2090             else {
2091 0         0 $i++;
2092             }
2093             }
2094 0         0 @singleoctet = ();
2095 0         0 for my $range (@singleoctet_ignorecase) {
2096 0 0       0 if (ref $range) {
2097 0 0       0 if (scalar(@{$range}) == 1) {
  0 0       0  
  0         0  
2098 0         0 push @singleoctet, sprintf('\x%02X', @{$range}[0]);
  0         0  
2099             }
2100             elsif (scalar(@{$range}) == 2) {
2101 0         0 push @singleoctet, sprintf('\x%02X\x%02X', @{$range}[0], @{$range}[-1]);
  0         0  
  0         0  
2102             }
2103             else {
2104 0         0 push @singleoctet, sprintf('\x%02X-\x%02X', @{$range}[0], @{$range}[-1]);
  0         0  
  0         0  
2105             }
2106             }
2107             }
2108             }
2109              
2110             # return character list
2111 0 0       0 if (scalar(@multipleoctet) >= 1) {
2112 0 0       0 if (scalar(@singleoctet) >= 1) {
2113              
2114             # any character other than multiple-octet and single octet character class
2115 0         0 return '(?!' . join('|', @multipleoctet) . ')(?:[^' . join('', @singleoctet) . '])';
2116             }
2117             else {
2118              
2119             # any character other than multiple-octet character class
2120 0         0 return '(?!' . join('|', @multipleoctet) . ")(?:$your_char)";
2121             }
2122             }
2123             else {
2124 0 0       0 if (scalar(@singleoctet) >= 1) {
2125              
2126             # any character other than single octet character class
2127 0         0 return '(?:[^' . join('', @singleoctet) . '])';
2128             }
2129             else {
2130              
2131             # any character
2132 0         0 return "(?:$your_char)";
2133             }
2134             }
2135             }
2136              
2137             #
2138             # open file in read mode
2139             #
2140             sub _open_r {
2141 197     197   654 my(undef,$file) = @_;
2142 197         861 $file =~ s#\A (\s) #./$1#oxms;
2143 197   33     26588 return CORE::eval(q{open($_[0],'<',$_[1])}) ||
2144             open($_[0],"< $file\0");
2145             }
2146              
2147             #
2148             # open file in write mode
2149             #
2150             sub _open_w {
2151 0     0   0 my(undef,$file) = @_;
2152 0         0 $file =~ s#\A (\s) #./$1#oxms;
2153 0   0     0 return CORE::eval(q{open($_[0],'>',$_[1])}) ||
2154             open($_[0],"> $file\0");
2155             }
2156              
2157             #
2158             # open file in append mode
2159             #
2160             sub _open_a {
2161 0     0   0 my(undef,$file) = @_;
2162 0         0 $file =~ s#\A (\s) #./$1#oxms;
2163 0   0     0 return CORE::eval(q{open($_[0],'>>',$_[1])}) ||
2164             open($_[0],">> $file\0");
2165             }
2166              
2167             #
2168             # safe system
2169             #
2170             sub _systemx {
2171              
2172             # P.707 29.2.33. exec
2173             # in Chapter 29: Functions
2174             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
2175             #
2176             # Be aware that in older releases of Perl, exec (and system) did not flush
2177             # your output buffer, so you needed to enable command buffering by setting $|
2178             # on one or more filehandles to avoid lost output in the case of exec, or
2179             # misordererd output in the case of system. This situation was largely remedied
2180             # in the 5.6 release of Perl. (So, 5.005 release not yet.)
2181              
2182             # P.855 exec
2183             # in Chapter 27: Functions
2184             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
2185             #
2186             # In very old release of Perl (before v5.6), exec (and system) did not flush
2187             # your output buffer, so you needed to enable command buffering by setting $|
2188             # on one or more filehandles to avoid lost output with exec or misordered
2189             # output with system.
2190              
2191 197     197   793 $| = 1;
2192              
2193             # P.565 23.1.2. Cleaning Up Your Environment
2194             # in Chapter 23: Security
2195             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
2196              
2197             # P.656 Cleaning Up Your Environment
2198             # in Chapter 20: Security
2199             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
2200              
2201             # local $ENV{'PATH'} = '.';
2202 197         2116 local @ENV{qw(IFS CDPATH ENV BASH_ENV)}; # Make %ENV safer
2203              
2204             # P.707 29.2.33. exec
2205             # in Chapter 29: Functions
2206             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
2207             #
2208             # As we mentioned earlier, exec treats a discrete list of arguments as an
2209             # indication that it should bypass shell processing. However, there is one
2210             # place where you might still get tripped up. The exec call (and system, too)
2211             # will not distinguish between a single scalar argument and an array containing
2212             # only one element.
2213             #
2214             # @args = ("echo surprise"); # just one element in list
2215             # exec @args # still subject to shell escapes
2216             # or die "exec: $!"; # because @args == 1
2217             #
2218             # To avoid this, you can use the PATHNAME syntax, explicitly duplicating the
2219             # first argument as the pathname, which forces the rest of the arguments to be
2220             # interpreted as a list, even if there is only one of them:
2221             #
2222             # exec { $args[0] } @args # safe even with one-argument list
2223             # or die "can't exec @args: $!";
2224              
2225             # P.855 exec
2226             # in Chapter 27: Functions
2227             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
2228             #
2229             # As we mentioned earlier, exec treats a discrete list of arguments as a
2230             # directive to bypass shell processing. However, there is one place where
2231             # you might still get tripped up. The exec call (and system, too) cannot
2232             # distinguish between a single scalar argument and an array containing
2233             # only one element.
2234             #
2235             # @args = ("echo surprise"); # just one element in list
2236             # exec @args # still subject to shell escapes
2237             # || die "exec: $!"; # because @args == 1
2238             #
2239             # To avoid this, use the PATHNAME syntax, explicitly duplicating the first
2240             # argument as the pathname, which forces the rest of the arguments to be
2241             # interpreted as a list, even if there is only one of them:
2242             #
2243             # exec { $args[0] } @args # safe even with one-argument list
2244             # || die "can't exec @args: $!";
2245              
2246 197         414 return CORE::system { $_[0] } @_; # safe even with one-argument list
  197         25882995  
2247             }
2248              
2249             #
2250             # Cyrillic order to character (with parameter)
2251             #
2252             sub Char::Ecyrillic::chr(;$) {
2253              
2254 0 0   0 0   my $c = @_ ? $_[0] : $_;
2255              
2256 0 0         if ($c == 0x00) {
2257 0           return "\x00";
2258             }
2259             else {
2260 0           my @chr = ();
2261 0           while ($c > 0) {
2262 0           unshift @chr, ($c % 0x100);
2263 0           $c = int($c / 0x100);
2264             }
2265 0           return pack 'C*', @chr;
2266             }
2267             }
2268              
2269             #
2270             # Cyrillic order to character (without parameter)
2271             #
2272             sub Char::Ecyrillic::chr_() {
2273              
2274 0     0 0   my $c = $_;
2275              
2276 0 0         if ($c == 0x00) {
2277 0           return "\x00";
2278             }
2279             else {
2280 0           my @chr = ();
2281 0           while ($c > 0) {
2282 0           unshift @chr, ($c % 0x100);
2283 0           $c = int($c / 0x100);
2284             }
2285 0           return pack 'C*', @chr;
2286             }
2287             }
2288              
2289             #
2290             # Cyrillic path globbing (with parameter)
2291             #
2292             sub Char::Ecyrillic::glob($) {
2293              
2294 0 0   0 0   if (wantarray) {
2295 0           my @glob = _DOS_like_glob(@_);
2296 0           for my $glob (@glob) {
2297 0           $glob =~ s{ \A (?:\./)+ }{}oxms;
2298             }
2299 0           return @glob;
2300             }
2301             else {
2302 0           my $glob = _DOS_like_glob(@_);
2303 0           $glob =~ s{ \A (?:\./)+ }{}oxms;
2304 0           return $glob;
2305             }
2306             }
2307              
2308             #
2309             # Cyrillic path globbing (without parameter)
2310             #
2311             sub Char::Ecyrillic::glob_() {
2312              
2313 0 0   0 0   if (wantarray) {
2314 0           my @glob = _DOS_like_glob();
2315 0           for my $glob (@glob) {
2316 0           $glob =~ s{ \A (?:\./)+ }{}oxms;
2317             }
2318 0           return @glob;
2319             }
2320             else {
2321 0           my $glob = _DOS_like_glob();
2322 0           $glob =~ s{ \A (?:\./)+ }{}oxms;
2323 0           return $glob;
2324             }
2325             }
2326              
2327             #
2328             # Cyrillic path globbing via File::DosGlob 1.10
2329             #
2330             # Often I confuse "_dosglob" and "_doglob".
2331             # So, I renamed "_dosglob" to "_DOS_like_glob".
2332             #
2333             my %iter;
2334             my %entries;
2335             sub _DOS_like_glob {
2336              
2337             # context (keyed by second cxix argument provided by core)
2338 0     0     my($expr,$cxix) = @_;
2339              
2340             # glob without args defaults to $_
2341 0 0         $expr = $_ if not defined $expr;
2342              
2343             # represents the current user's home directory
2344             #
2345             # 7.3. Expanding Tildes in Filenames
2346             # in Chapter 7. File Access
2347             # of ISBN 0-596-00313-7 Perl Cookbook, 2nd Edition.
2348             #
2349             # and File::HomeDir, File::HomeDir::Windows module
2350              
2351             # DOS-like system
2352 0 0         if ($^O =~ /\A (?: MSWin32 | NetWare | symbian | dos ) \z/oxms) {
2353 0           $expr =~ s{ \A ~ (?= [^/\\] ) }
2354 0           { my_home_MSWin32() }oxmse;
2355             }
2356              
2357             # UNIX-like system
2358             else {
2359 0           $expr =~ s{ \A ~ ( (?:[^/])* ) }
2360 0 0 0       { $1 ? (CORE::eval(q{(getpwnam($1))[7]})||my_home()) : my_home() }oxmse;
2361             }
2362              
2363             # assume global context if not provided one
2364 0 0         $cxix = '_G_' if not defined $cxix;
2365 0 0         $iter{$cxix} = 0 if not exists $iter{$cxix};
2366              
2367             # if we're just beginning, do it all first
2368 0 0         if ($iter{$cxix} == 0) {
2369 0           $entries{$cxix} = [ _do_glob(1, _parse_line($expr)) ];
2370             }
2371              
2372             # chuck it all out, quick or slow
2373 0 0         if (wantarray) {
2374 0           delete $iter{$cxix};
2375 0           return @{delete $entries{$cxix}};
  0            
2376             }
2377             else {
2378 0 0         if ($iter{$cxix} = scalar @{$entries{$cxix}}) {
  0            
2379 0           return shift @{$entries{$cxix}};
  0            
2380             }
2381             else {
2382             # return undef for EOL
2383 0           delete $iter{$cxix};
2384 0           delete $entries{$cxix};
2385 0           return undef;
2386             }
2387             }
2388             }
2389              
2390             #
2391             # Cyrillic path globbing subroutine
2392             #
2393             sub _do_glob {
2394              
2395 0     0     my($cond,@expr) = @_;
2396 0           my @glob = ();
2397 0           my $fix_drive_relative_paths = 0;
2398              
2399             OUTER:
2400 0           for my $expr (@expr) {
2401 0 0         next OUTER if not defined $expr;
2402 0 0         next OUTER if $expr eq '';
2403              
2404 0           my @matched = ();
2405 0           my @globdir = ();
2406 0           my $head = '.';
2407 0           my $pathsep = '/';
2408 0           my $tail;
2409              
2410             # if argument is within quotes strip em and do no globbing
2411 0 0         if ($expr =~ /\A " ((?:$q_char)*) " \z/oxms) {
2412 0           $expr = $1;
2413 0 0         if ($cond eq 'd') {
2414 0 0         if (-d $expr) {
2415 0           push @glob, $expr;
2416             }
2417             }
2418             else {
2419 0 0         if (-e $expr) {
2420 0           push @glob, $expr;
2421             }
2422             }
2423 0           next OUTER;
2424             }
2425              
2426             # wildcards with a drive prefix such as h:*.pm must be changed
2427             # to h:./*.pm to expand correctly
2428 0 0         if ($^O =~ /\A (?: MSWin32 | NetWare | symbian | dos ) \z/oxms) {
2429 0 0         if ($expr =~ s# \A ((?:[A-Za-z]:)?) ([^/\\]) #$1./$2#oxms) {
2430 0           $fix_drive_relative_paths = 1;
2431             }
2432             }
2433              
2434 0 0         if (($head, $tail) = _parse_path($expr,$pathsep)) {
2435 0 0         if ($tail eq '') {
2436 0           push @glob, $expr;
2437 0           next OUTER;
2438             }
2439 0 0         if ($head =~ / \A (?:$q_char)*? [*?] /oxms) {
2440 0 0         if (@globdir = _do_glob('d', $head)) {
2441 0           push @glob, _do_glob($cond, map {"$_$pathsep$tail"} @globdir);
  0            
2442 0           next OUTER;
2443             }
2444             }
2445 0 0 0       if ($head eq '' or $head =~ /\A [A-Za-z]: \z/oxms) {
2446 0           $head .= $pathsep;
2447             }
2448 0           $expr = $tail;
2449             }
2450              
2451             # If file component has no wildcards, we can avoid opendir
2452 0 0         if ($expr !~ / \A (?:$q_char)*? [*?] /oxms) {
2453 0 0         if ($head eq '.') {
2454 0           $head = '';
2455             }
2456 0 0 0       if ($head ne '' and ($head =~ / \G ($q_char) /oxmsg)[-1] ne $pathsep) {
2457 0           $head .= $pathsep;
2458             }
2459 0           $head .= $expr;
2460 0 0         if ($cond eq 'd') {
2461 0 0         if (-d $head) {
2462 0           push @glob, $head;
2463             }
2464             }
2465             else {
2466 0 0         if (-e $head) {
2467 0           push @glob, $head;
2468             }
2469             }
2470 0           next OUTER;
2471             }
2472 0 0         opendir(*DIR, $head) or next OUTER;
2473 0           my @leaf = readdir DIR;
2474 0           closedir DIR;
2475              
2476 0 0         if ($head eq '.') {
2477 0           $head = '';
2478             }
2479 0 0 0       if ($head ne '' and ($head =~ / \G ($q_char) /oxmsg)[-1] ne $pathsep) {
2480 0           $head .= $pathsep;
2481             }
2482              
2483 0           my $pattern = '';
2484 0           while ($expr =~ / \G ($q_char) /oxgc) {
2485 0           my $char = $1;
2486              
2487             # 6.9. Matching Shell Globs as Regular Expressions
2488             # in Chapter 6. Pattern Matching
2489             # of ISBN 0-596-00313-7 Perl Cookbook, 2nd Edition.
2490             # (and so on)
2491              
2492 0 0         if ($char eq '*') {
    0          
    0          
2493 0           $pattern .= "(?:$your_char)*",
2494             }
2495             elsif ($char eq '?') {
2496 0           $pattern .= "(?:$your_char)?", # DOS style
2497             # $pattern .= "(?:$your_char)", # UNIX style
2498             }
2499             elsif ((my $fc = Char::Ecyrillic::fc($char)) ne $char) {
2500 0           $pattern .= $fc;
2501             }
2502             else {
2503 0           $pattern .= quotemeta $char;
2504             }
2505             }
2506 0     0     my $matchsub = sub { Char::Ecyrillic::fc($_[0]) =~ /\A $pattern \z/xms };
  0            
2507              
2508             # if ($@) {
2509             # print STDERR "$0: $@\n";
2510             # next OUTER;
2511             # }
2512              
2513             INNER:
2514 0           for my $leaf (@leaf) {
2515 0 0 0       if ($leaf eq '.' or $leaf eq '..') {
2516 0           next INNER;
2517             }
2518 0 0 0       if ($cond eq 'd' and not -d "$head$leaf") {
2519 0           next INNER;
2520             }
2521              
2522 0 0         if (&$matchsub($leaf)) {
2523 0           push @matched, "$head$leaf";
2524 0           next INNER;
2525             }
2526              
2527             # [DOS compatibility special case]
2528             # Failed, add a trailing dot and try again, but only...
2529              
2530 0 0 0       if (Char::Ecyrillic::index($leaf,'.') == -1 and # if name does not have a dot in it *and*
      0        
2531             CORE::length($leaf) <= 8 and # name is shorter than or equal to 8 chars *and*
2532             Char::Ecyrillic::index($pattern,'\\.') != -1 # pattern has a dot.
2533             ) {
2534 0 0         if (&$matchsub("$leaf.")) {
2535 0           push @matched, "$head$leaf";
2536 0           next INNER;
2537             }
2538             }
2539             }
2540 0 0         if (@matched) {
2541 0           push @glob, @matched;
2542             }
2543             }
2544 0 0         if ($fix_drive_relative_paths) {
2545 0           for my $glob (@glob) {
2546 0           $glob =~ s# \A ([A-Za-z]:) \./ #$1#oxms;
2547             }
2548             }
2549 0           return @glob;
2550             }
2551              
2552             #
2553             # Cyrillic parse line
2554             #
2555             sub _parse_line {
2556              
2557 0     0     my($line) = @_;
2558              
2559 0           $line .= ' ';
2560 0           my @piece = ();
2561 0           while ($line =~ /
2562             " ( (?: [^"] )* ) " \s+ |
2563             ( (?: [^"\s] )* ) \s+
2564             /oxmsg
2565             ) {
2566 0 0         push @piece, defined($1) ? $1 : $2;
2567             }
2568 0           return @piece;
2569             }
2570              
2571             #
2572             # Cyrillic parse path
2573             #
2574             sub _parse_path {
2575              
2576 0     0     my($path,$pathsep) = @_;
2577              
2578 0           $path .= '/';
2579 0           my @subpath = ();
2580 0           while ($path =~ /
2581             ((?: [^\/\\] )+?) [\/\\]
2582             /oxmsg
2583             ) {
2584 0           push @subpath, $1;
2585             }
2586              
2587 0           my $tail = pop @subpath;
2588 0           my $head = join $pathsep, @subpath;
2589 0           return $head, $tail;
2590             }
2591              
2592             #
2593             # via File::HomeDir::Windows 1.00
2594             #
2595             sub my_home_MSWin32 {
2596              
2597             # A lot of unix people and unix-derived tools rely on
2598             # the ability to overload HOME. We will support it too
2599             # so that they can replace raw HOME calls with File::HomeDir.
2600 0 0 0 0 0   if (exists $ENV{'HOME'} and $ENV{'HOME'}) {
    0 0        
    0 0        
      0        
      0        
2601 0           return $ENV{'HOME'};
2602             }
2603              
2604             # Do we have a user profile?
2605             elsif (exists $ENV{'USERPROFILE'} and $ENV{'USERPROFILE'}) {
2606 0           return $ENV{'USERPROFILE'};
2607             }
2608              
2609             # Some Windows use something like $ENV{'HOME'}
2610             elsif (exists $ENV{'HOMEDRIVE'} and exists $ENV{'HOMEPATH'} and $ENV{'HOMEDRIVE'} and $ENV{'HOMEPATH'}) {
2611 0           return join '', $ENV{'HOMEDRIVE'}, $ENV{'HOMEPATH'};
2612             }
2613              
2614 0           return undef;
2615             }
2616              
2617             #
2618             # via File::HomeDir::Unix 1.00
2619             #
2620             sub my_home {
2621 0     0 0   my $home;
2622              
2623 0 0 0       if (exists $ENV{'HOME'} and defined $ENV{'HOME'}) {
    0 0        
2624 0           $home = $ENV{'HOME'};
2625             }
2626              
2627             # This is from the original code, but I'm guessing
2628             # it means "login directory" and exists on some Unixes.
2629             elsif (exists $ENV{'LOGDIR'} and $ENV{'LOGDIR'}) {
2630 0           $home = $ENV{'LOGDIR'};
2631             }
2632              
2633             ### More-desperate methods
2634              
2635             # Light desperation on any (Unixish) platform
2636             else {
2637 0           $home = CORE::eval q{ (getpwuid($<))[7] };
2638             }
2639              
2640             # On Unix in general, a non-existant home means "no home"
2641             # For example, "nobody"-like users might use /nonexistant
2642 0 0 0       if (defined $home and ! -d($home)) {
2643 0           $home = undef;
2644             }
2645 0           return $home;
2646             }
2647              
2648             #
2649             # ${^PREMATCH}, $PREMATCH, $` the string preceding what was matched
2650             #
2651             sub Char::Ecyrillic::PREMATCH {
2652 0     0 0   return $`;
2653             }
2654              
2655             #
2656             # ${^MATCH}, $MATCH, $& the string that matched
2657             #
2658             sub Char::Ecyrillic::MATCH {
2659 0     0 0   return $&;
2660             }
2661              
2662             #
2663             # ${^POSTMATCH}, $POSTMATCH, $' the string following what was matched
2664             #
2665             sub Char::Ecyrillic::POSTMATCH {
2666 0     0 0   return $';
2667             }
2668              
2669             #
2670             # Cyrillic character to order (with parameter)
2671             #
2672             sub Char::Cyrillic::ord(;$) {
2673              
2674 0 0   0 1   local $_ = shift if @_;
2675              
2676 0 0         if (/\A ($q_char) /oxms) {
2677 0           my @ord = unpack 'C*', $1;
2678 0           my $ord = 0;
2679 0           while (my $o = shift @ord) {
2680 0           $ord = $ord * 0x100 + $o;
2681             }
2682 0           return $ord;
2683             }
2684             else {
2685 0           return CORE::ord $_;
2686             }
2687             }
2688              
2689             #
2690             # Cyrillic character to order (without parameter)
2691             #
2692             sub Char::Cyrillic::ord_() {
2693              
2694 0 0   0 0   if (/\A ($q_char) /oxms) {
2695 0           my @ord = unpack 'C*', $1;
2696 0           my $ord = 0;
2697 0           while (my $o = shift @ord) {
2698 0           $ord = $ord * 0x100 + $o;
2699             }
2700 0           return $ord;
2701             }
2702             else {
2703 0           return CORE::ord $_;
2704             }
2705             }
2706              
2707             #
2708             # Cyrillic reverse
2709             #
2710             sub Char::Cyrillic::reverse(@) {
2711              
2712 0 0   0 0   if (wantarray) {
2713 0           return CORE::reverse @_;
2714             }
2715             else {
2716              
2717             # One of us once cornered Larry in an elevator and asked him what
2718             # problem he was solving with this, but he looked as far off into
2719             # the distance as he could in an elevator and said, "It seemed like
2720             # a good idea at the time."
2721              
2722 0           return join '', CORE::reverse(join('',@_) =~ /\G ($q_char) /oxmsg);
2723             }
2724             }
2725              
2726             #
2727             # Cyrillic getc (with parameter, without parameter)
2728             #
2729             sub Char::Cyrillic::getc(;*@) {
2730              
2731 0     0 0   my($package) = caller;
2732 0 0         my $fh = @_ ? qualify_to_ref(shift,$package) : \*STDIN;
2733 0 0 0       croak 'Too many arguments for Char::Cyrillic::getc' if @_ and not wantarray;
2734              
2735 0           my @length = sort { $a <=> $b } keys %range_tr;
  0            
2736 0           my $getc = '';
2737 0           for my $length ($length[0] .. $length[-1]) {
2738 0           $getc .= CORE::getc($fh);
2739 0 0         if (exists $range_tr{CORE::length($getc)}) {
2740 0 0         if ($getc =~ /\A ${Char::Ecyrillic::dot_s} \z/oxms) {
2741 0 0         return wantarray ? ($getc,@_) : $getc;
2742             }
2743             }
2744             }
2745 0 0         return wantarray ? ($getc,@_) : $getc;
2746             }
2747              
2748             #
2749             # Cyrillic length by character
2750             #
2751             sub Char::Cyrillic::length(;$) {
2752              
2753 0 0   0 1   local $_ = shift if @_;
2754              
2755 0           local @_ = /\G ($q_char) /oxmsg;
2756 0           return scalar @_;
2757             }
2758              
2759             #
2760             # Cyrillic substr by character
2761             #
2762             BEGIN {
2763              
2764             # P.232 The lvalue Attribute
2765             # in Chapter 6: Subroutines
2766             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
2767              
2768             # P.336 The lvalue Attribute
2769             # in Chapter 7: Subroutines
2770             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
2771              
2772             # P.144 8.4 Lvalue subroutines
2773             # in Chapter 8: perlsub: Perl subroutines
2774             # of ISBN-13: 978-1-906966-02-7 The Perl Language Reference Manual (for Perl version 5.12.1)
2775              
2776 197 50 0 197 1 175732 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            
2777             # vv----------------*******
2778             sub Char::Cyrillic::substr($$;$$) %s {
2779              
2780             my @char = $_[0] =~ /\G ($q_char) /oxmsg;
2781              
2782             # If the substring is beyond either end of the string, substr() returns the undefined
2783             # value and produces a warning. When used as an lvalue, specifying a substring that
2784             # is entirely outside the string raises an exception.
2785             # http://perldoc.perl.org/functions/substr.html
2786              
2787             # A return with no argument returns the scalar value undef in scalar context,
2788             # an empty list () in list context, and (naturally) nothing at all in void
2789             # context.
2790              
2791             my $offset = $_[1];
2792             if (($offset > scalar(@char)) or ($offset < (-1 * scalar(@char)))) {
2793             return;
2794             }
2795              
2796             # substr($string,$offset,$length,$replacement)
2797             if (@_ == 4) {
2798             my(undef,undef,$length,$replacement) = @_;
2799             my $substr = join '', splice(@char, $offset, $length, $replacement);
2800             $_[0] = join '', @char;
2801              
2802             # return $substr; this doesn't work, don't say "return"
2803             $substr;
2804             }
2805              
2806             # substr($string,$offset,$length)
2807             elsif (@_ == 3) {
2808             my(undef,undef,$length) = @_;
2809             my $octet_offset = 0;
2810             my $octet_length = 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             if ($length == 0) {
2821             $octet_length = 0;
2822             }
2823             elsif ($length > 0) {
2824             $octet_length = CORE::length(join '', @char[$offset..$offset+$length-1]);
2825             }
2826             else {
2827             $octet_length = -1 * CORE::length(join '', @char[$#char+$length+1..$#char]);
2828             }
2829             CORE::substr($_[0], $octet_offset, $octet_length);
2830             }
2831              
2832             # substr($string,$offset)
2833             else {
2834             my $octet_offset = 0;
2835             if ($offset == 0) {
2836             $octet_offset = 0;
2837             }
2838             elsif ($offset > 0) {
2839             $octet_offset = CORE::length(join '', @char[0..$offset-1]);
2840             }
2841             else {
2842             $octet_offset = -1 * CORE::length(join '', @char[$#char+$offset+1..$#char]);
2843             }
2844             CORE::substr($_[0], $octet_offset);
2845             }
2846             }
2847             END
2848             }
2849              
2850             #
2851             # Cyrillic index by character
2852             #
2853             sub Char::Cyrillic::index($$;$) {
2854              
2855 0     0 1   my $index;
2856 0 0         if (@_ == 3) {
2857 0           $index = Char::Ecyrillic::index($_[0], $_[1], CORE::length(Char::Cyrillic::substr($_[0], 0, $_[2])));
2858             }
2859             else {
2860 0           $index = Char::Ecyrillic::index($_[0], $_[1]);
2861             }
2862              
2863 0 0         if ($index == -1) {
2864 0           return -1;
2865             }
2866             else {
2867 0           return Char::Cyrillic::length(CORE::substr $_[0], 0, $index);
2868             }
2869             }
2870              
2871             #
2872             # Cyrillic rindex by character
2873             #
2874             sub Char::Cyrillic::rindex($$;$) {
2875              
2876 0     0 1   my $rindex;
2877 0 0         if (@_ == 3) {
2878 0           $rindex = Char::Ecyrillic::rindex($_[0], $_[1], CORE::length(Char::Cyrillic::substr($_[0], 0, $_[2])));
2879             }
2880             else {
2881 0           $rindex = Char::Ecyrillic::rindex($_[0], $_[1]);
2882             }
2883              
2884 0 0         if ($rindex == -1) {
2885 0           return -1;
2886             }
2887             else {
2888 0           return Char::Cyrillic::length(CORE::substr $_[0], 0, $rindex);
2889             }
2890             }
2891              
2892             # when 'm//', '/' means regexp match 'm//' and '?' means regexp match '??'
2893             # when 'div', '/' means division operator and '?' means conditional operator (condition ? then : else)
2894 197     197   18803 BEGIN { CORE::eval q{ use vars qw($slash) } } $slash = 'm//';
  197     197   2233  
  197         549  
  197         17459  
2895              
2896             # ord() to ord() or Char::Cyrillic::ord()
2897 197     197   12755 BEGIN { CORE::eval q{ use vars qw($function_ord) } } $function_ord = 'ord';
  197     197   1340  
  197         589  
  197         14060  
2898              
2899             # ord to ord or Char::Cyrillic::ord_
2900 197     197   12448 BEGIN { CORE::eval q{ use vars qw($function_ord_) } } $function_ord_ = 'ord';
  197     197   1315  
  197         402  
  197         14319  
2901              
2902             # reverse to reverse or Char::Cyrillic::reverse
2903 197     197   13615 BEGIN { CORE::eval q{ use vars qw($function_reverse) } } $function_reverse = 'reverse';
  197     197   1443  
  197         401  
  197         14679  
2904              
2905             # getc to getc or Char::Cyrillic::getc
2906 197     197   12451 BEGIN { CORE::eval q{ use vars qw($function_getc) } } $function_getc = 'getc';
  197     197   1121  
  197         913  
  197         15161  
2907              
2908             # P.1023 Appendix W.9 Multibyte Anchoring
2909             # of ISBN 1-56592-224-7 CJKV Information Processing
2910              
2911             my $anchor = '';
2912              
2913 197     197   13463 BEGIN { CORE::eval q{ use vars qw($nest) } }
  197     197   1173  
  197         384  
  197         13620022  
2914              
2915             # regexp of nested parens in qqXX
2916              
2917             # P.340 Matching Nested Constructs with Embedded Code
2918             # in Chapter 7: Perl
2919             # of ISBN 0-596-00289-0 Mastering Regular Expressions, Second edition
2920              
2921             my $qq_paren = qr{(?{local $nest=0}) (?>(?:
2922             \\c[\x40-\x5F] |
2923             \\ [\x00-\xFF] |
2924             [^()] |
2925             \( (?{$nest++}) |
2926             \) (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!))
2927             }xms;
2928             my $qq_brace = qr{(?{local $nest=0}) (?>(?:
2929             \\c[\x40-\x5F] |
2930             \\ [\x00-\xFF] |
2931             [^{}] |
2932             \{ (?{$nest++}) |
2933             \} (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!))
2934             }xms;
2935             my $qq_bracket = qr{(?{local $nest=0}) (?>(?:
2936             \\c[\x40-\x5F] |
2937             \\ [\x00-\xFF] |
2938             [^[\]] |
2939             \[ (?{$nest++}) |
2940             \] (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!))
2941             }xms;
2942             my $qq_angle = qr{(?{local $nest=0}) (?>(?:
2943             \\c[\x40-\x5F] |
2944             \\ [\x00-\xFF] |
2945             [^<>] |
2946             \< (?{$nest++}) |
2947             \> (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!))
2948             }xms;
2949             my $qq_scalar = qr{(?: \{ (?:$qq_brace)*? \} |
2950             (?: ::)? (?:
2951             [a-zA-Z_][a-zA-Z_0-9]*
2952             (?: ::[a-zA-Z_][a-zA-Z_0-9]* )* (?: \[ (?: \$\[ | \$\] | $qq_char )*? \] | \{ (?:$qq_brace)*? \} )*
2953             (?: (?: -> )? (?: [\$\@\%\&\*]\* | \$\#\* | [\@\%]? \[ (?: \$\[ | \$\] | $qq_char )*? \] | [\@\%\*]? \{ (?:$qq_brace)*? \} ) )*
2954             ))
2955             }xms;
2956             my $qq_variable = qr{(?: \{ (?:$qq_brace)*? \} |
2957             (?: ::)? (?:
2958             [0-9]+ |
2959             [^a-zA-Z_0-9\[\]] |
2960             ^[A-Z] |
2961             [a-zA-Z_][a-zA-Z_0-9]*
2962             (?: ::[a-zA-Z_][a-zA-Z_0-9]* )* (?: \[ (?: \$\[ | \$\] | $qq_char )*? \] | \{ (?:$qq_brace)*? \} )*
2963             (?: (?: -> )? (?: [\$\@\%\&\*]\* | \$\#\* | [\@\%]? \[ (?: \$\[ | \$\] | $qq_char )*? \] | [\@\%\*]? \{ (?:$qq_brace)*? \} ) )*
2964             ))
2965             }xms;
2966             my $qq_substr = qr{(?: Char::Cyrillic::substr | CORE::substr | substr ) \( $qq_paren \)
2967             }xms;
2968              
2969             # regexp of nested parens in qXX
2970             my $q_paren = qr{(?{local $nest=0}) (?>(?:
2971             [^()] |
2972             \( (?{$nest++}) |
2973             \) (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!))
2974             }xms;
2975             my $q_brace = qr{(?{local $nest=0}) (?>(?:
2976             [^{}] |
2977             \{ (?{$nest++}) |
2978             \} (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!))
2979             }xms;
2980             my $q_bracket = qr{(?{local $nest=0}) (?>(?:
2981             [^[\]] |
2982             \[ (?{$nest++}) |
2983             \] (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!))
2984             }xms;
2985             my $q_angle = qr{(?{local $nest=0}) (?>(?:
2986             [^<>] |
2987             \< (?{$nest++}) |
2988             \> (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!))
2989             }xms;
2990              
2991             my $matched = '';
2992             my $s_matched = '';
2993              
2994             my $tr_variable = ''; # variable of tr///
2995             my $sub_variable = ''; # variable of s///
2996             my $bind_operator = ''; # =~ or !~
2997              
2998             my @heredoc = (); # here document
2999             my @heredoc_delimiter = ();
3000             my $here_script = ''; # here script
3001              
3002             #
3003             # escape Cyrillic script
3004             #
3005             sub Char::Cyrillic::escape(;$) {
3006 0 0   0 0   local($_) = $_[0] if @_;
3007              
3008             # P.359 The Study Function
3009             # in Chapter 7: Perl
3010             # of ISBN 0-596-00289-0 Mastering Regular Expressions, Second edition
3011              
3012 0           study $_; # Yes, I studied study yesterday.
3013              
3014             # while all script
3015              
3016             # 6.14. Matching from Where the Last Pattern Left Off
3017             # in Chapter 6. Pattern Matching
3018             # of ISBN 0-596-00313-7 Perl Cookbook, 2nd Edition.
3019             # (and so on)
3020              
3021             # one member of Tag-team
3022             #
3023             # P.128 Start of match (or end of previous match): \G
3024             # P.130 Advanced Use of \G with Perl
3025             # in Chapter 3: Overview of Regular Expression Features and Flavors
3026             # P.255 Use leading anchors
3027             # P.256 Expose ^ and \G at the front expressions
3028             # in Chapter 6: Crafting an Efficient Expression
3029             # P.315 "Tag-team" matching with /gc
3030             # in Chapter 7: Perl
3031             # of ISBN 0-596-00289-0 Mastering Regular Expressions, Second edition
3032              
3033 0           my $e_script = '';
3034 0           while (not /\G \z/oxgc) { # member
3035 0           $e_script .= Char::Cyrillic::escape_token();
3036             }
3037              
3038 0           return $e_script;
3039             }
3040              
3041             #
3042             # escape Cyrillic token of script
3043             #
3044             sub Char::Cyrillic::escape_token {
3045              
3046             # \n output here document
3047              
3048 0     0 0   my $ignore_modules = join('|', qw(
3049             utf8
3050             bytes
3051             charnames
3052             I18N::Japanese
3053             I18N::Collate
3054             I18N::JExt
3055             File::DosGlob
3056             Wild
3057             Wildcard
3058             Japanese
3059             ));
3060              
3061             # another member of Tag-team
3062             #
3063             # P.315 "Tag-team" matching with /gc
3064             # in Chapter 7: Perl
3065             # of ISBN 0-596-00289-0 Mastering Regular Expressions, Second edition
3066              
3067 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          
3068 0           my $heredoc = '';
3069 0 0         if (scalar(@heredoc_delimiter) >= 1) {
3070 0           $slash = 'm//';
3071              
3072 0           $heredoc = join '', @heredoc;
3073 0           @heredoc = ();
3074              
3075             # skip here document
3076 0           for my $heredoc_delimiter (@heredoc_delimiter) {
3077 0           /\G .*? \n $heredoc_delimiter \n/xmsgc;
3078             }
3079 0           @heredoc_delimiter = ();
3080              
3081 0           $here_script = '';
3082             }
3083 0           return "\n" . $heredoc;
3084             }
3085              
3086             # ignore space, comment
3087 0           elsif (/\G (\s+|\#.*) /oxgc) { return $1; }
3088              
3089             # if (, elsif (, unless (, while (, until (, given (, and when (
3090              
3091             # given, when
3092              
3093             # P.225 The given Statement
3094             # in Chapter 15: Smart Matching and given-when
3095             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
3096              
3097             # P.133 The given Statement
3098             # in Chapter 4: Statements and Declarations
3099             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
3100              
3101             elsif (/\G ( (?: if | elsif | unless | while | until | given | when ) \s* \( ) /oxgc) {
3102 0           $slash = 'm//';
3103 0           return $1;
3104             }
3105              
3106             # scalar variable ($scalar = ...) =~ tr///;
3107             # scalar variable ($scalar = ...) =~ s///;
3108              
3109             # state
3110              
3111             # P.68 Persistent, Private Variables
3112             # in Chapter 4: Subroutines
3113             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
3114              
3115             # P.160 Persistent Lexically Scoped Variables: state
3116             # in Chapter 4: Statements and Declarations
3117             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
3118              
3119             # (and so on)
3120              
3121             elsif (/\G ( \( \s* (?: local \b | my \b | our \b | state \b )? \s* \$ $qq_scalar ) /oxgc) {
3122 0           my $e_string = e_string($1);
3123              
3124 0 0         if (/\G ( \s* = $qq_paren \) ) ( \s* (?: =~ | !~ ) \s* ) (?= (?: tr | y ) \b ) /oxgc) {
    0          
3125 0           $tr_variable = $e_string . e_string($1);
3126 0           $bind_operator = $2;
3127 0           $slash = 'm//';
3128 0           return '';
3129             }
3130             elsif (/\G ( \s* = $qq_paren \) ) ( \s* (?: =~ | !~ ) \s* ) (?= s \b ) /oxgc) {
3131 0           $sub_variable = $e_string . e_string($1);
3132 0           $bind_operator = $2;
3133 0           $slash = 'm//';
3134 0           return '';
3135             }
3136             else {
3137 0           $slash = 'div';
3138 0           return $e_string;
3139             }
3140             }
3141              
3142             # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Char::Ecyrillic::PREMATCH()
3143             elsif (/\G ( \$` | \$\{`\} | \$ \s* PREMATCH \b | \$ \s* \{ \s* PREMATCH \s* \} | \$ \s* \{\^PREMATCH\} ) /oxmsgc) {
3144 0           $slash = 'div';
3145 0           return q{Char::Ecyrillic::PREMATCH()};
3146             }
3147              
3148             # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Char::Ecyrillic::MATCH()
3149             elsif (/\G ( \$& | \$\{&\} | \$ \s* MATCH \b | \$ \s* \{ \s* MATCH \s* \} | \$ \s* \{\^MATCH\} ) /oxmsgc) {
3150 0           $slash = 'div';
3151 0           return q{Char::Ecyrillic::MATCH()};
3152             }
3153              
3154             # $', ${'} --> $', ${'}
3155             elsif (/\G ( \$' | \$\{'\} ) /oxmsgc) {
3156 0           $slash = 'div';
3157 0           return $1;
3158             }
3159              
3160             # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Char::Ecyrillic::POSTMATCH()
3161             elsif (/\G ( \$ \s* POSTMATCH \b | \$ \s* \{ \s* POSTMATCH \s* \} | \$ \s* \{\^POSTMATCH\} ) /oxmsgc) {
3162 0           $slash = 'div';
3163 0           return q{Char::Ecyrillic::POSTMATCH()};
3164             }
3165              
3166             # scalar variable $scalar =~ tr///;
3167             # scalar variable $scalar =~ s///;
3168             # substr() =~ tr///;
3169             # substr() =~ s///;
3170             elsif (/\G ( \$ $qq_scalar | $qq_substr ) /oxgc) {
3171 0           my $scalar = e_string($1);
3172              
3173 0 0         if (/\G ( \s* (?: =~ | !~ ) \s* ) (?= (?: tr | y ) \b ) /oxgc) {
    0          
3174 0           $tr_variable = $scalar;
3175 0           $bind_operator = $1;
3176 0           $slash = 'm//';
3177 0           return '';
3178             }
3179             elsif (/\G ( \s* (?: =~ | !~ ) \s* ) (?= s \b ) /oxgc) {
3180 0           $sub_variable = $scalar;
3181 0           $bind_operator = $1;
3182 0           $slash = 'm//';
3183 0           return '';
3184             }
3185             else {
3186 0           $slash = 'div';
3187 0           return $scalar;
3188             }
3189             }
3190              
3191             # end of statement
3192             elsif (/\G ( [,;] ) /oxgc) {
3193 0           $slash = 'm//';
3194              
3195             # clear tr/// variable
3196 0           $tr_variable = '';
3197              
3198             # clear s/// variable
3199 0           $sub_variable = '';
3200              
3201 0           $bind_operator = '';
3202              
3203 0           return $1;
3204             }
3205              
3206             # bareword
3207             elsif (/\G ( \{ \s* (?: tr | index | rindex | reverse ) \s* \} ) /oxmsgc) {
3208 0           return $1;
3209             }
3210              
3211             # $0 --> $0
3212             elsif (/\G ( \$ 0 ) /oxmsgc) {
3213 0           $slash = 'div';
3214 0           return $1;
3215             }
3216             elsif (/\G ( \$ \{ \s* 0 \s* \} ) /oxmsgc) {
3217 0           $slash = 'div';
3218 0           return $1;
3219             }
3220              
3221             # $$ --> $$
3222             elsif (/\G ( \$ \$ ) (?![\w\{]) /oxmsgc) {
3223 0           $slash = 'div';
3224 0           return $1;
3225             }
3226              
3227             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
3228             # $1, $2, $3 --> $1, $2, $3 otherwise
3229             elsif (/\G \$ ([1-9][0-9]*) /oxmsgc) {
3230 0           $slash = 'div';
3231 0           return e_capture($1);
3232             }
3233             elsif (/\G \$ \{ \s* ([1-9][0-9]*) \s* \} /oxmsgc) {
3234 0           $slash = 'div';
3235 0           return e_capture($1);
3236             }
3237              
3238             # $$foo[ ... ] --> $ $foo->[ ... ]
3239             elsif (/\G \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) ( \[ .+? \] ) /oxmsgc) {
3240 0           $slash = 'div';
3241 0           return e_capture($1.'->'.$2);
3242             }
3243              
3244             # $$foo{ ... } --> $ $foo->{ ... }
3245             elsif (/\G \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) ( \{ .+? \} ) /oxmsgc) {
3246 0           $slash = 'div';
3247 0           return e_capture($1.'->'.$2);
3248             }
3249              
3250             # $$foo
3251             elsif (/\G \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) /oxmsgc) {
3252 0           $slash = 'div';
3253 0           return e_capture($1);
3254             }
3255              
3256             # ${ foo }
3257             elsif (/\G \$ \s* \{ ( \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* ) \} /oxmsgc) {
3258 0           $slash = 'div';
3259 0           return '${' . $1 . '}';
3260             }
3261              
3262             # ${ ... }
3263             elsif (/\G \$ \s* \{ \s* ( $qq_brace ) \s* \} /oxmsgc) {
3264 0           $slash = 'div';
3265 0           return e_capture($1);
3266             }
3267              
3268             # variable or function
3269             # $ @ % & * $ #
3270             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) {
3271 0           $slash = 'div';
3272 0           return $1;
3273             }
3274             # $ $ $ $ $ $ $ $ $ $ $ $ $ $
3275             # $ @ # \ ' " / ? ( ) [ ] < >
3276             elsif (/\G ( \$[\$\@\#\\\'\"\/\?\(\)\[\]\<\>] ) /oxmsgc) {
3277 0           $slash = 'div';
3278 0           return $1;
3279             }
3280              
3281             # while ()
3282             elsif (/\G \b (while \s* \( \s* <[\$]?[A-Za-z_][A-Za-z_0-9]*> \s* \)) \b /oxgc) {
3283 0           return $1;
3284             }
3285              
3286             # while () --- glob
3287              
3288             # avoid "Error: Runtime exception" of perl version 5.005_03
3289              
3290             elsif (/\G \b while \s* \( \s* < ((?:[^>\0\a\e\f\n\r\t])+?) > \s* \) \b /oxgc) {
3291 0           return 'while ($_ = Char::Ecyrillic::glob("' . $1 . '"))';
3292             }
3293              
3294             # while (glob)
3295             elsif (/\G \b while \s* \( \s* glob \s* \) /oxgc) {
3296 0           return 'while ($_ = Char::Ecyrillic::glob_)';
3297             }
3298              
3299             # while (glob(WILDCARD))
3300             elsif (/\G \b while \s* \( \s* glob \b /oxgc) {
3301 0           return 'while ($_ = Char::Ecyrillic::glob';
3302             }
3303              
3304             # doit if, doit unless, doit while, doit until, doit for, doit when
3305 0           elsif (/\G \b ( if | unless | while | until | for | when ) \b /oxgc) { $slash = 'm//'; return $1; }
  0            
3306              
3307             # subroutines of package Char::Ecyrillic
3308 0           elsif (/\G \b (CORE:: | ->[ ]* (?: atan2 | [a-z]{2,})) \b /oxgc) { $slash = 'm//'; return $1; }
  0            
3309 0           elsif (/\G \b Char::Cyrillic::eval (?= \s* \{ ) /oxgc) { $slash = 'm//'; return 'eval'; }
  0            
3310 0           elsif (/\G \b Char::Cyrillic::eval \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'eval Char::Cyrillic::escape'; }
  0            
3311 0           elsif (/\G \b bytes::substr \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'substr'; }
  0            
3312 0           elsif (/\G \b chop \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'Char::Ecyrillic::chop'; }
  0            
3313 0           elsif (/\G \b bytes::index \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'index'; }
  0            
3314 0           elsif (/\G \b Char::Cyrillic::index \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'Char::Cyrillic::index'; }
  0            
3315 0           elsif (/\G \b index \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'Char::Ecyrillic::index'; }
  0            
3316 0           elsif (/\G \b bytes::rindex \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'rindex'; }
  0            
3317 0           elsif (/\G \b Char::Cyrillic::rindex \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'Char::Cyrillic::rindex'; }
  0            
3318 0           elsif (/\G \b rindex \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'Char::Ecyrillic::rindex'; }
  0            
3319 0           elsif (/\G \b lc (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Char::Ecyrillic::lc'; }
  0            
3320 0           elsif (/\G \b lcfirst (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Char::Ecyrillic::lcfirst'; }
  0            
3321 0           elsif (/\G \b uc (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Char::Ecyrillic::uc'; }
  0            
3322 0           elsif (/\G \b ucfirst (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Char::Ecyrillic::ucfirst'; }
  0            
3323 0           elsif (/\G \b fc (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Char::Ecyrillic::fc'; }
  0            
3324              
3325             # "-s '' ..." means file test "-s 'filename' ..." (not means "- s/// ...")
3326 0           elsif (/\G -s \s+ \s* (\") ((?:$qq_char)+?) (\") /oxgc) { $slash = 'm//'; return '-s ' . e_qq('', $1,$3,$2); }
  0            
3327 0           elsif (/\G -s \s+ qq \s* (\#) ((?:$qq_char)+?) (\#) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0            
3328 0           elsif (/\G -s \s+ qq \s* (\() ((?:$qq_paren)+?) (\)) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0            
3329 0           elsif (/\G -s \s+ qq \s* (\{) ((?:$qq_brace)+?) (\}) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0            
3330 0           elsif (/\G -s \s+ qq \s* (\[) ((?:$qq_bracket)+?) (\]) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0            
3331 0           elsif (/\G -s \s+ qq \s* (\<) ((?:$qq_angle)+?) (\>) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0            
3332 0           elsif (/\G -s \s+ qq \s* (\S) ((?:$qq_char)+?) (\1) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0            
3333              
3334 0           elsif (/\G -s \s+ \s* (\') ((?:\\\'|\\\\|$q_char)+?) (\') /oxgc) { $slash = 'm//'; return '-s ' . e_q ('', $1,$3,$2); }
  0            
3335 0           elsif (/\G -s \s+ q \s* (\#) ((?:\\\#|\\\\|$q_char)+?) (\#) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0            
3336 0           elsif (/\G -s \s+ q \s* (\() ((?:\\\)|\\\\|$q_paren)+?) (\)) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0            
3337 0           elsif (/\G -s \s+ q \s* (\{) ((?:\\\}|\\\\|$q_brace)+?) (\}) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0            
3338 0           elsif (/\G -s \s+ q \s* (\[) ((?:\\\]|\\\\|$q_bracket)+?) (\]) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0            
3339 0           elsif (/\G -s \s+ q \s* (\<) ((?:\\\>|\\\\|$q_angle)+?) (\>) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0            
3340 0           elsif (/\G -s \s+ q \s* (\S) ((?:\\\1|\\\\|$q_char)+?) (\1) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0            
3341              
3342             elsif (/\G -s \s* (\$ \w+(?: ::\w+)* (?: (?: ->)? (?: [\$\@\%\&\*]\* | \$\#\* | \( (?:$qq_paren)*? \) | [\@\%\*]? \{ (?:$qq_brace)+? \} | [\@\%]? \[ (?:$qq_bracket)+? \] ) )*) /oxgc)
3343 0           { $slash = 'm//'; return "-s $1"; }
  0            
3344 0           elsif (/\G -s \s* \( ((?:$qq_paren)*?) \) /oxgc) { $slash = 'm//'; return "-s ($1)"; }
  0            
3345 0           elsif (/\G -s (?= \s+ [a-z]+) /oxgc) { $slash = 'm//'; return '-s'; }
  0            
3346 0           elsif (/\G -s \s+ (\w+) /oxgc) { $slash = 'm//'; return "-s $1"; }
  0            
3347              
3348 0           elsif (/\G \b bytes::length (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'length'; }
  0            
3349 0           elsif (/\G \b bytes::chr (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'chr'; }
  0            
3350 0           elsif (/\G \b chr (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Char::Ecyrillic::chr'; }
  0            
3351 0           elsif (/\G \b bytes::ord (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $slash = 'div'; return 'ord'; }
  0            
3352 0           elsif (/\G \b ord (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $slash = 'div'; return $function_ord; }
  0            
3353 0           elsif (/\G \b glob (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Char::Ecyrillic::glob'; }
  0            
3354 0           elsif (/\G \b lc \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'Char::Ecyrillic::lc_'; }
  0            
3355 0           elsif (/\G \b lcfirst \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'Char::Ecyrillic::lcfirst_'; }
  0            
3356 0           elsif (/\G \b uc \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'Char::Ecyrillic::uc_'; }
  0            
3357 0           elsif (/\G \b ucfirst \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'Char::Ecyrillic::ucfirst_'; }
  0            
3358 0           elsif (/\G \b fc \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'Char::Ecyrillic::fc_'; }
  0            
3359 0           elsif (/\G -s \b (?! \s* => ) /oxgc) { $slash = 'm//'; return '-s '; }
  0            
3360              
3361 0           elsif (/\G \b bytes::length \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'length'; }
  0            
3362 0           elsif (/\G \b bytes::chr \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'chr'; }
  0            
3363 0           elsif (/\G \b chr \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'Char::Ecyrillic::chr_'; }
  0            
3364 0           elsif (/\G \b bytes::ord \b (?! \s* => ) /oxgc) { $slash = 'div'; return 'ord'; }
  0            
3365 0           elsif (/\G \b ord \b (?! \s* => ) /oxgc) { $slash = 'div'; return $function_ord_; }
  0            
3366 0           elsif (/\G \b glob \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'Char::Ecyrillic::glob_'; }
  0            
3367 0           elsif (/\G \b reverse \b (?! \s* => ) /oxgc) { $slash = 'm//'; return $function_reverse; }
  0            
3368 0           elsif (/\G \b getc \b (?! \s* => ) /oxgc) { $slash = 'm//'; return $function_getc; }
  0            
3369             # split
3370             elsif (/\G \b (split) \b (?! \s* => ) /oxgc) {
3371 0           $slash = 'm//';
3372              
3373 0           my $e = '';
3374 0           while (/\G ( \s+ | \( | \#.* ) /oxgc) {
3375 0           $e .= $1;
3376             }
3377              
3378             # end of split
3379 0 0         if (/\G (?= [,;\)\}\]] ) /oxgc) { return 'Char::Ecyrillic::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          
3380              
3381             # split scalar value
3382 0           elsif (/\G ( [\$\@\&\*] $qq_scalar ) /oxgc) { return 'Char::Ecyrillic::split' . $e . e_string($1); }
3383              
3384             # split literal space
3385 0           elsif (/\G \b qq (\#) [ ] (\#) /oxgc) { return 'Char::Ecyrillic::split' . $e . qq {qq$1 $2}; }
3386 0           elsif (/\G \b qq (\s*) (\() [ ] (\)) /oxgc) { return 'Char::Ecyrillic::split' . $e . qq{$1qq$2 $3}; }
3387 0           elsif (/\G \b qq (\s*) (\{) [ ] (\}) /oxgc) { return 'Char::Ecyrillic::split' . $e . qq{$1qq$2 $3}; }
3388 0           elsif (/\G \b qq (\s*) (\[) [ ] (\]) /oxgc) { return 'Char::Ecyrillic::split' . $e . qq{$1qq$2 $3}; }
3389 0           elsif (/\G \b qq (\s*) (\<) [ ] (\>) /oxgc) { return 'Char::Ecyrillic::split' . $e . qq{$1qq$2 $3}; }
3390 0           elsif (/\G \b qq (\s*) (\S) [ ] (\2) /oxgc) { return 'Char::Ecyrillic::split' . $e . qq{$1qq$2 $3}; }
3391 0           elsif (/\G \b q (\#) [ ] (\#) /oxgc) { return 'Char::Ecyrillic::split' . $e . qq {q$1 $2}; }
3392 0           elsif (/\G \b q (\s*) (\() [ ] (\)) /oxgc) { return 'Char::Ecyrillic::split' . $e . qq {$1q$2 $3}; }
3393 0           elsif (/\G \b q (\s*) (\{) [ ] (\}) /oxgc) { return 'Char::Ecyrillic::split' . $e . qq {$1q$2 $3}; }
3394 0           elsif (/\G \b q (\s*) (\[) [ ] (\]) /oxgc) { return 'Char::Ecyrillic::split' . $e . qq {$1q$2 $3}; }
3395 0           elsif (/\G \b q (\s*) (\<) [ ] (\>) /oxgc) { return 'Char::Ecyrillic::split' . $e . qq {$1q$2 $3}; }
3396 0           elsif (/\G \b q (\s*) (\S) [ ] (\2) /oxgc) { return 'Char::Ecyrillic::split' . $e . qq {$1q$2 $3}; }
3397 0           elsif (/\G ' [ ] ' /oxgc) { return 'Char::Ecyrillic::split' . $e . qq {' '}; }
3398 0           elsif (/\G " [ ] " /oxgc) { return 'Char::Ecyrillic::split' . $e . qq {" "}; }
3399              
3400             # split qq//
3401             elsif (/\G \b (qq) \b /oxgc) {
3402 0 0         if (/\G (\#) ((?:$qq_char)*?) (\#) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq# # --> qr # #
  0            
3403             else {
3404 0           while (not /\G \z/oxgc) {
3405 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
3406 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq ( ) --> qr ( )
3407 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq { } --> qr { }
3408 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq [ ] --> qr [ ]
3409 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq < > --> qr < >
3410 0           elsif (/\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) /oxgc) { return e_split($e.'qr','{','}',$2,''); } # qq | | --> qr { }
3411 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq * * --> qr * *
3412             }
3413 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3414             }
3415             }
3416              
3417             # split qr//
3418             elsif (/\G \b (qr) \b /oxgc) {
3419 0 0         if (/\G (\#) ((?:$qq_char)*?) (\#) ([imosxpadlubB]*) /oxgc) { return e_split ($e.'qr',$1,$3,$2,$4); } # qr# #
  0            
3420             else {
3421 0           while (not /\G \z/oxgc) {
3422 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
3423 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([imosxpadlubB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # qr ( )
3424 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([imosxpadlubB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # qr { }
3425 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([imosxpadlubB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # qr [ ]
3426 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([imosxpadlubB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # qr < >
3427 0           elsif (/\G (\') ((?:$qq_char)*?) (\') ([imosxpadlubB]*) /oxgc) { return e_split_q($e.'qr',$1, $3, $2,$4); } # qr ' '
3428 0           elsif (/\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ([imosxpadlubB]*) /oxgc) { return e_split ($e.'qr','{','}',$2,$4); } # qr | | --> qr { }
3429 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([imosxpadlubB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # qr * *
3430             }
3431 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3432             }
3433             }
3434              
3435             # split q//
3436             elsif (/\G \b (q) \b /oxgc) {
3437 0 0         if (/\G (\#) ((?:\\\#|\\\\|$q_char)*?) (\#) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q# # --> qr # #
  0            
3438             else {
3439 0           while (not /\G \z/oxgc) {
3440 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
3441 0           elsif (/\G (\() ((?:\\\\|\\\)|\\\(|$q_paren)*?) (\)) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q ( ) --> qr ( )
3442 0           elsif (/\G (\{) ((?:\\\\|\\\}|\\\{|$q_brace)*?) (\}) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q { } --> qr { }
3443 0           elsif (/\G (\[) ((?:\\\\|\\\]|\\\[|$q_bracket)*?) (\]) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q [ ] --> qr [ ]
3444 0           elsif (/\G (\<) ((?:\\\\|\\\>|\\\<|$q_angle)*?) (\>) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q < > --> qr < >
3445 0           elsif (/\G ([*\-:?\\^|]) ((?:$q_char)*?) (\1) /oxgc) { return e_split_q($e.'qr','{','}',$2,''); } # q | | --> qr { }
3446 0           elsif (/\G (\S) ((?:\\\\|\\\1| $q_char)*?) (\1) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q * * --> qr * *
3447             }
3448 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3449             }
3450             }
3451              
3452             # split m//
3453             elsif (/\G \b (m) \b /oxgc) {
3454 0 0         if (/\G (\#) ((?:$qq_char)*?) (\#) ([cgimosxpadlubB]*) /oxgc) { return e_split ($e.'qr',$1,$3,$2,$4); } # m# # --> qr # #
  0            
3455             else {
3456 0           while (not /\G \z/oxgc) {
3457 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
3458 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cgimosxpadlubB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # m ( ) --> qr ( )
3459 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cgimosxpadlubB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # m { } --> qr { }
3460 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cgimosxpadlubB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # m [ ] --> qr [ ]
3461 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cgimosxpadlubB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # m < > --> qr < >
3462 0           elsif (/\G (\') ((?:$qq_char)*?) (\') ([cgimosxpadlubB]*) /oxgc) { return e_split_q($e.'qr',$1, $3, $2,$4); } # m ' ' --> qr ' '
3463 0           elsif (/\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ([cgimosxpadlubB]*) /oxgc) { return e_split ($e.'qr','{','}',$2,$4); } # m | | --> qr { }
3464 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cgimosxpadlubB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # m * * --> qr * *
3465             }
3466 0           die __FILE__, ": Search pattern not terminated";
3467             }
3468             }
3469              
3470             # split ''
3471             elsif (/\G (\') /oxgc) {
3472 0           my $q_string = '';
3473 0           while (not /\G \z/oxgc) {
3474 0 0         if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0          
    0          
    0          
3475 0           elsif (/\G (\\\') /oxgc) { $q_string .= $1; } # splitqr'' --> split qr''
3476 0           elsif (/\G \' /oxgc) { return e_split_q($e.q{ qr},"'","'",$q_string,''); } # ' ' --> qr ' '
3477 0           elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3478             }
3479 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3480             }
3481              
3482             # split ""
3483             elsif (/\G (\") /oxgc) {
3484 0           my $qq_string = '';
3485 0           while (not /\G \z/oxgc) {
3486 0 0         if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0          
    0          
    0          
3487 0           elsif (/\G (\\\") /oxgc) { $qq_string .= $1; } # splitqr"" --> split qr""
3488 0           elsif (/\G \" /oxgc) { return e_split($e.q{ qr},'"','"',$qq_string,''); } # " " --> qr " "
3489 0           elsif (/\G ($q_char) /oxgc) { $qq_string .= $1; }
3490             }
3491 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3492             }
3493              
3494             # split //
3495             elsif (/\G (\/) /oxgc) {
3496 0           my $regexp = '';
3497 0           while (not /\G \z/oxgc) {
3498 0 0         if (/\G (\\\\) /oxgc) { $regexp .= $1; }
  0 0          
    0          
    0          
3499 0           elsif (/\G (\\\/) /oxgc) { $regexp .= $1; } # splitqr// --> split qr//
3500 0           elsif (/\G \/ ([cgimosxpadlubB]*) /oxgc) { return e_split($e.q{ qr}, '/','/',$regexp,$1); } # / / --> qr / /
3501 0           elsif (/\G ($q_char) /oxgc) { $regexp .= $1; }
3502             }
3503 0           die __FILE__, ": Search pattern not terminated";
3504             }
3505             }
3506              
3507             # tr/// or y///
3508              
3509             # about [cdsrbB]* (/B modifier)
3510             #
3511             # P.559 appendix C
3512             # of ISBN 4-89052-384-7 Programming perl
3513             # (Japanese title is: Perl puroguramingu)
3514              
3515             elsif (/\G \b ( tr | y ) \b /oxgc) {
3516 0           my $ope = $1;
3517              
3518             # $1 $2 $3 $4 $5 $6
3519 0 0         if (/\G (\#) ((?:$qq_char)*?) (\#) ((?:$qq_char)*?) (\#) ([cdsrbB]*) /oxgc) { # tr# # #
3520 0           my @tr = ($tr_variable,$2);
3521 0           return e_tr(@tr,'',$4,$6);
3522             }
3523             else {
3524 0           my $e = '';
3525 0           while (not /\G \z/oxgc) {
3526 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3527             elsif (/\G (\() ((?:$qq_paren)*?) (\)) /oxgc) {
3528 0           my @tr = ($tr_variable,$2);
3529 0           while (not /\G \z/oxgc) {
3530 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3531 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr ( ) ( )
3532 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr ( ) { }
3533 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr ( ) [ ]
3534 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr ( ) < >
3535 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr ( ) * *
3536             }
3537 0           die __FILE__, ": Transliteration replacement not terminated";
3538             }
3539             elsif (/\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) {
3540 0           my @tr = ($tr_variable,$2);
3541 0           while (not /\G \z/oxgc) {
3542 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3543 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr { } ( )
3544 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr { } { }
3545 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr { } [ ]
3546 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr { } < >
3547 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr { } * *
3548             }
3549 0           die __FILE__, ": Transliteration replacement not terminated";
3550             }
3551             elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) {
3552 0           my @tr = ($tr_variable,$2);
3553 0           while (not /\G \z/oxgc) {
3554 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3555 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr [ ] ( )
3556 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr [ ] { }
3557 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr [ ] [ ]
3558 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr [ ] < >
3559 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr [ ] * *
3560             }
3561 0           die __FILE__, ": Transliteration replacement not terminated";
3562             }
3563             elsif (/\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) {
3564 0           my @tr = ($tr_variable,$2);
3565 0           while (not /\G \z/oxgc) {
3566 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3567 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr < > ( )
3568 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr < > { }
3569 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr < > [ ]
3570 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr < > < >
3571 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr < > * *
3572             }
3573 0           die __FILE__, ": Transliteration replacement not terminated";
3574             }
3575             # $1 $2 $3 $4 $5 $6
3576             elsif (/\G (\S) ((?:$qq_char)*?) (\1) ((?:$qq_char)*?) (\1) ([cdsrbB]*) /oxgc) { # tr * * *
3577 0           my @tr = ($tr_variable,$2);
3578 0           return e_tr(@tr,'',$4,$6);
3579             }
3580             }
3581 0           die __FILE__, ": Transliteration pattern not terminated";
3582             }
3583             }
3584              
3585             # qq//
3586             elsif (/\G \b (qq) \b /oxgc) {
3587 0           my $ope = $1;
3588              
3589             # if (/\G (\#) ((?:$qq_char)*?) (\#) /oxgc) { return e_qq($ope,$1,$3,$2); } # qq# #
3590 0 0         if (/\G (\#) /oxgc) { # qq# #
3591 0           my $qq_string = '';
3592 0           while (not /\G \z/oxgc) {
3593 0 0         if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0          
    0          
    0          
3594 0           elsif (/\G (\\\#) /oxgc) { $qq_string .= $1; }
3595 0           elsif (/\G (\#) /oxgc) { return e_qq($ope,'#','#',$qq_string); }
3596 0           elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3597             }
3598 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3599             }
3600              
3601             else {
3602 0           my $e = '';
3603 0           while (not /\G \z/oxgc) {
3604 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3605              
3606             # elsif (/\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qq ( )
3607             elsif (/\G (\() /oxgc) { # qq ( )
3608 0           my $qq_string = '';
3609 0           local $nest = 1;
3610 0           while (not /\G \z/oxgc) {
3611 0 0         if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0          
    0          
    0          
    0          
3612 0           elsif (/\G (\\\)) /oxgc) { $qq_string .= $1; }
3613 0           elsif (/\G (\() /oxgc) { $qq_string .= $1; $nest++; }
  0            
3614             elsif (/\G (\)) /oxgc) {
3615 0 0         if (--$nest == 0) { return $e . e_qq($ope,'(',')',$qq_string); }
  0            
3616 0           else { $qq_string .= $1; }
3617             }
3618 0           elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3619             }
3620 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3621             }
3622              
3623             # elsif (/\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qq { }
3624             elsif (/\G (\{) /oxgc) { # qq { }
3625 0           my $qq_string = '';
3626 0           local $nest = 1;
3627 0           while (not /\G \z/oxgc) {
3628 0 0         if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0          
    0          
    0          
    0          
3629 0           elsif (/\G (\\\}) /oxgc) { $qq_string .= $1; }
3630 0           elsif (/\G (\{) /oxgc) { $qq_string .= $1; $nest++; }
  0            
3631             elsif (/\G (\}) /oxgc) {
3632 0 0         if (--$nest == 0) { return $e . e_qq($ope,'{','}',$qq_string); }
  0            
3633 0           else { $qq_string .= $1; }
3634             }
3635 0           elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3636             }
3637 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3638             }
3639              
3640             # elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qq [ ]
3641             elsif (/\G (\[) /oxgc) { # qq [ ]
3642 0           my $qq_string = '';
3643 0           local $nest = 1;
3644 0           while (not /\G \z/oxgc) {
3645 0 0         if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0          
    0          
    0          
    0          
3646 0           elsif (/\G (\\\]) /oxgc) { $qq_string .= $1; }
3647 0           elsif (/\G (\[) /oxgc) { $qq_string .= $1; $nest++; }
  0            
3648             elsif (/\G (\]) /oxgc) {
3649 0 0         if (--$nest == 0) { return $e . e_qq($ope,'[',']',$qq_string); }
  0            
3650 0           else { $qq_string .= $1; }
3651             }
3652 0           elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3653             }
3654 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3655             }
3656              
3657             # elsif (/\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qq < >
3658             elsif (/\G (\<) /oxgc) { # qq < >
3659 0           my $qq_string = '';
3660 0           local $nest = 1;
3661 0           while (not /\G \z/oxgc) {
3662 0 0         if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0          
    0          
    0          
    0          
3663 0           elsif (/\G (\\\>) /oxgc) { $qq_string .= $1; }
3664 0           elsif (/\G (\<) /oxgc) { $qq_string .= $1; $nest++; }
  0            
3665             elsif (/\G (\>) /oxgc) {
3666 0 0         if (--$nest == 0) { return $e . e_qq($ope,'<','>',$qq_string); }
  0            
3667 0           else { $qq_string .= $1; }
3668             }
3669 0           elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3670             }
3671 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3672             }
3673              
3674             # elsif (/\G (\S) ((?:$qq_char)*?) (\1) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qq * *
3675             elsif (/\G (\S) /oxgc) { # qq * *
3676 0           my $delimiter = $1;
3677 0           my $qq_string = '';
3678 0           while (not /\G \z/oxgc) {
3679 0 0         if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0          
    0          
    0          
3680 0           elsif (/\G (\\\Q$delimiter\E) /oxgc) { $qq_string .= $1; }
3681 0           elsif (/\G (\Q$delimiter\E) /oxgc) { return $e . e_qq($ope,$delimiter,$delimiter,$qq_string); }
3682 0           elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3683             }
3684 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3685             }
3686             }
3687 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3688             }
3689             }
3690              
3691             # qr//
3692             elsif (/\G \b (qr) \b /oxgc) {
3693 0           my $ope = $1;
3694 0 0         if (/\G (\#) ((?:$qq_char)*?) (\#) ([imosxpadlubB]*) /oxgc) { # qr# # #
3695 0           return e_qr($ope,$1,$3,$2,$4);
3696             }
3697             else {
3698 0           my $e = '';
3699 0           while (not /\G \z/oxgc) {
3700 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
3701 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([imosxpadlubB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # qr ( )
3702 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([imosxpadlubB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # qr { }
3703 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([imosxpadlubB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # qr [ ]
3704 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([imosxpadlubB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # qr < >
3705 0           elsif (/\G (\') ((?:$qq_char)*?) (\') ([imosxpadlubB]*) /oxgc) { return $e . e_qr_q($ope,$1, $3, $2,$4); } # qr ' '
3706 0           elsif (/\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ([imosxpadlubB]*) /oxgc) { return $e . e_qr ($ope,'{','}',$2,$4); } # qr | | --> qr { }
3707 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([imosxpadlubB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # qr * *
3708             }
3709 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3710             }
3711             }
3712              
3713             # qw//
3714             elsif (/\G \b (qw) \b /oxgc) {
3715 0           my $ope = $1;
3716 0 0         if (/\G (\#) (.*?) (\#) /oxmsgc) { # qw# #
3717 0           return e_qw($ope,$1,$3,$2);
3718             }
3719             else {
3720 0           my $e = '';
3721 0           while (not /\G \z/oxgc) {
3722 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
3723              
3724 0           elsif (/\G (\() ([^(]*?) (\)) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw ( )
3725 0           elsif (/\G (\() ((?:$q_paren)*?) (\)) /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_brace)*?) (\}) /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_bracket)*?) (\]) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw [ ]
3732              
3733 0           elsif (/\G (\<) ([^<]*?) (\>) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw < >
3734 0           elsif (/\G (\<) ((?:$q_angle)*?) (\>) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw < >
3735              
3736 0           elsif (/\G ([\x21-\x3F]) (.*?) (\1) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw * *
3737 0           elsif (/\G (\S) ((?:$q_char)*?) (\1) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw * *
3738             }
3739 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3740             }
3741             }
3742              
3743             # qx//
3744             elsif (/\G \b (qx) \b /oxgc) {
3745 0           my $ope = $1;
3746 0 0         if (/\G (\#) ((?:$qq_char)*?) (\#) /oxgc) { # qx# #
3747 0           return e_qq($ope,$1,$3,$2);
3748             }
3749             else {
3750 0           my $e = '';
3751 0           while (not /\G \z/oxgc) {
3752 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
3753 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qx ( )
3754 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qx { }
3755 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qx [ ]
3756 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qx < >
3757 0           elsif (/\G (\') ((?:$qq_char)*?) (\') /oxgc) { return $e . e_q ($ope,$1,$3,$2); } # qx ' '
3758 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qx * *
3759             }
3760 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3761             }
3762             }
3763              
3764             # q//
3765             elsif (/\G \b (q) \b /oxgc) {
3766 0           my $ope = $1;
3767              
3768             # if (/\G (\#) ((?:\\\#|\\\\|$q_char)*?) (\#) /oxgc) { return e_q($ope,$1,$3,$2); } # q# #
3769              
3770             # avoid "Error: Runtime exception" of perl version 5.005_03
3771             # (and so on)
3772              
3773 0 0         if (/\G (\#) /oxgc) { # q# #
3774 0           my $q_string = '';
3775 0           while (not /\G \z/oxgc) {
3776 0 0         if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0          
    0          
    0          
3777 0           elsif (/\G (\\\#) /oxgc) { $q_string .= $1; }
3778 0           elsif (/\G (\#) /oxgc) { return e_q($ope,'#','#',$q_string); }
3779 0           elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3780             }
3781 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3782             }
3783              
3784             else {
3785 0           my $e = '';
3786 0           while (not /\G \z/oxgc) {
3787 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3788              
3789             # elsif (/\G (\() ((?:\\\)|\\\\|$q_paren)*?) (\)) /oxgc) { return $e . e_q($ope,$1,$3,$2); } # q ( )
3790             elsif (/\G (\() /oxgc) { # q ( )
3791 0           my $q_string = '';
3792 0           local $nest = 1;
3793 0           while (not /\G \z/oxgc) {
3794 0 0         if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3795 0           elsif (/\G (\\\)) /oxgc) { $q_string .= $1; }
3796 0           elsif (/\G (\\\() /oxgc) { $q_string .= $1; }
3797 0           elsif (/\G (\() /oxgc) { $q_string .= $1; $nest++; }
  0            
3798             elsif (/\G (\)) /oxgc) {
3799 0 0         if (--$nest == 0) { return $e . e_q($ope,'(',')',$q_string); }
  0            
3800 0           else { $q_string .= $1; }
3801             }
3802 0           elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3803             }
3804 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3805             }
3806              
3807             # elsif (/\G (\{) ((?:\\\}|\\\\|$q_brace)*?) (\}) /oxgc) { return $e . e_q($ope,$1,$3,$2); } # q { }
3808             elsif (/\G (\{) /oxgc) { # q { }
3809 0           my $q_string = '';
3810 0           local $nest = 1;
3811 0           while (not /\G \z/oxgc) {
3812 0 0         if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3813 0           elsif (/\G (\\\}) /oxgc) { $q_string .= $1; }
3814 0           elsif (/\G (\\\{) /oxgc) { $q_string .= $1; }
3815 0           elsif (/\G (\{) /oxgc) { $q_string .= $1; $nest++; }
  0            
3816             elsif (/\G (\}) /oxgc) {
3817 0 0         if (--$nest == 0) { return $e . e_q($ope,'{','}',$q_string); }
  0            
3818 0           else { $q_string .= $1; }
3819             }
3820 0           elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3821             }
3822 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3823             }
3824              
3825             # elsif (/\G (\[) ((?:\\\]|\\\\|$q_bracket)*?) (\]) /oxgc) { return $e . e_q($ope,$1,$3,$2); } # q [ ]
3826             elsif (/\G (\[) /oxgc) { # q [ ]
3827 0           my $q_string = '';
3828 0           local $nest = 1;
3829 0           while (not /\G \z/oxgc) {
3830 0 0         if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3831 0           elsif (/\G (\\\]) /oxgc) { $q_string .= $1; }
3832 0           elsif (/\G (\\\[) /oxgc) { $q_string .= $1; }
3833 0           elsif (/\G (\[) /oxgc) { $q_string .= $1; $nest++; }
  0            
3834             elsif (/\G (\]) /oxgc) {
3835 0 0         if (--$nest == 0) { return $e . e_q($ope,'[',']',$q_string); }
  0            
3836 0           else { $q_string .= $1; }
3837             }
3838 0           elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3839             }
3840 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3841             }
3842              
3843             # elsif (/\G (\<) ((?:\\\>|\\\\|$q_angle)*?) (\>) /oxgc) { return $e . e_q($ope,$1,$3,$2); } # q < >
3844             elsif (/\G (\<) /oxgc) { # q < >
3845 0           my $q_string = '';
3846 0           local $nest = 1;
3847 0           while (not /\G \z/oxgc) {
3848 0 0         if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3849 0           elsif (/\G (\\\>) /oxgc) { $q_string .= $1; }
3850 0           elsif (/\G (\\\<) /oxgc) { $q_string .= $1; }
3851 0           elsif (/\G (\<) /oxgc) { $q_string .= $1; $nest++; }
  0            
3852             elsif (/\G (\>) /oxgc) {
3853 0 0         if (--$nest == 0) { return $e . e_q($ope,'<','>',$q_string); }
  0            
3854 0           else { $q_string .= $1; }
3855             }
3856 0           elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3857             }
3858 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3859             }
3860              
3861             # elsif (/\G (\S) ((?:\\\1|\\\\|$q_char)*?) (\1) /oxgc) { return $e . e_q($ope,$1,$3,$2); } # q * *
3862             elsif (/\G (\S) /oxgc) { # q * *
3863 0           my $delimiter = $1;
3864 0           my $q_string = '';
3865 0           while (not /\G \z/oxgc) {
3866 0 0         if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0          
    0          
    0          
3867 0           elsif (/\G (\\\Q$delimiter\E) /oxgc) { $q_string .= $1; }
3868 0           elsif (/\G (\Q$delimiter\E) /oxgc) { return $e . e_q($ope,$delimiter,$delimiter,$q_string); }
3869 0           elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3870             }
3871 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3872             }
3873             }
3874 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3875             }
3876             }
3877              
3878             # m//
3879             elsif (/\G \b (m) \b /oxgc) {
3880 0           my $ope = $1;
3881 0 0         if (/\G (\#) ((?:$qq_char)*?) (\#) ([cgimosxpadlubB]*) /oxgc) { # m# #
3882 0           return e_qr($ope,$1,$3,$2,$4);
3883             }
3884             else {
3885 0           my $e = '';
3886 0           while (not /\G \z/oxgc) {
3887 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
3888 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cgimosxpadlubB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m ( )
3889 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cgimosxpadlubB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m { }
3890 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cgimosxpadlubB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m [ ]
3891 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cgimosxpadlubB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m < >
3892 0           elsif (/\G (\?) ((?:$qq_char)*?) (\?) ([cgimosxpadlubB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m ? ?
3893 0           elsif (/\G (\') ((?:$qq_char)*?) (\') ([cgimosxpadlubB]*) /oxgc) { return $e . e_qr_q($ope,$1, $3, $2,$4); } # m ' '
3894 0           elsif (/\G ([*\-:\\^|]) ((?:$qq_char)*?) (\1) ([cgimosxpadlubB]*) /oxgc) { return $e . e_qr ($ope,'{','}',$2,$4); } # m | | --> m { }
3895 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cgimosxpadlubB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m * *
3896             }
3897 0           die __FILE__, ": Search pattern not terminated";
3898             }
3899             }
3900              
3901             # s///
3902              
3903             # about [cegimosxpradlubB]* (/cg modifier)
3904             #
3905             # P.67 Pattern-Matching Operators
3906             # of ISBN 0-596-00241-6 Perl in a Nutshell, Second Edition.
3907              
3908             elsif (/\G \b (s) \b /oxgc) {
3909 0           my $ope = $1;
3910              
3911             # $1 $2 $3 $4 $5 $6
3912 0 0         if (/\G (\#) ((?:$qq_char)*?) (\#) ((?:$qq_char)*?) (\#) ([cegimosxpradlubB]*) /oxgc) { # s# # #
3913 0           return e_sub($sub_variable,$1,$2,$3,$3,$4,$5,$6);
3914             }
3915             else {
3916 0           my $e = '';
3917 0           while (not /\G \z/oxgc) {
3918 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
3919             elsif (/\G (\() ((?:$qq_paren)*?) (\)) /oxgc) {
3920 0           my @s = ($1,$2,$3);
3921 0           while (not /\G \z/oxgc) {
3922 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
3923             # $1 $2 $3 $4
3924 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3925 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3926 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3927 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3928 0           elsif (/\G (\') ((?:$qq_char)*?) (\') ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3929 0           elsif (/\G (\$) ((?:$qq_char)*?) (\$) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3930 0           elsif (/\G (\:) ((?:$qq_char)*?) (\:) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3931 0           elsif (/\G (\@) ((?:$qq_char)*?) (\@) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3932 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3933             }
3934 0           die __FILE__, ": Substitution replacement not terminated";
3935             }
3936             elsif (/\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) {
3937 0           my @s = ($1,$2,$3);
3938 0           while (not /\G \z/oxgc) {
3939 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
3940             # $1 $2 $3 $4
3941 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3942 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3943 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3944 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3945 0           elsif (/\G (\') ((?:$qq_char)*?) (\') ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3946 0           elsif (/\G (\$) ((?:$qq_char)*?) (\$) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3947 0           elsif (/\G (\:) ((?:$qq_char)*?) (\:) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3948 0           elsif (/\G (\@) ((?:$qq_char)*?) (\@) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3949 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3950             }
3951 0           die __FILE__, ": Substitution replacement not terminated";
3952             }
3953             elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) {
3954 0           my @s = ($1,$2,$3);
3955 0           while (not /\G \z/oxgc) {
3956 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
3957             # $1 $2 $3 $4
3958 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3959 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3960 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3961 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3962 0           elsif (/\G (\') ((?:$qq_char)*?) (\') ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3963 0           elsif (/\G (\$) ((?:$qq_char)*?) (\$) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3964 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3965             }
3966 0           die __FILE__, ": Substitution replacement not terminated";
3967             }
3968             elsif (/\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) {
3969 0           my @s = ($1,$2,$3);
3970 0           while (not /\G \z/oxgc) {
3971 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
3972             # $1 $2 $3 $4
3973 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3974 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3975 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3976 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3977 0           elsif (/\G (\') ((?:$qq_char)*?) (\') ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3978 0           elsif (/\G (\$) ((?:$qq_char)*?) (\$) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3979 0           elsif (/\G (\:) ((?:$qq_char)*?) (\:) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3980 0           elsif (/\G (\@) ((?:$qq_char)*?) (\@) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3981 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3982             }
3983 0           die __FILE__, ": Substitution replacement not terminated";
3984             }
3985             # $1 $2 $3 $4 $5 $6
3986             elsif (/\G (\') ((?:$qq_char)*?) (\') ((?:$qq_char)*?) (\') ([cegimosxpradlubB]*) /oxgc) {
3987 0           return e_sub($sub_variable,$1,$2,$3,$3,$4,$5,$6);
3988             }
3989             # $1 $2 $3 $4 $5 $6
3990             elsif (/\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ((?:$qq_char)*?) (\1) ([cegimosxpradlubB]*) /oxgc) {
3991 0           return e_sub($sub_variable,'{',$2,'}','{',$4,'}',$6); # s | | | --> s { } { }
3992             }
3993             # $1 $2 $3 $4 $5 $6
3994             elsif (/\G (\$) ((?:$qq_char)*?) (\1) ((?:$qq_char)*?) (\1) ([cegimosxpradlubB]*) /oxgc) {
3995 0           return e_sub($sub_variable,$1,$2,$3,$3,$4,$5,$6);
3996             }
3997             # $1 $2 $3 $4 $5 $6
3998             elsif (/\G (\S) ((?:$qq_char)*?) (\1) ((?:$qq_char)*?) (\1) ([cegimosxpradlubB]*) /oxgc) {
3999 0           return e_sub($sub_variable,$1,$2,$3,$3,$4,$5,$6);
4000             }
4001             }
4002 0           die __FILE__, ": Substitution pattern not terminated";
4003             }
4004             }
4005              
4006             # require ignore module
4007 0           elsif (/\G \b require (\s+ (?:$ignore_modules) .*? ;) ([ \t]* [#\n]) /oxmsgc) { return "# require$1$2"; }
4008 0           elsif (/\G \b require (\s+ (?:$ignore_modules) .*? ;) ([ \t]* [^#]) /oxmsgc) { return "# require$1\n$2"; }
4009 0           elsif (/\G \b require (\s+ (?:$ignore_modules)) \b /oxmsgc) { return "# require$1"; }
4010              
4011             # use strict; --> use strict; no strict qw(refs);
4012 0           elsif (/\G \b use (\s+ strict .*? ;) ([ \t]* [#\n]) /oxmsgc) { return "use$1 no strict qw(refs);$2"; }
4013 0           elsif (/\G \b use (\s+ strict .*? ;) ([ \t]* [^#]) /oxmsgc) { return "use$1 no strict qw(refs);\n$2"; }
4014 0           elsif (/\G \b use (\s+ strict) \b /oxmsgc) { return "use$1; no strict qw(refs)"; }
4015              
4016             # use 5.12.0; --> use 5.12.0; no strict qw(refs);
4017             elsif (/\G \b use \s+ (([1-9][0-9_]*)(?:\.([0-9_]+))*) \s* ; /oxmsgc) {
4018 0 0 0       if (($2 >= 6) or (($2 == 5) and ($3 ge '012'))) {
      0        
4019 0           return "use $1; no strict qw(refs);";
4020             }
4021             else {
4022 0           return "use $1;";
4023             }
4024             }
4025             elsif (/\G \b use \s+ (v([0-9][0-9_]*)(?:\.([0-9_]+))*) \s* ; /oxmsgc) {
4026 0 0 0       if (($2 >= 6) or (($2 == 5) and ($3 >= 12))) {
      0        
4027 0           return "use $1; no strict qw(refs);";
4028             }
4029             else {
4030 0           return "use $1;";
4031             }
4032             }
4033              
4034             # ignore use module
4035 0           elsif (/\G \b use (\s+ (?:$ignore_modules) .*? ;) ([ \t]* [#\n]) /oxmsgc) { return "# use$1$2"; }
4036 0           elsif (/\G \b use (\s+ (?:$ignore_modules) .*? ;) ([ \t]* [^#]) /oxmsgc) { return "# use$1\n$2"; }
4037 0           elsif (/\G \b use (\s+ (?:$ignore_modules)) \b /oxmsgc) { return "# use$1"; }
4038              
4039             # ignore no module
4040 0           elsif (/\G \b no (\s+ (?:$ignore_modules) .*? ;) ([ \t]* [#\n]) /oxmsgc) { return "# no$1$2"; }
4041 0           elsif (/\G \b no (\s+ (?:$ignore_modules) .*? ;) ([ \t]* [^#]) /oxmsgc) { return "# no$1\n$2"; }
4042 0           elsif (/\G \b no (\s+ (?:$ignore_modules)) \b /oxmsgc) { return "# no$1"; }
4043              
4044             # use else
4045 0           elsif (/\G \b use \b /oxmsgc) { return "use"; }
4046              
4047             # use else
4048 0           elsif (/\G \b no \b /oxmsgc) { return "no"; }
4049              
4050             # ''
4051             elsif (/\G (?
4052 0           my $q_string = '';
4053 0           while (not /\G \z/oxgc) {
4054 0 0         if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0          
    0          
    0          
4055 0           elsif (/\G (\\\') /oxgc) { $q_string .= $1; }
4056 0           elsif (/\G \' /oxgc) { return e_q('', "'","'",$q_string); }
4057 0           elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
4058             }
4059 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
4060             }
4061              
4062             # ""
4063             elsif (/\G (\") /oxgc) {
4064 0           my $qq_string = '';
4065 0           while (not /\G \z/oxgc) {
4066 0 0         if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0          
    0          
    0          
4067 0           elsif (/\G (\\\") /oxgc) { $qq_string .= $1; }
4068 0           elsif (/\G \" /oxgc) { return e_qq('', '"','"',$qq_string); }
4069 0           elsif (/\G ($q_char) /oxgc) { $qq_string .= $1; }
4070             }
4071 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
4072             }
4073              
4074             # ``
4075             elsif (/\G (\`) /oxgc) {
4076 0           my $qx_string = '';
4077 0           while (not /\G \z/oxgc) {
4078 0 0         if (/\G (\\\\) /oxgc) { $qx_string .= $1; }
  0 0          
    0          
    0          
4079 0           elsif (/\G (\\\`) /oxgc) { $qx_string .= $1; }
4080 0           elsif (/\G \` /oxgc) { return e_qq('', '`','`',$qx_string); }
4081 0           elsif (/\G ($q_char) /oxgc) { $qx_string .= $1; }
4082             }
4083 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
4084             }
4085              
4086             # // --- not divide operator (num / num), not defined-or
4087             elsif (($slash eq 'm//') and /\G (\/) /oxgc) {
4088 0           my $regexp = '';
4089 0           while (not /\G \z/oxgc) {
4090 0 0         if (/\G (\\\\) /oxgc) { $regexp .= $1; }
  0 0          
    0          
    0          
4091 0           elsif (/\G (\\\/) /oxgc) { $regexp .= $1; }
4092 0           elsif (/\G \/ ([cgimosxpadlubB]*) /oxgc) { return e_qr('', '/','/',$regexp,$1); }
4093 0           elsif (/\G ($q_char) /oxgc) { $regexp .= $1; }
4094             }
4095 0           die __FILE__, ": Search pattern not terminated";
4096             }
4097              
4098             # ?? --- not conditional operator (condition ? then : else)
4099             elsif (($slash eq 'm//') and /\G (\?) /oxgc) {
4100 0           my $regexp = '';
4101 0           while (not /\G \z/oxgc) {
4102 0 0         if (/\G (\\\\) /oxgc) { $regexp .= $1; }
  0 0          
    0          
    0          
4103 0           elsif (/\G (\\\?) /oxgc) { $regexp .= $1; }
4104 0           elsif (/\G \? ([cgimosxpadlubB]*) /oxgc) { return e_qr('m','?','?',$regexp,$1); }
4105 0           elsif (/\G ($q_char) /oxgc) { $regexp .= $1; }
4106             }
4107 0           die __FILE__, ": Search pattern not terminated";
4108             }
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";
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";
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";
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";
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";
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 'Char::Ecyrillic::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             \b x= |
4325             \|\|= | \|\| | \|= | \| |
4326             ~~ | ~ |
4327             \b(?: and | cmp | eq | ge | gt | le | lt | ne | not | or | xor | x )\b |
4328             \b(?: print )\b |
4329              
4330             [,;\(\{\[]
4331              
4332 0           ) /oxgc) { $slash = 'm//'; return $1; }
  0            
4333              
4334             # other any character
4335 0           elsif (/\G ($q_char) /oxgc) { $slash = 'div'; return $1; }
  0            
4336              
4337             # system error
4338             else {
4339 0           die __FILE__, ": Oops, this shouldn't happen!";
4340             }
4341             }
4342              
4343             # escape Cyrillic string
4344             sub e_string {
4345 0     0 0   my($string) = @_;
4346 0           my $e_string = '';
4347              
4348 0           local $slash = 'm//';
4349              
4350             # P.1024 Appendix W.10 Multibyte Processing
4351             # of ISBN 1-56592-224-7 CJKV Information Processing
4352             # (and so on)
4353              
4354 0           my @char = $string =~ / \G (\\?(?:$q_char)) /oxmsg;
4355              
4356             # without { ... }
4357 0 0 0       if (not (grep(/\A \{ \z/xms, @char) and grep(/\A \} \z/xms, @char))) {
4358 0 0         if ($string !~ /<
4359 0           return $string;
4360             }
4361             }
4362              
4363             E_STRING_LOOP:
4364 0           while ($string !~ /\G \z/oxgc) {
4365 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          
4366             }
4367              
4368             # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> @{[Char::Ecyrillic::PREMATCH()]}
4369 0           elsif ($string =~ /\G ( \$` | \$\{`\} | \$ \s* PREMATCH \b | \$ \s* \{ \s* PREMATCH \s* \} | \$ \s* \{\^PREMATCH\} ) /oxmsgc) {
4370 0           $e_string .= q{Char::Ecyrillic::PREMATCH()};
4371 0           $slash = 'div';
4372             }
4373              
4374             # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> @{[Char::Ecyrillic::MATCH()]}
4375             elsif ($string =~ /\G ( \$& | \$\{&\} | \$ \s* MATCH \b | \$ \s* \{ \s* MATCH \s* \} | \$ \s* \{\^MATCH\} ) /oxmsgc) {
4376 0           $e_string .= q{Char::Ecyrillic::MATCH()};
4377 0           $slash = 'div';
4378             }
4379              
4380             # $', ${'} --> $', ${'}
4381             elsif ($string =~ /\G ( \$' | \$\{'\} ) /oxmsgc) {
4382 0           $e_string .= $1;
4383 0           $slash = 'div';
4384             }
4385              
4386             # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> @{[Char::Ecyrillic::POSTMATCH()]}
4387             elsif ($string =~ /\G ( \$ \s* POSTMATCH \b | \$ \s* \{ \s* POSTMATCH \s* \} | \$ \s* \{\^POSTMATCH\} ) /oxmsgc) {
4388 0           $e_string .= q{Char::Ecyrillic::POSTMATCH()};
4389 0           $slash = 'div';
4390             }
4391              
4392             # bareword
4393             elsif ($string =~ /\G ( \{ \s* (?: tr | index | rindex | reverse ) \s* \} ) /oxmsgc) {
4394 0           $e_string .= $1;
4395 0           $slash = 'div';
4396             }
4397              
4398             # $0 --> $0
4399             elsif ($string =~ /\G ( \$ 0 ) /oxmsgc) {
4400 0           $e_string .= $1;
4401 0           $slash = 'div';
4402             }
4403             elsif ($string =~ /\G ( \$ \{ \s* 0 \s* \} ) /oxmsgc) {
4404 0           $e_string .= $1;
4405 0           $slash = 'div';
4406             }
4407              
4408             # $$ --> $$
4409             elsif ($string =~ /\G ( \$ \$ ) (?![\w\{]) /oxmsgc) {
4410 0           $e_string .= $1;
4411 0           $slash = 'div';
4412             }
4413              
4414             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
4415             # $1, $2, $3 --> $1, $2, $3 otherwise
4416             elsif ($string =~ /\G \$ ([1-9][0-9]*) /oxmsgc) {
4417 0           $e_string .= e_capture($1);
4418 0           $slash = 'div';
4419             }
4420             elsif ($string =~ /\G \$ \{ \s* ([1-9][0-9]*) \s* \} /oxmsgc) {
4421 0           $e_string .= e_capture($1);
4422 0           $slash = 'div';
4423             }
4424              
4425             # $$foo[ ... ] --> $ $foo->[ ... ]
4426             elsif ($string =~ /\G \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) ( \[ .+? \] ) /oxmsgc) {
4427 0           $e_string .= e_capture($1.'->'.$2);
4428 0           $slash = 'div';
4429             }
4430              
4431             # $$foo{ ... } --> $ $foo->{ ... }
4432             elsif ($string =~ /\G \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) ( \{ .+? \} ) /oxmsgc) {
4433 0           $e_string .= e_capture($1.'->'.$2);
4434 0           $slash = 'div';
4435             }
4436              
4437             # $$foo
4438             elsif ($string =~ /\G \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) /oxmsgc) {
4439 0           $e_string .= e_capture($1);
4440 0           $slash = 'div';
4441             }
4442              
4443             # ${ foo }
4444             elsif ($string =~ /\G \$ \s* \{ ( \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* ) \} /oxmsgc) {
4445 0           $e_string .= '${' . $1 . '}';
4446 0           $slash = 'div';
4447             }
4448              
4449             # ${ ... }
4450             elsif ($string =~ /\G \$ \s* \{ \s* ( $qq_brace ) \s* \} /oxmsgc) {
4451 0           $e_string .= e_capture($1);
4452 0           $slash = 'div';
4453             }
4454              
4455             # variable or function
4456             # $ @ % & * $ #
4457             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) {
4458 0           $e_string .= $1;
4459 0           $slash = 'div';
4460             }
4461             # $ $ $ $ $ $ $ $ $ $ $ $ $ $
4462             # $ @ # \ ' " / ? ( ) [ ] < >
4463             elsif ($string =~ /\G ( \$[\$\@\#\\\'\"\/\?\(\)\[\]\<\>] ) /oxmsgc) {
4464 0           $e_string .= $1;
4465 0           $slash = 'div';
4466             }
4467              
4468             # subroutines of package Char::Ecyrillic
4469 0           elsif ($string =~ /\G \b (CORE:: | ->[ ]* (?: atan2 | [a-z]{2,})) \b /oxgc) { $e_string .= $1; $slash = 'm//'; }
  0            
4470 0           elsif ($string =~ /\G \b Char::Cyrillic::eval (?= \s* \{ ) /oxgc) { $e_string .= 'eval'; $slash = 'm//'; }
  0            
4471 0           elsif ($string =~ /\G \b Char::Cyrillic::eval \b /oxgc) { $e_string .= 'eval Char::Cyrillic::escape'; $slash = 'm//'; }
  0            
4472 0           elsif ($string =~ /\G \b bytes::substr \b /oxgc) { $e_string .= 'substr'; $slash = 'm//'; }
  0            
4473 0           elsif ($string =~ /\G \b chop \b /oxgc) { $e_string .= 'Char::Ecyrillic::chop'; $slash = 'm//'; }
  0            
4474 0           elsif ($string =~ /\G \b bytes::index \b /oxgc) { $e_string .= 'index'; $slash = 'm//'; }
  0            
4475 0           elsif ($string =~ /\G \b Char::Cyrillic::index \b /oxgc) { $e_string .= 'Char::Cyrillic::index'; $slash = 'm//'; }
  0            
4476 0           elsif ($string =~ /\G \b index \b /oxgc) { $e_string .= 'Char::Ecyrillic::index'; $slash = 'm//'; }
  0            
4477 0           elsif ($string =~ /\G \b bytes::rindex \b /oxgc) { $e_string .= 'rindex'; $slash = 'm//'; }
  0            
4478 0           elsif ($string =~ /\G \b Char::Cyrillic::rindex \b /oxgc) { $e_string .= 'Char::Cyrillic::rindex'; $slash = 'm//'; }
  0            
4479 0           elsif ($string =~ /\G \b rindex \b /oxgc) { $e_string .= 'Char::Ecyrillic::rindex'; $slash = 'm//'; }
  0            
4480 0           elsif ($string =~ /\G \b lc (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Char::Ecyrillic::lc'; $slash = 'm//'; }
  0            
4481 0           elsif ($string =~ /\G \b lcfirst (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Char::Ecyrillic::lcfirst'; $slash = 'm//'; }
  0            
4482 0           elsif ($string =~ /\G \b uc (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Char::Ecyrillic::uc'; $slash = 'm//'; }
  0            
4483 0           elsif ($string =~ /\G \b ucfirst (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Char::Ecyrillic::ucfirst'; $slash = 'm//'; }
  0            
4484 0           elsif ($string =~ /\G \b fc (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Char::Ecyrillic::fc'; $slash = 'm//'; }
  0            
4485              
4486             # "-s '' ..." means file test "-s 'filename' ..." (not means "- s/// ...")
4487 0           elsif ($string =~ /\G -s \s+ \s* (\") ((?:$qq_char)+?) (\") /oxgc) { $e_string .= '-s ' . e_qq('', $1,$3,$2); $slash = 'm//'; }
  0            
4488 0           elsif ($string =~ /\G -s \s+ qq \s* (\#) ((?:$qq_char)+?) (\#) /oxgc) { $e_string .= '-s ' . e_qq('qq',$1,$3,$2); $slash = 'm//'; }
  0            
4489 0           elsif ($string =~ /\G -s \s+ qq \s* (\() ((?:$qq_paren)+?) (\)) /oxgc) { $e_string .= '-s ' . e_qq('qq',$1,$3,$2); $slash = 'm//'; }
  0            
4490 0           elsif ($string =~ /\G -s \s+ qq \s* (\{) ((?:$qq_brace)+?) (\}) /oxgc) { $e_string .= '-s ' . e_qq('qq',$1,$3,$2); $slash = 'm//'; }
  0            
4491 0           elsif ($string =~ /\G -s \s+ qq \s* (\[) ((?:$qq_bracket)+?) (\]) /oxgc) { $e_string .= '-s ' . e_qq('qq',$1,$3,$2); $slash = 'm//'; }
  0            
4492 0           elsif ($string =~ /\G -s \s+ qq \s* (\<) ((?:$qq_angle)+?) (\>) /oxgc) { $e_string .= '-s ' . e_qq('qq',$1,$3,$2); $slash = 'm//'; }
  0            
4493 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            
4494              
4495 0           elsif ($string =~ /\G -s \s+ \s* (\') ((?:\\\'|\\\\|$q_char)+?) (\') /oxgc) { $e_string .= '-s ' . e_q ('', $1,$3,$2); $slash = 'm//'; }
  0            
4496 0           elsif ($string =~ /\G -s \s+ q \s* (\#) ((?:\\\#|\\\\|$q_char)+?) (\#) /oxgc) { $e_string .= '-s ' . e_q ('q', $1,$3,$2); $slash = 'm//'; }
  0            
4497 0           elsif ($string =~ /\G -s \s+ q \s* (\() ((?:\\\)|\\\\|$q_paren)+?) (\)) /oxgc) { $e_string .= '-s ' . e_q ('q', $1,$3,$2); $slash = 'm//'; }
  0            
4498 0           elsif ($string =~ /\G -s \s+ q \s* (\{) ((?:\\\}|\\\\|$q_brace)+?) (\}) /oxgc) { $e_string .= '-s ' . e_q ('q', $1,$3,$2); $slash = 'm//'; }
  0            
4499 0           elsif ($string =~ /\G -s \s+ q \s* (\[) ((?:\\\]|\\\\|$q_bracket)+?) (\]) /oxgc) { $e_string .= '-s ' . e_q ('q', $1,$3,$2); $slash = 'm//'; }
  0            
4500 0           elsif ($string =~ /\G -s \s+ q \s* (\<) ((?:\\\>|\\\\|$q_angle)+?) (\>) /oxgc) { $e_string .= '-s ' . e_q ('q', $1,$3,$2); $slash = 'm//'; }
  0            
4501 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            
4502              
4503             elsif ($string =~ /\G -s \s* (\$ \w+(?: ::\w+)* (?: (?: ->)? (?: [\$\@\%\&\*]\* | \$\#\* | \( (?:$qq_paren)*? \) | [\@\%\*]? \{ (?:$qq_brace)+? \} | [\@\%]? \[ (?:$qq_bracket)+? \] ) )*) /oxgc)
4504 0           { $e_string .= "-s $1"; $slash = 'm//'; }
  0            
4505 0           elsif ($string =~ /\G -s \s* \( ((?:$qq_paren)*?) \) /oxgc) { $e_string .= "-s ($1)"; $slash = 'm//'; }
  0            
4506 0           elsif ($string =~ /\G -s (?= \s+ [a-z]+) /oxgc) { $e_string .= '-s'; $slash = 'm//'; }
  0            
4507 0           elsif ($string =~ /\G -s \s+ (\w+) /oxgc) { $e_string .= "-s $1"; $slash = 'm//'; }
  0            
4508              
4509 0           elsif ($string =~ /\G \b bytes::length (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'length'; $slash = 'm//'; }
  0            
4510 0           elsif ($string =~ /\G \b bytes::chr (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'chr'; $slash = 'm//'; }
  0            
4511 0           elsif ($string =~ /\G \b chr (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Char::Ecyrillic::chr'; $slash = 'm//'; }
  0            
4512 0           elsif ($string =~ /\G \b bytes::ord (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'ord'; $slash = 'div'; }
  0            
4513 0           elsif ($string =~ /\G \b ord (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $e_string .= $function_ord; $slash = 'div'; }
  0            
4514 0           elsif ($string =~ /\G \b glob (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Char::Ecyrillic::glob'; $slash = 'm//'; }
  0            
4515 0           elsif ($string =~ /\G \b lc \b /oxgc) { $e_string .= 'Char::Ecyrillic::lc_'; $slash = 'm//'; }
  0            
4516 0           elsif ($string =~ /\G \b lcfirst \b /oxgc) { $e_string .= 'Char::Ecyrillic::lcfirst_'; $slash = 'm//'; }
  0            
4517 0           elsif ($string =~ /\G \b uc \b /oxgc) { $e_string .= 'Char::Ecyrillic::uc_'; $slash = 'm//'; }
  0            
4518 0           elsif ($string =~ /\G \b ucfirst \b /oxgc) { $e_string .= 'Char::Ecyrillic::ucfirst_'; $slash = 'm//'; }
  0            
4519 0           elsif ($string =~ /\G \b fc \b /oxgc) { $e_string .= 'Char::Ecyrillic::fc_'; $slash = 'm//'; }
  0            
4520 0           elsif ($string =~ /\G -s \b /oxgc) { $e_string .= '-s '; $slash = 'm//'; }
  0            
4521              
4522 0           elsif ($string =~ /\G \b bytes::length \b /oxgc) { $e_string .= 'length'; $slash = 'm//'; }
  0            
4523 0           elsif ($string =~ /\G \b bytes::chr \b /oxgc) { $e_string .= 'chr'; $slash = 'm//'; }
  0            
4524 0           elsif ($string =~ /\G \b chr \b /oxgc) { $e_string .= 'Char::Ecyrillic::chr_'; $slash = 'm//'; }
  0            
4525 0           elsif ($string =~ /\G \b bytes::ord \b /oxgc) { $e_string .= 'ord'; $slash = 'div'; }
  0            
4526 0           elsif ($string =~ /\G \b ord \b /oxgc) { $e_string .= $function_ord_; $slash = 'div'; }
  0            
4527 0           elsif ($string =~ /\G \b glob \b /oxgc) { $e_string .= 'Char::Ecyrillic::glob_'; $slash = 'm//'; }
  0            
4528 0           elsif ($string =~ /\G \b reverse \b /oxgc) { $e_string .= $function_reverse; $slash = 'm//'; }
  0            
4529 0           elsif ($string =~ /\G \b getc \b /oxgc) { $e_string .= $function_getc; $slash = 'm//'; }
  0            
4530             # split
4531             elsif ($string =~ /\G \b (split) \b (?! \s* => ) /oxgc) {
4532 0           $slash = 'm//';
4533              
4534 0           my $e = '';
4535 0           while ($string =~ /\G ( \s+ | \( | \#.* ) /oxgc) {
4536 0           $e .= $1;
4537             }
4538              
4539             # end of split
4540 0 0         if ($string =~ /\G (?= [,;\)\}\]] ) /oxgc) { return 'Char::Ecyrillic::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          
4541              
4542             # split scalar value
4543 0           elsif ($string =~ /\G ( [\$\@\&\*] $qq_scalar ) /oxgc) { $e_string .= 'Char::Ecyrillic::split' . $e . e_string($1); next E_STRING_LOOP; }
  0            
4544              
4545             # split literal space
4546 0           elsif ($string =~ /\G \b qq (\#) [ ] (\#) /oxgc) { $e_string .= 'Char::Ecyrillic::split' . $e . qq {qq$1 $2}; next E_STRING_LOOP; }
  0            
4547 0           elsif ($string =~ /\G \b qq (\s*) (\() [ ] (\)) /oxgc) { $e_string .= 'Char::Ecyrillic::split' . $e . qq{$1qq$2 $3}; next E_STRING_LOOP; }
  0            
4548 0           elsif ($string =~ /\G \b qq (\s*) (\{) [ ] (\}) /oxgc) { $e_string .= 'Char::Ecyrillic::split' . $e . qq{$1qq$2 $3}; next E_STRING_LOOP; }
  0            
4549 0           elsif ($string =~ /\G \b qq (\s*) (\[) [ ] (\]) /oxgc) { $e_string .= 'Char::Ecyrillic::split' . $e . qq{$1qq$2 $3}; next E_STRING_LOOP; }
  0            
4550 0           elsif ($string =~ /\G \b qq (\s*) (\<) [ ] (\>) /oxgc) { $e_string .= 'Char::Ecyrillic::split' . $e . qq{$1qq$2 $3}; next E_STRING_LOOP; }
  0            
4551 0           elsif ($string =~ /\G \b qq (\s*) (\S) [ ] (\2) /oxgc) { $e_string .= 'Char::Ecyrillic::split' . $e . qq{$1qq$2 $3}; next E_STRING_LOOP; }
  0            
4552 0           elsif ($string =~ /\G \b q (\#) [ ] (\#) /oxgc) { $e_string .= 'Char::Ecyrillic::split' . $e . qq {q$1 $2}; next E_STRING_LOOP; }
  0            
4553 0           elsif ($string =~ /\G \b q (\s*) (\() [ ] (\)) /oxgc) { $e_string .= 'Char::Ecyrillic::split' . $e . qq {$1q$2 $3}; next E_STRING_LOOP; }
  0            
4554 0           elsif ($string =~ /\G \b q (\s*) (\{) [ ] (\}) /oxgc) { $e_string .= 'Char::Ecyrillic::split' . $e . qq {$1q$2 $3}; next E_STRING_LOOP; }
  0            
4555 0           elsif ($string =~ /\G \b q (\s*) (\[) [ ] (\]) /oxgc) { $e_string .= 'Char::Ecyrillic::split' . $e . qq {$1q$2 $3}; next E_STRING_LOOP; }
  0            
4556 0           elsif ($string =~ /\G \b q (\s*) (\<) [ ] (\>) /oxgc) { $e_string .= 'Char::Ecyrillic::split' . $e . qq {$1q$2 $3}; next E_STRING_LOOP; }
  0            
4557 0           elsif ($string =~ /\G \b q (\s*) (\S) [ ] (\2) /oxgc) { $e_string .= 'Char::Ecyrillic::split' . $e . qq {$1q$2 $3}; next E_STRING_LOOP; }
  0            
4558 0           elsif ($string =~ /\G ' [ ] ' /oxgc) { $e_string .= 'Char::Ecyrillic::split' . $e . qq {' '}; next E_STRING_LOOP; }
  0            
4559 0           elsif ($string =~ /\G " [ ] " /oxgc) { $e_string .= 'Char::Ecyrillic::split' . $e . qq {" "}; next E_STRING_LOOP; }
  0            
4560              
4561             # split qq//
4562             elsif ($string =~ /\G \b (qq) \b /oxgc) {
4563 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            
4564             else {
4565 0           while ($string !~ /\G \z/oxgc) {
4566 0 0         if ($string =~ /\G (\s+|\#.*) /oxgc) { $e_string .= $e . $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
4567 0           elsif ($string =~ /\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { $e_string .= e_split($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # qq ( ) --> qr ( )
  0            
4568 0           elsif ($string =~ /\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { $e_string .= e_split($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # qq { } --> qr { }
  0            
4569 0           elsif ($string =~ /\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { $e_string .= e_split($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # qq [ ] --> qr [ ]
  0            
4570 0           elsif ($string =~ /\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { $e_string .= e_split($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # qq < > --> qr < >
  0            
4571 0           elsif ($string =~ /\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) /oxgc) { $e_string .= e_split($e.'qr','{','}',$2,''); next E_STRING_LOOP; } # qq | | --> qr { }
  0            
4572 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            
4573             }
4574 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
4575             }
4576             }
4577              
4578             # split qr//
4579             elsif ($string =~ /\G \b (qr) \b /oxgc) {
4580 0 0         if ($string =~ /\G (\#) ((?:$qq_char)*?) (\#) ([imosxpadlubB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1,$3,$2,$4); next E_STRING_LOOP; } # qr# #
  0            
  0            
4581             else {
4582 0           while ($string !~ /\G \z/oxgc) {
4583 0 0         if ($string =~ /\G (\s+|\#.*) /oxgc) { $e_string .= $e . $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
4584 0           elsif ($string =~ /\G (\() ((?:$qq_paren)*?) (\)) ([imosxpadlubB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # qr ( )
  0            
4585 0           elsif ($string =~ /\G (\{) ((?:$qq_brace)*?) (\}) ([imosxpadlubB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # qr { }
  0            
4586 0           elsif ($string =~ /\G (\[) ((?:$qq_bracket)*?) (\]) ([imosxpadlubB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # qr [ ]
  0            
4587 0           elsif ($string =~ /\G (\<) ((?:$qq_angle)*?) (\>) ([imosxpadlubB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # qr < >
  0            
4588 0           elsif ($string =~ /\G (\') ((?:$qq_char)*?) (\') ([imosxpadlubB]*) /oxgc) { $e_string .= e_split_q($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # qr ' '
  0            
4589 0           elsif ($string =~ /\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ([imosxpadlubB]*) /oxgc) { $e_string .= e_split ($e.'qr','{','}',$2,$4); next E_STRING_LOOP; } # qr | | --> qr { }
  0            
4590 0           elsif ($string =~ /\G (\S) ((?:$qq_char)*?) (\1) ([imosxpadlubB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # qr * *
  0            
4591             }
4592 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
4593             }
4594             }
4595              
4596             # split q//
4597             elsif ($string =~ /\G \b (q) \b /oxgc) {
4598 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            
4599             else {
4600 0           while ($string !~ /\G \z/oxgc) {
4601 0 0         if ($string =~ /\G (\s+|\#.*) /oxgc) { $e_string .= $e . $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
4602 0           elsif ($string =~ /\G (\() ((?:\\\\|\\\)|\\\(|$q_paren)*?) (\)) /oxgc) { $e_string .= e_split_q($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # q ( ) --> qr ( )
  0            
4603 0           elsif ($string =~ /\G (\{) ((?:\\\\|\\\}|\\\{|$q_brace)*?) (\}) /oxgc) { $e_string .= e_split_q($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # q { } --> qr { }
  0            
4604 0           elsif ($string =~ /\G (\[) ((?:\\\\|\\\]|\\\[|$q_bracket)*?) (\]) /oxgc) { $e_string .= e_split_q($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # q [ ] --> qr [ ]
  0            
4605 0           elsif ($string =~ /\G (\<) ((?:\\\\|\\\>|\\\<|$q_angle)*?) (\>) /oxgc) { $e_string .= e_split_q($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # q < > --> qr < >
  0            
4606 0           elsif ($string =~ /\G ([*\-:?\\^|]) ((?:$q_char)*?) (\1) /oxgc) { $e_string .= e_split_q($e.'qr','{','}',$2,''); next E_STRING_LOOP; } # q | | --> qr { }
  0            
4607 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            
4608             }
4609 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
4610             }
4611             }
4612              
4613             # split m//
4614             elsif ($string =~ /\G \b (m) \b /oxgc) {
4615 0 0         if ($string =~ /\G (\#) ((?:$qq_char)*?) (\#) ([cgimosxpadlubB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1,$3,$2,$4); next E_STRING_LOOP; } # m# # --> qr # #
  0            
  0            
4616             else {
4617 0           while ($string !~ /\G \z/oxgc) {
4618 0 0         if ($string =~ /\G (\s+|\#.*) /oxgc) { $e_string .= $e . $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
4619 0           elsif ($string =~ /\G (\() ((?:$qq_paren)*?) (\)) ([cgimosxpadlubB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # m ( ) --> qr ( )
  0            
4620 0           elsif ($string =~ /\G (\{) ((?:$qq_brace)*?) (\}) ([cgimosxpadlubB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # m { } --> qr { }
  0            
4621 0           elsif ($string =~ /\G (\[) ((?:$qq_bracket)*?) (\]) ([cgimosxpadlubB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # m [ ] --> qr [ ]
  0            
4622 0           elsif ($string =~ /\G (\<) ((?:$qq_angle)*?) (\>) ([cgimosxpadlubB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # m < > --> qr < >
  0            
4623 0           elsif ($string =~ /\G (\') ((?:$qq_char)*?) (\') ([cgimosxpadlubB]*) /oxgc) { $e_string .= e_split_q($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # m ' ' --> qr ' '
  0            
4624 0           elsif ($string =~ /\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ([cgimosxpadlubB]*) /oxgc) { $e_string .= e_split ($e.'qr','{','}',$2,$4); next E_STRING_LOOP; } # m | | --> qr { }
  0            
4625 0           elsif ($string =~ /\G (\S) ((?:$qq_char)*?) (\1) ([cgimosxpadlubB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # m * * --> qr * *
  0            
4626             }
4627 0           die __FILE__, ": Search pattern not terminated";
4628             }
4629             }
4630              
4631             # split ''
4632             elsif ($string =~ /\G (\') /oxgc) {
4633 0           my $q_string = '';
4634 0           while ($string !~ /\G \z/oxgc) {
4635 0 0         if ($string =~ /\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0          
    0          
    0          
4636 0           elsif ($string =~ /\G (\\\') /oxgc) { $q_string .= $1; } # splitqr'' --> split qr''
4637 0           elsif ($string =~ /\G \' /oxgc) { $e_string .= e_split_q($e.q{ qr},"'","'",$q_string,''); next E_STRING_LOOP; } # ' ' --> qr ' '
  0            
4638 0           elsif ($string =~ /\G ($q_char) /oxgc) { $q_string .= $1; }
4639             }
4640 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
4641             }
4642              
4643             # split ""
4644             elsif ($string =~ /\G (\") /oxgc) {
4645 0           my $qq_string = '';
4646 0           while ($string !~ /\G \z/oxgc) {
4647 0 0         if ($string =~ /\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0          
    0          
    0          
4648 0           elsif ($string =~ /\G (\\\") /oxgc) { $qq_string .= $1; } # splitqr"" --> split qr""
4649 0           elsif ($string =~ /\G \" /oxgc) { $e_string .= e_split($e.q{ qr},'"','"',$qq_string,''); next E_STRING_LOOP; } # " " --> qr " "
  0            
4650 0           elsif ($string =~ /\G ($q_char) /oxgc) { $qq_string .= $1; }
4651             }
4652 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
4653             }
4654              
4655             # split //
4656             elsif ($string =~ /\G (\/) /oxgc) {
4657 0           my $regexp = '';
4658 0           while ($string !~ /\G \z/oxgc) {
4659 0 0         if ($string =~ /\G (\\\\) /oxgc) { $regexp .= $1; }
  0 0          
    0          
    0          
4660 0           elsif ($string =~ /\G (\\\/) /oxgc) { $regexp .= $1; } # splitqr// --> split qr//
4661 0           elsif ($string =~ /\G \/ ([cgimosxpadlubB]*) /oxgc) { $e_string .= e_split($e.q{ qr}, '/','/',$regexp,$1); next E_STRING_LOOP; } # / / --> qr / /
  0            
4662 0           elsif ($string =~ /\G ($q_char) /oxgc) { $regexp .= $1; }
4663             }
4664 0           die __FILE__, ": Search pattern not terminated";
4665             }
4666             }
4667              
4668             # qq//
4669             elsif ($string =~ /\G \b (qq) \b /oxgc) {
4670 0           my $ope = $1;
4671 0 0         if ($string =~ /\G (\#) ((?:$qq_char)*?) (\#) /oxgc) { # qq# #
4672 0           $e_string .= e_qq($ope,$1,$3,$2);
4673             }
4674             else {
4675 0           my $e = '';
4676 0           while ($string !~ /\G \z/oxgc) {
4677 0 0         if ($string =~ /\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
4678 0           elsif ($string =~ /\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qq ( )
  0            
4679 0           elsif ($string =~ /\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qq { }
  0            
4680 0           elsif ($string =~ /\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qq [ ]
  0            
4681 0           elsif ($string =~ /\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qq < >
  0            
4682 0           elsif ($string =~ /\G (\S) ((?:$qq_char)*?) (\1) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qq * *
  0            
4683             }
4684 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
4685             }
4686             }
4687              
4688             # qx//
4689             elsif ($string =~ /\G \b (qx) \b /oxgc) {
4690 0           my $ope = $1;
4691 0 0         if ($string =~ /\G (\#) ((?:$qq_char)*?) (\#) /oxgc) { # qx# #
4692 0           $e_string .= e_qq($ope,$1,$3,$2);
4693             }
4694             else {
4695 0           my $e = '';
4696 0           while ($string !~ /\G \z/oxgc) {
4697 0 0         if ($string =~ /\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
4698 0           elsif ($string =~ /\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qx ( )
  0            
4699 0           elsif ($string =~ /\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qx { }
  0            
4700 0           elsif ($string =~ /\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qx [ ]
  0            
4701 0           elsif ($string =~ /\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qx < >
  0            
4702 0           elsif ($string =~ /\G (\') ((?:$qq_char)*?) (\') /oxgc) { $e_string .= $e . e_q ($ope,$1,$3,$2); next E_STRING_LOOP; } # qx ' '
  0            
4703 0           elsif ($string =~ /\G (\S) ((?:$qq_char)*?) (\1) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qx * *
  0            
4704             }
4705 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
4706             }
4707             }
4708              
4709             # q//
4710             elsif ($string =~ /\G \b (q) \b /oxgc) {
4711 0           my $ope = $1;
4712 0 0         if ($string =~ /\G (\#) ((?:\\\#|\\\\|$q_char)*?) (\#) /oxgc) { # q# #
4713 0           $e_string .= e_q($ope,$1,$3,$2);
4714             }
4715             else {
4716 0           my $e = '';
4717 0           while ($string !~ /\G \z/oxgc) {
4718 0 0         if ($string =~ /\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
4719 0           elsif ($string =~ /\G (\() ((?:\\\\|\\\)|\\\(|$q_paren)*?) (\)) /oxgc) { $e_string .= $e . e_q($ope,$1,$3,$2); next E_STRING_LOOP; } # q ( )
  0            
4720 0           elsif ($string =~ /\G (\{) ((?:\\\\|\\\}|\\\{|$q_brace)*?) (\}) /oxgc) { $e_string .= $e . e_q($ope,$1,$3,$2); next E_STRING_LOOP; } # q { }
  0            
4721 0           elsif ($string =~ /\G (\[) ((?:\\\\|\\\]|\\\[|$q_bracket)*?) (\]) /oxgc) { $e_string .= $e . e_q($ope,$1,$3,$2); next E_STRING_LOOP; } # q [ ]
  0            
4722 0           elsif ($string =~ /\G (\<) ((?:\\\\|\\\>|\\\<|$q_angle)*?) (\>) /oxgc) { $e_string .= $e . e_q($ope,$1,$3,$2); next E_STRING_LOOP; } # q < >
  0            
4723 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            
4724             }
4725 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
4726             }
4727             }
4728              
4729             # ''
4730 0           elsif ($string =~ /\G (?
4731              
4732             # ""
4733 0           elsif ($string =~ /\G (\") ((?:$qq_char)*?) (\") /oxgc) { $e_string .= e_qq('',$1,$3,$2); }
4734              
4735             # ``
4736 0           elsif ($string =~ /\G (\`) ((?:$qq_char)*?) (\`) /oxgc) { $e_string .= e_qq('',$1,$3,$2); }
4737              
4738             # <<= <=> <= < operator
4739             elsif ($string =~ /\G ( <<= | <=> | <= | < ) (?= \s* [A-Za-z_0-9'"`\$\@\&\*\(\+\-] )/oxgc)
4740 0           { $e_string .= $1; }
4741              
4742             #
4743 0           elsif ($string =~ /\G (<[\$]?[A-Za-z_][A-Za-z_0-9]*>) /oxgc) { $e_string .= $1; }
4744              
4745             # --- glob
4746             elsif ($string =~ /\G < ((?:$q_char)+?) > /oxgc) {
4747 0           $e_string .= 'Char::Ecyrillic::glob("' . $1 . '")';
4748             }
4749              
4750             # << (bit shift) --- not here document
4751 0           elsif ($string =~ /\G ( << \s* ) (?= [0-9\$\@\&] ) /oxgc) { $slash = 'm//'; $e_string .= $1; }
  0            
4752              
4753             # <<'HEREDOC'
4754             elsif ($string =~ /\G ( << '([a-zA-Z_0-9]*)' ) /oxgc) {
4755 0           $slash = 'm//';
4756 0           my $here_quote = $1;
4757 0           my $delimiter = $2;
4758              
4759             # get here document
4760 0 0         if ($here_script eq '') {
4761 0           $here_script = CORE::substr $_, pos $_;
4762 0           $here_script =~ s/.*?\n//oxm;
4763             }
4764 0 0         if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4765 0           push @heredoc, $1 . qq{\n$delimiter\n};
4766 0           push @heredoc_delimiter, $delimiter;
4767             }
4768             else {
4769 0           die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF";
4770             }
4771 0           $e_string .= $here_quote;
4772             }
4773              
4774             # <<\HEREDOC
4775             elsif ($string =~ /\G ( << \\([a-zA-Z_0-9]+) ) /oxgc) {
4776 0           $slash = 'm//';
4777 0           my $here_quote = $1;
4778 0           my $delimiter = $2;
4779              
4780             # get here document
4781 0 0         if ($here_script eq '') {
4782 0           $here_script = CORE::substr $_, pos $_;
4783 0           $here_script =~ s/.*?\n//oxm;
4784             }
4785 0 0         if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4786 0           push @heredoc, $1 . qq{\n$delimiter\n};
4787 0           push @heredoc_delimiter, $delimiter;
4788             }
4789             else {
4790 0           die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF";
4791             }
4792 0           $e_string .= $here_quote;
4793             }
4794              
4795             # <<"HEREDOC"
4796             elsif ($string =~ /\G ( << "([a-zA-Z_0-9]*)" ) /oxgc) {
4797 0           $slash = 'm//';
4798 0           my $here_quote = $1;
4799 0           my $delimiter = $2;
4800              
4801             # get here document
4802 0 0         if ($here_script eq '') {
4803 0           $here_script = CORE::substr $_, pos $_;
4804 0           $here_script =~ s/.*?\n//oxm;
4805             }
4806 0 0         if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4807 0           push @heredoc, e_heredoc($1) . qq{\n$delimiter\n};
4808 0           push @heredoc_delimiter, $delimiter;
4809             }
4810             else {
4811 0           die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF";
4812             }
4813 0           $e_string .= $here_quote;
4814             }
4815              
4816             # <
4817             elsif ($string =~ /\G ( << ([a-zA-Z_0-9]+) ) /oxgc) {
4818 0           $slash = 'm//';
4819 0           my $here_quote = $1;
4820 0           my $delimiter = $2;
4821              
4822             # get here document
4823 0 0         if ($here_script eq '') {
4824 0           $here_script = CORE::substr $_, pos $_;
4825 0           $here_script =~ s/.*?\n//oxm;
4826             }
4827 0 0         if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4828 0           push @heredoc, e_heredoc($1) . qq{\n$delimiter\n};
4829 0           push @heredoc_delimiter, $delimiter;
4830             }
4831             else {
4832 0           die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF";
4833             }
4834 0           $e_string .= $here_quote;
4835             }
4836              
4837             # <<`HEREDOC`
4838             elsif ($string =~ /\G ( << `([a-zA-Z_0-9]*)` ) /oxgc) {
4839 0           $slash = 'm//';
4840 0           my $here_quote = $1;
4841 0           my $delimiter = $2;
4842              
4843             # get here document
4844 0 0         if ($here_script eq '') {
4845 0           $here_script = CORE::substr $_, pos $_;
4846 0           $here_script =~ s/.*?\n//oxm;
4847             }
4848 0 0         if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4849 0           push @heredoc, e_heredoc($1) . qq{\n$delimiter\n};
4850 0           push @heredoc_delimiter, $delimiter;
4851             }
4852             else {
4853 0           die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF";
4854             }
4855 0           $e_string .= $here_quote;
4856             }
4857              
4858             # any operator before div
4859             elsif ($string =~ /\G (
4860             -- | \+\+ |
4861             [\)\}\]]
4862              
4863 0           ) /oxgc) { $slash = 'div'; $e_string .= $1; }
  0            
4864              
4865             # yada-yada or triple-dot operator
4866             elsif ($string =~ /\G (
4867             \.\.\.
4868              
4869 0           ) /oxgc) { $slash = 'm//'; $e_string .= q{die('Unimplemented')}; }
  0            
4870              
4871             # any operator before m//
4872             elsif ($string =~ /\G (
4873              
4874             !~~ | !~ | != | ! |
4875             %= | % |
4876             &&= | && | &= | & |
4877             -= | -> | - |
4878             :\s*= |
4879             : |
4880             <<= | <=> | <= | < |
4881             == | => | =~ | = |
4882             >>= | >> | >= | > |
4883             \*\*= | \*\* | \*= | \* |
4884             \+= | \+ |
4885             \.\. | \.= | \. |
4886             \/\/= | \/\/ |
4887             \/= | \/ |
4888             \? |
4889             \\ |
4890             \^= | \^ |
4891             \b x= |
4892             \|\|= | \|\| | \|= | \| |
4893             ~~ | ~ |
4894             \b(?: and | cmp | eq | ge | gt | le | lt | ne | not | or | xor | x )\b |
4895             \b(?: print )\b |
4896              
4897             [,;\(\{\[]
4898              
4899 0           ) /oxgc) { $slash = 'm//'; $e_string .= $1; }
  0            
4900              
4901             # other any character
4902 0           elsif ($string =~ /\G ($q_char) /oxgc) { $e_string .= $1; }
4903              
4904             # system error
4905             else {
4906 0           die __FILE__, ": Oops, this shouldn't happen!";
4907             }
4908             }
4909              
4910 0           return $e_string;
4911             }
4912              
4913             #
4914             # character class
4915             #
4916             sub character_class {
4917 0     0 0   my($char,$modifier) = @_;
4918              
4919 0 0         if ($char eq '.') {
4920 0 0         if ($modifier =~ /s/) {
4921 0           return '${Char::Ecyrillic::dot_s}';
4922             }
4923             else {
4924 0           return '${Char::Ecyrillic::dot}';
4925             }
4926             }
4927             else {
4928 0           return Char::Ecyrillic::classic_character_class($char);
4929             }
4930             }
4931              
4932             #
4933             # escape capture ($1, $2, $3, ...)
4934             #
4935             sub e_capture {
4936              
4937 0     0 0   return join '', '${', $_[0], '}';
4938             }
4939              
4940             #
4941             # escape transliteration (tr/// or y///)
4942             #
4943             sub e_tr {
4944 0     0 0   my($variable,$charclass,$e,$charclass2,$modifier) = @_;
4945 0           my $e_tr = '';
4946 0   0       $modifier ||= '';
4947              
4948 0           $slash = 'div';
4949              
4950             # quote character class 1
4951 0           $charclass = q_tr($charclass);
4952              
4953             # quote character class 2
4954 0           $charclass2 = q_tr($charclass2);
4955              
4956             # /b /B modifier
4957 0 0         if ($modifier =~ tr/bB//d) {
4958 0 0         if ($variable eq '') {
4959 0           $e_tr = qq{tr$charclass$e$charclass2$modifier};
4960             }
4961             else {
4962 0           $e_tr = qq{$variable${bind_operator}tr$charclass$e$charclass2$modifier};
4963             }
4964             }
4965             else {
4966 0 0         if ($variable eq '') {
4967 0           $e_tr = qq{Char::Ecyrillic::tr(\$_,' =~ ',$charclass,$e$charclass2,'$modifier')};
4968             }
4969             else {
4970 0           $e_tr = qq{Char::Ecyrillic::tr($variable,'$bind_operator',$charclass,$e$charclass2,'$modifier')};
4971             }
4972             }
4973              
4974             # clear tr/// variable
4975 0           $tr_variable = '';
4976 0           $bind_operator = '';
4977              
4978 0           return $e_tr;
4979             }
4980              
4981             #
4982             # quote for escape transliteration (tr/// or y///)
4983             #
4984             sub q_tr {
4985 0     0 0   my($charclass) = @_;
4986              
4987             # quote character class
4988 0 0         if ($charclass !~ /'/oxms) {
    0          
    0          
    0          
    0          
    0          
4989 0           return e_q('', "'", "'", $charclass); # --> q' '
4990             }
4991             elsif ($charclass !~ /\//oxms) {
4992 0           return e_q('q', '/', '/', $charclass); # --> q/ /
4993             }
4994             elsif ($charclass !~ /\#/oxms) {
4995 0           return e_q('q', '#', '#', $charclass); # --> q# #
4996             }
4997             elsif ($charclass !~ /[\<\>]/oxms) {
4998 0           return e_q('q', '<', '>', $charclass); # --> q< >
4999             }
5000             elsif ($charclass !~ /[\(\)]/oxms) {
5001 0           return e_q('q', '(', ')', $charclass); # --> q( )
5002             }
5003             elsif ($charclass !~ /[\{\}]/oxms) {
5004 0           return e_q('q', '{', '}', $charclass); # --> q{ }
5005             }
5006             else {
5007 0           for my $char (qw( ! " $ % & * + . : = ? @ ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
5008 0 0         if ($charclass !~ /\Q$char\E/xms) {
5009 0           return e_q('q', $char, $char, $charclass);
5010             }
5011             }
5012             }
5013              
5014 0           return e_q('q', '{', '}', $charclass);
5015             }
5016              
5017             #
5018             # escape q string (q//, '')
5019             #
5020             sub e_q {
5021 0     0 0   my($ope,$delimiter,$end_delimiter,$string) = @_;
5022              
5023 0           $slash = 'div';
5024              
5025 0           return join '', $ope, $delimiter, $string, $end_delimiter;
5026             }
5027              
5028             #
5029             # escape qq string (qq//, "", qx//, ``)
5030             #
5031             sub e_qq {
5032 0     0 0   my($ope,$delimiter,$end_delimiter,$string) = @_;
5033              
5034 0           $slash = 'div';
5035              
5036 0           my $left_e = 0;
5037 0           my $right_e = 0;
5038 0           my @char = $string =~ /\G(
5039             \\o\{ [0-7]+ \} |
5040             \\x\{ [0-9A-Fa-f]+ \} |
5041             \\N\{ [^0-9\}][^\}]* \} |
5042             \$` | \$\{`\} | \$ \s* PREMATCH | \$ \s* \{ \s* PREMATCH \s* \} | \$ \s* \{\^PREMATCH\} |
5043             \$& | \$\{&\} | \$ \s* MATCH | \$ \s* \{ \s* MATCH \s* \} | \$ \s* \{\^MATCH\} |
5044             \$ \s* POSTMATCH | \$ \s* \{ \s* POSTMATCH \s* \} | \$ \s* \{\^POSTMATCH\} |
5045             \$ \s* \d+ |
5046             \$ \s* \{ \s* \d+ \s* \} |
5047             \$ \$ (?![\w\{]) |
5048             \$ \s* \$ \s* $qq_variable |
5049             \\?(?:$q_char)
5050             )/oxmsg;
5051              
5052 0           for (my $i=0; $i <= $#char; $i++) {
5053              
5054             # "\L\u" --> "\u\L"
5055 0 0 0       if (($char[$i] eq '\L') and ($char[$i+1] eq '\u')) {
    0 0        
    0          
    0          
    0          
5056 0           @char[$i,$i+1] = @char[$i+1,$i];
5057             }
5058              
5059             # "\U\l" --> "\l\U"
5060             elsif (($char[$i] eq '\U') and ($char[$i+1] eq '\l')) {
5061 0           @char[$i,$i+1] = @char[$i+1,$i];
5062             }
5063              
5064             # octal escape sequence
5065             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
5066 0           $char[$i] = Char::Ecyrillic::octchr($1);
5067             }
5068              
5069             # hexadecimal escape sequence
5070             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
5071 0           $char[$i] = Char::Ecyrillic::hexchr($1);
5072             }
5073              
5074             # \N{CHARNAME} --> N{CHARNAME}
5075             elsif ($char[$i] =~ /\A \\ ( N\{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
5076 0           $char[$i] = $1;
5077             }
5078              
5079 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          
5080             }
5081              
5082             # \F
5083             #
5084             # P.69 Table 2-6. Translation escapes
5085             # in Chapter 2: Bits and Pieces
5086             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
5087             # (and so on)
5088              
5089             # \u \l \U \L \F \Q \E
5090 0           elsif ($char[$i] =~ /\A ([<>]) \z/oxms) {
5091 0 0         if ($right_e < $left_e) {
5092 0           $char[$i] = '\\' . $char[$i];
5093             }
5094             }
5095             elsif ($char[$i] eq '\u') {
5096              
5097             # "STRING @{[ LIST EXPR ]} MORE STRING"
5098              
5099             # P.257 Other Tricks You Can Do with Hard References
5100             # in Chapter 8: References
5101             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
5102              
5103             # P.353 Other Tricks You Can Do with Hard References
5104             # in Chapter 8: References
5105             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
5106              
5107             # (and so on)
5108              
5109 0           $char[$i] = '@{[Char::Ecyrillic::ucfirst qq<';
5110 0           $left_e++;
5111             }
5112             elsif ($char[$i] eq '\l') {
5113 0           $char[$i] = '@{[Char::Ecyrillic::lcfirst qq<';
5114 0           $left_e++;
5115             }
5116             elsif ($char[$i] eq '\U') {
5117 0           $char[$i] = '@{[Char::Ecyrillic::uc qq<';
5118 0           $left_e++;
5119             }
5120             elsif ($char[$i] eq '\L') {
5121 0           $char[$i] = '@{[Char::Ecyrillic::lc qq<';
5122 0           $left_e++;
5123             }
5124             elsif ($char[$i] eq '\F') {
5125 0           $char[$i] = '@{[Char::Ecyrillic::fc qq<';
5126 0           $left_e++;
5127             }
5128             elsif ($char[$i] eq '\Q') {
5129 0           $char[$i] = '@{[CORE::quotemeta qq<';
5130 0           $left_e++;
5131             }
5132             elsif ($char[$i] eq '\E') {
5133 0 0         if ($right_e < $left_e) {
5134 0           $char[$i] = '>]}';
5135 0           $right_e++;
5136             }
5137             else {
5138 0           $char[$i] = '';
5139             }
5140             }
5141             elsif ($char[$i] eq '\Q') {
5142 0           while (1) {
5143 0 0         if (++$i > $#char) {
5144 0           last;
5145             }
5146 0 0         if ($char[$i] eq '\E') {
5147 0           last;
5148             }
5149             }
5150             }
5151             elsif ($char[$i] eq '\E') {
5152             }
5153              
5154             # $0 --> $0
5155             elsif ($char[$i] =~ /\A \$ 0 \z/oxms) {
5156             }
5157             elsif ($char[$i] =~ /\A \$ \{ \s* 0 \s* \} \z/oxms) {
5158             }
5159              
5160             # $$ --> $$
5161             elsif ($char[$i] =~ /\A \$\$ \z/oxms) {
5162             }
5163              
5164             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
5165             # $1, $2, $3 --> $1, $2, $3 otherwise
5166             elsif ($char[$i] =~ /\A \$ ([1-9][0-9]*) \z/oxms) {
5167 0           $char[$i] = e_capture($1);
5168             }
5169             elsif ($char[$i] =~ /\A \$ \{ \s* ([1-9][0-9]*) \s* \} \z/oxms) {
5170 0           $char[$i] = e_capture($1);
5171             }
5172              
5173             # $$foo[ ... ] --> $ $foo->[ ... ]
5174             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) ( \[ (?:$qq_bracket)*? \] ) \z/oxms) {
5175 0           $char[$i] = e_capture($1.'->'.$2);
5176             }
5177              
5178             # $$foo{ ... } --> $ $foo->{ ... }
5179             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) ( \{ (?:$qq_brace)*? \} ) \z/oxms) {
5180 0           $char[$i] = e_capture($1.'->'.$2);
5181             }
5182              
5183             # $$foo
5184             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) \z/oxms) {
5185 0           $char[$i] = e_capture($1);
5186             }
5187              
5188             # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Char::Ecyrillic::PREMATCH()
5189             elsif ($char[$i] =~ /\A ( \$` | \$\{`\} | \$ \s* PREMATCH | \$ \s* \{ \s* PREMATCH \s* \} | \$ \s* \{\^PREMATCH\} ) \z/oxmsgc) {
5190 0           $char[$i] = '@{[Char::Ecyrillic::PREMATCH()]}';
5191             }
5192              
5193             # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Char::Ecyrillic::MATCH()
5194             elsif ($char[$i] =~ /\A ( \$& | \$\{&\} | \$ \s* MATCH | \$ \s* \{ \s* MATCH \s* \} | \$ \s* \{\^MATCH\} ) \z/oxmsgc) {
5195 0           $char[$i] = '@{[Char::Ecyrillic::MATCH()]}';
5196             }
5197              
5198             # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Char::Ecyrillic::POSTMATCH()
5199             elsif ($char[$i] =~ /\A ( \$ \s* POSTMATCH | \$ \s* \{ \s* POSTMATCH \s* \} | \$ \s* \{\^POSTMATCH\} ) \z/oxmsgc) {
5200 0           $char[$i] = '@{[Char::Ecyrillic::POSTMATCH()]}';
5201             }
5202              
5203             # ${ foo } --> ${ foo }
5204             elsif ($char[$i] =~ /\A \$ \s* \{ \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* \} \z/oxms) {
5205             }
5206              
5207             # ${ ... }
5208             elsif ($char[$i] =~ /\A \$ \s* \{ \s* ( .+ ) \s* \} \z/oxms) {
5209 0           $char[$i] = e_capture($1);
5210             }
5211             }
5212              
5213             # return string
5214 0 0         if ($left_e > $right_e) {
5215 0           return join '', $ope, $delimiter, @char, '>]}' x ($left_e - $right_e), $end_delimiter;
5216             }
5217 0           return join '', $ope, $delimiter, @char, $end_delimiter;
5218             }
5219              
5220             #
5221             # escape qw string (qw//)
5222             #
5223             sub e_qw {
5224 0     0 0   my($ope,$delimiter,$end_delimiter,$string) = @_;
5225              
5226 0           $slash = 'div';
5227              
5228             # choice again delimiter
5229 0           my %octet = map {$_ => 1} ($string =~ /\G ([\x00-\xFF]) /oxmsg);
  0            
5230 0 0         if (not $octet{$end_delimiter}) {
    0          
    0          
    0          
    0          
5231 0           return join '', $ope, $delimiter, $string, $end_delimiter;
5232             }
5233             elsif (not $octet{')'}) {
5234 0           return join '', $ope, '(', $string, ')';
5235             }
5236             elsif (not $octet{'}'}) {
5237 0           return join '', $ope, '{', $string, '}';
5238             }
5239             elsif (not $octet{']'}) {
5240 0           return join '', $ope, '[', $string, ']';
5241             }
5242             elsif (not $octet{'>'}) {
5243 0           return join '', $ope, '<', $string, '>';
5244             }
5245             else {
5246 0           for my $char (qw( ! " $ % & * + - . / : = ? @ ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
5247 0 0         if (not $octet{$char}) {
5248 0           return join '', $ope, $char, $string, $char;
5249             }
5250             }
5251             }
5252              
5253             # qw/AAA BBB C'CC/ --> ('AAA', 'BBB', 'C\'CC')
5254 0           my @string = CORE::split(/\s+/, $string);
5255 0           for my $string (@string) {
5256 0           my @octet = $string =~ /\G ([\x00-\xFF]) /oxmsg;
5257 0           for my $octet (@octet) {
5258 0 0         if ($octet =~ /\A (['\\]) \z/oxms) {
5259 0           $octet = '\\' . $1;
5260             }
5261             }
5262 0           $string = join '', @octet;
5263             }
5264 0           return join '', '(', (join ', ', map { "'$_'" } @string), ')';
  0            
5265             }
5266              
5267             #
5268             # escape here document (<<"HEREDOC", <
5269             #
5270             sub e_heredoc {
5271 0     0 0   my($string) = @_;
5272              
5273 0           $slash = 'm//';
5274              
5275 0           my $metachar = qr/[\@\\|]/oxms; # '|' is for <<`HEREDOC`
5276              
5277 0           my $left_e = 0;
5278 0           my $right_e = 0;
5279 0           my @char = $string =~ /\G(
5280             \\o\{ [0-7]+ \} |
5281             \\x\{ [0-9A-Fa-f]+ \} |
5282             \\N\{ [^0-9\}][^\}]* \} |
5283             \$` | \$\{`\} | \$ \s* PREMATCH | \$ \s* \{ \s* PREMATCH \s* \} | \$ \s* \{\^PREMATCH\} |
5284             \$& | \$\{&\} | \$ \s* MATCH | \$ \s* \{ \s* MATCH \s* \} | \$ \s* \{\^MATCH\} |
5285             \$ \s* POSTMATCH | \$ \s* \{ \s* POSTMATCH \s* \} | \$ \s* \{\^POSTMATCH\} |
5286             \$ \s* \d+ |
5287             \$ \s* \{ \s* \d+ \s* \} |
5288             \$ \$ (?![\w\{]) |
5289             \$ \s* \$ \s* $qq_variable |
5290             \\?(?:$q_char)
5291             )/oxmsg;
5292              
5293 0           for (my $i=0; $i <= $#char; $i++) {
5294              
5295             # "\L\u" --> "\u\L"
5296 0 0 0       if (($char[$i] eq '\L') and ($char[$i+1] eq '\u')) {
    0 0        
    0          
    0          
    0          
5297 0           @char[$i,$i+1] = @char[$i+1,$i];
5298             }
5299              
5300             # "\U\l" --> "\l\U"
5301             elsif (($char[$i] eq '\U') and ($char[$i+1] eq '\l')) {
5302 0           @char[$i,$i+1] = @char[$i+1,$i];
5303             }
5304              
5305             # octal escape sequence
5306             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
5307 0           $char[$i] = Char::Ecyrillic::octchr($1);
5308             }
5309              
5310             # hexadecimal escape sequence
5311             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
5312 0           $char[$i] = Char::Ecyrillic::hexchr($1);
5313             }
5314              
5315             # \N{CHARNAME} --> N{CHARNAME}
5316             elsif ($char[$i] =~ /\A \\ ( N\{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
5317 0           $char[$i] = $1;
5318             }
5319              
5320 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          
5321             }
5322              
5323             # \u \l \U \L \F \Q \E
5324 0           elsif ($char[$i] =~ /\A ([<>]) \z/oxms) {
5325 0 0         if ($right_e < $left_e) {
5326 0           $char[$i] = '\\' . $char[$i];
5327             }
5328             }
5329             elsif ($char[$i] eq '\u') {
5330 0           $char[$i] = '@{[Char::Ecyrillic::ucfirst qq<';
5331 0           $left_e++;
5332             }
5333             elsif ($char[$i] eq '\l') {
5334 0           $char[$i] = '@{[Char::Ecyrillic::lcfirst qq<';
5335 0           $left_e++;
5336             }
5337             elsif ($char[$i] eq '\U') {
5338 0           $char[$i] = '@{[Char::Ecyrillic::uc qq<';
5339 0           $left_e++;
5340             }
5341             elsif ($char[$i] eq '\L') {
5342 0           $char[$i] = '@{[Char::Ecyrillic::lc qq<';
5343 0           $left_e++;
5344             }
5345             elsif ($char[$i] eq '\F') {
5346 0           $char[$i] = '@{[Char::Ecyrillic::fc qq<';
5347 0           $left_e++;
5348             }
5349             elsif ($char[$i] eq '\Q') {
5350 0           $char[$i] = '@{[CORE::quotemeta qq<';
5351 0           $left_e++;
5352             }
5353             elsif ($char[$i] eq '\E') {
5354 0 0         if ($right_e < $left_e) {
5355 0           $char[$i] = '>]}';
5356 0           $right_e++;
5357             }
5358             else {
5359 0           $char[$i] = '';
5360             }
5361             }
5362             elsif ($char[$i] eq '\Q') {
5363 0           while (1) {
5364 0 0         if (++$i > $#char) {
5365 0           last;
5366             }
5367 0 0         if ($char[$i] eq '\E') {
5368 0           last;
5369             }
5370             }
5371             }
5372             elsif ($char[$i] eq '\E') {
5373             }
5374              
5375             # $0 --> $0
5376             elsif ($char[$i] =~ /\A \$ 0 \z/oxms) {
5377             }
5378             elsif ($char[$i] =~ /\A \$ \{ \s* 0 \s* \} \z/oxms) {
5379             }
5380              
5381             # $$ --> $$
5382             elsif ($char[$i] =~ /\A \$\$ \z/oxms) {
5383             }
5384              
5385             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
5386             # $1, $2, $3 --> $1, $2, $3 otherwise
5387             elsif ($char[$i] =~ /\A \$ ([1-9][0-9]*) \z/oxms) {
5388 0           $char[$i] = e_capture($1);
5389             }
5390             elsif ($char[$i] =~ /\A \$ \{ \s* ([1-9][0-9]*) \s* \} \z/oxms) {
5391 0           $char[$i] = e_capture($1);
5392             }
5393              
5394             # $$foo[ ... ] --> $ $foo->[ ... ]
5395             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) ( \[ (?:$qq_bracket)*? \] ) \z/oxms) {
5396 0           $char[$i] = e_capture($1.'->'.$2);
5397             }
5398              
5399             # $$foo{ ... } --> $ $foo->{ ... }
5400             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) ( \{ (?:$qq_brace)*? \} ) \z/oxms) {
5401 0           $char[$i] = e_capture($1.'->'.$2);
5402             }
5403              
5404             # $$foo
5405             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) \z/oxms) {
5406 0           $char[$i] = e_capture($1);
5407             }
5408              
5409             # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Char::Ecyrillic::PREMATCH()
5410             elsif ($char[$i] =~ /\A ( \$` | \$\{`\} | \$ \s* PREMATCH | \$ \s* \{ \s* PREMATCH \s* \} | \$ \s* \{\^PREMATCH\} ) \z/oxmsgc) {
5411 0           $char[$i] = '@{[Char::Ecyrillic::PREMATCH()]}';
5412             }
5413              
5414             # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Char::Ecyrillic::MATCH()
5415             elsif ($char[$i] =~ /\A ( \$& | \$\{&\} | \$ \s* MATCH | \$ \s* \{ \s* MATCH \s* \} | \$ \s* \{\^MATCH\} ) \z/oxmsgc) {
5416 0           $char[$i] = '@{[Char::Ecyrillic::MATCH()]}';
5417             }
5418              
5419             # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Char::Ecyrillic::POSTMATCH()
5420             elsif ($char[$i] =~ /\A ( \$ \s* POSTMATCH | \$ \s* \{ \s* POSTMATCH \s* \} | \$ \s* \{\^POSTMATCH\} ) \z/oxmsgc) {
5421 0           $char[$i] = '@{[Char::Ecyrillic::POSTMATCH()]}';
5422             }
5423              
5424             # ${ foo } --> ${ foo }
5425             elsif ($char[$i] =~ /\A \$ \s* \{ \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* \} \z/oxms) {
5426             }
5427              
5428             # ${ ... }
5429             elsif ($char[$i] =~ /\A \$ \s* \{ \s* ( .+ ) \s* \} \z/oxms) {
5430 0           $char[$i] = e_capture($1);
5431             }
5432             }
5433              
5434             # return string
5435 0 0         if ($left_e > $right_e) {
5436 0           return join '', @char, '>]}' x ($left_e - $right_e);
5437             }
5438 0           return join '', @char;
5439             }
5440              
5441             #
5442             # escape regexp (m//, qr//)
5443             #
5444             sub e_qr {
5445 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
5446 0   0       $modifier ||= '';
5447              
5448 0           $modifier =~ tr/p//d;
5449 0 0         if ($modifier =~ /([adlu])/oxms) {
5450 0           my $line = 0;
5451 0           for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
5452 0 0         if ($filename ne __FILE__) {
5453 0           $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
5454 0           last;
5455             }
5456             }
5457 0           die qq{Unsupported modifier "$1" used at line $line.\n};
5458             }
5459              
5460 0           $slash = 'div';
5461              
5462             # literal null string pattern
5463 0 0         if ($string eq '') {
    0          
5464 0           $modifier =~ tr/bB//d;
5465 0           $modifier =~ tr/i//d;
5466 0           return join '', $ope, $delimiter, $end_delimiter, $modifier;
5467             }
5468              
5469             # /b /B modifier
5470             elsif ($modifier =~ tr/bB//d) {
5471              
5472             # choice again delimiter
5473 0 0         if ($delimiter =~ / [\@:] /oxms) {
5474 0           my @char = $string =~ /\G([\x00-\xFF])/oxmsg;
5475 0           my %octet = map {$_ => 1} @char;
  0            
5476 0 0         if (not $octet{')'}) {
    0          
    0          
    0          
5477 0           $delimiter = '(';
5478 0           $end_delimiter = ')';
5479             }
5480             elsif (not $octet{'}'}) {
5481 0           $delimiter = '{';
5482 0           $end_delimiter = '}';
5483             }
5484             elsif (not $octet{']'}) {
5485 0           $delimiter = '[';
5486 0           $end_delimiter = ']';
5487             }
5488             elsif (not $octet{'>'}) {
5489 0           $delimiter = '<';
5490 0           $end_delimiter = '>';
5491             }
5492             else {
5493 0           for my $char (qw( ! " $ % & * + - . / = ? ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
5494 0 0         if (not $octet{$char}) {
5495 0           $delimiter = $char;
5496 0           $end_delimiter = $char;
5497 0           last;
5498             }
5499             }
5500             }
5501             }
5502              
5503 0 0 0       if (($ope =~ /\A m? \z/oxms) and ($delimiter eq '?')) {
5504 0           return join '', $ope, $delimiter, $string, $matched, $end_delimiter, $modifier;
5505             }
5506             else {
5507 0           return join '', $ope, $delimiter, '(?:', $string, ')', $matched, $end_delimiter, $modifier;
5508             }
5509             }
5510              
5511 0 0         my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
5512 0           my $metachar = qr/[\@\\|[\]{^]/oxms;
5513              
5514             # split regexp
5515 0           my @char = $string =~ /\G(
5516             \\o\{ [0-7]+ \} |
5517             \\ [0-7]{2,3} |
5518             \\x\{ [0-9A-Fa-f]+ \} |
5519             \\x [0-9A-Fa-f]{1,2} |
5520             \\c [\x40-\x5F] |
5521             \\N\{ [^0-9\}][^\}]* \} |
5522             \\p\{ [^0-9\}][^\}]* \} |
5523             \\P\{ [^0-9\}][^\}]* \} |
5524             \\ (?:$q_char) |
5525             \$` | \$\{`\} | \$ \s* PREMATCH | \$ \s* \{ \s* PREMATCH \s* \} | \$ \s* \{\^PREMATCH\} |
5526             \$& | \$\{&\} | \$ \s* MATCH | \$ \s* \{ \s* MATCH \s* \} | \$ \s* \{\^MATCH\} |
5527             \$ \s* POSTMATCH | \$ \s* \{ \s* POSTMATCH \s* \} | \$ \s* \{\^POSTMATCH\} |
5528             [\$\@] $qq_variable |
5529             \$ \s* \d+ |
5530             \$ \s* \{ \s* \d+ \s* \} |
5531             \$ \$ (?![\w\{]) |
5532             \$ \s* \$ \s* $qq_variable |
5533             \[\:\^ (?:alnum|alpha|ascii|blank|cntrl|digit|graph|lower|print|punct|space|upper|word|xdigit) :\] |
5534             \[\: (?:alnum|alpha|ascii|blank|cntrl|digit|graph|lower|print|punct|space|upper|word|xdigit) :\] |
5535             \[\^ |
5536             \(\? |
5537             (?:$q_char)
5538             )/oxmsg;
5539              
5540             # choice again delimiter
5541 0 0         if ($delimiter =~ / [\@:] /oxms) {
5542 0           my %octet = map {$_ => 1} @char;
  0            
5543 0 0         if (not $octet{')'}) {
    0          
    0          
    0          
5544 0           $delimiter = '(';
5545 0           $end_delimiter = ')';
5546             }
5547             elsif (not $octet{'}'}) {
5548 0           $delimiter = '{';
5549 0           $end_delimiter = '}';
5550             }
5551             elsif (not $octet{']'}) {
5552 0           $delimiter = '[';
5553 0           $end_delimiter = ']';
5554             }
5555             elsif (not $octet{'>'}) {
5556 0           $delimiter = '<';
5557 0           $end_delimiter = '>';
5558             }
5559             else {
5560 0           for my $char (qw( ! " $ % & * + - . / = ? ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
5561 0 0         if (not $octet{$char}) {
5562 0           $delimiter = $char;
5563 0           $end_delimiter = $char;
5564 0           last;
5565             }
5566             }
5567             }
5568             }
5569              
5570 0           my $left_e = 0;
5571 0           my $right_e = 0;
5572 0           for (my $i=0; $i <= $#char; $i++) {
5573              
5574             # "\L\u" --> "\u\L"
5575 0 0 0       if (($char[$i] eq '\L') and ($char[$i+1] eq '\u')) {
    0 0        
    0          
    0          
    0          
    0          
    0          
    0          
5576 0           @char[$i,$i+1] = @char[$i+1,$i];
5577             }
5578              
5579             # "\U\l" --> "\l\U"
5580             elsif (($char[$i] eq '\U') and ($char[$i+1] eq '\l')) {
5581 0           @char[$i,$i+1] = @char[$i+1,$i];
5582             }
5583              
5584             # octal escape sequence
5585             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
5586 0           $char[$i] = Char::Ecyrillic::octchr($1);
5587             }
5588              
5589             # hexadecimal escape sequence
5590             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
5591 0           $char[$i] = Char::Ecyrillic::hexchr($1);
5592             }
5593              
5594             # \N{CHARNAME} --> N\{CHARNAME}
5595             elsif ($char[$i] =~ /\A \\ (N) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
5596 0           $char[$i] = $1 . '\\' . $2;
5597             }
5598              
5599             # \p{PROPERTY} --> p\{PROPERTY}
5600             elsif ($char[$i] =~ /\A \\ (p) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
5601 0           $char[$i] = $1 . '\\' . $2;
5602             }
5603              
5604             # \P{PROPERTY} --> P\{PROPERTY}
5605             elsif ($char[$i] =~ /\A \\ (P) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
5606 0           $char[$i] = $1 . '\\' . $2;
5607             }
5608              
5609             # \p, \P, \X --> p, P, X
5610             elsif ($char[$i] =~ /\A \\ ( [pPX] ) \z/oxms) {
5611 0           $char[$i] = $1;
5612             }
5613              
5614 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          
5615             }
5616              
5617             # join separated multiple-octet
5618 0           elsif ($char[$i] =~ /\A (?: \\ [0-7]{2,3} | \\x [0-9A-Fa-f]{1,2}) \z/oxms) {
5619 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        
5620 0           $char[$i] .= join '', splice @char, $i+1, 3;
5621             }
5622             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)) {
5623 0           $char[$i] .= join '', splice @char, $i+1, 2;
5624             }
5625             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)) {
5626 0           $char[$i] .= join '', splice @char, $i+1, 1;
5627             }
5628             }
5629              
5630             # open character class [...]
5631             elsif ($char[$i] eq '[') {
5632 0           my $left = $i;
5633              
5634             # [] make die "Unmatched [] in regexp ..."
5635             # (and so on)
5636              
5637 0 0         if ($char[$i+1] eq ']') {
5638 0           $i++;
5639             }
5640              
5641 0           while (1) {
5642 0 0         if (++$i > $#char) {
5643 0           die __FILE__, ": Unmatched [] in regexp";
5644             }
5645 0 0         if ($char[$i] eq ']') {
5646 0           my $right = $i;
5647              
5648             # [...]
5649 0 0         if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
5650 0           splice @char, $left, $right-$left+1, sprintf(q{@{[Char::Ecyrillic::charlist_qr(%s,'%s')]}}, join(',', map {qq_stuff($delimiter,$end_delimiter,$_)} @char[$left+1..$right-1]), $modifier);
  0            
5651             }
5652             else {
5653 0           splice @char, $left, $right-$left+1, Char::Ecyrillic::charlist_qr(@char[$left+1..$right-1], $modifier);
5654             }
5655              
5656 0           $i = $left;
5657 0           last;
5658             }
5659             }
5660             }
5661              
5662             # open character class [^...]
5663             elsif ($char[$i] eq '[^') {
5664 0           my $left = $i;
5665              
5666             # [^] make die "Unmatched [] in regexp ..."
5667             # (and so on)
5668              
5669 0 0         if ($char[$i+1] eq ']') {
5670 0           $i++;
5671             }
5672              
5673 0           while (1) {
5674 0 0         if (++$i > $#char) {
5675 0           die __FILE__, ": Unmatched [] in regexp";
5676             }
5677 0 0         if ($char[$i] eq ']') {
5678 0           my $right = $i;
5679              
5680             # [^...]
5681 0 0         if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
5682 0           splice @char, $left, $right-$left+1, sprintf(q{@{[Char::Ecyrillic::charlist_not_qr(%s,'%s')]}}, join(',', map {qq_stuff($delimiter,$end_delimiter,$_)} @char[$left+1..$right-1]), $modifier);
  0            
5683             }
5684             else {
5685 0           splice @char, $left, $right-$left+1, Char::Ecyrillic::charlist_not_qr(@char[$left+1..$right-1], $modifier);
5686             }
5687              
5688 0           $i = $left;
5689 0           last;
5690             }
5691             }
5692             }
5693              
5694             # rewrite character class or escape character
5695             elsif (my $char = character_class($char[$i],$modifier)) {
5696 0           $char[$i] = $char;
5697             }
5698              
5699             # /i modifier
5700             elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Char::Ecyrillic::uc($char[$i]) ne Char::Ecyrillic::fc($char[$i]))) {
5701 0 0         if (CORE::length(Char::Ecyrillic::fc($char[$i])) == 1) {
5702 0           $char[$i] = '[' . Char::Ecyrillic::uc($char[$i]) . Char::Ecyrillic::fc($char[$i]) . ']';
5703             }
5704             else {
5705 0           $char[$i] = '(?:' . Char::Ecyrillic::uc($char[$i]) . '|' . Char::Ecyrillic::fc($char[$i]) . ')';
5706             }
5707             }
5708              
5709             # \u \l \U \L \F \Q \E
5710             elsif ($char[$i] =~ /\A [<>] \z/oxms) {
5711 0 0         if ($right_e < $left_e) {
5712 0           $char[$i] = '\\' . $char[$i];
5713             }
5714             }
5715             elsif ($char[$i] eq '\u') {
5716 0           $char[$i] = '@{[Char::Ecyrillic::ucfirst qq<';
5717 0           $left_e++;
5718             }
5719             elsif ($char[$i] eq '\l') {
5720 0           $char[$i] = '@{[Char::Ecyrillic::lcfirst qq<';
5721 0           $left_e++;
5722             }
5723             elsif ($char[$i] eq '\U') {
5724 0           $char[$i] = '@{[Char::Ecyrillic::uc qq<';
5725 0           $left_e++;
5726             }
5727             elsif ($char[$i] eq '\L') {
5728 0           $char[$i] = '@{[Char::Ecyrillic::lc qq<';
5729 0           $left_e++;
5730             }
5731             elsif ($char[$i] eq '\F') {
5732 0           $char[$i] = '@{[Char::Ecyrillic::fc qq<';
5733 0           $left_e++;
5734             }
5735             elsif ($char[$i] eq '\Q') {
5736 0           $char[$i] = '@{[CORE::quotemeta qq<';
5737 0           $left_e++;
5738             }
5739             elsif ($char[$i] eq '\E') {
5740 0 0         if ($right_e < $left_e) {
5741 0           $char[$i] = '>]}';
5742 0           $right_e++;
5743             }
5744             else {
5745 0           $char[$i] = '';
5746             }
5747             }
5748             elsif ($char[$i] eq '\Q') {
5749 0           while (1) {
5750 0 0         if (++$i > $#char) {
5751 0           last;
5752             }
5753 0 0         if ($char[$i] eq '\E') {
5754 0           last;
5755             }
5756             }
5757             }
5758             elsif ($char[$i] eq '\E') {
5759             }
5760              
5761             # $0 --> $0
5762             elsif ($char[$i] =~ /\A \$ 0 \z/oxms) {
5763 0 0         if ($ignorecase) {
5764 0           $char[$i] = '@{[Char::Ecyrillic::ignorecase(' . $char[$i] . ')]}';
5765             }
5766             }
5767             elsif ($char[$i] =~ /\A \$ \{ \s* 0 \s* \} \z/oxms) {
5768 0 0         if ($ignorecase) {
5769 0           $char[$i] = '@{[Char::Ecyrillic::ignorecase(' . $char[$i] . ')]}';
5770             }
5771             }
5772              
5773             # $$ --> $$
5774             elsif ($char[$i] =~ /\A \$\$ \z/oxms) {
5775             }
5776              
5777             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
5778             # $1, $2, $3 --> $1, $2, $3 otherwise
5779             elsif ($char[$i] =~ /\A \$ ([1-9][0-9]*) \z/oxms) {
5780 0           $char[$i] = e_capture($1);
5781 0 0         if ($ignorecase) {
5782 0           $char[$i] = '@{[Char::Ecyrillic::ignorecase(' . $char[$i] . ')]}';
5783             }
5784             }
5785             elsif ($char[$i] =~ /\A \$ \{ \s* ([1-9][0-9]*) \s* \} \z/oxms) {
5786 0           $char[$i] = e_capture($1);
5787 0 0         if ($ignorecase) {
5788 0           $char[$i] = '@{[Char::Ecyrillic::ignorecase(' . $char[$i] . ')]}';
5789             }
5790             }
5791              
5792             # $$foo[ ... ] --> $ $foo->[ ... ]
5793             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) ( \[ (?:$qq_bracket)*? \] ) \z/oxms) {
5794 0           $char[$i] = e_capture($1.'->'.$2);
5795 0 0         if ($ignorecase) {
5796 0           $char[$i] = '@{[Char::Ecyrillic::ignorecase(' . $char[$i] . ')]}';
5797             }
5798             }
5799              
5800             # $$foo{ ... } --> $ $foo->{ ... }
5801             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) ( \{ (?:$qq_brace)*? \} ) \z/oxms) {
5802 0           $char[$i] = e_capture($1.'->'.$2);
5803 0 0         if ($ignorecase) {
5804 0           $char[$i] = '@{[Char::Ecyrillic::ignorecase(' . $char[$i] . ')]}';
5805             }
5806             }
5807              
5808             # $$foo
5809             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) \z/oxms) {
5810 0           $char[$i] = e_capture($1);
5811 0 0         if ($ignorecase) {
5812 0           $char[$i] = '@{[Char::Ecyrillic::ignorecase(' . $char[$i] . ')]}';
5813             }
5814             }
5815              
5816             # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Char::Ecyrillic::PREMATCH()
5817             elsif ($char[$i] =~ /\A ( \$` | \$\{`\} | \$ \s* PREMATCH | \$ \s* \{ \s* PREMATCH \s* \} | \$ \s* \{\^PREMATCH\} ) \z/oxmsgc) {
5818 0 0         if ($ignorecase) {
5819 0           $char[$i] = '@{[Char::Ecyrillic::ignorecase(Char::Ecyrillic::PREMATCH())]}';
5820             }
5821             else {
5822 0           $char[$i] = '@{[Char::Ecyrillic::PREMATCH()]}';
5823             }
5824             }
5825              
5826             # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Char::Ecyrillic::MATCH()
5827             elsif ($char[$i] =~ /\A ( \$& | \$\{&\} | \$ \s* MATCH | \$ \s* \{ \s* MATCH \s* \} | \$ \s* \{\^MATCH\} ) \z/oxmsgc) {
5828 0 0         if ($ignorecase) {
5829 0           $char[$i] = '@{[Char::Ecyrillic::ignorecase(Char::Ecyrillic::MATCH())]}';
5830             }
5831             else {
5832 0           $char[$i] = '@{[Char::Ecyrillic::MATCH()]}';
5833             }
5834             }
5835              
5836             # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Char::Ecyrillic::POSTMATCH()
5837             elsif ($char[$i] =~ /\A ( \$ \s* POSTMATCH | \$ \s* \{ \s* POSTMATCH \s* \} | \$ \s* \{\^POSTMATCH\} ) \z/oxmsgc) {
5838 0 0         if ($ignorecase) {
5839 0           $char[$i] = '@{[Char::Ecyrillic::ignorecase(Char::Ecyrillic::POSTMATCH())]}';
5840             }
5841             else {
5842 0           $char[$i] = '@{[Char::Ecyrillic::POSTMATCH()]}';
5843             }
5844             }
5845              
5846             # ${ foo }
5847             elsif ($char[$i] =~ /\A \$ \s* \{ ( \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* ) \} \z/oxms) {
5848 0 0         if ($ignorecase) {
5849 0           $char[$i] = '@{[Char::Ecyrillic::ignorecase(' . $char[$i] . ')]}';
5850             }
5851             }
5852              
5853             # ${ ... }
5854             elsif ($char[$i] =~ /\A \$ \s* \{ \s* ( .+ ) \s* \} \z/oxms) {
5855 0           $char[$i] = e_capture($1);
5856 0 0         if ($ignorecase) {
5857 0           $char[$i] = '@{[Char::Ecyrillic::ignorecase(' . $char[$i] . ')]}';
5858             }
5859             }
5860              
5861             # $scalar or @array
5862             elsif ($char[$i] =~ /\A [\$\@].+ /oxms) {
5863 0           $char[$i] = e_string($char[$i]);
5864 0 0         if ($ignorecase) {
5865 0           $char[$i] = '@{[Char::Ecyrillic::ignorecase(' . $char[$i] . ')]}';
5866             }
5867             }
5868              
5869             # quote character before ? + * {
5870             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
5871 0 0 0       if ($char[$i-1] =~ /\A (?:\\[0-7]{2,3}|\\x[0-9-A-Fa-f]{1,2}) \z/oxms) {
    0          
5872             }
5873             elsif (($ope =~ /\A m? \z/oxms) and ($delimiter eq '?')) {
5874 0           my $char = $char[$i-1];
5875 0 0         if ($char[$i] eq '{') {
5876 0           die __FILE__, qq{: "MULTIBYTE{n}" should be "(MULTIBYTE){n}" in m?? (and shift \$1,\$2,\$3,...) ($char){n}};
5877             }
5878             else {
5879 0           die __FILE__, qq{: "MULTIBYTE$char[$i]" should be "(MULTIBYTE)$char[$i]" in m?? (and shift \$1,\$2,\$3,...) ($char)$char[$i]};
5880             }
5881             }
5882             else {
5883 0           $char[$i-1] = '(?:' . $char[$i-1] . ')';
5884             }
5885             }
5886             }
5887              
5888             # make regexp string
5889 0           $modifier =~ tr/i//d;
5890 0 0         if ($left_e > $right_e) {
5891 0 0 0       if (($ope =~ /\A m? \z/oxms) and ($delimiter eq '?')) {
5892 0           return join '', $ope, $delimiter, $anchor, @char, '>]}' x ($left_e - $right_e), $matched, $end_delimiter, $modifier;
5893             }
5894             else {
5895 0           return join '', $ope, $delimiter, $anchor, '(?:', @char, '>]}' x ($left_e - $right_e), ')', $matched, $end_delimiter, $modifier;
5896             }
5897             }
5898 0 0 0       if (($ope =~ /\A m? \z/oxms) and ($delimiter eq '?')) {
5899 0           return join '', $ope, $delimiter, $anchor, @char, $matched, $end_delimiter, $modifier;
5900             }
5901             else {
5902 0           return join '', $ope, $delimiter, $anchor, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
5903             }
5904             }
5905              
5906             #
5907             # double quote stuff
5908             #
5909             sub qq_stuff {
5910 0     0 0   my($delimiter,$end_delimiter,$stuff) = @_;
5911              
5912             # scalar variable or array variable
5913 0 0         if ($stuff =~ /\A [\$\@] /oxms) {
5914 0           return $stuff;
5915             }
5916              
5917             # quote by delimiter
5918 0           my %octet = map {$_ => 1} ($stuff =~ /\G ([\x00-\xFF]) /oxmsg);
  0            
5919 0           for my $char (qw( ! " $ % & * + - . / : = ? @ ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
5920 0 0         next if $char eq $delimiter;
5921 0 0         next if $char eq $end_delimiter;
5922 0 0         if (not $octet{$char}) {
5923 0           return join '', 'qq', $char, $stuff, $char;
5924             }
5925             }
5926 0           return join '', 'qq', '<', $stuff, '>';
5927             }
5928              
5929             #
5930             # escape regexp (m'', qr'', and m''b, qr''b)
5931             #
5932             sub e_qr_q {
5933 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
5934 0   0       $modifier ||= '';
5935              
5936 0           $modifier =~ tr/p//d;
5937 0 0         if ($modifier =~ /([adlu])/oxms) {
5938 0           my $line = 0;
5939 0           for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
5940 0 0         if ($filename ne __FILE__) {
5941 0           $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
5942 0           last;
5943             }
5944             }
5945 0           die qq{Unsupported modifier "$1" used at line $line.\n};
5946             }
5947              
5948 0           $slash = 'div';
5949              
5950             # literal null string pattern
5951 0 0         if ($string eq '') {
    0          
5952 0           $modifier =~ tr/bB//d;
5953 0           $modifier =~ tr/i//d;
5954 0           return join '', $ope, $delimiter, $end_delimiter, $modifier;
5955             }
5956              
5957             # with /b /B modifier
5958             elsif ($modifier =~ tr/bB//d) {
5959 0           return e_qr_qb($ope,$delimiter,$end_delimiter,$string,$modifier);
5960             }
5961              
5962             # without /b /B modifier
5963             else {
5964 0           return e_qr_qt($ope,$delimiter,$end_delimiter,$string,$modifier);
5965             }
5966             }
5967              
5968             #
5969             # escape regexp (m'', qr'')
5970             #
5971             sub e_qr_qt {
5972 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
5973              
5974 0 0         my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
5975              
5976             # split regexp
5977 0           my @char = $string =~ /\G(
5978             \[\:\^ [a-z]+ \:\] |
5979             \[\: [a-z]+ \:\] |
5980             \[\^ |
5981             [\$\@\/\\] |
5982             \\? (?:$q_char)
5983             )/oxmsg;
5984              
5985             # unescape character
5986 0           for (my $i=0; $i <= $#char; $i++) {
5987 0 0 0       if (0) {
    0 0        
    0 0        
    0          
    0          
    0          
5988             }
5989              
5990             # open character class [...]
5991 0           elsif ($char[$i] eq '[') {
5992 0           my $left = $i;
5993 0 0         if ($char[$i+1] eq ']') {
5994 0           $i++;
5995             }
5996 0           while (1) {
5997 0 0         if (++$i > $#char) {
5998 0           die __FILE__, ": Unmatched [] in regexp";
5999             }
6000 0 0         if ($char[$i] eq ']') {
6001 0           my $right = $i;
6002              
6003             # [...]
6004 0           splice @char, $left, $right-$left+1, Char::Ecyrillic::charlist_qr(@char[$left+1..$right-1], $modifier);
6005              
6006 0           $i = $left;
6007 0           last;
6008             }
6009             }
6010             }
6011              
6012             # open character class [^...]
6013             elsif ($char[$i] eq '[^') {
6014 0           my $left = $i;
6015 0 0         if ($char[$i+1] eq ']') {
6016 0           $i++;
6017             }
6018 0           while (1) {
6019 0 0         if (++$i > $#char) {
6020 0           die __FILE__, ": Unmatched [] in regexp";
6021             }
6022 0 0         if ($char[$i] eq ']') {
6023 0           my $right = $i;
6024              
6025             # [^...]
6026 0           splice @char, $left, $right-$left+1, Char::Ecyrillic::charlist_not_qr(@char[$left+1..$right-1], $modifier);
6027              
6028 0           $i = $left;
6029 0           last;
6030             }
6031             }
6032             }
6033              
6034             # escape $ @ / and \
6035             elsif ($char[$i] =~ /\A [\$\@\/\\] \z/oxms) {
6036 0           $char[$i] = '\\' . $char[$i];
6037             }
6038              
6039             # rewrite character class or escape character
6040             elsif (my $char = character_class($char[$i],$modifier)) {
6041 0           $char[$i] = $char;
6042             }
6043              
6044             # /i modifier
6045             elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Char::Ecyrillic::uc($char[$i]) ne Char::Ecyrillic::fc($char[$i]))) {
6046 0 0         if (CORE::length(Char::Ecyrillic::fc($char[$i])) == 1) {
6047 0           $char[$i] = '[' . Char::Ecyrillic::uc($char[$i]) . Char::Ecyrillic::fc($char[$i]) . ']';
6048             }
6049             else {
6050 0           $char[$i] = '(?:' . Char::Ecyrillic::uc($char[$i]) . '|' . Char::Ecyrillic::fc($char[$i]) . ')';
6051             }
6052             }
6053              
6054             # quote character before ? + * {
6055             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
6056 0 0         if ($char[$i-1] =~ /\A [\x00-\xFF] \z/oxms) {
6057             }
6058             else {
6059 0           $char[$i-1] = '(?:' . $char[$i-1] . ')';
6060             }
6061             }
6062             }
6063              
6064 0           $delimiter = '/';
6065 0           $end_delimiter = '/';
6066              
6067 0           $modifier =~ tr/i//d;
6068 0           return join '', $ope, $delimiter, $anchor, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
6069             }
6070              
6071             #
6072             # escape regexp (m''b, qr''b)
6073             #
6074             sub e_qr_qb {
6075 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6076              
6077             # split regexp
6078 0           my @char = $string =~ /\G(
6079             \\\\ |
6080             [\$\@\/\\] |
6081             [\x00-\xFF]
6082             )/oxmsg;
6083              
6084             # unescape character
6085 0           for (my $i=0; $i <= $#char; $i++) {
6086 0 0         if (0) {
    0          
6087             }
6088              
6089             # remain \\
6090 0           elsif ($char[$i] eq '\\\\') {
6091             }
6092              
6093             # escape $ @ / and \
6094             elsif ($char[$i] =~ /\A [\$\@\/\\] \z/oxms) {
6095 0           $char[$i] = '\\' . $char[$i];
6096             }
6097             }
6098              
6099 0           $delimiter = '/';
6100 0           $end_delimiter = '/';
6101 0           return join '', $ope, $delimiter, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
6102             }
6103              
6104             #
6105             # escape regexp (s/here//)
6106             #
6107             sub e_s1 {
6108 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6109 0   0       $modifier ||= '';
6110              
6111 0           $modifier =~ tr/p//d;
6112 0 0         if ($modifier =~ /([adlu])/oxms) {
6113 0           my $line = 0;
6114 0           for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
6115 0 0         if ($filename ne __FILE__) {
6116 0           $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
6117 0           last;
6118             }
6119             }
6120 0           die qq{Unsupported modifier "$1" used at line $line.\n};
6121             }
6122              
6123 0           $slash = 'div';
6124              
6125             # literal null string pattern
6126 0 0         if ($string eq '') {
    0          
6127 0           $modifier =~ tr/bB//d;
6128 0           $modifier =~ tr/i//d;
6129 0           return join '', $ope, $delimiter, $end_delimiter, $modifier;
6130             }
6131              
6132             # /b /B modifier
6133             elsif ($modifier =~ tr/bB//d) {
6134              
6135             # choice again delimiter
6136 0 0         if ($delimiter =~ / [\@:] /oxms) {
6137 0           my @char = $string =~ /\G([\x00-\xFF])/oxmsg;
6138 0           my %octet = map {$_ => 1} @char;
  0            
6139 0 0         if (not $octet{')'}) {
    0          
    0          
    0          
6140 0           $delimiter = '(';
6141 0           $end_delimiter = ')';
6142             }
6143             elsif (not $octet{'}'}) {
6144 0           $delimiter = '{';
6145 0           $end_delimiter = '}';
6146             }
6147             elsif (not $octet{']'}) {
6148 0           $delimiter = '[';
6149 0           $end_delimiter = ']';
6150             }
6151             elsif (not $octet{'>'}) {
6152 0           $delimiter = '<';
6153 0           $end_delimiter = '>';
6154             }
6155             else {
6156 0           for my $char (qw( ! " $ % & * + - . / = ? ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
6157 0 0         if (not $octet{$char}) {
6158 0           $delimiter = $char;
6159 0           $end_delimiter = $char;
6160 0           last;
6161             }
6162             }
6163             }
6164             }
6165              
6166 0           my $prematch = '';
6167 0           return join '', $ope, $delimiter, $prematch, '(?:', $string, ')', $matched, $end_delimiter, $modifier;
6168             }
6169              
6170 0 0         my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
6171 0           my $metachar = qr/[\@\\|[\]{^]/oxms;
6172              
6173             # split regexp
6174 0           my @char = $string =~ /\G(
6175             \\g \s* \{ \s* - \s* [1-9][0-9]* \s* \} |
6176             \\g \s* \{ \s* [1-9][0-9]* \s* \} |
6177             \\g \s* [1-9][0-9]* |
6178             \\o\{ [0-7]+ \} |
6179             \\ [1-9][0-9]* |
6180             \\ [0-7]{2,3} |
6181             \\x\{ [0-9A-Fa-f]+ \} |
6182             \\x [0-9A-Fa-f]{1,2} |
6183             \\c [\x40-\x5F] |
6184             \\N\{ [^0-9\}][^\}]* \} |
6185             \\p\{ [^0-9\}][^\}]* \} |
6186             \\P\{ [^0-9\}][^\}]* \} |
6187             \\ (?:$q_char) |
6188             \$` | \$\{`\} | \$ \s* PREMATCH | \$ \s* \{ \s* PREMATCH \s* \} | \$ \s* \{\^PREMATCH\} |
6189             \$& | \$\{&\} | \$ \s* MATCH | \$ \s* \{ \s* MATCH \s* \} | \$ \s* \{\^MATCH\} |
6190             \$ \s* POSTMATCH | \$ \s* \{ \s* POSTMATCH \s* \} | \$ \s* \{\^POSTMATCH\} |
6191             [\$\@] $qq_variable |
6192             \$ \s* \d+ |
6193             \$ \s* \{ \s* \d+ \s* \} |
6194             \$ \$ (?![\w\{]) |
6195             \$ \s* \$ \s* $qq_variable |
6196             \[\:\^ (?:alnum|alpha|ascii|blank|cntrl|digit|graph|lower|print|punct|space|upper|word|xdigit) :\] |
6197             \[\: (?:alnum|alpha|ascii|blank|cntrl|digit|graph|lower|print|punct|space|upper|word|xdigit) :\] |
6198             \[\^ |
6199             \(\? |
6200             (?:$q_char)
6201             )/oxmsg;
6202              
6203             # choice again delimiter
6204 0 0         if ($delimiter =~ / [\@:] /oxms) {
6205 0           my %octet = map {$_ => 1} @char;
  0            
6206 0 0         if (not $octet{')'}) {
    0          
    0          
    0          
6207 0           $delimiter = '(';
6208 0           $end_delimiter = ')';
6209             }
6210             elsif (not $octet{'}'}) {
6211 0           $delimiter = '{';
6212 0           $end_delimiter = '}';
6213             }
6214             elsif (not $octet{']'}) {
6215 0           $delimiter = '[';
6216 0           $end_delimiter = ']';
6217             }
6218             elsif (not $octet{'>'}) {
6219 0           $delimiter = '<';
6220 0           $end_delimiter = '>';
6221             }
6222             else {
6223 0           for my $char (qw( ! " $ % & * + - . / = ? ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
6224 0 0         if (not $octet{$char}) {
6225 0           $delimiter = $char;
6226 0           $end_delimiter = $char;
6227 0           last;
6228             }
6229             }
6230             }
6231             }
6232              
6233             # count '('
6234 0           my $parens = grep { $_ eq '(' } @char;
  0            
6235              
6236 0           my $left_e = 0;
6237 0           my $right_e = 0;
6238 0           for (my $i=0; $i <= $#char; $i++) {
6239              
6240             # "\L\u" --> "\u\L"
6241 0 0 0       if (($char[$i] eq '\L') and ($char[$i+1] eq '\u')) {
    0 0        
    0          
    0          
    0          
    0          
    0          
    0          
6242 0           @char[$i,$i+1] = @char[$i+1,$i];
6243             }
6244              
6245             # "\U\l" --> "\l\U"
6246             elsif (($char[$i] eq '\U') and ($char[$i+1] eq '\l')) {
6247 0           @char[$i,$i+1] = @char[$i+1,$i];
6248             }
6249              
6250             # octal escape sequence
6251             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
6252 0           $char[$i] = Char::Ecyrillic::octchr($1);
6253             }
6254              
6255             # hexadecimal escape sequence
6256             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
6257 0           $char[$i] = Char::Ecyrillic::hexchr($1);
6258             }
6259              
6260             # \N{CHARNAME} --> N\{CHARNAME}
6261             elsif ($char[$i] =~ /\A \\ (N) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
6262 0           $char[$i] = $1 . '\\' . $2;
6263             }
6264              
6265             # \p{PROPERTY} --> p\{PROPERTY}
6266             elsif ($char[$i] =~ /\A \\ (p) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
6267 0           $char[$i] = $1 . '\\' . $2;
6268             }
6269              
6270             # \P{PROPERTY} --> P\{PROPERTY}
6271             elsif ($char[$i] =~ /\A \\ (P) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
6272 0           $char[$i] = $1 . '\\' . $2;
6273             }
6274              
6275             # \p, \P, \X --> p, P, X
6276             elsif ($char[$i] =~ /\A \\ ( [pPX] ) \z/oxms) {
6277 0           $char[$i] = $1;
6278             }
6279              
6280 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          
6281             }
6282              
6283             # join separated multiple-octet
6284 0           elsif ($char[$i] =~ /\A (?: \\ [0-7]{2,3} | \\x [0-9A-Fa-f]{1,2}) \z/oxms) {
6285 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        
6286 0           $char[$i] .= join '', splice @char, $i+1, 3;
6287             }
6288             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)) {
6289 0           $char[$i] .= join '', splice @char, $i+1, 2;
6290             }
6291             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)) {
6292 0           $char[$i] .= join '', splice @char, $i+1, 1;
6293             }
6294             }
6295              
6296             # open character class [...]
6297             elsif ($char[$i] eq '[') {
6298 0           my $left = $i;
6299 0 0         if ($char[$i+1] eq ']') {
6300 0           $i++;
6301             }
6302 0           while (1) {
6303 0 0         if (++$i > $#char) {
6304 0           die __FILE__, ": Unmatched [] in regexp";
6305             }
6306 0 0         if ($char[$i] eq ']') {
6307 0           my $right = $i;
6308              
6309             # [...]
6310 0 0         if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
6311 0           splice @char, $left, $right-$left+1, sprintf(q{@{[Char::Ecyrillic::charlist_qr(%s,'%s')]}}, join(',', map {qq_stuff($delimiter,$end_delimiter,$_)} @char[$left+1..$right-1]), $modifier);
  0            
6312             }
6313             else {
6314 0           splice @char, $left, $right-$left+1, Char::Ecyrillic::charlist_qr(@char[$left+1..$right-1], $modifier);
6315             }
6316              
6317 0           $i = $left;
6318 0           last;
6319             }
6320             }
6321             }
6322              
6323             # open character class [^...]
6324             elsif ($char[$i] eq '[^') {
6325 0           my $left = $i;
6326 0 0         if ($char[$i+1] eq ']') {
6327 0           $i++;
6328             }
6329 0           while (1) {
6330 0 0         if (++$i > $#char) {
6331 0           die __FILE__, ": Unmatched [] in regexp";
6332             }
6333 0 0         if ($char[$i] eq ']') {
6334 0           my $right = $i;
6335              
6336             # [^...]
6337 0 0         if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
6338 0           splice @char, $left, $right-$left+1, sprintf(q{@{[Char::Ecyrillic::charlist_not_qr(%s,'%s')]}}, join(',', map {qq_stuff($delimiter,$end_delimiter,$_)} @char[$left+1..$right-1]), $modifier);
  0            
6339             }
6340             else {
6341 0           splice @char, $left, $right-$left+1, Char::Ecyrillic::charlist_not_qr(@char[$left+1..$right-1], $modifier);
6342             }
6343              
6344 0           $i = $left;
6345 0           last;
6346             }
6347             }
6348             }
6349              
6350             # rewrite character class or escape character
6351             elsif (my $char = character_class($char[$i],$modifier)) {
6352 0           $char[$i] = $char;
6353             }
6354              
6355             # /i modifier
6356             elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Char::Ecyrillic::uc($char[$i]) ne Char::Ecyrillic::fc($char[$i]))) {
6357 0 0         if (CORE::length(Char::Ecyrillic::fc($char[$i])) == 1) {
6358 0           $char[$i] = '[' . Char::Ecyrillic::uc($char[$i]) . Char::Ecyrillic::fc($char[$i]) . ']';
6359             }
6360             else {
6361 0           $char[$i] = '(?:' . Char::Ecyrillic::uc($char[$i]) . '|' . Char::Ecyrillic::fc($char[$i]) . ')';
6362             }
6363             }
6364              
6365             # \u \l \U \L \F \Q \E
6366             elsif ($char[$i] =~ /\A [<>] \z/oxms) {
6367 0 0         if ($right_e < $left_e) {
6368 0           $char[$i] = '\\' . $char[$i];
6369             }
6370             }
6371             elsif ($char[$i] eq '\u') {
6372 0           $char[$i] = '@{[Char::Ecyrillic::ucfirst qq<';
6373 0           $left_e++;
6374             }
6375             elsif ($char[$i] eq '\l') {
6376 0           $char[$i] = '@{[Char::Ecyrillic::lcfirst qq<';
6377 0           $left_e++;
6378             }
6379             elsif ($char[$i] eq '\U') {
6380 0           $char[$i] = '@{[Char::Ecyrillic::uc qq<';
6381 0           $left_e++;
6382             }
6383             elsif ($char[$i] eq '\L') {
6384 0           $char[$i] = '@{[Char::Ecyrillic::lc qq<';
6385 0           $left_e++;
6386             }
6387             elsif ($char[$i] eq '\F') {
6388 0           $char[$i] = '@{[Char::Ecyrillic::fc qq<';
6389 0           $left_e++;
6390             }
6391             elsif ($char[$i] eq '\Q') {
6392 0           $char[$i] = '@{[CORE::quotemeta qq<';
6393 0           $left_e++;
6394             }
6395             elsif ($char[$i] eq '\E') {
6396 0 0         if ($right_e < $left_e) {
6397 0           $char[$i] = '>]}';
6398 0           $right_e++;
6399             }
6400             else {
6401 0           $char[$i] = '';
6402             }
6403             }
6404             elsif ($char[$i] eq '\Q') {
6405 0           while (1) {
6406 0 0         if (++$i > $#char) {
6407 0           last;
6408             }
6409 0 0         if ($char[$i] eq '\E') {
6410 0           last;
6411             }
6412             }
6413             }
6414             elsif ($char[$i] eq '\E') {
6415             }
6416              
6417             # \0 --> \0
6418             elsif ($char[$i] =~ /\A \\ \s* 0 \z/oxms) {
6419             }
6420              
6421             # \g{N}, \g{-N}
6422              
6423             # P.108 Using Simple Patterns
6424             # in Chapter 7: In the World of Regular Expressions
6425             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
6426              
6427             # P.221 Capturing
6428             # in Chapter 5: Pattern Matching
6429             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
6430              
6431             # \g{-1}, \g{-2}, \g{-3} --> \g{-1}, \g{-2}, \g{-3}
6432             elsif ($char[$i] =~ /\A \\g \s* \{ \s* - \s* ([1-9][0-9]*) \s* \} \z/oxms) {
6433             }
6434              
6435             # \g{1}, \g{2}, \g{3} --> \g{2}, \g{3}, \g{4} (only when multibyte anchoring is enable)
6436             elsif ($char[$i] =~ /\A \\g \s* \{ \s* ([1-9][0-9]*) \s* \} \z/oxms) {
6437             }
6438              
6439             # \g1, \g2, \g3 --> \g2, \g3, \g4 (only when multibyte anchoring is enable)
6440             elsif ($char[$i] =~ /\A \\g \s* ([1-9][0-9]*) \z/oxms) {
6441             }
6442              
6443             # \1, \2, \3 --> \2, \3, \4 (only when multibyte anchoring is enable)
6444             elsif ($char[$i] =~ /\A \\ \s* ([1-9][0-9]*) \z/oxms) {
6445             }
6446              
6447             # $0 --> $0
6448             elsif ($char[$i] =~ /\A \$ 0 \z/oxms) {
6449 0 0         if ($ignorecase) {
6450 0           $char[$i] = '@{[Char::Ecyrillic::ignorecase(' . $char[$i] . ')]}';
6451             }
6452             }
6453             elsif ($char[$i] =~ /\A \$ \{ \s* 0 \s* \} \z/oxms) {
6454 0 0         if ($ignorecase) {
6455 0           $char[$i] = '@{[Char::Ecyrillic::ignorecase(' . $char[$i] . ')]}';
6456             }
6457             }
6458              
6459             # $$ --> $$
6460             elsif ($char[$i] =~ /\A \$\$ \z/oxms) {
6461             }
6462              
6463             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
6464             # $1, $2, $3 --> $1, $2, $3 otherwise
6465             elsif ($char[$i] =~ /\A \$ ([1-9][0-9]*) \z/oxms) {
6466 0           $char[$i] = e_capture($1);
6467 0 0         if ($ignorecase) {
6468 0           $char[$i] = '@{[Char::Ecyrillic::ignorecase(' . $char[$i] . ')]}';
6469             }
6470             }
6471             elsif ($char[$i] =~ /\A \$ \{ \s* ([1-9][0-9]*) \s* \} \z/oxms) {
6472 0           $char[$i] = e_capture($1);
6473 0 0         if ($ignorecase) {
6474 0           $char[$i] = '@{[Char::Ecyrillic::ignorecase(' . $char[$i] . ')]}';
6475             }
6476             }
6477              
6478             # $$foo[ ... ] --> $ $foo->[ ... ]
6479             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) ( \[ (?:$qq_bracket)*? \] ) \z/oxms) {
6480 0           $char[$i] = e_capture($1.'->'.$2);
6481 0 0         if ($ignorecase) {
6482 0           $char[$i] = '@{[Char::Ecyrillic::ignorecase(' . $char[$i] . ')]}';
6483             }
6484             }
6485              
6486             # $$foo{ ... } --> $ $foo->{ ... }
6487             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) ( \{ (?:$qq_brace)*? \} ) \z/oxms) {
6488 0           $char[$i] = e_capture($1.'->'.$2);
6489 0 0         if ($ignorecase) {
6490 0           $char[$i] = '@{[Char::Ecyrillic::ignorecase(' . $char[$i] . ')]}';
6491             }
6492             }
6493              
6494             # $$foo
6495             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) \z/oxms) {
6496 0           $char[$i] = e_capture($1);
6497 0 0         if ($ignorecase) {
6498 0           $char[$i] = '@{[Char::Ecyrillic::ignorecase(' . $char[$i] . ')]}';
6499             }
6500             }
6501              
6502             # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Char::Ecyrillic::PREMATCH()
6503             elsif ($char[$i] =~ /\A ( \$` | \$\{`\} | \$ \s* PREMATCH | \$ \s* \{ \s* PREMATCH \s* \} | \$ \s* \{\^PREMATCH\} ) \z/oxmsgc) {
6504 0 0         if ($ignorecase) {
6505 0           $char[$i] = '@{[Char::Ecyrillic::ignorecase(Char::Ecyrillic::PREMATCH())]}';
6506             }
6507             else {
6508 0           $char[$i] = '@{[Char::Ecyrillic::PREMATCH()]}';
6509             }
6510             }
6511              
6512             # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Char::Ecyrillic::MATCH()
6513             elsif ($char[$i] =~ /\A ( \$& | \$\{&\} | \$ \s* MATCH | \$ \s* \{ \s* MATCH \s* \} | \$ \s* \{\^MATCH\} ) \z/oxmsgc) {
6514 0 0         if ($ignorecase) {
6515 0           $char[$i] = '@{[Char::Ecyrillic::ignorecase(Char::Ecyrillic::MATCH())]}';
6516             }
6517             else {
6518 0           $char[$i] = '@{[Char::Ecyrillic::MATCH()]}';
6519             }
6520             }
6521              
6522             # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Char::Ecyrillic::POSTMATCH()
6523             elsif ($char[$i] =~ /\A ( \$ \s* POSTMATCH | \$ \s* \{ \s* POSTMATCH \s* \} | \$ \s* \{\^POSTMATCH\} ) \z/oxmsgc) {
6524 0 0         if ($ignorecase) {
6525 0           $char[$i] = '@{[Char::Ecyrillic::ignorecase(Char::Ecyrillic::POSTMATCH())]}';
6526             }
6527             else {
6528 0           $char[$i] = '@{[Char::Ecyrillic::POSTMATCH()]}';
6529             }
6530             }
6531              
6532             # ${ foo }
6533             elsif ($char[$i] =~ /\A \$ \s* \{ ( \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* ) \} \z/oxms) {
6534 0 0         if ($ignorecase) {
6535 0           $char[$i] = '@{[Char::Ecyrillic::ignorecase(' . $char[$i] . ')]}';
6536             }
6537             }
6538              
6539             # ${ ... }
6540             elsif ($char[$i] =~ /\A \$ \s* \{ \s* ( .+ ) \s* \} \z/oxms) {
6541 0           $char[$i] = e_capture($1);
6542 0 0         if ($ignorecase) {
6543 0           $char[$i] = '@{[Char::Ecyrillic::ignorecase(' . $char[$i] . ')]}';
6544             }
6545             }
6546              
6547             # $scalar or @array
6548             elsif ($char[$i] =~ /\A [\$\@].+ /oxms) {
6549 0           $char[$i] = e_string($char[$i]);
6550 0 0         if ($ignorecase) {
6551 0           $char[$i] = '@{[Char::Ecyrillic::ignorecase(' . $char[$i] . ')]}';
6552             }
6553             }
6554              
6555             # quote character before ? + * {
6556             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
6557 0 0         if ($char[$i-1] =~ /\A (?:\\[0-7]{2,3}|\\x[0-9-A-Fa-f]{1,2}) \z/oxms) {
6558             }
6559             else {
6560 0           $char[$i-1] = '(?:' . $char[$i-1] . ')';
6561             }
6562             }
6563             }
6564              
6565             # make regexp string
6566 0           my $prematch = '';
6567 0           $modifier =~ tr/i//d;
6568 0 0         if ($left_e > $right_e) {
6569 0           return join '', $ope, $delimiter, $prematch, '(?:', @char, '>]}' x ($left_e - $right_e), ')', $matched, $end_delimiter, $modifier;
6570             }
6571 0           return join '', $ope, $delimiter, $prematch, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
6572             }
6573              
6574             #
6575             # escape regexp (s'here'' or s'here''b)
6576             #
6577             sub e_s1_q {
6578 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6579 0   0       $modifier ||= '';
6580              
6581 0           $modifier =~ tr/p//d;
6582 0 0         if ($modifier =~ /([adlu])/oxms) {
6583 0           my $line = 0;
6584 0           for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
6585 0 0         if ($filename ne __FILE__) {
6586 0           $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
6587 0           last;
6588             }
6589             }
6590 0           die qq{Unsupported modifier "$1" used at line $line.\n};
6591             }
6592              
6593 0           $slash = 'div';
6594              
6595             # literal null string pattern
6596 0 0         if ($string eq '') {
    0          
6597 0           $modifier =~ tr/bB//d;
6598 0           $modifier =~ tr/i//d;
6599 0           return join '', $ope, $delimiter, $end_delimiter, $modifier;
6600             }
6601              
6602             # with /b /B modifier
6603             elsif ($modifier =~ tr/bB//d) {
6604 0           return e_s1_qb($ope,$delimiter,$end_delimiter,$string,$modifier);
6605             }
6606              
6607             # without /b /B modifier
6608             else {
6609 0           return e_s1_qt($ope,$delimiter,$end_delimiter,$string,$modifier);
6610             }
6611             }
6612              
6613             #
6614             # escape regexp (s'here'')
6615             #
6616             sub e_s1_qt {
6617 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6618              
6619 0 0         my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
6620              
6621             # split regexp
6622 0           my @char = $string =~ /\G(
6623             \[\:\^ [a-z]+ \:\] |
6624             \[\: [a-z]+ \:\] |
6625             \[\^ |
6626             [\$\@\/\\] |
6627             \\? (?:$q_char)
6628             )/oxmsg;
6629              
6630             # unescape character
6631 0           for (my $i=0; $i <= $#char; $i++) {
6632 0 0 0       if (0) {
    0 0        
    0 0        
    0          
    0          
    0          
6633             }
6634              
6635             # open character class [...]
6636 0           elsif ($char[$i] eq '[') {
6637 0           my $left = $i;
6638 0 0         if ($char[$i+1] eq ']') {
6639 0           $i++;
6640             }
6641 0           while (1) {
6642 0 0         if (++$i > $#char) {
6643 0           die __FILE__, ": Unmatched [] in regexp";
6644             }
6645 0 0         if ($char[$i] eq ']') {
6646 0           my $right = $i;
6647              
6648             # [...]
6649 0           splice @char, $left, $right-$left+1, Char::Ecyrillic::charlist_qr(@char[$left+1..$right-1], $modifier);
6650              
6651 0           $i = $left;
6652 0           last;
6653             }
6654             }
6655             }
6656              
6657             # open character class [^...]
6658             elsif ($char[$i] eq '[^') {
6659 0           my $left = $i;
6660 0 0         if ($char[$i+1] eq ']') {
6661 0           $i++;
6662             }
6663 0           while (1) {
6664 0 0         if (++$i > $#char) {
6665 0           die __FILE__, ": Unmatched [] in regexp";
6666             }
6667 0 0         if ($char[$i] eq ']') {
6668 0           my $right = $i;
6669              
6670             # [^...]
6671 0           splice @char, $left, $right-$left+1, Char::Ecyrillic::charlist_not_qr(@char[$left+1..$right-1], $modifier);
6672              
6673 0           $i = $left;
6674 0           last;
6675             }
6676             }
6677             }
6678              
6679             # escape $ @ / and \
6680             elsif ($char[$i] =~ /\A [\$\@\/\\] \z/oxms) {
6681 0           $char[$i] = '\\' . $char[$i];
6682             }
6683              
6684             # rewrite character class or escape character
6685             elsif (my $char = character_class($char[$i],$modifier)) {
6686 0           $char[$i] = $char;
6687             }
6688              
6689             # /i modifier
6690             elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Char::Ecyrillic::uc($char[$i]) ne Char::Ecyrillic::fc($char[$i]))) {
6691 0 0         if (CORE::length(Char::Ecyrillic::fc($char[$i])) == 1) {
6692 0           $char[$i] = '[' . Char::Ecyrillic::uc($char[$i]) . Char::Ecyrillic::fc($char[$i]) . ']';
6693             }
6694             else {
6695 0           $char[$i] = '(?:' . Char::Ecyrillic::uc($char[$i]) . '|' . Char::Ecyrillic::fc($char[$i]) . ')';
6696             }
6697             }
6698              
6699             # quote character before ? + * {
6700             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
6701 0 0         if ($char[$i-1] =~ /\A [\x00-\xFF] \z/oxms) {
6702             }
6703             else {
6704 0           $char[$i-1] = '(?:' . $char[$i-1] . ')';
6705             }
6706             }
6707             }
6708              
6709 0           $modifier =~ tr/i//d;
6710 0           $delimiter = '/';
6711 0           $end_delimiter = '/';
6712 0           my $prematch = '';
6713 0           return join '', $ope, $delimiter, $prematch, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
6714             }
6715              
6716             #
6717             # escape regexp (s'here''b)
6718             #
6719             sub e_s1_qb {
6720 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6721              
6722             # split regexp
6723 0           my @char = $string =~ /\G(
6724             \\\\ |
6725             [\$\@\/\\] |
6726             [\x00-\xFF]
6727             )/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             '$Char::Cyrillic::re_r=CORE::eval $Char::Cyrillic::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 $Char::Cyrillic::re_r=%s; %s"%s$Char::Cyrillic::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             '$Char::Cyrillic::re_r=CORE::eval $Char::Cyrillic::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             '$Char::Cyrillic::re_r=CORE::eval $Char::Cyrillic::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 $Char::Cyrillic::re_r=%s; %s%s="%s$Char::Cyrillic::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 $Char::Cyrillic::re_r=%s; %s%s="%s$Char::Cyrillic::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             '$Char::Cyrillic::re_r=CORE::eval $Char::Cyrillic::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             \\o\{ [0-7]+ \} |
6992             \\ [0-7]{2,3} |
6993             \\x\{ [0-9A-Fa-f]+ \} |
6994             \\x [0-9A-Fa-f]{1,2} |
6995             \\c [\x40-\x5F] |
6996             \\N\{ [^0-9\}][^\}]* \} |
6997             \\p\{ [^0-9\}][^\}]* \} |
6998             \\P\{ [^0-9\}][^\}]* \} |
6999             \\ (?:$q_char) |
7000             \$` | \$\{`\} | \$ \s* PREMATCH | \$ \s* \{ \s* PREMATCH \s* \} | \$ \s* \{\^PREMATCH\} |
7001             \$& | \$\{&\} | \$ \s* MATCH | \$ \s* \{ \s* MATCH \s* \} | \$ \s* \{\^MATCH\} |
7002             \$ \s* POSTMATCH | \$ \s* \{ \s* POSTMATCH \s* \} | \$ \s* \{\^POSTMATCH\} |
7003             [\$\@] $qq_variable |
7004             \$ \s* \d+ |
7005             \$ \s* \{ \s* \d+ \s* \} |
7006             \$ \$ (?![\w\{]) |
7007             \$ \s* \$ \s* $qq_variable |
7008             \[\:\^ (?:alnum|alpha|ascii|blank|cntrl|digit|graph|lower|print|punct|space|upper|word|xdigit) :\] |
7009             \[\: (?:alnum|alpha|ascii|blank|cntrl|digit|graph|lower|print|punct|space|upper|word|xdigit) :\] |
7010             \[\^ |
7011             \(\? |
7012             (?:$q_char)
7013             )/oxmsg;
7014              
7015 0           my $left_e = 0;
7016 0           my $right_e = 0;
7017 0           for (my $i=0; $i <= $#char; $i++) {
7018              
7019             # "\L\u" --> "\u\L"
7020 0 0 0       if (($char[$i] eq '\L') and ($char[$i+1] eq '\u')) {
    0 0        
    0          
    0          
    0          
    0          
    0          
    0          
7021 0           @char[$i,$i+1] = @char[$i+1,$i];
7022             }
7023              
7024             # "\U\l" --> "\l\U"
7025             elsif (($char[$i] eq '\U') and ($char[$i+1] eq '\l')) {
7026 0           @char[$i,$i+1] = @char[$i+1,$i];
7027             }
7028              
7029             # octal escape sequence
7030             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
7031 0           $char[$i] = Char::Ecyrillic::octchr($1);
7032             }
7033              
7034             # hexadecimal escape sequence
7035             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
7036 0           $char[$i] = Char::Ecyrillic::hexchr($1);
7037             }
7038              
7039             # \N{CHARNAME} --> N\{CHARNAME}
7040             elsif ($char[$i] =~ /\A \\ (N) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
7041 0           $char[$i] = $1 . '\\' . $2;
7042             }
7043              
7044             # \p{PROPERTY} --> p\{PROPERTY}
7045             elsif ($char[$i] =~ /\A \\ (p) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
7046 0           $char[$i] = $1 . '\\' . $2;
7047             }
7048              
7049             # \P{PROPERTY} --> P\{PROPERTY}
7050             elsif ($char[$i] =~ /\A \\ (P) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
7051 0           $char[$i] = $1 . '\\' . $2;
7052             }
7053              
7054             # \p, \P, \X --> p, P, X
7055             elsif ($char[$i] =~ /\A \\ ( [pPX] ) \z/oxms) {
7056 0           $char[$i] = $1;
7057             }
7058              
7059 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          
7060             }
7061              
7062             # join separated multiple-octet
7063 0           elsif ($char[$i] =~ /\A (?: \\ [0-7]{2,3} | \\x [0-9A-Fa-f]{1,2}) \z/oxms) {
7064 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        
7065 0           $char[$i] .= join '', splice @char, $i+1, 3;
7066             }
7067             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)) {
7068 0           $char[$i] .= join '', splice @char, $i+1, 2;
7069             }
7070             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)) {
7071 0           $char[$i] .= join '', splice @char, $i+1, 1;
7072             }
7073             }
7074              
7075             # open character class [...]
7076             elsif ($char[$i] eq '[') {
7077 0           my $left = $i;
7078 0 0         if ($char[$i+1] eq ']') {
7079 0           $i++;
7080             }
7081 0           while (1) {
7082 0 0         if (++$i > $#char) {
7083 0           die __FILE__, ": Unmatched [] in regexp";
7084             }
7085 0 0         if ($char[$i] eq ']') {
7086 0           my $right = $i;
7087              
7088             # [...]
7089 0 0         if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
7090 0           splice @char, $left, $right-$left+1, sprintf(q{@{[Char::Ecyrillic::charlist_qr(%s,'%s')]}}, join(',', map {qq_stuff($delimiter,$end_delimiter,$_)} @char[$left+1..$right-1]), $modifier);
  0            
7091             }
7092             else {
7093 0           splice @char, $left, $right-$left+1, Char::Ecyrillic::charlist_qr(@char[$left+1..$right-1], $modifier);
7094             }
7095              
7096 0           $i = $left;
7097 0           last;
7098             }
7099             }
7100             }
7101              
7102             # open character class [^...]
7103             elsif ($char[$i] eq '[^') {
7104 0           my $left = $i;
7105 0 0         if ($char[$i+1] eq ']') {
7106 0           $i++;
7107             }
7108 0           while (1) {
7109 0 0         if (++$i > $#char) {
7110 0           die __FILE__, ": Unmatched [] in regexp";
7111             }
7112 0 0         if ($char[$i] eq ']') {
7113 0           my $right = $i;
7114              
7115             # [^...]
7116 0 0         if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
7117 0           splice @char, $left, $right-$left+1, sprintf(q{@{[Char::Ecyrillic::charlist_not_qr(%s,'%s')]}}, join(',', map {qq_stuff($delimiter,$end_delimiter,$_)} @char[$left+1..$right-1]), $modifier);
  0            
7118             }
7119             else {
7120 0           splice @char, $left, $right-$left+1, Char::Ecyrillic::charlist_not_qr(@char[$left+1..$right-1], $modifier);
7121             }
7122              
7123 0           $i = $left;
7124 0           last;
7125             }
7126             }
7127             }
7128              
7129             # rewrite character class or escape character
7130             elsif (my $char = character_class($char[$i],$modifier)) {
7131 0           $char[$i] = $char;
7132             }
7133              
7134             # P.794 29.2.161. split
7135             # in Chapter 29: Functions
7136             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
7137              
7138             # P.951 split
7139             # in Chapter 27: Functions
7140             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
7141              
7142             # said "The //m modifier is assumed when you split on the pattern /^/",
7143             # but perl5.008 is not so. Therefore, this software adds //m.
7144             # (and so on)
7145              
7146             # split(m/^/) --> split(m/^/m)
7147             elsif (($char[$i] eq '^') and ($modifier !~ /m/oxms)) {
7148 0           $modifier .= 'm';
7149             }
7150              
7151             # /i modifier
7152             elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Char::Ecyrillic::uc($char[$i]) ne Char::Ecyrillic::fc($char[$i]))) {
7153 0 0         if (CORE::length(Char::Ecyrillic::fc($char[$i])) == 1) {
7154 0           $char[$i] = '[' . Char::Ecyrillic::uc($char[$i]) . Char::Ecyrillic::fc($char[$i]) . ']';
7155             }
7156             else {
7157 0           $char[$i] = '(?:' . Char::Ecyrillic::uc($char[$i]) . '|' . Char::Ecyrillic::fc($char[$i]) . ')';
7158             }
7159             }
7160              
7161             # \u \l \U \L \F \Q \E
7162             elsif ($char[$i] =~ /\A ([<>]) \z/oxms) {
7163 0 0         if ($right_e < $left_e) {
7164 0           $char[$i] = '\\' . $char[$i];
7165             }
7166             }
7167             elsif ($char[$i] eq '\u') {
7168 0           $char[$i] = '@{[Char::Ecyrillic::ucfirst qq<';
7169 0           $left_e++;
7170             }
7171             elsif ($char[$i] eq '\l') {
7172 0           $char[$i] = '@{[Char::Ecyrillic::lcfirst qq<';
7173 0           $left_e++;
7174             }
7175             elsif ($char[$i] eq '\U') {
7176 0           $char[$i] = '@{[Char::Ecyrillic::uc qq<';
7177 0           $left_e++;
7178             }
7179             elsif ($char[$i] eq '\L') {
7180 0           $char[$i] = '@{[Char::Ecyrillic::lc qq<';
7181 0           $left_e++;
7182             }
7183             elsif ($char[$i] eq '\F') {
7184 0           $char[$i] = '@{[Char::Ecyrillic::fc qq<';
7185 0           $left_e++;
7186             }
7187             elsif ($char[$i] eq '\Q') {
7188 0           $char[$i] = '@{[CORE::quotemeta qq<';
7189 0           $left_e++;
7190             }
7191             elsif ($char[$i] eq '\E') {
7192 0 0         if ($right_e < $left_e) {
7193 0           $char[$i] = '>]}';
7194 0           $right_e++;
7195             }
7196             else {
7197 0           $char[$i] = '';
7198             }
7199             }
7200             elsif ($char[$i] eq '\Q') {
7201 0           while (1) {
7202 0 0         if (++$i > $#char) {
7203 0           last;
7204             }
7205 0 0         if ($char[$i] eq '\E') {
7206 0           last;
7207             }
7208             }
7209             }
7210             elsif ($char[$i] eq '\E') {
7211             }
7212              
7213             # $0 --> $0
7214             elsif ($char[$i] =~ /\A \$ 0 \z/oxms) {
7215 0 0         if ($ignorecase) {
7216 0           $char[$i] = '@{[Char::Ecyrillic::ignorecase(' . $char[$i] . ')]}';
7217             }
7218             }
7219             elsif ($char[$i] =~ /\A \$ \{ \s* 0 \s* \} \z/oxms) {
7220 0 0         if ($ignorecase) {
7221 0           $char[$i] = '@{[Char::Ecyrillic::ignorecase(' . $char[$i] . ')]}';
7222             }
7223             }
7224              
7225             # $$ --> $$
7226             elsif ($char[$i] =~ /\A \$\$ \z/oxms) {
7227             }
7228              
7229             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
7230             # $1, $2, $3 --> $1, $2, $3 otherwise
7231             elsif ($char[$i] =~ /\A \$ ([1-9][0-9]*) \z/oxms) {
7232 0           $char[$i] = e_capture($1);
7233 0 0         if ($ignorecase) {
7234 0           $char[$i] = '@{[Char::Ecyrillic::ignorecase(' . $char[$i] . ')]}';
7235             }
7236             }
7237             elsif ($char[$i] =~ /\A \$ \{ \s* ([1-9][0-9]*) \s* \} \z/oxms) {
7238 0           $char[$i] = e_capture($1);
7239 0 0         if ($ignorecase) {
7240 0           $char[$i] = '@{[Char::Ecyrillic::ignorecase(' . $char[$i] . ')]}';
7241             }
7242             }
7243              
7244             # $$foo[ ... ] --> $ $foo->[ ... ]
7245             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) ( \[ (?:$qq_bracket)*? \] ) \z/oxms) {
7246 0           $char[$i] = e_capture($1.'->'.$2);
7247 0 0         if ($ignorecase) {
7248 0           $char[$i] = '@{[Char::Ecyrillic::ignorecase(' . $char[$i] . ')]}';
7249             }
7250             }
7251              
7252             # $$foo{ ... } --> $ $foo->{ ... }
7253             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) ( \{ (?:$qq_brace)*? \} ) \z/oxms) {
7254 0           $char[$i] = e_capture($1.'->'.$2);
7255 0 0         if ($ignorecase) {
7256 0           $char[$i] = '@{[Char::Ecyrillic::ignorecase(' . $char[$i] . ')]}';
7257             }
7258             }
7259              
7260             # $$foo
7261             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) \z/oxms) {
7262 0           $char[$i] = e_capture($1);
7263 0 0         if ($ignorecase) {
7264 0           $char[$i] = '@{[Char::Ecyrillic::ignorecase(' . $char[$i] . ')]}';
7265             }
7266             }
7267              
7268             # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Char::Ecyrillic::PREMATCH()
7269             elsif ($char[$i] =~ /\A ( \$` | \$\{`\} | \$ \s* PREMATCH | \$ \s* \{ \s* PREMATCH \s* \} | \$ \s* \{\^PREMATCH\} ) \z/oxmsgc) {
7270 0 0         if ($ignorecase) {
7271 0           $char[$i] = '@{[Char::Ecyrillic::ignorecase(Char::Ecyrillic::PREMATCH())]}';
7272             }
7273             else {
7274 0           $char[$i] = '@{[Char::Ecyrillic::PREMATCH()]}';
7275             }
7276             }
7277              
7278             # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Char::Ecyrillic::MATCH()
7279             elsif ($char[$i] =~ /\A ( \$& | \$\{&\} | \$ \s* MATCH | \$ \s* \{ \s* MATCH \s* \} | \$ \s* \{\^MATCH\} ) \z/oxmsgc) {
7280 0 0         if ($ignorecase) {
7281 0           $char[$i] = '@{[Char::Ecyrillic::ignorecase(Char::Ecyrillic::MATCH())]}';
7282             }
7283             else {
7284 0           $char[$i] = '@{[Char::Ecyrillic::MATCH()]}';
7285             }
7286             }
7287              
7288             # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Char::Ecyrillic::POSTMATCH()
7289             elsif ($char[$i] =~ /\A ( \$ \s* POSTMATCH | \$ \s* \{ \s* POSTMATCH \s* \} | \$ \s* \{\^POSTMATCH\} ) \z/oxmsgc) {
7290 0 0         if ($ignorecase) {
7291 0           $char[$i] = '@{[Char::Ecyrillic::ignorecase(Char::Ecyrillic::POSTMATCH())]}';
7292             }
7293             else {
7294 0           $char[$i] = '@{[Char::Ecyrillic::POSTMATCH()]}';
7295             }
7296             }
7297              
7298             # ${ foo }
7299             elsif ($char[$i] =~ /\A \$ \s* \{ ( \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* ) \} \z/oxms) {
7300 0 0         if ($ignorecase) {
7301 0           $char[$i] = '@{[Char::Ecyrillic::ignorecase(' . $1 . ')]}';
7302             }
7303             }
7304              
7305             # ${ ... }
7306             elsif ($char[$i] =~ /\A \$ \s* \{ \s* ( .+ ) \s* \} \z/oxms) {
7307 0           $char[$i] = e_capture($1);
7308 0 0         if ($ignorecase) {
7309 0           $char[$i] = '@{[Char::Ecyrillic::ignorecase(' . $char[$i] . ')]}';
7310             }
7311             }
7312              
7313             # $scalar or @array
7314             elsif ($char[$i] =~ /\A [\$\@].+ /oxms) {
7315 0           $char[$i] = e_string($char[$i]);
7316 0 0         if ($ignorecase) {
7317 0           $char[$i] = '@{[Char::Ecyrillic::ignorecase(' . $char[$i] . ')]}';
7318             }
7319             }
7320              
7321             # quote character before ? + * {
7322             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
7323 0 0         if ($char[$i-1] =~ /\A (?:\\[0-7]{2,3}|\\x[0-9-A-Fa-f]{1,2}) \z/oxms) {
7324             }
7325             else {
7326 0           $char[$i-1] = '(?:' . $char[$i-1] . ')';
7327             }
7328             }
7329             }
7330              
7331             # make regexp string
7332 0           $modifier =~ tr/i//d;
7333 0 0         if ($left_e > $right_e) {
7334 0           return join '', 'Char::Ecyrillic::split', $ope, $delimiter, @char, '>]}' x ($left_e - $right_e), $end_delimiter, $modifier;
7335             }
7336 0           return join '', 'Char::Ecyrillic::split', $ope, $delimiter, @char, $end_delimiter, $modifier;
7337             }
7338              
7339             #
7340             # escape regexp of split qr''
7341             #
7342             sub e_split_q {
7343 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
7344 0   0       $modifier ||= '';
7345              
7346 0           $modifier =~ tr/p//d;
7347 0 0         if ($modifier =~ /([adlu])/oxms) {
7348 0           my $line = 0;
7349 0           for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
7350 0 0         if ($filename ne __FILE__) {
7351 0           $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
7352 0           last;
7353             }
7354             }
7355 0           die qq{Unsupported modifier "$1" used at line $line.\n};
7356             }
7357              
7358 0           $slash = 'div';
7359              
7360             # /b /B modifier
7361 0 0         if ($modifier =~ tr/bB//d) {
7362 0           return join '', 'split', $ope, $delimiter, $string, $end_delimiter, $modifier;
7363             }
7364              
7365 0 0         my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
7366              
7367             # split regexp
7368 0           my @char = $string =~ /\G(
7369             \[\:\^ [a-z]+ \:\] |
7370             \[\: [a-z]+ \:\] |
7371             \[\^ |
7372             \\? (?:$q_char)
7373             )/oxmsg;
7374              
7375             # unescape character
7376 0           for (my $i=0; $i <= $#char; $i++) {
7377 0 0 0       if (0) {
    0 0        
    0 0        
    0 0        
    0          
    0          
7378             }
7379              
7380             # open character class [...]
7381 0           elsif ($char[$i] eq '[') {
7382 0           my $left = $i;
7383 0 0         if ($char[$i+1] eq ']') {
7384 0           $i++;
7385             }
7386 0           while (1) {
7387 0 0         if (++$i > $#char) {
7388 0           die __FILE__, ": Unmatched [] in regexp";
7389             }
7390 0 0         if ($char[$i] eq ']') {
7391 0           my $right = $i;
7392              
7393             # [...]
7394 0           splice @char, $left, $right-$left+1, Char::Ecyrillic::charlist_qr(@char[$left+1..$right-1], $modifier);
7395              
7396 0           $i = $left;
7397 0           last;
7398             }
7399             }
7400             }
7401              
7402             # open character class [^...]
7403             elsif ($char[$i] eq '[^') {
7404 0           my $left = $i;
7405 0 0         if ($char[$i+1] eq ']') {
7406 0           $i++;
7407             }
7408 0           while (1) {
7409 0 0         if (++$i > $#char) {
7410 0           die __FILE__, ": Unmatched [] in regexp";
7411             }
7412 0 0         if ($char[$i] eq ']') {
7413 0           my $right = $i;
7414              
7415             # [^...]
7416 0           splice @char, $left, $right-$left+1, Char::Ecyrillic::charlist_not_qr(@char[$left+1..$right-1], $modifier);
7417              
7418 0           $i = $left;
7419 0           last;
7420             }
7421             }
7422             }
7423              
7424             # rewrite character class or escape character
7425             elsif (my $char = character_class($char[$i],$modifier)) {
7426 0           $char[$i] = $char;
7427             }
7428              
7429             # split(m/^/) --> split(m/^/m)
7430             elsif (($char[$i] eq '^') and ($modifier !~ /m/oxms)) {
7431 0           $modifier .= 'm';
7432             }
7433              
7434             # /i modifier
7435             elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Char::Ecyrillic::uc($char[$i]) ne Char::Ecyrillic::fc($char[$i]))) {
7436 0 0         if (CORE::length(Char::Ecyrillic::fc($char[$i])) == 1) {
7437 0           $char[$i] = '[' . Char::Ecyrillic::uc($char[$i]) . Char::Ecyrillic::fc($char[$i]) . ']';
7438             }
7439             else {
7440 0           $char[$i] = '(?:' . Char::Ecyrillic::uc($char[$i]) . '|' . Char::Ecyrillic::fc($char[$i]) . ')';
7441             }
7442             }
7443              
7444             # quote character before ? + * {
7445             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
7446 0 0         if ($char[$i-1] =~ /\A [\x00-\xFF] \z/oxms) {
7447             }
7448             else {
7449 0           $char[$i-1] = '(?:' . $char[$i-1] . ')';
7450             }
7451             }
7452             }
7453              
7454 0           $modifier =~ tr/i//d;
7455 0           return join '', 'Char::Ecyrillic::split', $ope, $delimiter, @char, $end_delimiter, $modifier;
7456             }
7457              
7458             #
7459             # instead of Carp::carp
7460             #
7461             sub carp {
7462 0     0 0   my($package,$filename,$line) = caller(1);
7463 0           print STDERR "@_ at $filename line $line.\n";
7464             }
7465              
7466             #
7467             # instead of Carp::croak
7468             #
7469             sub croak {
7470 0     0 0   my($package,$filename,$line) = caller(1);
7471 0           print STDERR "@_ at $filename line $line.\n";
7472 0           die "\n";
7473             }
7474              
7475             #
7476             # instead of Carp::cluck
7477             #
7478             sub cluck {
7479 0     0 0   my $i = 0;
7480 0           my @cluck = ();
7481 0           while (my($package,$filename,$line,$subroutine) = caller($i)) {
7482 0           push @cluck, "[$i] $filename($line) $package::$subroutine\n";
7483 0           $i++;
7484             }
7485 0           print STDERR CORE::reverse @cluck;
7486 0           print STDERR "\n";
7487 0           carp @_;
7488             }
7489              
7490             #
7491             # instead of Carp::confess
7492             #
7493             sub confess {
7494 0     0 0   my $i = 0;
7495 0           my @confess = ();
7496 0           while (my($package,$filename,$line,$subroutine) = caller($i)) {
7497 0           push @confess, "[$i] $filename($line) $package::$subroutine\n";
7498 0           $i++;
7499             }
7500 0           print STDERR CORE::reverse @confess;
7501 0           print STDERR "\n";
7502 0           croak @_;
7503             }
7504              
7505             1;
7506              
7507             __END__