File Coverage

blib/lib/Ecyrillic.pm
Criterion Covered Total %
statement 865 3080 28.0
branch 944 2674 35.3
condition 99 373 26.5
subroutine 67 125 53.6
pod 7 74 9.4
total 1982 6326 31.3


line stmt bran cond sub pod time code
1             package Ecyrillic;
2             ######################################################################
3             #
4             # Ecyrillic - Run-time routines for Cyrillic.pm
5             #
6             # http://search.cpan.org/dist/Char-Cyrillic/
7             #
8             # Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 INABA Hitoshi
9             ######################################################################
10              
11 200     200   2959 use 5.00503; # Galapagos Consensus 1998 for primetools
  200         490  
12             # use 5.008001; # Lancaster Consensus 2013 for toolchains
13              
14             # 12.3. Delaying use Until Runtime
15             # in Chapter 12. Packages, Libraries, and Modules
16             # of ISBN 0-596-00313-7 Perl Cookbook, 2nd Edition.
17             # (and so on)
18              
19             # Version numbers should be boring
20             # http://www.dagolden.com/index.php/369/version-numbers-should-be-boring/
21             # For the impatient, the disinterested or those who just want to follow
22             # a recipe, my advice for all modules is this:
23             # our $VERSION = "0.001"; # or "0.001_001" for a dev release
24             # $VERSION = eval $VERSION;
25              
26 200     200   11149 BEGIN { CORE::eval q{ use vars qw($VERSION) } }
  200     200   901  
  200         256  
  200         28320  
27             $VERSION = '1.08';
28             $VERSION = CORE::eval $VERSION;
29              
30             BEGIN {
31 200 50   200   1042 if ($^X =~ / jperl /oxmsi) {
32 0         0 die __FILE__, ": needs perl(not jperl) 5.00503 or later. (\$^X==$^X)\n";
33             }
34 200         251 if (CORE::ord('A') == 193) {
35             die __FILE__, ": is not US-ASCII script (may be EBCDIC or EBCDIK script).\n";
36             }
37 200         22061 if (CORE::ord('A') != 0x41) {
38             die __FILE__, ": is not US-ASCII script (must be US-ASCII script).\n";
39             }
40             }
41              
42             BEGIN {
43              
44             # instead of utf8.pm
45 200     200   11310 CORE::eval q{
  200     200   897  
  200     65   262  
  200         19518  
  55         4374  
  61         4926  
  41         3338  
  43         3467  
46             no warnings qw(redefine);
47             *utf8::upgrade = sub { CORE::length $_[0] };
48             *utf8::downgrade = sub { 1 };
49             *utf8::encode = sub { };
50             *utf8::decode = sub { 1 };
51             *utf8::is_utf8 = sub { };
52             *utf8::valid = sub { 1 };
53             };
54 200 50       86721 if ($@) {
55 0         0 *utf8::upgrade = sub { CORE::length $_[0] };
  0         0  
56 0         0 *utf8::downgrade = sub { 1 };
  0         0  
57 0         0 *utf8::encode = sub { };
58 0         0 *utf8::decode = sub { 1 };
  0         0  
59 0         0 *utf8::is_utf8 = sub { };
60 0         0 *utf8::valid = sub { 1 };
  0         0  
61             }
62             }
63              
64             # instead of Symbol.pm
65 0         0 BEGIN {
66 200     200   485 my $genpkg = "Symbol::";
67 200         7546 my $genseq = 0;
68              
69             sub gensym () {
70 0     0 0 0 my $name = "GEN" . $genseq++;
71              
72             # here, no strict qw(refs); if strict.pm exists
73              
74 0         0 my $ref = \*{$genpkg . $name};
  0         0  
75 0         0 delete $$genpkg{$name};
76 0         0 return $ref;
77             }
78              
79             sub qualify ($;$) {
80 0     0 0 0 my ($name) = @_;
81 0 0 0     0 if (!ref($name) && (Ecyrillic::index($name, '::') == -1) && (Ecyrillic::index($name, "'") == -1)) {
      0        
82 0         0 my $pkg;
83 0         0 my %global = map {$_ => 1} qw(ARGV ARGVOUT ENV INC SIG STDERR STDIN STDOUT DATA);
  0         0  
84              
85             # Global names: special character, "^xyz", or other.
86 0 0 0     0 if ($name =~ /^(([^a-z])|(\^[a-z_]+))\z/i || $global{$name}) {
87             # RGS 2001-11-05 : translate leading ^X to control-char
88 0         0 $name =~ s/^\^([a-z_])/'qq(\c'.$1.')'/eei;
  0         0  
89 0         0 $pkg = "main";
90             }
91             else {
92 0 0       0 $pkg = (@_ > 1) ? $_[1] : caller;
93             }
94 0         0 $name = $pkg . "::" . $name;
95             }
96 0         0 return $name;
97             }
98              
99             sub qualify_to_ref ($;$) {
100              
101             # here, no strict qw(refs); if strict.pm exists
102              
103 0 0   0 0 0 return \*{ qualify $_[0], @_ > 1 ? $_[1] : caller };
  0         0  
104             }
105             }
106              
107             # Column: local $@
108             # in Chapter 9. Osaete okitai Perl no kiso
109             # of ISBN 10: 4798119172 | ISBN 13: 978-4798119175 MODAN Perl NYUMON
110             # (and so on)
111              
112             # use strict; if strict.pm exists
113             BEGIN {
114 200 50   200   330 if (CORE::eval { local $@; CORE::require strict }) {
  200         289  
  200         1762  
115 200         18581 strict::->import;
116             }
117             }
118              
119             # P.714 29.2.39. flock
120             # in Chapter 29: Functions
121             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
122              
123             # P.863 flock
124             # in Chapter 27: Functions
125             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
126              
127             sub LOCK_SH() {1}
128             sub LOCK_EX() {2}
129             sub LOCK_UN() {8}
130             sub LOCK_NB() {4}
131              
132             # instead of Carp.pm
133             sub carp;
134             sub croak;
135             sub cluck;
136             sub confess;
137              
138             # 6.18. Matching Multiple-Byte Characters
139             # in Chapter 6. Pattern Matching
140             # of ISBN 978-1-56592-243-3 Perl Perl Cookbook.
141             # (and so on)
142              
143             # regexp of character
144 200     200   12174 BEGIN { CORE::eval q{ use vars qw($your_char) } } $your_char = q{[\x00-\xFF]};
  200     200   913  
  200         234  
  200         9845  
145 200     200   10538 BEGIN { CORE::eval q{ use vars qw($qq_char ) } } $qq_char = qr/\\c[\x40-\x5F]|\\?(?:$your_char)/oxms;
  200     200   828  
  200         246  
  200         10436  
146 200     200   10293 BEGIN { CORE::eval q{ use vars qw($q_char ) } } $q_char = qr/$your_char/oxms;
  200     200   827  
  200         258  
  200         11809  
147              
148             #
149             # Cyrillic character range per length
150             #
151             my %range_tr = ();
152              
153             #
154             # alias of encoding name
155             #
156 200     200   10496 BEGIN { CORE::eval q{ use vars qw($encoding_alias) } }
  200     200   807  
  200         247  
  200         320625  
157              
158             #
159             # Cyrillic case conversion
160             #
161             my %lc = ();
162             @lc{qw(A B C D E F G H I J K L M N O P Q R S T U V W X Y Z)} =
163             qw(a b c d e f g h i j k l m n o p q r s t u v w x y z);
164             my %uc = ();
165             @uc{qw(a b c d e f g h i j k l m n o p q r s t u v w x y z)} =
166             qw(A B C D E F G H I J K L M N O P Q R S T U V W X Y Z);
167             my %fc = ();
168             @fc{qw(A B C D E F G H I J K L M N O P Q R S T U V W X Y Z)} =
169             qw(a b c d e f g h i j k l m n o p q r s t u v w x y z);
170              
171             if (0) {
172             }
173              
174             elsif (__PACKAGE__ =~ / \b Ecyrillic \z/oxms) {
175             %range_tr = (
176             1 => [ [0x00..0xFF],
177             ],
178             );
179             $encoding_alias = qr/ \b (?: iso[-_ ]?8859-5 | iec[- ]?8859-5 | cyrillic ) \b /oxmsi;
180              
181             %lc = (%lc,
182             "\xA1" => "\xF1", # CYRILLIC LETTER IO
183             "\xA2" => "\xF2", # CYRILLIC LETTER DJE
184             "\xA3" => "\xF3", # CYRILLIC LETTER GJE
185             "\xA4" => "\xF4", # CYRILLIC LETTER UKRAINIAN IE
186             "\xA5" => "\xF5", # CYRILLIC LETTER DZE
187             "\xA6" => "\xF6", # CYRILLIC LETTER BYELORUSSIAN-UKRAINIAN I
188             "\xA7" => "\xF7", # CYRILLIC LETTER YI
189             "\xA8" => "\xF8", # CYRILLIC LETTER JE
190             "\xA9" => "\xF9", # CYRILLIC LETTER LJE
191             "\xAA" => "\xFA", # CYRILLIC LETTER NJE
192             "\xAB" => "\xFB", # CYRILLIC LETTER TSHE
193             "\xAC" => "\xFC", # CYRILLIC LETTER KJE
194             "\xAE" => "\xFE", # CYRILLIC LETTER SHORT U
195             "\xAF" => "\xFF", # CYRILLIC LETTER DZHE
196             "\xB0" => "\xD0", # CYRILLIC LETTER A
197             "\xB1" => "\xD1", # CYRILLIC LETTER BE
198             "\xB2" => "\xD2", # CYRILLIC LETTER VE
199             "\xB3" => "\xD3", # CYRILLIC LETTER GHE
200             "\xB4" => "\xD4", # CYRILLIC LETTER DE
201             "\xB5" => "\xD5", # CYRILLIC LETTER IE
202             "\xB6" => "\xD6", # CYRILLIC LETTER ZHE
203             "\xB7" => "\xD7", # CYRILLIC LETTER ZE
204             "\xB8" => "\xD8", # CYRILLIC LETTER I
205             "\xB9" => "\xD9", # CYRILLIC LETTER SHORT I
206             "\xBA" => "\xDA", # CYRILLIC LETTER KA
207             "\xBB" => "\xDB", # CYRILLIC LETTER EL
208             "\xBC" => "\xDC", # CYRILLIC LETTER EM
209             "\xBD" => "\xDD", # CYRILLIC LETTER EN
210             "\xBE" => "\xDE", # CYRILLIC LETTER O
211             "\xBF" => "\xDF", # CYRILLIC LETTER PE
212             "\xC0" => "\xE0", # CYRILLIC LETTER ER
213             "\xC1" => "\xE1", # CYRILLIC LETTER ES
214             "\xC2" => "\xE2", # CYRILLIC LETTER TE
215             "\xC3" => "\xE3", # CYRILLIC LETTER U
216             "\xC4" => "\xE4", # CYRILLIC LETTER EF
217             "\xC5" => "\xE5", # CYRILLIC LETTER HA
218             "\xC6" => "\xE6", # CYRILLIC LETTER TSE
219             "\xC7" => "\xE7", # CYRILLIC LETTER CHE
220             "\xC8" => "\xE8", # CYRILLIC LETTER SHA
221             "\xC9" => "\xE9", # CYRILLIC LETTER SHCHA
222             "\xCA" => "\xEA", # CYRILLIC LETTER HARD SIGN
223             "\xCB" => "\xEB", # CYRILLIC LETTER YERU
224             "\xCC" => "\xEC", # CYRILLIC LETTER SOFT SIGN
225             "\xCD" => "\xED", # CYRILLIC LETTER E
226             "\xCE" => "\xEE", # CYRILLIC LETTER YU
227             "\xCF" => "\xEF", # CYRILLIC LETTER YA
228             );
229              
230             %uc = (%uc,
231             "\xD0" => "\xB0", # CYRILLIC LETTER A
232             "\xD1" => "\xB1", # CYRILLIC LETTER BE
233             "\xD2" => "\xB2", # CYRILLIC LETTER VE
234             "\xD3" => "\xB3", # CYRILLIC LETTER GHE
235             "\xD4" => "\xB4", # CYRILLIC LETTER DE
236             "\xD5" => "\xB5", # CYRILLIC LETTER IE
237             "\xD6" => "\xB6", # CYRILLIC LETTER ZHE
238             "\xD7" => "\xB7", # CYRILLIC LETTER ZE
239             "\xD8" => "\xB8", # CYRILLIC LETTER I
240             "\xD9" => "\xB9", # CYRILLIC LETTER SHORT I
241             "\xDA" => "\xBA", # CYRILLIC LETTER KA
242             "\xDB" => "\xBB", # CYRILLIC LETTER EL
243             "\xDC" => "\xBC", # CYRILLIC LETTER EM
244             "\xDD" => "\xBD", # CYRILLIC LETTER EN
245             "\xDE" => "\xBE", # CYRILLIC LETTER O
246             "\xDF" => "\xBF", # CYRILLIC LETTER PE
247             "\xE0" => "\xC0", # CYRILLIC LETTER ER
248             "\xE1" => "\xC1", # CYRILLIC LETTER ES
249             "\xE2" => "\xC2", # CYRILLIC LETTER TE
250             "\xE3" => "\xC3", # CYRILLIC LETTER U
251             "\xE4" => "\xC4", # CYRILLIC LETTER EF
252             "\xE5" => "\xC5", # CYRILLIC LETTER HA
253             "\xE6" => "\xC6", # CYRILLIC LETTER TSE
254             "\xE7" => "\xC7", # CYRILLIC LETTER CHE
255             "\xE8" => "\xC8", # CYRILLIC LETTER SHA
256             "\xE9" => "\xC9", # CYRILLIC LETTER SHCHA
257             "\xEA" => "\xCA", # CYRILLIC LETTER HARD SIGN
258             "\xEB" => "\xCB", # CYRILLIC LETTER YERU
259             "\xEC" => "\xCC", # CYRILLIC LETTER SOFT SIGN
260             "\xED" => "\xCD", # CYRILLIC LETTER E
261             "\xEE" => "\xCE", # CYRILLIC LETTER YU
262             "\xEF" => "\xCF", # CYRILLIC LETTER YA
263             "\xF1" => "\xA1", # CYRILLIC LETTER IO
264             "\xF2" => "\xA2", # CYRILLIC LETTER DJE
265             "\xF3" => "\xA3", # CYRILLIC LETTER GJE
266             "\xF4" => "\xA4", # CYRILLIC LETTER UKRAINIAN IE
267             "\xF5" => "\xA5", # CYRILLIC LETTER DZE
268             "\xF6" => "\xA6", # CYRILLIC LETTER BYELORUSSIAN-UKRAINIAN I
269             "\xF7" => "\xA7", # CYRILLIC LETTER YI
270             "\xF8" => "\xA8", # CYRILLIC LETTER JE
271             "\xF9" => "\xA9", # CYRILLIC LETTER LJE
272             "\xFA" => "\xAA", # CYRILLIC LETTER NJE
273             "\xFB" => "\xAB", # CYRILLIC LETTER TSHE
274             "\xFC" => "\xAC", # CYRILLIC LETTER KJE
275             "\xFE" => "\xAE", # CYRILLIC LETTER SHORT U
276             "\xFF" => "\xAF", # CYRILLIC LETTER DZHE
277             );
278              
279             %fc = (%fc,
280             "\xA1" => "\xF1", # CYRILLIC CAPITAL LETTER IO --> CYRILLIC SMALL LETTER IO
281             "\xA2" => "\xF2", # CYRILLIC CAPITAL LETTER DJE --> CYRILLIC SMALL LETTER DJE
282             "\xA3" => "\xF3", # CYRILLIC CAPITAL LETTER GJE --> CYRILLIC SMALL LETTER GJE
283             "\xA4" => "\xF4", # CYRILLIC CAPITAL LETTER UKRAINIAN IE --> CYRILLIC SMALL LETTER UKRAINIAN IE
284             "\xA5" => "\xF5", # CYRILLIC CAPITAL LETTER DZE --> CYRILLIC SMALL LETTER DZE
285             "\xA6" => "\xF6", # CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I --> CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I
286             "\xA7" => "\xF7", # CYRILLIC CAPITAL LETTER YI --> CYRILLIC SMALL LETTER YI
287             "\xA8" => "\xF8", # CYRILLIC CAPITAL LETTER JE --> CYRILLIC SMALL LETTER JE
288             "\xA9" => "\xF9", # CYRILLIC CAPITAL LETTER LJE --> CYRILLIC SMALL LETTER LJE
289             "\xAA" => "\xFA", # CYRILLIC CAPITAL LETTER NJE --> CYRILLIC SMALL LETTER NJE
290             "\xAB" => "\xFB", # CYRILLIC CAPITAL LETTER TSHE --> CYRILLIC SMALL LETTER TSHE
291             "\xAC" => "\xFC", # CYRILLIC CAPITAL LETTER KJE --> CYRILLIC SMALL LETTER KJE
292             "\xAE" => "\xFE", # CYRILLIC CAPITAL LETTER SHORT U --> CYRILLIC SMALL LETTER SHORT U
293             "\xAF" => "\xFF", # CYRILLIC CAPITAL LETTER DZHE --> CYRILLIC SMALL LETTER DZHE
294             "\xB0" => "\xD0", # CYRILLIC CAPITAL LETTER A --> CYRILLIC SMALL LETTER A
295             "\xB1" => "\xD1", # CYRILLIC CAPITAL LETTER BE --> CYRILLIC SMALL LETTER BE
296             "\xB2" => "\xD2", # CYRILLIC CAPITAL LETTER VE --> CYRILLIC SMALL LETTER VE
297             "\xB3" => "\xD3", # CYRILLIC CAPITAL LETTER GHE --> CYRILLIC SMALL LETTER GHE
298             "\xB4" => "\xD4", # CYRILLIC CAPITAL LETTER DE --> CYRILLIC SMALL LETTER DE
299             "\xB5" => "\xD5", # CYRILLIC CAPITAL LETTER IE --> CYRILLIC SMALL LETTER IE
300             "\xB6" => "\xD6", # CYRILLIC CAPITAL LETTER ZHE --> CYRILLIC SMALL LETTER ZHE
301             "\xB7" => "\xD7", # CYRILLIC CAPITAL LETTER ZE --> CYRILLIC SMALL LETTER ZE
302             "\xB8" => "\xD8", # CYRILLIC CAPITAL LETTER I --> CYRILLIC SMALL LETTER I
303             "\xB9" => "\xD9", # CYRILLIC CAPITAL LETTER SHORT I --> CYRILLIC SMALL LETTER SHORT I
304             "\xBA" => "\xDA", # CYRILLIC CAPITAL LETTER KA --> CYRILLIC SMALL LETTER KA
305             "\xBB" => "\xDB", # CYRILLIC CAPITAL LETTER EL --> CYRILLIC SMALL LETTER EL
306             "\xBC" => "\xDC", # CYRILLIC CAPITAL LETTER EM --> CYRILLIC SMALL LETTER EM
307             "\xBD" => "\xDD", # CYRILLIC CAPITAL LETTER EN --> CYRILLIC SMALL LETTER EN
308             "\xBE" => "\xDE", # CYRILLIC CAPITAL LETTER O --> CYRILLIC SMALL LETTER O
309             "\xBF" => "\xDF", # CYRILLIC CAPITAL LETTER PE --> CYRILLIC SMALL LETTER PE
310             "\xC0" => "\xE0", # CYRILLIC CAPITAL LETTER ER --> CYRILLIC SMALL LETTER ER
311             "\xC1" => "\xE1", # CYRILLIC CAPITAL LETTER ES --> CYRILLIC SMALL LETTER ES
312             "\xC2" => "\xE2", # CYRILLIC CAPITAL LETTER TE --> CYRILLIC SMALL LETTER TE
313             "\xC3" => "\xE3", # CYRILLIC CAPITAL LETTER U --> CYRILLIC SMALL LETTER U
314             "\xC4" => "\xE4", # CYRILLIC CAPITAL LETTER EF --> CYRILLIC SMALL LETTER EF
315             "\xC5" => "\xE5", # CYRILLIC CAPITAL LETTER HA --> CYRILLIC SMALL LETTER HA
316             "\xC6" => "\xE6", # CYRILLIC CAPITAL LETTER TSE --> CYRILLIC SMALL LETTER TSE
317             "\xC7" => "\xE7", # CYRILLIC CAPITAL LETTER CHE --> CYRILLIC SMALL LETTER CHE
318             "\xC8" => "\xE8", # CYRILLIC CAPITAL LETTER SHA --> CYRILLIC SMALL LETTER SHA
319             "\xC9" => "\xE9", # CYRILLIC CAPITAL LETTER SHCHA --> CYRILLIC SMALL LETTER SHCHA
320             "\xCA" => "\xEA", # CYRILLIC CAPITAL LETTER HARD SIGN --> CYRILLIC SMALL LETTER HARD SIGN
321             "\xCB" => "\xEB", # CYRILLIC CAPITAL LETTER YERU --> CYRILLIC SMALL LETTER YERU
322             "\xCC" => "\xEC", # CYRILLIC CAPITAL LETTER SOFT SIGN --> CYRILLIC SMALL LETTER SOFT SIGN
323             "\xCD" => "\xED", # CYRILLIC CAPITAL LETTER E --> CYRILLIC SMALL LETTER E
324             "\xCE" => "\xEE", # CYRILLIC CAPITAL LETTER YU --> CYRILLIC SMALL LETTER YU
325             "\xCF" => "\xEF", # CYRILLIC CAPITAL LETTER YA --> CYRILLIC SMALL LETTER YA
326             );
327             }
328              
329             else {
330             croak "Don't know my package name '@{[__PACKAGE__]}'";
331             }
332              
333             #
334             # @ARGV wildcard globbing
335             #
336             sub import {
337              
338 0 0   0   0 if ($^O =~ /\A (?: MSWin32 | NetWare | symbian | dos ) \z/oxms) {
339 0         0 my @argv = ();
340 0         0 for (@ARGV) {
341              
342             # has space
343 0 0       0 if (/\A (?:$q_char)*? [ ] /oxms) {
    0          
344 0 0       0 if (my @glob = Ecyrillic::glob(qq{"$_"})) {
345 0         0 push @argv, @glob;
346             }
347             else {
348 0         0 push @argv, $_;
349             }
350             }
351              
352             # has wildcard metachar
353             elsif (/\A (?:$q_char)*? [*?] /oxms) {
354 0 0       0 if (my @glob = Ecyrillic::glob($_)) {
355 0         0 push @argv, @glob;
356             }
357             else {
358 0         0 push @argv, $_;
359             }
360             }
361              
362             # no wildcard globbing
363             else {
364 0         0 push @argv, $_;
365             }
366             }
367 0         0 @ARGV = @argv;
368             }
369              
370 0         0 *Char::ord = \&Cyrillic::ord;
371 0         0 *Char::ord_ = \&Cyrillic::ord_;
372 0         0 *Char::reverse = \&Cyrillic::reverse;
373 0         0 *Char::getc = \&Cyrillic::getc;
374 0         0 *Char::length = \&Cyrillic::length;
375 0         0 *Char::substr = \&Cyrillic::substr;
376 0         0 *Char::index = \&Cyrillic::index;
377 0         0 *Char::rindex = \&Cyrillic::rindex;
378 0         0 *Char::eval = \&Cyrillic::eval;
379 0         0 *Char::escape = \&Cyrillic::escape;
380 0         0 *Char::escape_token = \&Cyrillic::escape_token;
381 0         0 *Char::escape_script = \&Cyrillic::escape_script;
382             }
383              
384             # P.230 Care with Prototypes
385             # in Chapter 6: Subroutines
386             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
387             #
388             # If you aren't careful, you can get yourself into trouble with prototypes.
389             # But if you are careful, you can do a lot of neat things with them. This is
390             # all very powerful, of course, and should only be used in moderation to make
391             # the world a better place.
392              
393             # P.332 Care with Prototypes
394             # in Chapter 7: Subroutines
395             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
396             #
397             # If you aren't careful, you can get yourself into trouble with prototypes.
398             # But if you are careful, you can do a lot of neat things with them. This is
399             # all very powerful, of course, and should only be used in moderation to make
400             # the world a better place.
401              
402             #
403             # Prototypes of subroutines
404             #
405       0     sub unimport {}
406             sub Ecyrillic::split(;$$$);
407             sub Ecyrillic::tr($$$$;$);
408             sub Ecyrillic::chop(@);
409             sub Ecyrillic::index($$;$);
410             sub Ecyrillic::rindex($$;$);
411             sub Ecyrillic::lcfirst(@);
412             sub Ecyrillic::lcfirst_();
413             sub Ecyrillic::lc(@);
414             sub Ecyrillic::lc_();
415             sub Ecyrillic::ucfirst(@);
416             sub Ecyrillic::ucfirst_();
417             sub Ecyrillic::uc(@);
418             sub Ecyrillic::uc_();
419             sub Ecyrillic::fc(@);
420             sub Ecyrillic::fc_();
421             sub Ecyrillic::ignorecase;
422             sub Ecyrillic::classic_character_class;
423             sub Ecyrillic::capture;
424             sub Ecyrillic::chr(;$);
425             sub Ecyrillic::chr_();
426             sub Ecyrillic::glob($);
427             sub Ecyrillic::glob_();
428              
429             sub Cyrillic::ord(;$);
430             sub Cyrillic::ord_();
431             sub Cyrillic::reverse(@);
432             sub Cyrillic::getc(;*@);
433             sub Cyrillic::length(;$);
434             sub Cyrillic::substr($$;$$);
435             sub Cyrillic::index($$;$);
436             sub Cyrillic::rindex($$;$);
437             sub Cyrillic::escape(;$);
438              
439             #
440             # Regexp work
441             #
442 200     200   14291 BEGIN { CORE::eval q{ use vars qw(
  200     200   1002  
  200         277  
  200         62738  
443             $Cyrillic::re_a
444             $Cyrillic::re_t
445             $Cyrillic::re_n
446             $Cyrillic::re_r
447             ) } }
448              
449             #
450             # Character class
451             #
452 200     200   13146 BEGIN { CORE::eval q{ use vars qw(
  200     200   910  
  200         266  
  200         2130548  
453             $dot
454             $dot_s
455             $eD
456             $eS
457             $eW
458             $eH
459             $eV
460             $eR
461             $eN
462             $not_alnum
463             $not_alpha
464             $not_ascii
465             $not_blank
466             $not_cntrl
467             $not_digit
468             $not_graph
469             $not_lower
470             $not_lower_i
471             $not_print
472             $not_punct
473             $not_space
474             $not_upper
475             $not_upper_i
476             $not_word
477             $not_xdigit
478             $eb
479             $eB
480             ) } }
481              
482             ${Ecyrillic::dot} = qr{(?>[^\x0A])};
483             ${Ecyrillic::dot_s} = qr{(?>[\x00-\xFF])};
484             ${Ecyrillic::eD} = qr{(?>[^0-9])};
485              
486             # Vertical tabs are now whitespace
487             # \s in a regex now matches a vertical tab in all circumstances.
488             # http://search.cpan.org/dist/perl-5.18.0/pod/perldelta.pod#Vertical_tabs_are_now_whitespace
489             # ${Ecyrillic::eS} = qr{(?>[^\x09\x0A \x0C\x0D\x20])};
490             # ${Ecyrillic::eS} = qr{(?>[^\x09\x0A\x0B\x0C\x0D\x20])};
491             ${Ecyrillic::eS} = qr{(?>[^\s])};
492              
493             ${Ecyrillic::eW} = qr{(?>[^0-9A-Z_a-z])};
494             ${Ecyrillic::eH} = qr{(?>[^\x09\x20])};
495             ${Ecyrillic::eV} = qr{(?>[^\x0A\x0B\x0C\x0D])};
496             ${Ecyrillic::eR} = qr{(?>\x0D\x0A|[\x0A\x0D])};
497             ${Ecyrillic::eN} = qr{(?>[^\x0A])};
498             ${Ecyrillic::not_alnum} = qr{(?>[^\x30-\x39\x41-\x5A\x61-\x7A])};
499             ${Ecyrillic::not_alpha} = qr{(?>[^\x41-\x5A\x61-\x7A])};
500             ${Ecyrillic::not_ascii} = qr{(?>[^\x00-\x7F])};
501             ${Ecyrillic::not_blank} = qr{(?>[^\x09\x20])};
502             ${Ecyrillic::not_cntrl} = qr{(?>[^\x00-\x1F\x7F])};
503             ${Ecyrillic::not_digit} = qr{(?>[^\x30-\x39])};
504             ${Ecyrillic::not_graph} = qr{(?>[^\x21-\x7F])};
505             ${Ecyrillic::not_lower} = qr{(?>[^\x61-\x7A])};
506             ${Ecyrillic::not_lower_i} = qr{(?>[^\x41-\x5A\x61-\x7A])}; # Perl 5.16 compatible
507             # ${Ecyrillic::not_lower_i} = qr{(?>[\x00-\xFF])}; # older Perl compatible
508             ${Ecyrillic::not_print} = qr{(?>[^\x20-\x7F])};
509             ${Ecyrillic::not_punct} = qr{(?>[^\x21-\x2F\x3A-\x3F\x40\x5B-\x5F\x60\x7B-\x7E])};
510             ${Ecyrillic::not_space} = qr{(?>[^\s\x0B])};
511             ${Ecyrillic::not_upper} = qr{(?>[^\x41-\x5A])};
512             ${Ecyrillic::not_upper_i} = qr{(?>[^\x41-\x5A\x61-\x7A])}; # Perl 5.16 compatible
513             # ${Ecyrillic::not_upper_i} = qr{(?>[\x00-\xFF])}; # older Perl compatible
514             ${Ecyrillic::not_word} = qr{(?>[^\x30-\x39\x41-\x5A\x5F\x61-\x7A])};
515             ${Ecyrillic::not_xdigit} = qr{(?>[^\x30-\x39\x41-\x46\x61-\x66])};
516             ${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))};
517             ${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]))};
518              
519             # avoid: Name "Ecyrillic::foo" used only once: possible typo at here.
520             ${Ecyrillic::dot} = ${Ecyrillic::dot};
521             ${Ecyrillic::dot_s} = ${Ecyrillic::dot_s};
522             ${Ecyrillic::eD} = ${Ecyrillic::eD};
523             ${Ecyrillic::eS} = ${Ecyrillic::eS};
524             ${Ecyrillic::eW} = ${Ecyrillic::eW};
525             ${Ecyrillic::eH} = ${Ecyrillic::eH};
526             ${Ecyrillic::eV} = ${Ecyrillic::eV};
527             ${Ecyrillic::eR} = ${Ecyrillic::eR};
528             ${Ecyrillic::eN} = ${Ecyrillic::eN};
529             ${Ecyrillic::not_alnum} = ${Ecyrillic::not_alnum};
530             ${Ecyrillic::not_alpha} = ${Ecyrillic::not_alpha};
531             ${Ecyrillic::not_ascii} = ${Ecyrillic::not_ascii};
532             ${Ecyrillic::not_blank} = ${Ecyrillic::not_blank};
533             ${Ecyrillic::not_cntrl} = ${Ecyrillic::not_cntrl};
534             ${Ecyrillic::not_digit} = ${Ecyrillic::not_digit};
535             ${Ecyrillic::not_graph} = ${Ecyrillic::not_graph};
536             ${Ecyrillic::not_lower} = ${Ecyrillic::not_lower};
537             ${Ecyrillic::not_lower_i} = ${Ecyrillic::not_lower_i};
538             ${Ecyrillic::not_print} = ${Ecyrillic::not_print};
539             ${Ecyrillic::not_punct} = ${Ecyrillic::not_punct};
540             ${Ecyrillic::not_space} = ${Ecyrillic::not_space};
541             ${Ecyrillic::not_upper} = ${Ecyrillic::not_upper};
542             ${Ecyrillic::not_upper_i} = ${Ecyrillic::not_upper_i};
543             ${Ecyrillic::not_word} = ${Ecyrillic::not_word};
544             ${Ecyrillic::not_xdigit} = ${Ecyrillic::not_xdigit};
545             ${Ecyrillic::eb} = ${Ecyrillic::eb};
546             ${Ecyrillic::eB} = ${Ecyrillic::eB};
547              
548             #
549             # Cyrillic split
550             #
551             sub Ecyrillic::split(;$$$) {
552              
553             # P.794 29.2.161. split
554             # in Chapter 29: Functions
555             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
556              
557             # P.951 split
558             # in Chapter 27: Functions
559             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
560              
561 0     0 0 0 my $pattern = $_[0];
562 0         0 my $string = $_[1];
563 0         0 my $limit = $_[2];
564              
565             # if $pattern is also omitted or is the literal space, " "
566 0 0       0 if (not defined $pattern) {
567 0         0 $pattern = ' ';
568             }
569              
570             # if $string is omitted, the function splits the $_ string
571 0 0       0 if (not defined $string) {
572 0 0       0 if (defined $_) {
573 0         0 $string = $_;
574             }
575             else {
576 0         0 $string = '';
577             }
578             }
579              
580 0         0 my @split = ();
581              
582             # when string is empty
583 0 0       0 if ($string eq '') {
    0          
584              
585             # resulting list value in list context
586 0 0       0 if (wantarray) {
587 0         0 return @split;
588             }
589              
590             # count of substrings in scalar context
591             else {
592 0 0       0 carp "Use of implicit split to \@_ is deprecated" if $^W;
593 0         0 @_ = @split;
594 0         0 return scalar @_;
595             }
596             }
597              
598             # split's first argument is more consistently interpreted
599             #
600             # After some changes earlier in v5.17, split's behavior has been simplified:
601             # if the PATTERN argument evaluates to a string containing one space, it is
602             # treated the way that a literal string containing one space once was.
603             # http://search.cpan.org/dist/perl-5.18.0/pod/perldelta.pod#split's_first_argument_is_more_consistently_interpreted
604              
605             # if $pattern is also omitted or is the literal space, " ", the function splits
606             # on whitespace, /\s+/, after skipping any leading whitespace
607             # (and so on)
608              
609             elsif ($pattern eq ' ') {
610 0 0       0 if (not defined $limit) {
611 0         0 return CORE::split(' ', $string);
612             }
613             else {
614 0         0 return CORE::split(' ', $string, $limit);
615             }
616             }
617              
618             # if $limit is negative, it is treated as if an arbitrarily large $limit has been specified
619 0 0 0     0 if ((not defined $limit) or ($limit <= 0)) {
    0          
620              
621             # a pattern capable of matching either the null string or something longer than the
622             # null string will split the value of $string into separate characters wherever it
623             # matches the null string between characters
624             # (and so on)
625              
626 0 0       0 if ('' =~ / \A $pattern \z /xms) {
627 0         0 my $last_subexpression_offsets = _last_subexpression_offsets($pattern);
628 0         0 my $limit = scalar(() = $string =~ /($pattern)/oxmsg);
629              
630             # P.1024 Appendix W.10 Multibyte Processing
631             # of ISBN 1-56592-224-7 CJKV Information Processing
632             # (and so on)
633              
634             # the //m modifier is assumed when you split on the pattern /^/
635             # (and so on)
636              
637             # V
638 0   0     0 while ((--$limit > 0) and ($string =~ s/\A((?:$q_char)+?)$pattern//m)) {
639              
640             # if the $pattern contains parentheses, then the substring matched by each pair of parentheses
641             # is included in the resulting list, interspersed with the fields that are ordinarily returned
642             # (and so on)
643              
644 0         0 local $@;
645 0         0 for (my $digit=1; $digit <= ($last_subexpression_offsets + 1); $digit++) {
646 0         0 push @split, CORE::eval('$' . $digit);
647             }
648             }
649             }
650              
651             else {
652 0         0 my $last_subexpression_offsets = _last_subexpression_offsets($pattern);
653              
654             # V
655 0         0 while ($string =~ s/\A((?:$q_char)*?)$pattern//m) {
656 0         0 local $@;
657 0         0 for (my $digit=1; $digit <= ($last_subexpression_offsets + 1); $digit++) {
658 0         0 push @split, CORE::eval('$' . $digit);
659             }
660             }
661             }
662             }
663              
664             elsif ($limit > 0) {
665 0 0       0 if ('' =~ / \A $pattern \z /xms) {
666 0         0 my $last_subexpression_offsets = _last_subexpression_offsets($pattern);
667 0   0     0 while ((--$limit > 0) and (CORE::length($string) > 0)) {
668              
669             # V
670 0 0       0 if ($string =~ s/\A((?:$q_char)+?)$pattern//m) {
671 0         0 local $@;
672 0         0 for (my $digit=1; $digit <= ($last_subexpression_offsets + 1); $digit++) {
673 0         0 push @split, CORE::eval('$' . $digit);
674             }
675             }
676             }
677             }
678             else {
679 0         0 my $last_subexpression_offsets = _last_subexpression_offsets($pattern);
680 0   0     0 while ((--$limit > 0) and (CORE::length($string) > 0)) {
681              
682             # V
683 0 0       0 if ($string =~ s/\A((?:$q_char)*?)$pattern//m) {
684 0         0 local $@;
685 0         0 for (my $digit=1; $digit <= ($last_subexpression_offsets + 1); $digit++) {
686 0         0 push @split, CORE::eval('$' . $digit);
687             }
688             }
689             }
690             }
691             }
692              
693 0 0       0 if (CORE::length($string) > 0) {
694 0         0 push @split, $string;
695             }
696              
697             # if $_[2] (NOT "$limit") is omitted or zero, trailing null fields are stripped from the result
698 0 0 0     0 if ((not defined $_[2]) or ($_[2] == 0)) {
699 0   0     0 while ((scalar(@split) >= 1) and ($split[-1] eq '')) {
700 0         0 pop @split;
701             }
702             }
703              
704             # resulting list value in list context
705 0 0       0 if (wantarray) {
706 0         0 return @split;
707             }
708              
709             # count of substrings in scalar context
710             else {
711 0 0       0 carp "Use of implicit split to \@_ is deprecated" if $^W;
712 0         0 @_ = @split;
713 0         0 return scalar @_;
714             }
715             }
716              
717             #
718             # get last subexpression offsets
719             #
720             sub _last_subexpression_offsets {
721 0     0   0 my $pattern = $_[0];
722              
723             # remove comment
724 0         0 $pattern =~ s/\(\?\# .*? \)//oxmsg;
725              
726 0         0 my $modifier = '';
727 0 0       0 if ($pattern =~ /\(\?\^? ([\-A-Za-z]+) :/oxms) {
728 0         0 $modifier = $1;
729 0         0 $modifier =~ s/-[A-Za-z]*//;
730             }
731              
732             # with /x modifier
733 0         0 my @char = ();
734 0 0       0 if ($modifier =~ /x/oxms) {
735 0         0 @char = $pattern =~ /\G((?>
736             [^\\\#\[\(] |
737             \\ $q_char |
738             \# (?>[^\n]*) $ |
739             \[ (?>(?:[^\\\]]|\\\\|\\\]|$q_char)+) \] |
740             \(\? |
741             $q_char
742             ))/oxmsg;
743             }
744              
745             # without /x modifier
746             else {
747 0         0 @char = $pattern =~ /\G((?>
748             [^\\\[\(] |
749             \\ $q_char |
750             \[ (?>(?:[^\\\]]|\\\\|\\\]|$q_char)+) \] |
751             \(\? |
752             $q_char
753             ))/oxmsg;
754             }
755              
756 0         0 return scalar grep { $_ eq '(' } @char;
  0         0  
757             }
758              
759             #
760             # Cyrillic transliteration (tr///)
761             #
762             sub Ecyrillic::tr($$$$;$) {
763              
764 0     0 0 0 my $bind_operator = $_[1];
765 0         0 my $searchlist = $_[2];
766 0         0 my $replacementlist = $_[3];
767 0   0     0 my $modifier = $_[4] || '';
768              
769 0 0       0 if ($modifier =~ /r/oxms) {
770 0 0       0 if ($bind_operator =~ / !~ /oxms) {
771 0         0 croak "Using !~ with tr///r doesn't make sense";
772             }
773             }
774              
775 0         0 my @char = $_[0] =~ /\G (?>$q_char) /oxmsg;
776 0         0 my @searchlist = _charlist_tr($searchlist);
777 0         0 my @replacementlist = _charlist_tr($replacementlist);
778              
779 0         0 my %tr = ();
780 0         0 for (my $i=0; $i <= $#searchlist; $i++) {
781 0 0       0 if (not exists $tr{$searchlist[$i]}) {
782 0 0 0     0 if (defined $replacementlist[$i] and ($replacementlist[$i] ne '')) {
    0 0        
    0          
783 0         0 $tr{$searchlist[$i]} = $replacementlist[$i];
784             }
785             elsif ($modifier =~ /d/oxms) {
786 0         0 $tr{$searchlist[$i]} = '';
787             }
788             elsif (defined $replacementlist[-1] and ($replacementlist[-1] ne '')) {
789 0         0 $tr{$searchlist[$i]} = $replacementlist[-1];
790             }
791             else {
792 0         0 $tr{$searchlist[$i]} = $searchlist[$i];
793             }
794             }
795             }
796              
797 0         0 my $tr = 0;
798 0         0 my $replaced = '';
799 0 0       0 if ($modifier =~ /c/oxms) {
800 0         0 while (defined(my $char = shift @char)) {
801 0 0       0 if (not exists $tr{$char}) {
802 0 0       0 if (defined $replacementlist[0]) {
803 0         0 $replaced .= $replacementlist[0];
804             }
805 0         0 $tr++;
806 0 0       0 if ($modifier =~ /s/oxms) {
807 0   0     0 while (@char and (not exists $tr{$char[0]})) {
808 0         0 shift @char;
809 0         0 $tr++;
810             }
811             }
812             }
813             else {
814 0         0 $replaced .= $char;
815             }
816             }
817             }
818             else {
819 0         0 while (defined(my $char = shift @char)) {
820 0 0       0 if (exists $tr{$char}) {
821 0         0 $replaced .= $tr{$char};
822 0         0 $tr++;
823 0 0       0 if ($modifier =~ /s/oxms) {
824 0   0     0 while (@char and (exists $tr{$char[0]}) and ($tr{$char[0]} eq $tr{$char})) {
      0        
825 0         0 shift @char;
826 0         0 $tr++;
827             }
828             }
829             }
830             else {
831 0         0 $replaced .= $char;
832             }
833             }
834             }
835              
836 0 0       0 if ($modifier =~ /r/oxms) {
837 0         0 return $replaced;
838             }
839             else {
840 0         0 $_[0] = $replaced;
841 0 0       0 if ($bind_operator =~ / !~ /oxms) {
842 0         0 return not $tr;
843             }
844             else {
845 0         0 return $tr;
846             }
847             }
848             }
849              
850             #
851             # Cyrillic chop
852             #
853             sub Ecyrillic::chop(@) {
854              
855 0     0 0 0 my $chop;
856 0 0       0 if (@_ == 0) {
857 0         0 my @char = /\G (?>$q_char) /oxmsg;
858 0         0 $chop = pop @char;
859 0         0 $_ = join '', @char;
860             }
861             else {
862 0         0 for (@_) {
863 0         0 my @char = /\G (?>$q_char) /oxmsg;
864 0         0 $chop = pop @char;
865 0         0 $_ = join '', @char;
866             }
867             }
868 0         0 return $chop;
869             }
870              
871             #
872             # Cyrillic index by octet
873             #
874             sub Ecyrillic::index($$;$) {
875              
876 0     0 1 0 my($str,$substr,$position) = @_;
877 0   0     0 $position ||= 0;
878 0         0 my $pos = 0;
879              
880 0         0 while ($pos < CORE::length($str)) {
881 0 0       0 if (CORE::substr($str,$pos,CORE::length($substr)) eq $substr) {
882 0 0       0 if ($pos >= $position) {
883 0         0 return $pos;
884             }
885             }
886 0 0       0 if (CORE::substr($str,$pos) =~ /\A ($q_char) /oxms) {
887 0         0 $pos += CORE::length($1);
888             }
889             else {
890 0         0 $pos += 1;
891             }
892             }
893 0         0 return -1;
894             }
895              
896             #
897             # Cyrillic reverse index
898             #
899             sub Ecyrillic::rindex($$;$) {
900              
901 0     0 0 0 my($str,$substr,$position) = @_;
902 0   0     0 $position ||= CORE::length($str) - 1;
903 0         0 my $pos = 0;
904 0         0 my $rindex = -1;
905              
906 0   0     0 while (($pos < CORE::length($str)) and ($pos <= $position)) {
907 0 0       0 if (CORE::substr($str,$pos,CORE::length($substr)) eq $substr) {
908 0         0 $rindex = $pos;
909             }
910 0 0       0 if (CORE::substr($str,$pos) =~ /\A ($q_char) /oxms) {
911 0         0 $pos += CORE::length($1);
912             }
913             else {
914 0         0 $pos += 1;
915             }
916             }
917 0         0 return $rindex;
918             }
919              
920             #
921             # Cyrillic lower case first with parameter
922             #
923             sub Ecyrillic::lcfirst(@) {
924 0 0   0 0 0 if (@_) {
925 0         0 my $s = shift @_;
926 0 0 0     0 if (@_ and wantarray) {
927 0         0 return Ecyrillic::lc(CORE::substr($s,0,1)) . CORE::substr($s,1), @_;
928             }
929             else {
930 0         0 return Ecyrillic::lc(CORE::substr($s,0,1)) . CORE::substr($s,1);
931             }
932             }
933             else {
934 0         0 return Ecyrillic::lc(CORE::substr($_,0,1)) . CORE::substr($_,1);
935             }
936             }
937              
938             #
939             # Cyrillic lower case first without parameter
940             #
941             sub Ecyrillic::lcfirst_() {
942 0     0 0 0 return Ecyrillic::lc(CORE::substr($_,0,1)) . CORE::substr($_,1);
943             }
944              
945             #
946             # Cyrillic lower case with parameter
947             #
948             sub Ecyrillic::lc(@) {
949 0 0   0 0 0 if (@_) {
950 0         0 my $s = shift @_;
951 0 0 0     0 if (@_ and wantarray) {
952 0 0       0 return join('', map {defined($lc{$_}) ? $lc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg)), @_;
  0         0  
953             }
954             else {
955 0 0       0 return join('', map {defined($lc{$_}) ? $lc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg));
  0         0  
956             }
957             }
958             else {
959 0         0 return Ecyrillic::lc_();
960             }
961             }
962              
963             #
964             # Cyrillic lower case without parameter
965             #
966             sub Ecyrillic::lc_() {
967 0     0 0 0 my $s = $_;
968 0 0       0 return join '', map {defined($lc{$_}) ? $lc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg);
  0         0  
969             }
970              
971             #
972             # Cyrillic upper case first with parameter
973             #
974             sub Ecyrillic::ucfirst(@) {
975 0 0   0 0 0 if (@_) {
976 0         0 my $s = shift @_;
977 0 0 0     0 if (@_ and wantarray) {
978 0         0 return Ecyrillic::uc(CORE::substr($s,0,1)) . CORE::substr($s,1), @_;
979             }
980             else {
981 0         0 return Ecyrillic::uc(CORE::substr($s,0,1)) . CORE::substr($s,1);
982             }
983             }
984             else {
985 0         0 return Ecyrillic::uc(CORE::substr($_,0,1)) . CORE::substr($_,1);
986             }
987             }
988              
989             #
990             # Cyrillic upper case first without parameter
991             #
992             sub Ecyrillic::ucfirst_() {
993 0     0 0 0 return Ecyrillic::uc(CORE::substr($_,0,1)) . CORE::substr($_,1);
994             }
995              
996             #
997             # Cyrillic upper case with parameter
998             #
999             sub Ecyrillic::uc(@) {
1000 174 50   174 0 244 if (@_) {
1001 174         154 my $s = shift @_;
1002 174 50 33     312 if (@_ and wantarray) {
1003 0 0       0 return join('', map {defined($uc{$_}) ? $uc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg)), @_;
  0         0  
1004             }
1005             else {
1006 174 100       465 return join('', map {defined($uc{$_}) ? $uc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg));
  174         522  
1007             }
1008             }
1009             else {
1010 0         0 return Ecyrillic::uc_();
1011             }
1012             }
1013              
1014             #
1015             # Cyrillic upper case without parameter
1016             #
1017             sub Ecyrillic::uc_() {
1018 0     0 0 0 my $s = $_;
1019 0 0       0 return join '', map {defined($uc{$_}) ? $uc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg);
  0         0  
1020             }
1021              
1022             #
1023             # Cyrillic fold case with parameter
1024             #
1025             sub Ecyrillic::fc(@) {
1026 197 50   197 0 236 if (@_) {
1027 197         177 my $s = shift @_;
1028 197 50 33     324 if (@_ and wantarray) {
1029 0 0       0 return join('', map {defined($fc{$_}) ? $fc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg)), @_;
  0         0  
1030             }
1031             else {
1032 197 100       445 return join('', map {defined($fc{$_}) ? $fc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg));
  197         997  
1033             }
1034             }
1035             else {
1036 0         0 return Ecyrillic::fc_();
1037             }
1038             }
1039              
1040             #
1041             # Cyrillic fold case without parameter
1042             #
1043             sub Ecyrillic::fc_() {
1044 0     0 0 0 my $s = $_;
1045 0 0       0 return join '', map {defined($fc{$_}) ? $fc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg);
  0         0  
1046             }
1047              
1048             #
1049             # Cyrillic regexp capture
1050             #
1051             {
1052             sub Ecyrillic::capture {
1053 0     0 1 0 return $_[0];
1054             }
1055             }
1056              
1057             #
1058             # Cyrillic regexp ignore case modifier
1059             #
1060             sub Ecyrillic::ignorecase {
1061              
1062 0     0 0 0 my @string = @_;
1063 0         0 my $metachar = qr/[\@\\|[\]{]/oxms;
1064              
1065             # ignore case of $scalar or @array
1066 0         0 for my $string (@string) {
1067              
1068             # split regexp
1069 0         0 my @char = $string =~ /\G (?>\[\^|\\$q_char|$q_char) /oxmsg;
1070              
1071             # unescape character
1072 0         0 for (my $i=0; $i <= $#char; $i++) {
1073 0 0       0 next if not defined $char[$i];
1074              
1075             # open character class [...]
1076 0 0       0 if ($char[$i] eq '[') {
    0          
    0          
    0          
1077 0         0 my $left = $i;
1078              
1079             # [] make die "unmatched [] in regexp ...\n"
1080              
1081 0 0       0 if ($char[$i+1] eq ']') {
1082 0         0 $i++;
1083             }
1084              
1085 0         0 while (1) {
1086 0 0       0 if (++$i > $#char) {
1087 0         0 croak "Unmatched [] in regexp";
1088             }
1089 0 0       0 if ($char[$i] eq ']') {
1090 0         0 my $right = $i;
1091 0         0 my @charlist = charlist_qr(@char[$left+1..$right-1], 'i');
1092              
1093             # escape character
1094 0         0 for my $char (@charlist) {
1095 0 0       0 if (0) {
1096             }
1097              
1098 0         0 elsif ($char =~ /\A [.|)] \z/oxms) {
1099 0         0 $char = '\\' . $char;
1100             }
1101             }
1102              
1103             # [...]
1104 0         0 splice @char, $left, $right-$left+1, '(?:' . join('|', @charlist) . ')';
1105              
1106 0         0 $i = $left;
1107 0         0 last;
1108             }
1109             }
1110             }
1111              
1112             # open character class [^...]
1113             elsif ($char[$i] eq '[^') {
1114 0         0 my $left = $i;
1115              
1116             # [^] make die "unmatched [] in regexp ...\n"
1117              
1118 0 0       0 if ($char[$i+1] eq ']') {
1119 0         0 $i++;
1120             }
1121              
1122 0         0 while (1) {
1123 0 0       0 if (++$i > $#char) {
1124 0         0 croak "Unmatched [] in regexp";
1125             }
1126 0 0       0 if ($char[$i] eq ']') {
1127 0         0 my $right = $i;
1128 0         0 my @charlist = charlist_not_qr(@char[$left+1..$right-1], 'i');
1129              
1130             # escape character
1131 0         0 for my $char (@charlist) {
1132 0 0       0 if (0) {
1133             }
1134              
1135 0         0 elsif ($char =~ /\A [.|)] \z/oxms) {
1136 0         0 $char = '\\' . $char;
1137             }
1138             }
1139              
1140             # [^...]
1141 0         0 splice @char, $left, $right-$left+1, '(?!' . join('|', @charlist) . ")(?:$your_char)";
1142              
1143 0         0 $i = $left;
1144 0         0 last;
1145             }
1146             }
1147             }
1148              
1149             # rewrite classic character class or escape character
1150             elsif (my $char = classic_character_class($char[$i])) {
1151 0         0 $char[$i] = $char;
1152             }
1153              
1154             # with /i modifier
1155             elsif ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) {
1156 0         0 my $uc = Ecyrillic::uc($char[$i]);
1157 0         0 my $fc = Ecyrillic::fc($char[$i]);
1158 0 0       0 if ($uc ne $fc) {
1159 0 0       0 if (CORE::length($fc) == 1) {
1160 0         0 $char[$i] = '[' . $uc . $fc . ']';
1161             }
1162             else {
1163 0         0 $char[$i] = '(?:' . $uc . '|' . $fc . ')';
1164             }
1165             }
1166             }
1167             }
1168              
1169             # characterize
1170 0         0 for (my $i=0; $i <= $#char; $i++) {
1171 0 0       0 next if not defined $char[$i];
1172              
1173 0 0       0 if (0) {
1174             }
1175              
1176             # quote character before ? + * {
1177 0 0       0 elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
1178 0 0       0 if ($char[$i-1] !~ /\A [\x00-\xFF] \z/oxms) {
1179 0         0 $char[$i-1] = '(?:' . $char[$i-1] . ')';
1180             }
1181             }
1182             }
1183              
1184 0         0 $string = join '', @char;
1185             }
1186              
1187             # make regexp string
1188 0         0 return @string;
1189             }
1190              
1191             #
1192             # classic character class ( \D \S \W \d \s \w \C \X \H \V \h \v \R \N \b \B )
1193             #
1194             sub Ecyrillic::classic_character_class {
1195 1862     1862 0 1597 my($char) = @_;
1196              
1197             return {
1198             '\D' => '${Ecyrillic::eD}',
1199             '\S' => '${Ecyrillic::eS}',
1200             '\W' => '${Ecyrillic::eW}',
1201             '\d' => '[0-9]',
1202              
1203             # Before Perl 5.6, \s only matched the five whitespace characters
1204             # tab, newline, form-feed, carriage return, and the space character
1205             # itself, which, taken together, is the character class [\t\n\f\r ].
1206              
1207             # Vertical tabs are now whitespace
1208             # \s in a regex now matches a vertical tab in all circumstances.
1209             # http://search.cpan.org/dist/perl-5.18.0/pod/perldelta.pod#Vertical_tabs_are_now_whitespace
1210             # \t \n \v \f \r space
1211             # '\s' => '[\x09\x0A \x0C\x0D\x20]',
1212             # '\s' => '[\x09\x0A\x0B\x0C\x0D\x20]',
1213             '\s' => '\s',
1214              
1215             '\w' => '[0-9A-Z_a-z]',
1216             '\C' => '[\x00-\xFF]',
1217             '\X' => 'X',
1218              
1219             # \h \v \H \V
1220              
1221             # P.114 Character Class Shortcuts
1222             # in Chapter 7: In the World of Regular Expressions
1223             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
1224              
1225             # P.357 13.2.3 Whitespace
1226             # in Chapter 13: perlrecharclass: Perl Regular Expression Character Classes
1227             # of ISBN-13: 978-1-906966-02-7 The Perl Language Reference Manual (for Perl version 5.12.1)
1228             #
1229             # 0x00009 CHARACTER TABULATION h s
1230             # 0x0000a LINE FEED (LF) vs
1231             # 0x0000b LINE TABULATION v
1232             # 0x0000c FORM FEED (FF) vs
1233             # 0x0000d CARRIAGE RETURN (CR) vs
1234             # 0x00020 SPACE h s
1235              
1236             # P.196 Table 5-9. Alphanumeric regex metasymbols
1237             # in Chapter 5. Pattern Matching
1238             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
1239              
1240             # (and so on)
1241              
1242             '\H' => '${Ecyrillic::eH}',
1243             '\V' => '${Ecyrillic::eV}',
1244             '\h' => '[\x09\x20]',
1245             '\v' => '[\x0A\x0B\x0C\x0D]',
1246             '\R' => '${Ecyrillic::eR}',
1247              
1248             # \N
1249             #
1250             # http://perldoc.perl.org/perlre.html
1251             # Character Classes and other Special Escapes
1252             # Any character but \n (experimental). Not affected by /s modifier
1253              
1254             '\N' => '${Ecyrillic::eN}',
1255              
1256             # \b \B
1257              
1258             # P.180 Boundaries: The \b and \B Assertions
1259             # in Chapter 5: Pattern Matching
1260             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
1261              
1262             # P.219 Boundaries: The \b and \B Assertions
1263             # in Chapter 5: Pattern Matching
1264             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
1265              
1266             # \b really means (?:(?<=\w)(?!\w)|(?
1267             # or (?:(?<=\A|\W)(?=\w)|(?<=\w)(?=\W|\z))
1268             '\b' => '${Ecyrillic::eb}',
1269              
1270             # \B really means (?:(?<=\w)(?=\w)|(?
1271             # or (?:(?<=\w)(?=\w)|(?<=\W)(?=\W))
1272             '\B' => '${Ecyrillic::eB}',
1273              
1274 1862   100     70921 }->{$char} || '';
1275             }
1276              
1277             #
1278             # prepare Cyrillic characters per length
1279             #
1280              
1281             # 1 octet characters
1282             my @chars1 = ();
1283             sub chars1 {
1284 0 0   0 0 0 if (@chars1) {
1285 0         0 return @chars1;
1286             }
1287 0 0       0 if (exists $range_tr{1}) {
1288 0         0 my @ranges = @{ $range_tr{1} };
  0         0  
1289 0         0 while (my @range = splice(@ranges,0,1)) {
1290 0         0 for my $oct0 (@{$range[0]}) {
  0         0  
1291 0         0 push @chars1, pack 'C', $oct0;
1292             }
1293             }
1294             }
1295 0         0 return @chars1;
1296             }
1297              
1298             # 2 octets characters
1299             my @chars2 = ();
1300             sub chars2 {
1301 0 0   0 0 0 if (@chars2) {
1302 0         0 return @chars2;
1303             }
1304 0 0       0 if (exists $range_tr{2}) {
1305 0         0 my @ranges = @{ $range_tr{2} };
  0         0  
1306 0         0 while (my @range = splice(@ranges,0,2)) {
1307 0         0 for my $oct0 (@{$range[0]}) {
  0         0  
1308 0         0 for my $oct1 (@{$range[1]}) {
  0         0  
1309 0         0 push @chars2, pack 'CC', $oct0,$oct1;
1310             }
1311             }
1312             }
1313             }
1314 0         0 return @chars2;
1315             }
1316              
1317             # 3 octets characters
1318             my @chars3 = ();
1319             sub chars3 {
1320 0 0   0 0 0 if (@chars3) {
1321 0         0 return @chars3;
1322             }
1323 0 0       0 if (exists $range_tr{3}) {
1324 0         0 my @ranges = @{ $range_tr{3} };
  0         0  
1325 0         0 while (my @range = splice(@ranges,0,3)) {
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 push @chars3, pack 'CCC', $oct0,$oct1,$oct2;
1330             }
1331             }
1332             }
1333             }
1334             }
1335 0         0 return @chars3;
1336             }
1337              
1338             # 4 octets characters
1339             my @chars4 = ();
1340             sub chars4 {
1341 0 0   0 0 0 if (@chars4) {
1342 0         0 return @chars4;
1343             }
1344 0 0       0 if (exists $range_tr{4}) {
1345 0         0 my @ranges = @{ $range_tr{4} };
  0         0  
1346 0         0 while (my @range = splice(@ranges,0,4)) {
1347 0         0 for my $oct0 (@{$range[0]}) {
  0         0  
1348 0         0 for my $oct1 (@{$range[1]}) {
  0         0  
1349 0         0 for my $oct2 (@{$range[2]}) {
  0         0  
1350 0         0 for my $oct3 (@{$range[3]}) {
  0         0  
1351 0         0 push @chars4, pack 'CCCC', $oct0,$oct1,$oct2,$oct3;
1352             }
1353             }
1354             }
1355             }
1356             }
1357             }
1358 0         0 return @chars4;
1359             }
1360              
1361             #
1362             # Cyrillic open character list for tr
1363             #
1364             sub _charlist_tr {
1365              
1366 0     0   0 local $_ = shift @_;
1367              
1368             # unescape character
1369 0         0 my @char = ();
1370 0         0 while (not /\G \z/oxmsgc) {
1371 0 0       0 if (/\G (\\0?55|\\x2[Dd]|\\-) /oxmsgc) {
    0          
    0          
    0          
    0          
    0          
    0          
1372 0         0 push @char, '\-';
1373             }
1374             elsif (/\G \\ ([0-7]{2,3}) /oxmsgc) {
1375 0         0 push @char, CORE::chr(oct $1);
1376             }
1377             elsif (/\G \\x ([0-9A-Fa-f]{1,2}) /oxmsgc) {
1378 0         0 push @char, CORE::chr(hex $1);
1379             }
1380             elsif (/\G \\c ([\x40-\x5F]) /oxmsgc) {
1381 0         0 push @char, CORE::chr(CORE::ord($1) & 0x1F);
1382             }
1383             elsif (/\G (\\ [0nrtfbae]) /oxmsgc) {
1384             push @char, {
1385             '\0' => "\0",
1386             '\n' => "\n",
1387             '\r' => "\r",
1388             '\t' => "\t",
1389             '\f' => "\f",
1390             '\b' => "\x08", # \b means backspace in character class
1391             '\a' => "\a",
1392             '\e' => "\e",
1393 0         0 }->{$1};
1394             }
1395             elsif (/\G \\ ($q_char) /oxmsgc) {
1396 0         0 push @char, $1;
1397             }
1398             elsif (/\G ($q_char) /oxmsgc) {
1399 0         0 push @char, $1;
1400             }
1401             }
1402              
1403             # join separated multiple-octet
1404 0         0 @char = join('',@char) =~ /\G (?>\\-|$q_char) /oxmsg;
1405              
1406             # unescape '-'
1407 0         0 my @i = ();
1408 0         0 for my $i (0 .. $#char) {
1409 0 0       0 if ($char[$i] eq '\-') {
    0          
1410 0         0 $char[$i] = '-';
1411             }
1412             elsif ($char[$i] eq '-') {
1413 0 0 0     0 if ((0 < $i) and ($i < $#char)) {
1414 0         0 push @i, $i;
1415             }
1416             }
1417             }
1418              
1419             # open character list (reverse for splice)
1420 0         0 for my $i (CORE::reverse @i) {
1421 0         0 my @range = ();
1422              
1423             # range error
1424 0 0 0     0 if ((CORE::length($char[$i-1]) > CORE::length($char[$i+1])) or ($char[$i-1] gt $char[$i+1])) {
1425 0         0 croak "Invalid tr/// range \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1426             }
1427              
1428             # range of multiple-octet code
1429 0 0       0 if (CORE::length($char[$i-1]) == 1) {
    0          
    0          
    0          
1430 0 0       0 if (CORE::length($char[$i+1]) == 1) {
    0          
    0          
    0          
1431 0 0       0 push @range, grep {($char[$i-1] le $_) and ($_ le $char[$i+1])} chars1();
  0         0  
1432             }
1433             elsif (CORE::length($char[$i+1]) == 2) {
1434 0         0 push @range, grep {$char[$i-1] le $_} chars1();
  0         0  
1435 0         0 push @range, grep {$_ le $char[$i+1]} chars2();
  0         0  
1436             }
1437             elsif (CORE::length($char[$i+1]) == 3) {
1438 0         0 push @range, grep {$char[$i-1] le $_} chars1();
  0         0  
1439 0         0 push @range, chars2();
1440 0         0 push @range, grep {$_ le $char[$i+1]} chars3();
  0         0  
1441             }
1442             elsif (CORE::length($char[$i+1]) == 4) {
1443 0         0 push @range, grep {$char[$i-1] le $_} chars1();
  0         0  
1444 0         0 push @range, chars2();
1445 0         0 push @range, chars3();
1446 0         0 push @range, grep {$_ le $char[$i+1]} chars4();
  0         0  
1447             }
1448             else {
1449 0         0 croak "Invalid tr/// range (over 4octets) \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1450             }
1451             }
1452             elsif (CORE::length($char[$i-1]) == 2) {
1453 0 0       0 if (CORE::length($char[$i+1]) == 2) {
    0          
    0          
1454 0 0       0 push @range, grep {($char[$i-1] le $_) and ($_ le $char[$i+1])} chars2();
  0         0  
1455             }
1456             elsif (CORE::length($char[$i+1]) == 3) {
1457 0         0 push @range, grep {$char[$i-1] le $_} chars2();
  0         0  
1458 0         0 push @range, grep {$_ le $char[$i+1]} chars3();
  0         0  
1459             }
1460             elsif (CORE::length($char[$i+1]) == 4) {
1461 0         0 push @range, grep {$char[$i-1] le $_} chars2();
  0         0  
1462 0         0 push @range, chars3();
1463 0         0 push @range, grep {$_ le $char[$i+1]} chars4();
  0         0  
1464             }
1465             else {
1466 0         0 croak "Invalid tr/// range (over 4octets) \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1467             }
1468             }
1469             elsif (CORE::length($char[$i-1]) == 3) {
1470 0 0       0 if (CORE::length($char[$i+1]) == 3) {
    0          
1471 0 0       0 push @range, grep {($char[$i-1] le $_) and ($_ le $char[$i+1])} chars3();
  0         0  
1472             }
1473             elsif (CORE::length($char[$i+1]) == 4) {
1474 0         0 push @range, grep {$char[$i-1] le $_} chars3();
  0         0  
1475 0         0 push @range, grep {$_ le $char[$i+1]} chars4();
  0         0  
1476             }
1477             else {
1478 0         0 croak "Invalid tr/// range (over 4octets) \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1479             }
1480             }
1481             elsif (CORE::length($char[$i-1]) == 4) {
1482 0 0       0 if (CORE::length($char[$i+1]) == 4) {
1483 0 0       0 push @range, grep {($char[$i-1] le $_) and ($_ le $char[$i+1])} chars4();
  0         0  
1484             }
1485             else {
1486 0         0 croak "Invalid tr/// range (over 4octets) \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1487             }
1488             }
1489             else {
1490 0         0 croak "Invalid tr/// range (over 4octets) \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1491             }
1492              
1493 0         0 splice @char, $i-1, 3, @range;
1494             }
1495              
1496 0         0 return @char;
1497             }
1498              
1499             #
1500             # Cyrillic open character class
1501             #
1502             sub _cc {
1503 0 0   0   0 if (scalar(@_) == 0) {
    0          
    0          
1504 0         0 die __FILE__, ": subroutine cc got no parameter.\n";
1505             }
1506             elsif (scalar(@_) == 1) {
1507 0         0 return sprintf('\x%02X',$_[0]);
1508             }
1509             elsif (scalar(@_) == 2) {
1510 0 0       0 if ($_[0] > $_[1]) {
    0          
    0          
1511 0         0 die __FILE__, ": subroutine cc got \$_[0] > \$_[1] parameters).\n";
1512             }
1513             elsif ($_[0] == $_[1]) {
1514 0         0 return sprintf('\x%02X',$_[0]);
1515             }
1516             elsif (($_[0]+1) == $_[1]) {
1517 0         0 return sprintf('[\\x%02X\\x%02X]',$_[0],$_[1]);
1518             }
1519             else {
1520 0         0 return sprintf('[\\x%02X-\\x%02X]',$_[0],$_[1]);
1521             }
1522             }
1523             else {
1524 0         0 die __FILE__, ": subroutine cc got 3 or more parameters (@{[scalar(@_)]} parameters).\n";
  0         0  
1525             }
1526             }
1527              
1528             #
1529             # Cyrillic octet range
1530             #
1531             sub _octets {
1532 182     182   241 my $length = shift @_;
1533              
1534 182 50       301 if ($length == 1) {
1535 182         485 my($a1) = unpack 'C', $_[0];
1536 182         269 my($z1) = unpack 'C', $_[1];
1537              
1538 182 50       349 if ($a1 > $z1) {
1539 0         0 croak 'Invalid [] range in regexp (CORE::ord(A) > CORE::ord(B)) ' . '\x' . unpack('H*',$a1) . '-\x' . unpack('H*',$z1);
1540             }
1541              
1542 182 50       457 if ($a1 == $z1) {
    50          
1543 0         0 return sprintf('\x%02X',$a1);
1544             }
1545             elsif (($a1+1) == $z1) {
1546 0         0 return sprintf('\x%02X\x%02X',$a1,$z1);
1547             }
1548             else {
1549 182         1203 return sprintf('\x%02X-\x%02X',$a1,$z1);
1550             }
1551             }
1552             else {
1553 0         0 die __FILE__, ": subroutine _octets got invalid length ($length).\n";
1554             }
1555             }
1556              
1557             #
1558             # Cyrillic range regexp
1559             #
1560             sub _range_regexp {
1561 182     182   240 my($length,$first,$last) = @_;
1562              
1563 182         224 my @range_regexp = ();
1564 182 50       428 if (not exists $range_tr{$length}) {
1565 0         0 return @range_regexp;
1566             }
1567              
1568 182         165 my @ranges = @{ $range_tr{$length} };
  182         414  
1569 182         583 while (my @range = splice(@ranges,0,$length)) {
1570 182         192 my $min = '';
1571 182         173 my $max = '';
1572 182         399 for (my $i=0; $i < $length; $i++) {
1573 182         710 $min .= pack 'C', $range[$i][0];
1574 182         448 $max .= pack 'C', $range[$i][-1];
1575             }
1576              
1577             # min___max
1578             # FIRST_____________LAST
1579             # (nothing)
1580              
1581 182 50 33     2064 if ($max lt $first) {
    50 33        
    50 33        
    50 33        
    50 33        
    0 0        
    0 0        
1582             }
1583              
1584             # **********
1585             # min_________max
1586             # FIRST_____________LAST
1587             # **********
1588              
1589             elsif (($min le $first) and ($first le $max) and ($max le $last)) {
1590 0         0 push @range_regexp, _octets($length,$first,$max,$min,$max);
1591             }
1592              
1593             # **********************
1594             # min________________max
1595             # FIRST_____________LAST
1596             # **********************
1597              
1598             elsif (($min eq $first) and ($max eq $last)) {
1599 0         0 push @range_regexp, _octets($length,$first,$last,$min,$max);
1600             }
1601              
1602             # *********
1603             # min___max
1604             # FIRST_____________LAST
1605             # *********
1606              
1607             elsif (($first le $min) and ($max le $last)) {
1608 0         0 push @range_regexp, _octets($length,$min,$max,$min,$max);
1609             }
1610              
1611             # **********************
1612             # min__________________________max
1613             # FIRST_____________LAST
1614             # **********************
1615              
1616             elsif (($min le $first) and ($last le $max)) {
1617 182         405 push @range_regexp, _octets($length,$first,$last,$min,$max);
1618             }
1619              
1620             # *********
1621             # min________max
1622             # FIRST_____________LAST
1623             # *********
1624              
1625             elsif (($first le $min) and ($min le $last) and ($last le $max)) {
1626 0         0 push @range_regexp, _octets($length,$min,$last,$min,$max);
1627             }
1628              
1629             # min___max
1630             # FIRST_____________LAST
1631             # (nothing)
1632              
1633             elsif ($last lt $min) {
1634             }
1635              
1636             else {
1637 0         0 die __FILE__, ": subroutine _range_regexp panic.\n";
1638             }
1639             }
1640              
1641 182         319 return @range_regexp;
1642             }
1643              
1644             #
1645             # Cyrillic open character list for qr and not qr
1646             #
1647             sub _charlist {
1648              
1649 358     358   474 my $modifier = pop @_;
1650 358         641 my @char = @_;
1651              
1652 358 100       722 my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
1653              
1654             # unescape character
1655 358         955 for (my $i=0; $i <= $#char; $i++) {
1656              
1657             # escape - to ...
1658 1125 100 100     10169 if ($char[$i] eq '-') {
    50          
    50          
    50          
    50          
    50          
    100          
    50          
    100          
    100          
    100          
    100          
1659 206 100 100     949 if ((0 < $i) and ($i < $#char)) {
1660 182         397 $char[$i] = '...';
1661             }
1662             }
1663              
1664             # octal escape sequence
1665             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
1666 0         0 $char[$i] = octchr($1);
1667             }
1668              
1669             # hexadecimal escape sequence
1670             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
1671 0         0 $char[$i] = hexchr($1);
1672             }
1673              
1674             # \b{...} --> b\{...}
1675             # \B{...} --> B\{...}
1676             # \N{CHARNAME} --> N\{CHARNAME}
1677             # \p{PROPERTY} --> p\{PROPERTY}
1678             # \P{PROPERTY} --> P\{PROPERTY}
1679             elsif ($char[$i] =~ /\A \\ ([bBNpP]) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
1680 0         0 $char[$i] = $1 . '\\' . $2;
1681             }
1682              
1683             # \p, \P, \X --> p, P, X
1684             elsif ($char[$i] =~ /\A \\ ( [pPX] ) \z/oxms) {
1685 0         0 $char[$i] = $1;
1686             }
1687              
1688             elsif ($char[$i] =~ /\A \\ ([0-7]{2,3}) \z/oxms) {
1689 0         0 $char[$i] = CORE::chr oct $1;
1690             }
1691             elsif ($char[$i] =~ /\A \\x ([0-9A-Fa-f]{1,2}) \z/oxms) {
1692 22         93 $char[$i] = CORE::chr hex $1;
1693             }
1694             elsif ($char[$i] =~ /\A \\c ([\x40-\x5F]) \z/oxms) {
1695 0         0 $char[$i] = CORE::chr(CORE::ord($1) & 0x1F);
1696             }
1697             elsif ($char[$i] =~ /\A (\\ [0nrtfbaedswDSWHVhvR]) \z/oxms) {
1698             $char[$i] = {
1699             '\0' => "\0",
1700             '\n' => "\n",
1701             '\r' => "\r",
1702             '\t' => "\t",
1703             '\f' => "\f",
1704             '\b' => "\x08", # \b means backspace in character class
1705             '\a' => "\a",
1706             '\e' => "\e",
1707             '\d' => '[0-9]',
1708              
1709             # Vertical tabs are now whitespace
1710             # \s in a regex now matches a vertical tab in all circumstances.
1711             # http://search.cpan.org/dist/perl-5.18.0/pod/perldelta.pod#Vertical_tabs_are_now_whitespace
1712             # \t \n \v \f \r space
1713             # '\s' => '[\x09\x0A \x0C\x0D\x20]',
1714             # '\s' => '[\x09\x0A\x0B\x0C\x0D\x20]',
1715             '\s' => '\s',
1716              
1717             '\w' => '[0-9A-Z_a-z]',
1718             '\D' => '${Ecyrillic::eD}',
1719             '\S' => '${Ecyrillic::eS}',
1720             '\W' => '${Ecyrillic::eW}',
1721              
1722             '\H' => '${Ecyrillic::eH}',
1723             '\V' => '${Ecyrillic::eV}',
1724             '\h' => '[\x09\x20]',
1725             '\v' => '[\x0A\x0B\x0C\x0D]',
1726             '\R' => '${Ecyrillic::eR}',
1727              
1728 25         429 }->{$1};
1729             }
1730              
1731             # POSIX-style character classes
1732             elsif ($ignorecase and ($char[$i] =~ /\A ( \[\: \^? (?:lower|upper) :\] ) \z/oxms)) {
1733             $char[$i] = {
1734              
1735             '[:lower:]' => '[\x41-\x5A\x61-\x7A]',
1736             '[:upper:]' => '[\x41-\x5A\x61-\x7A]',
1737             '[:^lower:]' => '${Ecyrillic::not_lower_i}',
1738             '[:^upper:]' => '${Ecyrillic::not_upper_i}',
1739              
1740 8         75 }->{$1};
1741             }
1742             elsif ($char[$i] =~ /\A ( \[\: \^? (?:alnum|alpha|ascii|blank|cntrl|digit|graph|lower|print|punct|space|upper|word|xdigit) :\] ) \z/oxms) {
1743             $char[$i] = {
1744              
1745             '[:alnum:]' => '[\x30-\x39\x41-\x5A\x61-\x7A]',
1746             '[:alpha:]' => '[\x41-\x5A\x61-\x7A]',
1747             '[:ascii:]' => '[\x00-\x7F]',
1748             '[:blank:]' => '[\x09\x20]',
1749             '[:cntrl:]' => '[\x00-\x1F\x7F]',
1750             '[:digit:]' => '[\x30-\x39]',
1751             '[:graph:]' => '[\x21-\x7F]',
1752             '[:lower:]' => '[\x61-\x7A]',
1753             '[:print:]' => '[\x20-\x7F]',
1754             '[:punct:]' => '[\x21-\x2F\x3A-\x3F\x40\x5B-\x5F\x60\x7B-\x7E]',
1755              
1756             # P.174 POSIX-Style Character Classes
1757             # in Chapter 5: Pattern Matching
1758             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
1759              
1760             # P.311 11.2.4 Character Classes and other Special Escapes
1761             # in Chapter 11: perlre: Perl regular expressions
1762             # of ISBN-13: 978-1-906966-02-7 The Perl Language Reference Manual (for Perl version 5.12.1)
1763              
1764             # P.210 POSIX-Style Character Classes
1765             # in Chapter 5: Pattern Matching
1766             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
1767              
1768             '[:space:]' => '[\s\x0B]', # "\s" plus vertical tab ("\cK")
1769              
1770             '[:upper:]' => '[\x41-\x5A]',
1771             '[:word:]' => '[\x30-\x39\x41-\x5A\x5F\x61-\x7A]',
1772             '[:xdigit:]' => '[\x30-\x39\x41-\x46\x61-\x66]',
1773             '[:^alnum:]' => '${Ecyrillic::not_alnum}',
1774             '[:^alpha:]' => '${Ecyrillic::not_alpha}',
1775             '[:^ascii:]' => '${Ecyrillic::not_ascii}',
1776             '[:^blank:]' => '${Ecyrillic::not_blank}',
1777             '[:^cntrl:]' => '${Ecyrillic::not_cntrl}',
1778             '[:^digit:]' => '${Ecyrillic::not_digit}',
1779             '[:^graph:]' => '${Ecyrillic::not_graph}',
1780             '[:^lower:]' => '${Ecyrillic::not_lower}',
1781             '[:^print:]' => '${Ecyrillic::not_print}',
1782             '[:^punct:]' => '${Ecyrillic::not_punct}',
1783             '[:^space:]' => '${Ecyrillic::not_space}',
1784             '[:^upper:]' => '${Ecyrillic::not_upper}',
1785             '[:^word:]' => '${Ecyrillic::not_word}',
1786             '[:^xdigit:]' => '${Ecyrillic::not_xdigit}',
1787              
1788 70         1546 }->{$1};
1789             }
1790             elsif ($char[$i] =~ /\A \\ ($q_char) \z/oxms) {
1791 7         37 $char[$i] = $1;
1792             }
1793             }
1794              
1795             # open character list
1796 358         548 my @singleoctet = ();
1797 358         414 my @multipleoctet = ();
1798 358         871 for (my $i=0; $i <= $#char; ) {
1799              
1800             # escaped -
1801 943 100 100     4693 if (defined($char[$i+1]) and ($char[$i+1] eq '...')) {
    100          
    100          
    50          
    50          
    100          
1802 182         175 $i += 1;
1803 182         316 next;
1804             }
1805              
1806             # make range regexp
1807             elsif ($char[$i] eq '...') {
1808              
1809             # range error
1810 182 50       679 if (CORE::length($char[$i-1]) > CORE::length($char[$i+1])) {
    50          
1811 0         0 croak 'Invalid [] range in regexp (length(A) > length(B)) ' . '\x' . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]);
1812             }
1813             elsif (CORE::length($char[$i-1]) == CORE::length($char[$i+1])) {
1814 182 50       439 if ($char[$i-1] gt $char[$i+1]) {
1815 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]);
1816             }
1817             }
1818              
1819             # make range regexp per length
1820 182         543 for my $length (CORE::length($char[$i-1]) .. CORE::length($char[$i+1])) {
1821 182         212 my @regexp = ();
1822              
1823             # is first and last
1824 182 50 33     803 if (($length == CORE::length($char[$i-1])) and ($length == CORE::length($char[$i+1]))) {
    0 0        
    0          
    0          
1825 182         484 push @regexp, _range_regexp($length, $char[$i-1], $char[$i+1]);
1826             }
1827              
1828             # is first
1829             elsif ($length == CORE::length($char[$i-1])) {
1830 0         0 push @regexp, _range_regexp($length, $char[$i-1], "\xFF" x $length);
1831             }
1832              
1833             # is inside in first and last
1834             elsif ((CORE::length($char[$i-1]) < $length) and ($length < CORE::length($char[$i+1]))) {
1835 0         0 push @regexp, _range_regexp($length, "\x00" x $length, "\xFF" x $length);
1836             }
1837              
1838             # is last
1839             elsif ($length == CORE::length($char[$i+1])) {
1840 0         0 push @regexp, _range_regexp($length, "\x00" x $length, $char[$i+1]);
1841             }
1842              
1843             else {
1844 0         0 die __FILE__, ": subroutine make_regexp panic.\n";
1845             }
1846              
1847 182 50       374 if ($length == 1) {
1848 182         355 push @singleoctet, @regexp;
1849             }
1850             else {
1851 0         0 push @multipleoctet, @regexp;
1852             }
1853             }
1854              
1855 182         359 $i += 2;
1856             }
1857              
1858             # with /i modifier
1859             elsif ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) {
1860 493 100       673 if ($modifier =~ /i/oxms) {
1861 24         36 my $uc = Ecyrillic::uc($char[$i]);
1862 24         37 my $fc = Ecyrillic::fc($char[$i]);
1863 24 100       38 if ($uc ne $fc) {
1864 12 50       18 if (CORE::length($fc) == 1) {
1865 12         16 push @singleoctet, $uc, $fc;
1866             }
1867             else {
1868 0         0 push @singleoctet, $uc;
1869 0         0 push @multipleoctet, $fc;
1870             }
1871             }
1872             else {
1873 12         18 push @singleoctet, $char[$i];
1874             }
1875             }
1876             else {
1877 469         667 push @singleoctet, $char[$i];
1878             }
1879 493         866 $i += 1;
1880             }
1881              
1882             # single character of single octet code
1883             elsif ($char[$i] =~ /\A (?: \\h ) \z/oxms) {
1884 0         0 push @singleoctet, "\t", "\x20";
1885 0         0 $i += 1;
1886             }
1887             elsif ($char[$i] =~ /\A (?: \\v ) \z/oxms) {
1888 0         0 push @singleoctet, "\x0A", "\x0B", "\x0C", "\x0D";
1889 0         0 $i += 1;
1890             }
1891             elsif ($char[$i] =~ /\A (?: \\d | \\s | \\w ) \z/oxms) {
1892 2         5 push @singleoctet, $char[$i];
1893 2         6 $i += 1;
1894             }
1895              
1896             # single character of multiple-octet code
1897             else {
1898 84         148 push @multipleoctet, $char[$i];
1899 84         179 $i += 1;
1900             }
1901             }
1902              
1903             # quote metachar
1904 358         682 for (@singleoctet) {
1905 689 50       3437 if ($_ eq '...') {
    100          
    100          
    100          
    100          
1906 0         0 $_ = '-';
1907             }
1908             elsif (/\A \n \z/oxms) {
1909 8         22 $_ = '\n';
1910             }
1911             elsif (/\A \r \z/oxms) {
1912 8         17 $_ = '\r';
1913             }
1914             elsif (/\A ([\x00-\x20\x7F-\xFF]) \z/oxms) {
1915 60         166 $_ = sprintf('\x%02X', CORE::ord $1);
1916             }
1917             elsif (/\A [\x00-\xFF] \z/oxms) {
1918 429         601 $_ = quotemeta $_;
1919             }
1920             }
1921              
1922             # return character list
1923 358         1009 return \@singleoctet, \@multipleoctet;
1924             }
1925              
1926             #
1927             # Cyrillic octal escape sequence
1928             #
1929             sub octchr {
1930 5     5 0 14 my($octdigit) = @_;
1931              
1932 5         9 my @binary = ();
1933 5         28 for my $octal (split(//,$octdigit)) {
1934             push @binary, {
1935             '0' => '000',
1936             '1' => '001',
1937             '2' => '010',
1938             '3' => '011',
1939             '4' => '100',
1940             '5' => '101',
1941             '6' => '110',
1942             '7' => '111',
1943 50         224 }->{$octal};
1944             }
1945 5         18 my $binary = join '', @binary;
1946              
1947             my $octchr = {
1948             # 1234567
1949             1 => pack('B*', "0000000$binary"),
1950             2 => pack('B*', "000000$binary"),
1951             3 => pack('B*', "00000$binary"),
1952             4 => pack('B*', "0000$binary"),
1953             5 => pack('B*', "000$binary"),
1954             6 => pack('B*', "00$binary"),
1955             7 => pack('B*', "0$binary"),
1956             0 => pack('B*', "$binary"),
1957              
1958 5         97 }->{CORE::length($binary) % 8};
1959              
1960 5         25 return $octchr;
1961             }
1962              
1963             #
1964             # Cyrillic hexadecimal escape sequence
1965             #
1966             sub hexchr {
1967 5     5 0 15 my($hexdigit) = @_;
1968              
1969             my $hexchr = {
1970             1 => pack('H*', "0$hexdigit"),
1971             0 => pack('H*', "$hexdigit"),
1972              
1973 5         122 }->{CORE::length($_[0]) % 2};
1974              
1975 5         19 return $hexchr;
1976             }
1977              
1978             #
1979             # Cyrillic open character list for qr
1980             #
1981             sub charlist_qr {
1982              
1983 314     314 0 537 my $modifier = pop @_;
1984 314         710 my @char = @_;
1985              
1986 314         812 my($singleoctet, $multipleoctet) = _charlist(@char, $modifier);
1987 314         732 my @singleoctet = @$singleoctet;
1988 314         432 my @multipleoctet = @$multipleoctet;
1989              
1990             # return character list
1991 314 100       735 if (scalar(@singleoctet) >= 1) {
1992              
1993             # with /i modifier
1994 236 100       501 if ($modifier =~ m/i/oxms) {
1995 22         31 my %singleoctet_ignorecase = ();
1996 22         29 for (@singleoctet) {
1997 46   100     206 while (s/ \A \\x(..) - \\x(..) //oxms or s/ \A \\x((..)) //oxms) {
1998 46         108 for my $ord (hex($1) .. hex($2)) {
1999 66         73 my $char = CORE::chr($ord);
2000 66         72 my $uc = Ecyrillic::uc($char);
2001 66         86 my $fc = Ecyrillic::fc($char);
2002 66 100       86 if ($uc eq $fc) {
2003 12         82 $singleoctet_ignorecase{unpack 'C*', $char} = 1;
2004             }
2005             else {
2006 54 50       66 if (CORE::length($fc) == 1) {
2007 54         104 $singleoctet_ignorecase{unpack 'C*', $uc} = 1;
2008 54         181 $singleoctet_ignorecase{unpack 'C*', $fc} = 1;
2009             }
2010             else {
2011 0         0 $singleoctet_ignorecase{unpack 'C*', $uc} = 1;
2012 0         0 push @multipleoctet, join '', map {sprintf('\x%02X',$_)} unpack 'C*', $fc;
  0         0  
2013             }
2014             }
2015             }
2016             }
2017 46 50       81 if ($_ ne '') {
2018 0         0 $singleoctet_ignorecase{unpack 'C*', $_} = 1;
2019             }
2020             }
2021 22         20 my $i = 0;
2022 22         23 my @singleoctet_ignorecase = ();
2023 22         32 for my $ord (0 .. 255) {
2024 5632 100       4734 if (exists $singleoctet_ignorecase{$ord}) {
2025 96         60 push @{$singleoctet_ignorecase[$i]}, $ord;
  96         130  
2026             }
2027             else {
2028 5536         3534 $i++;
2029             }
2030             }
2031 22         38 @singleoctet = ();
2032 22         41 for my $range (@singleoctet_ignorecase) {
2033 3648 100       4803 if (ref $range) {
2034 56 100       39 if (scalar(@{$range}) == 1) {
  56 50       75  
2035 36         26 push @singleoctet, sprintf('\x%02X', @{$range}[0]);
  36         106  
2036             }
2037 20         24 elsif (scalar(@{$range}) == 2) {
2038 0         0 push @singleoctet, sprintf('\x%02X\x%02X', @{$range}[0], @{$range}[-1]);
  0         0  
  0         0  
2039             }
2040             else {
2041 20         17 push @singleoctet, sprintf('\x%02X-\x%02X', @{$range}[0], @{$range}[-1]);
  20         18  
  20         80  
2042             }
2043             }
2044             }
2045             }
2046              
2047 236         292 my $not_anchor = '';
2048              
2049 236         574 push @multipleoctet, join('', $not_anchor, '[', @singleoctet, ']' );
2050             }
2051 314 100       603 if (scalar(@multipleoctet) >= 2) {
2052 6         24 return '(?:' . join('|', @multipleoctet) . ')';
2053             }
2054             else {
2055 308         1267 return $multipleoctet[0];
2056             }
2057             }
2058              
2059             #
2060             # Cyrillic open character list for not qr
2061             #
2062             sub charlist_not_qr {
2063              
2064 44     44 0 68 my $modifier = pop @_;
2065 44         94 my @char = @_;
2066              
2067 44         103 my($singleoctet, $multipleoctet) = _charlist(@char, $modifier);
2068 44         86 my @singleoctet = @$singleoctet;
2069 44         52 my @multipleoctet = @$multipleoctet;
2070              
2071             # with /i modifier
2072 44 100       101 if ($modifier =~ m/i/oxms) {
2073 10         17 my %singleoctet_ignorecase = ();
2074 10         14 for (@singleoctet) {
2075 10   66     58 while (s/ \A \\x(..) - \\x(..) //oxms or s/ \A \\x((..)) //oxms) {
2076 10         41 for my $ord (hex($1) .. hex($2)) {
2077 30         38 my $char = CORE::chr($ord);
2078 30         46 my $uc = Ecyrillic::uc($char);
2079 30         47 my $fc = Ecyrillic::fc($char);
2080 30 50       48 if ($uc eq $fc) {
2081 0         0 $singleoctet_ignorecase{unpack 'C*', $char} = 1;
2082             }
2083             else {
2084 30 50       36 if (CORE::length($fc) == 1) {
2085 30         65 $singleoctet_ignorecase{unpack 'C*', $uc} = 1;
2086 30         104 $singleoctet_ignorecase{unpack 'C*', $fc} = 1;
2087             }
2088             else {
2089 0         0 $singleoctet_ignorecase{unpack 'C*', $uc} = 1;
2090 0         0 push @multipleoctet, join '', map {sprintf('\x%02X',$_)} unpack 'C*', $fc;
  0         0  
2091             }
2092             }
2093             }
2094             }
2095 10 50       25 if ($_ ne '') {
2096 0         0 $singleoctet_ignorecase{unpack 'C*', $_} = 1;
2097             }
2098             }
2099 10         10 my $i = 0;
2100 10         15 my @singleoctet_ignorecase = ();
2101 10         17 for my $ord (0 .. 255) {
2102 2560 100       2464 if (exists $singleoctet_ignorecase{$ord}) {
2103 60         40 push @{$singleoctet_ignorecase[$i]}, $ord;
  60         88  
2104             }
2105             else {
2106 2500         1851 $i++;
2107             }
2108             }
2109 10         17 @singleoctet = ();
2110 10         25 for my $range (@singleoctet_ignorecase) {
2111 960 100       1455 if (ref $range) {
2112 20 50       16 if (scalar(@{$range}) == 1) {
  20 50       33  
2113 0         0 push @singleoctet, sprintf('\x%02X', @{$range}[0]);
  0         0  
2114             }
2115 20         27 elsif (scalar(@{$range}) == 2) {
2116 0         0 push @singleoctet, sprintf('\x%02X\x%02X', @{$range}[0], @{$range}[-1]);
  0         0  
  0         0  
2117             }
2118             else {
2119 20         17 push @singleoctet, sprintf('\x%02X-\x%02X', @{$range}[0], @{$range}[-1]);
  20         22  
  20         85  
2120             }
2121             }
2122             }
2123             }
2124              
2125             # return character list
2126 44 50       90 if (scalar(@multipleoctet) >= 1) {
2127 0 0       0 if (scalar(@singleoctet) >= 1) {
2128              
2129             # any character other than multiple-octet and single octet character class
2130 0         0 return '(?!' . join('|', @multipleoctet) . ')(?:[^' . join('', @singleoctet) . '])';
2131             }
2132             else {
2133              
2134             # any character other than multiple-octet character class
2135 0         0 return '(?!' . join('|', @multipleoctet) . ")(?:$your_char)";
2136             }
2137             }
2138             else {
2139 44 50       80 if (scalar(@singleoctet) >= 1) {
2140              
2141             # any character other than single octet character class
2142 44         239 return '(?:[^' . join('', @singleoctet) . '])';
2143             }
2144             else {
2145              
2146             # any character
2147 0         0 return "(?:$your_char)";
2148             }
2149             }
2150             }
2151              
2152             #
2153             # open file in read mode
2154             #
2155             sub _open_r {
2156 400     400   920 my(undef,$file) = @_;
2157 400         1153 $file =~ s#\A (\s) #./$1#oxms;
2158 400   33     28888 return CORE::eval(q{open($_[0],'<',$_[1])}) ||
2159             open($_[0],"< $file\0");
2160             }
2161              
2162             #
2163             # open file in write mode
2164             #
2165             sub _open_w {
2166 0     0   0 my(undef,$file) = @_;
2167 0         0 $file =~ s#\A (\s) #./$1#oxms;
2168 0   0     0 return CORE::eval(q{open($_[0],'>',$_[1])}) ||
2169             open($_[0],"> $file\0");
2170             }
2171              
2172             #
2173             # open file in append mode
2174             #
2175             sub _open_a {
2176 0     0   0 my(undef,$file) = @_;
2177 0         0 $file =~ s#\A (\s) #./$1#oxms;
2178 0   0     0 return CORE::eval(q{open($_[0],'>>',$_[1])}) ||
2179             open($_[0],">> $file\0");
2180             }
2181              
2182             #
2183             # safe system
2184             #
2185             sub _systemx {
2186              
2187             # P.707 29.2.33. exec
2188             # in Chapter 29: Functions
2189             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
2190             #
2191             # Be aware that in older releases of Perl, exec (and system) did not flush
2192             # your output buffer, so you needed to enable command buffering by setting $|
2193             # on one or more filehandles to avoid lost output in the case of exec, or
2194             # misordererd output in the case of system. This situation was largely remedied
2195             # in the 5.6 release of Perl. (So, 5.005 release not yet.)
2196              
2197             # P.855 exec
2198             # in Chapter 27: Functions
2199             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
2200             #
2201             # In very old release of Perl (before v5.6), exec (and system) did not flush
2202             # your output buffer, so you needed to enable command buffering by setting $|
2203             # on one or more filehandles to avoid lost output with exec or misordered
2204             # output with system.
2205              
2206 200     200   705 $| = 1;
2207              
2208             # P.565 23.1.2. Cleaning Up Your Environment
2209             # in Chapter 23: Security
2210             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
2211              
2212             # P.656 Cleaning Up Your Environment
2213             # in Chapter 20: Security
2214             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
2215              
2216             # local $ENV{'PATH'} = '.';
2217 200         1680 local @ENV{qw(IFS CDPATH ENV BASH_ENV)}; # Make %ENV safer
2218              
2219             # P.707 29.2.33. exec
2220             # in Chapter 29: Functions
2221             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
2222             #
2223             # As we mentioned earlier, exec treats a discrete list of arguments as an
2224             # indication that it should bypass shell processing. However, there is one
2225             # place where you might still get tripped up. The exec call (and system, too)
2226             # will not distinguish between a single scalar argument and an array containing
2227             # only one element.
2228             #
2229             # @args = ("echo surprise"); # just one element in list
2230             # exec @args # still subject to shell escapes
2231             # or die "exec: $!"; # because @args == 1
2232             #
2233             # To avoid this, you can use the PATHNAME syntax, explicitly duplicating the
2234             # first argument as the pathname, which forces the rest of the arguments to be
2235             # interpreted as a list, even if there is only one of them:
2236             #
2237             # exec { $args[0] } @args # safe even with one-argument list
2238             # or die "can't exec @args: $!";
2239              
2240             # P.855 exec
2241             # in Chapter 27: Functions
2242             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
2243             #
2244             # As we mentioned earlier, exec treats a discrete list of arguments as a
2245             # directive to bypass shell processing. However, there is one place where
2246             # you might still get tripped up. The exec call (and system, too) cannot
2247             # distinguish between a single scalar argument and an array containing
2248             # only one element.
2249             #
2250             # @args = ("echo surprise"); # just one element in list
2251             # exec @args # still subject to shell escapes
2252             # || die "exec: $!"; # because @args == 1
2253             #
2254             # To avoid this, use the PATHNAME syntax, explicitly duplicating the first
2255             # argument as the pathname, which forces the rest of the arguments to be
2256             # interpreted as a list, even if there is only one of them:
2257             #
2258             # exec { $args[0] } @args # safe even with one-argument list
2259             # || die "can't exec @args: $!";
2260              
2261 200         334 return CORE::system { $_[0] } @_; # safe even with one-argument list
  200         14754261  
2262             }
2263              
2264             #
2265             # Cyrillic order to character (with parameter)
2266             #
2267             sub Ecyrillic::chr(;$) {
2268              
2269 0 0   0 0 0 my $c = @_ ? $_[0] : $_;
2270              
2271 0 0       0 if ($c == 0x00) {
2272 0         0 return "\x00";
2273             }
2274             else {
2275 0         0 my @chr = ();
2276 0         0 while ($c > 0) {
2277 0         0 unshift @chr, ($c % 0x100);
2278 0         0 $c = int($c / 0x100);
2279             }
2280 0         0 return pack 'C*', @chr;
2281             }
2282             }
2283              
2284             #
2285             # Cyrillic order to character (without parameter)
2286             #
2287             sub Ecyrillic::chr_() {
2288              
2289 0     0 0 0 my $c = $_;
2290              
2291 0 0       0 if ($c == 0x00) {
2292 0         0 return "\x00";
2293             }
2294             else {
2295 0         0 my @chr = ();
2296 0         0 while ($c > 0) {
2297 0         0 unshift @chr, ($c % 0x100);
2298 0         0 $c = int($c / 0x100);
2299             }
2300 0         0 return pack 'C*', @chr;
2301             }
2302             }
2303              
2304             #
2305             # Cyrillic path globbing (with parameter)
2306             #
2307             sub Ecyrillic::glob($) {
2308              
2309 0 0   0 0 0 if (wantarray) {
2310 0         0 my @glob = _DOS_like_glob(@_);
2311 0         0 for my $glob (@glob) {
2312 0         0 $glob =~ s{ \A (?:\./)+ }{}oxms;
2313             }
2314 0         0 return @glob;
2315             }
2316             else {
2317 0         0 my $glob = _DOS_like_glob(@_);
2318 0         0 $glob =~ s{ \A (?:\./)+ }{}oxms;
2319 0         0 return $glob;
2320             }
2321             }
2322              
2323             #
2324             # Cyrillic path globbing (without parameter)
2325             #
2326             sub Ecyrillic::glob_() {
2327              
2328 0 0   0 0 0 if (wantarray) {
2329 0         0 my @glob = _DOS_like_glob();
2330 0         0 for my $glob (@glob) {
2331 0         0 $glob =~ s{ \A (?:\./)+ }{}oxms;
2332             }
2333 0         0 return @glob;
2334             }
2335             else {
2336 0         0 my $glob = _DOS_like_glob();
2337 0         0 $glob =~ s{ \A (?:\./)+ }{}oxms;
2338 0         0 return $glob;
2339             }
2340             }
2341              
2342             #
2343             # Cyrillic path globbing via File::DosGlob 1.10
2344             #
2345             # Often I confuse "_dosglob" and "_doglob".
2346             # So, I renamed "_dosglob" to "_DOS_like_glob".
2347             #
2348             my %iter;
2349             my %entries;
2350             sub _DOS_like_glob {
2351              
2352             # context (keyed by second cxix argument provided by core)
2353 0     0   0 my($expr,$cxix) = @_;
2354              
2355             # glob without args defaults to $_
2356 0 0       0 $expr = $_ if not defined $expr;
2357              
2358             # represents the current user's home directory
2359             #
2360             # 7.3. Expanding Tildes in Filenames
2361             # in Chapter 7. File Access
2362             # of ISBN 0-596-00313-7 Perl Cookbook, 2nd Edition.
2363             #
2364             # and File::HomeDir, File::HomeDir::Windows module
2365              
2366             # DOS-like system
2367 0 0       0 if ($^O =~ /\A (?: MSWin32 | NetWare | symbian | dos ) \z/oxms) {
2368 0         0 $expr =~ s{ \A ~ (?= [^/\\] ) }
2369 0         0 { my_home_MSWin32() }oxmse;
2370             }
2371              
2372             # UNIX-like system
2373             else {
2374 0         0 $expr =~ s{ \A ~ ( (?:[^/])* ) }
2375 0 0 0     0 { $1 ? (CORE::eval(q{(getpwnam($1))[7]})||my_home()) : my_home() }oxmse;
2376             }
2377              
2378             # assume global context if not provided one
2379 0 0       0 $cxix = '_G_' if not defined $cxix;
2380 0 0       0 $iter{$cxix} = 0 if not exists $iter{$cxix};
2381              
2382             # if we're just beginning, do it all first
2383 0 0       0 if ($iter{$cxix} == 0) {
2384 0         0 $entries{$cxix} = [ _do_glob(1, _parse_line($expr)) ];
2385             }
2386              
2387             # chuck it all out, quick or slow
2388 0 0       0 if (wantarray) {
2389 0         0 delete $iter{$cxix};
2390 0         0 return @{delete $entries{$cxix}};
  0         0  
2391             }
2392             else {
2393 0 0       0 if ($iter{$cxix} = scalar @{$entries{$cxix}}) {
  0         0  
2394 0         0 return shift @{$entries{$cxix}};
  0         0  
2395             }
2396             else {
2397             # return undef for EOL
2398 0         0 delete $iter{$cxix};
2399 0         0 delete $entries{$cxix};
2400 0         0 return undef;
2401             }
2402             }
2403             }
2404              
2405             #
2406             # Cyrillic path globbing subroutine
2407             #
2408             sub _do_glob {
2409              
2410 0     0   0 my($cond,@expr) = @_;
2411 0         0 my @glob = ();
2412 0         0 my $fix_drive_relative_paths = 0;
2413              
2414             OUTER:
2415 0         0 for my $expr (@expr) {
2416 0 0       0 next OUTER if not defined $expr;
2417 0 0       0 next OUTER if $expr eq '';
2418              
2419 0         0 my @matched = ();
2420 0         0 my @globdir = ();
2421 0         0 my $head = '.';
2422 0         0 my $pathsep = '/';
2423 0         0 my $tail;
2424              
2425             # if argument is within quotes strip em and do no globbing
2426 0 0       0 if ($expr =~ /\A " ((?:$q_char)*?) " \z/oxms) {
2427 0         0 $expr = $1;
2428 0 0       0 if ($cond eq 'd') {
2429 0 0       0 if (-d $expr) {
2430 0         0 push @glob, $expr;
2431             }
2432             }
2433             else {
2434 0 0       0 if (-e $expr) {
2435 0         0 push @glob, $expr;
2436             }
2437             }
2438 0         0 next OUTER;
2439             }
2440              
2441             # wildcards with a drive prefix such as h:*.pm must be changed
2442             # to h:./*.pm to expand correctly
2443 0 0       0 if ($^O =~ /\A (?: MSWin32 | NetWare | symbian | dos ) \z/oxms) {
2444 0 0       0 if ($expr =~ s# \A ((?:[A-Za-z]:)?) ([^/\\]) #$1./$2#oxms) {
2445 0         0 $fix_drive_relative_paths = 1;
2446             }
2447             }
2448              
2449 0 0       0 if (($head, $tail) = _parse_path($expr,$pathsep)) {
2450 0 0       0 if ($tail eq '') {
2451 0         0 push @glob, $expr;
2452 0         0 next OUTER;
2453             }
2454 0 0       0 if ($head =~ / \A (?:$q_char)*? [*?] /oxms) {
2455 0 0       0 if (@globdir = _do_glob('d', $head)) {
2456 0         0 push @glob, _do_glob($cond, map {"$_$pathsep$tail"} @globdir);
  0         0  
2457 0         0 next OUTER;
2458             }
2459             }
2460 0 0 0     0 if ($head eq '' or $head =~ /\A [A-Za-z]: \z/oxms) {
2461 0         0 $head .= $pathsep;
2462             }
2463 0         0 $expr = $tail;
2464             }
2465              
2466             # If file component has no wildcards, we can avoid opendir
2467 0 0       0 if ($expr !~ / \A (?:$q_char)*? [*?] /oxms) {
2468 0 0       0 if ($head eq '.') {
2469 0         0 $head = '';
2470             }
2471 0 0 0     0 if ($head ne '' and ($head =~ / \G ($q_char) /oxmsg)[-1] ne $pathsep) {
2472 0         0 $head .= $pathsep;
2473             }
2474 0         0 $head .= $expr;
2475 0 0       0 if ($cond eq 'd') {
2476 0 0       0 if (-d $head) {
2477 0         0 push @glob, $head;
2478             }
2479             }
2480             else {
2481 0 0       0 if (-e $head) {
2482 0         0 push @glob, $head;
2483             }
2484             }
2485 0         0 next OUTER;
2486             }
2487 0 0       0 opendir(*DIR, $head) or next OUTER;
2488 0         0 my @leaf = readdir DIR;
2489 0         0 closedir DIR;
2490              
2491 0 0       0 if ($head eq '.') {
2492 0         0 $head = '';
2493             }
2494 0 0 0     0 if ($head ne '' and ($head =~ / \G ($q_char) /oxmsg)[-1] ne $pathsep) {
2495 0         0 $head .= $pathsep;
2496             }
2497              
2498 0         0 my $pattern = '';
2499 0         0 while ($expr =~ / \G ($q_char) /oxgc) {
2500 0         0 my $char = $1;
2501              
2502             # 6.9. Matching Shell Globs as Regular Expressions
2503             # in Chapter 6. Pattern Matching
2504             # of ISBN 0-596-00313-7 Perl Cookbook, 2nd Edition.
2505             # (and so on)
2506              
2507 0 0       0 if ($char eq '*') {
    0          
    0          
2508 0         0 $pattern .= "(?:$your_char)*",
2509             }
2510             elsif ($char eq '?') {
2511 0         0 $pattern .= "(?:$your_char)?", # DOS style
2512             # $pattern .= "(?:$your_char)", # UNIX style
2513             }
2514             elsif ((my $fc = Ecyrillic::fc($char)) ne $char) {
2515 0         0 $pattern .= $fc;
2516             }
2517             else {
2518 0         0 $pattern .= quotemeta $char;
2519             }
2520             }
2521 0     0   0 my $matchsub = sub { Ecyrillic::fc($_[0]) =~ /\A $pattern \z/xms };
  0         0  
2522              
2523             # if ($@) {
2524             # print STDERR "$0: $@\n";
2525             # next OUTER;
2526             # }
2527              
2528             INNER:
2529 0         0 for my $leaf (@leaf) {
2530 0 0 0     0 if ($leaf eq '.' or $leaf eq '..') {
2531 0         0 next INNER;
2532             }
2533 0 0 0     0 if ($cond eq 'd' and not -d "$head$leaf") {
2534 0         0 next INNER;
2535             }
2536              
2537 0 0       0 if (&$matchsub($leaf)) {
2538 0         0 push @matched, "$head$leaf";
2539 0         0 next INNER;
2540             }
2541              
2542             # [DOS compatibility special case]
2543             # Failed, add a trailing dot and try again, but only...
2544              
2545 0 0 0     0 if (Ecyrillic::index($leaf,'.') == -1 and # if name does not have a dot in it *and*
      0        
2546             CORE::length($leaf) <= 8 and # name is shorter than or equal to 8 chars *and*
2547             Ecyrillic::index($pattern,'\\.') != -1 # pattern has a dot.
2548             ) {
2549 0 0       0 if (&$matchsub("$leaf.")) {
2550 0         0 push @matched, "$head$leaf";
2551 0         0 next INNER;
2552             }
2553             }
2554             }
2555 0 0       0 if (@matched) {
2556 0         0 push @glob, @matched;
2557             }
2558             }
2559 0 0       0 if ($fix_drive_relative_paths) {
2560 0         0 for my $glob (@glob) {
2561 0         0 $glob =~ s# \A ([A-Za-z]:) \./ #$1#oxms;
2562             }
2563             }
2564 0         0 return @glob;
2565             }
2566              
2567             #
2568             # Cyrillic parse line
2569             #
2570             sub _parse_line {
2571              
2572 0     0   0 my($line) = @_;
2573              
2574 0         0 $line .= ' ';
2575 0         0 my @piece = ();
2576 0         0 while ($line =~ /
2577             " ( (?>(?: [^"] )* ) ) " (?>\s+) |
2578             ( (?>(?: [^"\s] )* ) ) (?>\s+)
2579             /oxmsg
2580             ) {
2581 0 0       0 push @piece, defined($1) ? $1 : $2;
2582             }
2583 0         0 return @piece;
2584             }
2585              
2586             #
2587             # Cyrillic parse path
2588             #
2589             sub _parse_path {
2590              
2591 0     0   0 my($path,$pathsep) = @_;
2592              
2593 0         0 $path .= '/';
2594 0         0 my @subpath = ();
2595 0         0 while ($path =~ /
2596             ((?: [^\/\\] )+?) [\/\\]
2597             /oxmsg
2598             ) {
2599 0         0 push @subpath, $1;
2600             }
2601              
2602 0         0 my $tail = pop @subpath;
2603 0         0 my $head = join $pathsep, @subpath;
2604 0         0 return $head, $tail;
2605             }
2606              
2607             #
2608             # via File::HomeDir::Windows 1.00
2609             #
2610             sub my_home_MSWin32 {
2611              
2612             # A lot of unix people and unix-derived tools rely on
2613             # the ability to overload HOME. We will support it too
2614             # so that they can replace raw HOME calls with File::HomeDir.
2615 0 0 0 0 0 0 if (exists $ENV{'HOME'} and $ENV{'HOME'}) {
    0 0        
    0 0        
      0        
      0        
2616 0         0 return $ENV{'HOME'};
2617             }
2618              
2619             # Do we have a user profile?
2620             elsif (exists $ENV{'USERPROFILE'} and $ENV{'USERPROFILE'}) {
2621 0         0 return $ENV{'USERPROFILE'};
2622             }
2623              
2624             # Some Windows use something like $ENV{'HOME'}
2625             elsif (exists $ENV{'HOMEDRIVE'} and exists $ENV{'HOMEPATH'} and $ENV{'HOMEDRIVE'} and $ENV{'HOMEPATH'}) {
2626 0         0 return join '', $ENV{'HOMEDRIVE'}, $ENV{'HOMEPATH'};
2627             }
2628              
2629 0         0 return undef;
2630             }
2631              
2632             #
2633             # via File::HomeDir::Unix 1.00
2634             #
2635             sub my_home {
2636 0     0 0 0 my $home;
2637              
2638 0 0 0     0 if (exists $ENV{'HOME'} and defined $ENV{'HOME'}) {
    0 0        
2639 0         0 $home = $ENV{'HOME'};
2640             }
2641              
2642             # This is from the original code, but I'm guessing
2643             # it means "login directory" and exists on some Unixes.
2644             elsif (exists $ENV{'LOGDIR'} and $ENV{'LOGDIR'}) {
2645 0         0 $home = $ENV{'LOGDIR'};
2646             }
2647              
2648             ### More-desperate methods
2649              
2650             # Light desperation on any (Unixish) platform
2651             else {
2652 0         0 $home = CORE::eval q{ (getpwuid($<))[7] };
2653             }
2654              
2655             # On Unix in general, a non-existant home means "no home"
2656             # For example, "nobody"-like users might use /nonexistant
2657 0 0 0     0 if (defined $home and ! -d($home)) {
2658 0         0 $home = undef;
2659             }
2660 0         0 return $home;
2661             }
2662              
2663             #
2664             # ${^PREMATCH}, $PREMATCH, $` the string preceding what was matched
2665             #
2666             sub Ecyrillic::PREMATCH {
2667 0     0 0 0 return $`;
2668             }
2669              
2670             #
2671             # ${^MATCH}, $MATCH, $& the string that matched
2672             #
2673             sub Ecyrillic::MATCH {
2674 0     0 0 0 return $&;
2675             }
2676              
2677             #
2678             # ${^POSTMATCH}, $POSTMATCH, $' the string following what was matched
2679             #
2680             sub Ecyrillic::POSTMATCH {
2681 0     0 0 0 return $';
2682             }
2683              
2684             #
2685             # Cyrillic character to order (with parameter)
2686             #
2687             sub Cyrillic::ord(;$) {
2688              
2689 0 0   0 1 0 local $_ = shift if @_;
2690              
2691 0 0       0 if (/\A ($q_char) /oxms) {
2692 0         0 my @ord = unpack 'C*', $1;
2693 0         0 my $ord = 0;
2694 0         0 while (my $o = shift @ord) {
2695 0         0 $ord = $ord * 0x100 + $o;
2696             }
2697 0         0 return $ord;
2698             }
2699             else {
2700 0         0 return CORE::ord $_;
2701             }
2702             }
2703              
2704             #
2705             # Cyrillic character to order (without parameter)
2706             #
2707             sub Cyrillic::ord_() {
2708              
2709 0 0   0 0 0 if (/\A ($q_char) /oxms) {
2710 0         0 my @ord = unpack 'C*', $1;
2711 0         0 my $ord = 0;
2712 0         0 while (my $o = shift @ord) {
2713 0         0 $ord = $ord * 0x100 + $o;
2714             }
2715 0         0 return $ord;
2716             }
2717             else {
2718 0         0 return CORE::ord $_;
2719             }
2720             }
2721              
2722             #
2723             # Cyrillic reverse
2724             #
2725             sub Cyrillic::reverse(@) {
2726              
2727 0 0   0 0 0 if (wantarray) {
2728 0         0 return CORE::reverse @_;
2729             }
2730             else {
2731              
2732             # One of us once cornered Larry in an elevator and asked him what
2733             # problem he was solving with this, but he looked as far off into
2734             # the distance as he could in an elevator and said, "It seemed like
2735             # a good idea at the time."
2736              
2737 0         0 return join '', CORE::reverse(join('',@_) =~ /\G ($q_char) /oxmsg);
2738             }
2739             }
2740              
2741             #
2742             # Cyrillic getc (with parameter, without parameter)
2743             #
2744             sub Cyrillic::getc(;*@) {
2745              
2746 0     0 0 0 my($package) = caller;
2747 0 0       0 my $fh = @_ ? qualify_to_ref(shift,$package) : \*STDIN;
2748 0 0 0     0 croak 'Too many arguments for Cyrillic::getc' if @_ and not wantarray;
2749              
2750 0         0 my @length = sort { $a <=> $b } keys %range_tr;
  0         0  
2751 0         0 my $getc = '';
2752 0         0 for my $length ($length[0] .. $length[-1]) {
2753 0         0 $getc .= CORE::getc($fh);
2754 0 0       0 if (exists $range_tr{CORE::length($getc)}) {
2755 0 0       0 if ($getc =~ /\A ${Ecyrillic::dot_s} \z/oxms) {
2756 0 0       0 return wantarray ? ($getc,@_) : $getc;
2757             }
2758             }
2759             }
2760 0 0       0 return wantarray ? ($getc,@_) : $getc;
2761             }
2762              
2763             #
2764             # Cyrillic length by character
2765             #
2766             sub Cyrillic::length(;$) {
2767              
2768 0 0   0 1 0 local $_ = shift if @_;
2769              
2770 0         0 local @_ = /\G ($q_char) /oxmsg;
2771 0         0 return scalar @_;
2772             }
2773              
2774             #
2775             # Cyrillic substr by character
2776             #
2777             BEGIN {
2778              
2779             # P.232 The lvalue Attribute
2780             # in Chapter 6: Subroutines
2781             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
2782              
2783             # P.336 The lvalue Attribute
2784             # in Chapter 7: Subroutines
2785             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
2786              
2787             # P.144 8.4 Lvalue subroutines
2788             # in Chapter 8: perlsub: Perl subroutines
2789             # of ISBN-13: 978-1-906966-02-7 The Perl Language Reference Manual (for Perl version 5.12.1)
2790              
2791 200 50 0 200 1 105328 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         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
2792             # vv----------------------*******
2793             sub Cyrillic::substr($$;$$) %s {
2794              
2795             my @char = $_[0] =~ /\G (?>$q_char) /oxmsg;
2796              
2797             # If the substring is beyond either end of the string, substr() returns the undefined
2798             # value and produces a warning. When used as an lvalue, specifying a substring that
2799             # is entirely outside the string raises an exception.
2800             # http://perldoc.perl.org/functions/substr.html
2801              
2802             # A return with no argument returns the scalar value undef in scalar context,
2803             # an empty list () in list context, and (naturally) nothing at all in void
2804             # context.
2805              
2806             my $offset = $_[1];
2807             if (($offset > scalar(@char)) or ($offset < (-1 * scalar(@char)))) {
2808             return;
2809             }
2810              
2811             # substr($string,$offset,$length,$replacement)
2812             if (@_ == 4) {
2813             my(undef,undef,$length,$replacement) = @_;
2814             my $substr = join '', splice(@char, $offset, $length, $replacement);
2815             $_[0] = join '', @char;
2816              
2817             # return $substr; this doesn't work, don't say "return"
2818             $substr;
2819             }
2820              
2821             # substr($string,$offset,$length)
2822             elsif (@_ == 3) {
2823             my(undef,undef,$length) = @_;
2824             my $octet_offset = 0;
2825             my $octet_length = 0;
2826             if ($offset == 0) {
2827             $octet_offset = 0;
2828             }
2829             elsif ($offset > 0) {
2830             $octet_offset = CORE::length(join '', @char[0..$offset-1]);
2831             }
2832             else {
2833             $octet_offset = -1 * CORE::length(join '', @char[$#char+$offset+1..$#char]);
2834             }
2835             if ($length == 0) {
2836             $octet_length = 0;
2837             }
2838             elsif ($length > 0) {
2839             $octet_length = CORE::length(join '', @char[$offset..$offset+$length-1]);
2840             }
2841             else {
2842             $octet_length = -1 * CORE::length(join '', @char[$#char+$length+1..$#char]);
2843             }
2844             CORE::substr($_[0], $octet_offset, $octet_length);
2845             }
2846              
2847             # substr($string,$offset)
2848             else {
2849             my $octet_offset = 0;
2850             if ($offset == 0) {
2851             $octet_offset = 0;
2852             }
2853             elsif ($offset > 0) {
2854             $octet_offset = CORE::length(join '', @char[0..$offset-1]);
2855             }
2856             else {
2857             $octet_offset = -1 * CORE::length(join '', @char[$#char+$offset+1..$#char]);
2858             }
2859             CORE::substr($_[0], $octet_offset);
2860             }
2861             }
2862             END
2863             }
2864              
2865             #
2866             # Cyrillic index by character
2867             #
2868             sub Cyrillic::index($$;$) {
2869              
2870 0     0 1 0 my $index;
2871 0 0       0 if (@_ == 3) {
2872 0         0 $index = Ecyrillic::index($_[0], $_[1], CORE::length(Cyrillic::substr($_[0], 0, $_[2])));
2873             }
2874             else {
2875 0         0 $index = Ecyrillic::index($_[0], $_[1]);
2876             }
2877              
2878 0 0       0 if ($index == -1) {
2879 0         0 return -1;
2880             }
2881             else {
2882 0         0 return Cyrillic::length(CORE::substr $_[0], 0, $index);
2883             }
2884             }
2885              
2886             #
2887             # Cyrillic rindex by character
2888             #
2889             sub Cyrillic::rindex($$;$) {
2890              
2891 0     0 1 0 my $rindex;
2892 0 0       0 if (@_ == 3) {
2893 0         0 $rindex = Ecyrillic::rindex($_[0], $_[1], CORE::length(Cyrillic::substr($_[0], 0, $_[2])));
2894             }
2895             else {
2896 0         0 $rindex = Ecyrillic::rindex($_[0], $_[1]);
2897             }
2898              
2899 0 0       0 if ($rindex == -1) {
2900 0         0 return -1;
2901             }
2902             else {
2903 0         0 return Cyrillic::length(CORE::substr $_[0], 0, $rindex);
2904             }
2905             }
2906              
2907             # when 'm//', '/' means regexp match 'm//' and '?' means regexp match '??'
2908             # when 'div', '/' means division operator and '?' means conditional operator (condition ? then : else)
2909 200     200   13924 BEGIN { CORE::eval q{ use vars qw($slash) } } $slash = 'm//';
  200     200   1423  
  200         290  
  200         11632  
2910              
2911             # ord() to ord() or Cyrillic::ord()
2912 200     200   15039 BEGIN { CORE::eval q{ use vars qw($function_ord) } } $function_ord = 'ord';
  200     200   893  
  200         324  
  200         9750  
2913              
2914             # ord to ord or Cyrillic::ord_
2915 200     200   10213 BEGIN { CORE::eval q{ use vars qw($function_ord_) } } $function_ord_ = 'ord';
  200     200   843  
  200         304  
  200         9223  
2916              
2917             # reverse to reverse or Cyrillic::reverse
2918 200     200   10215 BEGIN { CORE::eval q{ use vars qw($function_reverse) } } $function_reverse = 'reverse';
  200     200   803  
  200         323  
  200         9471  
2919              
2920             # getc to getc or Cyrillic::getc
2921 200     200   9430 BEGIN { CORE::eval q{ use vars qw($function_getc) } } $function_getc = 'getc';
  200     200   841  
  200         280  
  200         10239  
2922              
2923             # P.1023 Appendix W.9 Multibyte Anchoring
2924             # of ISBN 1-56592-224-7 CJKV Information Processing
2925              
2926             my $anchor = '';
2927              
2928 200     200   10444 BEGIN { CORE::eval q{ use vars qw($nest) } }
  200     200   841  
  200         293  
  200         7527521  
2929              
2930             # regexp of nested parens in qqXX
2931              
2932             # P.340 Matching Nested Constructs with Embedded Code
2933             # in Chapter 7: Perl
2934             # of ISBN 0-596-00289-0 Mastering Regular Expressions, Second edition
2935              
2936             my $qq_paren = qr{(?{local $nest=0}) (?>(?:
2937             [^\\()] |
2938             \( (?{$nest++}) |
2939             \) (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!)) |
2940             \\ [^c] |
2941             \\c[\x40-\x5F] |
2942             [\x00-\xFF]
2943             }xms;
2944              
2945             my $qq_brace = qr{(?{local $nest=0}) (?>(?:
2946             [^\\{}] |
2947             \{ (?{$nest++}) |
2948             \} (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!)) |
2949             \\ [^c] |
2950             \\c[\x40-\x5F] |
2951             [\x00-\xFF]
2952             }xms;
2953              
2954             my $qq_bracket = qr{(?{local $nest=0}) (?>(?:
2955             [^\\\[\]] |
2956             \[ (?{$nest++}) |
2957             \] (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!)) |
2958             \\ [^c] |
2959             \\c[\x40-\x5F] |
2960             [\x00-\xFF]
2961             }xms;
2962              
2963             my $qq_angle = qr{(?{local $nest=0}) (?>(?:
2964             [^\\<>] |
2965             \< (?{$nest++}) |
2966             \> (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!)) |
2967             \\ [^c] |
2968             \\c[\x40-\x5F] |
2969             [\x00-\xFF]
2970             }xms;
2971              
2972             my $qq_scalar = qr{(?: \{ (?:$qq_brace)*? \} |
2973             (?: ::)? (?:
2974             (?> [a-zA-Z_][a-zA-Z_0-9]* (?: ::[a-zA-Z_][a-zA-Z_0-9]*)* )
2975             (?>(?: \[ (?: \$\[ | \$\] | $qq_char )*? \] | \{ (?:$qq_brace)*? \} )*)
2976             (?>(?: (?: -> )? (?: [\$\@\%\&\*]\* | \$\#\* | [\@\%]? \[ (?: \$\[ | \$\] | $qq_char )*? \] | [\@\%\*]? \{ (?:$qq_brace)*? \} ) )*)
2977             ))
2978             }xms;
2979              
2980             my $qq_variable = qr{(?: \{ (?:$qq_brace)*? \} |
2981             (?: ::)? (?:
2982             (?>[0-9]+) |
2983             [^a-zA-Z_0-9\[\]] |
2984             ^[A-Z] |
2985             (?> [a-zA-Z_][a-zA-Z_0-9]* (?: ::[a-zA-Z_][a-zA-Z_0-9]*)* )
2986             (?>(?: \[ (?: \$\[ | \$\] | $qq_char )*? \] | \{ (?:$qq_brace)*? \} )*)
2987             (?>(?: (?: -> )? (?: [\$\@\%\&\*]\* | \$\#\* | [\@\%]? \[ (?: \$\[ | \$\] | $qq_char )*? \] | [\@\%\*]? \{ (?:$qq_brace)*? \} ) )*)
2988             ))
2989             }xms;
2990              
2991             my $qq_substr = qr{(?> Char::substr | Cyrillic::substr | CORE::substr | substr ) (?>\s*) \( $qq_paren \)
2992             }xms;
2993              
2994             # regexp of nested parens in qXX
2995             my $q_paren = qr{(?{local $nest=0}) (?>(?:
2996             [^()] |
2997             \( (?{$nest++}) |
2998             \) (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!)) |
2999             [\x00-\xFF]
3000             }xms;
3001              
3002             my $q_brace = qr{(?{local $nest=0}) (?>(?:
3003             [^\{\}] |
3004             \{ (?{$nest++}) |
3005             \} (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!)) |
3006             [\x00-\xFF]
3007             }xms;
3008              
3009             my $q_bracket = qr{(?{local $nest=0}) (?>(?:
3010             [^\[\]] |
3011             \[ (?{$nest++}) |
3012             \] (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!)) |
3013             [\x00-\xFF]
3014             }xms;
3015              
3016             my $q_angle = qr{(?{local $nest=0}) (?>(?:
3017             [^<>] |
3018             \< (?{$nest++}) |
3019             \> (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!)) |
3020             [\x00-\xFF]
3021             }xms;
3022              
3023             my $matched = '';
3024             my $s_matched = '';
3025              
3026             my $tr_variable = ''; # variable of tr///
3027             my $sub_variable = ''; # variable of s///
3028             my $bind_operator = ''; # =~ or !~
3029              
3030             my @heredoc = (); # here document
3031             my @heredoc_delimiter = ();
3032             my $here_script = ''; # here script
3033              
3034             #
3035             # escape Cyrillic script
3036             #
3037             sub Cyrillic::escape(;$) {
3038 200 50   200 0 579 local($_) = $_[0] if @_;
3039              
3040             # P.359 The Study Function
3041             # in Chapter 7: Perl
3042             # of ISBN 0-596-00289-0 Mastering Regular Expressions, Second edition
3043              
3044 200         332 study $_; # Yes, I studied study yesterday.
3045              
3046             # while all script
3047              
3048             # 6.14. Matching from Where the Last Pattern Left Off
3049             # in Chapter 6. Pattern Matching
3050             # of ISBN 0-596-00313-7 Perl Cookbook, 2nd Edition.
3051             # (and so on)
3052              
3053             # one member of Tag-team
3054             #
3055             # P.128 Start of match (or end of previous match): \G
3056             # P.130 Advanced Use of \G with Perl
3057             # in Chapter 3: Overview of Regular Expression Features and Flavors
3058             # P.255 Use leading anchors
3059             # P.256 Expose ^ and \G at the front expressions
3060             # in Chapter 6: Crafting an Efficient Expression
3061             # P.315 "Tag-team" matching with /gc
3062             # in Chapter 7: Perl
3063             # of ISBN 0-596-00289-0 Mastering Regular Expressions, Second edition
3064              
3065 200         304 my $e_script = '';
3066 200         756 while (not /\G \z/oxgc) { # member
3067 72412         82982 $e_script .= Cyrillic::escape_token();
3068             }
3069              
3070 200         2087 return $e_script;
3071             }
3072              
3073             #
3074             # escape Cyrillic token of script
3075             #
3076             sub Cyrillic::escape_token {
3077              
3078             # \n output here document
3079              
3080 72412     72412 0 55899 my $ignore_modules = join('|', qw(
3081             utf8
3082             bytes
3083             charnames
3084             I18N::Japanese
3085             I18N::Collate
3086             I18N::JExt
3087             File::DosGlob
3088             Wild
3089             Wildcard
3090             Japanese
3091             ));
3092              
3093             # another member of Tag-team
3094             #
3095             # P.315 "Tag-team" matching with /gc
3096             # in Chapter 7: Perl
3097             # of ISBN 0-596-00289-0 Mastering Regular Expressions, Second edition
3098              
3099 72412 100 100     3612493 if (/\G ( \n ) /oxgc) { # another member (and so on)
    100 66        
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    50          
    100          
    50          
    100          
    100          
    50          
    50          
    50          
    50          
    50          
    50          
    100          
    100          
    50          
    50          
    50          
    50          
    100          
    100          
    50          
    100          
    50          
    100          
    100          
    50          
    100          
    50          
    50          
    50          
    100          
    50          
    50          
    50          
    100          
    50          
    100          
    50          
    100          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    100          
    100          
    100          
    100          
    100          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    100          
    100          
    100          
    100          
    50          
    100          
    50          
    100          
    100          
    100          
    50          
    50          
    50          
    100          
    50          
    50          
    100          
    50          
    100          
    50          
    50          
    50          
    50          
    50          
    50          
    100          
    100          
    100          
    100          
    100          
    50          
    50          
    50          
    100          
    50          
    100          
    100          
    50          
    100          
    50          
    50          
    50          
    100          
    50          
    50          
    100          
    100          
    100          
    50          
3100 12102         9698 my $heredoc = '';
3101 12102 100       19438 if (scalar(@heredoc_delimiter) >= 1) {
3102 150         146 $slash = 'm//';
3103              
3104 150         245 $heredoc = join '', @heredoc;
3105 150         205 @heredoc = ();
3106              
3107             # skip here document
3108 150         217 for my $heredoc_delimiter (@heredoc_delimiter) {
3109 150         883 /\G .*? \n $heredoc_delimiter \n/xmsgc;
3110             }
3111 150         185 @heredoc_delimiter = ();
3112              
3113 150         146 $here_script = '';
3114             }
3115 12102         32264 return "\n" . $heredoc;
3116             }
3117              
3118             # ignore space, comment
3119 17407         44930 elsif (/\G ((?>\s+)|\#.*) /oxgc) { return $1; }
3120              
3121             # if (, elsif (, unless (, while (, until (, given (, and when (
3122              
3123             # given, when
3124              
3125             # P.225 The given Statement
3126             # in Chapter 15: Smart Matching and given-when
3127             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
3128              
3129             # P.133 The given Statement
3130             # in Chapter 4: Statements and Declarations
3131             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
3132              
3133             elsif (/\G ( (?: if | elsif | unless | while | until | given | when ) (?>\s*) \( ) /oxgc) {
3134 1373         1636 $slash = 'm//';
3135 1373         3806 return $1;
3136             }
3137              
3138             # scalar variable ($scalar = ...) =~ tr///;
3139             # scalar variable ($scalar = ...) =~ s///;
3140              
3141             # state
3142              
3143             # P.68 Persistent, Private Variables
3144             # in Chapter 4: Subroutines
3145             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
3146              
3147             # P.160 Persistent Lexically Scoped Variables: state
3148             # in Chapter 4: Statements and Declarations
3149             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
3150              
3151             # (and so on)
3152              
3153             elsif (/\G ( \( (?>\s*) (?: local \b | my \b | our \b | state \b )? (?>\s*) \$ $qq_scalar ) /oxgc) {
3154 85         198 my $e_string = e_string($1);
3155              
3156 85 50       2035 if (/\G ( (?>\s*) = $qq_paren \) ) ( (?>\s*) (?: =~ | !~ ) (?>\s*) ) (?= (?: tr | y ) \b ) /oxgc) {
    50          
3157 0         0 $tr_variable = $e_string . e_string($1);
3158 0         0 $bind_operator = $2;
3159 0         0 $slash = 'm//';
3160 0         0 return '';
3161             }
3162             elsif (/\G ( (?>\s*) = $qq_paren \) ) ( (?>\s*) (?: =~ | !~ ) (?>\s*) ) (?= s \b ) /oxgc) {
3163 0         0 $sub_variable = $e_string . e_string($1);
3164 0         0 $bind_operator = $2;
3165 0         0 $slash = 'm//';
3166 0         0 return '';
3167             }
3168             else {
3169 85         141 $slash = 'div';
3170 85         299 return $e_string;
3171             }
3172             }
3173              
3174             # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Ecyrillic::PREMATCH()
3175             elsif (/\G ( \$` | \$\{`\} | \$ (?>\s*) PREMATCH \b | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} ) /oxmsgc) {
3176 4         9 $slash = 'div';
3177 4         9 return q{Ecyrillic::PREMATCH()};
3178             }
3179              
3180             # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Ecyrillic::MATCH()
3181             elsif (/\G ( \$& | \$\{&\} | \$ (?>\s*) MATCH \b | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} ) /oxmsgc) {
3182 28         46 $slash = 'div';
3183 28         82 return q{Ecyrillic::MATCH()};
3184             }
3185              
3186             # $', ${'} --> $', ${'}
3187             elsif (/\G ( \$' | \$\{'\} ) /oxmsgc) {
3188 1         1 $slash = 'div';
3189 1         3 return $1;
3190             }
3191              
3192             # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Ecyrillic::POSTMATCH()
3193             elsif (/\G ( \$ (?>\s*) POSTMATCH \b | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} ) /oxmsgc) {
3194 3         4 $slash = 'div';
3195 3         10 return q{Ecyrillic::POSTMATCH()};
3196             }
3197              
3198             # scalar variable $scalar =~ tr///;
3199             # scalar variable $scalar =~ s///;
3200             # substr() =~ tr///;
3201             # substr() =~ s///;
3202             elsif (/\G ( \$ $qq_scalar | $qq_substr ) /oxgc) {
3203 1604         2861 my $scalar = e_string($1);
3204              
3205 1604 100       6100 if (/\G ( (?>\s*) (?: =~ | !~ ) (?>\s*) ) (?= (?: tr | y ) \b ) /oxgc) {
    100          
3206 1         3 $tr_variable = $scalar;
3207 1         3 $bind_operator = $1;
3208 1         3 $slash = 'm//';
3209 1         4 return '';
3210             }
3211             elsif (/\G ( (?>\s*) (?: =~ | !~ ) (?>\s*) ) (?= s \b ) /oxgc) {
3212 61         106 $sub_variable = $scalar;
3213 61         121 $bind_operator = $1;
3214 61         77 $slash = 'm//';
3215 61         173 return '';
3216             }
3217             else {
3218 1542         1669 $slash = 'div';
3219 1542         3814 return $scalar;
3220             }
3221             }
3222              
3223             # end of statement
3224             elsif (/\G ( [,;] ) /oxgc) {
3225 4597         4689 $slash = 'm//';
3226              
3227             # clear tr/// variable
3228 4597         3864 $tr_variable = '';
3229              
3230             # clear s/// variable
3231 4597         3604 $sub_variable = '';
3232              
3233 4597         3511 $bind_operator = '';
3234              
3235 4597         14343 return $1;
3236             }
3237              
3238             # bareword
3239             elsif (/\G ( \{ (?>\s*) (?: tr | index | rindex | reverse ) (?>\s*) \} ) /oxmsgc) {
3240 0         0 return $1;
3241             }
3242              
3243             # $0 --> $0
3244             elsif (/\G ( \$ 0 ) /oxmsgc) {
3245 2         5 $slash = 'div';
3246 2         8 return $1;
3247             }
3248             elsif (/\G ( \$ \{ (?>\s*) 0 (?>\s*) \} ) /oxmsgc) {
3249 0         0 $slash = 'div';
3250 0         0 return $1;
3251             }
3252              
3253             # $$ --> $$
3254             elsif (/\G ( \$ \$ ) (?![\w\{]) /oxmsgc) {
3255 1         2 $slash = 'div';
3256 1         3 return $1;
3257             }
3258              
3259             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
3260             # $1, $2, $3 --> $1, $2, $3 otherwise
3261             elsif (/\G \$ ((?>[1-9][0-9]*)) /oxmsgc) {
3262 4         6 $slash = 'div';
3263 4         10 return e_capture($1);
3264             }
3265             elsif (/\G \$ \{ (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} /oxmsgc) {
3266 0         0 $slash = 'div';
3267 0         0 return e_capture($1);
3268             }
3269              
3270             # $$foo[ ... ] --> $ $foo->[ ... ]
3271             elsif (/\G \$ ( \$ (?> [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \[ .+? \] ) /oxmsgc) {
3272 0         0 $slash = 'div';
3273 0         0 return e_capture($1.'->'.$2);
3274             }
3275              
3276             # $$foo{ ... } --> $ $foo->{ ... }
3277             elsif (/\G \$ ( \$ (?> [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \{ .+? \} ) /oxmsgc) {
3278 0         0 $slash = 'div';
3279 0         0 return e_capture($1.'->'.$2);
3280             }
3281              
3282             # $$foo
3283             elsif (/\G \$ ( \$ (?> [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) /oxmsgc) {
3284 0         0 $slash = 'div';
3285 0         0 return e_capture($1);
3286             }
3287              
3288             # ${ foo }
3289             elsif (/\G \$ (?>\s*) \{ ( (?>\s*) (?> [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) (?>\s*) ) \} /oxmsgc) {
3290 0         0 $slash = 'div';
3291 0         0 return '${' . $1 . '}';
3292             }
3293              
3294             # ${ ... }
3295             elsif (/\G \$ (?>\s*) \{ (?>\s*) ( $qq_brace ) (?>\s*) \} /oxmsgc) {
3296 0         0 $slash = 'div';
3297 0         0 return e_capture($1);
3298             }
3299              
3300             # variable or function
3301             # $ @ % & * $ #
3302             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) {
3303 42         61 $slash = 'div';
3304 42         132 return $1;
3305             }
3306             # $ $ $ $ $ $ $ $ $ $ $ $ $ $
3307             # $ @ # \ ' " / ? ( ) [ ] < >
3308             elsif (/\G ( \$[\$\@\#\\\'\"\/\?\(\)\[\]\<\>] ) /oxmsgc) {
3309 60         96 $slash = 'div';
3310 60         203 return $1;
3311             }
3312              
3313             # while ()
3314             elsif (/\G \b (while (?>\s*) \( (?>\s*) <[\$]?[A-Za-z_][A-Za-z_0-9]*> (?>\s*) \)) \b /oxgc) {
3315 0         0 return $1;
3316             }
3317              
3318             # while () --- glob
3319              
3320             # avoid "Error: Runtime exception" of perl version 5.005_03
3321              
3322             elsif (/\G \b while (?>\s*) \( (?>\s*) < ((?:[^>\0\a\e\f\n\r\t])+?) > (?>\s*) \) \b /oxgc) {
3323 0         0 return 'while ($_ = Ecyrillic::glob("' . $1 . '"))';
3324             }
3325              
3326             # while (glob)
3327             elsif (/\G \b while (?>\s*) \( (?>\s*) glob (?>\s*) \) /oxgc) {
3328 0         0 return 'while ($_ = Ecyrillic::glob_)';
3329             }
3330              
3331             # while (glob(WILDCARD))
3332             elsif (/\G \b while (?>\s*) \( (?>\s*) glob \b /oxgc) {
3333 0         0 return 'while ($_ = Ecyrillic::glob';
3334             }
3335              
3336             # doit if, doit unless, doit while, doit until, doit for, doit when
3337 241         439 elsif (/\G \b ( if | unless | while | until | for | when ) \b /oxgc) { $slash = 'm//'; return $1; }
  241         960  
3338              
3339             # subroutines of package Ecyrillic
3340 19         28 elsif (/\G \b (CORE:: | ->(>?\s*) (?: atan2 | [a-z]{2,})) \b /oxgc) { $slash = 'm//'; return $1; }
  19         51  
3341 0         0 elsif (/\G \b Char::eval (?= (?>\s*) \{ ) /oxgc) { $slash = 'm//'; return 'eval'; }
  0         0  
3342 13         9 elsif (/\G \b Cyrillic::eval (?= (?>\s*) \{ ) /oxgc) { $slash = 'm//'; return 'eval'; }
  13         43  
3343 0         0 elsif (/\G \b Char::eval \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'eval Char::escape'; }
  0         0  
3344 114         128 elsif (/\G \b Cyrillic::eval \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'eval Cyrillic::escape'; }
  114         336  
3345 2         5 elsif (/\G \b bytes::substr \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'substr'; }
  2         6  
3346 0         0 elsif (/\G \b chop \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Ecyrillic::chop'; }
  0         0  
3347 2         7 elsif (/\G \b bytes::index \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'index'; }
  2         9  
3348 0         0 elsif (/\G \b Char::index \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Char::index'; }
  0         0  
3349 0         0 elsif (/\G \b Cyrillic::index \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Cyrillic::index'; }
  0         0  
3350 0         0 elsif (/\G \b index \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Ecyrillic::index'; }
  0         0  
3351 2         6 elsif (/\G \b bytes::rindex \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'rindex'; }
  2         5  
3352 0         0 elsif (/\G \b Char::rindex \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Char::rindex'; }
  0         0  
3353 0         0 elsif (/\G \b Cyrillic::rindex \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Cyrillic::rindex'; }
  0         0  
3354 0         0 elsif (/\G \b rindex \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Ecyrillic::rindex'; }
  0         0  
3355 1         1 elsif (/\G \b lc (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Ecyrillic::lc'; }
  1         3  
3356 0         0 elsif (/\G \b lcfirst (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Ecyrillic::lcfirst'; }
  0         0  
3357 1         3 elsif (/\G \b uc (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Ecyrillic::uc'; }
  1         3  
3358 0         0 elsif (/\G \b ucfirst (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Ecyrillic::ucfirst'; }
  0         0  
3359 6         8 elsif (/\G \b fc (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Ecyrillic::fc'; }
  6         16  
3360              
3361             # "-s '' ..." means file test "-s 'filename' ..." (not means "- s/// ...")
3362 0         0 elsif (/\G -s (?>\s*) (\") ((?:$qq_char)+?) (\") /oxgc) { $slash = 'm//'; return '-s ' . e_qq('', $1,$3,$2); }
  0         0  
3363 0         0 elsif (/\G -s (?>\s+) qq (?>\s*) (\#) ((?:$qq_char)+?) (\#) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0         0  
3364 0         0 elsif (/\G -s (?>\s+) qq (?>\s*) (\() ((?:$qq_paren)+?) (\)) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0         0  
3365 0         0 elsif (/\G -s (?>\s+) qq (?>\s*) (\{) ((?:$qq_brace)+?) (\}) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0         0  
3366 0         0 elsif (/\G -s (?>\s+) qq (?>\s*) (\[) ((?:$qq_bracket)+?) (\]) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0         0  
3367 0         0 elsif (/\G -s (?>\s+) qq (?>\s*) (\<) ((?:$qq_angle)+?) (\>) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0         0  
3368 0         0 elsif (/\G -s (?>\s+) qq (?>\s*) (\S) ((?:$qq_char)+?) (\1) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0         0  
3369              
3370 0         0 elsif (/\G -s (?>\s*) (\') ((?:\\\'|\\\\|$q_char)+?) (\') /oxgc) { $slash = 'm//'; return '-s ' . e_q ('', $1,$3,$2); }
  0         0  
3371 0         0 elsif (/\G -s (?>\s+) q (?>\s*) (\#) ((?:\\\#|\\\\|$q_char)+?) (\#) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0         0  
3372 0         0 elsif (/\G -s (?>\s+) q (?>\s*) (\() ((?:\\\)|\\\\|$q_paren)+?) (\)) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0         0  
3373 0         0 elsif (/\G -s (?>\s+) q (?>\s*) (\{) ((?:\\\}|\\\\|$q_brace)+?) (\}) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0         0  
3374 0         0 elsif (/\G -s (?>\s+) q (?>\s*) (\[) ((?:\\\]|\\\\|$q_bracket)+?) (\]) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0         0  
3375 0         0 elsif (/\G -s (?>\s+) q (?>\s*) (\<) ((?:\\\>|\\\\|$q_angle)+?) (\>) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0         0  
3376 0         0 elsif (/\G -s (?>\s+) q (?>\s*) (\S) ((?:\\\1|\\\\|$q_char)+?) (\1) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0         0  
3377              
3378             elsif (/\G -s (?>\s*) (\$ (?> \w+ (?: ::\w+)* ) (?: (?: ->)? (?: [\$\@\%\&\*]\* | \$\#\* | \( (?:$qq_paren)*? \) | [\@\%\*]? \{ (?:$qq_brace)+? \} | [\@\%]? \[ (?:$qq_bracket)+? \] ) )*) /oxgc)
3379 0         0 { $slash = 'm//'; return "-s $1"; }
  0         0  
3380 0         0 elsif (/\G -s (?>\s*) \( ((?:$qq_paren)*?) \) /oxgc) { $slash = 'm//'; return "-s ($1)"; }
  0         0  
3381 0         0 elsif (/\G -s (?= (?>\s+) [a-z]+) /oxgc) { $slash = 'm//'; return '-s'; }
  0         0  
3382 0         0 elsif (/\G -s (?>\s+) ((?>\w+)) /oxgc) { $slash = 'm//'; return "-s $1"; }
  0         0  
3383              
3384 2         4 elsif (/\G \b bytes::length (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'length'; }
  2         6  
3385 2         3 elsif (/\G \b bytes::chr (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'chr'; }
  2         7  
3386 36         60 elsif (/\G \b chr (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Ecyrillic::chr'; }
  36         109  
3387 2         4 elsif (/\G \b bytes::ord (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'div'; return 'ord'; }
  2         6  
3388 8         11 elsif (/\G \b ord (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'div'; return $function_ord; }
  8         21  
3389 0         0 elsif (/\G \b glob (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Ecyrillic::glob'; }
  0         0  
3390 0         0 elsif (/\G \b lc \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Ecyrillic::lc_'; }
  0         0  
3391 0         0 elsif (/\G \b lcfirst \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Ecyrillic::lcfirst_'; }
  0         0  
3392 0         0 elsif (/\G \b uc \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Ecyrillic::uc_'; }
  0         0  
3393 0         0 elsif (/\G \b ucfirst \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Ecyrillic::ucfirst_'; }
  0         0  
3394 0         0 elsif (/\G \b fc \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Ecyrillic::fc_'; }
  0         0  
3395 0         0 elsif (/\G -s \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return '-s '; }
  0         0  
3396              
3397 0         0 elsif (/\G \b bytes::length \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'length'; }
  0         0  
3398 0         0 elsif (/\G \b bytes::chr \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'chr'; }
  0         0  
3399 0         0 elsif (/\G \b chr \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Ecyrillic::chr_'; }
  0         0  
3400 0         0 elsif (/\G \b bytes::ord \b (?! (?>\s*) => ) /oxgc) { $slash = 'div'; return 'ord'; }
  0         0  
3401 0         0 elsif (/\G \b ord \b (?! (?>\s*) => ) /oxgc) { $slash = 'div'; return $function_ord_; }
  0         0  
3402 0         0 elsif (/\G \b glob \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Ecyrillic::glob_'; }
  0         0  
3403 0         0 elsif (/\G \b reverse \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return $function_reverse; }
  0         0  
3404 8         17 elsif (/\G \b getc \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return $function_getc; }
  8         33  
3405             # split
3406             elsif (/\G \b (split) \b (?! (?>\s*) => ) /oxgc) {
3407 87         158 $slash = 'm//';
3408              
3409 87         124 my $e = '';
3410 87         383 while (/\G ( (?>\s+) | \( | \#.* ) /oxgc) {
3411 85         398 $e .= $1;
3412             }
3413              
3414             # end of split
3415 87 100       7643 if (/\G (?= [,;\)\}\]] ) /oxgc) { return 'Ecyrillic::split' . $e; }
  2 100       12  
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    100          
    50          
    50          
    100          
    50          
    100          
    50          
    50          
    50          
3416              
3417             # split scalar value
3418 1         4 elsif (/\G ( [\$\@\&\*] $qq_scalar ) /oxgc) { return 'Ecyrillic::split' . $e . e_string($1); }
3419              
3420             # split literal space
3421 0         0 elsif (/\G \b qq (\#) [ ] (\#) /oxgc) { return 'Ecyrillic::split' . $e . qq {qq$1 $2}; }
3422 0         0 elsif (/\G \b qq ((?>\s*)) (\() [ ] (\)) /oxgc) { return 'Ecyrillic::split' . $e . qq{$1qq$2 $3}; }
3423 0         0 elsif (/\G \b qq ((?>\s*)) (\{) [ ] (\}) /oxgc) { return 'Ecyrillic::split' . $e . qq{$1qq$2 $3}; }
3424 0         0 elsif (/\G \b qq ((?>\s*)) (\[) [ ] (\]) /oxgc) { return 'Ecyrillic::split' . $e . qq{$1qq$2 $3}; }
3425 0         0 elsif (/\G \b qq ((?>\s*)) (\<) [ ] (\>) /oxgc) { return 'Ecyrillic::split' . $e . qq{$1qq$2 $3}; }
3426 0         0 elsif (/\G \b qq ((?>\s*)) (\S) [ ] (\2) /oxgc) { return 'Ecyrillic::split' . $e . qq{$1qq$2 $3}; }
3427 0         0 elsif (/\G \b q (\#) [ ] (\#) /oxgc) { return 'Ecyrillic::split' . $e . qq {q$1 $2}; }
3428 0         0 elsif (/\G \b q ((?>\s*)) (\() [ ] (\)) /oxgc) { return 'Ecyrillic::split' . $e . qq {$1q$2 $3}; }
3429 0         0 elsif (/\G \b q ((?>\s*)) (\{) [ ] (\}) /oxgc) { return 'Ecyrillic::split' . $e . qq {$1q$2 $3}; }
3430 0         0 elsif (/\G \b q ((?>\s*)) (\[) [ ] (\]) /oxgc) { return 'Ecyrillic::split' . $e . qq {$1q$2 $3}; }
3431 0         0 elsif (/\G \b q ((?>\s*)) (\<) [ ] (\>) /oxgc) { return 'Ecyrillic::split' . $e . qq {$1q$2 $3}; }
3432 0         0 elsif (/\G \b q ((?>\s*)) (\S) [ ] (\2) /oxgc) { return 'Ecyrillic::split' . $e . qq {$1q$2 $3}; }
3433 10         55 elsif (/\G ' [ ] ' /oxgc) { return 'Ecyrillic::split' . $e . qq {' '}; }
3434 0         0 elsif (/\G " [ ] " /oxgc) { return 'Ecyrillic::split' . $e . qq {" "}; }
3435              
3436             # split qq//
3437             elsif (/\G \b (qq) \b /oxgc) {
3438 0 0       0 if (/\G (\#) ((?:$qq_char)*?) (\#) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq# # --> qr # #
  0         0  
3439             else {
3440 0         0 while (not /\G \z/oxgc) {
3441 0 0       0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0       0  
    0          
    0          
    0          
    0          
    0          
3442 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq ( ) --> qr ( )
3443 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq { } --> qr { }
3444 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq [ ] --> qr [ ]
3445 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq < > --> qr < >
3446 0         0 elsif (/\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) /oxgc) { return e_split($e.'qr','{','}',$2,''); } # qq | | --> qr { }
3447 0         0 elsif (/\G (\S) ((?:$qq_char)*?) (\1) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq * * --> qr * *
3448             }
3449 0         0 die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3450             }
3451             }
3452              
3453             # split qr//
3454             elsif (/\G \b (qr) \b /oxgc) {
3455 12 50       459 if (/\G (\#) ((?:$qq_char)*?) (\#) ([imosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1,$3,$2,$4); } # qr# #
  0         0  
3456             else {
3457 12         55 while (not /\G \z/oxgc) {
3458 12 50       3175 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 50       0  
    50          
    50          
    50          
    50          
    50          
    50          
3459 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([imosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # qr ( )
3460 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([imosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # qr { }
3461 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([imosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # qr [ ]
3462 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([imosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # qr < >
3463 0         0 elsif (/\G (\') ((?:$qq_char)*?) (\') ([imosxpadlunbB]*) /oxgc) { return e_split_q($e.'qr',$1, $3, $2,$4); } # qr ' '
3464 0         0 elsif (/\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ([imosxpadlunbB]*) /oxgc) { return e_split ($e.'qr','{','}',$2,$4); } # qr | | --> qr { }
3465 12         71 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([imosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # qr * *
3466             }
3467 0         0 die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3468             }
3469             }
3470              
3471             # split q//
3472             elsif (/\G \b (q) \b /oxgc) {
3473 0 0       0 if (/\G (\#) ((?:\\\#|\\\\|$q_char)*?) (\#) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q# # --> qr # #
  0         0  
3474             else {
3475 0         0 while (not /\G \z/oxgc) {
3476 0 0       0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0       0  
    0          
    0          
    0          
    0          
    0          
3477 0         0 elsif (/\G (\() ((?:\\\\|\\\)|\\\(|$q_paren)*?) (\)) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q ( ) --> qr ( )
3478 0         0 elsif (/\G (\{) ((?:\\\\|\\\}|\\\{|$q_brace)*?) (\}) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q { } --> qr { }
3479 0         0 elsif (/\G (\[) ((?:\\\\|\\\]|\\\[|$q_bracket)*?) (\]) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q [ ] --> qr [ ]
3480 0         0 elsif (/\G (\<) ((?:\\\\|\\\>|\\\<|$q_angle)*?) (\>) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q < > --> qr < >
3481 0         0 elsif (/\G ([*\-:?\\^|]) ((?:$q_char)*?) (\1) /oxgc) { return e_split_q($e.'qr','{','}',$2,''); } # q | | --> qr { }
3482 0         0 elsif (/\G (\S) ((?:\\\\|\\\1| $q_char)*?) (\1) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q * * --> qr * *
3483             }
3484 0         0 die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3485             }
3486             }
3487              
3488             # split m//
3489             elsif (/\G \b (m) \b /oxgc) {
3490 18 50       548 if (/\G (\#) ((?:$qq_char)*?) (\#) ([cgimosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1,$3,$2,$4); } # m# # --> qr # #
  0         0  
3491             else {
3492 18         89 while (not /\G \z/oxgc) {
3493 18 50       4222 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 50       0  
    50          
    50          
    50          
    50          
    50          
    50          
3494 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cgimosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # m ( ) --> qr ( )
3495 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cgimosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # m { } --> qr { }
3496 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cgimosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # m [ ] --> qr [ ]
3497 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cgimosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # m < > --> qr < >
3498 0         0 elsif (/\G (\') ((?:$qq_char)*?) (\') ([cgimosxpadlunbB]*) /oxgc) { return e_split_q($e.'qr',$1, $3, $2,$4); } # m ' ' --> qr ' '
3499 0         0 elsif (/\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ([cgimosxpadlunbB]*) /oxgc) { return e_split ($e.'qr','{','}',$2,$4); } # m | | --> qr { }
3500 18         114 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cgimosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # m * * --> qr * *
3501             }
3502 0         0 die __FILE__, ": Search pattern not terminated\n";
3503             }
3504             }
3505              
3506             # split ''
3507             elsif (/\G (\') /oxgc) {
3508 0         0 my $q_string = '';
3509 0         0 while (not /\G \z/oxgc) {
3510 0 0       0 if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0       0  
    0          
    0          
3511 0         0 elsif (/\G (\\\') /oxgc) { $q_string .= $1; } # splitqr'' --> split qr''
3512 0         0 elsif (/\G \' /oxgc) { return e_split_q($e.q{ qr},"'","'",$q_string,''); } # ' ' --> qr ' '
3513 0         0 elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3514             }
3515 0         0 die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3516             }
3517              
3518             # split ""
3519             elsif (/\G (\") /oxgc) {
3520 0         0 my $qq_string = '';
3521 0         0 while (not /\G \z/oxgc) {
3522 0 0       0 if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0       0  
    0          
    0          
3523 0         0 elsif (/\G (\\\") /oxgc) { $qq_string .= $1; } # splitqr"" --> split qr""
3524 0         0 elsif (/\G \" /oxgc) { return e_split($e.q{ qr},'"','"',$qq_string,''); } # " " --> qr " "
3525 0         0 elsif (/\G ($q_char) /oxgc) { $qq_string .= $1; }
3526             }
3527 0         0 die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3528             }
3529              
3530             # split //
3531             elsif (/\G (\/) /oxgc) {
3532 44         70 my $regexp = '';
3533 44         151 while (not /\G \z/oxgc) {
3534 381 50       1523 if (/\G (\\\\) /oxgc) { $regexp .= $1; }
  0 50       0  
    100          
    50          
3535 0         0 elsif (/\G (\\\/) /oxgc) { $regexp .= $1; } # splitqr// --> split qr//
3536 44         189 elsif (/\G \/ ([cgimosxpadlunbB]*) /oxgc) { return e_split($e.q{ qr}, '/','/',$regexp,$1); } # / / --> qr / /
3537 337         633 elsif (/\G ($q_char) /oxgc) { $regexp .= $1; }
3538             }
3539 0         0 die __FILE__, ": Search pattern not terminated\n";
3540             }
3541             }
3542              
3543             # tr/// or y///
3544              
3545             # about [cdsrbB]* (/B modifier)
3546             #
3547             # P.559 appendix C
3548             # of ISBN 4-89052-384-7 Programming perl
3549             # (Japanese title is: Perl puroguramingu)
3550              
3551             elsif (/\G \b ( tr | y ) \b /oxgc) {
3552 3         7 my $ope = $1;
3553              
3554             # $1 $2 $3 $4 $5 $6
3555 3 50       49 if (/\G (\#) ((?:$qq_char)*?) (\#) ((?:$qq_char)*?) (\#) ([cdsrbB]*) /oxgc) { # tr# # #
3556 0         0 my @tr = ($tr_variable,$2);
3557 0         0 return e_tr(@tr,'',$4,$6);
3558             }
3559             else {
3560 3         4 my $e = '';
3561 3         10 while (not /\G \z/oxgc) {
3562 3 50       244 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 50       0  
    50          
    50          
    50          
    50          
3563             elsif (/\G (\() ((?:$qq_paren)*?) (\)) /oxgc) {
3564 0         0 my @tr = ($tr_variable,$2);
3565 0         0 while (not /\G \z/oxgc) {
3566 0 0       0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0       0  
    0          
    0          
    0          
    0          
3567 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr ( ) ( )
3568 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr ( ) { }
3569 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr ( ) [ ]
3570 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr ( ) < >
3571 0         0 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr ( ) * *
3572             }
3573 0         0 die __FILE__, ": Transliteration replacement not terminated\n";
3574             }
3575             elsif (/\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) {
3576 0         0 my @tr = ($tr_variable,$2);
3577 0         0 while (not /\G \z/oxgc) {
3578 0 0       0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0       0  
    0          
    0          
    0          
    0          
3579 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr { } ( )
3580 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr { } { }
3581 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr { } [ ]
3582 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr { } < >
3583 0         0 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr { } * *
3584             }
3585 0         0 die __FILE__, ": Transliteration replacement not terminated\n";
3586             }
3587             elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) {
3588 0         0 my @tr = ($tr_variable,$2);
3589 0         0 while (not /\G \z/oxgc) {
3590 0 0       0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0       0  
    0          
    0          
    0          
    0          
3591 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr [ ] ( )
3592 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr [ ] { }
3593 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr [ ] [ ]
3594 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr [ ] < >
3595 0         0 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr [ ] * *
3596             }
3597 0         0 die __FILE__, ": Transliteration replacement not terminated\n";
3598             }
3599             elsif (/\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) {
3600 0         0 my @tr = ($tr_variable,$2);
3601 0         0 while (not /\G \z/oxgc) {
3602 0 0       0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0       0  
    0          
    0          
    0          
    0          
3603 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr < > ( )
3604 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr < > { }
3605 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr < > [ ]
3606 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr < > < >
3607 0         0 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr < > * *
3608             }
3609 0         0 die __FILE__, ": Transliteration replacement not terminated\n";
3610             }
3611             # $1 $2 $3 $4 $5 $6
3612             elsif (/\G (\S) ((?:$qq_char)*?) (\1) ((?:$qq_char)*?) (\1) ([cdsrbB]*) /oxgc) { # tr * * *
3613 3         11 my @tr = ($tr_variable,$2);
3614 3         11 return e_tr(@tr,'',$4,$6);
3615             }
3616             }
3617 0         0 die __FILE__, ": Transliteration pattern not terminated\n";
3618             }
3619             }
3620              
3621             # qq//
3622             elsif (/\G \b (qq) \b /oxgc) {
3623 2130         3417 my $ope = $1;
3624              
3625             # if (/\G (\#) ((?:$qq_char)*?) (\#) /oxgc) { return e_qq($ope,$1,$3,$2); } # qq# #
3626 2130 50       3182 if (/\G (\#) /oxgc) { # qq# #
3627 0         0 my $qq_string = '';
3628 0         0 while (not /\G \z/oxgc) {
3629 0 0       0 if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0       0  
    0          
    0          
3630 0         0 elsif (/\G (\\\#) /oxgc) { $qq_string .= $1; }
3631 0         0 elsif (/\G (\#) /oxgc) { return e_qq($ope,'#','#',$qq_string); }
3632 0         0 elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3633             }
3634 0         0 die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3635             }
3636              
3637             else {
3638 2130         2031 my $e = '';
3639 2130         4554 while (not /\G \z/oxgc) {
3640 2130 50       7538 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 50       0  
    100          
    50          
    50          
    0          
3641              
3642             # elsif (/\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qq ( )
3643             elsif (/\G (\() /oxgc) { # qq ( )
3644 0         0 my $qq_string = '';
3645 0         0 local $nest = 1;
3646 0         0 while (not /\G \z/oxgc) {
3647 0 0       0 if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0       0  
    0          
    0          
    0          
3648 0         0 elsif (/\G (\\\)) /oxgc) { $qq_string .= $1; }
3649 0         0 elsif (/\G (\() /oxgc) { $qq_string .= $1; $nest++; }
  0         0  
3650             elsif (/\G (\)) /oxgc) {
3651 0 0       0 if (--$nest == 0) { return $e . e_qq($ope,'(',')',$qq_string); }
  0         0  
3652 0         0 else { $qq_string .= $1; }
3653             }
3654 0         0 elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3655             }
3656 0         0 die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3657             }
3658              
3659             # elsif (/\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qq { }
3660             elsif (/\G (\{) /oxgc) { # qq { }
3661 2100         1872 my $qq_string = '';
3662 2100         2400 local $nest = 1;
3663 2100         3802 while (not /\G \z/oxgc) {
3664 82670 100       258055 if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  722 50       1378  
    100          
    100          
    50          
3665 0         0 elsif (/\G (\\\}) /oxgc) { $qq_string .= $1; }
3666 1103         1105 elsif (/\G (\{) /oxgc) { $qq_string .= $1; $nest++; }
  1103         1787  
3667             elsif (/\G (\}) /oxgc) {
3668 3203 100       4041 if (--$nest == 0) { return $e . e_qq($ope,'{','}',$qq_string); }
  2100         3789  
3669 1103         2039 else { $qq_string .= $1; }
3670             }
3671 77642         135008 elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3672             }
3673 0         0 die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3674             }
3675              
3676             # elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qq [ ]
3677             elsif (/\G (\[) /oxgc) { # qq [ ]
3678 0         0 my $qq_string = '';
3679 0         0 local $nest = 1;
3680 0         0 while (not /\G \z/oxgc) {
3681 0 0       0 if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0       0  
    0          
    0          
    0          
3682 0         0 elsif (/\G (\\\]) /oxgc) { $qq_string .= $1; }
3683 0         0 elsif (/\G (\[) /oxgc) { $qq_string .= $1; $nest++; }
  0         0  
3684             elsif (/\G (\]) /oxgc) {
3685 0 0       0 if (--$nest == 0) { return $e . e_qq($ope,'[',']',$qq_string); }
  0         0  
3686 0         0 else { $qq_string .= $1; }
3687             }
3688 0         0 elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3689             }
3690 0         0 die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3691             }
3692              
3693             # elsif (/\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qq < >
3694             elsif (/\G (\<) /oxgc) { # qq < >
3695 30         42 my $qq_string = '';
3696 30         68 local $nest = 1;
3697 30         108 while (not /\G \z/oxgc) {
3698 1166 100       4792 if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  22 50       59  
    50          
    100          
    50          
3699 0         0 elsif (/\G (\\\>) /oxgc) { $qq_string .= $1; }
3700 0         0 elsif (/\G (\<) /oxgc) { $qq_string .= $1; $nest++; }
  0         0  
3701             elsif (/\G (\>) /oxgc) {
3702 30 50       76 if (--$nest == 0) { return $e . e_qq($ope,'<','>',$qq_string); }
  30         82  
3703 0         0 else { $qq_string .= $1; }
3704             }
3705 1114         2330 elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3706             }
3707 0         0 die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3708             }
3709              
3710             # elsif (/\G (\S) ((?:$qq_char)*?) (\1) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qq * *
3711             elsif (/\G (\S) /oxgc) { # qq * *
3712 0         0 my $delimiter = $1;
3713 0         0 my $qq_string = '';
3714 0         0 while (not /\G \z/oxgc) {
3715 0 0       0 if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0       0  
    0          
    0          
3716 0         0 elsif (/\G (\\\Q$delimiter\E) /oxgc) { $qq_string .= $1; }
3717 0         0 elsif (/\G (\Q$delimiter\E) /oxgc) { return $e . e_qq($ope,$delimiter,$delimiter,$qq_string); }
3718 0         0 elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3719             }
3720 0         0 die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3721             }
3722             }
3723 0         0 die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3724             }
3725             }
3726              
3727             # qr//
3728             elsif (/\G \b (qr) \b /oxgc) {
3729 0         0 my $ope = $1;
3730 0 0       0 if (/\G (\#) ((?:$qq_char)*?) (\#) ([imosxpadlunbB]*) /oxgc) { # qr# # #
3731 0         0 return e_qr($ope,$1,$3,$2,$4);
3732             }
3733             else {
3734 0         0 my $e = '';
3735 0         0 while (not /\G \z/oxgc) {
3736 0 0       0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0       0  
    0          
    0          
    0          
    0          
    0          
    0          
3737 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([imosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # qr ( )
3738 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([imosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # qr { }
3739 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([imosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # qr [ ]
3740 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([imosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # qr < >
3741 0         0 elsif (/\G (\') ((?:$qq_char)*?) (\') ([imosxpadlunbB]*) /oxgc) { return $e . e_qr_q($ope,$1, $3, $2,$4); } # qr ' '
3742 0         0 elsif (/\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ([imosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,'{','}',$2,$4); } # qr | | --> qr { }
3743 0         0 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([imosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # qr * *
3744             }
3745 0         0 die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3746             }
3747             }
3748              
3749             # qw//
3750             elsif (/\G \b (qw) \b /oxgc) {
3751 16         41 my $ope = $1;
3752 16 50       64 if (/\G (\#) (.*?) (\#) /oxmsgc) { # qw# #
3753 0         0 return e_qw($ope,$1,$3,$2);
3754             }
3755             else {
3756 16         26 my $e = '';
3757 16         51 while (not /\G \z/oxgc) {
3758 16 50       118 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 50       0  
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
3759              
3760 16         56 elsif (/\G (\() ([^(]*?) (\)) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw ( )
3761 0         0 elsif (/\G (\() ((?:$q_paren)*?) (\)) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw ( )
3762              
3763 0         0 elsif (/\G (\{) ([^{]*?) (\}) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw { }
3764 0         0 elsif (/\G (\{) ((?:$q_brace)*?) (\}) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw { }
3765              
3766 0         0 elsif (/\G (\[) ([^[]*?) (\]) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw [ ]
3767 0         0 elsif (/\G (\[) ((?:$q_bracket)*?) (\]) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw [ ]
3768              
3769 0         0 elsif (/\G (\<) ([^<]*?) (\>) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw < >
3770 0         0 elsif (/\G (\<) ((?:$q_angle)*?) (\>) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw < >
3771              
3772 0         0 elsif (/\G ([\x21-\x3F]) (.*?) (\1) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw * *
3773 0         0 elsif (/\G (\S) ((?:$q_char)*?) (\1) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw * *
3774             }
3775 0         0 die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3776             }
3777             }
3778              
3779             # qx//
3780             elsif (/\G \b (qx) \b /oxgc) {
3781 0         0 my $ope = $1;
3782 0 0       0 if (/\G (\#) ((?:$qq_char)*?) (\#) /oxgc) { # qx# #
3783 0         0 return e_qq($ope,$1,$3,$2);
3784             }
3785             else {
3786 0         0 my $e = '';
3787 0         0 while (not /\G \z/oxgc) {
3788 0 0       0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0       0  
    0          
    0          
    0          
    0          
    0          
3789 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qx ( )
3790 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qx { }
3791 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qx [ ]
3792 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qx < >
3793 0         0 elsif (/\G (\') ((?:$qq_char)*?) (\') /oxgc) { return $e . e_q ($ope,$1,$3,$2); } # qx ' '
3794 0         0 elsif (/\G (\S) ((?:$qq_char)*?) (\1) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qx * *
3795             }
3796 0         0 die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3797             }
3798             }
3799              
3800             # q//
3801             elsif (/\G \b (q) \b /oxgc) {
3802 245         647 my $ope = $1;
3803              
3804             # if (/\G (\#) ((?:\\\#|\\\\|$q_char)*?) (\#) /oxgc) { return e_q($ope,$1,$3,$2); } # q# #
3805              
3806             # avoid "Error: Runtime exception" of perl version 5.005_03
3807             # (and so on)
3808              
3809 245 50       713 if (/\G (\#) /oxgc) { # q# #
3810 0         0 my $q_string = '';
3811 0         0 while (not /\G \z/oxgc) {
3812 0 0       0 if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0       0  
    0          
    0          
3813 0         0 elsif (/\G (\\\#) /oxgc) { $q_string .= $1; }
3814 0         0 elsif (/\G (\#) /oxgc) { return e_q($ope,'#','#',$q_string); }
3815 0         0 elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3816             }
3817 0         0 die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3818             }
3819              
3820             else {
3821 245         451 my $e = '';
3822 245         972 while (not /\G \z/oxgc) {
3823 245 50       1594 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 50       0  
    100          
    50          
    100          
    50          
3824              
3825             # elsif (/\G (\() ((?:\\\)|\\\\|$q_paren)*?) (\)) /oxgc) { return $e . e_q($ope,$1,$3,$2); } # q ( )
3826             elsif (/\G (\() /oxgc) { # q ( )
3827 0         0 my $q_string = '';
3828 0         0 local $nest = 1;
3829 0         0 while (not /\G \z/oxgc) {
3830 0 0       0 if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0       0  
    0          
    0          
    0          
    0          
3831 0         0 elsif (/\G (\\\)) /oxgc) { $q_string .= $1; }
3832 0         0 elsif (/\G (\\\() /oxgc) { $q_string .= $1; }
3833 0         0 elsif (/\G (\() /oxgc) { $q_string .= $1; $nest++; }
  0         0  
3834             elsif (/\G (\)) /oxgc) {
3835 0 0       0 if (--$nest == 0) { return $e . e_q($ope,'(',')',$q_string); }
  0         0  
3836 0         0 else { $q_string .= $1; }
3837             }
3838 0         0 elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3839             }
3840 0         0 die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3841             }
3842              
3843             # elsif (/\G (\{) ((?:\\\}|\\\\|$q_brace)*?) (\}) /oxgc) { return $e . e_q($ope,$1,$3,$2); } # q { }
3844             elsif (/\G (\{) /oxgc) { # q { }
3845 239         384 my $q_string = '';
3846 239         435 local $nest = 1;
3847 239         899 while (not /\G \z/oxgc) {
3848 3663 50       17546 if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 50       0  
    50          
    100          
    100          
    50          
3849 0         0 elsif (/\G (\\\}) /oxgc) { $q_string .= $1; }
3850 0         0 elsif (/\G (\\\{) /oxgc) { $q_string .= $1; }
3851 107         139 elsif (/\G (\{) /oxgc) { $q_string .= $1; $nest++; }
  107         205  
3852             elsif (/\G (\}) /oxgc) {
3853 346 100       720 if (--$nest == 0) { return $e . e_q($ope,'{','}',$q_string); }
  239         797  
3854 107         235 else { $q_string .= $1; }
3855             }
3856 3210         6472 elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3857             }
3858 0         0 die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3859             }
3860              
3861             # elsif (/\G (\[) ((?:\\\]|\\\\|$q_bracket)*?) (\]) /oxgc) { return $e . e_q($ope,$1,$3,$2); } # q [ ]
3862             elsif (/\G (\[) /oxgc) { # q [ ]
3863 0         0 my $q_string = '';
3864 0         0 local $nest = 1;
3865 0         0 while (not /\G \z/oxgc) {
3866 0 0       0 if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0       0  
    0          
    0          
    0          
    0          
3867 0         0 elsif (/\G (\\\]) /oxgc) { $q_string .= $1; }
3868 0         0 elsif (/\G (\\\[) /oxgc) { $q_string .= $1; }
3869 0         0 elsif (/\G (\[) /oxgc) { $q_string .= $1; $nest++; }
  0         0  
3870             elsif (/\G (\]) /oxgc) {
3871 0 0       0 if (--$nest == 0) { return $e . e_q($ope,'[',']',$q_string); }
  0         0  
3872 0         0 else { $q_string .= $1; }
3873             }
3874 0         0 elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3875             }
3876 0         0 die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3877             }
3878              
3879             # elsif (/\G (\<) ((?:\\\>|\\\\|$q_angle)*?) (\>) /oxgc) { return $e . e_q($ope,$1,$3,$2); } # q < >
3880             elsif (/\G (\<) /oxgc) { # q < >
3881 5         7 my $q_string = '';
3882 5         11 local $nest = 1;
3883 5         59 while (not /\G \z/oxgc) {
3884 88 50       478 if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 50       0  
    50          
    50          
    100          
    50          
3885 0         0 elsif (/\G (\\\>) /oxgc) { $q_string .= $1; }
3886 0         0 elsif (/\G (\\\<) /oxgc) { $q_string .= $1; }
3887 0         0 elsif (/\G (\<) /oxgc) { $q_string .= $1; $nest++; }
  0         0  
3888             elsif (/\G (\>) /oxgc) {
3889 5 50       14 if (--$nest == 0) { return $e . e_q($ope,'<','>',$q_string); }
  5         14  
3890 0         0 else { $q_string .= $1; }
3891             }
3892 83         163 elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3893             }
3894 0         0 die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3895             }
3896              
3897             # elsif (/\G (\S) ((?:\\\1|\\\\|$q_char)*?) (\1) /oxgc) { return $e . e_q($ope,$1,$3,$2); } # q * *
3898             elsif (/\G (\S) /oxgc) { # q * *
3899 1         6 my $delimiter = $1;
3900 1         3 my $q_string = '';
3901 1         5 while (not /\G \z/oxgc) {
3902 14 50       97 if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 50       0  
    100          
    50          
3903 0         0 elsif (/\G (\\\Q$delimiter\E) /oxgc) { $q_string .= $1; }
3904 1         3 elsif (/\G (\Q$delimiter\E) /oxgc) { return $e . e_q($ope,$delimiter,$delimiter,$q_string); }
3905 13         40 elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3906             }
3907 0         0 die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3908             }
3909             }
3910 0         0 die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3911             }
3912             }
3913              
3914             # m//
3915             elsif (/\G \b (m) \b /oxgc) {
3916 209         438 my $ope = $1;
3917 209 50       1761 if (/\G (\#) ((?:$qq_char)*?) (\#) ([cgimosxpadlunbB]*) /oxgc) { # m# #
3918 0         0 return e_qr($ope,$1,$3,$2,$4);
3919             }
3920             else {
3921 209         268 my $e = '';
3922 209         603 while (not /\G \z/oxgc) {
3923 209 50       12842 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 50       0  
    50          
    50          
    50          
    50          
    100          
    50          
    50          
3924 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cgimosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m ( )
3925 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cgimosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m { }
3926 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cgimosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m [ ]
3927 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cgimosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m < >
3928 0         0 elsif (/\G (\?) ((?:$qq_char)*?) (\?) ([cgimosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m ? ?
3929 10         32 elsif (/\G (\') ((?:$qq_char)*?) (\') ([cgimosxpadlunbB]*) /oxgc) { return $e . e_qr_q($ope,$1, $3, $2,$4); } # m ' '
3930 0         0 elsif (/\G ([*\-:\\^|]) ((?:$qq_char)*?) (\1) ([cgimosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,'{','}',$2,$4); } # m | | --> m { }
3931 199         594 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cgimosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m * *
3932             }
3933 0         0 die __FILE__, ": Search pattern not terminated\n";
3934             }
3935             }
3936              
3937             # s///
3938              
3939             # about [cegimosxpradlunbB]* (/cg modifier)
3940             #
3941             # P.67 Pattern-Matching Operators
3942             # of ISBN 0-596-00241-6 Perl in a Nutshell, Second Edition.
3943              
3944             elsif (/\G \b (s) \b /oxgc) {
3945 97         222 my $ope = $1;
3946              
3947             # $1 $2 $3 $4 $5 $6
3948 97 100       2098 if (/\G (\#) ((?:$qq_char)*?) (\#) ((?:$qq_char)*?) (\#) ([cegimosxpradlunbB]*) /oxgc) { # s# # #
3949 1         4 return e_sub($sub_variable,$1,$2,$3,$3,$4,$5,$6);
3950             }
3951             else {
3952 96         139 my $e = '';
3953 96         324 while (not /\G \z/oxgc) {
3954 96 50       12341 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 50       0  
    50          
    50          
    50          
    100          
    50          
    50          
    50          
3955             elsif (/\G (\() ((?:$qq_paren)*?) (\)) /oxgc) {
3956 0         0 my @s = ($1,$2,$3);
3957 0         0 while (not /\G \z/oxgc) {
3958 0 0       0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0       0  
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
3959             # $1 $2 $3 $4
3960 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3961 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3962 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3963 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3964 0         0 elsif (/\G (\') ((?:$qq_char)*?) (\') ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3965 0         0 elsif (/\G (\$) ((?:$qq_char)*?) (\$) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3966 0         0 elsif (/\G (\:) ((?:$qq_char)*?) (\:) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3967 0         0 elsif (/\G (\@) ((?:$qq_char)*?) (\@) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3968 0         0 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3969             }
3970 0         0 die __FILE__, ": Substitution replacement not terminated\n";
3971             }
3972             elsif (/\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) {
3973 0         0 my @s = ($1,$2,$3);
3974 0         0 while (not /\G \z/oxgc) {
3975 0 0       0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0       0  
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
3976             # $1 $2 $3 $4
3977 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3978 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3979 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3980 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3981 0         0 elsif (/\G (\') ((?:$qq_char)*?) (\') ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3982 0         0 elsif (/\G (\$) ((?:$qq_char)*?) (\$) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3983 0         0 elsif (/\G (\:) ((?:$qq_char)*?) (\:) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3984 0         0 elsif (/\G (\@) ((?:$qq_char)*?) (\@) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3985 0         0 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3986             }
3987 0         0 die __FILE__, ": Substitution replacement not terminated\n";
3988             }
3989             elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) {
3990 0         0 my @s = ($1,$2,$3);
3991 0         0 while (not /\G \z/oxgc) {
3992 0 0       0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0       0  
    0          
    0          
    0          
    0          
    0          
    0          
3993             # $1 $2 $3 $4
3994 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3995 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3996 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3997 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3998 0         0 elsif (/\G (\') ((?:$qq_char)*?) (\') ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3999 0         0 elsif (/\G (\$) ((?:$qq_char)*?) (\$) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
4000 0         0 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
4001             }
4002 0         0 die __FILE__, ": Substitution replacement not terminated\n";
4003             }
4004             elsif (/\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) {
4005 0         0 my @s = ($1,$2,$3);
4006 0         0 while (not /\G \z/oxgc) {
4007 0 0       0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0       0  
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
4008             # $1 $2 $3 $4
4009 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
4010 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
4011 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
4012 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
4013 0         0 elsif (/\G (\') ((?:$qq_char)*?) (\') ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
4014 0         0 elsif (/\G (\$) ((?:$qq_char)*?) (\$) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
4015 0         0 elsif (/\G (\:) ((?:$qq_char)*?) (\:) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
4016 0         0 elsif (/\G (\@) ((?:$qq_char)*?) (\@) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
4017 0         0 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
4018             }
4019 0         0 die __FILE__, ": Substitution replacement not terminated\n";
4020             }
4021             # $1 $2 $3 $4 $5 $6
4022             elsif (/\G (\') ((?:$qq_char)*?) (\') ((?:$qq_char)*?) (\') ([cegimosxpradlunbB]*) /oxgc) {
4023 21         57 return e_sub($sub_variable,$1,$2,$3,$3,$4,$5,$6);
4024             }
4025             # $1 $2 $3 $4 $5 $6
4026             elsif (/\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ((?:$qq_char)*?) (\1) ([cegimosxpradlunbB]*) /oxgc) {
4027 0         0 return e_sub($sub_variable,'{',$2,'}','{',$4,'}',$6); # s | | | --> s { } { }
4028             }
4029             # $1 $2 $3 $4 $5 $6
4030             elsif (/\G (\$) ((?:$qq_char)*?) (\1) ((?:$qq_char)*?) (\1) ([cegimosxpradlunbB]*) /oxgc) {
4031 0         0 return e_sub($sub_variable,$1,$2,$3,$3,$4,$5,$6);
4032             }
4033             # $1 $2 $3 $4 $5 $6
4034             elsif (/\G (\S) ((?:$qq_char)*?) (\1) ((?:$qq_char)*?) (\1) ([cegimosxpradlunbB]*) /oxgc) {
4035 75         290 return e_sub($sub_variable,$1,$2,$3,$3,$4,$5,$6);
4036             }
4037             }
4038 0         0 die __FILE__, ": Substitution pattern not terminated\n";
4039             }
4040             }
4041              
4042             # require ignore module
4043 0         0 elsif (/\G \b require ((?>\s+) (?:$ignore_modules) .*? ;) ([ \t]* [#\n]) /oxmsgc) { return "# require$1$2"; }
4044 0         0 elsif (/\G \b require ((?>\s+) (?:$ignore_modules) .*? ;) ([ \t]* [^#]) /oxmsgc) { return "# require$1\n$2"; }
4045 0         0 elsif (/\G \b require ((?>\s+) (?:$ignore_modules)) \b /oxmsgc) { return "# require$1"; }
4046              
4047             # use strict; --> use strict; no strict qw(refs);
4048 36         264 elsif (/\G \b use ((?>\s+) strict .*? ;) ([ \t]* [#\n]) /oxmsgc) { return "use$1 no strict qw(refs);$2"; }
4049 0         0 elsif (/\G \b use ((?>\s+) strict .*? ;) ([ \t]* [^#]) /oxmsgc) { return "use$1 no strict qw(refs);\n$2"; }
4050 0         0 elsif (/\G \b use ((?>\s+) strict) \b /oxmsgc) { return "use$1; no strict qw(refs)"; }
4051              
4052             # use 5.12.0; --> use 5.12.0; no strict qw(refs);
4053             elsif (/\G \b use (?>\s+) ((?>([1-9][0-9_]*)(?:\.([0-9_]+))*)) (?>\s*) ; /oxmsgc) {
4054 2 50 33     23 if (($2 >= 6) or (($2 == 5) and ($3 ge '012'))) {
      33        
4055 0         0 return "use $1; no strict qw(refs);";
4056             }
4057             else {
4058 2         9 return "use $1;";
4059             }
4060             }
4061             elsif (/\G \b use (?>\s+) ((?>v([0-9][0-9_]*)(?:\.([0-9_]+))*)) (?>\s*) ; /oxmsgc) {
4062 0 0 0     0 if (($2 >= 6) or (($2 == 5) and ($3 >= 12))) {
      0        
4063 0         0 return "use $1; no strict qw(refs);";
4064             }
4065             else {
4066 0         0 return "use $1;";
4067             }
4068             }
4069              
4070             # ignore use module
4071 2         18 elsif (/\G \b use ((?>\s+) (?:$ignore_modules) .*? ;) ([ \t]* [#\n]) /oxmsgc) { return "# use$1$2"; }
4072 0         0 elsif (/\G \b use ((?>\s+) (?:$ignore_modules) .*? ;) ([ \t]* [^#]) /oxmsgc) { return "# use$1\n$2"; }
4073 0         0 elsif (/\G \b use ((?>\s+) (?:$ignore_modules)) \b /oxmsgc) { return "# use$1"; }
4074              
4075             # ignore no module
4076 0         0 elsif (/\G \b no ((?>\s+) (?:$ignore_modules) .*? ;) ([ \t]* [#\n]) /oxmsgc) { return "# no$1$2"; }
4077 0         0 elsif (/\G \b no ((?>\s+) (?:$ignore_modules) .*? ;) ([ \t]* [^#]) /oxmsgc) { return "# no$1\n$2"; }
4078 0         0 elsif (/\G \b no ((?>\s+) (?:$ignore_modules)) \b /oxmsgc) { return "# no$1"; }
4079              
4080             # use else
4081 0         0 elsif (/\G \b use \b /oxmsgc) { return "use"; }
4082              
4083             # use else
4084 2         10 elsif (/\G \b no \b /oxmsgc) { return "no"; }
4085              
4086             # ''
4087             elsif (/\G (?
4088 841         1212 my $q_string = '';
4089 841         2120 while (not /\G \z/oxgc) {
4090 8235 100       26901 if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  4 100       13  
    100          
    50          
4091 48         109 elsif (/\G (\\\') /oxgc) { $q_string .= $1; }
4092 841         2197 elsif (/\G \' /oxgc) { return e_q('', "'","'",$q_string); }
4093 7342         13707 elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
4094             }
4095 0         0 die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4096             }
4097              
4098             # ""
4099             elsif (/\G (\") /oxgc) {
4100 1817         2479 my $qq_string = '';
4101 1817         4043 while (not /\G \z/oxgc) {
4102 34872 100       100464 if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  67 100       143  
    100          
    50          
4103 12         28 elsif (/\G (\\\") /oxgc) { $qq_string .= $1; }
4104 1817         3712 elsif (/\G \" /oxgc) { return e_qq('', '"','"',$qq_string); }
4105 32976         59884 elsif (/\G ($q_char) /oxgc) { $qq_string .= $1; }
4106             }
4107 0         0 die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4108             }
4109              
4110             # ``
4111             elsif (/\G (\`) /oxgc) {
4112 1         1 my $qx_string = '';
4113 1         4 while (not /\G \z/oxgc) {
4114 19 50       71 if (/\G (\\\\) /oxgc) { $qx_string .= $1; }
  0 50       0  
    100          
    50          
4115 0         0 elsif (/\G (\\\`) /oxgc) { $qx_string .= $1; }
4116 1         2 elsif (/\G \` /oxgc) { return e_qq('', '`','`',$qx_string); }
4117 18         28 elsif (/\G ($q_char) /oxgc) { $qx_string .= $1; }
4118             }
4119 0         0 die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4120             }
4121              
4122             # // --- not divide operator (num / num), not defined-or
4123             elsif (($slash eq 'm//') and /\G (\/) /oxgc) {
4124 452         688 my $regexp = '';
4125 452         1218 while (not /\G \z/oxgc) {
4126 4490 50       15245 if (/\G (\\\\) /oxgc) { $regexp .= $1; }
  0 50       0  
    100          
    50          
4127 0         0 elsif (/\G (\\\/) /oxgc) { $regexp .= $1; }
4128 452         1214 elsif (/\G \/ ([cgimosxpadlunbB]*) /oxgc) { return e_qr('', '/','/',$regexp,$1); }
4129 4038         7734 elsif (/\G ($q_char) /oxgc) { $regexp .= $1; }
4130             }
4131 0         0 die __FILE__, ": Search pattern not terminated\n";
4132             }
4133              
4134             # ?? --- not conditional operator (condition ? then : else)
4135             elsif (($slash eq 'm//') and /\G (\?) /oxgc) {
4136 0         0 my $regexp = '';
4137 0         0 while (not /\G \z/oxgc) {
4138 0 0       0 if (/\G (\\\\) /oxgc) { $regexp .= $1; }
  0 0       0  
    0          
    0          
4139 0         0 elsif (/\G (\\\?) /oxgc) { $regexp .= $1; }
4140 0         0 elsif (/\G \? ([cgimosxpadlunbB]*) /oxgc) { return e_qr('m','?','?',$regexp,$1); }
4141 0         0 elsif (/\G ($q_char) /oxgc) { $regexp .= $1; }
4142             }
4143 0         0 die __FILE__, ": Search pattern not terminated\n";
4144             }
4145              
4146             # <<>> (a safer ARGV)
4147 0         0 elsif (/\G ( <<>> ) /oxgc) { $slash = 'm//'; return $1; }
  0         0  
4148              
4149             # << (bit shift) --- not here document
4150 0         0 elsif (/\G ( << (?>\s*) ) (?= [0-9\$\@\&] ) /oxgc) { $slash = 'm//'; return $1; }
  0         0  
4151              
4152             # <<'HEREDOC'
4153             elsif (/\G ( << '([a-zA-Z_0-9]*)' ) /oxgc) {
4154 72         88 $slash = 'm//';
4155 72         110 my $here_quote = $1;
4156 72         90 my $delimiter = $2;
4157              
4158             # get here document
4159 72 50       124 if ($here_script eq '') {
4160 72         321 $here_script = CORE::substr $_, pos $_;
4161 72         334 $here_script =~ s/.*?\n//oxm;
4162             }
4163 72 50       487 if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4164 72         181 push @heredoc, $1 . qq{\n$delimiter\n};
4165 72         100 push @heredoc_delimiter, $delimiter;
4166             }
4167             else {
4168 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4169             }
4170 72         235 return $here_quote;
4171             }
4172              
4173             # <<\HEREDOC
4174              
4175             # P.66 2.6.6. "Here" Documents
4176             # in Chapter 2: Bits and Pieces
4177             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
4178              
4179             # P.73 "Here" Documents
4180             # in Chapter 2: Bits and Pieces
4181             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
4182              
4183             elsif (/\G ( << \\([a-zA-Z_0-9]+) ) /oxgc) {
4184 0         0 $slash = 'm//';
4185 0         0 my $here_quote = $1;
4186 0         0 my $delimiter = $2;
4187              
4188             # get here document
4189 0 0       0 if ($here_script eq '') {
4190 0         0 $here_script = CORE::substr $_, pos $_;
4191 0         0 $here_script =~ s/.*?\n//oxm;
4192             }
4193 0 0       0 if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4194 0         0 push @heredoc, $1 . qq{\n$delimiter\n};
4195 0         0 push @heredoc_delimiter, $delimiter;
4196             }
4197             else {
4198 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4199             }
4200 0         0 return $here_quote;
4201             }
4202              
4203             # <<"HEREDOC"
4204             elsif (/\G ( << "([a-zA-Z_0-9]*)" ) /oxgc) {
4205 36         60 $slash = 'm//';
4206 36         65 my $here_quote = $1;
4207 36         411 my $delimiter = $2;
4208              
4209             # get here document
4210 36 50       84 if ($here_script eq '') {
4211 36         215 $here_script = CORE::substr $_, pos $_;
4212 36         180 $here_script =~ s/.*?\n//oxm;
4213             }
4214 36 50       714 if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4215 36         94 push @heredoc, e_heredoc($1) . qq{\n$delimiter\n};
4216 36         134 push @heredoc_delimiter, $delimiter;
4217             }
4218             else {
4219 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4220             }
4221 36         140 return $here_quote;
4222             }
4223              
4224             # <
4225             elsif (/\G ( << ([a-zA-Z_0-9]+) ) /oxgc) {
4226 42         70 $slash = 'm//';
4227 42         85 my $here_quote = $1;
4228 42         69 my $delimiter = $2;
4229              
4230             # get here document
4231 42 50       106 if ($here_script eq '') {
4232 42         373 $here_script = CORE::substr $_, pos $_;
4233 42         278 $here_script =~ s/.*?\n//oxm;
4234             }
4235 42 50       574 if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4236 42         117 push @heredoc, e_heredoc($1) . qq{\n$delimiter\n};
4237 42         77 push @heredoc_delimiter, $delimiter;
4238             }
4239             else {
4240 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4241             }
4242 42         179 return $here_quote;
4243             }
4244              
4245             # <<`HEREDOC`
4246             elsif (/\G ( << `([a-zA-Z_0-9]*)` ) /oxgc) {
4247 0         0 $slash = 'm//';
4248 0         0 my $here_quote = $1;
4249 0         0 my $delimiter = $2;
4250              
4251             # get here document
4252 0 0       0 if ($here_script eq '') {
4253 0         0 $here_script = CORE::substr $_, pos $_;
4254 0         0 $here_script =~ s/.*?\n//oxm;
4255             }
4256 0 0       0 if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4257 0         0 push @heredoc, e_heredoc($1) . qq{\n$delimiter\n};
4258 0         0 push @heredoc_delimiter, $delimiter;
4259             }
4260             else {
4261 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4262             }
4263 0         0 return $here_quote;
4264             }
4265              
4266             # <<= <=> <= < operator
4267             elsif (/\G ( <<= | <=> | <= | < ) (?= (?>\s*) [A-Za-z_0-9'"`\$\@\&\*\(\+\-] )/oxgc) {
4268 11         44 return $1;
4269             }
4270              
4271             #
4272             elsif (/\G (<[\$]?[A-Za-z_][A-Za-z_0-9]*>) /oxgc) {
4273 0         0 return $1;
4274             }
4275              
4276             # --- glob
4277              
4278             # avoid "Error: Runtime exception" of perl version 5.005_03
4279              
4280             elsif (/\G < ((?:[^>\0\a\e\f\n\r\t])+?) > /oxgc) {
4281 0         0 return 'Ecyrillic::glob("' . $1 . '")';
4282             }
4283              
4284             # __DATA__
4285 0         0 elsif (/\G ^ ( __DATA__ \n .*) \z /oxmsgc) { return $1; }
4286              
4287             # __END__
4288 200         1298 elsif (/\G ^ ( __END__ \n .*) \z /oxmsgc) { return $1; }
4289              
4290             # \cD Control-D
4291              
4292             # P.68 2.6.8. Other Literal Tokens
4293             # in Chapter 2: Bits and Pieces
4294             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
4295              
4296             # P.76 Other Literal Tokens
4297             # in Chapter 2: Bits and Pieces
4298             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
4299              
4300 0         0 elsif (/\G ( \cD .*) \z /oxmsgc) { return $1; }
4301              
4302             # \cZ Control-Z
4303 0         0 elsif (/\G ( \cZ .*) \z /oxmsgc) { return $1; }
4304              
4305             # any operator before div
4306             elsif (/\G (
4307             -- | \+\+ |
4308             [\)\}\]]
4309              
4310 4824         5597 ) /oxgc) { $slash = 'div'; return $1; }
  4824         19039  
4311              
4312             # yada-yada or triple-dot operator
4313             elsif (/\G (
4314             \.\.\.
4315              
4316 7         15 ) /oxgc) { $slash = 'm//'; return q{die('Unimplemented')}; }
  7         35  
4317              
4318             # any operator before m//
4319              
4320             # //, //= (defined-or)
4321              
4322             # P.164 Logical Operators
4323             # in Chapter 10: More Control Structures
4324             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
4325              
4326             # P.119 C-Style Logical (Short-Circuit) Operators
4327             # in Chapter 3: Unary and Binary Operators
4328             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
4329              
4330             # (and so on)
4331              
4332             # ~~
4333              
4334             # P.221 The Smart Match Operator
4335             # in Chapter 15: Smart Matching and given-when
4336             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
4337              
4338             # P.112 Smartmatch Operator
4339             # in Chapter 3: Unary and Binary Operators
4340             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
4341              
4342             # (and so on)
4343              
4344             elsif (/\G ((?>
4345              
4346             !~~ | !~ | != | ! |
4347             %= | % |
4348             &&= | && | &= | &\.= | &\. | & |
4349             -= | -> | - |
4350             :(?>\s*)= |
4351             : |
4352             <<>> |
4353             <<= | <=> | <= | < |
4354             == | => | =~ | = |
4355             >>= | >> | >= | > |
4356             \*\*= | \*\* | \*= | \* |
4357             \+= | \+ |
4358             \.\. | \.= | \. |
4359             \/\/= | \/\/ |
4360             \/= | \/ |
4361             \? |
4362             \\ |
4363             \^= | \^\.= | \^\. | \^ |
4364             \b x= |
4365             \|\|= | \|\| | \|= | \|\.= | \|\. | \| |
4366             ~~ | ~\. | ~ |
4367             \b(?: and | cmp | eq | ge | gt | le | lt | ne | not | or | xor | x )\b |
4368             \b(?: print )\b |
4369              
4370             [,;\(\{\[]
4371              
4372 8520         9315 )) /oxgc) { $slash = 'm//'; return $1; }
  8520         32007  
4373              
4374             # other any character
4375 14988         15401 elsif (/\G ($q_char) /oxgc) { $slash = 'div'; return $1; }
  14988         55565  
4376              
4377             # system error
4378             else {
4379 0         0 die __FILE__, ": Oops, this shouldn't happen!\n";
4380             }
4381             }
4382              
4383             # escape Cyrillic string
4384             sub e_string {
4385 1718     1718 0 2973 my($string) = @_;
4386 1718         1711 my $e_string = '';
4387              
4388 1718         1999 local $slash = 'm//';
4389              
4390             # P.1024 Appendix W.10 Multibyte Processing
4391             # of ISBN 1-56592-224-7 CJKV Information Processing
4392             # (and so on)
4393              
4394 1718         14655 my @char = $string =~ / \G (?>[^\\]|\\$q_char|$q_char) /oxmsg;
4395              
4396             # without { ... }
4397 1718 100 66     7252 if (not (grep(/\A \{ \z/xms, @char) and grep(/\A \} \z/xms, @char))) {
4398 1701 50       3326 if ($string !~ /<
4399 1701         3622 return $string;
4400             }
4401             }
4402              
4403             E_STRING_LOOP:
4404 17         56 while ($string !~ /\G \z/oxgc) {
4405 190 50       11774 if (0) {
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    100          
    100          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    100          
    50          
    100          
    50          
4406             }
4407              
4408             # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> @{[Ecyrillic::PREMATCH()]}
4409 0         0 elsif ($string =~ /\G ( \$` | \$\{`\} | \$ (?>\s*) PREMATCH \b | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} ) /oxmsgc) {
4410 0         0 $e_string .= q{Ecyrillic::PREMATCH()};
4411 0         0 $slash = 'div';
4412             }
4413              
4414             # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> @{[Ecyrillic::MATCH()]}
4415             elsif ($string =~ /\G ( \$& | \$\{&\} | \$ (?>\s*) MATCH \b | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} ) /oxmsgc) {
4416 0         0 $e_string .= q{Ecyrillic::MATCH()};
4417 0         0 $slash = 'div';
4418             }
4419              
4420             # $', ${'} --> $', ${'}
4421             elsif ($string =~ /\G ( \$' | \$\{'\} ) /oxmsgc) {
4422 0         0 $e_string .= $1;
4423 0         0 $slash = 'div';
4424             }
4425              
4426             # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> @{[Ecyrillic::POSTMATCH()]}
4427             elsif ($string =~ /\G ( \$ (?>\s*) POSTMATCH \b | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} ) /oxmsgc) {
4428 0         0 $e_string .= q{Ecyrillic::POSTMATCH()};
4429 0         0 $slash = 'div';
4430             }
4431              
4432             # bareword
4433             elsif ($string =~ /\G ( \{ (?>\s*) (?: tr | index | rindex | reverse ) (?>\s*) \} ) /oxmsgc) {
4434 0         0 $e_string .= $1;
4435 0         0 $slash = 'div';
4436             }
4437              
4438             # $0 --> $0
4439             elsif ($string =~ /\G ( \$ 0 ) /oxmsgc) {
4440 0         0 $e_string .= $1;
4441 0         0 $slash = 'div';
4442             }
4443             elsif ($string =~ /\G ( \$ \{ (?>\s*) 0 (?>\s*) \} ) /oxmsgc) {
4444 0         0 $e_string .= $1;
4445 0         0 $slash = 'div';
4446             }
4447              
4448             # $$ --> $$
4449             elsif ($string =~ /\G ( \$ \$ ) (?![\w\{]) /oxmsgc) {
4450 0         0 $e_string .= $1;
4451 0         0 $slash = 'div';
4452             }
4453              
4454             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
4455             # $1, $2, $3 --> $1, $2, $3 otherwise
4456             elsif ($string =~ /\G \$ ((?>[1-9][0-9]*)) /oxmsgc) {
4457 0         0 $e_string .= e_capture($1);
4458 0         0 $slash = 'div';
4459             }
4460             elsif ($string =~ /\G \$ \{ (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} /oxmsgc) {
4461 0         0 $e_string .= e_capture($1);
4462 0         0 $slash = 'div';
4463             }
4464              
4465             # $$foo[ ... ] --> $ $foo->[ ... ]
4466             elsif ($string =~ /\G \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \[ .+? \] ) /oxmsgc) {
4467 0         0 $e_string .= e_capture($1.'->'.$2);
4468 0         0 $slash = 'div';
4469             }
4470              
4471             # $$foo{ ... } --> $ $foo->{ ... }
4472             elsif ($string =~ /\G \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \{ .+? \} ) /oxmsgc) {
4473 0         0 $e_string .= e_capture($1.'->'.$2);
4474 0         0 $slash = 'div';
4475             }
4476              
4477             # $$foo
4478             elsif ($string =~ /\G \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) /oxmsgc) {
4479 0         0 $e_string .= e_capture($1);
4480 0         0 $slash = 'div';
4481             }
4482              
4483             # ${ foo }
4484             elsif ($string =~ /\G \$ (?>\s*) \{ ((?> \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* )) \} /oxmsgc) {
4485 0         0 $e_string .= '${' . $1 . '}';
4486 0         0 $slash = 'div';
4487             }
4488              
4489             # ${ ... }
4490             elsif ($string =~ /\G \$ (?>\s*) \{ (?>\s*) ( $qq_brace ) (?>\s*) \} /oxmsgc) {
4491 3         9 $e_string .= e_capture($1);
4492 3         13 $slash = 'div';
4493             }
4494              
4495             # variable or function
4496             # $ @ % & * $ #
4497             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) {
4498 7         14 $e_string .= $1;
4499 7         17 $slash = 'div';
4500             }
4501             # $ $ $ $ $ $ $ $ $ $ $ $ $ $
4502             # $ @ # \ ' " / ? ( ) [ ] < >
4503             elsif ($string =~ /\G ( \$[\$\@\#\\\'\"\/\?\(\)\[\]\<\>] ) /oxmsgc) {
4504 0         0 $e_string .= $1;
4505 0         0 $slash = 'div';
4506             }
4507              
4508             # subroutines of package Ecyrillic
4509 0         0 elsif ($string =~ /\G \b (CORE:: | ->(>?\s*) (?: atan2 | [a-z]{2,})) \b /oxgc) { $e_string .= $1; $slash = 'm//'; }
  0         0  
4510 0         0 elsif ($string =~ /\G \b Char::eval (?= (?>\s*) \{ ) /oxgc) { $e_string .= 'eval'; $slash = 'm//'; }
  0         0  
4511 0         0 elsif ($string =~ /\G \b Cyrillic::eval (?= (?>\s*) \{ ) /oxgc) { $e_string .= 'eval'; $slash = 'm//'; }
  0         0  
4512 0         0 elsif ($string =~ /\G \b Char::eval \b /oxgc) { $e_string .= 'eval Char::escape'; $slash = 'm//'; }
  0         0  
4513 0         0 elsif ($string =~ /\G \b Cyrillic::eval \b /oxgc) { $e_string .= 'eval Cyrillic::escape'; $slash = 'm//'; }
  0         0  
4514 0         0 elsif ($string =~ /\G \b bytes::substr \b /oxgc) { $e_string .= 'substr'; $slash = 'm//'; }
  0         0  
4515 0         0 elsif ($string =~ /\G \b chop \b /oxgc) { $e_string .= 'Ecyrillic::chop'; $slash = 'm//'; }
  0         0  
4516 0         0 elsif ($string =~ /\G \b bytes::index \b /oxgc) { $e_string .= 'index'; $slash = 'm//'; }
  0         0  
4517 0         0 elsif ($string =~ /\G \b Char::index \b /oxgc) { $e_string .= 'Char::index'; $slash = 'm//'; }
  0         0  
4518 0         0 elsif ($string =~ /\G \b Cyrillic::index \b /oxgc) { $e_string .= 'Cyrillic::index'; $slash = 'm//'; }
  0         0  
4519 0         0 elsif ($string =~ /\G \b index \b /oxgc) { $e_string .= 'Ecyrillic::index'; $slash = 'm//'; }
  0         0  
4520 0         0 elsif ($string =~ /\G \b bytes::rindex \b /oxgc) { $e_string .= 'rindex'; $slash = 'm//'; }
  0         0  
4521 0         0 elsif ($string =~ /\G \b Char::rindex \b /oxgc) { $e_string .= 'Char::rindex'; $slash = 'm//'; }
  0         0  
4522 0         0 elsif ($string =~ /\G \b Cyrillic::rindex \b /oxgc) { $e_string .= 'Cyrillic::rindex'; $slash = 'm//'; }
  0         0  
4523 0         0 elsif ($string =~ /\G \b rindex \b /oxgc) { $e_string .= 'Ecyrillic::rindex'; $slash = 'm//'; }
  0         0  
4524 0         0 elsif ($string =~ /\G \b lc (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Ecyrillic::lc'; $slash = 'm//'; }
  0         0  
4525 0         0 elsif ($string =~ /\G \b lcfirst (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Ecyrillic::lcfirst'; $slash = 'm//'; }
  0         0  
4526 0         0 elsif ($string =~ /\G \b uc (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Ecyrillic::uc'; $slash = 'm//'; }
  0         0  
4527 0         0 elsif ($string =~ /\G \b ucfirst (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Ecyrillic::ucfirst'; $slash = 'm//'; }
  0         0  
4528 0         0 elsif ($string =~ /\G \b fc (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Ecyrillic::fc'; $slash = 'm//'; }
  0         0  
4529              
4530             # "-s '' ..." means file test "-s 'filename' ..." (not means "- s/// ...")
4531 0         0 elsif ($string =~ /\G -s (?>\s*) (\") ((?:$qq_char)+?) (\") /oxgc) { $e_string .= '-s ' . e_qq('', $1,$3,$2); $slash = 'm//'; }
  0         0  
4532 0         0 elsif ($string =~ /\G -s (?>\s+) qq (?>\s*) (\#) ((?:$qq_char)+?) (\#) /oxgc) { $e_string .= '-s ' . e_qq('qq',$1,$3,$2); $slash = 'm//'; }
  0         0  
4533 0         0 elsif ($string =~ /\G -s (?>\s+) qq (?>\s*) (\() ((?:$qq_paren)+?) (\)) /oxgc) { $e_string .= '-s ' . e_qq('qq',$1,$3,$2); $slash = 'm//'; }
  0         0  
4534 0         0 elsif ($string =~ /\G -s (?>\s+) qq (?>\s*) (\{) ((?:$qq_brace)+?) (\}) /oxgc) { $e_string .= '-s ' . e_qq('qq',$1,$3,$2); $slash = 'm//'; }
  0         0  
4535 0         0 elsif ($string =~ /\G -s (?>\s+) qq (?>\s*) (\[) ((?:$qq_bracket)+?) (\]) /oxgc) { $e_string .= '-s ' . e_qq('qq',$1,$3,$2); $slash = 'm//'; }
  0         0  
4536 0         0 elsif ($string =~ /\G -s (?>\s+) qq (?>\s*) (\<) ((?:$qq_angle)+?) (\>) /oxgc) { $e_string .= '-s ' . e_qq('qq',$1,$3,$2); $slash = 'm//'; }
  0         0  
4537 0         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         0  
4538              
4539 0         0 elsif ($string =~ /\G -s (?>\s*) (\') ((?:\\\'|\\\\|$q_char)+?) (\') /oxgc) { $e_string .= '-s ' . e_q ('', $1,$3,$2); $slash = 'm//'; }
  0         0  
4540 0         0 elsif ($string =~ /\G -s (?>\s+) q (?>\s*) (\#) ((?:\\\#|\\\\|$q_char)+?) (\#) /oxgc) { $e_string .= '-s ' . e_q ('q', $1,$3,$2); $slash = 'm//'; }
  0         0  
4541 0         0 elsif ($string =~ /\G -s (?>\s+) q (?>\s*) (\() ((?:\\\)|\\\\|$q_paren)+?) (\)) /oxgc) { $e_string .= '-s ' . e_q ('q', $1,$3,$2); $slash = 'm//'; }
  0         0  
4542 0         0 elsif ($string =~ /\G -s (?>\s+) q (?>\s*) (\{) ((?:\\\}|\\\\|$q_brace)+?) (\}) /oxgc) { $e_string .= '-s ' . e_q ('q', $1,$3,$2); $slash = 'm//'; }
  0         0  
4543 0         0 elsif ($string =~ /\G -s (?>\s+) q (?>\s*) (\[) ((?:\\\]|\\\\|$q_bracket)+?) (\]) /oxgc) { $e_string .= '-s ' . e_q ('q', $1,$3,$2); $slash = 'm//'; }
  0         0  
4544 0         0 elsif ($string =~ /\G -s (?>\s+) q (?>\s*) (\<) ((?:\\\>|\\\\|$q_angle)+?) (\>) /oxgc) { $e_string .= '-s ' . e_q ('q', $1,$3,$2); $slash = 'm//'; }
  0         0  
4545 0         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         0  
4546              
4547             elsif ($string =~ /\G -s (?>\s*) (\$ (?> \w+ (?: ::\w+)*) (?: (?: ->)? (?: [\$\@\%\&\*]\* | \$\#\* | \( (?:$qq_paren)*? \) | [\@\%\*]? \{ (?:$qq_brace)+? \} | [\@\%]? \[ (?:$qq_bracket)+? \] ))*) /oxgc)
4548 0         0 { $e_string .= "-s $1"; $slash = 'm//'; }
  0         0  
4549 0         0 elsif ($string =~ /\G -s (?>\s*) \( ((?:$qq_paren)*?) \) /oxgc) { $e_string .= "-s ($1)"; $slash = 'm//'; }
  0         0  
4550 0         0 elsif ($string =~ /\G -s (?= (?>\s+) [a-z]+) /oxgc) { $e_string .= '-s'; $slash = 'm//'; }
  0         0  
4551 0         0 elsif ($string =~ /\G -s (?>\s+) ((?>\w+)) /oxgc) { $e_string .= "-s $1"; $slash = 'm//'; }
  0         0  
4552              
4553 0         0 elsif ($string =~ /\G \b bytes::length (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'length'; $slash = 'm//'; }
  0         0  
4554 0         0 elsif ($string =~ /\G \b bytes::chr (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'chr'; $slash = 'm//'; }
  0         0  
4555 0         0 elsif ($string =~ /\G \b chr (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Ecyrillic::chr'; $slash = 'm//'; }
  0         0  
4556 0         0 elsif ($string =~ /\G \b bytes::ord (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'ord'; $slash = 'div'; }
  0         0  
4557 0         0 elsif ($string =~ /\G \b ord (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $e_string .= $function_ord; $slash = 'div'; }
  0         0  
4558 0         0 elsif ($string =~ /\G \b glob (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Ecyrillic::glob'; $slash = 'm//'; }
  0         0  
4559 0         0 elsif ($string =~ /\G \b lc \b /oxgc) { $e_string .= 'Ecyrillic::lc_'; $slash = 'm//'; }
  0         0  
4560 0         0 elsif ($string =~ /\G \b lcfirst \b /oxgc) { $e_string .= 'Ecyrillic::lcfirst_'; $slash = 'm//'; }
  0         0  
4561 0         0 elsif ($string =~ /\G \b uc \b /oxgc) { $e_string .= 'Ecyrillic::uc_'; $slash = 'm//'; }
  0         0  
4562 0         0 elsif ($string =~ /\G \b ucfirst \b /oxgc) { $e_string .= 'Ecyrillic::ucfirst_'; $slash = 'm//'; }
  0         0  
4563 0         0 elsif ($string =~ /\G \b fc \b /oxgc) { $e_string .= 'Ecyrillic::fc_'; $slash = 'm//'; }
  0         0  
4564 0         0 elsif ($string =~ /\G -s \b /oxgc) { $e_string .= '-s '; $slash = 'm//'; }
  0         0  
4565              
4566 0         0 elsif ($string =~ /\G \b bytes::length \b /oxgc) { $e_string .= 'length'; $slash = 'm//'; }
  0         0  
4567 0         0 elsif ($string =~ /\G \b bytes::chr \b /oxgc) { $e_string .= 'chr'; $slash = 'm//'; }
  0         0  
4568 0         0 elsif ($string =~ /\G \b chr \b /oxgc) { $e_string .= 'Ecyrillic::chr_'; $slash = 'm//'; }
  0         0  
4569 0         0 elsif ($string =~ /\G \b bytes::ord \b /oxgc) { $e_string .= 'ord'; $slash = 'div'; }
  0         0  
4570 0         0 elsif ($string =~ /\G \b ord \b /oxgc) { $e_string .= $function_ord_; $slash = 'div'; }
  0         0  
4571 0         0 elsif ($string =~ /\G \b glob \b /oxgc) { $e_string .= 'Ecyrillic::glob_'; $slash = 'm//'; }
  0         0  
4572 0         0 elsif ($string =~ /\G \b reverse \b /oxgc) { $e_string .= $function_reverse; $slash = 'm//'; }
  0         0  
4573 0         0 elsif ($string =~ /\G \b getc \b /oxgc) { $e_string .= $function_getc; $slash = 'm//'; }
  0         0  
4574             # split
4575             elsif ($string =~ /\G \b (split) \b (?! (?>\s*) => ) /oxgc) {
4576 0         0 $slash = 'm//';
4577              
4578 0         0 my $e = '';
4579 0         0 while ($string =~ /\G ( (?>\s+) | \( | \#.* ) /oxgc) {
4580 0         0 $e .= $1;
4581             }
4582              
4583             # end of split
4584 0 0       0 if ($string =~ /\G (?= [,;\)\}\]] ) /oxgc) { return '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          
    0          
4585              
4586             # split scalar value
4587 0         0 elsif ($string =~ /\G ( [\$\@\&\*] $qq_scalar ) /oxgc) { $e_string .= 'Ecyrillic::split' . $e . e_string($1); next E_STRING_LOOP; }
  0         0  
4588              
4589             # split literal space
4590 0         0 elsif ($string =~ /\G \b qq (\#) [ ] (\#) /oxgc) { $e_string .= 'Ecyrillic::split' . $e . qq {qq$1 $2}; next E_STRING_LOOP; }
  0         0  
4591 0         0 elsif ($string =~ /\G \b qq ((?>\s*)) (\() [ ] (\)) /oxgc) { $e_string .= 'Ecyrillic::split' . $e . qq{$1qq$2 $3}; next E_STRING_LOOP; }
  0         0  
4592 0         0 elsif ($string =~ /\G \b qq ((?>\s*)) (\{) [ ] (\}) /oxgc) { $e_string .= 'Ecyrillic::split' . $e . qq{$1qq$2 $3}; next E_STRING_LOOP; }
  0         0  
4593 0         0 elsif ($string =~ /\G \b qq ((?>\s*)) (\[) [ ] (\]) /oxgc) { $e_string .= 'Ecyrillic::split' . $e . qq{$1qq$2 $3}; next E_STRING_LOOP; }
  0         0  
4594 0         0 elsif ($string =~ /\G \b qq ((?>\s*)) (\<) [ ] (\>) /oxgc) { $e_string .= 'Ecyrillic::split' . $e . qq{$1qq$2 $3}; next E_STRING_LOOP; }
  0         0  
4595 0         0 elsif ($string =~ /\G \b qq ((?>\s*)) (\S) [ ] (\2) /oxgc) { $e_string .= 'Ecyrillic::split' . $e . qq{$1qq$2 $3}; next E_STRING_LOOP; }
  0         0  
4596 0         0 elsif ($string =~ /\G \b q (\#) [ ] (\#) /oxgc) { $e_string .= 'Ecyrillic::split' . $e . qq {q$1 $2}; next E_STRING_LOOP; }
  0         0  
4597 0         0 elsif ($string =~ /\G \b q ((?>\s*)) (\() [ ] (\)) /oxgc) { $e_string .= 'Ecyrillic::split' . $e . qq {$1q$2 $3}; next E_STRING_LOOP; }
  0         0  
4598 0         0 elsif ($string =~ /\G \b q ((?>\s*)) (\{) [ ] (\}) /oxgc) { $e_string .= 'Ecyrillic::split' . $e . qq {$1q$2 $3}; next E_STRING_LOOP; }
  0         0  
4599 0         0 elsif ($string =~ /\G \b q ((?>\s*)) (\[) [ ] (\]) /oxgc) { $e_string .= 'Ecyrillic::split' . $e . qq {$1q$2 $3}; next E_STRING_LOOP; }
  0         0  
4600 0         0 elsif ($string =~ /\G \b q ((?>\s*)) (\<) [ ] (\>) /oxgc) { $e_string .= 'Ecyrillic::split' . $e . qq {$1q$2 $3}; next E_STRING_LOOP; }
  0         0  
4601 0         0 elsif ($string =~ /\G \b q ((?>\s*)) (\S) [ ] (\2) /oxgc) { $e_string .= 'Ecyrillic::split' . $e . qq {$1q$2 $3}; next E_STRING_LOOP; }
  0         0  
4602 0         0 elsif ($string =~ /\G ' [ ] ' /oxgc) { $e_string .= 'Ecyrillic::split' . $e . qq {' '}; next E_STRING_LOOP; }
  0         0  
4603 0         0 elsif ($string =~ /\G " [ ] " /oxgc) { $e_string .= 'Ecyrillic::split' . $e . qq {" "}; next E_STRING_LOOP; }
  0         0  
4604              
4605             # split qq//
4606             elsif ($string =~ /\G \b (qq) \b /oxgc) {
4607 0 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  
  0         0  
4608             else {
4609 0         0 while ($string !~ /\G \z/oxgc) {
4610 0 0       0 if ($string =~ /\G ((?>\s+)|\#.*) /oxgc) { $e_string .= $e . $1; }
  0 0       0  
    0          
    0          
    0          
    0          
    0          
4611 0         0 elsif ($string =~ /\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { $e_string .= e_split($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # qq ( ) --> qr ( )
  0         0  
4612 0         0 elsif ($string =~ /\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { $e_string .= e_split($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # qq { } --> qr { }
  0         0  
4613 0         0 elsif ($string =~ /\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { $e_string .= e_split($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # qq [ ] --> qr [ ]
  0         0  
4614 0         0 elsif ($string =~ /\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { $e_string .= e_split($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # qq < > --> qr < >
  0         0  
4615 0         0 elsif ($string =~ /\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) /oxgc) { $e_string .= e_split($e.'qr','{','}',$2,''); next E_STRING_LOOP; } # qq | | --> qr { }
  0         0  
4616 0         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         0  
4617             }
4618 0         0 die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4619             }
4620             }
4621              
4622             # split qr//
4623             elsif ($string =~ /\G \b (qr) \b /oxgc) {
4624 0 0       0 if ($string =~ /\G (\#) ((?:$qq_char)*?) (\#) ([imosxpadlunbB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1,$3,$2,$4); next E_STRING_LOOP; } # qr# #
  0         0  
  0         0  
4625             else {
4626 0         0 while ($string !~ /\G \z/oxgc) {
4627 0 0       0 if ($string =~ /\G ((?>\s+)|\#.*) /oxgc) { $e_string .= $e . $1; }
  0 0       0  
    0          
    0          
    0          
    0          
    0          
    0          
4628 0         0 elsif ($string =~ /\G (\() ((?:$qq_paren)*?) (\)) ([imosxpadlunbB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # qr ( )
  0         0  
4629 0         0 elsif ($string =~ /\G (\{) ((?:$qq_brace)*?) (\}) ([imosxpadlunbB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # qr { }
  0         0  
4630 0         0 elsif ($string =~ /\G (\[) ((?:$qq_bracket)*?) (\]) ([imosxpadlunbB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # qr [ ]
  0         0  
4631 0         0 elsif ($string =~ /\G (\<) ((?:$qq_angle)*?) (\>) ([imosxpadlunbB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # qr < >
  0         0  
4632 0         0 elsif ($string =~ /\G (\') ((?:$qq_char)*?) (\') ([imosxpadlunbB]*) /oxgc) { $e_string .= e_split_q($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # qr ' '
  0         0  
4633 0         0 elsif ($string =~ /\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ([imosxpadlunbB]*) /oxgc) { $e_string .= e_split ($e.'qr','{','}',$2,$4); next E_STRING_LOOP; } # qr | | --> qr { }
  0         0  
4634 0         0 elsif ($string =~ /\G (\S) ((?:$qq_char)*?) (\1) ([imosxpadlunbB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # qr * *
  0         0  
4635             }
4636 0         0 die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4637             }
4638             }
4639              
4640             # split q//
4641             elsif ($string =~ /\G \b (q) \b /oxgc) {
4642 0 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  
  0         0  
4643             else {
4644 0         0 while ($string !~ /\G \z/oxgc) {
4645 0 0       0 if ($string =~ /\G ((?>\s+)|\#.*) /oxgc) { $e_string .= $e . $1; }
  0 0       0  
    0          
    0          
    0          
    0          
    0          
4646 0         0 elsif ($string =~ /\G (\() ((?:\\\\|\\\)|\\\(|$q_paren)*?) (\)) /oxgc) { $e_string .= e_split_q($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # q ( ) --> qr ( )
  0         0  
4647 0         0 elsif ($string =~ /\G (\{) ((?:\\\\|\\\}|\\\{|$q_brace)*?) (\}) /oxgc) { $e_string .= e_split_q($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # q { } --> qr { }
  0         0  
4648 0         0 elsif ($string =~ /\G (\[) ((?:\\\\|\\\]|\\\[|$q_bracket)*?) (\]) /oxgc) { $e_string .= e_split_q($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # q [ ] --> qr [ ]
  0         0  
4649 0         0 elsif ($string =~ /\G (\<) ((?:\\\\|\\\>|\\\<|$q_angle)*?) (\>) /oxgc) { $e_string .= e_split_q($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # q < > --> qr < >
  0         0  
4650 0         0 elsif ($string =~ /\G ([*\-:?\\^|]) ((?:$q_char)*?) (\1) /oxgc) { $e_string .= e_split_q($e.'qr','{','}',$2,''); next E_STRING_LOOP; } # q | | --> qr { }
  0         0  
4651 0         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         0  
4652             }
4653 0         0 die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4654             }
4655             }
4656              
4657             # split m//
4658             elsif ($string =~ /\G \b (m) \b /oxgc) {
4659 0 0       0 if ($string =~ /\G (\#) ((?:$qq_char)*?) (\#) ([cgimosxpadlunbB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1,$3,$2,$4); next E_STRING_LOOP; } # m# # --> qr # #
  0         0  
  0         0  
4660             else {
4661 0         0 while ($string !~ /\G \z/oxgc) {
4662 0 0       0 if ($string =~ /\G ((?>\s+)|\#.*) /oxgc) { $e_string .= $e . $1; }
  0 0       0  
    0          
    0          
    0          
    0          
    0          
    0          
4663 0         0 elsif ($string =~ /\G (\() ((?:$qq_paren)*?) (\)) ([cgimosxpadlunbB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # m ( ) --> qr ( )
  0         0  
4664 0         0 elsif ($string =~ /\G (\{) ((?:$qq_brace)*?) (\}) ([cgimosxpadlunbB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # m { } --> qr { }
  0         0  
4665 0         0 elsif ($string =~ /\G (\[) ((?:$qq_bracket)*?) (\]) ([cgimosxpadlunbB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # m [ ] --> qr [ ]
  0         0  
4666 0         0 elsif ($string =~ /\G (\<) ((?:$qq_angle)*?) (\>) ([cgimosxpadlunbB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # m < > --> qr < >
  0         0  
4667 0         0 elsif ($string =~ /\G (\') ((?:$qq_char)*?) (\') ([cgimosxpadlunbB]*) /oxgc) { $e_string .= e_split_q($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # m ' ' --> qr ' '
  0         0  
4668 0         0 elsif ($string =~ /\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ([cgimosxpadlunbB]*) /oxgc) { $e_string .= e_split ($e.'qr','{','}',$2,$4); next E_STRING_LOOP; } # m | | --> qr { }
  0         0  
4669 0         0 elsif ($string =~ /\G (\S) ((?:$qq_char)*?) (\1) ([cgimosxpadlunbB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # m * * --> qr * *
  0         0  
4670             }
4671 0         0 die __FILE__, ": Search pattern not terminated\n";
4672             }
4673             }
4674              
4675             # split ''
4676             elsif ($string =~ /\G (\') /oxgc) {
4677 0         0 my $q_string = '';
4678 0         0 while ($string !~ /\G \z/oxgc) {
4679 0 0       0 if ($string =~ /\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0       0  
    0          
    0          
4680 0         0 elsif ($string =~ /\G (\\\') /oxgc) { $q_string .= $1; } # splitqr'' --> split qr''
4681 0         0 elsif ($string =~ /\G \' /oxgc) { $e_string .= e_split_q($e.q{ qr},"'","'",$q_string,''); next E_STRING_LOOP; } # ' ' --> qr ' '
  0         0  
4682 0         0 elsif ($string =~ /\G ($q_char) /oxgc) { $q_string .= $1; }
4683             }
4684 0         0 die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4685             }
4686              
4687             # split ""
4688             elsif ($string =~ /\G (\") /oxgc) {
4689 0         0 my $qq_string = '';
4690 0         0 while ($string !~ /\G \z/oxgc) {
4691 0 0       0 if ($string =~ /\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0       0  
    0          
    0          
4692 0         0 elsif ($string =~ /\G (\\\") /oxgc) { $qq_string .= $1; } # splitqr"" --> split qr""
4693 0         0 elsif ($string =~ /\G \" /oxgc) { $e_string .= e_split($e.q{ qr},'"','"',$qq_string,''); next E_STRING_LOOP; } # " " --> qr " "
  0         0  
4694 0         0 elsif ($string =~ /\G ($q_char) /oxgc) { $qq_string .= $1; }
4695             }
4696 0         0 die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4697             }
4698              
4699             # split //
4700             elsif ($string =~ /\G (\/) /oxgc) {
4701 0         0 my $regexp = '';
4702 0         0 while ($string !~ /\G \z/oxgc) {
4703 0 0       0 if ($string =~ /\G (\\\\) /oxgc) { $regexp .= $1; }
  0 0       0  
    0          
    0          
4704 0         0 elsif ($string =~ /\G (\\\/) /oxgc) { $regexp .= $1; } # splitqr// --> split qr//
4705 0         0 elsif ($string =~ /\G \/ ([cgimosxpadlunbB]*) /oxgc) { $e_string .= e_split($e.q{ qr}, '/','/',$regexp,$1); next E_STRING_LOOP; } # / / --> qr / /
  0         0  
4706 0         0 elsif ($string =~ /\G ($q_char) /oxgc) { $regexp .= $1; }
4707             }
4708 0         0 die __FILE__, ": Search pattern not terminated\n";
4709             }
4710             }
4711              
4712             # qq//
4713             elsif ($string =~ /\G \b (qq) \b /oxgc) {
4714 0         0 my $ope = $1;
4715 0 0       0 if ($string =~ /\G (\#) ((?:$qq_char)*?) (\#) /oxgc) { # qq# #
4716 0         0 $e_string .= e_qq($ope,$1,$3,$2);
4717             }
4718             else {
4719 0         0 my $e = '';
4720 0         0 while ($string !~ /\G \z/oxgc) {
4721 0 0       0 if ($string =~ /\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0       0  
    0          
    0          
    0          
    0          
4722 0         0 elsif ($string =~ /\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qq ( )
  0         0  
4723 0         0 elsif ($string =~ /\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qq { }
  0         0  
4724 0         0 elsif ($string =~ /\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qq [ ]
  0         0  
4725 0         0 elsif ($string =~ /\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qq < >
  0         0  
4726 0         0 elsif ($string =~ /\G (\S) ((?:$qq_char)*?) (\1) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qq * *
  0         0  
4727             }
4728 0         0 die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4729             }
4730             }
4731              
4732             # qx//
4733             elsif ($string =~ /\G \b (qx) \b /oxgc) {
4734 0         0 my $ope = $1;
4735 0 0       0 if ($string =~ /\G (\#) ((?:$qq_char)*?) (\#) /oxgc) { # qx# #
4736 0         0 $e_string .= e_qq($ope,$1,$3,$2);
4737             }
4738             else {
4739 0         0 my $e = '';
4740 0         0 while ($string !~ /\G \z/oxgc) {
4741 0 0       0 if ($string =~ /\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0       0  
    0          
    0          
    0          
    0          
    0          
4742 0         0 elsif ($string =~ /\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qx ( )
  0         0  
4743 0         0 elsif ($string =~ /\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qx { }
  0         0  
4744 0         0 elsif ($string =~ /\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qx [ ]
  0         0  
4745 0         0 elsif ($string =~ /\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qx < >
  0         0  
4746 0         0 elsif ($string =~ /\G (\') ((?:$qq_char)*?) (\') /oxgc) { $e_string .= $e . e_q ($ope,$1,$3,$2); next E_STRING_LOOP; } # qx ' '
  0         0  
4747 0         0 elsif ($string =~ /\G (\S) ((?:$qq_char)*?) (\1) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qx * *
  0         0  
4748             }
4749 0         0 die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4750             }
4751             }
4752              
4753             # q//
4754             elsif ($string =~ /\G \b (q) \b /oxgc) {
4755 0         0 my $ope = $1;
4756 0 0       0 if ($string =~ /\G (\#) ((?:\\\#|\\\\|$q_char)*?) (\#) /oxgc) { # q# #
4757 0         0 $e_string .= e_q($ope,$1,$3,$2);
4758             }
4759             else {
4760 0         0 my $e = '';
4761 0         0 while ($string !~ /\G \z/oxgc) {
4762 0 0       0 if ($string =~ /\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0       0  
    0          
    0          
    0          
    0          
4763 0         0 elsif ($string =~ /\G (\() ((?:\\\\|\\\)|\\\(|$q_paren)*?) (\)) /oxgc) { $e_string .= $e . e_q($ope,$1,$3,$2); next E_STRING_LOOP; } # q ( )
  0         0  
4764 0         0 elsif ($string =~ /\G (\{) ((?:\\\\|\\\}|\\\{|$q_brace)*?) (\}) /oxgc) { $e_string .= $e . e_q($ope,$1,$3,$2); next E_STRING_LOOP; } # q { }
  0         0  
4765 0         0 elsif ($string =~ /\G (\[) ((?:\\\\|\\\]|\\\[|$q_bracket)*?) (\]) /oxgc) { $e_string .= $e . e_q($ope,$1,$3,$2); next E_STRING_LOOP; } # q [ ]
  0         0  
4766 0         0 elsif ($string =~ /\G (\<) ((?:\\\\|\\\>|\\\<|$q_angle)*?) (\>) /oxgc) { $e_string .= $e . e_q($ope,$1,$3,$2); next E_STRING_LOOP; } # q < >
  0         0  
4767 0         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         0  
4768             }
4769 0         0 die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4770             }
4771             }
4772              
4773             # ''
4774 0         0 elsif ($string =~ /\G (?
4775              
4776             # ""
4777 0         0 elsif ($string =~ /\G (\") ((?:$qq_char)*?) (\") /oxgc) { $e_string .= e_qq('',$1,$3,$2); }
4778              
4779             # ``
4780 0         0 elsif ($string =~ /\G (\`) ((?:$qq_char)*?) (\`) /oxgc) { $e_string .= e_qq('',$1,$3,$2); }
4781              
4782             # <<>> (a safer ARGV)
4783 0         0 elsif ($string =~ /\G ( <<>> ) /oxgc) { $e_string .= $1; }
4784              
4785             # <<= <=> <= < operator
4786 0         0 elsif ($string =~ /\G ( <<= | <=> | <= | < ) (?= (?>\s*) [A-Za-z_0-9'"`\$\@\&\*\(\+\-] )/oxgc) { $e_string .= $1; }
4787              
4788             #
4789 0         0 elsif ($string =~ /\G (<[\$]?[A-Za-z_][A-Za-z_0-9]*>) /oxgc) { $e_string .= $1; }
4790              
4791             # --- glob
4792             elsif ($string =~ /\G < ((?:$q_char)+?) > /oxgc) {
4793 0         0 $e_string .= 'Ecyrillic::glob("' . $1 . '")';
4794             }
4795              
4796             # << (bit shift) --- not here document
4797 0         0 elsif ($string =~ /\G ( << (?>\s*) ) (?= [0-9\$\@\&] ) /oxgc) { $slash = 'm//'; $e_string .= $1; }
  0         0  
4798              
4799             # <<'HEREDOC'
4800             elsif ($string =~ /\G ( << '([a-zA-Z_0-9]*)' ) /oxgc) {
4801 0         0 $slash = 'm//';
4802 0         0 my $here_quote = $1;
4803 0         0 my $delimiter = $2;
4804              
4805             # get here document
4806 0 0       0 if ($here_script eq '') {
4807 0         0 $here_script = CORE::substr $_, pos $_;
4808 0         0 $here_script =~ s/.*?\n//oxm;
4809             }
4810 0 0       0 if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4811 0         0 push @heredoc, $1 . qq{\n$delimiter\n};
4812 0         0 push @heredoc_delimiter, $delimiter;
4813             }
4814             else {
4815 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4816             }
4817 0         0 $e_string .= $here_quote;
4818             }
4819              
4820             # <<\HEREDOC
4821             elsif ($string =~ /\G ( << \\([a-zA-Z_0-9]+) ) /oxgc) {
4822 0         0 $slash = 'm//';
4823 0         0 my $here_quote = $1;
4824 0         0 my $delimiter = $2;
4825              
4826             # get here document
4827 0 0       0 if ($here_script eq '') {
4828 0         0 $here_script = CORE::substr $_, pos $_;
4829 0         0 $here_script =~ s/.*?\n//oxm;
4830             }
4831 0 0       0 if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4832 0         0 push @heredoc, $1 . qq{\n$delimiter\n};
4833 0         0 push @heredoc_delimiter, $delimiter;
4834             }
4835             else {
4836 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4837             }
4838 0         0 $e_string .= $here_quote;
4839             }
4840              
4841             # <<"HEREDOC"
4842             elsif ($string =~ /\G ( << "([a-zA-Z_0-9]*)" ) /oxgc) {
4843 0         0 $slash = 'm//';
4844 0         0 my $here_quote = $1;
4845 0         0 my $delimiter = $2;
4846              
4847             # get here document
4848 0 0       0 if ($here_script eq '') {
4849 0         0 $here_script = CORE::substr $_, pos $_;
4850 0         0 $here_script =~ s/.*?\n//oxm;
4851             }
4852 0 0       0 if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4853 0         0 push @heredoc, e_heredoc($1) . qq{\n$delimiter\n};
4854 0         0 push @heredoc_delimiter, $delimiter;
4855             }
4856             else {
4857 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4858             }
4859 0         0 $e_string .= $here_quote;
4860             }
4861              
4862             # <
4863             elsif ($string =~ /\G ( << ([a-zA-Z_0-9]+) ) /oxgc) {
4864 0         0 $slash = 'm//';
4865 0         0 my $here_quote = $1;
4866 0         0 my $delimiter = $2;
4867              
4868             # get here document
4869 0 0       0 if ($here_script eq '') {
4870 0         0 $here_script = CORE::substr $_, pos $_;
4871 0         0 $here_script =~ s/.*?\n//oxm;
4872             }
4873 0 0       0 if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4874 0         0 push @heredoc, e_heredoc($1) . qq{\n$delimiter\n};
4875 0         0 push @heredoc_delimiter, $delimiter;
4876             }
4877             else {
4878 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4879             }
4880 0         0 $e_string .= $here_quote;
4881             }
4882              
4883             # <<`HEREDOC`
4884             elsif ($string =~ /\G ( << `([a-zA-Z_0-9]*)` ) /oxgc) {
4885 0         0 $slash = 'm//';
4886 0         0 my $here_quote = $1;
4887 0         0 my $delimiter = $2;
4888              
4889             # get here document
4890 0 0       0 if ($here_script eq '') {
4891 0         0 $here_script = CORE::substr $_, pos $_;
4892 0         0 $here_script =~ s/.*?\n//oxm;
4893             }
4894 0 0       0 if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4895 0         0 push @heredoc, e_heredoc($1) . qq{\n$delimiter\n};
4896 0         0 push @heredoc_delimiter, $delimiter;
4897             }
4898             else {
4899 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4900             }
4901 0         0 $e_string .= $here_quote;
4902             }
4903              
4904             # any operator before div
4905             elsif ($string =~ /\G (
4906             -- | \+\+ |
4907             [\)\}\]]
4908              
4909 18         28 ) /oxgc) { $slash = 'div'; $e_string .= $1; }
  18         52  
4910              
4911             # yada-yada or triple-dot operator
4912             elsif ($string =~ /\G (
4913             \.\.\.
4914              
4915 0         0 ) /oxgc) { $slash = 'm//'; $e_string .= q{die('Unimplemented')}; }
  0         0  
4916              
4917             # any operator before m//
4918             elsif ($string =~ /\G ((?>
4919              
4920             !~~ | !~ | != | ! |
4921             %= | % |
4922             &&= | && | &= | &\.= | &\. | & |
4923             -= | -> | - |
4924             :(?>\s*)= |
4925             : |
4926             <<>> |
4927             <<= | <=> | <= | < |
4928             == | => | =~ | = |
4929             >>= | >> | >= | > |
4930             \*\*= | \*\* | \*= | \* |
4931             \+= | \+ |
4932             \.\. | \.= | \. |
4933             \/\/= | \/\/ |
4934             \/= | \/ |
4935             \? |
4936             \\ |
4937             \^= | \^\.= | \^\. | \^ |
4938             \b x= |
4939             \|\|= | \|\| | \|= | \|\.= | \|\. | \| |
4940             ~~ | ~\. | ~ |
4941             \b(?: and | cmp | eq | ge | gt | le | lt | ne | not | or | xor | x )\b |
4942             \b(?: print )\b |
4943              
4944             [,;\(\{\[]
4945              
4946 31         35 )) /oxgc) { $slash = 'm//'; $e_string .= $1; }
  31         101  
4947              
4948             # other any character
4949 131         304 elsif ($string =~ /\G ($q_char) /oxgc) { $e_string .= $1; }
4950              
4951             # system error
4952             else {
4953 0         0 die __FILE__, ": Oops, this shouldn't happen!\n";
4954             }
4955             }
4956              
4957 17         66 return $e_string;
4958             }
4959              
4960             #
4961             # character class
4962             #
4963             sub character_class {
4964 1914     1914 0 2318 my($char,$modifier) = @_;
4965              
4966 1914 100       2473 if ($char eq '.') {
4967 52 100       91 if ($modifier =~ /s/) {
4968 17         36 return '${Ecyrillic::dot_s}';
4969             }
4970             else {
4971 35         80 return '${Ecyrillic::dot}';
4972             }
4973             }
4974             else {
4975 1862         2661 return Ecyrillic::classic_character_class($char);
4976             }
4977             }
4978              
4979             #
4980             # escape capture ($1, $2, $3, ...)
4981             #
4982             sub e_capture {
4983              
4984 212     212 0 837 return join '', '${', $_[0], '}';
4985             }
4986              
4987             #
4988             # escape transliteration (tr/// or y///)
4989             #
4990             sub e_tr {
4991 3     3 0 9 my($variable,$charclass,$e,$charclass2,$modifier) = @_;
4992 3         4 my $e_tr = '';
4993 3   50     7 $modifier ||= '';
4994              
4995 3         5 $slash = 'div';
4996              
4997             # quote character class 1
4998 3         8 $charclass = q_tr($charclass);
4999              
5000             # quote character class 2
5001 3         7 $charclass2 = q_tr($charclass2);
5002              
5003             # /b /B modifier
5004 3 50       10 if ($modifier =~ tr/bB//d) {
5005 0 0       0 if ($variable eq '') {
5006 0         0 $e_tr = qq{tr$charclass$e$charclass2$modifier};
5007             }
5008             else {
5009 0         0 $e_tr = qq{$variable${bind_operator}tr$charclass$e$charclass2$modifier};
5010             }
5011             }
5012             else {
5013 3 100       8 if ($variable eq '') {
5014 2         12 $e_tr = qq{Ecyrillic::tr(\$_,' =~ ',$charclass,$e$charclass2,'$modifier')};
5015             }
5016             else {
5017 1         8 $e_tr = qq{Ecyrillic::tr($variable,'$bind_operator',$charclass,$e$charclass2,'$modifier')};
5018             }
5019             }
5020              
5021             # clear tr/// variable
5022 3         5 $tr_variable = '';
5023 3         3 $bind_operator = '';
5024              
5025 3         18 return $e_tr;
5026             }
5027              
5028             #
5029             # quote for escape transliteration (tr/// or y///)
5030             #
5031             sub q_tr {
5032 6     6 0 6 my($charclass) = @_;
5033              
5034             # quote character class
5035 6 50       14 if ($charclass !~ /'/oxms) {
    0          
    0          
    0          
    0          
    0          
5036 6         8 return e_q('', "'", "'", $charclass); # --> q' '
5037             }
5038             elsif ($charclass !~ /\//oxms) {
5039 0         0 return e_q('q', '/', '/', $charclass); # --> q/ /
5040             }
5041             elsif ($charclass !~ /\#/oxms) {
5042 0         0 return e_q('q', '#', '#', $charclass); # --> q# #
5043             }
5044             elsif ($charclass !~ /[\<\>]/oxms) {
5045 0         0 return e_q('q', '<', '>', $charclass); # --> q< >
5046             }
5047             elsif ($charclass !~ /[\(\)]/oxms) {
5048 0         0 return e_q('q', '(', ')', $charclass); # --> q( )
5049             }
5050             elsif ($charclass !~ /[\{\}]/oxms) {
5051 0         0 return e_q('q', '{', '}', $charclass); # --> q{ }
5052             }
5053             else {
5054 0         0 for my $char (qw( ! " $ % & * + . : = ? @ ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
5055 0 0       0 if ($charclass !~ /\Q$char\E/xms) {
5056 0         0 return e_q('q', $char, $char, $charclass);
5057             }
5058             }
5059             }
5060              
5061 0         0 return e_q('q', '{', '}', $charclass);
5062             }
5063              
5064             #
5065             # escape q string (q//, '')
5066             #
5067             sub e_q {
5068 1092     1092 0 1968 my($ope,$delimiter,$end_delimiter,$string) = @_;
5069              
5070 1092         1189 $slash = 'div';
5071              
5072 1092         5264 return join '', $ope, $delimiter, $string, $end_delimiter;
5073             }
5074              
5075             #
5076             # escape qq string (qq//, "", qx//, ``)
5077             #
5078             sub e_qq {
5079 4029     4029 0 6522 my($ope,$delimiter,$end_delimiter,$string) = @_;
5080              
5081 4029         3982 $slash = 'div';
5082              
5083 4029         3432 my $left_e = 0;
5084 4029         3022 my $right_e = 0;
5085              
5086             # split regexp
5087 4029         136562 my @char = $string =~ /\G((?>
5088             [^\\\$] |
5089             \\x\{ (?>[0-9A-Fa-f]+) \} |
5090             \\o\{ (?>[0-7]+) \} |
5091             \\N\{ (?>[^0-9\}][^\}]*) \} |
5092             \\ $q_char |
5093             \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} |
5094             \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} |
5095             \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} |
5096             \$ (?>\s* [0-9]+) |
5097             \$ (?>\s*) \{ (?>\s* [0-9]+ \s*) \} |
5098             \$ \$ (?![\w\{]) |
5099             \$ (?>\s*) \$ (?>\s*) $qq_variable |
5100             $q_char
5101             ))/oxmsg;
5102              
5103 4029         13537 for (my $i=0; $i <= $#char; $i++) {
5104              
5105             # "\L\u" --> "\u\L"
5106 112287 50 33     427634 if (($char[$i] eq '\L') and ($char[$i+1] eq '\u')) {
    50 33        
    100          
    100          
    50          
5107 0         0 @char[$i,$i+1] = @char[$i+1,$i];
5108             }
5109              
5110             # "\U\l" --> "\l\U"
5111             elsif (($char[$i] eq '\U') and ($char[$i+1] eq '\l')) {
5112 0         0 @char[$i,$i+1] = @char[$i+1,$i];
5113             }
5114              
5115             # octal escape sequence
5116             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
5117 1         4 $char[$i] = Ecyrillic::octchr($1);
5118             }
5119              
5120             # hexadecimal escape sequence
5121             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
5122 1         4 $char[$i] = Ecyrillic::hexchr($1);
5123             }
5124              
5125             # \N{CHARNAME} --> N{CHARNAME}
5126             elsif ($char[$i] =~ /\A \\ ( N\{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
5127 0         0 $char[$i] = $1;
5128             }
5129              
5130 112287 100       1164326 if (0) {
    50          
    50          
    50          
    50          
    100          
    50          
    100          
    50          
    50          
    100          
    50          
    50          
    100          
    50          
    50          
    50          
    50          
    100          
    100          
    100          
    50          
    50          
5131             }
5132              
5133             # \F
5134             #
5135             # P.69 Table 2-6. Translation escapes
5136             # in Chapter 2: Bits and Pieces
5137             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
5138             # (and so on)
5139              
5140             # \u \l \U \L \F \Q \E
5141 0         0 elsif ($char[$i] =~ /\A ([<>]) \z/oxms) {
5142 484 50       1092 if ($right_e < $left_e) {
5143 0         0 $char[$i] = '\\' . $char[$i];
5144             }
5145             }
5146             elsif ($char[$i] eq '\u') {
5147              
5148             # "STRING @{[ LIST EXPR ]} MORE STRING"
5149              
5150             # P.257 Other Tricks You Can Do with Hard References
5151             # in Chapter 8: References
5152             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
5153              
5154             # P.353 Other Tricks You Can Do with Hard References
5155             # in Chapter 8: References
5156             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
5157              
5158             # (and so on)
5159              
5160 0         0 $char[$i] = '@{[Ecyrillic::ucfirst qq<';
5161 0         0 $left_e++;
5162             }
5163             elsif ($char[$i] eq '\l') {
5164 0         0 $char[$i] = '@{[Ecyrillic::lcfirst qq<';
5165 0         0 $left_e++;
5166             }
5167             elsif ($char[$i] eq '\U') {
5168 0         0 $char[$i] = '@{[Ecyrillic::uc qq<';
5169 0         0 $left_e++;
5170             }
5171             elsif ($char[$i] eq '\L') {
5172 0         0 $char[$i] = '@{[Ecyrillic::lc qq<';
5173 0         0 $left_e++;
5174             }
5175             elsif ($char[$i] eq '\F') {
5176 24         24 $char[$i] = '@{[Ecyrillic::fc qq<';
5177 24         39 $left_e++;
5178             }
5179             elsif ($char[$i] eq '\Q') {
5180 0         0 $char[$i] = '@{[CORE::quotemeta qq<';
5181 0         0 $left_e++;
5182             }
5183             elsif ($char[$i] eq '\E') {
5184 24 50       31 if ($right_e < $left_e) {
5185 24         22 $char[$i] = '>]}';
5186 24         41 $right_e++;
5187             }
5188             else {
5189 0         0 $char[$i] = '';
5190             }
5191             }
5192             elsif ($char[$i] eq '\Q') {
5193 0         0 while (1) {
5194 0 0       0 if (++$i > $#char) {
5195 0         0 last;
5196             }
5197 0 0       0 if ($char[$i] eq '\E') {
5198 0         0 last;
5199             }
5200             }
5201             }
5202             elsif ($char[$i] eq '\E') {
5203             }
5204              
5205             # $0 --> $0
5206             elsif ($char[$i] =~ /\A \$ 0 \z/oxms) {
5207             }
5208             elsif ($char[$i] =~ /\A \$ \{ (?>\s*) 0 (?>\s*) \} \z/oxms) {
5209             }
5210              
5211             # $$ --> $$
5212             elsif ($char[$i] =~ /\A \$\$ \z/oxms) {
5213             }
5214              
5215             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
5216             # $1, $2, $3 --> $1, $2, $3 otherwise
5217             elsif ($char[$i] =~ /\A \$ ((?>[1-9][0-9]*)) \z/oxms) {
5218 205         354 $char[$i] = e_capture($1);
5219             }
5220             elsif ($char[$i] =~ /\A \$ \{ (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} \z/oxms) {
5221 0         0 $char[$i] = e_capture($1);
5222             }
5223              
5224             # $$foo[ ... ] --> $ $foo->[ ... ]
5225             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \[ (?:$qq_bracket)*? \] ) \z/oxms) {
5226 0         0 $char[$i] = e_capture($1.'->'.$2);
5227             }
5228              
5229             # $$foo{ ... } --> $ $foo->{ ... }
5230             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \{ (?:$qq_brace)*? \} ) \z/oxms) {
5231 0         0 $char[$i] = e_capture($1.'->'.$2);
5232             }
5233              
5234             # $$foo
5235             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) \z/oxms) {
5236 0         0 $char[$i] = e_capture($1);
5237             }
5238              
5239             # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Ecyrillic::PREMATCH()
5240             elsif ($char[$i] =~ /\A ( \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} ) \z/oxmsgc) {
5241 44         119 $char[$i] = '@{[Ecyrillic::PREMATCH()]}';
5242             }
5243              
5244             # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Ecyrillic::MATCH()
5245             elsif ($char[$i] =~ /\A ( \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} ) \z/oxmsgc) {
5246 45         113 $char[$i] = '@{[Ecyrillic::MATCH()]}';
5247             }
5248              
5249             # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Ecyrillic::POSTMATCH()
5250             elsif ($char[$i] =~ /\A ( \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} ) \z/oxmsgc) {
5251 33         84 $char[$i] = '@{[Ecyrillic::POSTMATCH()]}';
5252             }
5253              
5254             # ${ foo } --> ${ foo }
5255             elsif ($char[$i] =~ /\A \$ (?>\s*) \{ (?> \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* ) \} \z/oxms) {
5256             }
5257              
5258             # ${ ... }
5259             elsif ($char[$i] =~ /\A \$ (?>\s*) \{ ( .+ ) \} \z/oxms) {
5260 0         0 $char[$i] = e_capture($1);
5261             }
5262             }
5263              
5264             # return string
5265 4029 50       6770 if ($left_e > $right_e) {
5266 0         0 return join '', $ope, $delimiter, @char, '>]}' x ($left_e - $right_e), $end_delimiter;
5267             }
5268 4029         33882 return join '', $ope, $delimiter, @char, $end_delimiter;
5269             }
5270              
5271             #
5272             # escape qw string (qw//)
5273             #
5274             sub e_qw {
5275 16     16 0 103 my($ope,$delimiter,$end_delimiter,$string) = @_;
5276              
5277 16         27 $slash = 'div';
5278              
5279             # choice again delimiter
5280 16         213 my %octet = map {$_ => 1} ($string =~ /\G ([\x00-\xFF]) /oxmsg);
  483         617  
5281 16 50       101 if (not $octet{$end_delimiter}) {
    0          
    0          
    0          
    0          
5282 16         137 return join '', $ope, $delimiter, $string, $end_delimiter;
5283             }
5284             elsif (not $octet{')'}) {
5285 0         0 return join '', $ope, '(', $string, ')';
5286             }
5287             elsif (not $octet{'}'}) {
5288 0         0 return join '', $ope, '{', $string, '}';
5289             }
5290             elsif (not $octet{']'}) {
5291 0         0 return join '', $ope, '[', $string, ']';
5292             }
5293             elsif (not $octet{'>'}) {
5294 0         0 return join '', $ope, '<', $string, '>';
5295             }
5296             else {
5297 0         0 for my $char (qw( ! " $ % & * + - . / : = ? @ ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
5298 0 0       0 if (not $octet{$char}) {
5299 0         0 return join '', $ope, $char, $string, $char;
5300             }
5301             }
5302             }
5303              
5304             # qw/AAA BBB C'CC/ --> ('AAA', 'BBB', 'C\'CC')
5305 0         0 my @string = CORE::split(/\s+/, $string);
5306 0         0 for my $string (@string) {
5307 0         0 my @octet = $string =~ /\G ([\x00-\xFF]) /oxmsg;
5308 0         0 for my $octet (@octet) {
5309 0 0       0 if ($octet =~ /\A (['\\]) \z/oxms) {
5310 0         0 $octet = '\\' . $1;
5311             }
5312             }
5313 0         0 $string = join '', @octet;
5314             }
5315 0         0 return join '', '(', (join ', ', map { "'$_'" } @string), ')';
  0         0  
5316             }
5317              
5318             #
5319             # escape here document (<<"HEREDOC", <
5320             #
5321             sub e_heredoc {
5322 78     78 0 152 my($string) = @_;
5323              
5324 78         93 $slash = 'm//';
5325              
5326 78         291 my $metachar = qr/[\@\\|]/oxms; # '|' is for <<`HEREDOC`
5327              
5328 78         102 my $left_e = 0;
5329 78         79 my $right_e = 0;
5330              
5331             # split regexp
5332 78         6848 my @char = $string =~ /\G((?>
5333             [^\\\$] |
5334             \\x\{ (?>[0-9A-Fa-f]+) \} |
5335             \\o\{ (?>[0-7]+) \} |
5336             \\N\{ (?>[^0-9\}][^\}]*) \} |
5337             \\ $q_char |
5338             \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} |
5339             \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} |
5340             \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} |
5341             \$ (?>\s* [0-9]+) |
5342             \$ (?>\s*) \{ (?>\s* [0-9]+ \s*) \} |
5343             \$ \$ (?![\w\{]) |
5344             \$ (?>\s*) \$ (?>\s*) $qq_variable |
5345             $q_char
5346             ))/oxmsg;
5347              
5348 78         414 for (my $i=0; $i <= $#char; $i++) {
5349              
5350             # "\L\u" --> "\u\L"
5351 2934 50 33     10422 if (($char[$i] eq '\L') and ($char[$i+1] eq '\u')) {
    50 33        
    100          
    100          
    50          
5352 0         0 @char[$i,$i+1] = @char[$i+1,$i];
5353             }
5354              
5355             # "\U\l" --> "\l\U"
5356             elsif (($char[$i] eq '\U') and ($char[$i+1] eq '\l')) {
5357 0         0 @char[$i,$i+1] = @char[$i+1,$i];
5358             }
5359              
5360             # octal escape sequence
5361             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
5362 1         5 $char[$i] = Ecyrillic::octchr($1);
5363             }
5364              
5365             # hexadecimal escape sequence
5366             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
5367 1         6 $char[$i] = Ecyrillic::hexchr($1);
5368             }
5369              
5370             # \N{CHARNAME} --> N{CHARNAME}
5371             elsif ($char[$i] =~ /\A \\ ( N\{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
5372 0         0 $char[$i] = $1;
5373             }
5374              
5375 2934 50       29339 if (0) {
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    100          
    100          
    100          
    50          
    50          
5376             }
5377              
5378             # \u \l \U \L \F \Q \E
5379 0         0 elsif ($char[$i] =~ /\A ([<>]) \z/oxms) {
5380 0 0       0 if ($right_e < $left_e) {
5381 0         0 $char[$i] = '\\' . $char[$i];
5382             }
5383             }
5384             elsif ($char[$i] eq '\u') {
5385 0         0 $char[$i] = '@{[Ecyrillic::ucfirst qq<';
5386 0         0 $left_e++;
5387             }
5388             elsif ($char[$i] eq '\l') {
5389 0         0 $char[$i] = '@{[Ecyrillic::lcfirst qq<';
5390 0         0 $left_e++;
5391             }
5392             elsif ($char[$i] eq '\U') {
5393 0         0 $char[$i] = '@{[Ecyrillic::uc qq<';
5394 0         0 $left_e++;
5395             }
5396             elsif ($char[$i] eq '\L') {
5397 0         0 $char[$i] = '@{[Ecyrillic::lc qq<';
5398 0         0 $left_e++;
5399             }
5400             elsif ($char[$i] eq '\F') {
5401 0         0 $char[$i] = '@{[Ecyrillic::fc qq<';
5402 0         0 $left_e++;
5403             }
5404             elsif ($char[$i] eq '\Q') {
5405 0         0 $char[$i] = '@{[CORE::quotemeta qq<';
5406 0         0 $left_e++;
5407             }
5408             elsif ($char[$i] eq '\E') {
5409 0 0       0 if ($right_e < $left_e) {
5410 0         0 $char[$i] = '>]}';
5411 0         0 $right_e++;
5412             }
5413             else {
5414 0         0 $char[$i] = '';
5415             }
5416             }
5417             elsif ($char[$i] eq '\Q') {
5418 0         0 while (1) {
5419 0 0       0 if (++$i > $#char) {
5420 0         0 last;
5421             }
5422 0 0       0 if ($char[$i] eq '\E') {
5423 0         0 last;
5424             }
5425             }
5426             }
5427             elsif ($char[$i] eq '\E') {
5428             }
5429              
5430             # $0 --> $0
5431             elsif ($char[$i] =~ /\A \$ 0 \z/oxms) {
5432             }
5433             elsif ($char[$i] =~ /\A \$ \{ (?>\s*) 0 (?>\s*) \} \z/oxms) {
5434             }
5435              
5436             # $$ --> $$
5437             elsif ($char[$i] =~ /\A \$\$ \z/oxms) {
5438             }
5439              
5440             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
5441             # $1, $2, $3 --> $1, $2, $3 otherwise
5442             elsif ($char[$i] =~ /\A \$ ((?>[1-9][0-9]*)) \z/oxms) {
5443 0         0 $char[$i] = e_capture($1);
5444             }
5445             elsif ($char[$i] =~ /\A \$ \{ (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} \z/oxms) {
5446 0         0 $char[$i] = e_capture($1);
5447             }
5448              
5449             # $$foo[ ... ] --> $ $foo->[ ... ]
5450             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \[ (?:$qq_bracket)*? \] ) \z/oxms) {
5451 0         0 $char[$i] = e_capture($1.'->'.$2);
5452             }
5453              
5454             # $$foo{ ... } --> $ $foo->{ ... }
5455             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \{ (?:$qq_brace)*? \} ) \z/oxms) {
5456 0         0 $char[$i] = e_capture($1.'->'.$2);
5457             }
5458              
5459             # $$foo
5460             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) \z/oxms) {
5461 0         0 $char[$i] = e_capture($1);
5462             }
5463              
5464             # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Ecyrillic::PREMATCH()
5465             elsif ($char[$i] =~ /\A ( \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} ) \z/oxmsgc) {
5466 8         35 $char[$i] = '@{[Ecyrillic::PREMATCH()]}';
5467             }
5468              
5469             # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Ecyrillic::MATCH()
5470             elsif ($char[$i] =~ /\A ( \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} ) \z/oxmsgc) {
5471 8         33 $char[$i] = '@{[Ecyrillic::MATCH()]}';
5472             }
5473              
5474             # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Ecyrillic::POSTMATCH()
5475             elsif ($char[$i] =~ /\A ( \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} ) \z/oxmsgc) {
5476 6         26 $char[$i] = '@{[Ecyrillic::POSTMATCH()]}';
5477             }
5478              
5479             # ${ foo } --> ${ foo }
5480             elsif ($char[$i] =~ /\A \$ (?>\s*) \{ (?> \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* ) \} \z/oxms) {
5481             }
5482              
5483             # ${ ... }
5484             elsif ($char[$i] =~ /\A \$ (?>\s*) \{ ( .+ ) \} \z/oxms) {
5485 0         0 $char[$i] = e_capture($1);
5486             }
5487             }
5488              
5489             # return string
5490 78 50       153 if ($left_e > $right_e) {
5491 0         0 return join '', @char, '>]}' x ($left_e - $right_e);
5492             }
5493 78         614 return join '', @char;
5494             }
5495              
5496             #
5497             # escape regexp (m//, qr//)
5498             #
5499             sub e_qr {
5500 651     651 0 1668 my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
5501 651   100     2310 $modifier ||= '';
5502              
5503 651         928 $modifier =~ tr/p//d;
5504 651 50       1473 if ($modifier =~ /([adlu])/oxms) {
5505 0         0 my $line = 0;
5506 0         0 for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
5507 0 0       0 if ($filename ne __FILE__) {
5508 0         0 $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
5509 0         0 last;
5510             }
5511             }
5512 0         0 die qq{Unsupported modifier "$1" used at line $line.\n};
5513             }
5514              
5515 651         795 $slash = 'div';
5516              
5517             # literal null string pattern
5518 651 100       1936 if ($string eq '') {
    100          
5519 8         9 $modifier =~ tr/bB//d;
5520 8         6 $modifier =~ tr/i//d;
5521 8         49 return join '', $ope, $delimiter, $end_delimiter, $modifier;
5522             }
5523              
5524             # /b /B modifier
5525             elsif ($modifier =~ tr/bB//d) {
5526              
5527             # choice again delimiter
5528 2 50       14 if ($delimiter =~ / [\@:] /oxms) {
5529 0         0 my @char = $string =~ /\G ([\x00-\xFF]) /oxmsg;
5530 0         0 my %octet = map {$_ => 1} @char;
  0         0  
5531 0 0       0 if (not $octet{')'}) {
    0          
    0          
    0          
5532 0         0 $delimiter = '(';
5533 0         0 $end_delimiter = ')';
5534             }
5535             elsif (not $octet{'}'}) {
5536 0         0 $delimiter = '{';
5537 0         0 $end_delimiter = '}';
5538             }
5539             elsif (not $octet{']'}) {
5540 0         0 $delimiter = '[';
5541 0         0 $end_delimiter = ']';
5542             }
5543             elsif (not $octet{'>'}) {
5544 0         0 $delimiter = '<';
5545 0         0 $end_delimiter = '>';
5546             }
5547             else {
5548 0         0 for my $char (qw( ! " $ % & * + - . / = ? ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
5549 0 0       0 if (not $octet{$char}) {
5550 0         0 $delimiter = $char;
5551 0         0 $end_delimiter = $char;
5552 0         0 last;
5553             }
5554             }
5555             }
5556             }
5557              
5558 2 50 33     13 if (($ope =~ /\A m? \z/oxms) and ($delimiter eq '?')) {
5559 0         0 return join '', $ope, $delimiter, $string, $matched, $end_delimiter, $modifier;
5560             }
5561             else {
5562 2         10 return join '', $ope, $delimiter, '(?:', $string, ')', $matched, $end_delimiter, $modifier;
5563             }
5564             }
5565              
5566 641 100       1308 my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
5567 641         2190 my $metachar = qr/[\@\\|[\]{^]/oxms;
5568              
5569             # split regexp
5570 641         61722 my @char = $string =~ /\G((?>
5571             [^\\\$\@\[\(] |
5572             \\x (?>[0-9A-Fa-f]{1,2}) |
5573             \\ (?>[0-7]{2,3}) |
5574             \\c [\x40-\x5F] |
5575             \\x\{ (?>[0-9A-Fa-f]+) \} |
5576             \\o\{ (?>[0-7]+) \} |
5577             \\[bBNpP]\{ (?>[^0-9\}][^\}]*) \} |
5578             \\ $q_char |
5579             \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} |
5580             \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} |
5581             \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} |
5582             [\$\@] $qq_variable |
5583             \$ (?>\s* [0-9]+) |
5584             \$ (?>\s*) \{ (?>\s* [0-9]+ \s*) \} |
5585             \$ \$ (?![\w\{]) |
5586             \$ (?>\s*) \$ (?>\s*) $qq_variable |
5587             \[\^ |
5588             \[\: (?>[a-z]+) :\] |
5589             \[\:\^ (?>[a-z]+) :\] |
5590             \(\? |
5591             $q_char
5592             ))/oxmsg;
5593              
5594             # choice again delimiter
5595 641 50       2851 if ($delimiter =~ / [\@:] /oxms) {
5596 0         0 my %octet = map {$_ => 1} @char;
  0         0  
5597 0 0       0 if (not $octet{')'}) {
    0          
    0          
    0          
5598 0         0 $delimiter = '(';
5599 0         0 $end_delimiter = ')';
5600             }
5601             elsif (not $octet{'}'}) {
5602 0         0 $delimiter = '{';
5603 0         0 $end_delimiter = '}';
5604             }
5605             elsif (not $octet{']'}) {
5606 0         0 $delimiter = '[';
5607 0         0 $end_delimiter = ']';
5608             }
5609             elsif (not $octet{'>'}) {
5610 0         0 $delimiter = '<';
5611 0         0 $end_delimiter = '>';
5612             }
5613             else {
5614 0         0 for my $char (qw( ! " $ % & * + - . / = ? ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
5615 0 0       0 if (not $octet{$char}) {
5616 0         0 $delimiter = $char;
5617 0         0 $end_delimiter = $char;
5618 0         0 last;
5619             }
5620             }
5621             }
5622             }
5623              
5624 641         771 my $left_e = 0;
5625 641         625 my $right_e = 0;
5626 641         1702 for (my $i=0; $i <= $#char; $i++) {
5627              
5628             # "\L\u" --> "\u\L"
5629 1867 50 66     10949 if (($char[$i] eq '\L') and ($char[$i+1] eq '\u')) {
    50 66        
    100          
    100          
    100          
    100          
5630 0         0 @char[$i,$i+1] = @char[$i+1,$i];
5631             }
5632              
5633             # "\U\l" --> "\l\U"
5634             elsif (($char[$i] eq '\U') and ($char[$i+1] eq '\l')) {
5635 0         0 @char[$i,$i+1] = @char[$i+1,$i];
5636             }
5637              
5638             # octal escape sequence
5639             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
5640 1         5 $char[$i] = Ecyrillic::octchr($1);
5641             }
5642              
5643             # hexadecimal escape sequence
5644             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
5645 1         5 $char[$i] = Ecyrillic::hexchr($1);
5646             }
5647              
5648             # \b{...} --> b\{...}
5649             # \B{...} --> B\{...}
5650             # \N{CHARNAME} --> N\{CHARNAME}
5651             # \p{PROPERTY} --> p\{PROPERTY}
5652             # \P{PROPERTY} --> P\{PROPERTY}
5653             elsif ($char[$i] =~ /\A \\ ([bBNpP]) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
5654 6         27 $char[$i] = $1 . '\\' . $2;
5655             }
5656              
5657             # \p, \P, \X --> p, P, X
5658             elsif ($char[$i] =~ /\A \\ ( [pPX] ) \z/oxms) {
5659 4         12 $char[$i] = $1;
5660             }
5661              
5662 1867 100 100     5497 if (0) {
    100 100        
    100 100        
    100          
    100          
    100          
    50          
    50          
    100          
    100          
    100          
    100          
    100          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    100          
    100          
    100          
    50          
    50          
    100          
    100          
5663             }
5664              
5665             # join separated multiple-octet
5666 0         0 elsif ($char[$i] =~ /\A (?: \\ [0-7]{2,3} | \\x [0-9A-Fa-f]{1,2}) \z/oxms) {
5667 6 50 33     138 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)) {
    50 33        
    50 33        
      33        
      66        
      33        
5668 0         0 $char[$i] .= join '', splice @char, $i+1, 3;
5669             }
5670             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)) {
5671 0         0 $char[$i] .= join '', splice @char, $i+1, 2;
5672             }
5673             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)) {
5674 0         0 $char[$i] .= join '', splice @char, $i+1, 1;
5675             }
5676             }
5677              
5678             # open character class [...]
5679             elsif ($char[$i] eq '[') {
5680 328         401 my $left = $i;
5681              
5682             # [] make die "Unmatched [] in regexp ...\n"
5683             # (and so on)
5684              
5685 328 100       883 if ($char[$i+1] eq ']') {
5686 3         5 $i++;
5687             }
5688              
5689 328         307 while (1) {
5690 1379 50       1868 if (++$i > $#char) {
5691 0         0 die __FILE__, ": Unmatched [] in regexp\n";
5692             }
5693 1379 100       2091 if ($char[$i] eq ']') {
5694 328         324 my $right = $i;
5695              
5696             # [...]
5697 328 100       1887 if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
5698 30         47 splice @char, $left, $right-$left+1, sprintf(q{@{[Ecyrillic::charlist_qr(%s,'%s')]}}, join(',', map {qq_stuff($delimiter,$end_delimiter,$_)} @char[$left+1..$right-1]), $modifier);
  90         110  
5699             }
5700             else {
5701 298         1202 splice @char, $left, $right-$left+1, Ecyrillic::charlist_qr(@char[$left+1..$right-1], $modifier);
5702             }
5703              
5704 328         450 $i = $left;
5705 328         903 last;
5706             }
5707             }
5708             }
5709              
5710             # open character class [^...]
5711             elsif ($char[$i] eq '[^') {
5712 74         74 my $left = $i;
5713              
5714             # [^] make die "Unmatched [] in regexp ...\n"
5715             # (and so on)
5716              
5717 74 100       164 if ($char[$i+1] eq ']') {
5718 4         7 $i++;
5719             }
5720              
5721 74         60 while (1) {
5722 272 50       349 if (++$i > $#char) {
5723 0         0 die __FILE__, ": Unmatched [] in regexp\n";
5724             }
5725 272 100       418 if ($char[$i] eq ']') {
5726 74         60 my $right = $i;
5727              
5728             # [^...]
5729 74 100       388 if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
5730 30         50 splice @char, $left, $right-$left+1, sprintf(q{@{[Ecyrillic::charlist_not_qr(%s,'%s')]}}, join(',', map {qq_stuff($delimiter,$end_delimiter,$_)} @char[$left+1..$right-1]), $modifier);
  90         105  
5731             }
5732             else {
5733 44         167 splice @char, $left, $right-$left+1, Ecyrillic::charlist_not_qr(@char[$left+1..$right-1], $modifier);
5734             }
5735              
5736 74         100 $i = $left;
5737 74         193 last;
5738             }
5739             }
5740             }
5741              
5742             # rewrite character class or escape character
5743             elsif (my $char = character_class($char[$i],$modifier)) {
5744 139         476 $char[$i] = $char;
5745             }
5746              
5747             # /i modifier
5748             elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Ecyrillic::uc($char[$i]) ne Ecyrillic::fc($char[$i]))) {
5749 20 50       28 if (CORE::length(Ecyrillic::fc($char[$i])) == 1) {
5750 20         31 $char[$i] = '[' . Ecyrillic::uc($char[$i]) . Ecyrillic::fc($char[$i]) . ']';
5751             }
5752             else {
5753 0         0 $char[$i] = '(?:' . Ecyrillic::uc($char[$i]) . '|' . Ecyrillic::fc($char[$i]) . ')';
5754             }
5755             }
5756              
5757             # \u \l \U \L \F \Q \E
5758             elsif ($char[$i] =~ /\A [<>] \z/oxms) {
5759 1 50       10 if ($right_e < $left_e) {
5760 0         0 $char[$i] = '\\' . $char[$i];
5761             }
5762             }
5763             elsif ($char[$i] eq '\u') {
5764 0         0 $char[$i] = '@{[Ecyrillic::ucfirst qq<';
5765 0         0 $left_e++;
5766             }
5767             elsif ($char[$i] eq '\l') {
5768 0         0 $char[$i] = '@{[Ecyrillic::lcfirst qq<';
5769 0         0 $left_e++;
5770             }
5771             elsif ($char[$i] eq '\U') {
5772 1         1 $char[$i] = '@{[Ecyrillic::uc qq<';
5773 1         5 $left_e++;
5774             }
5775             elsif ($char[$i] eq '\L') {
5776 1         1 $char[$i] = '@{[Ecyrillic::lc qq<';
5777 1         4 $left_e++;
5778             }
5779             elsif ($char[$i] eq '\F') {
5780 18         21 $char[$i] = '@{[Ecyrillic::fc qq<';
5781 18         74 $left_e++;
5782             }
5783             elsif ($char[$i] eq '\Q') {
5784 1         1 $char[$i] = '@{[CORE::quotemeta qq<';
5785 1         4 $left_e++;
5786             }
5787             elsif ($char[$i] eq '\E') {
5788 21 50       32 if ($right_e < $left_e) {
5789 21         21 $char[$i] = '>]}';
5790 21         64 $right_e++;
5791             }
5792             else {
5793 0         0 $char[$i] = '';
5794             }
5795             }
5796             elsif ($char[$i] eq '\Q') {
5797 0         0 while (1) {
5798 0 0       0 if (++$i > $#char) {
5799 0         0 last;
5800             }
5801 0 0       0 if ($char[$i] eq '\E') {
5802 0         0 last;
5803             }
5804             }
5805             }
5806             elsif ($char[$i] eq '\E') {
5807             }
5808              
5809             # $0 --> $0
5810             elsif ($char[$i] =~ /\A \$ 0 \z/oxms) {
5811 0 0       0 if ($ignorecase) {
5812 0         0 $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
5813             }
5814             }
5815             elsif ($char[$i] =~ /\A \$ \{ (?>\s*) 0 (?>\s*) \} \z/oxms) {
5816 0 0       0 if ($ignorecase) {
5817 0         0 $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
5818             }
5819             }
5820              
5821             # $$ --> $$
5822             elsif ($char[$i] =~ /\A \$\$ \z/oxms) {
5823             }
5824              
5825             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
5826             # $1, $2, $3 --> $1, $2, $3 otherwise
5827             elsif ($char[$i] =~ /\A \$ ((?>[1-9][0-9]*)) \z/oxms) {
5828 0         0 $char[$i] = e_capture($1);
5829 0 0       0 if ($ignorecase) {
5830 0         0 $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
5831             }
5832             }
5833             elsif ($char[$i] =~ /\A \$ \{ (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} \z/oxms) {
5834 0         0 $char[$i] = e_capture($1);
5835 0 0       0 if ($ignorecase) {
5836 0         0 $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
5837             }
5838             }
5839              
5840             # $$foo[ ... ] --> $ $foo->[ ... ]
5841             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \[ (?:$qq_bracket)*? \] ) \z/oxms) {
5842 0         0 $char[$i] = e_capture($1.'->'.$2);
5843 0 0       0 if ($ignorecase) {
5844 0         0 $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
5845             }
5846             }
5847              
5848             # $$foo{ ... } --> $ $foo->{ ... }
5849             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \{ (?:$qq_brace)*? \} ) \z/oxms) {
5850 0         0 $char[$i] = e_capture($1.'->'.$2);
5851 0 0       0 if ($ignorecase) {
5852 0         0 $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
5853             }
5854             }
5855              
5856             # $$foo
5857             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) \z/oxms) {
5858 0         0 $char[$i] = e_capture($1);
5859 0 0       0 if ($ignorecase) {
5860 0         0 $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
5861             }
5862             }
5863              
5864             # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Ecyrillic::PREMATCH()
5865             elsif ($char[$i] =~ /\A ( \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} ) \z/oxmsgc) {
5866 8 50       17 if ($ignorecase) {
5867 0         0 $char[$i] = '@{[Ecyrillic::ignorecase(Ecyrillic::PREMATCH())]}';
5868             }
5869             else {
5870 8         32 $char[$i] = '@{[Ecyrillic::PREMATCH()]}';
5871             }
5872             }
5873              
5874             # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Ecyrillic::MATCH()
5875             elsif ($char[$i] =~ /\A ( \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} ) \z/oxmsgc) {
5876 8 50       16 if ($ignorecase) {
5877 0         0 $char[$i] = '@{[Ecyrillic::ignorecase(Ecyrillic::MATCH())]}';
5878             }
5879             else {
5880 8         36 $char[$i] = '@{[Ecyrillic::MATCH()]}';
5881             }
5882             }
5883              
5884             # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Ecyrillic::POSTMATCH()
5885             elsif ($char[$i] =~ /\A ( \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} ) \z/oxmsgc) {
5886 6 50       15 if ($ignorecase) {
5887 0         0 $char[$i] = '@{[Ecyrillic::ignorecase(Ecyrillic::POSTMATCH())]}';
5888             }
5889             else {
5890 6         25 $char[$i] = '@{[Ecyrillic::POSTMATCH()]}';
5891             }
5892             }
5893              
5894             # ${ foo }
5895             elsif ($char[$i] =~ /\A \$ (?>\s*) \{ ((?> \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* )) \} \z/oxms) {
5896 0 0       0 if ($ignorecase) {
5897 0         0 $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
5898             }
5899             }
5900              
5901             # ${ ... }
5902             elsif ($char[$i] =~ /\A \$ (?>\s*) \{ ( .+ ) \} \z/oxms) {
5903 0         0 $char[$i] = e_capture($1);
5904 0 0       0 if ($ignorecase) {
5905 0         0 $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
5906             }
5907             }
5908              
5909             # $scalar or @array
5910             elsif ($char[$i] =~ /\A [\$\@].+ /oxms) {
5911 21         42 $char[$i] = e_string($char[$i]);
5912 21 100       78 if ($ignorecase) {
5913 11         51 $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
5914             }
5915             }
5916              
5917             # quote character before ? + * {
5918             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
5919 138 100 33     1127 if ($char[$i-1] =~ /\A (?:[\x00-\xFF]|\\[0-7]{2,3}|\\x[0-9-A-Fa-f]{1,2}) \z/oxms) {
    50          
5920             }
5921             elsif (($ope =~ /\A m? \z/oxms) and ($delimiter eq '?')) {
5922 0         0 my $char = $char[$i-1];
5923 0 0       0 if ($char[$i] eq '{') {
5924 0         0 die __FILE__, qq{: "MULTIBYTE{n}" should be "(MULTIBYTE){n}" in m?? (and shift \$1,\$2,\$3,...) ($char){n}\n};
5925             }
5926             else {
5927 0         0 die __FILE__, qq{: "MULTIBYTE$char[$i]" should be "(MULTIBYTE)$char[$i]" in m?? (and shift \$1,\$2,\$3,...) ($char)$char[$i]\n};
5928             }
5929             }
5930             else {
5931 127         736 $char[$i-1] = '(?:' . $char[$i-1] . ')';
5932             }
5933             }
5934             }
5935              
5936             # make regexp string
5937 641         846 $modifier =~ tr/i//d;
5938 641 50       1314 if ($left_e > $right_e) {
5939 0 0 0     0 if (($ope =~ /\A m? \z/oxms) and ($delimiter eq '?')) {
5940 0         0 return join '', $ope, $delimiter, $anchor, @char, '>]}' x ($left_e - $right_e), $matched, $end_delimiter, $modifier;
5941             }
5942             else {
5943 0         0 return join '', $ope, $delimiter, $anchor, '(?:', @char, '>]}' x ($left_e - $right_e), ')', $matched, $end_delimiter, $modifier;
5944             }
5945             }
5946 641 50 33     3841 if (($ope =~ /\A m? \z/oxms) and ($delimiter eq '?')) {
5947 0         0 return join '', $ope, $delimiter, $anchor, @char, $matched, $end_delimiter, $modifier;
5948             }
5949             else {
5950 641         5087 return join '', $ope, $delimiter, $anchor, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
5951             }
5952             }
5953              
5954             #
5955             # double quote stuff
5956             #
5957             sub qq_stuff {
5958 180     180 0 157 my($delimiter,$end_delimiter,$stuff) = @_;
5959              
5960             # scalar variable or array variable
5961 180 100       330 if ($stuff =~ /\A [\$\@] /oxms) {
5962 100         297 return $stuff;
5963             }
5964              
5965             # quote by delimiter
5966 80         157 my %octet = map {$_ => 1} ($stuff =~ /\G ([\x00-\xFF]) /oxmsg);
  80         196  
5967 80         152 for my $char (qw( ! " $ % & * + - . / : = ? @ ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
5968 80 50       118 next if $char eq $delimiter;
5969 80 50       96 next if $char eq $end_delimiter;
5970 80 50       153 if (not $octet{$char}) {
5971 80         336 return join '', 'qq', $char, $stuff, $char;
5972             }
5973             }
5974 0         0 return join '', 'qq', '<', $stuff, '>';
5975             }
5976              
5977             #
5978             # escape regexp (m'', qr'', and m''b, qr''b)
5979             #
5980             sub e_qr_q {
5981 10     10 0 30 my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
5982 10   50     39 $modifier ||= '';
5983              
5984 10         11 $modifier =~ tr/p//d;
5985 10 50       24 if ($modifier =~ /([adlu])/oxms) {
5986 0         0 my $line = 0;
5987 0         0 for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
5988 0 0       0 if ($filename ne __FILE__) {
5989 0         0 $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
5990 0         0 last;
5991             }
5992             }
5993 0         0 die qq{Unsupported modifier "$1" used at line $line.\n};
5994             }
5995              
5996 10         10 $slash = 'div';
5997              
5998             # literal null string pattern
5999 10 100       35 if ($string eq '') {
    50          
6000 8         9 $modifier =~ tr/bB//d;
6001 8         7 $modifier =~ tr/i//d;
6002 8         41 return join '', $ope, $delimiter, $end_delimiter, $modifier;
6003             }
6004              
6005             # with /b /B modifier
6006             elsif ($modifier =~ tr/bB//d) {
6007 0         0 return e_qr_qb($ope,$delimiter,$end_delimiter,$string,$modifier);
6008             }
6009              
6010             # without /b /B modifier
6011             else {
6012 2         7 return e_qr_qt($ope,$delimiter,$end_delimiter,$string,$modifier);
6013             }
6014             }
6015              
6016             #
6017             # escape regexp (m'', qr'')
6018             #
6019             sub e_qr_qt {
6020 2     2 0 4 my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6021              
6022 2 50       7 my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
6023              
6024             # split regexp
6025 2         134 my @char = $string =~ /\G((?>
6026             [^\\\[\$\@\/] |
6027             [\x00-\xFF] |
6028             \[\^ |
6029             \[\: (?>[a-z]+) \:\] |
6030             \[\:\^ (?>[a-z]+) \:\] |
6031             [\$\@\/] |
6032             \\ (?:$q_char) |
6033             (?:$q_char)
6034             ))/oxmsg;
6035              
6036             # unescape character
6037 2         13 for (my $i=0; $i <= $#char; $i++) {
6038 2 50 33     22 if (0) {
    50 33        
    50 33        
    50          
    50          
    50          
6039             }
6040              
6041             # open character class [...]
6042 0         0 elsif ($char[$i] eq '[') {
6043 0         0 my $left = $i;
6044 0 0       0 if ($char[$i+1] eq ']') {
6045 0         0 $i++;
6046             }
6047 0         0 while (1) {
6048 0 0       0 if (++$i > $#char) {
6049 0         0 die __FILE__, ": Unmatched [] in regexp\n";
6050             }
6051 0 0       0 if ($char[$i] eq ']') {
6052 0         0 my $right = $i;
6053              
6054             # [...]
6055 0         0 splice @char, $left, $right-$left+1, Ecyrillic::charlist_qr(@char[$left+1..$right-1], $modifier);
6056              
6057 0         0 $i = $left;
6058 0         0 last;
6059             }
6060             }
6061             }
6062              
6063             # open character class [^...]
6064             elsif ($char[$i] eq '[^') {
6065 0         0 my $left = $i;
6066 0 0       0 if ($char[$i+1] eq ']') {
6067 0         0 $i++;
6068             }
6069 0         0 while (1) {
6070 0 0       0 if (++$i > $#char) {
6071 0         0 die __FILE__, ": Unmatched [] in regexp\n";
6072             }
6073 0 0       0 if ($char[$i] eq ']') {
6074 0         0 my $right = $i;
6075              
6076             # [^...]
6077 0         0 splice @char, $left, $right-$left+1, Ecyrillic::charlist_not_qr(@char[$left+1..$right-1], $modifier);
6078              
6079 0         0 $i = $left;
6080 0         0 last;
6081             }
6082             }
6083             }
6084              
6085             # escape $ @ / and \
6086             elsif ($char[$i] =~ /\A [\$\@\/\\] \z/oxms) {
6087 0         0 $char[$i] = '\\' . $char[$i];
6088             }
6089              
6090             # rewrite character class or escape character
6091             elsif (my $char = character_class($char[$i],$modifier)) {
6092 0         0 $char[$i] = $char;
6093             }
6094              
6095             # /i modifier
6096             elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Ecyrillic::uc($char[$i]) ne Ecyrillic::fc($char[$i]))) {
6097 0 0       0 if (CORE::length(Ecyrillic::fc($char[$i])) == 1) {
6098 0         0 $char[$i] = '[' . Ecyrillic::uc($char[$i]) . Ecyrillic::fc($char[$i]) . ']';
6099             }
6100             else {
6101 0         0 $char[$i] = '(?:' . Ecyrillic::uc($char[$i]) . '|' . Ecyrillic::fc($char[$i]) . ')';
6102             }
6103             }
6104              
6105             # quote character before ? + * {
6106             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
6107 0 0       0 if ($char[$i-1] =~ /\A [\x00-\xFF] \z/oxms) {
6108             }
6109             else {
6110 0         0 $char[$i-1] = '(?:' . $char[$i-1] . ')';
6111             }
6112             }
6113             }
6114              
6115 2         5 $delimiter = '/';
6116 2         4 $end_delimiter = '/';
6117              
6118 2         3 $modifier =~ tr/i//d;
6119 2         19 return join '', $ope, $delimiter, $anchor, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
6120             }
6121              
6122             #
6123             # escape regexp (m''b, qr''b)
6124             #
6125             sub e_qr_qb {
6126 0     0 0 0 my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6127              
6128             # split regexp
6129 0         0 my @char = $string =~ /\G ((?>[^\\]|\\\\)) /oxmsg;
6130              
6131             # unescape character
6132 0         0 for (my $i=0; $i <= $#char; $i++) {
6133 0 0       0 if (0) {
    0          
6134             }
6135              
6136             # remain \\
6137 0         0 elsif ($char[$i] eq '\\\\') {
6138             }
6139              
6140             # escape $ @ / and \
6141             elsif ($char[$i] =~ /\A [\$\@\/\\] \z/oxms) {
6142 0         0 $char[$i] = '\\' . $char[$i];
6143             }
6144             }
6145              
6146 0         0 $delimiter = '/';
6147 0         0 $end_delimiter = '/';
6148 0         0 return join '', $ope, $delimiter, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
6149             }
6150              
6151             #
6152             # escape regexp (s/here//)
6153             #
6154             sub e_s1 {
6155 76     76 0 164 my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6156 76   100     268 $modifier ||= '';
6157              
6158 76         90 $modifier =~ tr/p//d;
6159 76 50       242 if ($modifier =~ /([adlu])/oxms) {
6160 0         0 my $line = 0;
6161 0         0 for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
6162 0 0       0 if ($filename ne __FILE__) {
6163 0         0 $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
6164 0         0 last;
6165             }
6166             }
6167 0         0 die qq{Unsupported modifier "$1" used at line $line.\n};
6168             }
6169              
6170 76         112 $slash = 'div';
6171              
6172             # literal null string pattern
6173 76 100       285 if ($string eq '') {
    50          
6174 8         11 $modifier =~ tr/bB//d;
6175 8         6 $modifier =~ tr/i//d;
6176 8         60 return join '', $ope, $delimiter, $end_delimiter, $modifier;
6177             }
6178              
6179             # /b /B modifier
6180             elsif ($modifier =~ tr/bB//d) {
6181              
6182             # choice again delimiter
6183 0 0       0 if ($delimiter =~ / [\@:] /oxms) {
6184 0         0 my @char = $string =~ /\G ([\x00-\xFF]) /oxmsg;
6185 0         0 my %octet = map {$_ => 1} @char;
  0         0  
6186 0 0       0 if (not $octet{')'}) {
    0          
    0          
    0          
6187 0         0 $delimiter = '(';
6188 0         0 $end_delimiter = ')';
6189             }
6190             elsif (not $octet{'}'}) {
6191 0         0 $delimiter = '{';
6192 0         0 $end_delimiter = '}';
6193             }
6194             elsif (not $octet{']'}) {
6195 0         0 $delimiter = '[';
6196 0         0 $end_delimiter = ']';
6197             }
6198             elsif (not $octet{'>'}) {
6199 0         0 $delimiter = '<';
6200 0         0 $end_delimiter = '>';
6201             }
6202             else {
6203 0         0 for my $char (qw( ! " $ % & * + - . / = ? ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
6204 0 0       0 if (not $octet{$char}) {
6205 0         0 $delimiter = $char;
6206 0         0 $end_delimiter = $char;
6207 0         0 last;
6208             }
6209             }
6210             }
6211             }
6212              
6213 0         0 my $prematch = '';
6214 0         0 return join '', $ope, $delimiter, $prematch, '(?:', $string, ')', $matched, $end_delimiter, $modifier;
6215             }
6216              
6217 68 100       170 my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
6218 68         276 my $metachar = qr/[\@\\|[\]{^]/oxms;
6219              
6220             # split regexp
6221 68         16194 my @char = $string =~ /\G((?>
6222             [^\\\$\@\[\(] |
6223             \\ (?>[1-9][0-9]*) |
6224             \\g (?>\s*) (?>[1-9][0-9]*) |
6225             \\g (?>\s*) \{ (?>\s*) (?>[1-9][0-9]*) (?>\s*) \} |
6226             \\g (?>\s*) \{ (?>\s*) - (?>\s*) (?>[1-9][0-9]*) (?>\s*) \} |
6227             \\x (?>[0-9A-Fa-f]{1,2}) |
6228             \\ (?>[0-7]{2,3}) |
6229             \\c [\x40-\x5F] |
6230             \\x\{ (?>[0-9A-Fa-f]+) \} |
6231             \\o\{ (?>[0-7]+) \} |
6232             \\[bBNpP]\{ (?>[^0-9\}][^\}]*) \} |
6233             \\ $q_char |
6234             \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} |
6235             \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} |
6236             \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} |
6237             [\$\@] $qq_variable |
6238             \$ (?>\s* [0-9]+) |
6239             \$ (?>\s*) \{ (?>\s* [0-9]+ \s*) \} |
6240             \$ \$ (?![\w\{]) |
6241             \$ (?>\s*) \$ (?>\s*) $qq_variable |
6242             \[\^ |
6243             \[\: (?>[a-z]+) :\] |
6244             \[\:\^ (?>[a-z]+) :\] |
6245             \(\? |
6246             $q_char
6247             ))/oxmsg;
6248              
6249             # choice again delimiter
6250 68 50       528 if ($delimiter =~ / [\@:] /oxms) {
6251 0         0 my %octet = map {$_ => 1} @char;
  0         0  
6252 0 0       0 if (not $octet{')'}) {
    0          
    0          
    0          
6253 0         0 $delimiter = '(';
6254 0         0 $end_delimiter = ')';
6255             }
6256             elsif (not $octet{'}'}) {
6257 0         0 $delimiter = '{';
6258 0         0 $end_delimiter = '}';
6259             }
6260             elsif (not $octet{']'}) {
6261 0         0 $delimiter = '[';
6262 0         0 $end_delimiter = ']';
6263             }
6264             elsif (not $octet{'>'}) {
6265 0         0 $delimiter = '<';
6266 0         0 $end_delimiter = '>';
6267             }
6268             else {
6269 0         0 for my $char (qw( ! " $ % & * + - . / = ? ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
6270 0 0       0 if (not $octet{$char}) {
6271 0         0 $delimiter = $char;
6272 0         0 $end_delimiter = $char;
6273 0         0 last;
6274             }
6275             }
6276             }
6277             }
6278              
6279             # count '('
6280 68         119 my $parens = grep { $_ eq '(' } @char;
  253         357  
6281              
6282 68         92 my $left_e = 0;
6283 68         90 my $right_e = 0;
6284 68         215 for (my $i=0; $i <= $#char; $i++) {
6285              
6286             # "\L\u" --> "\u\L"
6287 195 50 33     1311 if (($char[$i] eq '\L') and ($char[$i+1] eq '\u')) {
    50 33        
    100          
    100          
    50          
    50          
6288 0         0 @char[$i,$i+1] = @char[$i+1,$i];
6289             }
6290              
6291             # "\U\l" --> "\l\U"
6292             elsif (($char[$i] eq '\U') and ($char[$i+1] eq '\l')) {
6293 0         0 @char[$i,$i+1] = @char[$i+1,$i];
6294             }
6295              
6296             # octal escape sequence
6297             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
6298 1         4 $char[$i] = Ecyrillic::octchr($1);
6299             }
6300              
6301             # hexadecimal escape sequence
6302             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
6303 1         4 $char[$i] = Ecyrillic::hexchr($1);
6304             }
6305              
6306             # \b{...} --> b\{...}
6307             # \B{...} --> B\{...}
6308             # \N{CHARNAME} --> N\{CHARNAME}
6309             # \p{PROPERTY} --> p\{PROPERTY}
6310             # \P{PROPERTY} --> P\{PROPERTY}
6311             elsif ($char[$i] =~ /\A \\ ([bBNpP]) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
6312 0         0 $char[$i] = $1 . '\\' . $2;
6313             }
6314              
6315             # \p, \P, \X --> p, P, X
6316             elsif ($char[$i] =~ /\A \\ ( [pPX] ) \z/oxms) {
6317 0         0 $char[$i] = $1;
6318             }
6319              
6320 195 50 66     745 if (0) {
    100 66        
    50 100        
    100          
    100          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    100          
    100          
    100          
    50          
    50          
    100          
    100          
6321             }
6322              
6323             # join separated multiple-octet
6324 0         0 elsif ($char[$i] =~ /\A (?: \\ [0-7]{2,3} | \\x [0-9A-Fa-f]{1,2}) \z/oxms) {
6325 0 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        
6326 0         0 $char[$i] .= join '', splice @char, $i+1, 3;
6327             }
6328             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)) {
6329 0         0 $char[$i] .= join '', splice @char, $i+1, 2;
6330             }
6331             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)) {
6332 0         0 $char[$i] .= join '', splice @char, $i+1, 1;
6333             }
6334             }
6335              
6336             # open character class [...]
6337             elsif ($char[$i] eq '[') {
6338 13         18 my $left = $i;
6339 13 50       34 if ($char[$i+1] eq ']') {
6340 0         0 $i++;
6341             }
6342 13         12 while (1) {
6343 58 50       72 if (++$i > $#char) {
6344 0         0 die __FILE__, ": Unmatched [] in regexp\n";
6345             }
6346 58 100       77 if ($char[$i] eq ']') {
6347 13         11 my $right = $i;
6348              
6349             # [...]
6350 13 50       82 if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
6351 0         0 splice @char, $left, $right-$left+1, sprintf(q{@{[Ecyrillic::charlist_qr(%s,'%s')]}}, join(',', map {qq_stuff($delimiter,$end_delimiter,$_)} @char[$left+1..$right-1]), $modifier);
  0         0  
6352             }
6353             else {
6354 13         87 splice @char, $left, $right-$left+1, Ecyrillic::charlist_qr(@char[$left+1..$right-1], $modifier);
6355             }
6356              
6357 13         20 $i = $left;
6358 13         27 last;
6359             }
6360             }
6361             }
6362              
6363             # open character class [^...]
6364             elsif ($char[$i] eq '[^') {
6365 0         0 my $left = $i;
6366 0 0       0 if ($char[$i+1] eq ']') {
6367 0         0 $i++;
6368             }
6369 0         0 while (1) {
6370 0 0       0 if (++$i > $#char) {
6371 0         0 die __FILE__, ": Unmatched [] in regexp\n";
6372             }
6373 0 0       0 if ($char[$i] eq ']') {
6374 0         0 my $right = $i;
6375              
6376             # [^...]
6377 0 0       0 if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
6378 0         0 splice @char, $left, $right-$left+1, sprintf(q{@{[Ecyrillic::charlist_not_qr(%s,'%s')]}}, join(',', map {qq_stuff($delimiter,$end_delimiter,$_)} @char[$left+1..$right-1]), $modifier);
  0         0  
6379             }
6380             else {
6381 0         0 splice @char, $left, $right-$left+1, Ecyrillic::charlist_not_qr(@char[$left+1..$right-1], $modifier);
6382             }
6383              
6384 0         0 $i = $left;
6385 0         0 last;
6386             }
6387             }
6388             }
6389              
6390             # rewrite character class or escape character
6391             elsif (my $char = character_class($char[$i],$modifier)) {
6392 7         19 $char[$i] = $char;
6393             }
6394              
6395             # /i modifier
6396             elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Ecyrillic::uc($char[$i]) ne Ecyrillic::fc($char[$i]))) {
6397 3 50       6 if (CORE::length(Ecyrillic::fc($char[$i])) == 1) {
6398 3         7 $char[$i] = '[' . Ecyrillic::uc($char[$i]) . Ecyrillic::fc($char[$i]) . ']';
6399             }
6400             else {
6401 0         0 $char[$i] = '(?:' . Ecyrillic::uc($char[$i]) . '|' . Ecyrillic::fc($char[$i]) . ')';
6402             }
6403             }
6404              
6405             # \u \l \U \L \F \Q \E
6406             elsif ($char[$i] =~ /\A [<>] \z/oxms) {
6407 0 0       0 if ($right_e < $left_e) {
6408 0         0 $char[$i] = '\\' . $char[$i];
6409             }
6410             }
6411             elsif ($char[$i] eq '\u') {
6412 0         0 $char[$i] = '@{[Ecyrillic::ucfirst qq<';
6413 0         0 $left_e++;
6414             }
6415             elsif ($char[$i] eq '\l') {
6416 0         0 $char[$i] = '@{[Ecyrillic::lcfirst qq<';
6417 0         0 $left_e++;
6418             }
6419             elsif ($char[$i] eq '\U') {
6420 0         0 $char[$i] = '@{[Ecyrillic::uc qq<';
6421 0         0 $left_e++;
6422             }
6423             elsif ($char[$i] eq '\L') {
6424 0         0 $char[$i] = '@{[Ecyrillic::lc qq<';
6425 0         0 $left_e++;
6426             }
6427             elsif ($char[$i] eq '\F') {
6428 0         0 $char[$i] = '@{[Ecyrillic::fc qq<';
6429 0         0 $left_e++;
6430             }
6431             elsif ($char[$i] eq '\Q') {
6432 0         0 $char[$i] = '@{[CORE::quotemeta qq<';
6433 0         0 $left_e++;
6434             }
6435             elsif ($char[$i] eq '\E') {
6436 0 0       0 if ($right_e < $left_e) {
6437 0         0 $char[$i] = '>]}';
6438 0         0 $right_e++;
6439             }
6440             else {
6441 0         0 $char[$i] = '';
6442             }
6443             }
6444             elsif ($char[$i] eq '\Q') {
6445 0         0 while (1) {
6446 0 0       0 if (++$i > $#char) {
6447 0         0 last;
6448             }
6449 0 0       0 if ($char[$i] eq '\E') {
6450 0         0 last;
6451             }
6452             }
6453             }
6454             elsif ($char[$i] eq '\E') {
6455             }
6456              
6457             # \0 --> \0
6458             elsif ($char[$i] =~ /\A \\ (?>\s*) 0 \z/oxms) {
6459             }
6460              
6461             # \g{N}, \g{-N}
6462              
6463             # P.108 Using Simple Patterns
6464             # in Chapter 7: In the World of Regular Expressions
6465             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
6466              
6467             # P.221 Capturing
6468             # in Chapter 5: Pattern Matching
6469             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
6470              
6471             # \g{-1}, \g{-2}, \g{-3} --> \g{-1}, \g{-2}, \g{-3}
6472             elsif ($char[$i] =~ /\A \\g (?>\s*) \{ (?>\s*) - (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} \z/oxms) {
6473             }
6474              
6475             # \g{1}, \g{2}, \g{3} --> \g{2}, \g{3}, \g{4} (only when multibyte anchoring is enable)
6476             elsif ($char[$i] =~ /\A \\g (?>\s*) \{ (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} \z/oxms) {
6477             }
6478              
6479             # \g1, \g2, \g3 --> \g2, \g3, \g4 (only when multibyte anchoring is enable)
6480             elsif ($char[$i] =~ /\A \\g (?>\s*) ((?>[1-9][0-9]*)) \z/oxms) {
6481             }
6482              
6483             # \1, \2, \3 --> \2, \3, \4 (only when multibyte anchoring is enable)
6484             elsif ($char[$i] =~ /\A \\ (?>\s*) ((?>[1-9][0-9]*)) \z/oxms) {
6485             }
6486              
6487             # $0 --> $0
6488             elsif ($char[$i] =~ /\A \$ 0 \z/oxms) {
6489 0 0       0 if ($ignorecase) {
6490 0         0 $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
6491             }
6492             }
6493             elsif ($char[$i] =~ /\A \$ \{ (?>\s*) 0 (?>\s*) \} \z/oxms) {
6494 0 0       0 if ($ignorecase) {
6495 0         0 $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
6496             }
6497             }
6498              
6499             # $$ --> $$
6500             elsif ($char[$i] =~ /\A \$\$ \z/oxms) {
6501             }
6502              
6503             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
6504             # $1, $2, $3 --> $1, $2, $3 otherwise
6505             elsif ($char[$i] =~ /\A \$ ((?>[1-9][0-9]*)) \z/oxms) {
6506 0         0 $char[$i] = e_capture($1);
6507 0 0       0 if ($ignorecase) {
6508 0         0 $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
6509             }
6510             }
6511             elsif ($char[$i] =~ /\A \$ \{ (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} \z/oxms) {
6512 0         0 $char[$i] = e_capture($1);
6513 0 0       0 if ($ignorecase) {
6514 0         0 $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
6515             }
6516             }
6517              
6518             # $$foo[ ... ] --> $ $foo->[ ... ]
6519             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \[ (?:$qq_bracket)*? \] ) \z/oxms) {
6520 0         0 $char[$i] = e_capture($1.'->'.$2);
6521 0 0       0 if ($ignorecase) {
6522 0         0 $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
6523             }
6524             }
6525              
6526             # $$foo{ ... } --> $ $foo->{ ... }
6527             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \{ (?:$qq_brace)*? \} ) \z/oxms) {
6528 0         0 $char[$i] = e_capture($1.'->'.$2);
6529 0 0       0 if ($ignorecase) {
6530 0         0 $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
6531             }
6532             }
6533              
6534             # $$foo
6535             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) \z/oxms) {
6536 0         0 $char[$i] = e_capture($1);
6537 0 0       0 if ($ignorecase) {
6538 0         0 $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
6539             }
6540             }
6541              
6542             # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Ecyrillic::PREMATCH()
6543             elsif ($char[$i] =~ /\A ( \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} ) \z/oxmsgc) {
6544 4 50       15 if ($ignorecase) {
6545 0         0 $char[$i] = '@{[Ecyrillic::ignorecase(Ecyrillic::PREMATCH())]}';
6546             }
6547             else {
6548 4         24 $char[$i] = '@{[Ecyrillic::PREMATCH()]}';
6549             }
6550             }
6551              
6552             # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Ecyrillic::MATCH()
6553             elsif ($char[$i] =~ /\A ( \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} ) \z/oxmsgc) {
6554 4 50       16 if ($ignorecase) {
6555 0         0 $char[$i] = '@{[Ecyrillic::ignorecase(Ecyrillic::MATCH())]}';
6556             }
6557             else {
6558 4         29 $char[$i] = '@{[Ecyrillic::MATCH()]}';
6559             }
6560             }
6561              
6562             # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Ecyrillic::POSTMATCH()
6563             elsif ($char[$i] =~ /\A ( \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} ) \z/oxmsgc) {
6564 3 50       12 if ($ignorecase) {
6565 0         0 $char[$i] = '@{[Ecyrillic::ignorecase(Ecyrillic::POSTMATCH())]}';
6566             }
6567             else {
6568 3         19 $char[$i] = '@{[Ecyrillic::POSTMATCH()]}';
6569             }
6570             }
6571              
6572             # ${ foo }
6573             elsif ($char[$i] =~ /\A \$ (?>\s*) \{ ((?> \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* )) \} \z/oxms) {
6574 0 0       0 if ($ignorecase) {
6575 0         0 $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
6576             }
6577             }
6578              
6579             # ${ ... }
6580             elsif ($char[$i] =~ /\A \$ (?>\s*) \{ ( .+ ) \} \z/oxms) {
6581 0         0 $char[$i] = e_capture($1);
6582 0 0       0 if ($ignorecase) {
6583 0         0 $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
6584             }
6585             }
6586              
6587             # $scalar or @array
6588             elsif ($char[$i] =~ /\A [\$\@].+ /oxms) {
6589 4         17 $char[$i] = e_string($char[$i]);
6590 4 50       35 if ($ignorecase) {
6591 0         0 $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
6592             }
6593             }
6594              
6595             # quote character before ? + * {
6596             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
6597 13 50       44 if ($char[$i-1] =~ /\A (?:[\x00-\xFF]|\\[0-7]{2,3}|\\x[0-9-A-Fa-f]{1,2}) \z/oxms) {
6598             }
6599             else {
6600 13         73 $char[$i-1] = '(?:' . $char[$i-1] . ')';
6601             }
6602             }
6603             }
6604              
6605             # make regexp string
6606 68         122 my $prematch = '';
6607 68         102 $modifier =~ tr/i//d;
6608 68 50       206 if ($left_e > $right_e) {
6609 0         0 return join '', $ope, $delimiter, $prematch, '(?:', @char, '>]}' x ($left_e - $right_e), ')', $matched, $end_delimiter, $modifier;
6610             }
6611 68         838 return join '', $ope, $delimiter, $prematch, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
6612             }
6613              
6614             #
6615             # escape regexp (s'here'' or s'here''b)
6616             #
6617             sub e_s1_q {
6618 21     21 0 39 my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6619 21   100     62 $modifier ||= '';
6620              
6621 21         22 $modifier =~ tr/p//d;
6622 21 50       48 if ($modifier =~ /([adlu])/oxms) {
6623 0         0 my $line = 0;
6624 0         0 for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
6625 0 0       0 if ($filename ne __FILE__) {
6626 0         0 $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
6627 0         0 last;
6628             }
6629             }
6630 0         0 die qq{Unsupported modifier "$1" used at line $line.\n};
6631             }
6632              
6633 21         24 $slash = 'div';
6634              
6635             # literal null string pattern
6636 21 100       49 if ($string eq '') {
    50          
6637 8         8 $modifier =~ tr/bB//d;
6638 8         8 $modifier =~ tr/i//d;
6639 8         59 return join '', $ope, $delimiter, $end_delimiter, $modifier;
6640             }
6641              
6642             # with /b /B modifier
6643             elsif ($modifier =~ tr/bB//d) {
6644 0         0 return e_s1_qb($ope,$delimiter,$end_delimiter,$string,$modifier);
6645             }
6646              
6647             # without /b /B modifier
6648             else {
6649 13         34 return e_s1_qt($ope,$delimiter,$end_delimiter,$string,$modifier);
6650             }
6651             }
6652              
6653             #
6654             # escape regexp (s'here'')
6655             #
6656             sub e_s1_qt {
6657 13     13 0 22 my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6658              
6659 13 50       28 my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
6660              
6661             # split regexp
6662 13         265 my @char = $string =~ /\G((?>
6663             [^\\\[\$\@\/] |
6664             [\x00-\xFF] |
6665             \[\^ |
6666             \[\: (?>[a-z]+) \:\] |
6667             \[\:\^ (?>[a-z]+) \:\] |
6668             [\$\@\/] |
6669             \\ (?:$q_char) |
6670             (?:$q_char)
6671             ))/oxmsg;
6672              
6673             # unescape character
6674 13         43 for (my $i=0; $i <= $#char; $i++) {
6675 25 50 33     114 if (0) {
    50 33        
    50 66        
    100          
    50          
    50          
6676             }
6677              
6678             # open character class [...]
6679 0         0 elsif ($char[$i] eq '[') {
6680 0         0 my $left = $i;
6681 0 0       0 if ($char[$i+1] eq ']') {
6682 0         0 $i++;
6683             }
6684 0         0 while (1) {
6685 0 0       0 if (++$i > $#char) {
6686 0         0 die __FILE__, ": Unmatched [] in regexp\n";
6687             }
6688 0 0       0 if ($char[$i] eq ']') {
6689 0         0 my $right = $i;
6690              
6691             # [...]
6692 0         0 splice @char, $left, $right-$left+1, Ecyrillic::charlist_qr(@char[$left+1..$right-1], $modifier);
6693              
6694 0         0 $i = $left;
6695 0         0 last;
6696             }
6697             }
6698             }
6699              
6700             # open character class [^...]
6701             elsif ($char[$i] eq '[^') {
6702 0         0 my $left = $i;
6703 0 0       0 if ($char[$i+1] eq ']') {
6704 0         0 $i++;
6705             }
6706 0         0 while (1) {
6707 0 0       0 if (++$i > $#char) {
6708 0         0 die __FILE__, ": Unmatched [] in regexp\n";
6709             }
6710 0 0       0 if ($char[$i] eq ']') {
6711 0         0 my $right = $i;
6712              
6713             # [^...]
6714 0         0 splice @char, $left, $right-$left+1, Ecyrillic::charlist_not_qr(@char[$left+1..$right-1], $modifier);
6715              
6716 0         0 $i = $left;
6717 0         0 last;
6718             }
6719             }
6720             }
6721              
6722             # escape $ @ / and \
6723             elsif ($char[$i] =~ /\A [\$\@\/\\] \z/oxms) {
6724 0         0 $char[$i] = '\\' . $char[$i];
6725             }
6726              
6727             # rewrite character class or escape character
6728             elsif (my $char = character_class($char[$i],$modifier)) {
6729 6         11 $char[$i] = $char;
6730             }
6731              
6732             # /i modifier
6733             elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Ecyrillic::uc($char[$i]) ne Ecyrillic::fc($char[$i]))) {
6734 0 0       0 if (CORE::length(Ecyrillic::fc($char[$i])) == 1) {
6735 0         0 $char[$i] = '[' . Ecyrillic::uc($char[$i]) . Ecyrillic::fc($char[$i]) . ']';
6736             }
6737             else {
6738 0         0 $char[$i] = '(?:' . Ecyrillic::uc($char[$i]) . '|' . Ecyrillic::fc($char[$i]) . ')';
6739             }
6740             }
6741              
6742             # quote character before ? + * {
6743             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
6744 0 0       0 if ($char[$i-1] =~ /\A [\x00-\xFF] \z/oxms) {
6745             }
6746             else {
6747 0         0 $char[$i-1] = '(?:' . $char[$i-1] . ')';
6748             }
6749             }
6750             }
6751              
6752 13         19 $modifier =~ tr/i//d;
6753 13         18 $delimiter = '/';
6754 13         12 $end_delimiter = '/';
6755 13         17 my $prematch = '';
6756 13         111 return join '', $ope, $delimiter, $prematch, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
6757             }
6758              
6759             #
6760             # escape regexp (s'here''b)
6761             #
6762             sub e_s1_qb {
6763 0     0 0 0 my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6764              
6765             # split regexp
6766 0         0 my @char = $string =~ /\G (?>[^\\]|\\\\) /oxmsg;
6767              
6768             # unescape character
6769 0         0 for (my $i=0; $i <= $#char; $i++) {
6770 0 0       0 if (0) {
    0          
6771             }
6772              
6773             # remain \\
6774 0         0 elsif ($char[$i] eq '\\\\') {
6775             }
6776              
6777             # escape $ @ / and \
6778             elsif ($char[$i] =~ /\A [\$\@\/\\] \z/oxms) {
6779 0         0 $char[$i] = '\\' . $char[$i];
6780             }
6781             }
6782              
6783 0         0 $delimiter = '/';
6784 0         0 $end_delimiter = '/';
6785 0         0 my $prematch = '';
6786 0         0 return join '', $ope, $delimiter, $prematch, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
6787             }
6788              
6789             #
6790             # escape regexp (s''here')
6791             #
6792             sub e_s2_q {
6793 16     16 0 26 my($ope,$delimiter,$end_delimiter,$string) = @_;
6794              
6795 16         16 $slash = 'div';
6796              
6797 16         121 my @char = $string =~ / \G (?>[^\\]|\\\\|$q_char) /oxmsg;
6798 16         49 for (my $i=0; $i <= $#char; $i++) {
6799 9 100       33 if (0) {
    100          
6800             }
6801              
6802             # not escape \\
6803 0         0 elsif ($char[$i] =~ /\A \\\\ \z/oxms) {
6804             }
6805              
6806             # escape $ @ / and \
6807             elsif ($char[$i] =~ /\A [\$\@\/\\] \z/oxms) {
6808 5         17 $char[$i] = '\\' . $char[$i];
6809             }
6810             }
6811              
6812 16         48 return join '', $ope, $delimiter, @char, $end_delimiter;
6813             }
6814              
6815             #
6816             # escape regexp (s/here/and here/modifier)
6817             #
6818             sub e_sub {
6819 97     97 0 458 my($variable,$delimiter1,$pattern,$end_delimiter1,$delimiter2,$replacement,$end_delimiter2,$modifier) = @_;
6820 97   100     384 $modifier ||= '';
6821              
6822 97         184 $modifier =~ tr/p//d;
6823 97 50       284 if ($modifier =~ /([adlu])/oxms) {
6824 0         0 my $line = 0;
6825 0         0 for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
6826 0 0       0 if ($filename ne __FILE__) {
6827 0         0 $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
6828 0         0 last;
6829             }
6830             }
6831 0         0 die qq{Unsupported modifier "$1" used at line $line.\n};
6832             }
6833              
6834 97 100       235 if ($variable eq '') {
6835 36         45 $variable = '$_';
6836 36         46 $bind_operator = ' =~ ';
6837             }
6838              
6839 97         124 $slash = 'div';
6840              
6841             # P.128 Start of match (or end of previous match): \G
6842             # P.130 Advanced Use of \G with Perl
6843             # in Chapter 3: Overview of Regular Expression Features and Flavors
6844             # P.312 Iterative Matching: Scalar Context, with /g
6845             # in Chapter 7: Perl
6846             # of ISBN 0-596-00289-0 Mastering Regular Expressions, Second edition
6847              
6848             # P.181 Where You Left Off: The \G Assertion
6849             # in Chapter 5: Pattern Matching
6850             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
6851              
6852             # P.220 Where You Left Off: The \G Assertion
6853             # in Chapter 5: Pattern Matching
6854             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
6855              
6856 97         127 my $e_modifier = $modifier =~ tr/e//d;
6857 97         121 my $r_modifier = $modifier =~ tr/r//d;
6858              
6859 97         112 my $my = '';
6860 97 50       248 if ($variable =~ s/\A \( (?>\s*) ( (?>(?: local \b | my \b | our \b | state \b )?) .+ ) \) \z/$1/oxms) {
6861 0         0 $my = $variable;
6862 0         0 $variable =~ s/ (?: local \b | my \b | our \b | state \b ) (?>\s*) //oxms;
6863 0         0 $variable =~ s/ = .+ \z//oxms;
6864             }
6865              
6866 97         204 (my $variable_basename = $variable) =~ s/ [\[\{].* \z//oxms;
6867 97         145 $variable_basename =~ s/ \s+ \z//oxms;
6868              
6869             # quote replacement string
6870 97         106 my $e_replacement = '';
6871 97 100       196 if ($e_modifier >= 1) {
6872 17         42 $e_replacement = e_qq('', '', '', $replacement);
6873 17         23 $e_modifier--;
6874             }
6875             else {
6876 80 100       165 if ($delimiter2 eq "'") {
6877 16         31 $e_replacement = e_s2_q('qq', '/', '/', $replacement);
6878             }
6879             else {
6880 64         153 $e_replacement = e_qq ('qq', $delimiter2, $end_delimiter2, $replacement);
6881             }
6882             }
6883              
6884 97         138 my $sub = '';
6885              
6886             # with /r
6887 97 100       195 if ($r_modifier) {
6888 8 100       20 if (0) {
6889             }
6890              
6891             # s///gr without multibyte anchoring
6892 0         0 elsif ($modifier =~ /g/oxms) {
6893 4 50       17 $sub = sprintf(
6894             # 1 2 3 4 5
6895             q,
6896              
6897             $variable, # 1
6898             ($delimiter1 eq "'") ? # 2
6899             e_s1_q('m', $delimiter1, $end_delimiter1, $pattern, $modifier) : # :
6900             e_s1 ('m', $delimiter1, $end_delimiter1, $pattern, $modifier), # :
6901             $s_matched, # 3
6902             $e_replacement, # 4
6903             '$Cyrillic::re_r=CORE::eval $Cyrillic::re_r; ' x $e_modifier, # 5
6904             );
6905             }
6906              
6907             # s///r
6908             else {
6909              
6910 4         3 my $prematch = q{$`};
6911              
6912 4 50       17 $sub = sprintf(
6913             # 1 2 3 4 5 6 7
6914             q<(%s =~ %s) ? CORE::eval{%s local $^W=0; local $Cyrillic::re_r=%s; %s"%s$Cyrillic::re_r$'" } : %s>,
6915              
6916             $variable, # 1
6917             ($delimiter1 eq "'") ? # 2
6918             e_s1_q('m', $delimiter1, $end_delimiter1, $pattern, $modifier) : # :
6919             e_s1 ('m', $delimiter1, $end_delimiter1, $pattern, $modifier), # :
6920             $s_matched, # 3
6921             $e_replacement, # 4
6922             '$Cyrillic::re_r=CORE::eval $Cyrillic::re_r; ' x $e_modifier, # 5
6923             $prematch, # 6
6924             $variable, # 7
6925             );
6926             }
6927              
6928             # $var !~ s///r doesn't make sense
6929 8 50       22 if ($bind_operator =~ / !~ /oxms) {
6930 0         0 $sub = q{die("$0: Using !~ with s///r doesn't make sense"), } . $sub;
6931             }
6932             }
6933              
6934             # without /r
6935             else {
6936 89 100       205 if (0) {
6937             }
6938              
6939             # s///g without multibyte anchoring
6940 0         0 elsif ($modifier =~ /g/oxms) {
6941 22 100       88 $sub = sprintf(
    100          
6942             # 1 2 3 4 5 6 7 8
6943             q,
6944              
6945             $variable, # 1
6946             ($delimiter1 eq "'") ? # 2
6947             e_s1_q('m', $delimiter1, $end_delimiter1, $pattern, $modifier) : # :
6948             e_s1 ('m', $delimiter1, $end_delimiter1, $pattern, $modifier), # :
6949             $s_matched, # 3
6950             $e_replacement, # 4
6951             '$Cyrillic::re_r=CORE::eval $Cyrillic::re_r; ' x $e_modifier, # 5
6952             $variable, # 6
6953             $variable, # 7
6954             ($bind_operator =~ / !~ /oxms) ? '!' : '', # 8
6955             );
6956             }
6957              
6958             # s///
6959             else {
6960              
6961 67         102 my $prematch = q{$`};
6962              
6963 67 100       410 $sub = sprintf(
    100          
6964              
6965             ($bind_operator =~ / =~ /oxms) ?
6966              
6967             # 1 2 3 4 5 6 7 8
6968             q<(%s%s%s) ? CORE::eval{%s local $^W=0; local $Cyrillic::re_r=%s; %s%s="%s$Cyrillic::re_r$'"; 1 } : undef> :
6969              
6970             # 1 2 3 4 5 6 7 8
6971             q<(%s%s%s) ? 1 : CORE::eval{%s local $^W=0; local $Cyrillic::re_r=%s; %s%s="%s$Cyrillic::re_r$'"; undef }>,
6972              
6973             $variable, # 1
6974             $bind_operator, # 2
6975             ($delimiter1 eq "'") ? # 3
6976             e_s1_q('m', $delimiter1, $end_delimiter1, $pattern, $modifier) : # :
6977             e_s1 ('m', $delimiter1, $end_delimiter1, $pattern, $modifier), # :
6978             $s_matched, # 4
6979             $e_replacement, # 5
6980             '$Cyrillic::re_r=CORE::eval $Cyrillic::re_r; ' x $e_modifier, # 6
6981             $variable, # 7
6982             $prematch, # 8
6983             );
6984             }
6985             }
6986              
6987             # (my $foo = $bar) =~ s/// --> (my $foo = $bar, CORE::eval { ... })[1]
6988 97 50       262 if ($my ne '') {
6989 0         0 $sub = "($my, $sub)[1]";
6990             }
6991              
6992             # clear s/// variable
6993 97         121 $sub_variable = '';
6994 97         114 $bind_operator = '';
6995              
6996 97         718 return $sub;
6997             }
6998              
6999             #
7000             # escape regexp of split qr//
7001             #
7002             sub e_split {
7003 74     74 0 249 my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
7004 74   100     350 $modifier ||= '';
7005              
7006 74         112 $modifier =~ tr/p//d;
7007 74 50       361 if ($modifier =~ /([adlu])/oxms) {
7008 0         0 my $line = 0;
7009 0         0 for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
7010 0 0       0 if ($filename ne __FILE__) {
7011 0         0 $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
7012 0         0 last;
7013             }
7014             }
7015 0         0 die qq{Unsupported modifier "$1" used at line $line.\n};
7016             }
7017              
7018 74         103 $slash = 'div';
7019              
7020             # /b /B modifier
7021 74 50       160 if ($modifier =~ tr/bB//d) {
7022 0         0 return join '', 'split', $ope, $delimiter, $string, $end_delimiter, $modifier;
7023             }
7024              
7025 74 50       165 my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
7026 74         348 my $metachar = qr/[\@\\|[\]{^]/oxms;
7027              
7028             # split regexp
7029 74         9453 my @char = $string =~ /\G((?>
7030             [^\\\$\@\[\(] |
7031             \\x (?>[0-9A-Fa-f]{1,2}) |
7032             \\ (?>[0-7]{2,3}) |
7033             \\c [\x40-\x5F] |
7034             \\x\{ (?>[0-9A-Fa-f]+) \} |
7035             \\o\{ (?>[0-7]+) \} |
7036             \\[bBNpP]\{ (?>[^0-9\}][^\}]*) \} |
7037             \\ $q_char |
7038             \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} |
7039             \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} |
7040             \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} |
7041             [\$\@] $qq_variable |
7042             \$ (?>\s* [0-9]+) |
7043             \$ (?>\s*) \{ (?>\s* [0-9]+ \s*) \} |
7044             \$ \$ (?![\w\{]) |
7045             \$ (?>\s*) \$ (?>\s*) $qq_variable |
7046             \[\^ |
7047             \[\: (?>[a-z]+) :\] |
7048             \[\:\^ (?>[a-z]+) :\] |
7049             \(\? |
7050             $q_char
7051             ))/oxmsg;
7052              
7053 74         467 my $left_e = 0;
7054 74         87 my $right_e = 0;
7055 74         316 for (my $i=0; $i <= $#char; $i++) {
7056              
7057             # "\L\u" --> "\u\L"
7058 249 50 33     1470 if (($char[$i] eq '\L') and ($char[$i+1] eq '\u')) {
    50 33        
    100          
    100          
    50          
    50          
7059 0         0 @char[$i,$i+1] = @char[$i+1,$i];
7060             }
7061              
7062             # "\U\l" --> "\l\U"
7063             elsif (($char[$i] eq '\U') and ($char[$i+1] eq '\l')) {
7064 0         0 @char[$i,$i+1] = @char[$i+1,$i];
7065             }
7066              
7067             # octal escape sequence
7068             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
7069 1         6 $char[$i] = Ecyrillic::octchr($1);
7070             }
7071              
7072             # hexadecimal escape sequence
7073             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
7074 1         4 $char[$i] = Ecyrillic::hexchr($1);
7075             }
7076              
7077             # \b{...} --> b\{...}
7078             # \B{...} --> B\{...}
7079             # \N{CHARNAME} --> N\{CHARNAME}
7080             # \p{PROPERTY} --> p\{PROPERTY}
7081             # \P{PROPERTY} --> P\{PROPERTY}
7082             elsif ($char[$i] =~ /\A \\ ([bBNpP]) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
7083 0         0 $char[$i] = $1 . '\\' . $2;
7084             }
7085              
7086             # \p, \P, \X --> p, P, X
7087             elsif ($char[$i] =~ /\A \\ ( [pPX] ) \z/oxms) {
7088 0         0 $char[$i] = $1;
7089             }
7090              
7091 249 50 100     783 if (0) {
    100 33        
    50 33        
    100 100        
    100          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    100          
    100          
    100          
    50          
    50          
    100          
    100          
7092             }
7093              
7094             # join separated multiple-octet
7095 0         0 elsif ($char[$i] =~ /\A (?: \\ [0-7]{2,3} | \\x [0-9A-Fa-f]{1,2}) \z/oxms) {
7096 0 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        
7097 0         0 $char[$i] .= join '', splice @char, $i+1, 3;
7098             }
7099             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)) {
7100 0         0 $char[$i] .= join '', splice @char, $i+1, 2;
7101             }
7102             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)) {
7103 0         0 $char[$i] .= join '', splice @char, $i+1, 1;
7104             }
7105             }
7106              
7107             # open character class [...]
7108             elsif ($char[$i] eq '[') {
7109 3         5 my $left = $i;
7110 3 50       9 if ($char[$i+1] eq ']') {
7111 0         0 $i++;
7112             }
7113 3         3 while (1) {
7114 7 50       16 if (++$i > $#char) {
7115 0         0 die __FILE__, ": Unmatched [] in regexp\n";
7116             }
7117 7 100       13 if ($char[$i] eq ']') {
7118 3         3 my $right = $i;
7119              
7120             # [...]
7121 3 50       17 if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
7122 0         0 splice @char, $left, $right-$left+1, sprintf(q{@{[Ecyrillic::charlist_qr(%s,'%s')]}}, join(',', map {qq_stuff($delimiter,$end_delimiter,$_)} @char[$left+1..$right-1]), $modifier);
  0         0  
7123             }
7124             else {
7125 3         16 splice @char, $left, $right-$left+1, Ecyrillic::charlist_qr(@char[$left+1..$right-1], $modifier);
7126             }
7127              
7128 3         3 $i = $left;
7129 3         8 last;
7130             }
7131             }
7132             }
7133              
7134             # open character class [^...]
7135             elsif ($char[$i] eq '[^') {
7136 0         0 my $left = $i;
7137 0 0       0 if ($char[$i+1] eq ']') {
7138 0         0 $i++;
7139             }
7140 0         0 while (1) {
7141 0 0       0 if (++$i > $#char) {
7142 0         0 die __FILE__, ": Unmatched [] in regexp\n";
7143             }
7144 0 0       0 if ($char[$i] eq ']') {
7145 0         0 my $right = $i;
7146              
7147             # [^...]
7148 0 0       0 if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
7149 0         0 splice @char, $left, $right-$left+1, sprintf(q{@{[Ecyrillic::charlist_not_qr(%s,'%s')]}}, join(',', map {qq_stuff($delimiter,$end_delimiter,$_)} @char[$left+1..$right-1]), $modifier);
  0         0  
7150             }
7151             else {
7152 0         0 splice @char, $left, $right-$left+1, Ecyrillic::charlist_not_qr(@char[$left+1..$right-1], $modifier);
7153             }
7154              
7155 0         0 $i = $left;
7156 0         0 last;
7157             }
7158             }
7159             }
7160              
7161             # rewrite character class or escape character
7162             elsif (my $char = character_class($char[$i],$modifier)) {
7163 1         3 $char[$i] = $char;
7164             }
7165              
7166             # P.794 29.2.161. split
7167             # in Chapter 29: Functions
7168             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
7169              
7170             # P.951 split
7171             # in Chapter 27: Functions
7172             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
7173              
7174             # said "The //m modifier is assumed when you split on the pattern /^/",
7175             # but perl5.008 is not so. Therefore, this software adds //m.
7176             # (and so on)
7177              
7178             # split(m/^/) --> split(m/^/m)
7179             elsif (($char[$i] eq '^') and ($modifier !~ /m/oxms)) {
7180 7         50 $modifier .= 'm';
7181             }
7182              
7183             # /i modifier
7184             elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Ecyrillic::uc($char[$i]) ne Ecyrillic::fc($char[$i]))) {
7185 0 0       0 if (CORE::length(Ecyrillic::fc($char[$i])) == 1) {
7186 0         0 $char[$i] = '[' . Ecyrillic::uc($char[$i]) . Ecyrillic::fc($char[$i]) . ']';
7187             }
7188             else {
7189 0         0 $char[$i] = '(?:' . Ecyrillic::uc($char[$i]) . '|' . Ecyrillic::fc($char[$i]) . ')';
7190             }
7191             }
7192              
7193             # \u \l \U \L \F \Q \E
7194             elsif ($char[$i] =~ /\A ([<>]) \z/oxms) {
7195 0 0       0 if ($right_e < $left_e) {
7196 0         0 $char[$i] = '\\' . $char[$i];
7197             }
7198             }
7199             elsif ($char[$i] eq '\u') {
7200 0         0 $char[$i] = '@{[Ecyrillic::ucfirst qq<';
7201 0         0 $left_e++;
7202             }
7203             elsif ($char[$i] eq '\l') {
7204 0         0 $char[$i] = '@{[Ecyrillic::lcfirst qq<';
7205 0         0 $left_e++;
7206             }
7207             elsif ($char[$i] eq '\U') {
7208 0         0 $char[$i] = '@{[Ecyrillic::uc qq<';
7209 0         0 $left_e++;
7210             }
7211             elsif ($char[$i] eq '\L') {
7212 0         0 $char[$i] = '@{[Ecyrillic::lc qq<';
7213 0         0 $left_e++;
7214             }
7215             elsif ($char[$i] eq '\F') {
7216 0         0 $char[$i] = '@{[Ecyrillic::fc qq<';
7217 0         0 $left_e++;
7218             }
7219             elsif ($char[$i] eq '\Q') {
7220 0         0 $char[$i] = '@{[CORE::quotemeta qq<';
7221 0         0 $left_e++;
7222             }
7223             elsif ($char[$i] eq '\E') {
7224 0 0       0 if ($right_e < $left_e) {
7225 0         0 $char[$i] = '>]}';
7226 0         0 $right_e++;
7227             }
7228             else {
7229 0         0 $char[$i] = '';
7230             }
7231             }
7232             elsif ($char[$i] eq '\Q') {
7233 0         0 while (1) {
7234 0 0       0 if (++$i > $#char) {
7235 0         0 last;
7236             }
7237 0 0       0 if ($char[$i] eq '\E') {
7238 0         0 last;
7239             }
7240             }
7241             }
7242             elsif ($char[$i] eq '\E') {
7243             }
7244              
7245             # $0 --> $0
7246             elsif ($char[$i] =~ /\A \$ 0 \z/oxms) {
7247 0 0       0 if ($ignorecase) {
7248 0         0 $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
7249             }
7250             }
7251             elsif ($char[$i] =~ /\A \$ \{ (?>\s*) 0 (?>\s*) \} \z/oxms) {
7252 0 0       0 if ($ignorecase) {
7253 0         0 $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
7254             }
7255             }
7256              
7257             # $$ --> $$
7258             elsif ($char[$i] =~ /\A \$\$ \z/oxms) {
7259             }
7260              
7261             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
7262             # $1, $2, $3 --> $1, $2, $3 otherwise
7263             elsif ($char[$i] =~ /\A \$ ((?>[1-9][0-9]*)) \z/oxms) {
7264 0         0 $char[$i] = e_capture($1);
7265 0 0       0 if ($ignorecase) {
7266 0         0 $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
7267             }
7268             }
7269             elsif ($char[$i] =~ /\A \$ \{ (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} \z/oxms) {
7270 0         0 $char[$i] = e_capture($1);
7271 0 0       0 if ($ignorecase) {
7272 0         0 $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
7273             }
7274             }
7275              
7276             # $$foo[ ... ] --> $ $foo->[ ... ]
7277             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \[ (?:$qq_bracket)*? \] ) \z/oxms) {
7278 0         0 $char[$i] = e_capture($1.'->'.$2);
7279 0 0       0 if ($ignorecase) {
7280 0         0 $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
7281             }
7282             }
7283              
7284             # $$foo{ ... } --> $ $foo->{ ... }
7285             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \{ (?:$qq_brace)*? \} ) \z/oxms) {
7286 0         0 $char[$i] = e_capture($1.'->'.$2);
7287 0 0       0 if ($ignorecase) {
7288 0         0 $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
7289             }
7290             }
7291              
7292             # $$foo
7293             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) \z/oxms) {
7294 0         0 $char[$i] = e_capture($1);
7295 0 0       0 if ($ignorecase) {
7296 0         0 $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
7297             }
7298             }
7299              
7300             # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Ecyrillic::PREMATCH()
7301             elsif ($char[$i] =~ /\A ( \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} ) \z/oxmsgc) {
7302 12 50       23 if ($ignorecase) {
7303 0         0 $char[$i] = '@{[Ecyrillic::ignorecase(Ecyrillic::PREMATCH())]}';
7304             }
7305             else {
7306 12         71 $char[$i] = '@{[Ecyrillic::PREMATCH()]}';
7307             }
7308             }
7309              
7310             # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Ecyrillic::MATCH()
7311             elsif ($char[$i] =~ /\A ( \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} ) \z/oxmsgc) {
7312 12 50       19 if ($ignorecase) {
7313 0         0 $char[$i] = '@{[Ecyrillic::ignorecase(Ecyrillic::MATCH())]}';
7314             }
7315             else {
7316 12         74 $char[$i] = '@{[Ecyrillic::MATCH()]}';
7317             }
7318             }
7319              
7320             # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Ecyrillic::POSTMATCH()
7321             elsif ($char[$i] =~ /\A ( \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} ) \z/oxmsgc) {
7322 9 50       16 if ($ignorecase) {
7323 0         0 $char[$i] = '@{[Ecyrillic::ignorecase(Ecyrillic::POSTMATCH())]}';
7324             }
7325             else {
7326 9         57 $char[$i] = '@{[Ecyrillic::POSTMATCH()]}';
7327             }
7328             }
7329              
7330             # ${ foo }
7331             elsif ($char[$i] =~ /\A \$ (?>\s*) \{ ((?> \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* )) \} \z/oxms) {
7332 0 0       0 if ($ignorecase) {
7333 0         0 $char[$i] = '@{[Ecyrillic::ignorecase(' . $1 . ')]}';
7334             }
7335             }
7336              
7337             # ${ ... }
7338             elsif ($char[$i] =~ /\A \$ (?>\s*) \{ ( .+ ) \} \z/oxms) {
7339 0         0 $char[$i] = e_capture($1);
7340 0 0       0 if ($ignorecase) {
7341 0         0 $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
7342             }
7343             }
7344              
7345             # $scalar or @array
7346             elsif ($char[$i] =~ /\A [\$\@].+ /oxms) {
7347 3         11 $char[$i] = e_string($char[$i]);
7348 3 50       31 if ($ignorecase) {
7349 0         0 $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
7350             }
7351             }
7352              
7353             # quote character before ? + * {
7354             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
7355 1 50       6 if ($char[$i-1] =~ /\A (?:[\x00-\xFF]|\\[0-7]{2,3}|\\x[0-9-A-Fa-f]{1,2}) \z/oxms) {
7356             }
7357             else {
7358 0         0 $char[$i-1] = '(?:' . $char[$i-1] . ')';
7359             }
7360             }
7361             }
7362              
7363             # make regexp string
7364 74         117 $modifier =~ tr/i//d;
7365 74 50       175 if ($left_e > $right_e) {
7366 0         0 return join '', 'Ecyrillic::split', $ope, $delimiter, @char, '>]}' x ($left_e - $right_e), $end_delimiter, $modifier;
7367             }
7368 74         717 return join '', 'Ecyrillic::split', $ope, $delimiter, @char, $end_delimiter, $modifier;
7369             }
7370              
7371             #
7372             # escape regexp of split qr''
7373             #
7374             sub e_split_q {
7375 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
7376 0   0       $modifier ||= '';
7377              
7378 0           $modifier =~ tr/p//d;
7379 0 0         if ($modifier =~ /([adlu])/oxms) {
7380 0           my $line = 0;
7381 0           for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
7382 0 0         if ($filename ne __FILE__) {
7383 0           $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
7384 0           last;
7385             }
7386             }
7387 0           die qq{Unsupported modifier "$1" used at line $line.\n};
7388             }
7389              
7390 0           $slash = 'div';
7391              
7392             # /b /B modifier
7393 0 0         if ($modifier =~ tr/bB//d) {
7394 0           return join '', 'split', $ope, $delimiter, $string, $end_delimiter, $modifier;
7395             }
7396              
7397 0 0         my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
7398              
7399             # split regexp
7400 0           my @char = $string =~ /\G((?>
7401             [^\\\[] |
7402             [\x00-\xFF] |
7403             \[\^ |
7404             \[\: (?>[a-z]+) \:\] |
7405             \[\:\^ (?>[a-z]+) \:\] |
7406             \\ (?:$q_char) |
7407             (?:$q_char)
7408             ))/oxmsg;
7409              
7410             # unescape character
7411 0           for (my $i=0; $i <= $#char; $i++) {
7412 0 0 0       if (0) {
    0 0        
    0 0        
    0 0        
    0          
    0          
7413             }
7414              
7415             # open character class [...]
7416 0           elsif ($char[$i] eq '[') {
7417 0           my $left = $i;
7418 0 0         if ($char[$i+1] eq ']') {
7419 0           $i++;
7420             }
7421 0           while (1) {
7422 0 0         if (++$i > $#char) {
7423 0           die __FILE__, ": Unmatched [] in regexp\n";
7424             }
7425 0 0         if ($char[$i] eq ']') {
7426 0           my $right = $i;
7427              
7428             # [...]
7429 0           splice @char, $left, $right-$left+1, Ecyrillic::charlist_qr(@char[$left+1..$right-1], $modifier);
7430              
7431 0           $i = $left;
7432 0           last;
7433             }
7434             }
7435             }
7436              
7437             # open character class [^...]
7438             elsif ($char[$i] eq '[^') {
7439 0           my $left = $i;
7440 0 0         if ($char[$i+1] eq ']') {
7441 0           $i++;
7442             }
7443 0           while (1) {
7444 0 0         if (++$i > $#char) {
7445 0           die __FILE__, ": Unmatched [] in regexp\n";
7446             }
7447 0 0         if ($char[$i] eq ']') {
7448 0           my $right = $i;
7449              
7450             # [^...]
7451 0           splice @char, $left, $right-$left+1, Ecyrillic::charlist_not_qr(@char[$left+1..$right-1], $modifier);
7452              
7453 0           $i = $left;
7454 0           last;
7455             }
7456             }
7457             }
7458              
7459             # rewrite character class or escape character
7460             elsif (my $char = character_class($char[$i],$modifier)) {
7461 0           $char[$i] = $char;
7462             }
7463              
7464             # split(m/^/) --> split(m/^/m)
7465             elsif (($char[$i] eq '^') and ($modifier !~ /m/oxms)) {
7466 0           $modifier .= 'm';
7467             }
7468              
7469             # /i modifier
7470             elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Ecyrillic::uc($char[$i]) ne Ecyrillic::fc($char[$i]))) {
7471 0 0         if (CORE::length(Ecyrillic::fc($char[$i])) == 1) {
7472 0           $char[$i] = '[' . Ecyrillic::uc($char[$i]) . Ecyrillic::fc($char[$i]) . ']';
7473             }
7474             else {
7475 0           $char[$i] = '(?:' . Ecyrillic::uc($char[$i]) . '|' . Ecyrillic::fc($char[$i]) . ')';
7476             }
7477             }
7478              
7479             # quote character before ? + * {
7480             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
7481 0 0         if ($char[$i-1] =~ /\A [\x00-\xFF] \z/oxms) {
7482             }
7483             else {
7484 0           $char[$i-1] = '(?:' . $char[$i-1] . ')';
7485             }
7486             }
7487             }
7488              
7489 0           $modifier =~ tr/i//d;
7490 0           return join '', 'Ecyrillic::split', $ope, $delimiter, @char, $end_delimiter, $modifier;
7491             }
7492              
7493             #
7494             # instead of Carp::carp
7495             #
7496             sub carp {
7497 0     0 0   my($package,$filename,$line) = caller(1);
7498 0           print STDERR "@_ at $filename line $line.\n";
7499             }
7500              
7501             #
7502             # instead of Carp::croak
7503             #
7504             sub croak {
7505 0     0 0   my($package,$filename,$line) = caller(1);
7506 0           print STDERR "@_ at $filename line $line.\n";
7507 0           die "\n";
7508             }
7509              
7510             #
7511             # instead of Carp::cluck
7512             #
7513             sub cluck {
7514 0     0 0   my $i = 0;
7515 0           my @cluck = ();
7516 0           while (my($package,$filename,$line,$subroutine) = caller($i)) {
7517 0           push @cluck, "[$i] $filename($line) $package::$subroutine\n";
7518 0           $i++;
7519             }
7520 0           print STDERR CORE::reverse @cluck;
7521 0           print STDERR "\n";
7522 0           carp @_;
7523             }
7524              
7525             #
7526             # instead of Carp::confess
7527             #
7528             sub confess {
7529 0     0 0   my $i = 0;
7530 0           my @confess = ();
7531 0           while (my($package,$filename,$line,$subroutine) = caller($i)) {
7532 0           push @confess, "[$i] $filename($line) $package::$subroutine\n";
7533 0           $i++;
7534             }
7535 0           print STDERR CORE::reverse @confess;
7536 0           print STDERR "\n";
7537 0           croak @_;
7538             }
7539              
7540             1;
7541              
7542             __END__