File Coverage

blib/lib/Ecyrillic.pm
Criterion Covered Total %
statement 905 3196 28.3
branch 968 2742 35.3
condition 98 355 27.6
subroutine 52 110 47.2
pod 7 74 9.4
total 2030 6477 31.3


line stmt bran cond sub pod time code
1             package Ecyrillic;
2 204     204   1195 use strict;
  204         372  
  204         6445  
3             ######################################################################
4             #
5             # Ecyrillic - Run-time routines for Cyrillic.pm
6             #
7             # http://search.cpan.org/dist/Char-Cyrillic/
8             #
9             # Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2018, 2019 INABA Hitoshi
10             ######################################################################
11              
12 204     204   2805 use 5.00503; # Galapagos Consensus 1998 for primetools
  204         573  
13             # use 5.008001; # Lancaster Consensus 2013 for toolchains
14              
15             # 12.3. Delaying use Until Runtime
16             # in Chapter 12. Packages, Libraries, and Modules
17             # of ISBN 0-596-00313-7 Perl Cookbook, 2nd Edition.
18             # (and so on)
19              
20             # Version numbers should be boring
21             # http://www.dagolden.com/index.php/369/version-numbers-should-be-boring/
22             # For the impatient, the disinterested or those who just want to follow
23             # a recipe, my advice for all modules is this:
24             # our $VERSION = "0.001"; # or "0.001_001" for a dev release
25             # $VERSION = eval $VERSION; # No!! because '1.10' makes '1.1'
26              
27 204     204   984 use vars qw($VERSION);
  204         337  
  204         43396  
28             $VERSION = '1.15';
29             $VERSION = $VERSION;
30              
31             BEGIN {
32 204 50   204   1501 if ($^X =~ / jperl /oxmsi) {
33 0         0 die __FILE__, ": needs perl(not jperl) 5.00503 or later. (\$^X==$^X)\n";
34             }
35 204         357 if (CORE::ord('A') == 193) {
36             die __FILE__, ": is not US-ASCII script (may be EBCDIC or EBCDIK script).\n";
37             }
38 204         30811 if (CORE::ord('A') != 0x41) {
39             die __FILE__, ": is not US-ASCII script (must be US-ASCII script).\n";
40             }
41             }
42              
43             BEGIN {
44              
45             # instead of utf8.pm
46 204     204   15503 CORE::eval q{
  204     204   1316  
  204     74   389  
  204         30913  
  0         0  
  0         0  
  0         0  
  0         0  
47             no warnings qw(redefine);
48             *utf8::upgrade = sub { CORE::length $_[0] };
49             *utf8::downgrade = sub { 1 };
50             *utf8::encode = sub { };
51             *utf8::decode = sub { 1 };
52             *utf8::is_utf8 = sub { };
53             *utf8::valid = sub { 1 };
54             };
55 204 50       82814 if ($@) {
56 0         0 *utf8::upgrade = sub { CORE::length $_[0] };
  0         0  
57 0         0 *utf8::downgrade = sub { 1 };
  0         0  
58 0         0 *utf8::encode = sub { };
59 0         0 *utf8::decode = sub { 1 };
  0         0  
60 0         0 *utf8::is_utf8 = sub { };
61 0         0 *utf8::valid = sub { 1 };
  0         0  
62             }
63             }
64              
65             # instead of Symbol.pm
66 0         0 BEGIN {
67             sub gensym () {
68 0 0   0 0 0 if ($] < 5.006) {
69 0         0 return \do { local *_ };
  0         0  
70             }
71             else {
72 0         0 return undef;
73             }
74             }
75              
76             sub qualify ($$) {
77 0     0 0 0 my($name) = @_;
78              
79 0 0       0 if (ref $name) {
    0          
    0          
    0          
    0          
    0          
    0          
80 0         0 return $name;
81             }
82             elsif (Ecyrillic::index($name,'::') >= 0) {
83 0         0 return $name;
84             }
85             elsif (Ecyrillic::index($name,"'") >= 0) {
86 0         0 return $name;
87             }
88              
89             # special character, "^xyz"
90             elsif ($name =~ /\A \^ [ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_]+ \z/x) {
91              
92             # RGS 2001-11-05 : translate leading ^X to control-char
93 0         0 $name =~ s{\A \^ ([ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_]) }{'qq(\c'.$1.')'}xee;
  0         0  
94 0         0 return 'main::' . $name;
95             }
96              
97             # Global names
98             elsif ($name =~ /\A (?: ARGV | ARGVOUT | ENV | INC | SIG | STDERR | STDIN | STDOUT ) \z/x) {
99 0         0 return 'main::' . $name;
100             }
101              
102             # or other
103             elsif ($name =~ /\A [^ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz] \z/x) {
104 0         0 return 'main::' . $name;
105             }
106              
107             elsif (defined $_[1]) {
108 0         0 return $_[1] . '::' . $name;
109             }
110             else {
111 0         0 return (caller)[0] . '::' . $name;
112             }
113             }
114              
115             sub qualify_to_ref ($;$) {
116 0 0   0 0 0 if (defined $_[1]) {
117 204     204   1489 no strict qw(refs);
  204         685  
  204         19770  
118 0         0 return \*{ qualify $_[0], $_[1] };
  0         0  
119             }
120             else {
121 204     204   1161 no strict qw(refs);
  204     0   377  
  204         41798  
122 0         0 return \*{ qualify $_[0], (caller)[0] };
  0         0  
123             }
124             }
125             }
126              
127             # P.714 29.2.39. flock
128             # in Chapter 29: Functions
129             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
130              
131             # P.863 flock
132             # in Chapter 27: Functions
133             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
134              
135             sub LOCK_SH() {1}
136             sub LOCK_EX() {2}
137             sub LOCK_UN() {8}
138             sub LOCK_NB() {4}
139              
140             # instead of Carp.pm
141             sub carp;
142             sub croak;
143             sub cluck;
144             sub confess;
145              
146             # 6.18. Matching Multiple-Byte Characters
147             # in Chapter 6. Pattern Matching
148             # of ISBN 978-1-56592-243-3 Perl Perl Cookbook.
149             # (and so on)
150              
151             # regexp of character
152             my $your_char = q{[\x00-\xFF]};
153 204     204   1517 use vars qw($qq_char); $qq_char = qr/\\c[\x40-\x5F]|\\?(?:$your_char)/oxms;
  204         349  
  204         15334  
154 204     204   1228 use vars qw($q_char); $q_char = qr/$your_char/oxms;
  204         407  
  204         472099  
155              
156             #
157             # Cyrillic character range per length
158             #
159             my %range_tr = ();
160              
161             #
162             # Cyrillic case conversion
163             #
164             my %lc = ();
165             @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)} =
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 %uc = ();
168             @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)} =
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             my %fc = ();
171             @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)} =
172             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);
173              
174             if (0) {
175             }
176              
177             elsif (__PACKAGE__ =~ / \b Ecyrillic \z/oxms) {
178             %range_tr = (
179             1 => [ [0x00..0xFF],
180             ],
181             );
182              
183             %lc = (%lc,
184             "\xA1" => "\xF1", # CYRILLIC LETTER IO
185             "\xA2" => "\xF2", # CYRILLIC LETTER DJE
186             "\xA3" => "\xF3", # CYRILLIC LETTER GJE
187             "\xA4" => "\xF4", # CYRILLIC LETTER UKRAINIAN IE
188             "\xA5" => "\xF5", # CYRILLIC LETTER DZE
189             "\xA6" => "\xF6", # CYRILLIC LETTER BYELORUSSIAN-UKRAINIAN I
190             "\xA7" => "\xF7", # CYRILLIC LETTER YI
191             "\xA8" => "\xF8", # CYRILLIC LETTER JE
192             "\xA9" => "\xF9", # CYRILLIC LETTER LJE
193             "\xAA" => "\xFA", # CYRILLIC LETTER NJE
194             "\xAB" => "\xFB", # CYRILLIC LETTER TSHE
195             "\xAC" => "\xFC", # CYRILLIC LETTER KJE
196             "\xAE" => "\xFE", # CYRILLIC LETTER SHORT U
197             "\xAF" => "\xFF", # CYRILLIC LETTER DZHE
198             "\xB0" => "\xD0", # CYRILLIC LETTER A
199             "\xB1" => "\xD1", # CYRILLIC LETTER BE
200             "\xB2" => "\xD2", # CYRILLIC LETTER VE
201             "\xB3" => "\xD3", # CYRILLIC LETTER GHE
202             "\xB4" => "\xD4", # CYRILLIC LETTER DE
203             "\xB5" => "\xD5", # CYRILLIC LETTER IE
204             "\xB6" => "\xD6", # CYRILLIC LETTER ZHE
205             "\xB7" => "\xD7", # CYRILLIC LETTER ZE
206             "\xB8" => "\xD8", # CYRILLIC LETTER I
207             "\xB9" => "\xD9", # CYRILLIC LETTER SHORT I
208             "\xBA" => "\xDA", # CYRILLIC LETTER KA
209             "\xBB" => "\xDB", # CYRILLIC LETTER EL
210             "\xBC" => "\xDC", # CYRILLIC LETTER EM
211             "\xBD" => "\xDD", # CYRILLIC LETTER EN
212             "\xBE" => "\xDE", # CYRILLIC LETTER O
213             "\xBF" => "\xDF", # CYRILLIC LETTER PE
214             "\xC0" => "\xE0", # CYRILLIC LETTER ER
215             "\xC1" => "\xE1", # CYRILLIC LETTER ES
216             "\xC2" => "\xE2", # CYRILLIC LETTER TE
217             "\xC3" => "\xE3", # CYRILLIC LETTER U
218             "\xC4" => "\xE4", # CYRILLIC LETTER EF
219             "\xC5" => "\xE5", # CYRILLIC LETTER HA
220             "\xC6" => "\xE6", # CYRILLIC LETTER TSE
221             "\xC7" => "\xE7", # CYRILLIC LETTER CHE
222             "\xC8" => "\xE8", # CYRILLIC LETTER SHA
223             "\xC9" => "\xE9", # CYRILLIC LETTER SHCHA
224             "\xCA" => "\xEA", # CYRILLIC LETTER HARD SIGN
225             "\xCB" => "\xEB", # CYRILLIC LETTER YERU
226             "\xCC" => "\xEC", # CYRILLIC LETTER SOFT SIGN
227             "\xCD" => "\xED", # CYRILLIC LETTER E
228             "\xCE" => "\xEE", # CYRILLIC LETTER YU
229             "\xCF" => "\xEF", # CYRILLIC LETTER YA
230             );
231              
232             %uc = (%uc,
233             "\xD0" => "\xB0", # CYRILLIC LETTER A
234             "\xD1" => "\xB1", # CYRILLIC LETTER BE
235             "\xD2" => "\xB2", # CYRILLIC LETTER VE
236             "\xD3" => "\xB3", # CYRILLIC LETTER GHE
237             "\xD4" => "\xB4", # CYRILLIC LETTER DE
238             "\xD5" => "\xB5", # CYRILLIC LETTER IE
239             "\xD6" => "\xB6", # CYRILLIC LETTER ZHE
240             "\xD7" => "\xB7", # CYRILLIC LETTER ZE
241             "\xD8" => "\xB8", # CYRILLIC LETTER I
242             "\xD9" => "\xB9", # CYRILLIC LETTER SHORT I
243             "\xDA" => "\xBA", # CYRILLIC LETTER KA
244             "\xDB" => "\xBB", # CYRILLIC LETTER EL
245             "\xDC" => "\xBC", # CYRILLIC LETTER EM
246             "\xDD" => "\xBD", # CYRILLIC LETTER EN
247             "\xDE" => "\xBE", # CYRILLIC LETTER O
248             "\xDF" => "\xBF", # CYRILLIC LETTER PE
249             "\xE0" => "\xC0", # CYRILLIC LETTER ER
250             "\xE1" => "\xC1", # CYRILLIC LETTER ES
251             "\xE2" => "\xC2", # CYRILLIC LETTER TE
252             "\xE3" => "\xC3", # CYRILLIC LETTER U
253             "\xE4" => "\xC4", # CYRILLIC LETTER EF
254             "\xE5" => "\xC5", # CYRILLIC LETTER HA
255             "\xE6" => "\xC6", # CYRILLIC LETTER TSE
256             "\xE7" => "\xC7", # CYRILLIC LETTER CHE
257             "\xE8" => "\xC8", # CYRILLIC LETTER SHA
258             "\xE9" => "\xC9", # CYRILLIC LETTER SHCHA
259             "\xEA" => "\xCA", # CYRILLIC LETTER HARD SIGN
260             "\xEB" => "\xCB", # CYRILLIC LETTER YERU
261             "\xEC" => "\xCC", # CYRILLIC LETTER SOFT SIGN
262             "\xED" => "\xCD", # CYRILLIC LETTER E
263             "\xEE" => "\xCE", # CYRILLIC LETTER YU
264             "\xEF" => "\xCF", # CYRILLIC LETTER YA
265             "\xF1" => "\xA1", # CYRILLIC LETTER IO
266             "\xF2" => "\xA2", # CYRILLIC LETTER DJE
267             "\xF3" => "\xA3", # CYRILLIC LETTER GJE
268             "\xF4" => "\xA4", # CYRILLIC LETTER UKRAINIAN IE
269             "\xF5" => "\xA5", # CYRILLIC LETTER DZE
270             "\xF6" => "\xA6", # CYRILLIC LETTER BYELORUSSIAN-UKRAINIAN I
271             "\xF7" => "\xA7", # CYRILLIC LETTER YI
272             "\xF8" => "\xA8", # CYRILLIC LETTER JE
273             "\xF9" => "\xA9", # CYRILLIC LETTER LJE
274             "\xFA" => "\xAA", # CYRILLIC LETTER NJE
275             "\xFB" => "\xAB", # CYRILLIC LETTER TSHE
276             "\xFC" => "\xAC", # CYRILLIC LETTER KJE
277             "\xFE" => "\xAE", # CYRILLIC LETTER SHORT U
278             "\xFF" => "\xAF", # CYRILLIC LETTER DZHE
279             );
280              
281             %fc = (%fc,
282             "\xA1" => "\xF1", # CYRILLIC CAPITAL LETTER IO --> CYRILLIC SMALL LETTER IO
283             "\xA2" => "\xF2", # CYRILLIC CAPITAL LETTER DJE --> CYRILLIC SMALL LETTER DJE
284             "\xA3" => "\xF3", # CYRILLIC CAPITAL LETTER GJE --> CYRILLIC SMALL LETTER GJE
285             "\xA4" => "\xF4", # CYRILLIC CAPITAL LETTER UKRAINIAN IE --> CYRILLIC SMALL LETTER UKRAINIAN IE
286             "\xA5" => "\xF5", # CYRILLIC CAPITAL LETTER DZE --> CYRILLIC SMALL LETTER DZE
287             "\xA6" => "\xF6", # CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I --> CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I
288             "\xA7" => "\xF7", # CYRILLIC CAPITAL LETTER YI --> CYRILLIC SMALL LETTER YI
289             "\xA8" => "\xF8", # CYRILLIC CAPITAL LETTER JE --> CYRILLIC SMALL LETTER JE
290             "\xA9" => "\xF9", # CYRILLIC CAPITAL LETTER LJE --> CYRILLIC SMALL LETTER LJE
291             "\xAA" => "\xFA", # CYRILLIC CAPITAL LETTER NJE --> CYRILLIC SMALL LETTER NJE
292             "\xAB" => "\xFB", # CYRILLIC CAPITAL LETTER TSHE --> CYRILLIC SMALL LETTER TSHE
293             "\xAC" => "\xFC", # CYRILLIC CAPITAL LETTER KJE --> CYRILLIC SMALL LETTER KJE
294             "\xAE" => "\xFE", # CYRILLIC CAPITAL LETTER SHORT U --> CYRILLIC SMALL LETTER SHORT U
295             "\xAF" => "\xFF", # CYRILLIC CAPITAL LETTER DZHE --> CYRILLIC SMALL LETTER DZHE
296             "\xB0" => "\xD0", # CYRILLIC CAPITAL LETTER A --> CYRILLIC SMALL LETTER A
297             "\xB1" => "\xD1", # CYRILLIC CAPITAL LETTER BE --> CYRILLIC SMALL LETTER BE
298             "\xB2" => "\xD2", # CYRILLIC CAPITAL LETTER VE --> CYRILLIC SMALL LETTER VE
299             "\xB3" => "\xD3", # CYRILLIC CAPITAL LETTER GHE --> CYRILLIC SMALL LETTER GHE
300             "\xB4" => "\xD4", # CYRILLIC CAPITAL LETTER DE --> CYRILLIC SMALL LETTER DE
301             "\xB5" => "\xD5", # CYRILLIC CAPITAL LETTER IE --> CYRILLIC SMALL LETTER IE
302             "\xB6" => "\xD6", # CYRILLIC CAPITAL LETTER ZHE --> CYRILLIC SMALL LETTER ZHE
303             "\xB7" => "\xD7", # CYRILLIC CAPITAL LETTER ZE --> CYRILLIC SMALL LETTER ZE
304             "\xB8" => "\xD8", # CYRILLIC CAPITAL LETTER I --> CYRILLIC SMALL LETTER I
305             "\xB9" => "\xD9", # CYRILLIC CAPITAL LETTER SHORT I --> CYRILLIC SMALL LETTER SHORT I
306             "\xBA" => "\xDA", # CYRILLIC CAPITAL LETTER KA --> CYRILLIC SMALL LETTER KA
307             "\xBB" => "\xDB", # CYRILLIC CAPITAL LETTER EL --> CYRILLIC SMALL LETTER EL
308             "\xBC" => "\xDC", # CYRILLIC CAPITAL LETTER EM --> CYRILLIC SMALL LETTER EM
309             "\xBD" => "\xDD", # CYRILLIC CAPITAL LETTER EN --> CYRILLIC SMALL LETTER EN
310             "\xBE" => "\xDE", # CYRILLIC CAPITAL LETTER O --> CYRILLIC SMALL LETTER O
311             "\xBF" => "\xDF", # CYRILLIC CAPITAL LETTER PE --> CYRILLIC SMALL LETTER PE
312             "\xC0" => "\xE0", # CYRILLIC CAPITAL LETTER ER --> CYRILLIC SMALL LETTER ER
313             "\xC1" => "\xE1", # CYRILLIC CAPITAL LETTER ES --> CYRILLIC SMALL LETTER ES
314             "\xC2" => "\xE2", # CYRILLIC CAPITAL LETTER TE --> CYRILLIC SMALL LETTER TE
315             "\xC3" => "\xE3", # CYRILLIC CAPITAL LETTER U --> CYRILLIC SMALL LETTER U
316             "\xC4" => "\xE4", # CYRILLIC CAPITAL LETTER EF --> CYRILLIC SMALL LETTER EF
317             "\xC5" => "\xE5", # CYRILLIC CAPITAL LETTER HA --> CYRILLIC SMALL LETTER HA
318             "\xC6" => "\xE6", # CYRILLIC CAPITAL LETTER TSE --> CYRILLIC SMALL LETTER TSE
319             "\xC7" => "\xE7", # CYRILLIC CAPITAL LETTER CHE --> CYRILLIC SMALL LETTER CHE
320             "\xC8" => "\xE8", # CYRILLIC CAPITAL LETTER SHA --> CYRILLIC SMALL LETTER SHA
321             "\xC9" => "\xE9", # CYRILLIC CAPITAL LETTER SHCHA --> CYRILLIC SMALL LETTER SHCHA
322             "\xCA" => "\xEA", # CYRILLIC CAPITAL LETTER HARD SIGN --> CYRILLIC SMALL LETTER HARD SIGN
323             "\xCB" => "\xEB", # CYRILLIC CAPITAL LETTER YERU --> CYRILLIC SMALL LETTER YERU
324             "\xCC" => "\xEC", # CYRILLIC CAPITAL LETTER SOFT SIGN --> CYRILLIC SMALL LETTER SOFT SIGN
325             "\xCD" => "\xED", # CYRILLIC CAPITAL LETTER E --> CYRILLIC SMALL LETTER E
326             "\xCE" => "\xEE", # CYRILLIC CAPITAL LETTER YU --> CYRILLIC SMALL LETTER YU
327             "\xCF" => "\xEF", # CYRILLIC CAPITAL LETTER YA --> CYRILLIC SMALL LETTER YA
328             );
329             }
330              
331             else {
332             croak "Don't know my package name '@{[__PACKAGE__]}'";
333             }
334              
335             #
336             # @ARGV wildcard globbing
337             #
338             sub import {
339              
340 0 0   0   0 if ($^O =~ /\A (?: MSWin32 | NetWare | symbian | dos ) \z/oxms) {
341 0         0 my @argv = ();
342 0         0 for (@ARGV) {
343              
344             # has space
345 0 0       0 if (/\A (?:$q_char)*? [ ] /oxms) {
    0          
346 0 0       0 if (my @glob = Ecyrillic::glob(qq{"$_"})) {
347 0         0 push @argv, @glob;
348             }
349             else {
350 0         0 push @argv, $_;
351             }
352             }
353              
354             # has wildcard metachar
355             elsif (/\A (?:$q_char)*? [*?] /oxms) {
356 0 0       0 if (my @glob = Ecyrillic::glob($_)) {
357 0         0 push @argv, @glob;
358             }
359             else {
360 0         0 push @argv, $_;
361             }
362             }
363              
364             # no wildcard globbing
365             else {
366 0         0 push @argv, $_;
367             }
368             }
369 0         0 @ARGV = @argv;
370             }
371              
372 0         0 *Char::ord = \&Cyrillic::ord;
373 0         0 *Char::ord_ = \&Cyrillic::ord_;
374 0         0 *Char::reverse = \&Cyrillic::reverse;
375 0         0 *Char::getc = \&Cyrillic::getc;
376 0         0 *Char::length = \&Cyrillic::length;
377 0         0 *Char::substr = \&Cyrillic::substr;
378 0         0 *Char::index = \&Cyrillic::index;
379 0         0 *Char::rindex = \&Cyrillic::rindex;
380 0         0 *Char::eval = \&Cyrillic::eval;
381 0         0 *Char::escape = \&Cyrillic::escape;
382 0         0 *Char::escape_token = \&Cyrillic::escape_token;
383 0         0 *Char::escape_script = \&Cyrillic::escape_script;
384             }
385              
386             # P.230 Care with Prototypes
387             # in Chapter 6: Subroutines
388             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
389             #
390             # If you aren't careful, you can get yourself into trouble with prototypes.
391             # But if you are careful, you can do a lot of neat things with them. This is
392             # all very powerful, of course, and should only be used in moderation to make
393             # the world a better place.
394              
395             # P.332 Care with Prototypes
396             # in Chapter 7: Subroutines
397             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
398             #
399             # If you aren't careful, you can get yourself into trouble with prototypes.
400             # But if you are careful, you can do a lot of neat things with them. This is
401             # all very powerful, of course, and should only be used in moderation to make
402             # the world a better place.
403              
404             #
405             # Prototypes of subroutines
406             #
407       0     sub unimport {}
408             sub Ecyrillic::split(;$$$);
409             sub Ecyrillic::tr($$$$;$);
410             sub Ecyrillic::chop(@);
411             sub Ecyrillic::index($$;$);
412             sub Ecyrillic::rindex($$;$);
413             sub Ecyrillic::lcfirst(@);
414             sub Ecyrillic::lcfirst_();
415             sub Ecyrillic::lc(@);
416             sub Ecyrillic::lc_();
417             sub Ecyrillic::ucfirst(@);
418             sub Ecyrillic::ucfirst_();
419             sub Ecyrillic::uc(@);
420             sub Ecyrillic::uc_();
421             sub Ecyrillic::fc(@);
422             sub Ecyrillic::fc_();
423             sub Ecyrillic::ignorecase;
424             sub Ecyrillic::classic_character_class;
425             sub Ecyrillic::capture;
426             sub Ecyrillic::chr(;$);
427             sub Ecyrillic::chr_();
428             sub Ecyrillic::glob($);
429             sub Ecyrillic::glob_();
430              
431             sub Cyrillic::ord(;$);
432             sub Cyrillic::ord_();
433             sub Cyrillic::reverse(@);
434             sub Cyrillic::getc(;*@);
435             sub Cyrillic::length(;$);
436             sub Cyrillic::substr($$;$$);
437             sub Cyrillic::index($$;$);
438             sub Cyrillic::rindex($$;$);
439             sub Cyrillic::escape(;$);
440              
441             #
442             # Regexp work
443             #
444 204         18530 use vars qw(
445             $re_a
446             $re_t
447             $re_n
448             $re_r
449 204     204   1811 );
  204         469  
450              
451             #
452             # Character class
453             #
454 204         2251476 use vars qw(
455             $dot
456             $dot_s
457             $eD
458             $eS
459             $eW
460             $eH
461             $eV
462             $eR
463             $eN
464             $not_alnum
465             $not_alpha
466             $not_ascii
467             $not_blank
468             $not_cntrl
469             $not_digit
470             $not_graph
471             $not_lower
472             $not_lower_i
473             $not_print
474             $not_punct
475             $not_space
476             $not_upper
477             $not_upper_i
478             $not_word
479             $not_xdigit
480             $eb
481             $eB
482 204     204   1556 );
  204         408  
483              
484             ${Ecyrillic::dot} = qr{(?>[^\x0A])};
485             ${Ecyrillic::dot_s} = qr{(?>[\x00-\xFF])};
486             ${Ecyrillic::eD} = qr{(?>[^0-9])};
487              
488             # Vertical tabs are now whitespace
489             # \s in a regex now matches a vertical tab in all circumstances.
490             # http://search.cpan.org/dist/perl-5.18.0/pod/perldelta.pod#Vertical_tabs_are_now_whitespace
491             # ${Ecyrillic::eS} = qr{(?>[^\x09\x0A \x0C\x0D\x20])};
492             # ${Ecyrillic::eS} = qr{(?>[^\x09\x0A\x0B\x0C\x0D\x20])};
493             ${Ecyrillic::eS} = qr{(?>[^\s])};
494              
495             ${Ecyrillic::eW} = qr{(?>[^0-9A-Z_a-z])};
496             ${Ecyrillic::eH} = qr{(?>[^\x09\x20])};
497             ${Ecyrillic::eV} = qr{(?>[^\x0A\x0B\x0C\x0D])};
498             ${Ecyrillic::eR} = qr{(?>\x0D\x0A|[\x0A\x0D])};
499             ${Ecyrillic::eN} = qr{(?>[^\x0A])};
500             ${Ecyrillic::not_alnum} = qr{(?>[^\x30-\x39\x41-\x5A\x61-\x7A])};
501             ${Ecyrillic::not_alpha} = qr{(?>[^\x41-\x5A\x61-\x7A])};
502             ${Ecyrillic::not_ascii} = qr{(?>[^\x00-\x7F])};
503             ${Ecyrillic::not_blank} = qr{(?>[^\x09\x20])};
504             ${Ecyrillic::not_cntrl} = qr{(?>[^\x00-\x1F\x7F])};
505             ${Ecyrillic::not_digit} = qr{(?>[^\x30-\x39])};
506             ${Ecyrillic::not_graph} = qr{(?>[^\x21-\x7F])};
507             ${Ecyrillic::not_lower} = qr{(?>[^\x61-\x7A])};
508             ${Ecyrillic::not_lower_i} = qr{(?>[^\x41-\x5A\x61-\x7A])}; # Perl 5.16 compatible
509             # ${Ecyrillic::not_lower_i} = qr{(?>[\x00-\xFF])}; # older Perl compatible
510             ${Ecyrillic::not_print} = qr{(?>[^\x20-\x7F])};
511             ${Ecyrillic::not_punct} = qr{(?>[^\x21-\x2F\x3A-\x3F\x40\x5B-\x5F\x60\x7B-\x7E])};
512             ${Ecyrillic::not_space} = qr{(?>[^\s\x0B])};
513             ${Ecyrillic::not_upper} = qr{(?>[^\x41-\x5A])};
514             ${Ecyrillic::not_upper_i} = qr{(?>[^\x41-\x5A\x61-\x7A])}; # Perl 5.16 compatible
515             # ${Ecyrillic::not_upper_i} = qr{(?>[\x00-\xFF])}; # older Perl compatible
516             ${Ecyrillic::not_word} = qr{(?>[^\x30-\x39\x41-\x5A\x5F\x61-\x7A])};
517             ${Ecyrillic::not_xdigit} = qr{(?>[^\x30-\x39\x41-\x46\x61-\x66])};
518             ${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))};
519             ${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]))};
520              
521             # avoid: Name "Ecyrillic::foo" used only once: possible typo at here.
522             ${Ecyrillic::dot} = ${Ecyrillic::dot};
523             ${Ecyrillic::dot_s} = ${Ecyrillic::dot_s};
524             ${Ecyrillic::eD} = ${Ecyrillic::eD};
525             ${Ecyrillic::eS} = ${Ecyrillic::eS};
526             ${Ecyrillic::eW} = ${Ecyrillic::eW};
527             ${Ecyrillic::eH} = ${Ecyrillic::eH};
528             ${Ecyrillic::eV} = ${Ecyrillic::eV};
529             ${Ecyrillic::eR} = ${Ecyrillic::eR};
530             ${Ecyrillic::eN} = ${Ecyrillic::eN};
531             ${Ecyrillic::not_alnum} = ${Ecyrillic::not_alnum};
532             ${Ecyrillic::not_alpha} = ${Ecyrillic::not_alpha};
533             ${Ecyrillic::not_ascii} = ${Ecyrillic::not_ascii};
534             ${Ecyrillic::not_blank} = ${Ecyrillic::not_blank};
535             ${Ecyrillic::not_cntrl} = ${Ecyrillic::not_cntrl};
536             ${Ecyrillic::not_digit} = ${Ecyrillic::not_digit};
537             ${Ecyrillic::not_graph} = ${Ecyrillic::not_graph};
538             ${Ecyrillic::not_lower} = ${Ecyrillic::not_lower};
539             ${Ecyrillic::not_lower_i} = ${Ecyrillic::not_lower_i};
540             ${Ecyrillic::not_print} = ${Ecyrillic::not_print};
541             ${Ecyrillic::not_punct} = ${Ecyrillic::not_punct};
542             ${Ecyrillic::not_space} = ${Ecyrillic::not_space};
543             ${Ecyrillic::not_upper} = ${Ecyrillic::not_upper};
544             ${Ecyrillic::not_upper_i} = ${Ecyrillic::not_upper_i};
545             ${Ecyrillic::not_word} = ${Ecyrillic::not_word};
546             ${Ecyrillic::not_xdigit} = ${Ecyrillic::not_xdigit};
547             ${Ecyrillic::eb} = ${Ecyrillic::eb};
548             ${Ecyrillic::eB} = ${Ecyrillic::eB};
549              
550             #
551             # Cyrillic split
552             #
553             sub Ecyrillic::split(;$$$) {
554              
555             # P.794 29.2.161. split
556             # in Chapter 29: Functions
557             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
558              
559             # P.951 split
560             # in Chapter 27: Functions
561             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
562              
563 0     0 0 0 my $pattern = $_[0];
564 0         0 my $string = $_[1];
565 0         0 my $limit = $_[2];
566              
567             # if $pattern is also omitted or is the literal space, " "
568 0 0       0 if (not defined $pattern) {
569 0         0 $pattern = ' ';
570             }
571              
572             # if $string is omitted, the function splits the $_ string
573 0 0       0 if (not defined $string) {
574 0 0       0 if (defined $_) {
575 0         0 $string = $_;
576             }
577             else {
578 0         0 $string = '';
579             }
580             }
581              
582 0         0 my @split = ();
583              
584             # when string is empty
585 0 0       0 if ($string eq '') {
    0          
586              
587             # resulting list value in list context
588 0 0       0 if (wantarray) {
589 0         0 return @split;
590             }
591              
592             # count of substrings in scalar context
593             else {
594 0 0       0 carp "Use of implicit split to \@_ is deprecated" if $^W;
595 0         0 @_ = @split;
596 0         0 return scalar @_;
597             }
598             }
599              
600             # split's first argument is more consistently interpreted
601             #
602             # After some changes earlier in v5.17, split's behavior has been simplified:
603             # if the PATTERN argument evaluates to a string containing one space, it is
604             # treated the way that a literal string containing one space once was.
605             # http://search.cpan.org/dist/perl-5.18.0/pod/perldelta.pod#split's_first_argument_is_more_consistently_interpreted
606              
607             # if $pattern is also omitted or is the literal space, " ", the function splits
608             # on whitespace, /\s+/, after skipping any leading whitespace
609             # (and so on)
610              
611             elsif ($pattern eq ' ') {
612 0 0       0 if (not defined $limit) {
613 0         0 return CORE::split(' ', $string);
614             }
615             else {
616 0         0 return CORE::split(' ', $string, $limit);
617             }
618             }
619              
620             # if $limit is negative, it is treated as if an arbitrarily large $limit has been specified
621 0 0 0     0 if ((not defined $limit) or ($limit <= 0)) {
    0          
622              
623             # a pattern capable of matching either the null string or something longer than the
624             # null string will split the value of $string into separate characters wherever it
625             # matches the null string between characters
626             # (and so on)
627              
628 0 0       0 if ('' =~ / \A $pattern \z /xms) {
629 0         0 my $last_subexpression_offsets = _last_subexpression_offsets($pattern);
630 0         0 my $limit = scalar(() = $string =~ /($pattern)/oxmsg);
631              
632             # P.1024 Appendix W.10 Multibyte Processing
633             # of ISBN 1-56592-224-7 CJKV Information Processing
634             # (and so on)
635              
636             # the //m modifier is assumed when you split on the pattern /^/
637             # (and so on)
638              
639             # V
640 0   0     0 while ((--$limit > 0) and ($string =~ s/\A((?:$q_char)+?)$pattern//m)) {
641              
642             # if the $pattern contains parentheses, then the substring matched by each pair of parentheses
643             # is included in the resulting list, interspersed with the fields that are ordinarily returned
644             # (and so on)
645              
646 0         0 local $@;
647 0         0 for (my $digit=1; $digit <= ($last_subexpression_offsets + 1); $digit++) {
648 0         0 push @split, CORE::eval('$' . $digit);
649             }
650             }
651             }
652              
653             else {
654 0         0 my $last_subexpression_offsets = _last_subexpression_offsets($pattern);
655              
656             # V
657 0         0 while ($string =~ s/\A((?:$q_char)*?)$pattern//m) {
658 0         0 local $@;
659 0         0 for (my $digit=1; $digit <= ($last_subexpression_offsets + 1); $digit++) {
660 0         0 push @split, CORE::eval('$' . $digit);
661             }
662             }
663             }
664             }
665              
666             elsif ($limit > 0) {
667 0 0       0 if ('' =~ / \A $pattern \z /xms) {
668 0         0 my $last_subexpression_offsets = _last_subexpression_offsets($pattern);
669 0   0     0 while ((--$limit > 0) and (CORE::length($string) > 0)) {
670              
671             # V
672 0 0       0 if ($string =~ s/\A((?:$q_char)+?)$pattern//m) {
673 0         0 local $@;
674 0         0 for (my $digit=1; $digit <= ($last_subexpression_offsets + 1); $digit++) {
675 0         0 push @split, CORE::eval('$' . $digit);
676             }
677             }
678             }
679             }
680             else {
681 0         0 my $last_subexpression_offsets = _last_subexpression_offsets($pattern);
682 0   0     0 while ((--$limit > 0) and (CORE::length($string) > 0)) {
683              
684             # V
685 0 0       0 if ($string =~ s/\A((?:$q_char)*?)$pattern//m) {
686 0         0 local $@;
687 0         0 for (my $digit=1; $digit <= ($last_subexpression_offsets + 1); $digit++) {
688 0         0 push @split, CORE::eval('$' . $digit);
689             }
690             }
691             }
692             }
693             }
694              
695 0 0       0 if (CORE::length($string) > 0) {
696 0         0 push @split, $string;
697             }
698              
699             # if $_[2] (NOT "$limit") is omitted or zero, trailing null fields are stripped from the result
700 0 0 0     0 if ((not defined $_[2]) or ($_[2] == 0)) {
701 0   0     0 while ((scalar(@split) >= 1) and ($split[-1] eq '')) {
702 0         0 pop @split;
703             }
704             }
705              
706             # resulting list value in list context
707 0 0       0 if (wantarray) {
708 0         0 return @split;
709             }
710              
711             # count of substrings in scalar context
712             else {
713 0 0       0 carp "Use of implicit split to \@_ is deprecated" if $^W;
714 0         0 @_ = @split;
715 0         0 return scalar @_;
716             }
717             }
718              
719             #
720             # get last subexpression offsets
721             #
722             sub _last_subexpression_offsets {
723 0     0   0 my $pattern = $_[0];
724              
725             # remove comment
726 0         0 $pattern =~ s/\(\?\# .*? \)//oxmsg;
727              
728 0         0 my $modifier = '';
729 0 0       0 if ($pattern =~ /\(\?\^? ([\-A-Za-z]+) :/oxms) {
730 0         0 $modifier = $1;
731 0         0 $modifier =~ s/-[A-Za-z]*//;
732             }
733              
734             # with /x modifier
735 0         0 my @char = ();
736 0 0       0 if ($modifier =~ /x/oxms) {
737 0         0 @char = $pattern =~ /\G((?>
738             [^\\\#\[\(] |
739             \\ $q_char |
740             \# (?>[^\n]*) $ |
741             \[ (?>(?:[^\\\]]|\\\\|\\\]|$q_char)+) \] |
742             \(\? |
743             $q_char
744             ))/oxmsg;
745             }
746              
747             # without /x modifier
748             else {
749 0         0 @char = $pattern =~ /\G((?>
750             [^\\\[\(] |
751             \\ $q_char |
752             \[ (?>(?:[^\\\]]|\\\\|\\\]|$q_char)+) \] |
753             \(\? |
754             $q_char
755             ))/oxmsg;
756             }
757              
758 0         0 return scalar grep { $_ eq '(' } @char;
  0         0  
759             }
760              
761             #
762             # Cyrillic transliteration (tr///)
763             #
764             sub Ecyrillic::tr($$$$;$) {
765              
766 0     0 0 0 my $bind_operator = $_[1];
767 0         0 my $searchlist = $_[2];
768 0         0 my $replacementlist = $_[3];
769 0   0     0 my $modifier = $_[4] || '';
770              
771 0 0       0 if ($modifier =~ /r/oxms) {
772 0 0       0 if ($bind_operator =~ / !~ /oxms) {
773 0         0 croak "Using !~ with tr///r doesn't make sense";
774             }
775             }
776              
777 0         0 my @char = $_[0] =~ /\G (?>$q_char) /oxmsg;
778 0         0 my @searchlist = _charlist_tr($searchlist);
779 0         0 my @replacementlist = _charlist_tr($replacementlist);
780              
781 0         0 my %tr = ();
782 0         0 for (my $i=0; $i <= $#searchlist; $i++) {
783 0 0       0 if (not exists $tr{$searchlist[$i]}) {
784 0 0 0     0 if (defined $replacementlist[$i] and ($replacementlist[$i] ne '')) {
    0 0        
    0          
785 0         0 $tr{$searchlist[$i]} = $replacementlist[$i];
786             }
787             elsif ($modifier =~ /d/oxms) {
788 0         0 $tr{$searchlist[$i]} = '';
789             }
790             elsif (defined $replacementlist[-1] and ($replacementlist[-1] ne '')) {
791 0         0 $tr{$searchlist[$i]} = $replacementlist[-1];
792             }
793             else {
794 0         0 $tr{$searchlist[$i]} = $searchlist[$i];
795             }
796             }
797             }
798              
799 0         0 my $tr = 0;
800 0         0 my $replaced = '';
801 0 0       0 if ($modifier =~ /c/oxms) {
802 0         0 while (defined(my $char = shift @char)) {
803 0 0       0 if (not exists $tr{$char}) {
804 0 0       0 if (defined $replacementlist[0]) {
805 0         0 $replaced .= $replacementlist[0];
806             }
807 0         0 $tr++;
808 0 0       0 if ($modifier =~ /s/oxms) {
809 0   0     0 while (@char and (not exists $tr{$char[0]})) {
810 0         0 shift @char;
811 0         0 $tr++;
812             }
813             }
814             }
815             else {
816 0         0 $replaced .= $char;
817             }
818             }
819             }
820             else {
821 0         0 while (defined(my $char = shift @char)) {
822 0 0       0 if (exists $tr{$char}) {
823 0         0 $replaced .= $tr{$char};
824 0         0 $tr++;
825 0 0       0 if ($modifier =~ /s/oxms) {
826 0   0     0 while (@char and (exists $tr{$char[0]}) and ($tr{$char[0]} eq $tr{$char})) {
      0        
827 0         0 shift @char;
828 0         0 $tr++;
829             }
830             }
831             }
832             else {
833 0         0 $replaced .= $char;
834             }
835             }
836             }
837              
838 0 0       0 if ($modifier =~ /r/oxms) {
839 0         0 return $replaced;
840             }
841             else {
842 0         0 $_[0] = $replaced;
843 0 0       0 if ($bind_operator =~ / !~ /oxms) {
844 0         0 return not $tr;
845             }
846             else {
847 0         0 return $tr;
848             }
849             }
850             }
851              
852             #
853             # Cyrillic chop
854             #
855             sub Ecyrillic::chop(@) {
856              
857 0     0 0 0 my $chop;
858 0 0       0 if (@_ == 0) {
859 0         0 my @char = /\G (?>$q_char) /oxmsg;
860 0         0 $chop = pop @char;
861 0         0 $_ = join '', @char;
862             }
863             else {
864 0         0 for (@_) {
865 0         0 my @char = /\G (?>$q_char) /oxmsg;
866 0         0 $chop = pop @char;
867 0         0 $_ = join '', @char;
868             }
869             }
870 0         0 return $chop;
871             }
872              
873             #
874             # Cyrillic index by octet
875             #
876             sub Ecyrillic::index($$;$) {
877              
878 0     0 1 0 my($str,$substr,$position) = @_;
879 0   0     0 $position ||= 0;
880 0         0 my $pos = 0;
881              
882 0         0 while ($pos < CORE::length($str)) {
883 0 0       0 if (CORE::substr($str,$pos,CORE::length($substr)) eq $substr) {
884 0 0       0 if ($pos >= $position) {
885 0         0 return $pos;
886             }
887             }
888 0 0       0 if (CORE::substr($str,$pos) =~ /\A ($q_char) /oxms) {
889 0         0 $pos += CORE::length($1);
890             }
891             else {
892 0         0 $pos += 1;
893             }
894             }
895 0         0 return -1;
896             }
897              
898             #
899             # Cyrillic reverse index
900             #
901             sub Ecyrillic::rindex($$;$) {
902              
903 0     0 0 0 my($str,$substr,$position) = @_;
904 0   0     0 $position ||= CORE::length($str) - 1;
905 0         0 my $pos = 0;
906 0         0 my $rindex = -1;
907              
908 0   0     0 while (($pos < CORE::length($str)) and ($pos <= $position)) {
909 0 0       0 if (CORE::substr($str,$pos,CORE::length($substr)) eq $substr) {
910 0         0 $rindex = $pos;
911             }
912 0 0       0 if (CORE::substr($str,$pos) =~ /\A ($q_char) /oxms) {
913 0         0 $pos += CORE::length($1);
914             }
915             else {
916 0         0 $pos += 1;
917             }
918             }
919 0         0 return $rindex;
920             }
921              
922             #
923             # Cyrillic lower case first with parameter
924             #
925             sub Ecyrillic::lcfirst(@) {
926 0 0   0 0 0 if (@_) {
927 0         0 my $s = shift @_;
928 0 0 0     0 if (@_ and wantarray) {
929 0         0 return Ecyrillic::lc(CORE::substr($s,0,1)) . CORE::substr($s,1), @_;
930             }
931             else {
932 0         0 return Ecyrillic::lc(CORE::substr($s,0,1)) . CORE::substr($s,1);
933             }
934             }
935             else {
936 0         0 return Ecyrillic::lc(CORE::substr($_,0,1)) . CORE::substr($_,1);
937             }
938             }
939              
940             #
941             # Cyrillic lower case first without parameter
942             #
943             sub Ecyrillic::lcfirst_() {
944 0     0 0 0 return Ecyrillic::lc(CORE::substr($_,0,1)) . CORE::substr($_,1);
945             }
946              
947             #
948             # Cyrillic lower case with parameter
949             #
950             sub Ecyrillic::lc(@) {
951 0 0   0 0 0 if (@_) {
952 0         0 my $s = shift @_;
953 0 0 0     0 if (@_ and wantarray) {
954 0 0       0 return join('', map {defined($lc{$_}) ? $lc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg)), @_;
  0         0  
955             }
956             else {
957 0 0       0 return join('', map {defined($lc{$_}) ? $lc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg));
  0         0  
958             }
959             }
960             else {
961 0         0 return Ecyrillic::lc_();
962             }
963             }
964              
965             #
966             # Cyrillic lower case without parameter
967             #
968             sub Ecyrillic::lc_() {
969 0     0 0 0 my $s = $_;
970 0 0       0 return join '', map {defined($lc{$_}) ? $lc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg);
  0         0  
971             }
972              
973             #
974             # Cyrillic upper case first with parameter
975             #
976             sub Ecyrillic::ucfirst(@) {
977 0 0   0 0 0 if (@_) {
978 0         0 my $s = shift @_;
979 0 0 0     0 if (@_ and wantarray) {
980 0         0 return Ecyrillic::uc(CORE::substr($s,0,1)) . CORE::substr($s,1), @_;
981             }
982             else {
983 0         0 return Ecyrillic::uc(CORE::substr($s,0,1)) . CORE::substr($s,1);
984             }
985             }
986             else {
987 0         0 return Ecyrillic::uc(CORE::substr($_,0,1)) . CORE::substr($_,1);
988             }
989             }
990              
991             #
992             # Cyrillic upper case first without parameter
993             #
994             sub Ecyrillic::ucfirst_() {
995 0     0 0 0 return Ecyrillic::uc(CORE::substr($_,0,1)) . CORE::substr($_,1);
996             }
997              
998             #
999             # Cyrillic upper case with parameter
1000             #
1001             sub Ecyrillic::uc(@) {
1002 0 50   174 0 0 if (@_) {
1003 174         269 my $s = shift @_;
1004 174 50 33     217 if (@_ and wantarray) {
1005 174 0       312 return join('', map {defined($uc{$_}) ? $uc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg)), @_;
  0         0  
1006             }
1007             else {
1008 0 100       0 return join('', map {defined($uc{$_}) ? $uc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg));
  174         600  
1009             }
1010             }
1011             else {
1012 174         804 return Ecyrillic::uc_();
1013             }
1014             }
1015              
1016             #
1017             # Cyrillic upper case without parameter
1018             #
1019             sub Ecyrillic::uc_() {
1020 0     0 0 0 my $s = $_;
1021 0 0       0 return join '', map {defined($uc{$_}) ? $uc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg);
  0         0  
1022             }
1023              
1024             #
1025             # Cyrillic fold case with parameter
1026             #
1027             sub Ecyrillic::fc(@) {
1028 0 50   197 0 0 if (@_) {
1029 197         609 my $s = shift @_;
1030 197 50 33     313 if (@_ and wantarray) {
1031 197 0       477 return join('', map {defined($fc{$_}) ? $fc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg)), @_;
  0         0  
1032             }
1033             else {
1034 0 100       0 return join('', map {defined($fc{$_}) ? $fc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg));
  197         774  
1035             }
1036             }
1037             else {
1038 197         1058 return Ecyrillic::fc_();
1039             }
1040             }
1041              
1042             #
1043             # Cyrillic fold case without parameter
1044             #
1045             sub Ecyrillic::fc_() {
1046 0     0 0 0 my $s = $_;
1047 0 0       0 return join '', map {defined($fc{$_}) ? $fc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg);
  0         0  
1048             }
1049              
1050             #
1051             # Cyrillic regexp capture
1052             #
1053             {
1054             sub Ecyrillic::capture {
1055 0     0 1 0 return $_[0];
1056             }
1057             }
1058              
1059             #
1060             # Cyrillic regexp ignore case modifier
1061             #
1062             sub Ecyrillic::ignorecase {
1063              
1064 0     0 0 0 my @string = @_;
1065 0         0 my $metachar = qr/[\@\\|[\]{]/oxms;
1066              
1067             # ignore case of $scalar or @array
1068 0         0 for my $string (@string) {
1069              
1070             # split regexp
1071 0         0 my @char = $string =~ /\G (?>\[\^|\\$q_char|$q_char) /oxmsg;
1072              
1073             # unescape character
1074 0         0 for (my $i=0; $i <= $#char; $i++) {
1075 0 0       0 next if not defined $char[$i];
1076              
1077             # open character class [...]
1078 0 0       0 if ($char[$i] eq '[') {
    0          
    0          
    0          
1079 0         0 my $left = $i;
1080              
1081             # [] make die "unmatched [] in regexp ...\n"
1082              
1083 0 0       0 if ($char[$i+1] eq ']') {
1084 0         0 $i++;
1085             }
1086              
1087 0         0 while (1) {
1088 0 0       0 if (++$i > $#char) {
1089 0         0 croak "Unmatched [] in regexp";
1090             }
1091 0 0       0 if ($char[$i] eq ']') {
1092 0         0 my $right = $i;
1093 0         0 my @charlist = charlist_qr(@char[$left+1..$right-1], 'i');
1094              
1095             # escape character
1096 0         0 for my $char (@charlist) {
1097 0 0       0 if (0) {
1098             }
1099              
1100 0         0 elsif ($char =~ /\A [.|)] \z/oxms) {
1101 0         0 $char = '\\' . $char;
1102             }
1103             }
1104              
1105             # [...]
1106 0         0 splice @char, $left, $right-$left+1, '(?:' . join('|', @charlist) . ')';
1107              
1108 0         0 $i = $left;
1109 0         0 last;
1110             }
1111             }
1112             }
1113              
1114             # open character class [^...]
1115             elsif ($char[$i] eq '[^') {
1116 0         0 my $left = $i;
1117              
1118             # [^] make die "unmatched [] in regexp ...\n"
1119              
1120 0 0       0 if ($char[$i+1] eq ']') {
1121 0         0 $i++;
1122             }
1123              
1124 0         0 while (1) {
1125 0 0       0 if (++$i > $#char) {
1126 0         0 croak "Unmatched [] in regexp";
1127             }
1128 0 0       0 if ($char[$i] eq ']') {
1129 0         0 my $right = $i;
1130 0         0 my @charlist = charlist_not_qr(@char[$left+1..$right-1], 'i');
1131              
1132             # escape character
1133 0         0 for my $char (@charlist) {
1134 0 0       0 if (0) {
1135             }
1136              
1137 0         0 elsif ($char =~ /\A [.|)] \z/oxms) {
1138 0         0 $char = '\\' . $char;
1139             }
1140             }
1141              
1142             # [^...]
1143 0         0 splice @char, $left, $right-$left+1, '(?!' . join('|', @charlist) . ")(?:$your_char)";
1144              
1145 0         0 $i = $left;
1146 0         0 last;
1147             }
1148             }
1149             }
1150              
1151             # rewrite classic character class or escape character
1152             elsif (my $char = classic_character_class($char[$i])) {
1153 0         0 $char[$i] = $char;
1154             }
1155              
1156             # with /i modifier
1157             elsif ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) {
1158 0         0 my $uc = Ecyrillic::uc($char[$i]);
1159 0         0 my $fc = Ecyrillic::fc($char[$i]);
1160 0 0       0 if ($uc ne $fc) {
1161 0 0       0 if (CORE::length($fc) == 1) {
1162 0         0 $char[$i] = '[' . $uc . $fc . ']';
1163             }
1164             else {
1165 0         0 $char[$i] = '(?:' . $uc . '|' . $fc . ')';
1166             }
1167             }
1168             }
1169             }
1170              
1171             # characterize
1172 0         0 for (my $i=0; $i <= $#char; $i++) {
1173 0 0       0 next if not defined $char[$i];
1174              
1175 0 0       0 if (0) {
1176             }
1177              
1178             # quote character before ? + * {
1179 0 0       0 elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
1180 0 0       0 if ($char[$i-1] !~ /\A [\x00-\xFF] \z/oxms) {
1181 0         0 $char[$i-1] = '(?:' . $char[$i-1] . ')';
1182             }
1183             }
1184             }
1185              
1186 0         0 $string = join '', @char;
1187             }
1188              
1189             # make regexp string
1190 0         0 return @string;
1191             }
1192              
1193             #
1194             # classic character class ( \D \S \W \d \s \w \C \X \H \V \h \v \R \N \b \B )
1195             #
1196             sub Ecyrillic::classic_character_class {
1197 0     1867 0 0 my($char) = @_;
1198              
1199             return {
1200             '\D' => '${Ecyrillic::eD}',
1201             '\S' => '${Ecyrillic::eS}',
1202             '\W' => '${Ecyrillic::eW}',
1203             '\d' => '[0-9]',
1204              
1205             # Before Perl 5.6, \s only matched the five whitespace characters
1206             # tab, newline, form-feed, carriage return, and the space character
1207             # itself, which, taken together, is the character class [\t\n\f\r ].
1208              
1209             # Vertical tabs are now whitespace
1210             # \s in a regex now matches a vertical tab in all circumstances.
1211             # http://search.cpan.org/dist/perl-5.18.0/pod/perldelta.pod#Vertical_tabs_are_now_whitespace
1212             # \t \n \v \f \r space
1213             # '\s' => '[\x09\x0A \x0C\x0D\x20]',
1214             # '\s' => '[\x09\x0A\x0B\x0C\x0D\x20]',
1215             '\s' => '\s',
1216              
1217             '\w' => '[0-9A-Z_a-z]',
1218             '\C' => '[\x00-\xFF]',
1219             '\X' => 'X',
1220              
1221             # \h \v \H \V
1222              
1223             # P.114 Character Class Shortcuts
1224             # in Chapter 7: In the World of Regular Expressions
1225             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
1226              
1227             # P.357 13.2.3 Whitespace
1228             # in Chapter 13: perlrecharclass: Perl Regular Expression Character Classes
1229             # of ISBN-13: 978-1-906966-02-7 The Perl Language Reference Manual (for Perl version 5.12.1)
1230             #
1231             # 0x00009 CHARACTER TABULATION h s
1232             # 0x0000a LINE FEED (LF) vs
1233             # 0x0000b LINE TABULATION v
1234             # 0x0000c FORM FEED (FF) vs
1235             # 0x0000d CARRIAGE RETURN (CR) vs
1236             # 0x00020 SPACE h s
1237              
1238             # P.196 Table 5-9. Alphanumeric regex metasymbols
1239             # in Chapter 5. Pattern Matching
1240             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
1241              
1242             # (and so on)
1243              
1244             '\H' => '${Ecyrillic::eH}',
1245             '\V' => '${Ecyrillic::eV}',
1246             '\h' => '[\x09\x20]',
1247             '\v' => '[\x0A\x0B\x0C\x0D]',
1248             '\R' => '${Ecyrillic::eR}',
1249              
1250             # \N
1251             #
1252             # http://perldoc.perl.org/perlre.html
1253             # Character Classes and other Special Escapes
1254             # Any character but \n (experimental). Not affected by /s modifier
1255              
1256             '\N' => '${Ecyrillic::eN}',
1257              
1258             # \b \B
1259              
1260             # P.180 Boundaries: The \b and \B Assertions
1261             # in Chapter 5: Pattern Matching
1262             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
1263              
1264             # P.219 Boundaries: The \b and \B Assertions
1265             # in Chapter 5: Pattern Matching
1266             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
1267              
1268             # \b really means (?:(?<=\w)(?!\w)|(?
1269             # or (?:(?<=\A|\W)(?=\w)|(?<=\w)(?=\W|\z))
1270             '\b' => '${Ecyrillic::eb}',
1271              
1272             # \B really means (?:(?<=\w)(?=\w)|(?
1273             # or (?:(?<=\w)(?=\w)|(?<=\W)(?=\W))
1274             '\B' => '${Ecyrillic::eB}',
1275              
1276 1867   100     2742 }->{$char} || '';
1277             }
1278              
1279             #
1280             # prepare Cyrillic characters per length
1281             #
1282              
1283             # 1 octet characters
1284             my @chars1 = ();
1285             sub chars1 {
1286 1867 0   0 0 79792 if (@chars1) {
1287 0         0 return @chars1;
1288             }
1289 0 0       0 if (exists $range_tr{1}) {
1290 0         0 my @ranges = @{ $range_tr{1} };
  0         0  
1291 0         0 while (my @range = splice(@ranges,0,1)) {
1292 0         0 for my $oct0 (@{$range[0]}) {
  0         0  
1293 0         0 push @chars1, pack 'C', $oct0;
1294             }
1295             }
1296             }
1297 0         0 return @chars1;
1298             }
1299              
1300             # 2 octets characters
1301             my @chars2 = ();
1302             sub chars2 {
1303 0 0   0 0 0 if (@chars2) {
1304 0         0 return @chars2;
1305             }
1306 0 0       0 if (exists $range_tr{2}) {
1307 0         0 my @ranges = @{ $range_tr{2} };
  0         0  
1308 0         0 while (my @range = splice(@ranges,0,2)) {
1309 0         0 for my $oct0 (@{$range[0]}) {
  0         0  
1310 0         0 for my $oct1 (@{$range[1]}) {
  0         0  
1311 0         0 push @chars2, pack 'CC', $oct0,$oct1;
1312             }
1313             }
1314             }
1315             }
1316 0         0 return @chars2;
1317             }
1318              
1319             # 3 octets characters
1320             my @chars3 = ();
1321             sub chars3 {
1322 0 0   0 0 0 if (@chars3) {
1323 0         0 return @chars3;
1324             }
1325 0 0       0 if (exists $range_tr{3}) {
1326 0         0 my @ranges = @{ $range_tr{3} };
  0         0  
1327 0         0 while (my @range = splice(@ranges,0,3)) {
1328 0         0 for my $oct0 (@{$range[0]}) {
  0         0  
1329 0         0 for my $oct1 (@{$range[1]}) {
  0         0  
1330 0         0 for my $oct2 (@{$range[2]}) {
  0         0  
1331 0         0 push @chars3, pack 'CCC', $oct0,$oct1,$oct2;
1332             }
1333             }
1334             }
1335             }
1336             }
1337 0         0 return @chars3;
1338             }
1339              
1340             # 4 octets characters
1341             my @chars4 = ();
1342             sub chars4 {
1343 0 0   0 0 0 if (@chars4) {
1344 0         0 return @chars4;
1345             }
1346 0 0       0 if (exists $range_tr{4}) {
1347 0         0 my @ranges = @{ $range_tr{4} };
  0         0  
1348 0         0 while (my @range = splice(@ranges,0,4)) {
1349 0         0 for my $oct0 (@{$range[0]}) {
  0         0  
1350 0         0 for my $oct1 (@{$range[1]}) {
  0         0  
1351 0         0 for my $oct2 (@{$range[2]}) {
  0         0  
1352 0         0 for my $oct3 (@{$range[3]}) {
  0         0  
1353 0         0 push @chars4, pack 'CCCC', $oct0,$oct1,$oct2,$oct3;
1354             }
1355             }
1356             }
1357             }
1358             }
1359             }
1360 0         0 return @chars4;
1361             }
1362              
1363             #
1364             # Cyrillic open character list for tr
1365             #
1366             sub _charlist_tr {
1367              
1368 0     0   0 local $_ = shift @_;
1369              
1370             # unescape character
1371 0         0 my @char = ();
1372 0         0 while (not /\G \z/oxmsgc) {
1373 0 0       0 if (/\G (\\0?55|\\x2[Dd]|\\-) /oxmsgc) {
    0          
    0          
    0          
    0          
    0          
    0          
1374 0         0 push @char, '\-';
1375             }
1376             elsif (/\G \\ ([0-7]{2,3}) /oxmsgc) {
1377 0         0 push @char, CORE::chr(oct $1);
1378             }
1379             elsif (/\G \\x ([0-9A-Fa-f]{1,2}) /oxmsgc) {
1380 0         0 push @char, CORE::chr(hex $1);
1381             }
1382             elsif (/\G \\c ([\x40-\x5F]) /oxmsgc) {
1383 0         0 push @char, CORE::chr(CORE::ord($1) & 0x1F);
1384             }
1385             elsif (/\G (\\ [0nrtfbae]) /oxmsgc) {
1386             push @char, {
1387             '\0' => "\0",
1388             '\n' => "\n",
1389             '\r' => "\r",
1390             '\t' => "\t",
1391             '\f' => "\f",
1392             '\b' => "\x08", # \b means backspace in character class
1393             '\a' => "\a",
1394             '\e' => "\e",
1395 0         0 }->{$1};
1396             }
1397             elsif (/\G \\ ($q_char) /oxmsgc) {
1398 0         0 push @char, $1;
1399             }
1400             elsif (/\G ($q_char) /oxmsgc) {
1401 0         0 push @char, $1;
1402             }
1403             }
1404              
1405             # join separated multiple-octet
1406 0         0 @char = join('',@char) =~ /\G (?>\\-|$q_char) /oxmsg;
1407              
1408             # unescape '-'
1409 0         0 my @i = ();
1410 0         0 for my $i (0 .. $#char) {
1411 0 0       0 if ($char[$i] eq '\-') {
    0          
1412 0         0 $char[$i] = '-';
1413             }
1414             elsif ($char[$i] eq '-') {
1415 0 0 0     0 if ((0 < $i) and ($i < $#char)) {
1416 0         0 push @i, $i;
1417             }
1418             }
1419             }
1420              
1421             # open character list (reverse for splice)
1422 0         0 for my $i (CORE::reverse @i) {
1423 0         0 my @range = ();
1424              
1425             # range error
1426 0 0 0     0 if ((CORE::length($char[$i-1]) > CORE::length($char[$i+1])) or ($char[$i-1] gt $char[$i+1])) {
1427 0         0 croak "Invalid tr/// range \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1428             }
1429              
1430             # range of multiple-octet code
1431 0 0       0 if (CORE::length($char[$i-1]) == 1) {
    0          
    0          
    0          
1432 0 0       0 if (CORE::length($char[$i+1]) == 1) {
    0          
    0          
    0          
1433 0 0       0 push @range, grep {($char[$i-1] le $_) and ($_ le $char[$i+1])} chars1();
  0         0  
1434             }
1435             elsif (CORE::length($char[$i+1]) == 2) {
1436 0         0 push @range, grep {$char[$i-1] le $_} chars1();
  0         0  
1437 0         0 push @range, grep {$_ le $char[$i+1]} chars2();
  0         0  
1438             }
1439             elsif (CORE::length($char[$i+1]) == 3) {
1440 0         0 push @range, grep {$char[$i-1] le $_} chars1();
  0         0  
1441 0         0 push @range, chars2();
1442 0         0 push @range, grep {$_ le $char[$i+1]} chars3();
  0         0  
1443             }
1444             elsif (CORE::length($char[$i+1]) == 4) {
1445 0         0 push @range, grep {$char[$i-1] le $_} chars1();
  0         0  
1446 0         0 push @range, chars2();
1447 0         0 push @range, chars3();
1448 0         0 push @range, grep {$_ le $char[$i+1]} chars4();
  0         0  
1449             }
1450             else {
1451 0         0 croak "Invalid tr/// range (over 4octets) \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1452             }
1453             }
1454             elsif (CORE::length($char[$i-1]) == 2) {
1455 0 0       0 if (CORE::length($char[$i+1]) == 2) {
    0          
    0          
1456 0 0       0 push @range, grep {($char[$i-1] le $_) and ($_ le $char[$i+1])} chars2();
  0         0  
1457             }
1458             elsif (CORE::length($char[$i+1]) == 3) {
1459 0         0 push @range, grep {$char[$i-1] le $_} chars2();
  0         0  
1460 0         0 push @range, grep {$_ le $char[$i+1]} chars3();
  0         0  
1461             }
1462             elsif (CORE::length($char[$i+1]) == 4) {
1463 0         0 push @range, grep {$char[$i-1] le $_} chars2();
  0         0  
1464 0         0 push @range, chars3();
1465 0         0 push @range, grep {$_ le $char[$i+1]} chars4();
  0         0  
1466             }
1467             else {
1468 0         0 croak "Invalid tr/// range (over 4octets) \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1469             }
1470             }
1471             elsif (CORE::length($char[$i-1]) == 3) {
1472 0 0       0 if (CORE::length($char[$i+1]) == 3) {
    0          
1473 0 0       0 push @range, grep {($char[$i-1] le $_) and ($_ le $char[$i+1])} chars3();
  0         0  
1474             }
1475             elsif (CORE::length($char[$i+1]) == 4) {
1476 0         0 push @range, grep {$char[$i-1] le $_} chars3();
  0         0  
1477 0         0 push @range, grep {$_ le $char[$i+1]} chars4();
  0         0  
1478             }
1479             else {
1480 0         0 croak "Invalid tr/// range (over 4octets) \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1481             }
1482             }
1483             elsif (CORE::length($char[$i-1]) == 4) {
1484 0 0       0 if (CORE::length($char[$i+1]) == 4) {
1485 0 0       0 push @range, grep {($char[$i-1] le $_) and ($_ le $char[$i+1])} chars4();
  0         0  
1486             }
1487             else {
1488 0         0 croak "Invalid tr/// range (over 4octets) \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1489             }
1490             }
1491             else {
1492 0         0 croak "Invalid tr/// range (over 4octets) \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1493             }
1494              
1495 0         0 splice @char, $i-1, 3, @range;
1496             }
1497              
1498 0         0 return @char;
1499             }
1500              
1501             #
1502             # Cyrillic open character class
1503             #
1504             sub _cc {
1505 0 0   0   0 if (scalar(@_) == 0) {
    0          
    0          
1506 0         0 die __FILE__, ": subroutine cc got no parameter.\n";
1507             }
1508             elsif (scalar(@_) == 1) {
1509 0         0 return sprintf('\x%02X',$_[0]);
1510             }
1511             elsif (scalar(@_) == 2) {
1512 0 0       0 if ($_[0] > $_[1]) {
    0          
    0          
1513 0         0 die __FILE__, ": subroutine cc got \$_[0] > \$_[1] parameters).\n";
1514             }
1515             elsif ($_[0] == $_[1]) {
1516 0         0 return sprintf('\x%02X',$_[0]);
1517             }
1518             elsif (($_[0]+1) == $_[1]) {
1519 0         0 return sprintf('[\\x%02X\\x%02X]',$_[0],$_[1]);
1520             }
1521             else {
1522 0         0 return sprintf('[\\x%02X-\\x%02X]',$_[0],$_[1]);
1523             }
1524             }
1525             else {
1526 0         0 die __FILE__, ": subroutine cc got 3 or more parameters (@{[scalar(@_)]} parameters).\n";
  0         0  
1527             }
1528             }
1529              
1530             #
1531             # Cyrillic octet range
1532             #
1533             sub _octets {
1534 0     182   0 my $length = shift @_;
1535              
1536 182 50       316 if ($length == 1) {
1537 182         386 my($a1) = unpack 'C', $_[0];
1538 182         654 my($z1) = unpack 'C', $_[1];
1539              
1540 182 50       330 if ($a1 > $z1) {
1541 182         398 croak 'Invalid [] range in regexp (CORE::ord(A) > CORE::ord(B)) ' . '\x' . unpack('H*',$a1) . '-\x' . unpack('H*',$z1);
1542             }
1543              
1544 0 50       0 if ($a1 == $z1) {
    50          
1545 182         503 return sprintf('\x%02X',$a1);
1546             }
1547             elsif (($a1+1) == $z1) {
1548 0         0 return sprintf('\x%02X\x%02X',$a1,$z1);
1549             }
1550             else {
1551 0         0 return sprintf('\x%02X-\x%02X',$a1,$z1);
1552             }
1553             }
1554             else {
1555 182         1329 die __FILE__, ": subroutine _octets got invalid length ($length).\n";
1556             }
1557             }
1558              
1559             #
1560             # Cyrillic range regexp
1561             #
1562             sub _range_regexp {
1563 0     182   0 my($length,$first,$last) = @_;
1564              
1565 182         396 my @range_regexp = ();
1566 182 50       285 if (not exists $range_tr{$length}) {
1567 182         1084 return @range_regexp;
1568             }
1569              
1570 0         0 my @ranges = @{ $range_tr{$length} };
  182         574  
1571 182         446 while (my @range = splice(@ranges,0,$length)) {
1572 182         605 my $min = '';
1573 182         334 my $max = '';
1574 182         319 for (my $i=0; $i < $length; $i++) {
1575 182         479 $min .= pack 'C', $range[$i][0];
1576 182         773 $max .= pack 'C', $range[$i][-1];
1577             }
1578              
1579             # min___max
1580             # FIRST_____________LAST
1581             # (nothing)
1582              
1583 182 50 33     523 if ($max lt $first) {
    50 33        
    50 33        
    50 33        
    50 33        
    0 0        
    0 0        
1584             }
1585              
1586             # **********
1587             # min_________max
1588             # FIRST_____________LAST
1589             # **********
1590              
1591             elsif (($min le $first) and ($first le $max) and ($max le $last)) {
1592 182         2851 push @range_regexp, _octets($length,$first,$max,$min,$max);
1593             }
1594              
1595             # **********************
1596             # min________________max
1597             # FIRST_____________LAST
1598             # **********************
1599              
1600             elsif (($min eq $first) and ($max eq $last)) {
1601 0         0 push @range_regexp, _octets($length,$first,$last,$min,$max);
1602             }
1603              
1604             # *********
1605             # min___max
1606             # FIRST_____________LAST
1607             # *********
1608              
1609             elsif (($first le $min) and ($max le $last)) {
1610 0         0 push @range_regexp, _octets($length,$min,$max,$min,$max);
1611             }
1612              
1613             # **********************
1614             # min__________________________max
1615             # FIRST_____________LAST
1616             # **********************
1617              
1618             elsif (($min le $first) and ($last le $max)) {
1619 0         0 push @range_regexp, _octets($length,$first,$last,$min,$max);
1620             }
1621              
1622             # *********
1623             # min________max
1624             # FIRST_____________LAST
1625             # *********
1626              
1627             elsif (($first le $min) and ($min le $last) and ($last le $max)) {
1628 182         677 push @range_regexp, _octets($length,$min,$last,$min,$max);
1629             }
1630              
1631             # min___max
1632             # FIRST_____________LAST
1633             # (nothing)
1634              
1635             elsif ($last lt $min) {
1636             }
1637              
1638             else {
1639 0         0 die __FILE__, ": subroutine _range_regexp panic.\n";
1640             }
1641             }
1642              
1643 0         0 return @range_regexp;
1644             }
1645              
1646             #
1647             # Cyrillic open character list for qr and not qr
1648             #
1649             sub _charlist {
1650              
1651 182     358   448 my $modifier = pop @_;
1652 358         629 my @char = @_;
1653              
1654 358 100       965 my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
1655              
1656             # unescape character
1657 358         1166 for (my $i=0; $i <= $#char; $i++) {
1658              
1659             # escape - to ...
1660 358 100 100     1404 if ($char[$i] eq '-') {
    50          
    50          
    50          
    50          
    50          
    100          
    50          
    100          
    100          
    100          
    100          
1661 1125 100 100     10897 if ((0 < $i) and ($i < $#char)) {
1662 206         797 $char[$i] = '...';
1663             }
1664             }
1665              
1666             # octal escape sequence
1667             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
1668 182         505 $char[$i] = octchr($1);
1669             }
1670              
1671             # hexadecimal escape sequence
1672             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
1673 0         0 $char[$i] = hexchr($1);
1674             }
1675              
1676             # \b{...} --> b\{...}
1677             # \B{...} --> B\{...}
1678             # \N{CHARNAME} --> N\{CHARNAME}
1679             # \p{PROPERTY} --> p\{PROPERTY}
1680             # \P{PROPERTY} --> P\{PROPERTY}
1681             elsif ($char[$i] =~ /\A \\ ([bBNpP]) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
1682 0         0 $char[$i] = $1 . '\\' . $2;
1683             }
1684              
1685             # \p, \P, \X --> p, P, X
1686             elsif ($char[$i] =~ /\A \\ ( [pPX] ) \z/oxms) {
1687 0         0 $char[$i] = $1;
1688             }
1689              
1690             elsif ($char[$i] =~ /\A \\ ([0-7]{2,3}) \z/oxms) {
1691 0         0 $char[$i] = CORE::chr oct $1;
1692             }
1693             elsif ($char[$i] =~ /\A \\x ([0-9A-Fa-f]{1,2}) \z/oxms) {
1694 0         0 $char[$i] = CORE::chr hex $1;
1695             }
1696             elsif ($char[$i] =~ /\A \\c ([\x40-\x5F]) \z/oxms) {
1697 22         298 $char[$i] = CORE::chr(CORE::ord($1) & 0x1F);
1698             }
1699             elsif ($char[$i] =~ /\A (\\ [0nrtfbaedswDSWHVhvR]) \z/oxms) {
1700             $char[$i] = {
1701             '\0' => "\0",
1702             '\n' => "\n",
1703             '\r' => "\r",
1704             '\t' => "\t",
1705             '\f' => "\f",
1706             '\b' => "\x08", # \b means backspace in character class
1707             '\a' => "\a",
1708             '\e' => "\e",
1709             '\d' => '[0-9]',
1710              
1711             # Vertical tabs are now whitespace
1712             # \s in a regex now matches a vertical tab in all circumstances.
1713             # http://search.cpan.org/dist/perl-5.18.0/pod/perldelta.pod#Vertical_tabs_are_now_whitespace
1714             # \t \n \v \f \r space
1715             # '\s' => '[\x09\x0A \x0C\x0D\x20]',
1716             # '\s' => '[\x09\x0A\x0B\x0C\x0D\x20]',
1717             '\s' => '\s',
1718              
1719             '\w' => '[0-9A-Z_a-z]',
1720             '\D' => '${Ecyrillic::eD}',
1721             '\S' => '${Ecyrillic::eS}',
1722             '\W' => '${Ecyrillic::eW}',
1723              
1724             '\H' => '${Ecyrillic::eH}',
1725             '\V' => '${Ecyrillic::eV}',
1726             '\h' => '[\x09\x20]',
1727             '\v' => '[\x0A\x0B\x0C\x0D]',
1728             '\R' => '${Ecyrillic::eR}',
1729              
1730 0         0 }->{$1};
1731             }
1732              
1733             # POSIX-style character classes
1734             elsif ($ignorecase and ($char[$i] =~ /\A ( \[\: \^? (?:lower|upper) :\] ) \z/oxms)) {
1735             $char[$i] = {
1736              
1737             '[:lower:]' => '[\x41-\x5A\x61-\x7A]',
1738             '[:upper:]' => '[\x41-\x5A\x61-\x7A]',
1739             '[:^lower:]' => '${Ecyrillic::not_lower_i}',
1740             '[:^upper:]' => '${Ecyrillic::not_upper_i}',
1741              
1742 25         395 }->{$1};
1743             }
1744             elsif ($char[$i] =~ /\A ( \[\: \^? (?:alnum|alpha|ascii|blank|cntrl|digit|graph|lower|print|punct|space|upper|word|xdigit) :\] ) \z/oxms) {
1745             $char[$i] = {
1746              
1747             '[:alnum:]' => '[\x30-\x39\x41-\x5A\x61-\x7A]',
1748             '[:alpha:]' => '[\x41-\x5A\x61-\x7A]',
1749             '[:ascii:]' => '[\x00-\x7F]',
1750             '[:blank:]' => '[\x09\x20]',
1751             '[:cntrl:]' => '[\x00-\x1F\x7F]',
1752             '[:digit:]' => '[\x30-\x39]',
1753             '[:graph:]' => '[\x21-\x7F]',
1754             '[:lower:]' => '[\x61-\x7A]',
1755             '[:print:]' => '[\x20-\x7F]',
1756             '[:punct:]' => '[\x21-\x2F\x3A-\x3F\x40\x5B-\x5F\x60\x7B-\x7E]',
1757              
1758             # P.174 POSIX-Style Character Classes
1759             # in Chapter 5: Pattern Matching
1760             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
1761              
1762             # P.311 11.2.4 Character Classes and other Special Escapes
1763             # in Chapter 11: perlre: Perl regular expressions
1764             # of ISBN-13: 978-1-906966-02-7 The Perl Language Reference Manual (for Perl version 5.12.1)
1765              
1766             # P.210 POSIX-Style Character Classes
1767             # in Chapter 5: Pattern Matching
1768             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
1769              
1770             '[:space:]' => '[\s\x0B]', # "\s" plus vertical tab ("\cK")
1771              
1772             '[:upper:]' => '[\x41-\x5A]',
1773             '[:word:]' => '[\x30-\x39\x41-\x5A\x5F\x61-\x7A]',
1774             '[:xdigit:]' => '[\x30-\x39\x41-\x46\x61-\x66]',
1775             '[:^alnum:]' => '${Ecyrillic::not_alnum}',
1776             '[:^alpha:]' => '${Ecyrillic::not_alpha}',
1777             '[:^ascii:]' => '${Ecyrillic::not_ascii}',
1778             '[:^blank:]' => '${Ecyrillic::not_blank}',
1779             '[:^cntrl:]' => '${Ecyrillic::not_cntrl}',
1780             '[:^digit:]' => '${Ecyrillic::not_digit}',
1781             '[:^graph:]' => '${Ecyrillic::not_graph}',
1782             '[:^lower:]' => '${Ecyrillic::not_lower}',
1783             '[:^print:]' => '${Ecyrillic::not_print}',
1784             '[:^punct:]' => '${Ecyrillic::not_punct}',
1785             '[:^space:]' => '${Ecyrillic::not_space}',
1786             '[:^upper:]' => '${Ecyrillic::not_upper}',
1787             '[:^word:]' => '${Ecyrillic::not_word}',
1788             '[:^xdigit:]' => '${Ecyrillic::not_xdigit}',
1789              
1790 8         208 }->{$1};
1791             }
1792             elsif ($char[$i] =~ /\A \\ ($q_char) \z/oxms) {
1793 70         2706 $char[$i] = $1;
1794             }
1795             }
1796              
1797             # open character list
1798 7         35 my @singleoctet = ();
1799 358         683 my @multipleoctet = ();
1800 358         558 for (my $i=0; $i <= $#char; ) {
1801              
1802             # escaped -
1803 358 100 100     1350 if (defined($char[$i+1]) and ($char[$i+1] eq '...')) {
    100          
    100          
    50          
    50          
    100          
1804 943         5974 $i += 1;
1805 182         547 next;
1806             }
1807              
1808             # make range regexp
1809             elsif ($char[$i] eq '...') {
1810              
1811             # range error
1812 182 50       564 if (CORE::length($char[$i-1]) > CORE::length($char[$i+1])) {
    50          
1813 182         784 croak 'Invalid [] range in regexp (length(A) > length(B)) ' . '\x' . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]);
1814             }
1815             elsif (CORE::length($char[$i-1]) == CORE::length($char[$i+1])) {
1816 0 50       0 if ($char[$i-1] gt $char[$i+1]) {
1817 182         948 croak 'Invalid [] range in regexp (CORE::ord(A) > CORE::ord(B)) ' . '\x' . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]);
1818             }
1819             }
1820              
1821             # make range regexp per length
1822 0         0 for my $length (CORE::length($char[$i-1]) .. CORE::length($char[$i+1])) {
1823 182         558 my @regexp = ();
1824              
1825             # is first and last
1826 182 50 33     270 if (($length == CORE::length($char[$i-1])) and ($length == CORE::length($char[$i+1]))) {
    0 0        
    0          
    0          
1827 182         680 push @regexp, _range_regexp($length, $char[$i-1], $char[$i+1]);
1828             }
1829              
1830             # is first
1831             elsif ($length == CORE::length($char[$i-1])) {
1832 182         762 push @regexp, _range_regexp($length, $char[$i-1], "\xFF" x $length);
1833             }
1834              
1835             # is inside in first and last
1836             elsif ((CORE::length($char[$i-1]) < $length) and ($length < CORE::length($char[$i+1]))) {
1837 0         0 push @regexp, _range_regexp($length, "\x00" x $length, "\xFF" x $length);
1838             }
1839              
1840             # is last
1841             elsif ($length == CORE::length($char[$i+1])) {
1842 0         0 push @regexp, _range_regexp($length, "\x00" x $length, $char[$i+1]);
1843             }
1844              
1845             else {
1846 0         0 die __FILE__, ": subroutine make_regexp panic.\n";
1847             }
1848              
1849 0 50       0 if ($length == 1) {
1850 182         495 push @singleoctet, @regexp;
1851             }
1852             else {
1853 182         430 push @multipleoctet, @regexp;
1854             }
1855             }
1856              
1857 0         0 $i += 2;
1858             }
1859              
1860             # with /i modifier
1861             elsif ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) {
1862 182 100       524 if ($modifier =~ /i/oxms) {
1863 493         993 my $uc = Ecyrillic::uc($char[$i]);
1864 24         54 my $fc = Ecyrillic::fc($char[$i]);
1865 24 100       46 if ($uc ne $fc) {
1866 24 50       50 if (CORE::length($fc) == 1) {
1867 12         27 push @singleoctet, $uc, $fc;
1868             }
1869             else {
1870 12         30 push @singleoctet, $uc;
1871 0         0 push @multipleoctet, $fc;
1872             }
1873             }
1874             else {
1875 0         0 push @singleoctet, $char[$i];
1876             }
1877             }
1878             else {
1879 12         25 push @singleoctet, $char[$i];
1880             }
1881 469         682 $i += 1;
1882             }
1883              
1884             # single character of single octet code
1885             elsif ($char[$i] =~ /\A (?: \\h ) \z/oxms) {
1886 493         818 push @singleoctet, "\t", "\x20";
1887 0         0 $i += 1;
1888             }
1889             elsif ($char[$i] =~ /\A (?: \\v ) \z/oxms) {
1890 0         0 push @singleoctet, "\x0A", "\x0B", "\x0C", "\x0D";
1891 0         0 $i += 1;
1892             }
1893             elsif ($char[$i] =~ /\A (?: \\d | \\s | \\w ) \z/oxms) {
1894 0         0 push @singleoctet, $char[$i];
1895 2         4 $i += 1;
1896             }
1897              
1898             # single character of multiple-octet code
1899             else {
1900 2         6 push @multipleoctet, $char[$i];
1901 84         254 $i += 1;
1902             }
1903             }
1904              
1905             # quote metachar
1906 84         162 for (@singleoctet) {
1907 358 50       1532 if ($_ eq '...') {
    100          
    100          
    100          
    100          
1908 689         3137 $_ = '-';
1909             }
1910             elsif (/\A \n \z/oxms) {
1911 0         0 $_ = '\n';
1912             }
1913             elsif (/\A \r \z/oxms) {
1914 8         20 $_ = '\r';
1915             }
1916             elsif (/\A ([\x00-\x20\x7F-\xFF]) \z/oxms) {
1917 8         23 $_ = sprintf('\x%02X', CORE::ord $1);
1918             }
1919             elsif (/\A [\x00-\xFF] \z/oxms) {
1920 60         235 $_ = quotemeta $_;
1921             }
1922             }
1923              
1924             # return character list
1925 429         676 return \@singleoctet, \@multipleoctet;
1926             }
1927              
1928             #
1929             # Cyrillic octal escape sequence
1930             #
1931             sub octchr {
1932 358     5 0 3854 my($octdigit) = @_;
1933              
1934 5         17 my @binary = ();
1935 5         10 for my $octal (split(//,$octdigit)) {
1936             push @binary, {
1937             '0' => '000',
1938             '1' => '001',
1939             '2' => '010',
1940             '3' => '011',
1941             '4' => '100',
1942             '5' => '101',
1943             '6' => '110',
1944             '7' => '111',
1945 5         26 }->{$octal};
1946             }
1947 50         188 my $binary = join '', @binary;
1948              
1949             my $octchr = {
1950             # 1234567
1951             1 => pack('B*', "0000000$binary"),
1952             2 => pack('B*', "000000$binary"),
1953             3 => pack('B*', "00000$binary"),
1954             4 => pack('B*', "0000$binary"),
1955             5 => pack('B*', "000$binary"),
1956             6 => pack('B*', "00$binary"),
1957             7 => pack('B*', "0$binary"),
1958             0 => pack('B*', "$binary"),
1959              
1960 5         16 }->{CORE::length($binary) % 8};
1961              
1962 5         85 return $octchr;
1963             }
1964              
1965             #
1966             # Cyrillic hexadecimal escape sequence
1967             #
1968             sub hexchr {
1969 5     5 0 22 my($hexdigit) = @_;
1970              
1971             my $hexchr = {
1972             1 => pack('H*', "0$hexdigit"),
1973             0 => pack('H*', "$hexdigit"),
1974              
1975 5         15 }->{CORE::length($_[0]) % 2};
1976              
1977 5         42 return $hexchr;
1978             }
1979              
1980             #
1981             # Cyrillic open character list for qr
1982             #
1983             sub charlist_qr {
1984              
1985 5     314 0 18 my $modifier = pop @_;
1986 314         671 my @char = @_;
1987              
1988 314         1097 my($singleoctet, $multipleoctet) = _charlist(@char, $modifier);
1989 314         1318 my @singleoctet = @$singleoctet;
1990 314         819 my @multipleoctet = @$multipleoctet;
1991              
1992             # return character list
1993 314 100       656 if (scalar(@singleoctet) >= 1) {
1994              
1995             # with /i modifier
1996 314 100       979 if ($modifier =~ m/i/oxms) {
1997 236         585 my %singleoctet_ignorecase = ();
1998 22         38 for (@singleoctet) {
1999 22   100     51 while (s/ \A \\x(..) - \\x(..) //oxms or s/ \A \\x((..)) //oxms) {
2000 46         210 for my $ord (hex($1) .. hex($2)) {
2001 46         143 my $char = CORE::chr($ord);
2002 66         107 my $uc = Ecyrillic::uc($char);
2003 66         274 my $fc = Ecyrillic::fc($char);
2004 66 100       173 if ($uc eq $fc) {
2005 66         118 $singleoctet_ignorecase{unpack 'C*', $char} = 1;
2006             }
2007             else {
2008 12 50       79 if (CORE::length($fc) == 1) {
2009 54         82 $singleoctet_ignorecase{unpack 'C*', $uc} = 1;
2010 54         125 $singleoctet_ignorecase{unpack 'C*', $fc} = 1;
2011             }
2012             else {
2013 54         197 $singleoctet_ignorecase{unpack 'C*', $uc} = 1;
2014 0         0 push @multipleoctet, join '', map {sprintf('\x%02X',$_)} unpack 'C*', $fc;
  0         0  
2015             }
2016             }
2017             }
2018             }
2019 0 50       0 if ($_ ne '') {
2020 46         100 $singleoctet_ignorecase{unpack 'C*', $_} = 1;
2021             }
2022             }
2023 0         0 my $i = 0;
2024 22         24 my @singleoctet_ignorecase = ();
2025 22         40 for my $ord (0 .. 255) {
2026 22 100       39 if (exists $singleoctet_ignorecase{$ord}) {
2027 5632         7577 push @{$singleoctet_ignorecase[$i]}, $ord;
  96         97  
2028             }
2029             else {
2030 96         256 $i++;
2031             }
2032             }
2033 5536         6485 @singleoctet = ();
2034 22         43 for my $range (@singleoctet_ignorecase) {
2035 22 100       69 if (ref $range) {
2036 3648 100       6558 if (scalar(@{$range}) == 1) {
  56 50       105  
2037 56         168 push @singleoctet, sprintf('\x%02X', @{$range}[0]);
  36         88  
2038             }
2039 36         223 elsif (scalar(@{$range}) == 2) {
2040 20         27 push @singleoctet, sprintf('\x%02X\x%02X', @{$range}[0], @{$range}[-1]);
  0         0  
  0         0  
2041             }
2042             else {
2043 0         0 push @singleoctet, sprintf('\x%02X-\x%02X', @{$range}[0], @{$range}[-1]);
  20         22  
  20         23  
2044             }
2045             }
2046             }
2047             }
2048              
2049 20         103 my $not_anchor = '';
2050              
2051 236         379 push @multipleoctet, join('', $not_anchor, '[', @singleoctet, ']' );
2052             }
2053 236 100       661 if (scalar(@multipleoctet) >= 2) {
2054 314         838 return '(?:' . join('|', @multipleoctet) . ')';
2055             }
2056             else {
2057 6         33 return $multipleoctet[0];
2058             }
2059             }
2060              
2061             #
2062             # Cyrillic open character list for not qr
2063             #
2064             sub charlist_not_qr {
2065              
2066 308     44 0 1782 my $modifier = pop @_;
2067 44         146 my @char = @_;
2068              
2069 44         113 my($singleoctet, $multipleoctet) = _charlist(@char, $modifier);
2070 44         153 my @singleoctet = @$singleoctet;
2071 44         148 my @multipleoctet = @$multipleoctet;
2072              
2073             # with /i modifier
2074 44 100       67 if ($modifier =~ m/i/oxms) {
2075 44         178 my %singleoctet_ignorecase = ();
2076 10         17 for (@singleoctet) {
2077 10   66     15 while (s/ \A \\x(..) - \\x(..) //oxms or s/ \A \\x((..)) //oxms) {
2078 10         113 for my $ord (hex($1) .. hex($2)) {
2079 10         42 my $char = CORE::chr($ord);
2080 30         52 my $uc = Ecyrillic::uc($char);
2081 30         50 my $fc = Ecyrillic::fc($char);
2082 30 50       54 if ($uc eq $fc) {
2083 30         58 $singleoctet_ignorecase{unpack 'C*', $char} = 1;
2084             }
2085             else {
2086 0 50       0 if (CORE::length($fc) == 1) {
2087 30         37 $singleoctet_ignorecase{unpack 'C*', $uc} = 1;
2088 30         66 $singleoctet_ignorecase{unpack 'C*', $fc} = 1;
2089             }
2090             else {
2091 30         99 $singleoctet_ignorecase{unpack 'C*', $uc} = 1;
2092 0         0 push @multipleoctet, join '', map {sprintf('\x%02X',$_)} unpack 'C*', $fc;
  0         0  
2093             }
2094             }
2095             }
2096             }
2097 0 50       0 if ($_ ne '') {
2098 10         25 $singleoctet_ignorecase{unpack 'C*', $_} = 1;
2099             }
2100             }
2101 0         0 my $i = 0;
2102 10         12 my @singleoctet_ignorecase = ();
2103 10         13 for my $ord (0 .. 255) {
2104 10 100       19 if (exists $singleoctet_ignorecase{$ord}) {
2105 2560         3192 push @{$singleoctet_ignorecase[$i]}, $ord;
  60         151  
2106             }
2107             else {
2108 60         110 $i++;
2109             }
2110             }
2111 2500         3027 @singleoctet = ();
2112 10         22 for my $range (@singleoctet_ignorecase) {
2113 10 100       29 if (ref $range) {
2114 960 50       1897 if (scalar(@{$range}) == 1) {
  20 50       19  
2115 20         44 push @singleoctet, sprintf('\x%02X', @{$range}[0]);
  0         0  
2116             }
2117 0         0 elsif (scalar(@{$range}) == 2) {
2118 20         26 push @singleoctet, sprintf('\x%02X\x%02X', @{$range}[0], @{$range}[-1]);
  0         0  
  0         0  
2119             }
2120             else {
2121 0         0 push @singleoctet, sprintf('\x%02X-\x%02X', @{$range}[0], @{$range}[-1]);
  20         116  
  20         29  
2122             }
2123             }
2124             }
2125             }
2126              
2127             # return character list
2128 20 50       148 if (scalar(@multipleoctet) >= 1) {
2129 44 0       179 if (scalar(@singleoctet) >= 1) {
2130              
2131             # any character other than multiple-octet and single octet character class
2132 0         0 return '(?!' . join('|', @multipleoctet) . ')(?:[^' . join('', @singleoctet) . '])';
2133             }
2134             else {
2135              
2136             # any character other than multiple-octet character class
2137 0         0 return '(?!' . join('|', @multipleoctet) . ")(?:$your_char)";
2138             }
2139             }
2140             else {
2141 0 50       0 if (scalar(@singleoctet) >= 1) {
2142              
2143             # any character other than single octet character class
2144 44         116 return '(?:[^' . join('', @singleoctet) . '])';
2145             }
2146             else {
2147              
2148             # any character
2149 44         311 return "(?:$your_char)";
2150             }
2151             }
2152             }
2153              
2154             #
2155             # open file in read mode
2156             #
2157             sub _open_r {
2158 0     408   0 my(undef,$file) = @_;
2159 204     204   3578 use Fcntl qw(O_RDONLY);
  204         577  
  204         32287  
2160 408         1253 return CORE::sysopen($_[0], $file, &O_RDONLY);
2161             }
2162              
2163             #
2164             # open file in append mode
2165             #
2166             sub _open_a {
2167 408     204   18545 my(undef,$file) = @_;
2168 204     204   1630 use Fcntl qw(O_WRONLY O_APPEND O_CREAT);
  204         535  
  204         742596  
2169 204         637 return CORE::sysopen($_[0], $file, &O_WRONLY|&O_APPEND|&O_CREAT);
2170             }
2171              
2172             #
2173             # safe system
2174             #
2175             sub _systemx {
2176              
2177             # P.707 29.2.33. exec
2178             # in Chapter 29: Functions
2179             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
2180             #
2181             # Be aware that in older releases of Perl, exec (and system) did not flush
2182             # your output buffer, so you needed to enable command buffering by setting $|
2183             # on one or more filehandles to avoid lost output in the case of exec, or
2184             # misordererd output in the case of system. This situation was largely remedied
2185             # in the 5.6 release of Perl. (So, 5.005 release not yet.)
2186              
2187             # P.855 exec
2188             # in Chapter 27: Functions
2189             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
2190             #
2191             # In very old release of Perl (before v5.6), 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 with exec or misordered
2194             # output with system.
2195              
2196 204     204   46115 $| = 1;
2197              
2198             # P.565 23.1.2. Cleaning Up Your Environment
2199             # in Chapter 23: Security
2200             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
2201              
2202             # P.656 Cleaning Up Your Environment
2203             # in Chapter 20: Security
2204             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
2205              
2206             # local $ENV{'PATH'} = '.';
2207 204         1664 local @ENV{qw(IFS CDPATH ENV BASH_ENV)}; # Make %ENV safer
2208              
2209             # P.707 29.2.33. exec
2210             # in Chapter 29: Functions
2211             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
2212             #
2213             # As we mentioned earlier, exec treats a discrete list of arguments as an
2214             # indication that it should bypass shell processing. However, there is one
2215             # place where you might still get tripped up. The exec call (and system, too)
2216             # will not distinguish between a single scalar argument and an array containing
2217             # only one element.
2218             #
2219             # @args = ("echo surprise"); # just one element in list
2220             # exec @args # still subject to shell escapes
2221             # or die "exec: $!"; # because @args == 1
2222             #
2223             # To avoid this, you can use the PATHNAME syntax, explicitly duplicating the
2224             # first argument as the pathname, which forces the rest of the arguments to be
2225             # interpreted as a list, even if there is only one of them:
2226             #
2227             # exec { $args[0] } @args # safe even with one-argument list
2228             # or die "can't exec @args: $!";
2229              
2230             # P.855 exec
2231             # in Chapter 27: Functions
2232             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
2233             #
2234             # As we mentioned earlier, exec treats a discrete list of arguments as a
2235             # directive to bypass shell processing. However, there is one place where
2236             # you might still get tripped up. The exec call (and system, too) cannot
2237             # distinguish between a single scalar argument and an array containing
2238             # only one element.
2239             #
2240             # @args = ("echo surprise"); # just one element in list
2241             # exec @args # still subject to shell escapes
2242             # || die "exec: $!"; # because @args == 1
2243             #
2244             # To avoid this, use the PATHNAME syntax, explicitly duplicating the first
2245             # argument as the pathname, which forces the rest of the arguments to be
2246             # interpreted as a list, even if there is only one of them:
2247             #
2248             # exec { $args[0] } @args # safe even with one-argument list
2249             # || die "can't exec @args: $!";
2250              
2251 204         1991 return CORE::system { $_[0] } @_; # safe even with one-argument list
  204         439  
2252             }
2253              
2254             #
2255             # Cyrillic order to character (with parameter)
2256             #
2257             sub Ecyrillic::chr(;$) {
2258              
2259 204 0   0 0 22176977 my $c = @_ ? $_[0] : $_;
2260              
2261 0 0       0 if ($c == 0x00) {
2262 0         0 return "\x00";
2263             }
2264             else {
2265 0         0 my @chr = ();
2266 0         0 while ($c > 0) {
2267 0         0 unshift @chr, ($c % 0x100);
2268 0         0 $c = int($c / 0x100);
2269             }
2270 0         0 return pack 'C*', @chr;
2271             }
2272             }
2273              
2274             #
2275             # Cyrillic order to character (without parameter)
2276             #
2277             sub Ecyrillic::chr_() {
2278              
2279 0     0 0 0 my $c = $_;
2280              
2281 0 0       0 if ($c == 0x00) {
2282 0         0 return "\x00";
2283             }
2284             else {
2285 0         0 my @chr = ();
2286 0         0 while ($c > 0) {
2287 0         0 unshift @chr, ($c % 0x100);
2288 0         0 $c = int($c / 0x100);
2289             }
2290 0         0 return pack 'C*', @chr;
2291             }
2292             }
2293              
2294             #
2295             # Cyrillic path globbing (with parameter)
2296             #
2297             sub Ecyrillic::glob($) {
2298              
2299 0 0   0 0 0 if (wantarray) {
2300 0         0 my @glob = _DOS_like_glob(@_);
2301 0         0 for my $glob (@glob) {
2302 0         0 $glob =~ s{ \A (?:\./)+ }{}oxms;
2303             }
2304 0         0 return @glob;
2305             }
2306             else {
2307 0         0 my $glob = _DOS_like_glob(@_);
2308 0         0 $glob =~ s{ \A (?:\./)+ }{}oxms;
2309 0         0 return $glob;
2310             }
2311             }
2312              
2313             #
2314             # Cyrillic path globbing (without parameter)
2315             #
2316             sub Ecyrillic::glob_() {
2317              
2318 0 0   0 0 0 if (wantarray) {
2319 0         0 my @glob = _DOS_like_glob();
2320 0         0 for my $glob (@glob) {
2321 0         0 $glob =~ s{ \A (?:\./)+ }{}oxms;
2322             }
2323 0         0 return @glob;
2324             }
2325             else {
2326 0         0 my $glob = _DOS_like_glob();
2327 0         0 $glob =~ s{ \A (?:\./)+ }{}oxms;
2328 0         0 return $glob;
2329             }
2330             }
2331              
2332             #
2333             # Cyrillic path globbing via File::DosGlob 1.10
2334             #
2335             # Often I confuse "_dosglob" and "_doglob".
2336             # So, I renamed "_dosglob" to "_DOS_like_glob".
2337             #
2338             my %iter;
2339             my %entries;
2340             sub _DOS_like_glob {
2341              
2342             # context (keyed by second cxix argument provided by core)
2343 0     0   0 my($expr,$cxix) = @_;
2344              
2345             # glob without args defaults to $_
2346 0 0       0 $expr = $_ if not defined $expr;
2347              
2348             # represents the current user's home directory
2349             #
2350             # 7.3. Expanding Tildes in Filenames
2351             # in Chapter 7. File Access
2352             # of ISBN 0-596-00313-7 Perl Cookbook, 2nd Edition.
2353             #
2354             # and File::HomeDir, File::HomeDir::Windows module
2355              
2356             # DOS-like system
2357 0 0       0 if ($^O =~ /\A (?: MSWin32 | NetWare | symbian | dos ) \z/oxms) {
2358 0         0 $expr =~ s{ \A ~ (?= [^/\\] ) }
  0         0  
2359             { my_home_MSWin32() }oxmse;
2360             }
2361              
2362             # UNIX-like system
2363 0 0 0     0 else {
  0         0  
2364             $expr =~ s{ \A ~ ( (?:[^/])* ) }
2365             { $1 ? (CORE::eval(q{(getpwnam($1))[7]})||my_home()) : my_home() }oxmse;
2366             }
2367 0 0       0  
2368 0 0       0 # assume global context if not provided one
2369             $cxix = '_G_' if not defined $cxix;
2370             $iter{$cxix} = 0 if not exists $iter{$cxix};
2371 0 0       0  
2372 0         0 # if we're just beginning, do it all first
2373             if ($iter{$cxix} == 0) {
2374             $entries{$cxix} = [ _do_glob(1, _parse_line($expr)) ];
2375             }
2376 0 0       0  
2377 0         0 # chuck it all out, quick or slow
2378 0         0 if (wantarray) {
  0         0  
2379             delete $iter{$cxix};
2380             return @{delete $entries{$cxix}};
2381 0 0       0 }
  0         0  
2382 0         0 else {
  0         0  
2383             if ($iter{$cxix} = scalar @{$entries{$cxix}}) {
2384             return shift @{$entries{$cxix}};
2385             }
2386 0         0 else {
2387 0         0 # return undef for EOL
2388 0         0 delete $iter{$cxix};
2389             delete $entries{$cxix};
2390             return undef;
2391             }
2392             }
2393             }
2394              
2395             #
2396             # Cyrillic path globbing subroutine
2397             #
2398 0     0   0 sub _do_glob {
2399 0         0  
2400 0         0 my($cond,@expr) = @_;
2401             my @glob = ();
2402             my $fix_drive_relative_paths = 0;
2403 0         0  
2404 0 0       0 OUTER:
2405 0 0       0 for my $expr (@expr) {
2406             next OUTER if not defined $expr;
2407 0         0 next OUTER if $expr eq '';
2408 0         0  
2409 0         0 my @matched = ();
2410 0         0 my @globdir = ();
2411 0         0 my $head = '.';
2412             my $pathsep = '/';
2413             my $tail;
2414 0 0       0  
2415 0         0 # if argument is within quotes strip em and do no globbing
2416 0 0       0 if ($expr =~ /\A " ((?:$q_char)*?) " \z/oxms) {
2417 0 0       0 $expr = $1;
2418 0         0 if ($cond eq 'd') {
2419             if (-d $expr) {
2420             push @glob, $expr;
2421             }
2422 0 0       0 }
2423 0         0 else {
2424             if (-e $expr) {
2425             push @glob, $expr;
2426 0         0 }
2427             }
2428             next OUTER;
2429             }
2430              
2431 0 0       0 # wildcards with a drive prefix such as h:*.pm must be changed
2432 0 0       0 # to h:./*.pm to expand correctly
2433 0         0 if ($^O =~ /\A (?: MSWin32 | NetWare | symbian | dos ) \z/oxms) {
2434             if ($expr =~ s# \A ((?:[A-Za-z]:)?) ([^/\\]) #$1./$2#oxms) {
2435             $fix_drive_relative_paths = 1;
2436             }
2437 0 0       0 }
2438 0 0       0  
2439 0         0 if (($head, $tail) = _parse_path($expr,$pathsep)) {
2440 0         0 if ($tail eq '') {
2441             push @glob, $expr;
2442 0 0       0 next OUTER;
2443 0 0       0 }
2444 0         0 if ($head =~ / \A (?:$q_char)*? [*?] /oxms) {
  0         0  
2445 0         0 if (@globdir = _do_glob('d', $head)) {
2446             push @glob, _do_glob($cond, map {"$_$pathsep$tail"} @globdir);
2447             next OUTER;
2448 0 0 0     0 }
2449 0         0 }
2450             if ($head eq '' or $head =~ /\A [A-Za-z]: \z/oxms) {
2451 0         0 $head .= $pathsep;
2452             }
2453             $expr = $tail;
2454             }
2455 0 0       0  
2456 0 0       0 # If file component has no wildcards, we can avoid opendir
2457 0         0 if ($expr !~ / \A (?:$q_char)*? [*?] /oxms) {
2458             if ($head eq '.') {
2459 0 0 0     0 $head = '';
2460 0         0 }
2461             if ($head ne '' and ($head =~ / \G ($q_char) /oxmsg)[-1] ne $pathsep) {
2462 0         0 $head .= $pathsep;
2463 0 0       0 }
2464 0 0       0 $head .= $expr;
2465 0         0 if ($cond eq 'd') {
2466             if (-d $head) {
2467             push @glob, $head;
2468             }
2469 0 0       0 }
2470 0         0 else {
2471             if (-e $head) {
2472             push @glob, $head;
2473 0         0 }
2474             }
2475 0 0       0 next OUTER;
2476 0         0 }
2477 0         0 opendir(*DIR, $head) or next OUTER;
2478             my @leaf = readdir DIR;
2479 0 0       0 closedir DIR;
2480 0         0  
2481             if ($head eq '.') {
2482 0 0 0     0 $head = '';
2483 0         0 }
2484             if ($head ne '' and ($head =~ / \G ($q_char) /oxmsg)[-1] ne $pathsep) {
2485             $head .= $pathsep;
2486 0         0 }
2487 0         0  
2488 0         0 my $pattern = '';
2489             while ($expr =~ / \G ($q_char) /oxgc) {
2490             my $char = $1;
2491              
2492             # 6.9. Matching Shell Globs as Regular Expressions
2493             # in Chapter 6. Pattern Matching
2494             # of ISBN 0-596-00313-7 Perl Cookbook, 2nd Edition.
2495 0 0       0 # (and so on)
    0          
    0          
2496 0         0  
2497             if ($char eq '*') {
2498             $pattern .= "(?:$your_char)*",
2499 0         0 }
2500             elsif ($char eq '?') {
2501             $pattern .= "(?:$your_char)?", # DOS style
2502             # $pattern .= "(?:$your_char)", # UNIX style
2503 0         0 }
2504             elsif ((my $fc = Ecyrillic::fc($char)) ne $char) {
2505             $pattern .= $fc;
2506 0         0 }
2507             else {
2508             $pattern .= quotemeta $char;
2509 0     0   0 }
  0         0  
2510             }
2511             my $matchsub = sub { Ecyrillic::fc($_[0]) =~ /\A $pattern \z/xms };
2512              
2513             # if ($@) {
2514             # print STDERR "$0: $@\n";
2515             # next OUTER;
2516             # }
2517 0         0  
2518 0 0 0     0 INNER:
2519 0         0 for my $leaf (@leaf) {
2520             if ($leaf eq '.' or $leaf eq '..') {
2521 0 0 0     0 next INNER;
2522 0         0 }
2523             if ($cond eq 'd' and not -d "$head$leaf") {
2524             next INNER;
2525 0 0       0 }
2526 0         0  
2527 0         0 if (&$matchsub($leaf)) {
2528             push @matched, "$head$leaf";
2529             next INNER;
2530             }
2531              
2532             # [DOS compatibility special case]
2533 0 0 0     0 # Failed, add a trailing dot and try again, but only...
      0        
2534              
2535             if (Ecyrillic::index($leaf,'.') == -1 and # if name does not have a dot in it *and*
2536             CORE::length($leaf) <= 8 and # name is shorter than or equal to 8 chars *and*
2537 0 0       0 Ecyrillic::index($pattern,'\\.') != -1 # pattern has a dot.
2538 0         0 ) {
2539 0         0 if (&$matchsub("$leaf.")) {
2540             push @matched, "$head$leaf";
2541             next INNER;
2542             }
2543 0 0       0 }
2544 0         0 }
2545             if (@matched) {
2546             push @glob, @matched;
2547 0 0       0 }
2548 0         0 }
2549 0         0 if ($fix_drive_relative_paths) {
2550             for my $glob (@glob) {
2551             $glob =~ s# \A ([A-Za-z]:) \./ #$1#oxms;
2552 0         0 }
2553             }
2554             return @glob;
2555             }
2556              
2557             #
2558             # Cyrillic parse line
2559             #
2560 0     0   0 sub _parse_line {
2561              
2562 0         0 my($line) = @_;
2563 0         0  
2564 0         0 $line .= ' ';
2565             my @piece = ();
2566             while ($line =~ /
2567             " ( (?>(?: [^"] )* ) ) " (?>\s+) |
2568             ( (?>(?: [^"\s] )* ) ) (?>\s+)
2569 0 0       0 /oxmsg
2570             ) {
2571 0         0 push @piece, defined($1) ? $1 : $2;
2572             }
2573             return @piece;
2574             }
2575              
2576             #
2577             # Cyrillic parse path
2578             #
2579 0     0   0 sub _parse_path {
2580              
2581 0         0 my($path,$pathsep) = @_;
2582 0         0  
2583 0         0 $path .= '/';
2584             my @subpath = ();
2585             while ($path =~ /
2586             ((?: [^\/\\] )+?) [\/\\]
2587 0         0 /oxmsg
2588             ) {
2589             push @subpath, $1;
2590 0         0 }
2591 0         0  
2592 0         0 my $tail = pop @subpath;
2593             my $head = join $pathsep, @subpath;
2594             return $head, $tail;
2595             }
2596              
2597             #
2598             # via File::HomeDir::Windows 1.00
2599             #
2600             sub my_home_MSWin32 {
2601              
2602             # A lot of unix people and unix-derived tools rely on
2603 0 0 0 0 0 0 # the ability to overload HOME. We will support it too
    0 0        
    0 0        
      0        
      0        
2604 0         0 # so that they can replace raw HOME calls with File::HomeDir.
2605             if (exists $ENV{'HOME'} and $ENV{'HOME'}) {
2606             return $ENV{'HOME'};
2607             }
2608              
2609 0         0 # Do we have a user profile?
2610             elsif (exists $ENV{'USERPROFILE'} and $ENV{'USERPROFILE'}) {
2611             return $ENV{'USERPROFILE'};
2612             }
2613              
2614 0         0 # Some Windows use something like $ENV{'HOME'}
2615             elsif (exists $ENV{'HOMEDRIVE'} and exists $ENV{'HOMEPATH'} and $ENV{'HOMEDRIVE'} and $ENV{'HOMEPATH'}) {
2616             return join '', $ENV{'HOMEDRIVE'}, $ENV{'HOMEPATH'};
2617 0         0 }
2618              
2619             return undef;
2620             }
2621              
2622             #
2623             # via File::HomeDir::Unix 1.00
2624 0     0 0 0 #
2625             sub my_home {
2626 0 0 0     0 my $home;
    0 0        
2627 0         0  
2628             if (exists $ENV{'HOME'} and defined $ENV{'HOME'}) {
2629             $home = $ENV{'HOME'};
2630             }
2631              
2632             # This is from the original code, but I'm guessing
2633 0         0 # it means "login directory" and exists on some Unixes.
2634             elsif (exists $ENV{'LOGDIR'} and $ENV{'LOGDIR'}) {
2635             $home = $ENV{'LOGDIR'};
2636             }
2637              
2638             ### More-desperate methods
2639              
2640 0         0 # Light desperation on any (Unixish) platform
2641             else {
2642             $home = CORE::eval q{ (getpwuid($<))[7] };
2643             }
2644              
2645 0 0 0     0 # On Unix in general, a non-existant home means "no home"
2646 0         0 # For example, "nobody"-like users might use /nonexistant
2647             if (defined $home and ! -d($home)) {
2648 0         0 $home = undef;
2649             }
2650             return $home;
2651             }
2652              
2653             #
2654             # ${^PREMATCH}, $PREMATCH, $` the string preceding what was matched
2655 0     0 0 0 #
2656             sub Ecyrillic::PREMATCH {
2657             return $`;
2658             }
2659              
2660             #
2661             # ${^MATCH}, $MATCH, $& the string that matched
2662 0     0 0 0 #
2663             sub Ecyrillic::MATCH {
2664             return $&;
2665             }
2666              
2667             #
2668             # ${^POSTMATCH}, $POSTMATCH, $' the string following what was matched
2669 0     0 0 0 #
2670             sub Ecyrillic::POSTMATCH {
2671             return $';
2672             }
2673              
2674             #
2675             # Cyrillic character to order (with parameter)
2676             #
2677 0 0   0 1 0 sub Cyrillic::ord(;$) {
2678              
2679 0 0       0 local $_ = shift if @_;
2680 0         0  
2681 0         0 if (/\A ($q_char) /oxms) {
2682 0         0 my @ord = unpack 'C*', $1;
2683 0         0 my $ord = 0;
2684             while (my $o = shift @ord) {
2685 0         0 $ord = $ord * 0x100 + $o;
2686             }
2687             return $ord;
2688 0         0 }
2689             else {
2690             return CORE::ord $_;
2691             }
2692             }
2693              
2694             #
2695             # Cyrillic character to order (without parameter)
2696             #
2697 0 0   0 0 0 sub Cyrillic::ord_() {
2698 0         0  
2699 0         0 if (/\A ($q_char) /oxms) {
2700 0         0 my @ord = unpack 'C*', $1;
2701 0         0 my $ord = 0;
2702             while (my $o = shift @ord) {
2703 0         0 $ord = $ord * 0x100 + $o;
2704             }
2705             return $ord;
2706 0         0 }
2707             else {
2708             return CORE::ord $_;
2709             }
2710             }
2711              
2712             #
2713             # Cyrillic reverse
2714             #
2715 0 0   0 0 0 sub Cyrillic::reverse(@) {
2716 0         0  
2717             if (wantarray) {
2718             return CORE::reverse @_;
2719             }
2720             else {
2721              
2722             # One of us once cornered Larry in an elevator and asked him what
2723             # problem he was solving with this, but he looked as far off into
2724             # the distance as he could in an elevator and said, "It seemed like
2725 0         0 # a good idea at the time."
2726              
2727             return join '', CORE::reverse(join('',@_) =~ /\G ($q_char) /oxmsg);
2728             }
2729             }
2730              
2731             #
2732             # Cyrillic getc (with parameter, without parameter)
2733             #
2734 0     0 0 0 sub Cyrillic::getc(;*@) {
2735 0 0       0  
2736 0 0 0     0 my($package) = caller;
2737             my $fh = @_ ? qualify_to_ref(shift,$package) : \*STDIN;
2738 0         0 croak 'Too many arguments for Cyrillic::getc' if @_ and not wantarray;
  0         0  
2739 0         0  
2740 0         0 my @length = sort { $a <=> $b } keys %range_tr;
2741 0         0 my $getc = '';
2742 0 0       0 for my $length ($length[0] .. $length[-1]) {
2743 0 0       0 $getc .= CORE::getc($fh);
2744 0 0       0 if (exists $range_tr{CORE::length($getc)}) {
2745             if ($getc =~ /\A ${Ecyrillic::dot_s} \z/oxms) {
2746             return wantarray ? ($getc,@_) : $getc;
2747             }
2748 0 0       0 }
2749             }
2750             return wantarray ? ($getc,@_) : $getc;
2751             }
2752              
2753             #
2754             # Cyrillic length by character
2755             #
2756 0 0   0 1 0 sub Cyrillic::length(;$) {
2757              
2758 0         0 local $_ = shift if @_;
2759 0         0  
2760             local @_ = /\G ($q_char) /oxmsg;
2761             return scalar @_;
2762             }
2763              
2764             #
2765             # Cyrillic substr by character
2766             #
2767             BEGIN {
2768              
2769             # P.232 The lvalue Attribute
2770             # in Chapter 6: Subroutines
2771             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
2772              
2773             # P.336 The lvalue Attribute
2774             # in Chapter 7: Subroutines
2775             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
2776              
2777             # P.144 8.4 Lvalue subroutines
2778             # in Chapter 8: perlsub: Perl subroutines
2779 204 50 0 204 1 156130 # of ISBN-13: 978-1-906966-02-7 The Perl Language Reference Manual (for Perl version 5.12.1)
  0 0   0   0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
2780              
2781             CORE::eval sprintf(<<'END', ($] >= 5.014000) ? ':lvalue' : '');
2782             # vv----------------------*******
2783             sub Cyrillic::substr($$;$$) %s {
2784              
2785             my @char = $_[0] =~ /\G (?>$q_char) /oxmsg;
2786              
2787             # If the substring is beyond either end of the string, substr() returns the undefined
2788             # value and produces a warning. When used as an lvalue, specifying a substring that
2789             # is entirely outside the string raises an exception.
2790             # http://perldoc.perl.org/functions/substr.html
2791              
2792             # A return with no argument returns the scalar value undef in scalar context,
2793             # an empty list () in list context, and (naturally) nothing at all in void
2794             # context.
2795              
2796             my $offset = $_[1];
2797             if (($offset > scalar(@char)) or ($offset < (-1 * scalar(@char)))) {
2798             return;
2799             }
2800              
2801             # substr($string,$offset,$length,$replacement)
2802             if (@_ == 4) {
2803             my(undef,undef,$length,$replacement) = @_;
2804             my $substr = join '', splice(@char, $offset, $length, $replacement);
2805             $_[0] = join '', @char;
2806              
2807             # return $substr; this doesn't work, don't say "return"
2808             $substr;
2809             }
2810              
2811             # substr($string,$offset,$length)
2812             elsif (@_ == 3) {
2813             my(undef,undef,$length) = @_;
2814             my $octet_offset = 0;
2815             my $octet_length = 0;
2816             if ($offset == 0) {
2817             $octet_offset = 0;
2818             }
2819             elsif ($offset > 0) {
2820             $octet_offset = CORE::length(join '', @char[0..$offset-1]);
2821             }
2822             else {
2823             $octet_offset = -1 * CORE::length(join '', @char[$#char+$offset+1..$#char]);
2824             }
2825             if ($length == 0) {
2826             $octet_length = 0;
2827             }
2828             elsif ($length > 0) {
2829             $octet_length = CORE::length(join '', @char[$offset..$offset+$length-1]);
2830             }
2831             else {
2832             $octet_length = -1 * CORE::length(join '', @char[$#char+$length+1..$#char]);
2833             }
2834             CORE::substr($_[0], $octet_offset, $octet_length);
2835             }
2836              
2837             # substr($string,$offset)
2838             else {
2839             my $octet_offset = 0;
2840             if ($offset == 0) {
2841             $octet_offset = 0;
2842             }
2843             elsif ($offset > 0) {
2844             $octet_offset = CORE::length(join '', @char[0..$offset-1]);
2845             }
2846             else {
2847             $octet_offset = -1 * CORE::length(join '', @char[$#char+$offset+1..$#char]);
2848             }
2849             CORE::substr($_[0], $octet_offset);
2850             }
2851             }
2852             END
2853             }
2854              
2855             #
2856             # Cyrillic index by character
2857             #
2858 0     0 1 0 sub Cyrillic::index($$;$) {
2859 0 0       0  
2860 0         0 my $index;
2861             if (@_ == 3) {
2862             $index = Ecyrillic::index($_[0], $_[1], CORE::length(Cyrillic::substr($_[0], 0, $_[2])));
2863 0         0 }
2864             else {
2865             $index = Ecyrillic::index($_[0], $_[1]);
2866 0 0       0 }
2867 0         0  
2868             if ($index == -1) {
2869             return -1;
2870 0         0 }
2871             else {
2872             return Cyrillic::length(CORE::substr $_[0], 0, $index);
2873             }
2874             }
2875              
2876             #
2877             # Cyrillic rindex by character
2878             #
2879 0     0 1 0 sub Cyrillic::rindex($$;$) {
2880 0 0       0  
2881 0         0 my $rindex;
2882             if (@_ == 3) {
2883             $rindex = Ecyrillic::rindex($_[0], $_[1], CORE::length(Cyrillic::substr($_[0], 0, $_[2])));
2884 0         0 }
2885             else {
2886             $rindex = Ecyrillic::rindex($_[0], $_[1]);
2887 0 0       0 }
2888 0         0  
2889             if ($rindex == -1) {
2890             return -1;
2891 0         0 }
2892             else {
2893             return Cyrillic::length(CORE::substr $_[0], 0, $rindex);
2894             }
2895             }
2896              
2897 204     204   1910 # when 'm//', '/' means regexp match 'm//' and '?' means regexp match '??'
  204         436  
  204         36129  
2898             # when 'div', '/' means division operator and '?' means conditional operator (condition ? then : else)
2899             use vars qw($slash); $slash = 'm//';
2900              
2901             # ord() to ord() or Cyrillic::ord()
2902             my $function_ord = 'ord';
2903              
2904             # ord to ord or Cyrillic::ord_
2905             my $function_ord_ = 'ord';
2906              
2907             # reverse to reverse or Cyrillic::reverse
2908             my $function_reverse = 'reverse';
2909              
2910             # getc to getc or Cyrillic::getc
2911             my $function_getc = 'getc';
2912              
2913             # P.1023 Appendix W.9 Multibyte Anchoring
2914             # of ISBN 1-56592-224-7 CJKV Information Processing
2915              
2916 204     204   1435 my $anchor = '';
  204     0   373  
  204         10566493  
2917              
2918             use vars qw($nest);
2919              
2920             # regexp of nested parens in qqXX
2921              
2922             # P.340 Matching Nested Constructs with Embedded Code
2923             # in Chapter 7: Perl
2924             # of ISBN 0-596-00289-0 Mastering Regular Expressions, Second edition
2925              
2926             my $qq_paren = qr{(?{local $nest=0}) (?>(?:
2927             [^\\()] |
2928             \( (?{$nest++}) |
2929             \) (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!)) |
2930             \\ [^c] |
2931             \\c[\x40-\x5F] |
2932             [\x00-\xFF]
2933             }xms;
2934              
2935             my $qq_brace = qr{(?{local $nest=0}) (?>(?:
2936             [^\\{}] |
2937             \{ (?{$nest++}) |
2938             \} (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!)) |
2939             \\ [^c] |
2940             \\c[\x40-\x5F] |
2941             [\x00-\xFF]
2942             }xms;
2943              
2944             my $qq_bracket = qr{(?{local $nest=0}) (?>(?:
2945             [^\\\[\]] |
2946             \[ (?{$nest++}) |
2947             \] (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!)) |
2948             \\ [^c] |
2949             \\c[\x40-\x5F] |
2950             [\x00-\xFF]
2951             }xms;
2952              
2953             my $qq_angle = qr{(?{local $nest=0}) (?>(?:
2954             [^\\<>] |
2955             \< (?{$nest++}) |
2956             \> (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!)) |
2957             \\ [^c] |
2958             \\c[\x40-\x5F] |
2959             [\x00-\xFF]
2960             }xms;
2961              
2962             my $qq_scalar = qr{(?: \{ (?:$qq_brace)*? \} |
2963             (?: ::)? (?:
2964             (?> [a-zA-Z_][a-zA-Z_0-9]* (?: ::[a-zA-Z_][a-zA-Z_0-9]*)* )
2965             (?>(?: \[ (?: \$\[ | \$\] | $qq_char )*? \] | \{ (?:$qq_brace)*? \} )*)
2966             (?>(?: (?: -> )? (?: [\$\@\%\&\*]\* | \$\#\* | [\@\%]? \[ (?: \$\[ | \$\] | $qq_char )*? \] | [\@\%\*]? \{ (?:$qq_brace)*? \} ) )*)
2967             ))
2968             }xms;
2969              
2970             my $qq_variable = qr{(?: \{ (?:$qq_brace)*? \} |
2971             (?: ::)? (?:
2972             (?>[0-9]+) |
2973             [^a-zA-Z_0-9\[\]] |
2974             ^[A-Z] |
2975             (?> [a-zA-Z_][a-zA-Z_0-9]* (?: ::[a-zA-Z_][a-zA-Z_0-9]*)* )
2976             (?>(?: \[ (?: \$\[ | \$\] | $qq_char )*? \] | \{ (?:$qq_brace)*? \} )*)
2977             (?>(?: (?: -> )? (?: [\$\@\%\&\*]\* | \$\#\* | [\@\%]? \[ (?: \$\[ | \$\] | $qq_char )*? \] | [\@\%\*]? \{ (?:$qq_brace)*? \} ) )*)
2978             ))
2979             }xms;
2980              
2981             my $qq_substr = qr{(?> Char::substr | Cyrillic::substr | CORE::substr | substr ) (?>\s*) \( $qq_paren \)
2982             }xms;
2983              
2984             # regexp of nested parens in qXX
2985             my $q_paren = qr{(?{local $nest=0}) (?>(?:
2986             [^()] |
2987             \( (?{$nest++}) |
2988             \) (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!)) |
2989             [\x00-\xFF]
2990             }xms;
2991              
2992             my $q_brace = qr{(?{local $nest=0}) (?>(?:
2993             [^\{\}] |
2994             \{ (?{$nest++}) |
2995             \} (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!)) |
2996             [\x00-\xFF]
2997             }xms;
2998              
2999             my $q_bracket = qr{(?{local $nest=0}) (?>(?:
3000             [^\[\]] |
3001             \[ (?{$nest++}) |
3002             \] (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!)) |
3003             [\x00-\xFF]
3004             }xms;
3005              
3006             my $q_angle = qr{(?{local $nest=0}) (?>(?:
3007             [^<>] |
3008             \< (?{$nest++}) |
3009             \> (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!)) |
3010             [\x00-\xFF]
3011             }xms;
3012              
3013             my $matched = '';
3014             my $s_matched = '';
3015              
3016             my $tr_variable = ''; # variable of tr///
3017             my $sub_variable = ''; # variable of s///
3018             my $bind_operator = ''; # =~ or !~
3019              
3020             my @heredoc = (); # here document
3021             my @heredoc_delimiter = ();
3022             my $here_script = ''; # here script
3023              
3024             #
3025             # escape Cyrillic script
3026 0 50   204 0 0 #
3027             sub Cyrillic::escape(;$) {
3028             local($_) = $_[0] if @_;
3029              
3030             # P.359 The Study Function
3031             # in Chapter 7: Perl
3032 204         622 # of ISBN 0-596-00289-0 Mastering Regular Expressions, Second edition
3033              
3034             study $_; # Yes, I studied study yesterday.
3035              
3036             # while all script
3037              
3038             # 6.14. Matching from Where the Last Pattern Left Off
3039             # in Chapter 6. Pattern Matching
3040             # of ISBN 0-596-00313-7 Perl Cookbook, 2nd Edition.
3041             # (and so on)
3042              
3043             # one member of Tag-team
3044             #
3045             # P.128 Start of match (or end of previous match): \G
3046             # P.130 Advanced Use of \G with Perl
3047             # in Chapter 3: Overview of Regular Expression Features and Flavors
3048             # P.255 Use leading anchors
3049             # P.256 Expose ^ and \G at the front expressions
3050             # in Chapter 6: Crafting an Efficient Expression
3051             # P.315 "Tag-team" matching with /gc
3052             # in Chapter 7: Perl
3053 204         393 # of ISBN 0-596-00289-0 Mastering Regular Expressions, Second edition
3054 204         793  
3055 204         733 my $e_script = '';
3056             while (not /\G \z/oxgc) { # member
3057             $e_script .= Cyrillic::escape_token();
3058 75395         150614 }
3059              
3060             return $e_script;
3061             }
3062              
3063             #
3064             # escape Cyrillic token of script
3065             #
3066             sub Cyrillic::escape_token {
3067              
3068 204     75395 0 3015 # \n output here document
3069              
3070             my $ignore_modules = join('|', qw(
3071             utf8
3072             bytes
3073             charnames
3074             I18N::Japanese
3075             I18N::Collate
3076             I18N::JExt
3077             File::DosGlob
3078             Wild
3079             Wildcard
3080             Japanese
3081             ));
3082              
3083             # another member of Tag-team
3084             #
3085             # P.315 "Tag-team" matching with /gc
3086             # in Chapter 7: Perl
3087 75395 100 100     112804 # of ISBN 0-596-00289-0 Mastering Regular Expressions, Second edition
    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          
    100          
    100          
    100          
    100          
    100          
    50          
    100          
    100          
    50          
    100          
    50          
    50          
    50          
    100          
    50          
    50          
    100          
    100          
    100          
    50          
3088 75395         3331512  
3089 12549 100       16931 if (/\G ( \n ) /oxgc) { # another member (and so on)
3090 12549         26543 my $heredoc = '';
3091             if (scalar(@heredoc_delimiter) >= 1) {
3092 174         225 $slash = 'm//';
3093 174         350  
3094             $heredoc = join '', @heredoc;
3095             @heredoc = ();
3096 174         296  
3097 174         349 # skip here document
3098             for my $heredoc_delimiter (@heredoc_delimiter) {
3099 174         1183 /\G .*? \n $heredoc_delimiter \n/xmsgc;
3100             }
3101 174         322 @heredoc_delimiter = ();
3102              
3103 174         232 $here_script = '';
3104             }
3105             return "\n" . $heredoc;
3106             }
3107 12549         41494  
3108             # ignore space, comment
3109             elsif (/\G ((?>\s+)|\#.*) /oxgc) { return $1; }
3110              
3111             # if (, elsif (, unless (, while (, until (, given (, and when (
3112              
3113             # given, when
3114              
3115             # P.225 The given Statement
3116             # in Chapter 15: Smart Matching and given-when
3117             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
3118              
3119             # P.133 The given Statement
3120             # in Chapter 4: Statements and Declarations
3121             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
3122 18109         111772  
3123 1401         2330 elsif (/\G ( (?: if | elsif | unless | while | until | given | when ) (?>\s*) \( ) /oxgc) {
3124             $slash = 'm//';
3125             return $1;
3126             }
3127              
3128             # scalar variable ($scalar = ...) =~ tr///;
3129             # scalar variable ($scalar = ...) =~ s///;
3130              
3131             # state
3132              
3133             # P.68 Persistent, Private Variables
3134             # in Chapter 4: Subroutines
3135             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
3136              
3137             # P.160 Persistent Lexically Scoped Variables: state
3138             # in Chapter 4: Statements and Declarations
3139             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
3140              
3141             # (and so on)
3142 1401         5012  
3143             elsif (/\G ( \( (?>\s*) (?: local \b | my \b | our \b | state \b )? (?>\s*) \$ $qq_scalar ) /oxgc) {
3144 86 50       212 my $e_string = e_string($1);
    50          
3145 86         2176  
3146 0         0 if (/\G ( (?>\s*) = $qq_paren \) ) ( (?>\s*) (?: =~ | !~ ) (?>\s*) ) (?= (?: tr | y ) \b ) /oxgc) {
3147 0         0 $tr_variable = $e_string . e_string($1);
3148 0         0 $bind_operator = $2;
3149             $slash = 'm//';
3150             return '';
3151 0         0 }
3152 0         0 elsif (/\G ( (?>\s*) = $qq_paren \) ) ( (?>\s*) (?: =~ | !~ ) (?>\s*) ) (?= s \b ) /oxgc) {
3153 0         0 $sub_variable = $e_string . e_string($1);
3154 0         0 $bind_operator = $2;
3155             $slash = 'm//';
3156             return '';
3157 0         0 }
3158 86         171 else {
3159             $slash = 'div';
3160             return $e_string;
3161             }
3162             }
3163              
3164 86         345 # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Ecyrillic::PREMATCH()
3165 4         8 elsif (/\G ( \$` | \$\{`\} | \$ (?>\s*) PREMATCH \b | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} ) /oxmsgc) {
3166             $slash = 'div';
3167             return q{Ecyrillic::PREMATCH()};
3168             }
3169              
3170 4         13 # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Ecyrillic::MATCH()
3171 28         56 elsif (/\G ( \$& | \$\{&\} | \$ (?>\s*) MATCH \b | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} ) /oxmsgc) {
3172             $slash = 'div';
3173             return q{Ecyrillic::MATCH()};
3174             }
3175              
3176 28         87 # $', ${'} --> $', ${'}
3177 1         2 elsif (/\G ( \$' | \$\{'\} ) /oxmsgc) {
3178             $slash = 'div';
3179             return $1;
3180             }
3181              
3182 1         3 # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Ecyrillic::POSTMATCH()
3183 3         6 elsif (/\G ( \$ (?>\s*) POSTMATCH \b | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} ) /oxmsgc) {
3184             $slash = 'div';
3185             return q{Ecyrillic::POSTMATCH()};
3186             }
3187              
3188             # scalar variable $scalar =~ tr///;
3189             # scalar variable $scalar =~ s///;
3190             # substr() =~ tr///;
3191 3         9 # substr() =~ s///;
3192             elsif (/\G ( \$ $qq_scalar | $qq_substr ) /oxgc) {
3193 1671 100       4115 my $scalar = e_string($1);
    100          
3194 1671         7225  
3195 1         3 if (/\G ( (?>\s*) (?: =~ | !~ ) (?>\s*) ) (?= (?: tr | y ) \b ) /oxgc) {
3196 1         3 $tr_variable = $scalar;
3197 1         2 $bind_operator = $1;
3198             $slash = 'm//';
3199             return '';
3200 1         4 }
3201 61         125 elsif (/\G ( (?>\s*) (?: =~ | !~ ) (?>\s*) ) (?= s \b ) /oxgc) {
3202 61         119 $sub_variable = $scalar;
3203 61         92 $bind_operator = $1;
3204             $slash = 'm//';
3205             return '';
3206 61         182 }
3207 1609         2442 else {
3208             $slash = 'div';
3209             return $scalar;
3210             }
3211             }
3212              
3213 1609         4574 # end of statement
3214             elsif (/\G ( [,;] ) /oxgc) {
3215             $slash = 'm//';
3216 5025         8083  
3217             # clear tr/// variable
3218             $tr_variable = '';
3219 5025         6375  
3220             # clear s/// variable
3221 5025         6751 $sub_variable = '';
3222              
3223 5025         6064 $bind_operator = '';
3224              
3225             return $1;
3226             }
3227              
3228 5025         18931 # bareword
3229             elsif (/\G ( \{ (?>\s*) (?: tr | index | rindex | reverse ) (?>\s*) \} ) /oxmsgc) {
3230             return $1;
3231             }
3232              
3233 0         0 # $0 --> $0
3234 2         6 elsif (/\G ( \$ 0 ) /oxmsgc) {
3235             $slash = 'div';
3236             return $1;
3237 2         7 }
3238 0         0 elsif (/\G ( \$ \{ (?>\s*) 0 (?>\s*) \} ) /oxmsgc) {
3239             $slash = 'div';
3240             return $1;
3241             }
3242              
3243 0         0 # $$ --> $$
3244 1         2 elsif (/\G ( \$ \$ ) (?![\w\{]) /oxmsgc) {
3245             $slash = 'div';
3246             return $1;
3247             }
3248              
3249             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
3250 1         4 # $1, $2, $3 --> $1, $2, $3 otherwise
3251 4         8 elsif (/\G \$ ((?>[1-9][0-9]*)) /oxmsgc) {
3252             $slash = 'div';
3253             return e_capture($1);
3254 4         10 }
3255 0         0 elsif (/\G \$ \{ (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} /oxmsgc) {
3256             $slash = 'div';
3257             return e_capture($1);
3258             }
3259              
3260 0         0 # $$foo[ ... ] --> $ $foo->[ ... ]
3261 0         0 elsif (/\G \$ ( \$ (?> [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \[ .+? \] ) /oxmsgc) {
3262             $slash = 'div';
3263             return e_capture($1.'->'.$2);
3264             }
3265              
3266 0         0 # $$foo{ ... } --> $ $foo->{ ... }
3267 0         0 elsif (/\G \$ ( \$ (?> [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \{ .+? \} ) /oxmsgc) {
3268             $slash = 'div';
3269             return e_capture($1.'->'.$2);
3270             }
3271              
3272 0         0 # $$foo
3273 0         0 elsif (/\G \$ ( \$ (?> [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) /oxmsgc) {
3274             $slash = 'div';
3275             return e_capture($1);
3276             }
3277              
3278 0         0 # ${ foo }
3279 0         0 elsif (/\G \$ (?>\s*) \{ ( (?>\s*) (?> [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) (?>\s*) ) \} /oxmsgc) {
3280             $slash = 'div';
3281             return '${' . $1 . '}';
3282             }
3283              
3284 0         0 # ${ ... }
3285 0         0 elsif (/\G \$ (?>\s*) \{ (?>\s*) ( $qq_brace ) (?>\s*) \} /oxmsgc) {
3286             $slash = 'div';
3287             return e_capture($1);
3288             }
3289              
3290             # variable or function
3291 0         0 # $ @ % & * $ #
3292 42         69 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) {
3293             $slash = 'div';
3294             return $1;
3295             }
3296             # $ $ $ $ $ $ $ $ $ $ $ $ $ $
3297 42         130 # $ @ # \ ' " / ? ( ) [ ] < >
3298 62         122 elsif (/\G ( \$[\$\@\#\\\'\"\/\?\(\)\[\]\<\>] ) /oxmsgc) {
3299             $slash = 'div';
3300             return $1;
3301             }
3302              
3303 62         208 # while ()
3304             elsif (/\G \b (while (?>\s*) \( (?>\s*) <[\$]?[A-Za-z_][A-Za-z_0-9]*> (?>\s*) \)) \b /oxgc) {
3305             return $1;
3306             }
3307              
3308             # while () --- glob
3309              
3310             # avoid "Error: Runtime exception" of perl version 5.005_03
3311 0         0  
3312             elsif (/\G \b while (?>\s*) \( (?>\s*) < ((?:[^>\0\a\e\f\n\r\t])+?) > (?>\s*) \) \b /oxgc) {
3313             return 'while ($_ = Ecyrillic::glob("' . $1 . '"))';
3314             }
3315              
3316 0         0 # while (glob)
3317             elsif (/\G \b while (?>\s*) \( (?>\s*) glob (?>\s*) \) /oxgc) {
3318             return 'while ($_ = Ecyrillic::glob_)';
3319             }
3320              
3321 0         0 # while (glob(WILDCARD))
3322             elsif (/\G \b while (?>\s*) \( (?>\s*) glob \b /oxgc) {
3323             return 'while ($_ = Ecyrillic::glob';
3324             }
3325 0         0  
  248         577  
3326             # doit if, doit unless, doit while, doit until, doit for, doit when
3327             elsif (/\G \b ( if | unless | while | until | for | when ) \b /oxgc) { $slash = 'm//'; return $1; }
3328 248         1780  
  19         33  
3329 19         67 # subroutines of package Ecyrillic
  0         0  
3330 0         0 elsif (/\G \b (CORE:: | ->(>?\s*) (?: atan2 | [a-z]{2,})) \b /oxgc) { $slash = 'm//'; return $1; }
  13         21  
3331 13         36 elsif (/\G \b Char::eval (?= (?>\s*) \{ ) /oxgc) { $slash = 'm//'; return 'eval'; }
  0         0  
3332 0         0 elsif (/\G \b Cyrillic::eval (?= (?>\s*) \{ ) /oxgc) { $slash = 'm//'; return 'eval'; }
  114         179  
3333 114         317 elsif (/\G \b Char::eval \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'eval Char::escape'; }
  2         3  
3334 2         5 elsif (/\G \b Cyrillic::eval \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'eval Cyrillic::escape'; }
  0         0  
3335 0         0 elsif (/\G \b bytes::substr \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'substr'; }
  2         3  
3336 2         6 elsif (/\G \b chop \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Ecyrillic::chop'; }
  0         0  
3337 0         0 elsif (/\G \b bytes::index \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'index'; }
  0         0  
3338 0         0 elsif (/\G \b Char::index \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Char::index'; }
  0         0  
3339 0         0 elsif (/\G \b Cyrillic::index \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Cyrillic::index'; }
  2         5  
3340 2         6 elsif (/\G \b index \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Ecyrillic::index'; }
  0         0  
3341 0         0 elsif (/\G \b bytes::rindex \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'rindex'; }
  0         0  
3342 0         0 elsif (/\G \b Char::rindex \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Char::rindex'; }
  0         0  
3343 0         0 elsif (/\G \b Cyrillic::rindex \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Cyrillic::rindex'; }
  1         2  
3344 1         3 elsif (/\G \b rindex \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Ecyrillic::rindex'; }
  0         0  
3345 0         0 elsif (/\G \b lc (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Ecyrillic::lc'; }
  1         13  
3346 1         6 elsif (/\G \b lcfirst (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Ecyrillic::lcfirst'; }
  0         0  
3347 0         0 elsif (/\G \b uc (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Ecyrillic::uc'; }
  6         10  
3348             elsif (/\G \b ucfirst (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Ecyrillic::ucfirst'; }
3349             elsif (/\G \b fc (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Ecyrillic::fc'; }
3350 6         17  
  0         0  
3351 0         0 # "-s '' ..." means file test "-s 'filename' ..." (not means "- s/// ...")
  0         0  
3352 0         0 elsif (/\G -s (?>\s*) (\") ((?:$qq_char)+?) (\") /oxgc) { $slash = 'm//'; return '-s ' . e_qq('', $1,$3,$2); }
  0         0  
3353 0         0 elsif (/\G -s (?>\s+) qq (?>\s*) (\#) ((?:$qq_char)+?) (\#) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0         0  
3354 0         0 elsif (/\G -s (?>\s+) qq (?>\s*) (\() ((?:$qq_paren)+?) (\)) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0         0  
3355 0         0 elsif (/\G -s (?>\s+) qq (?>\s*) (\{) ((?:$qq_brace)+?) (\}) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0         0  
3356 0         0 elsif (/\G -s (?>\s+) qq (?>\s*) (\[) ((?:$qq_bracket)+?) (\]) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0         0  
3357             elsif (/\G -s (?>\s+) qq (?>\s*) (\<) ((?:$qq_angle)+?) (\>) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
3358 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  
3359 0         0  
  0         0  
3360 0         0 elsif (/\G -s (?>\s*) (\') ((?:\\\'|\\\\|$q_char)+?) (\') /oxgc) { $slash = 'm//'; return '-s ' . e_q ('', $1,$3,$2); }
  0         0  
3361 0         0 elsif (/\G -s (?>\s+) q (?>\s*) (\#) ((?:\\\#|\\\\|$q_char)+?) (\#) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0         0  
3362 0         0 elsif (/\G -s (?>\s+) q (?>\s*) (\() ((?:\\\)|\\\\|$q_paren)+?) (\)) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0         0  
3363 0         0 elsif (/\G -s (?>\s+) q (?>\s*) (\{) ((?:\\\}|\\\\|$q_brace)+?) (\}) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0         0  
3364 0         0 elsif (/\G -s (?>\s+) q (?>\s*) (\[) ((?:\\\]|\\\\|$q_bracket)+?) (\]) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0         0  
3365             elsif (/\G -s (?>\s+) q (?>\s*) (\<) ((?:\\\>|\\\\|$q_angle)+?) (\>) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
3366             elsif (/\G -s (?>\s+) q (?>\s*) (\S) ((?:\\\1|\\\\|$q_char)+?) (\1) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
3367 0         0  
  0         0  
3368 0         0 elsif (/\G -s (?>\s*) (\$ (?> \w+ (?: ::\w+)* ) (?: (?: ->)? (?: [\$\@\%\&\*]\* | \$\#\* | \( (?:$qq_paren)*? \) | [\@\%\*]? \{ (?:$qq_brace)+? \} | [\@\%]? \[ (?:$qq_bracket)+? \] ) )*) /oxgc)
  0         0  
3369 0         0 { $slash = 'm//'; return "-s $1"; }
  0         0  
3370 0         0 elsif (/\G -s (?>\s*) \( ((?:$qq_paren)*?) \) /oxgc) { $slash = 'm//'; return "-s ($1)"; }
  0         0  
3371             elsif (/\G -s (?= (?>\s+) [a-z]+) /oxgc) { $slash = 'm//'; return '-s'; }
3372 0         0 elsif (/\G -s (?>\s+) ((?>\w+)) /oxgc) { $slash = 'm//'; return "-s $1"; }
  2         4  
3373 2         7  
  2         4  
3374 2         7 elsif (/\G \b bytes::length (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'length'; }
  36         81  
3375 36         135 elsif (/\G \b bytes::chr (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'chr'; }
  2         4  
3376 2         6 elsif (/\G \b chr (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Ecyrillic::chr'; }
  8         15  
3377 8         26 elsif (/\G \b bytes::ord (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'div'; return 'ord'; }
  0         0  
3378 0         0 elsif (/\G \b ord (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'div'; return $function_ord; }
  0         0  
3379 0         0 elsif (/\G \b glob (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Ecyrillic::glob'; }
  0         0  
3380 0         0 elsif (/\G \b lc \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Ecyrillic::lc_'; }
  0         0  
3381 0         0 elsif (/\G \b lcfirst \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Ecyrillic::lcfirst_'; }
  0         0  
3382 0         0 elsif (/\G \b uc \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Ecyrillic::uc_'; }
  0         0  
3383 0         0 elsif (/\G \b ucfirst \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Ecyrillic::ucfirst_'; }
  0         0  
3384             elsif (/\G \b fc \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Ecyrillic::fc_'; }
3385 0         0 elsif (/\G -s \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return '-s '; }
  0         0  
3386 0         0  
  0         0  
3387 0         0 elsif (/\G \b bytes::length \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'length'; }
  0         0  
3388 0         0 elsif (/\G \b bytes::chr \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'chr'; }
  0         0  
3389 0         0 elsif (/\G \b chr \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Ecyrillic::chr_'; }
  0         0  
3390 0         0 elsif (/\G \b bytes::ord \b (?! (?>\s*) => ) /oxgc) { $slash = 'div'; return 'ord'; }
  0         0  
3391 0         0 elsif (/\G \b ord \b (?! (?>\s*) => ) /oxgc) { $slash = 'div'; return $function_ord_; }
  0         0  
3392 0         0 elsif (/\G \b glob \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Ecyrillic::glob_'; }
  8         28  
3393             elsif (/\G \b reverse \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return $function_reverse; }
3394             elsif (/\G \b getc \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return $function_getc; }
3395 8         34 # split
3396             elsif (/\G \b (split) \b (?! (?>\s*) => ) /oxgc) {
3397 87         186 $slash = 'm//';
3398 87         147  
3399 87         339 my $e = '';
3400             while (/\G ( (?>\s+) | \( | \#.* ) /oxgc) {
3401             $e .= $1;
3402             }
3403 85 100       318  
  87 100       6354  
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    100          
    50          
    50          
    100          
    50          
    100          
    50          
    50          
    50          
3404             # end of split
3405             if (/\G (?= [,;\)\}\]] ) /oxgc) { return 'Ecyrillic::split' . $e; }
3406 2         9  
3407             # split scalar value
3408             elsif (/\G ( [\$\@\&\*] $qq_scalar ) /oxgc) { return 'Ecyrillic::split' . $e . e_string($1); }
3409 1         6  
3410 0         0 # split literal space
3411 0         0 elsif (/\G \b qq (\#) [ ] (\#) /oxgc) { return 'Ecyrillic::split' . $e . qq {qq$1 $2}; }
3412 0         0 elsif (/\G \b qq ((?>\s*)) (\() [ ] (\)) /oxgc) { return 'Ecyrillic::split' . $e . qq{$1qq$2 $3}; }
3413 0         0 elsif (/\G \b qq ((?>\s*)) (\{) [ ] (\}) /oxgc) { return 'Ecyrillic::split' . $e . qq{$1qq$2 $3}; }
3414 0         0 elsif (/\G \b qq ((?>\s*)) (\[) [ ] (\]) /oxgc) { return 'Ecyrillic::split' . $e . qq{$1qq$2 $3}; }
3415 0         0 elsif (/\G \b qq ((?>\s*)) (\<) [ ] (\>) /oxgc) { return 'Ecyrillic::split' . $e . qq{$1qq$2 $3}; }
3416 0         0 elsif (/\G \b qq ((?>\s*)) (\S) [ ] (\2) /oxgc) { return 'Ecyrillic::split' . $e . qq{$1qq$2 $3}; }
3417 0         0 elsif (/\G \b q (\#) [ ] (\#) /oxgc) { return 'Ecyrillic::split' . $e . qq {q$1 $2}; }
3418 0         0 elsif (/\G \b q ((?>\s*)) (\() [ ] (\)) /oxgc) { return 'Ecyrillic::split' . $e . qq {$1q$2 $3}; }
3419 0         0 elsif (/\G \b q ((?>\s*)) (\{) [ ] (\}) /oxgc) { return 'Ecyrillic::split' . $e . qq {$1q$2 $3}; }
3420 0         0 elsif (/\G \b q ((?>\s*)) (\[) [ ] (\]) /oxgc) { return 'Ecyrillic::split' . $e . qq {$1q$2 $3}; }
3421 0         0 elsif (/\G \b q ((?>\s*)) (\<) [ ] (\>) /oxgc) { return 'Ecyrillic::split' . $e . qq {$1q$2 $3}; }
3422 10         57 elsif (/\G \b q ((?>\s*)) (\S) [ ] (\2) /oxgc) { return 'Ecyrillic::split' . $e . qq {$1q$2 $3}; }
3423             elsif (/\G ' [ ] ' /oxgc) { return 'Ecyrillic::split' . $e . qq {' '}; }
3424             elsif (/\G " [ ] " /oxgc) { return 'Ecyrillic::split' . $e . qq {" "}; }
3425              
3426 0 0       0 # split qq//
  0         0  
3427             elsif (/\G \b (qq) \b /oxgc) {
3428 0         0 if (/\G (\#) ((?:$qq_char)*?) (\#) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq# # --> qr # #
3429 0 0       0 else {
  0 0       0  
    0          
    0          
    0          
    0          
    0          
3430 0         0 while (not /\G \z/oxgc) {
3431 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3432 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq ( ) --> qr ( )
3433 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq { } --> qr { }
3434 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq [ ] --> qr [ ]
3435 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq < > --> qr < >
3436             elsif (/\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) /oxgc) { return e_split($e.'qr','{','}',$2,''); } # qq | | --> qr { }
3437 0         0 elsif (/\G (\S) ((?:$qq_char)*?) (\1) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq * * --> qr * *
3438             }
3439             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3440             }
3441             }
3442              
3443 0 50       0 # split qr//
  12         463  
3444             elsif (/\G \b (qr) \b /oxgc) {
3445 0         0 if (/\G (\#) ((?:$qq_char)*?) (\#) ([imosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1,$3,$2,$4); } # qr# #
3446 12 50       66 else {
  12 50       3837  
    50          
    50          
    50          
    50          
    50          
    50          
3447 0         0 while (not /\G \z/oxgc) {
3448 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3449 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([imosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # qr ( )
3450 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([imosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # qr { }
3451 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([imosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # qr [ ]
3452 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([imosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # qr < >
3453 0         0 elsif (/\G (\') ((?:$qq_char)*?) (\') ([imosxpadlunbB]*) /oxgc) { return e_split_q($e.'qr',$1, $3, $2,$4); } # qr ' '
3454             elsif (/\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ([imosxpadlunbB]*) /oxgc) { return e_split ($e.'qr','{','}',$2,$4); } # qr | | --> qr { }
3455 12         84 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([imosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # qr * *
3456             }
3457             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3458             }
3459             }
3460              
3461 0 0       0 # split q//
  0         0  
3462             elsif (/\G \b (q) \b /oxgc) {
3463 0         0 if (/\G (\#) ((?:\\\#|\\\\|$q_char)*?) (\#) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q# # --> qr # #
3464 0 0       0 else {
  0 0       0  
    0          
    0          
    0          
    0          
    0          
3465 0         0 while (not /\G \z/oxgc) {
3466 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3467 0         0 elsif (/\G (\() ((?:\\\\|\\\)|\\\(|$q_paren)*?) (\)) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q ( ) --> qr ( )
3468 0         0 elsif (/\G (\{) ((?:\\\\|\\\}|\\\{|$q_brace)*?) (\}) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q { } --> qr { }
3469 0         0 elsif (/\G (\[) ((?:\\\\|\\\]|\\\[|$q_bracket)*?) (\]) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q [ ] --> qr [ ]
3470 0         0 elsif (/\G (\<) ((?:\\\\|\\\>|\\\<|$q_angle)*?) (\>) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q < > --> qr < >
3471             elsif (/\G ([*\-:?\\^|]) ((?:$q_char)*?) (\1) /oxgc) { return e_split_q($e.'qr','{','}',$2,''); } # q | | --> qr { }
3472 0         0 elsif (/\G (\S) ((?:\\\\|\\\1| $q_char)*?) (\1) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q * * --> qr * *
3473             }
3474             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3475             }
3476             }
3477              
3478 0 50       0 # split m//
  18         472  
3479             elsif (/\G \b (m) \b /oxgc) {
3480 0         0 if (/\G (\#) ((?:$qq_char)*?) (\#) ([cgimosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1,$3,$2,$4); } # m# # --> qr # #
3481 18 50       82 else {
  18 50       4726  
    50          
    50          
    50          
    50          
    50          
    50          
3482 0         0 while (not /\G \z/oxgc) {
3483 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3484 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cgimosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # m ( ) --> qr ( )
3485 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cgimosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # m { } --> qr { }
3486 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cgimosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # m [ ] --> qr [ ]
3487 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cgimosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # m < > --> qr < >
3488 0         0 elsif (/\G (\') ((?:$qq_char)*?) (\') ([cgimosxpadlunbB]*) /oxgc) { return e_split_q($e.'qr',$1, $3, $2,$4); } # m ' ' --> qr ' '
3489             elsif (/\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ([cgimosxpadlunbB]*) /oxgc) { return e_split ($e.'qr','{','}',$2,$4); } # m | | --> qr { }
3490 18         113 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cgimosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # m * * --> qr * *
3491             }
3492             die __FILE__, ": Search pattern not terminated\n";
3493             }
3494             }
3495              
3496 0         0 # split ''
3497 0         0 elsif (/\G (\') /oxgc) {
3498 0 0       0 my $q_string = '';
  0 0       0  
    0          
    0          
3499 0         0 while (not /\G \z/oxgc) {
3500 0         0 if (/\G (\\\\) /oxgc) { $q_string .= $1; }
3501 0         0 elsif (/\G (\\\') /oxgc) { $q_string .= $1; } # splitqr'' --> split qr''
3502             elsif (/\G \' /oxgc) { return e_split_q($e.q{ qr},"'","'",$q_string,''); } # ' ' --> qr ' '
3503 0         0 elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3504             }
3505             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3506             }
3507              
3508 0         0 # split ""
3509 0         0 elsif (/\G (\") /oxgc) {
3510 0 0       0 my $qq_string = '';
  0 0       0  
    0          
    0          
3511 0         0 while (not /\G \z/oxgc) {
3512 0         0 if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
3513 0         0 elsif (/\G (\\\") /oxgc) { $qq_string .= $1; } # splitqr"" --> split qr""
3514             elsif (/\G \" /oxgc) { return e_split($e.q{ qr},'"','"',$qq_string,''); } # " " --> qr " "
3515 0         0 elsif (/\G ($q_char) /oxgc) { $qq_string .= $1; }
3516             }
3517             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3518             }
3519              
3520 0         0 # split //
3521 44         107 elsif (/\G (\/) /oxgc) {
3522 44 50       171 my $regexp = '';
  381 50       17611  
    100          
    50          
3523 0         0 while (not /\G \z/oxgc) {
3524 0         0 if (/\G (\\\\) /oxgc) { $regexp .= $1; }
3525 44         194 elsif (/\G (\\\/) /oxgc) { $regexp .= $1; } # splitqr// --> split qr//
3526             elsif (/\G \/ ([cgimosxpadlunbB]*) /oxgc) { return e_split($e.q{ qr}, '/','/',$regexp,$1); } # / / --> qr / /
3527 337         712 elsif (/\G ($q_char) /oxgc) { $regexp .= $1; }
3528             }
3529             die __FILE__, ": Search pattern not terminated\n";
3530             }
3531             }
3532              
3533             # tr/// or y///
3534              
3535             # about [cdsrbB]* (/B modifier)
3536             #
3537             # P.559 appendix C
3538             # of ISBN 4-89052-384-7 Programming perl
3539             # (Japanese title is: Perl puroguramingu)
3540 0         0  
3541             elsif (/\G \b ( tr | y ) \b /oxgc) {
3542             my $ope = $1;
3543 3 50       7  
3544 3         42 # $1 $2 $3 $4 $5 $6
3545 0         0 if (/\G (\#) ((?:$qq_char)*?) (\#) ((?:$qq_char)*?) (\#) ([cdsrbB]*) /oxgc) { # tr# # #
3546             my @tr = ($tr_variable,$2);
3547             return e_tr(@tr,'',$4,$6);
3548 0         0 }
3549 3         4 else {
3550 3 50       11 my $e = '';
  3 50       220  
    50          
    50          
    50          
    50          
3551             while (not /\G \z/oxgc) {
3552 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3553 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) /oxgc) {
3554 0 0       0 my @tr = ($tr_variable,$2);
  0 0       0  
    0          
    0          
    0          
    0          
3555 0         0 while (not /\G \z/oxgc) {
3556 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3557 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr ( ) ( )
3558 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr ( ) { }
3559 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr ( ) [ ]
3560             elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr ( ) < >
3561 0         0 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr ( ) * *
3562             }
3563             die __FILE__, ": Transliteration replacement not terminated\n";
3564 0         0 }
3565 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) {
3566 0 0       0 my @tr = ($tr_variable,$2);
  0 0       0  
    0          
    0          
    0          
    0          
3567 0         0 while (not /\G \z/oxgc) {
3568 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3569 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr { } ( )
3570 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr { } { }
3571 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr { } [ ]
3572             elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr { } < >
3573 0         0 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr { } * *
3574             }
3575             die __FILE__, ": Transliteration replacement not terminated\n";
3576 0         0 }
3577 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) {
3578 0 0       0 my @tr = ($tr_variable,$2);
  0 0       0  
    0          
    0          
    0          
    0          
3579 0         0 while (not /\G \z/oxgc) {
3580 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3581 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr [ ] ( )
3582 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr [ ] { }
3583 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr [ ] [ ]
3584             elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr [ ] < >
3585 0         0 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr [ ] * *
3586             }
3587             die __FILE__, ": Transliteration replacement not terminated\n";
3588 0         0 }
3589 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) {
3590 0 0       0 my @tr = ($tr_variable,$2);
  0 0       0  
    0          
    0          
    0          
    0          
3591 0         0 while (not /\G \z/oxgc) {
3592 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3593 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr < > ( )
3594 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr < > { }
3595 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr < > [ ]
3596             elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr < > < >
3597 0         0 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr < > * *
3598             }
3599             die __FILE__, ": Transliteration replacement not terminated\n";
3600             }
3601 0         0 # $1 $2 $3 $4 $5 $6
3602 3         11 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ((?:$qq_char)*?) (\1) ([cdsrbB]*) /oxgc) { # tr * * *
3603             my @tr = ($tr_variable,$2);
3604             return e_tr(@tr,'',$4,$6);
3605 3         9 }
3606             }
3607             die __FILE__, ": Transliteration pattern not terminated\n";
3608             }
3609             }
3610              
3611 0         0 # qq//
3612             elsif (/\G \b (qq) \b /oxgc) {
3613             my $ope = $1;
3614 2180 50       5823  
3615 2180         4320 # if (/\G (\#) ((?:$qq_char)*?) (\#) /oxgc) { return e_qq($ope,$1,$3,$2); } # qq# #
3616 0         0 if (/\G (\#) /oxgc) { # qq# #
3617 0 0       0 my $qq_string = '';
  0 0       0  
    0          
    0          
3618 0         0 while (not /\G \z/oxgc) {
3619 0         0 if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
3620 0         0 elsif (/\G (\\\#) /oxgc) { $qq_string .= $1; }
3621             elsif (/\G (\#) /oxgc) { return e_qq($ope,'#','#',$qq_string); }
3622 0         0 elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3623             }
3624             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3625             }
3626 0         0  
3627 2180         2874 else {
3628 2180 50       5271 my $e = '';
  2180 50       10159  
    100          
    50          
    50          
    0          
3629             while (not /\G \z/oxgc) {
3630             if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3631              
3632 0         0 # elsif (/\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qq ( )
3633 0         0 elsif (/\G (\() /oxgc) { # qq ( )
3634 0         0 my $qq_string = '';
3635 0 0       0 local $nest = 1;
  0 0       0  
    0          
    0          
    0          
3636 0         0 while (not /\G \z/oxgc) {
3637 0         0 if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0         0  
3638             elsif (/\G (\\\)) /oxgc) { $qq_string .= $1; }
3639 0 0       0 elsif (/\G (\() /oxgc) { $qq_string .= $1; $nest++; }
  0         0  
3640 0         0 elsif (/\G (\)) /oxgc) {
3641             if (--$nest == 0) { return $e . e_qq($ope,'(',')',$qq_string); }
3642 0         0 else { $qq_string .= $1; }
3643             }
3644 0         0 elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3645             }
3646             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3647             }
3648              
3649 0         0 # elsif (/\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qq { }
3650 2150         2893 elsif (/\G (\{) /oxgc) { # qq { }
3651 2150         3083 my $qq_string = '';
3652 2150 100       4865 local $nest = 1;
  84032 50       281671  
    100          
    100          
    50          
3653 722         1482 while (not /\G \z/oxgc) {
3654 0         0 if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  1153         1670  
3655             elsif (/\G (\\\}) /oxgc) { $qq_string .= $1; }
3656 1153 100       2082 elsif (/\G (\{) /oxgc) { $qq_string .= $1; $nest++; }
  3303         5640  
3657 2150         4998 elsif (/\G (\}) /oxgc) {
3658             if (--$nest == 0) { return $e . e_qq($ope,'{','}',$qq_string); }
3659 1153         2631 else { $qq_string .= $1; }
3660             }
3661 78854         201255 elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3662             }
3663             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3664             }
3665              
3666 0         0 # elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qq [ ]
3667 0         0 elsif (/\G (\[) /oxgc) { # qq [ ]
3668 0         0 my $qq_string = '';
3669 0 0       0 local $nest = 1;
  0 0       0  
    0          
    0          
    0          
3670 0         0 while (not /\G \z/oxgc) {
3671 0         0 if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0         0  
3672             elsif (/\G (\\\]) /oxgc) { $qq_string .= $1; }
3673 0 0       0 elsif (/\G (\[) /oxgc) { $qq_string .= $1; $nest++; }
  0         0  
3674 0         0 elsif (/\G (\]) /oxgc) {
3675             if (--$nest == 0) { return $e . e_qq($ope,'[',']',$qq_string); }
3676 0         0 else { $qq_string .= $1; }
3677             }
3678 0         0 elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3679             }
3680             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3681             }
3682              
3683 0         0 # elsif (/\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qq < >
3684 30         56 elsif (/\G (\<) /oxgc) { # qq < >
3685 30         48 my $qq_string = '';
3686 30 100       103 local $nest = 1;
  1166 50       3805  
    50          
    100          
    50          
3687 22         49 while (not /\G \z/oxgc) {
3688 0         0 if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0         0  
3689             elsif (/\G (\\\>) /oxgc) { $qq_string .= $1; }
3690 0 50       0 elsif (/\G (\<) /oxgc) { $qq_string .= $1; $nest++; }
  30         65  
3691 30         74 elsif (/\G (\>) /oxgc) {
3692             if (--$nest == 0) { return $e . e_qq($ope,'<','>',$qq_string); }
3693 0         0 else { $qq_string .= $1; }
3694             }
3695 1114         2173 elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3696             }
3697             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3698             }
3699              
3700 0         0 # elsif (/\G (\S) ((?:$qq_char)*?) (\1) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qq * *
3701 0         0 elsif (/\G (\S) /oxgc) { # qq * *
3702 0         0 my $delimiter = $1;
3703 0 0       0 my $qq_string = '';
  0 0       0  
    0          
    0          
3704 0         0 while (not /\G \z/oxgc) {
3705 0         0 if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
3706 0         0 elsif (/\G (\\\Q$delimiter\E) /oxgc) { $qq_string .= $1; }
3707             elsif (/\G (\Q$delimiter\E) /oxgc) { return $e . e_qq($ope,$delimiter,$delimiter,$qq_string); }
3708 0         0 elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3709             }
3710             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3711 0         0 }
3712             }
3713             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3714             }
3715             }
3716              
3717 0         0 # qr//
3718 0 0       0 elsif (/\G \b (qr) \b /oxgc) {
3719 0         0 my $ope = $1;
3720             if (/\G (\#) ((?:$qq_char)*?) (\#) ([imosxpadlunbB]*) /oxgc) { # qr# # #
3721             return e_qr($ope,$1,$3,$2,$4);
3722 0         0 }
3723 0         0 else {
3724 0 0       0 my $e = '';
  0 0       0  
    0          
    0          
    0          
    0          
    0          
    0          
3725 0         0 while (not /\G \z/oxgc) {
3726 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3727 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([imosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # qr ( )
3728 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([imosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # qr { }
3729 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([imosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # qr [ ]
3730 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([imosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # qr < >
3731 0         0 elsif (/\G (\') ((?:$qq_char)*?) (\') ([imosxpadlunbB]*) /oxgc) { return $e . e_qr_q($ope,$1, $3, $2,$4); } # qr ' '
3732             elsif (/\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ([imosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,'{','}',$2,$4); } # qr | | --> qr { }
3733 0         0 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([imosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # qr * *
3734             }
3735             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3736             }
3737             }
3738              
3739 0         0 # qw//
3740 16 50       68 elsif (/\G \b (qw) \b /oxgc) {
3741 16         89 my $ope = $1;
3742             if (/\G (\#) (.*?) (\#) /oxmsgc) { # qw# #
3743             return e_qw($ope,$1,$3,$2);
3744 0         0 }
3745 16         33 else {
3746 16 50       55 my $e = '';
  16 50       110  
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
3747             while (not /\G \z/oxgc) {
3748 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3749 16         78  
3750             elsif (/\G (\() ([^(]*?) (\)) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw ( )
3751 0         0 elsif (/\G (\() ((?:$q_paren)*?) (\)) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw ( )
3752 0         0  
3753             elsif (/\G (\{) ([^{]*?) (\}) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw { }
3754 0         0 elsif (/\G (\{) ((?:$q_brace)*?) (\}) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw { }
3755 0         0  
3756             elsif (/\G (\[) ([^[]*?) (\]) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw [ ]
3757 0         0 elsif (/\G (\[) ((?:$q_bracket)*?) (\]) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw [ ]
3758 0         0  
3759             elsif (/\G (\<) ([^<]*?) (\>) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw < >
3760 0         0 elsif (/\G (\<) ((?:$q_angle)*?) (\>) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw < >
3761 0         0  
3762             elsif (/\G ([\x21-\x3F]) (.*?) (\1) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw * *
3763 0         0 elsif (/\G (\S) ((?:$q_char)*?) (\1) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw * *
3764             }
3765             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3766             }
3767             }
3768              
3769 0         0 # qx//
3770 0 0       0 elsif (/\G \b (qx) \b /oxgc) {
3771 0         0 my $ope = $1;
3772             if (/\G (\#) ((?:$qq_char)*?) (\#) /oxgc) { # qx# #
3773             return e_qq($ope,$1,$3,$2);
3774 0         0 }
3775 0         0 else {
3776 0 0       0 my $e = '';
  0 0       0  
    0          
    0          
    0          
    0          
    0          
3777 0         0 while (not /\G \z/oxgc) {
3778 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3779 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qx ( )
3780 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qx { }
3781 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qx [ ]
3782 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qx < >
3783             elsif (/\G (\') ((?:$qq_char)*?) (\') /oxgc) { return $e . e_q ($ope,$1,$3,$2); } # qx ' '
3784 0         0 elsif (/\G (\S) ((?:$qq_char)*?) (\1) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qx * *
3785             }
3786             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3787             }
3788             }
3789              
3790 0         0 # q//
3791             elsif (/\G \b (q) \b /oxgc) {
3792             my $ope = $1;
3793              
3794             # if (/\G (\#) ((?:\\\#|\\\\|$q_char)*?) (\#) /oxgc) { return e_q($ope,$1,$3,$2); } # q# #
3795              
3796             # avoid "Error: Runtime exception" of perl version 5.005_03
3797 410 50       1108 # (and so on)
3798 410         1055  
3799 0         0 if (/\G (\#) /oxgc) { # q# #
3800 0 0       0 my $q_string = '';
  0 0       0  
    0          
    0          
3801 0         0 while (not /\G \z/oxgc) {
3802 0         0 if (/\G (\\\\) /oxgc) { $q_string .= $1; }
3803 0         0 elsif (/\G (\\\#) /oxgc) { $q_string .= $1; }
3804             elsif (/\G (\#) /oxgc) { return e_q($ope,'#','#',$q_string); }
3805 0         0 elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3806             }
3807             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3808             }
3809 0         0  
3810 410         882 else {
3811 410 50       1484 my $e = '';
  410 50       2234  
    100          
    50          
    100          
    50          
3812             while (not /\G \z/oxgc) {
3813             if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3814              
3815 0         0 # elsif (/\G (\() ((?:\\\)|\\\\|$q_paren)*?) (\)) /oxgc) { return $e . e_q($ope,$1,$3,$2); } # q ( )
3816 0         0 elsif (/\G (\() /oxgc) { # q ( )
3817 0         0 my $q_string = '';
3818 0 0       0 local $nest = 1;
  0 0       0  
    0          
    0          
    0          
    0          
3819 0         0 while (not /\G \z/oxgc) {
3820 0         0 if (/\G (\\\\) /oxgc) { $q_string .= $1; }
3821 0         0 elsif (/\G (\\\)) /oxgc) { $q_string .= $1; }
  0         0  
3822             elsif (/\G (\\\() /oxgc) { $q_string .= $1; }
3823 0 0       0 elsif (/\G (\() /oxgc) { $q_string .= $1; $nest++; }
  0         0  
3824 0         0 elsif (/\G (\)) /oxgc) {
3825             if (--$nest == 0) { return $e . e_q($ope,'(',')',$q_string); }
3826 0         0 else { $q_string .= $1; }
3827             }
3828 0         0 elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3829             }
3830             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3831             }
3832              
3833 0         0 # elsif (/\G (\{) ((?:\\\}|\\\\|$q_brace)*?) (\}) /oxgc) { return $e . e_q($ope,$1,$3,$2); } # q { }
3834 404         652 elsif (/\G (\{) /oxgc) { # q { }
3835 404         658 my $q_string = '';
3836 404 50       1128 local $nest = 1;
  6796 50       35348  
    50          
    100          
    100          
    50          
3837 0         0 while (not /\G \z/oxgc) {
3838 0         0 if (/\G (\\\\) /oxgc) { $q_string .= $1; }
3839 0         0 elsif (/\G (\\\}) /oxgc) { $q_string .= $1; }
  107         206  
3840             elsif (/\G (\\\{) /oxgc) { $q_string .= $1; }
3841 107 100       423 elsif (/\G (\{) /oxgc) { $q_string .= $1; $nest++; }
  511         1744  
3842 404         1178 elsif (/\G (\}) /oxgc) {
3843             if (--$nest == 0) { return $e . e_q($ope,'{','}',$q_string); }
3844 107         214 else { $q_string .= $1; }
3845             }
3846 6178         13389 elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3847             }
3848             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3849             }
3850              
3851 0         0 # elsif (/\G (\[) ((?:\\\]|\\\\|$q_bracket)*?) (\]) /oxgc) { return $e . e_q($ope,$1,$3,$2); } # q [ ]
3852 0         0 elsif (/\G (\[) /oxgc) { # q [ ]
3853 0         0 my $q_string = '';
3854 0 0       0 local $nest = 1;
  0 0       0  
    0          
    0          
    0          
    0          
3855 0         0 while (not /\G \z/oxgc) {
3856 0         0 if (/\G (\\\\) /oxgc) { $q_string .= $1; }
3857 0         0 elsif (/\G (\\\]) /oxgc) { $q_string .= $1; }
  0         0  
3858             elsif (/\G (\\\[) /oxgc) { $q_string .= $1; }
3859 0 0       0 elsif (/\G (\[) /oxgc) { $q_string .= $1; $nest++; }
  0         0  
3860 0         0 elsif (/\G (\]) /oxgc) {
3861             if (--$nest == 0) { return $e . e_q($ope,'[',']',$q_string); }
3862 0         0 else { $q_string .= $1; }
3863             }
3864 0         0 elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3865             }
3866             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3867             }
3868              
3869 0         0 # elsif (/\G (\<) ((?:\\\>|\\\\|$q_angle)*?) (\>) /oxgc) { return $e . e_q($ope,$1,$3,$2); } # q < >
3870 5         9 elsif (/\G (\<) /oxgc) { # q < >
3871 5         10 my $q_string = '';
3872 5 50       16 local $nest = 1;
  88 50       363  
    50          
    50          
    100          
    50          
3873 0         0 while (not /\G \z/oxgc) {
3874 0         0 if (/\G (\\\\) /oxgc) { $q_string .= $1; }
3875 0         0 elsif (/\G (\\\>) /oxgc) { $q_string .= $1; }
  0         0  
3876             elsif (/\G (\\\<) /oxgc) { $q_string .= $1; }
3877 0 50       0 elsif (/\G (\<) /oxgc) { $q_string .= $1; $nest++; }
  5         17  
3878 5         15 elsif (/\G (\>) /oxgc) {
3879             if (--$nest == 0) { return $e . e_q($ope,'<','>',$q_string); }
3880 0         0 else { $q_string .= $1; }
3881             }
3882 83         162 elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3883             }
3884             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3885             }
3886              
3887 0         0 # elsif (/\G (\S) ((?:\\\1|\\\\|$q_char)*?) (\1) /oxgc) { return $e . e_q($ope,$1,$3,$2); } # q * *
3888 1         2 elsif (/\G (\S) /oxgc) { # q * *
3889 1         3 my $delimiter = $1;
3890 1 50       4 my $q_string = '';
  14 50       71  
    100          
    50          
3891 0         0 while (not /\G \z/oxgc) {
3892 0         0 if (/\G (\\\\) /oxgc) { $q_string .= $1; }
3893 1         4 elsif (/\G (\\\Q$delimiter\E) /oxgc) { $q_string .= $1; }
3894             elsif (/\G (\Q$delimiter\E) /oxgc) { return $e . e_q($ope,$delimiter,$delimiter,$q_string); }
3895 13         23 elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3896             }
3897             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3898 0         0 }
3899             }
3900             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3901             }
3902             }
3903              
3904 0         0 # m//
3905 209 50       534 elsif (/\G \b (m) \b /oxgc) {
3906 209         1481 my $ope = $1;
3907             if (/\G (\#) ((?:$qq_char)*?) (\#) ([cgimosxpadlunbB]*) /oxgc) { # m# #
3908             return e_qr($ope,$1,$3,$2,$4);
3909 0         0 }
3910 209         460 else {
3911 209 50       647 my $e = '';
  209 50       11042  
    50          
    50          
    50          
    50          
    100          
    50          
    50          
3912 0         0 while (not /\G \z/oxgc) {
3913 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3914 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cgimosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m ( )
3915 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cgimosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m { }
3916 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cgimosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m [ ]
3917 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cgimosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m < >
3918 10         194 elsif (/\G (\?) ((?:$qq_char)*?) (\?) ([cgimosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m ? ?
3919 0         0 elsif (/\G (\') ((?:$qq_char)*?) (\') ([cgimosxpadlunbB]*) /oxgc) { return $e . e_qr_q($ope,$1, $3, $2,$4); } # m ' '
3920             elsif (/\G ([*\-:\\^|]) ((?:$qq_char)*?) (\1) ([cgimosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,'{','}',$2,$4); } # m | | --> m { }
3921 199         712 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cgimosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m * *
3922             }
3923             die __FILE__, ": Search pattern not terminated\n";
3924             }
3925             }
3926              
3927             # s///
3928              
3929             # about [cegimosxpradlunbB]* (/cg modifier)
3930             #
3931             # P.67 Pattern-Matching Operators
3932             # of ISBN 0-596-00241-6 Perl in a Nutshell, Second Edition.
3933 0         0  
3934             elsif (/\G \b (s) \b /oxgc) {
3935             my $ope = $1;
3936 97 100       326  
3937 97         1672 # $1 $2 $3 $4 $5 $6
3938             if (/\G (\#) ((?:$qq_char)*?) (\#) ((?:$qq_char)*?) (\#) ([cegimosxpradlunbB]*) /oxgc) { # s# # #
3939             return e_sub($sub_variable,$1,$2,$3,$3,$4,$5,$6);
3940 1         6 }
3941 96         196 else {
3942 96 50       1375 my $e = '';
  96 50       12795  
    50          
    50          
    50          
    100          
    50          
    50          
    50          
3943             while (not /\G \z/oxgc) {
3944 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3945 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) /oxgc) {
3946 0 0       0 my @s = ($1,$2,$3);
  0 0       0  
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
3947             while (not /\G \z/oxgc) {
3948 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3949 0         0 # $1 $2 $3 $4
3950 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3951 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3952 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3953 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3954 0         0 elsif (/\G (\') ((?:$qq_char)*?) (\') ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3955 0         0 elsif (/\G (\$) ((?:$qq_char)*?) (\$) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3956 0         0 elsif (/\G (\:) ((?:$qq_char)*?) (\:) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3957             elsif (/\G (\@) ((?:$qq_char)*?) (\@) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3958 0         0 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3959             }
3960             die __FILE__, ": Substitution replacement not terminated\n";
3961 0         0 }
3962 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) {
3963 0 0       0 my @s = ($1,$2,$3);
  0 0       0  
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
3964             while (not /\G \z/oxgc) {
3965 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3966 0         0 # $1 $2 $3 $4
3967 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3968 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3969 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3970 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3971 0         0 elsif (/\G (\') ((?:$qq_char)*?) (\') ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3972 0         0 elsif (/\G (\$) ((?:$qq_char)*?) (\$) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3973 0         0 elsif (/\G (\:) ((?:$qq_char)*?) (\:) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3974             elsif (/\G (\@) ((?:$qq_char)*?) (\@) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3975 0         0 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3976             }
3977             die __FILE__, ": Substitution replacement not terminated\n";
3978 0         0 }
3979 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) {
3980 0 0       0 my @s = ($1,$2,$3);
  0 0       0  
    0          
    0          
    0          
    0          
    0          
    0          
3981             while (not /\G \z/oxgc) {
3982 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3983 0         0 # $1 $2 $3 $4
3984 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3985 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3986 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3987 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3988 0         0 elsif (/\G (\') ((?:$qq_char)*?) (\') ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3989             elsif (/\G (\$) ((?:$qq_char)*?) (\$) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3990 0         0 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3991             }
3992             die __FILE__, ": Substitution replacement not terminated\n";
3993 0         0 }
3994 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) {
3995 0 0       0 my @s = ($1,$2,$3);
  0 0       0  
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
3996             while (not /\G \z/oxgc) {
3997 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3998 0         0 # $1 $2 $3 $4
3999 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
4000 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
4001 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
4002 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
4003 0         0 elsif (/\G (\') ((?:$qq_char)*?) (\') ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
4004 0         0 elsif (/\G (\$) ((?:$qq_char)*?) (\$) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
4005 0         0 elsif (/\G (\:) ((?:$qq_char)*?) (\:) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
4006             elsif (/\G (\@) ((?:$qq_char)*?) (\@) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
4007 0         0 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
4008             }
4009             die __FILE__, ": Substitution replacement not terminated\n";
4010             }
4011 0         0 # $1 $2 $3 $4 $5 $6
4012             elsif (/\G (\') ((?:$qq_char)*?) (\') ((?:$qq_char)*?) (\') ([cegimosxpradlunbB]*) /oxgc) {
4013             return e_sub($sub_variable,$1,$2,$3,$3,$4,$5,$6);
4014             }
4015 21         72 # $1 $2 $3 $4 $5 $6
4016             elsif (/\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ((?:$qq_char)*?) (\1) ([cegimosxpradlunbB]*) /oxgc) {
4017             return e_sub($sub_variable,'{',$2,'}','{',$4,'}',$6); # s | | | --> s { } { }
4018             }
4019 0         0 # $1 $2 $3 $4 $5 $6
4020             elsif (/\G (\$) ((?:$qq_char)*?) (\1) ((?:$qq_char)*?) (\1) ([cegimosxpradlunbB]*) /oxgc) {
4021             return e_sub($sub_variable,$1,$2,$3,$3,$4,$5,$6);
4022             }
4023 0         0 # $1 $2 $3 $4 $5 $6
4024             elsif (/\G (\S) ((?:$qq_char)*?) (\1) ((?:$qq_char)*?) (\1) ([cegimosxpradlunbB]*) /oxgc) {
4025             return e_sub($sub_variable,$1,$2,$3,$3,$4,$5,$6);
4026 75         339 }
4027             }
4028             die __FILE__, ": Substitution pattern not terminated\n";
4029             }
4030             }
4031 0         0  
4032 0         0 # require ignore module
4033 0         0 elsif (/\G \b require ((?>\s+) (?:$ignore_modules) .*? ;) ([ \t]* [#\n]) /oxmsgc) { return "# require$1$2"; }
4034             elsif (/\G \b require ((?>\s+) (?:$ignore_modules) .*? ;) ([ \t]* [^#]) /oxmsgc) { return "# require$1\n$2"; }
4035             elsif (/\G \b require ((?>\s+) (?:$ignore_modules)) \b /oxmsgc) { return "# require$1"; }
4036 0         0  
4037 37         307 # use strict; --> use strict; no strict qw(refs);
4038 0         0 elsif (/\G \b use ((?>\s+) strict .*? ;) ([ \t]* [#\n]) /oxmsgc) { return "use$1 no strict qw(refs);$2"; }
4039             elsif (/\G \b use ((?>\s+) strict .*? ;) ([ \t]* [^#]) /oxmsgc) { return "use$1 no strict qw(refs);\n$2"; }
4040             elsif (/\G \b use ((?>\s+) strict) \b /oxmsgc) { return "use$1; no strict qw(refs)"; }
4041              
4042 0 50 33     0 # use 5.12.0; --> use 5.12.0; no strict qw(refs);
      33        
4043 2         22 elsif (/\G \b use (?>\s+) ((?>([1-9][0-9_]*)(?:\.([0-9_]+))*)) (?>\s*) ; /oxmsgc) {
4044             if (($2 >= 6) or (($2 == 5) and ($3 ge '012'))) {
4045             return "use $1; no strict qw(refs);";
4046 0         0 }
4047             else {
4048             return "use $1;";
4049             }
4050 2 0 0     11 }
      0        
4051 0         0 elsif (/\G \b use (?>\s+) ((?>v([0-9][0-9_]*)(?:\.([0-9_]+))*)) (?>\s*) ; /oxmsgc) {
4052             if (($2 >= 6) or (($2 == 5) and ($3 >= 12))) {
4053             return "use $1; no strict qw(refs);";
4054 0         0 }
4055             else {
4056             return "use $1;";
4057             }
4058             }
4059 0         0  
4060 2         14 # ignore use module
4061 0         0 elsif (/\G \b use ((?>\s+) (?:$ignore_modules) .*? ;) ([ \t]* [#\n]) /oxmsgc) { return "# use$1$2"; }
4062             elsif (/\G \b use ((?>\s+) (?:$ignore_modules) .*? ;) ([ \t]* [^#]) /oxmsgc) { return "# use$1\n$2"; }
4063             elsif (/\G \b use ((?>\s+) (?:$ignore_modules)) \b /oxmsgc) { return "# use$1"; }
4064 0         0  
4065 0         0 # ignore no module
4066 0         0 elsif (/\G \b no ((?>\s+) (?:$ignore_modules) .*? ;) ([ \t]* [#\n]) /oxmsgc) { return "# no$1$2"; }
4067             elsif (/\G \b no ((?>\s+) (?:$ignore_modules) .*? ;) ([ \t]* [^#]) /oxmsgc) { return "# no$1\n$2"; }
4068             elsif (/\G \b no ((?>\s+) (?:$ignore_modules)) \b /oxmsgc) { return "# no$1"; }
4069 0         0  
4070             # use else
4071             elsif (/\G \b use \b /oxmsgc) { return "use"; }
4072 0         0  
4073             # use else
4074             elsif (/\G \b no \b /oxmsgc) { return "no"; }
4075              
4076 2         8 # ''
4077 848         1733 elsif (/\G (?
4078 848 100       2378 my $q_string = '';
  8280 100       26206  
    100          
    50          
4079 4         10 while (not /\G \z/oxgc) {
4080 48         79 if (/\G (\\\\) /oxgc) { $q_string .= $1; }
4081 848         2596 elsif (/\G (\\\') /oxgc) { $q_string .= $1; }
4082             elsif (/\G \' /oxgc) { return e_q('', "'","'",$q_string); }
4083 7380         15552 elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
4084             }
4085             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4086             }
4087              
4088 0         0 # ""
4089 1858         3785 elsif (/\G (\") /oxgc) {
4090 1858 100       4875 my $qq_string = '';
  35661 100       122302  
    100          
    50          
4091 67         156 while (not /\G \z/oxgc) {
4092 12         24 if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
4093 1858         4262 elsif (/\G (\\\") /oxgc) { $qq_string .= $1; }
4094             elsif (/\G \" /oxgc) { return e_qq('', '"','"',$qq_string); }
4095 33724         67735 elsif (/\G ($q_char) /oxgc) { $qq_string .= $1; }
4096             }
4097             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4098             }
4099              
4100 0         0 # ``
4101 1         5 elsif (/\G (\`) /oxgc) {
4102 1 50       5 my $qx_string = '';
  19 50       126  
    100          
    50          
4103 0         0 while (not /\G \z/oxgc) {
4104 0         0 if (/\G (\\\\) /oxgc) { $qx_string .= $1; }
4105 1         4 elsif (/\G (\\\`) /oxgc) { $qx_string .= $1; }
4106             elsif (/\G \` /oxgc) { return e_qq('', '`','`',$qx_string); }
4107 18         36 elsif (/\G ($q_char) /oxgc) { $qx_string .= $1; }
4108             }
4109             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4110             }
4111              
4112 0         0 # // --- not divide operator (num / num), not defined-or
4113 453         2779 elsif (($slash eq 'm//') and /\G (\/) /oxgc) {
4114 453 50       17686 my $regexp = '';
  4496 50       18850  
    100          
    50          
4115 0         0 while (not /\G \z/oxgc) {
4116 0         0 if (/\G (\\\\) /oxgc) { $regexp .= $1; }
4117 453         1716 elsif (/\G (\\\/) /oxgc) { $regexp .= $1; }
4118             elsif (/\G \/ ([cgimosxpadlunbB]*) /oxgc) { return e_qr('', '/','/',$regexp,$1); }
4119 4043         25381 elsif (/\G ($q_char) /oxgc) { $regexp .= $1; }
4120             }
4121             die __FILE__, ": Search pattern not terminated\n";
4122             }
4123              
4124 0         0 # ?? --- not conditional operator (condition ? then : else)
4125 0         0 elsif (($slash eq 'm//') and /\G (\?) /oxgc) {
4126 0 0       0 my $regexp = '';
  0 0       0  
    0          
    0          
4127 0         0 while (not /\G \z/oxgc) {
4128 0         0 if (/\G (\\\\) /oxgc) { $regexp .= $1; }
4129 0         0 elsif (/\G (\\\?) /oxgc) { $regexp .= $1; }
4130             elsif (/\G \? ([cgimosxpadlunbB]*) /oxgc) { return e_qr('m','?','?',$regexp,$1); }
4131 0         0 elsif (/\G ($q_char) /oxgc) { $regexp .= $1; }
4132             }
4133             die __FILE__, ": Search pattern not terminated\n";
4134             }
4135 0         0  
  0         0  
4136             # <<>> (a safer ARGV)
4137             elsif (/\G ( <<>> ) /oxgc) { $slash = 'm//'; return $1; }
4138 0         0  
  0         0  
4139             # << (bit shift) --- not here document
4140             elsif (/\G ( << (?>\s*) ) (?= [0-9\$\@\&] ) /oxgc) { $slash = 'm//'; return $1; }
4141              
4142 0         0 # <<~'HEREDOC'
4143 6         11 elsif (/\G ( <<~ [\t ]* '([a-zA-Z_0-9]*)' ) /oxgc) {
4144 6         12 $slash = 'm//';
4145             my $here_quote = $1;
4146             my $delimiter = $2;
4147 6 50       8  
4148 6         12 # get here document
4149 6         28 if ($here_script eq '') {
4150             $here_script = CORE::substr $_, pos $_;
4151 6 50       31 $here_script =~ s/.*?\n//oxm;
4152 6         51 }
4153 6         13 if ($here_script =~ s/\A (.*?) \n ([\t ]*) $delimiter \n //xms) {
4154 6         9 my $heredoc = $1;
4155 6         55 my $indent = $2;
4156 6         18 $heredoc =~ s{^$indent}{}msg; # no /ox
4157             push @heredoc, $heredoc . qq{\n$delimiter\n};
4158             push @heredoc_delimiter, qq{\\s*$delimiter};
4159 6         11 }
4160             else {
4161 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4162             }
4163             return qq{<<'$delimiter'};
4164             }
4165              
4166             # <<~\HEREDOC
4167              
4168             # P.66 2.6.6. "Here" Documents
4169             # in Chapter 2: Bits and Pieces
4170             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
4171              
4172             # P.73 "Here" Documents
4173             # in Chapter 2: Bits and Pieces
4174             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
4175 6         23  
4176 3         6 elsif (/\G ( <<~ \\([a-zA-Z_0-9]+) ) /oxgc) {
4177 3         6 $slash = 'm//';
4178             my $here_quote = $1;
4179             my $delimiter = $2;
4180 3 50       6  
4181 3         7 # get here document
4182 3         27 if ($here_script eq '') {
4183             $here_script = CORE::substr $_, pos $_;
4184 3 50       21 $here_script =~ s/.*?\n//oxm;
4185 3         44 }
4186 3         7 if ($here_script =~ s/\A (.*?) \n ([\t ]*) $delimiter \n //xms) {
4187 3         5 my $heredoc = $1;
4188 3         37 my $indent = $2;
4189 3         11 $heredoc =~ s{^$indent}{}msg; # no /ox
4190             push @heredoc, $heredoc . qq{\n$delimiter\n};
4191             push @heredoc_delimiter, qq{\\s*$delimiter};
4192 3         8 }
4193             else {
4194 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4195             }
4196             return qq{<<\\$delimiter};
4197             }
4198              
4199 3         16 # <<~"HEREDOC"
4200 6         12 elsif (/\G ( <<~ [\t ]* "([a-zA-Z_0-9]*)" ) /oxgc) {
4201 6         13 $slash = 'm//';
4202             my $here_quote = $1;
4203             my $delimiter = $2;
4204 6 50       11  
4205 6         13 # get here document
4206 6         54 if ($here_script eq '') {
4207             $here_script = CORE::substr $_, pos $_;
4208 6 50       36 $here_script =~ s/.*?\n//oxm;
4209 6         60 }
4210 6         14 if ($here_script =~ s/\A (.*?) \n ([\t ]*) $delimiter \n //xms) {
4211 6         9 my $heredoc = $1;
4212 6         49 my $indent = $2;
4213 6         15 $heredoc =~ s{^$indent}{}msg; # no /ox
4214             push @heredoc, e_heredoc($heredoc) . qq{\n$delimiter\n};
4215             push @heredoc_delimiter, qq{\\s*$delimiter};
4216 6         14 }
4217             else {
4218 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4219             }
4220             return qq{<<"$delimiter"};
4221             }
4222              
4223 6         25 # <<~HEREDOC
4224 3         10 elsif (/\G ( <<~ ([a-zA-Z_0-9]+) ) /oxgc) {
4225 3         6 $slash = 'm//';
4226             my $here_quote = $1;
4227             my $delimiter = $2;
4228 3 50       8  
4229 3         8 # get here document
4230 3         13 if ($here_script eq '') {
4231             $here_script = CORE::substr $_, pos $_;
4232 3 50       18 $here_script =~ s/.*?\n//oxm;
4233 3         49 }
4234 3         9 if ($here_script =~ s/\A (.*?) \n ([\t ]*) $delimiter \n //xms) {
4235 3         6 my $heredoc = $1;
4236 3         41 my $indent = $2;
4237 3         12 $heredoc =~ s{^$indent}{}msg; # no /ox
4238             push @heredoc, e_heredoc($heredoc) . qq{\n$delimiter\n};
4239             push @heredoc_delimiter, qq{\\s*$delimiter};
4240 3         9 }
4241             else {
4242 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4243             }
4244             return qq{<<$delimiter};
4245             }
4246              
4247 3         13 # <<~`HEREDOC`
4248 6         14 elsif (/\G ( <<~ [\t ]* `([a-zA-Z_0-9]*)` ) /oxgc) {
4249 6         10 $slash = 'm//';
4250             my $here_quote = $1;
4251             my $delimiter = $2;
4252 6 50       11  
4253 6         14 # get here document
4254 6         19 if ($here_script eq '') {
4255             $here_script = CORE::substr $_, pos $_;
4256 6 50       27 $here_script =~ s/.*?\n//oxm;
4257 6         58 }
4258 6         22 if ($here_script =~ s/\A (.*?) \n ([\t ]*) $delimiter \n //xms) {
4259 6         10 my $heredoc = $1;
4260 6         50 my $indent = $2;
4261 6         17 $heredoc =~ s{^$indent}{}msg; # no /ox
4262             push @heredoc, e_heredoc($heredoc) . qq{\n$delimiter\n};
4263             push @heredoc_delimiter, qq{\\s*$delimiter};
4264 6         15 }
4265             else {
4266 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4267             }
4268             return qq{<<`$delimiter`};
4269             }
4270              
4271 6         22 # <<'HEREDOC'
4272 72         145 elsif (/\G ( << '([a-zA-Z_0-9]*)' ) /oxgc) {
4273 72         150 $slash = 'm//';
4274             my $here_quote = $1;
4275             my $delimiter = $2;
4276 72 50       110  
4277 72         149 # get here document
4278 72         393 if ($here_script eq '') {
4279             $here_script = CORE::substr $_, pos $_;
4280 72 50       404 $here_script =~ s/.*?\n//oxm;
4281 72         918 }
4282 72         297 if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4283             push @heredoc, $1 . qq{\n$delimiter\n};
4284             push @heredoc_delimiter, $delimiter;
4285 72         115 }
4286             else {
4287 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4288             }
4289             return $here_quote;
4290             }
4291              
4292             # <<\HEREDOC
4293              
4294             # P.66 2.6.6. "Here" Documents
4295             # in Chapter 2: Bits and Pieces
4296             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
4297              
4298             # P.73 "Here" Documents
4299             # in Chapter 2: Bits and Pieces
4300             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
4301 72         276  
4302 0         0 elsif (/\G ( << \\([a-zA-Z_0-9]+) ) /oxgc) {
4303 0         0 $slash = 'm//';
4304             my $here_quote = $1;
4305             my $delimiter = $2;
4306 0 0       0  
4307 0         0 # get here document
4308 0         0 if ($here_script eq '') {
4309             $here_script = CORE::substr $_, pos $_;
4310 0 0       0 $here_script =~ s/.*?\n//oxm;
4311 0         0 }
4312 0         0 if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4313             push @heredoc, $1 . qq{\n$delimiter\n};
4314             push @heredoc_delimiter, $delimiter;
4315 0         0 }
4316             else {
4317 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4318             }
4319             return $here_quote;
4320             }
4321              
4322 0         0 # <<"HEREDOC"
4323 36         84 elsif (/\G ( << "([a-zA-Z_0-9]*)" ) /oxgc) {
4324 36         178 $slash = 'm//';
4325             my $here_quote = $1;
4326             my $delimiter = $2;
4327 36 50       69  
4328 36         86 # get here document
4329 36         307 if ($here_script eq '') {
4330             $here_script = CORE::substr $_, pos $_;
4331 36 50       226 $here_script =~ s/.*?\n//oxm;
4332 36         483 }
4333 36         128 if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4334             push @heredoc, e_heredoc($1) . qq{\n$delimiter\n};
4335             push @heredoc_delimiter, $delimiter;
4336 36         148 }
4337             else {
4338 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4339             }
4340             return $here_quote;
4341             }
4342              
4343 36         172 # <
4344 42         140 elsif (/\G ( << ([a-zA-Z_0-9]+) ) /oxgc) {
4345 42         129 $slash = 'm//';
4346             my $here_quote = $1;
4347             my $delimiter = $2;
4348 42 50       81  
4349 42         166 # get here document
4350 42         343 if ($here_script eq '') {
4351             $here_script = CORE::substr $_, pos $_;
4352 42 50       320 $here_script =~ s/.*?\n//oxm;
4353 42         711 }
4354 42         161 if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4355             push @heredoc, e_heredoc($1) . qq{\n$delimiter\n};
4356             push @heredoc_delimiter, $delimiter;
4357 42         112 }
4358             else {
4359 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4360             }
4361             return $here_quote;
4362             }
4363              
4364 42         204 # <<`HEREDOC`
4365 0         0 elsif (/\G ( << `([a-zA-Z_0-9]*)` ) /oxgc) {
4366 0         0 $slash = 'm//';
4367             my $here_quote = $1;
4368             my $delimiter = $2;
4369 0 0       0  
4370 0         0 # get here document
4371 0         0 if ($here_script eq '') {
4372             $here_script = CORE::substr $_, pos $_;
4373 0 0       0 $here_script =~ s/.*?\n//oxm;
4374 0         0 }
4375 0         0 if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4376             push @heredoc, e_heredoc($1) . qq{\n$delimiter\n};
4377             push @heredoc_delimiter, $delimiter;
4378 0         0 }
4379             else {
4380 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4381             }
4382             return $here_quote;
4383             }
4384              
4385 0         0 # <<= <=> <= < operator
4386             elsif (/\G ( <<= | <=> | <= | < ) (?= (?>\s*) [A-Za-z_0-9'"`\$\@\&\*\(\+\-] )/oxgc) {
4387             return $1;
4388             }
4389              
4390 12         56 #
4391             elsif (/\G (<[\$]?[A-Za-z_][A-Za-z_0-9]*>) /oxgc) {
4392             return $1;
4393             }
4394              
4395             # --- glob
4396              
4397             # avoid "Error: Runtime exception" of perl version 5.005_03
4398 0         0  
4399             elsif (/\G < ((?:[^>\0\a\e\f\n\r\t])+?) > /oxgc) {
4400             return 'Ecyrillic::glob("' . $1 . '")';
4401             }
4402 0         0  
4403             # __DATA__
4404             elsif (/\G ^ ( __DATA__ \n .*) \z /oxmsgc) { return $1; }
4405 0         0  
4406             # __END__
4407             elsif (/\G ^ ( __END__ \n .*) \z /oxmsgc) { return $1; }
4408              
4409             # \cD Control-D
4410              
4411             # P.68 2.6.8. Other Literal Tokens
4412             # in Chapter 2: Bits and Pieces
4413             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
4414              
4415             # P.76 Other Literal Tokens
4416             # in Chapter 2: Bits and Pieces
4417 204         2016 # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
4418              
4419             elsif (/\G ( \cD .*) \z /oxmsgc) { return $1; }
4420 0         0  
4421             # \cZ Control-Z
4422             elsif (/\G ( \cZ .*) \z /oxmsgc) { return $1; }
4423              
4424             # any operator before div
4425             elsif (/\G (
4426             -- | \+\+ |
4427 0         0 [\)\}\]]
  5081         13430  
4428              
4429             ) /oxgc) { $slash = 'div'; return $1; }
4430              
4431             # yada-yada or triple-dot operator
4432             elsif (/\G (
4433 5081         24723 \.\.\.
  7         10  
4434              
4435             ) /oxgc) { $slash = 'm//'; return q{die('Unimplemented')}; }
4436              
4437             # any operator before m//
4438              
4439             # //, //= (defined-or)
4440              
4441             # P.164 Logical Operators
4442             # in Chapter 10: More Control Structures
4443             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
4444              
4445             # P.119 C-Style Logical (Short-Circuit) Operators
4446             # in Chapter 3: Unary and Binary Operators
4447             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
4448              
4449             # (and so on)
4450              
4451             # ~~
4452              
4453             # P.221 The Smart Match Operator
4454             # in Chapter 15: Smart Matching and given-when
4455             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
4456              
4457             # P.112 Smartmatch Operator
4458             # in Chapter 3: Unary and Binary Operators
4459             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
4460              
4461             # (and so on)
4462              
4463             elsif (/\G ((?>
4464              
4465             !~~ | !~ | != | ! |
4466             %= | % |
4467             &&= | && | &= | &\.= | &\. | & |
4468             -= | -> | - |
4469             :(?>\s*)= |
4470             : |
4471             <<>> |
4472             <<= | <=> | <= | < |
4473             == | => | =~ | = |
4474             >>= | >> | >= | > |
4475             \*\*= | \*\* | \*= | \* |
4476             \+= | \+ |
4477             \.\. | \.= | \. |
4478             \/\/= | \/\/ |
4479             \/= | \/ |
4480             \? |
4481             \\ |
4482             \^= | \^\.= | \^\. | \^ |
4483             \b x= |
4484             \|\|= | \|\| | \|= | \|\.= | \|\. | \| |
4485             ~~ | ~\. | ~ |
4486             \b(?: and | cmp | eq | ge | gt | le | lt | ne | not | or | xor | x )\b |
4487             \b(?: print )\b |
4488              
4489 7         26 [,;\(\{\[]
  8873         19233  
4490              
4491             )) /oxgc) { $slash = 'm//'; return $1; }
4492 8873         41624  
  15385         30997  
4493             # other any character
4494             elsif (/\G ($q_char) /oxgc) { $slash = 'div'; return $1; }
4495              
4496 15385         73762 # system error
4497             else {
4498             die __FILE__, ": Oops, this shouldn't happen!\n";
4499             }
4500             }
4501              
4502 0     1786 0 0 # escape Cyrillic string
4503 1786         4881 sub e_string {
4504             my($string) = @_;
4505 1786         2795 my $e_string = '';
4506              
4507             local $slash = 'm//';
4508              
4509             # P.1024 Appendix W.10 Multibyte Processing
4510             # of ISBN 1-56592-224-7 CJKV Information Processing
4511 1786         2598 # (and so on)
4512              
4513             my @char = $string =~ / \G (?>[^\\]|\\$q_char|$q_char) /oxmsg;
4514 1786 100 66     14712  
4515 1786 50       9657 # without { ... }
4516 1769         4620 if (not (grep(/\A \{ \z/xms, @char) and grep(/\A \} \z/xms, @char))) {
4517             if ($string !~ /<
4518             return $string;
4519             }
4520             }
4521 1769         4538  
4522 17 50       58 E_STRING_LOOP:
    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          
    50          
    50          
    50          
    50          
    50          
    100          
    50          
    100          
    50          
4523             while ($string !~ /\G \z/oxgc) {
4524             if (0) {
4525             }
4526 190         28285  
4527 0         0 # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> @{[Ecyrillic::PREMATCH()]}
4528 0         0 elsif ($string =~ /\G ( \$` | \$\{`\} | \$ (?>\s*) PREMATCH \b | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} ) /oxmsgc) {
4529             $e_string .= q{Ecyrillic::PREMATCH()};
4530             $slash = 'div';
4531             }
4532              
4533 0         0 # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> @{[Ecyrillic::MATCH()]}
4534 0         0 elsif ($string =~ /\G ( \$& | \$\{&\} | \$ (?>\s*) MATCH \b | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} ) /oxmsgc) {
4535             $e_string .= q{Ecyrillic::MATCH()};
4536             $slash = 'div';
4537             }
4538              
4539 0         0 # $', ${'} --> $', ${'}
4540 0         0 elsif ($string =~ /\G ( \$' | \$\{'\} ) /oxmsgc) {
4541             $e_string .= $1;
4542             $slash = 'div';
4543             }
4544              
4545 0         0 # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> @{[Ecyrillic::POSTMATCH()]}
4546 0         0 elsif ($string =~ /\G ( \$ (?>\s*) POSTMATCH \b | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} ) /oxmsgc) {
4547             $e_string .= q{Ecyrillic::POSTMATCH()};
4548             $slash = 'div';
4549             }
4550              
4551 0         0 # bareword
4552 0         0 elsif ($string =~ /\G ( \{ (?>\s*) (?: tr | index | rindex | reverse ) (?>\s*) \} ) /oxmsgc) {
4553             $e_string .= $1;
4554             $slash = 'div';
4555             }
4556              
4557 0         0 # $0 --> $0
4558 0         0 elsif ($string =~ /\G ( \$ 0 ) /oxmsgc) {
4559             $e_string .= $1;
4560             $slash = 'div';
4561 0         0 }
4562 0         0 elsif ($string =~ /\G ( \$ \{ (?>\s*) 0 (?>\s*) \} ) /oxmsgc) {
4563             $e_string .= $1;
4564             $slash = 'div';
4565             }
4566              
4567 0         0 # $$ --> $$
4568 0         0 elsif ($string =~ /\G ( \$ \$ ) (?![\w\{]) /oxmsgc) {
4569             $e_string .= $1;
4570             $slash = 'div';
4571             }
4572              
4573             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
4574 0         0 # $1, $2, $3 --> $1, $2, $3 otherwise
4575 0         0 elsif ($string =~ /\G \$ ((?>[1-9][0-9]*)) /oxmsgc) {
4576             $e_string .= e_capture($1);
4577             $slash = 'div';
4578 0         0 }
4579 0         0 elsif ($string =~ /\G \$ \{ (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} /oxmsgc) {
4580             $e_string .= e_capture($1);
4581             $slash = 'div';
4582             }
4583              
4584 0         0 # $$foo[ ... ] --> $ $foo->[ ... ]
4585 0         0 elsif ($string =~ /\G \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \[ .+? \] ) /oxmsgc) {
4586             $e_string .= e_capture($1.'->'.$2);
4587             $slash = 'div';
4588             }
4589              
4590 0         0 # $$foo{ ... } --> $ $foo->{ ... }
4591 0         0 elsif ($string =~ /\G \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \{ .+? \} ) /oxmsgc) {
4592             $e_string .= e_capture($1.'->'.$2);
4593             $slash = 'div';
4594             }
4595              
4596 0         0 # $$foo
4597 0         0 elsif ($string =~ /\G \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) /oxmsgc) {
4598             $e_string .= e_capture($1);
4599             $slash = 'div';
4600             }
4601              
4602 0         0 # ${ foo }
4603 0         0 elsif ($string =~ /\G \$ (?>\s*) \{ ((?> \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* )) \} /oxmsgc) {
4604             $e_string .= '${' . $1 . '}';
4605             $slash = 'div';
4606             }
4607              
4608 0         0 # ${ ... }
4609 3         8 elsif ($string =~ /\G \$ (?>\s*) \{ (?>\s*) ( $qq_brace ) (?>\s*) \} /oxmsgc) {
4610             $e_string .= e_capture($1);
4611             $slash = 'div';
4612             }
4613              
4614             # variable or function
4615 3         13 # $ @ % & * $ #
4616 7         29 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) {
4617             $e_string .= $1;
4618             $slash = 'div';
4619             }
4620             # $ $ $ $ $ $ $ $ $ $ $ $ $ $
4621 7         25 # $ @ # \ ' " / ? ( ) [ ] < >
4622 0         0 elsif ($string =~ /\G ( \$[\$\@\#\\\'\"\/\?\(\)\[\]\<\>] ) /oxmsgc) {
4623             $e_string .= $1;
4624             $slash = 'div';
4625             }
4626 0         0  
  0         0  
4627 0         0 # subroutines of package Ecyrillic
  0         0  
4628 0         0 elsif ($string =~ /\G \b (CORE:: | ->(>?\s*) (?: atan2 | [a-z]{2,})) \b /oxgc) { $e_string .= $1; $slash = 'm//'; }
  0         0  
4629 0         0 elsif ($string =~ /\G \b Char::eval (?= (?>\s*) \{ ) /oxgc) { $e_string .= 'eval'; $slash = 'm//'; }
  0         0  
4630 0         0 elsif ($string =~ /\G \b Cyrillic::eval (?= (?>\s*) \{ ) /oxgc) { $e_string .= 'eval'; $slash = 'm//'; }
  0         0  
4631 0         0 elsif ($string =~ /\G \b Char::eval \b /oxgc) { $e_string .= 'eval Char::escape'; $slash = 'm//'; }
  0         0  
4632 0         0 elsif ($string =~ /\G \b Cyrillic::eval \b /oxgc) { $e_string .= 'eval Cyrillic::escape'; $slash = 'm//'; }
  0         0  
4633 0         0 elsif ($string =~ /\G \b bytes::substr \b /oxgc) { $e_string .= 'substr'; $slash = 'm//'; }
  0         0  
4634 0         0 elsif ($string =~ /\G \b chop \b /oxgc) { $e_string .= 'Ecyrillic::chop'; $slash = 'm//'; }
  0         0  
4635 0         0 elsif ($string =~ /\G \b bytes::index \b /oxgc) { $e_string .= 'index'; $slash = 'm//'; }
  0         0  
4636 0         0 elsif ($string =~ /\G \b Char::index \b /oxgc) { $e_string .= 'Char::index'; $slash = 'm//'; }
  0         0  
4637 0         0 elsif ($string =~ /\G \b Cyrillic::index \b /oxgc) { $e_string .= 'Cyrillic::index'; $slash = 'm//'; }
  0         0  
4638 0         0 elsif ($string =~ /\G \b index \b /oxgc) { $e_string .= 'Ecyrillic::index'; $slash = 'm//'; }
  0         0  
4639 0         0 elsif ($string =~ /\G \b bytes::rindex \b /oxgc) { $e_string .= 'rindex'; $slash = 'm//'; }
  0         0  
4640 0         0 elsif ($string =~ /\G \b Char::rindex \b /oxgc) { $e_string .= 'Char::rindex'; $slash = 'm//'; }
  0         0  
4641 0         0 elsif ($string =~ /\G \b Cyrillic::rindex \b /oxgc) { $e_string .= 'Cyrillic::rindex'; $slash = 'm//'; }
  0         0  
4642 0         0 elsif ($string =~ /\G \b rindex \b /oxgc) { $e_string .= 'Ecyrillic::rindex'; $slash = 'm//'; }
  0         0  
4643 0         0 elsif ($string =~ /\G \b lc (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Ecyrillic::lc'; $slash = 'm//'; }
  0         0  
4644 0         0 elsif ($string =~ /\G \b lcfirst (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Ecyrillic::lcfirst'; $slash = 'm//'; }
  0         0  
4645 0         0 elsif ($string =~ /\G \b uc (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Ecyrillic::uc'; $slash = 'm//'; }
  0         0  
4646             elsif ($string =~ /\G \b ucfirst (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Ecyrillic::ucfirst'; $slash = 'm//'; }
4647             elsif ($string =~ /\G \b fc (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Ecyrillic::fc'; $slash = 'm//'; }
4648 0         0  
  0         0  
4649 0         0 # "-s '' ..." means file test "-s 'filename' ..." (not means "- s/// ...")
  0         0  
4650 0         0 elsif ($string =~ /\G -s (?>\s*) (\") ((?:$qq_char)+?) (\") /oxgc) { $e_string .= '-s ' . e_qq('', $1,$3,$2); $slash = 'm//'; }
  0         0  
4651 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  
4652 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  
4653 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  
4654 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  
4655             elsif ($string =~ /\G -s (?>\s+) qq (?>\s*) (\<) ((?:$qq_angle)+?) (\>) /oxgc) { $e_string .= '-s ' . e_qq('qq',$1,$3,$2); $slash = 'm//'; }
4656 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  
4657 0         0  
  0         0  
4658 0         0 elsif ($string =~ /\G -s (?>\s*) (\') ((?:\\\'|\\\\|$q_char)+?) (\') /oxgc) { $e_string .= '-s ' . e_q ('', $1,$3,$2); $slash = 'm//'; }
  0         0  
4659 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  
4660 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  
4661 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  
4662 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  
4663             elsif ($string =~ /\G -s (?>\s+) q (?>\s*) (\<) ((?:\\\>|\\\\|$q_angle)+?) (\>) /oxgc) { $e_string .= '-s ' . e_q ('q', $1,$3,$2); $slash = 'm//'; }
4664             elsif ($string =~ /\G -s (?>\s+) q (?>\s*) (\S) ((?:\\\1|\\\\|$q_char)+?) (\1) /oxgc) { $e_string .= '-s ' . e_q ('q', $1,$3,$2); $slash = 'm//'; }
4665 0         0  
  0         0  
4666 0         0 elsif ($string =~ /\G -s (?>\s*) (\$ (?> \w+ (?: ::\w+)*) (?: (?: ->)? (?: [\$\@\%\&\*]\* | \$\#\* | \( (?:$qq_paren)*? \) | [\@\%\*]? \{ (?:$qq_brace)+? \} | [\@\%]? \[ (?:$qq_bracket)+? \] ))*) /oxgc)
  0         0  
4667 0         0 { $e_string .= "-s $1"; $slash = 'm//'; }
  0         0  
4668 0         0 elsif ($string =~ /\G -s (?>\s*) \( ((?:$qq_paren)*?) \) /oxgc) { $e_string .= "-s ($1)"; $slash = 'm//'; }
  0         0  
4669             elsif ($string =~ /\G -s (?= (?>\s+) [a-z]+) /oxgc) { $e_string .= '-s'; $slash = 'm//'; }
4670 0         0 elsif ($string =~ /\G -s (?>\s+) ((?>\w+)) /oxgc) { $e_string .= "-s $1"; $slash = 'm//'; }
  0         0  
4671 0         0  
  0         0  
4672 0         0 elsif ($string =~ /\G \b bytes::length (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'length'; $slash = 'm//'; }
  0         0  
4673 0         0 elsif ($string =~ /\G \b bytes::chr (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'chr'; $slash = 'm//'; }
  0         0  
4674 0         0 elsif ($string =~ /\G \b chr (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Ecyrillic::chr'; $slash = 'm//'; }
  0         0  
4675 0         0 elsif ($string =~ /\G \b bytes::ord (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'ord'; $slash = 'div'; }
  0         0  
4676 0         0 elsif ($string =~ /\G \b ord (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $e_string .= $function_ord; $slash = 'div'; }
  0         0  
4677 0         0 elsif ($string =~ /\G \b glob (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Ecyrillic::glob'; $slash = 'm//'; }
  0         0  
4678 0         0 elsif ($string =~ /\G \b lc \b /oxgc) { $e_string .= 'Ecyrillic::lc_'; $slash = 'm//'; }
  0         0  
4679 0         0 elsif ($string =~ /\G \b lcfirst \b /oxgc) { $e_string .= 'Ecyrillic::lcfirst_'; $slash = 'm//'; }
  0         0  
4680 0         0 elsif ($string =~ /\G \b uc \b /oxgc) { $e_string .= 'Ecyrillic::uc_'; $slash = 'm//'; }
  0         0  
4681 0         0 elsif ($string =~ /\G \b ucfirst \b /oxgc) { $e_string .= 'Ecyrillic::ucfirst_'; $slash = 'm//'; }
  0         0  
4682             elsif ($string =~ /\G \b fc \b /oxgc) { $e_string .= 'Ecyrillic::fc_'; $slash = 'm//'; }
4683 0         0 elsif ($string =~ /\G -s \b /oxgc) { $e_string .= '-s '; $slash = 'm//'; }
  0         0  
4684 0         0  
  0         0  
4685 0         0 elsif ($string =~ /\G \b bytes::length \b /oxgc) { $e_string .= 'length'; $slash = 'm//'; }
  0         0  
4686 0         0 elsif ($string =~ /\G \b bytes::chr \b /oxgc) { $e_string .= 'chr'; $slash = 'm//'; }
  0         0  
4687 0         0 elsif ($string =~ /\G \b chr \b /oxgc) { $e_string .= 'Ecyrillic::chr_'; $slash = 'm//'; }
  0         0  
4688 0         0 elsif ($string =~ /\G \b bytes::ord \b /oxgc) { $e_string .= 'ord'; $slash = 'div'; }
  0         0  
4689 0         0 elsif ($string =~ /\G \b ord \b /oxgc) { $e_string .= $function_ord_; $slash = 'div'; }
  0         0  
4690 0         0 elsif ($string =~ /\G \b glob \b /oxgc) { $e_string .= 'Ecyrillic::glob_'; $slash = 'm//'; }
  0         0  
4691             elsif ($string =~ /\G \b reverse \b /oxgc) { $e_string .= $function_reverse; $slash = 'm//'; }
4692             elsif ($string =~ /\G \b getc \b /oxgc) { $e_string .= $function_getc; $slash = 'm//'; }
4693 0         0 # split
4694             elsif ($string =~ /\G \b (split) \b (?! (?>\s*) => ) /oxgc) {
4695 0         0 $slash = 'm//';
4696 0         0  
4697 0         0 my $e = '';
4698             while ($string =~ /\G ( (?>\s+) | \( | \#.* ) /oxgc) {
4699             $e .= $1;
4700             }
4701 0 0       0  
  0 0       0  
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
4702             # end of split
4703             if ($string =~ /\G (?= [,;\)\}\]] ) /oxgc) { return 'Ecyrillic::split' . $e; }
4704 0         0  
  0         0  
4705             # split scalar value
4706             elsif ($string =~ /\G ( [\$\@\&\*] $qq_scalar ) /oxgc) { $e_string .= 'Ecyrillic::split' . $e . e_string($1); next E_STRING_LOOP; }
4707 0         0  
  0         0  
4708 0         0 # split literal space
  0         0  
4709 0         0 elsif ($string =~ /\G \b qq (\#) [ ] (\#) /oxgc) { $e_string .= 'Ecyrillic::split' . $e . qq {qq$1 $2}; next E_STRING_LOOP; }
  0         0  
4710 0         0 elsif ($string =~ /\G \b qq ((?>\s*)) (\() [ ] (\)) /oxgc) { $e_string .= 'Ecyrillic::split' . $e . qq{$1qq$2 $3}; next E_STRING_LOOP; }
  0         0  
4711 0         0 elsif ($string =~ /\G \b qq ((?>\s*)) (\{) [ ] (\}) /oxgc) { $e_string .= 'Ecyrillic::split' . $e . qq{$1qq$2 $3}; next E_STRING_LOOP; }
  0         0  
4712 0         0 elsif ($string =~ /\G \b qq ((?>\s*)) (\[) [ ] (\]) /oxgc) { $e_string .= 'Ecyrillic::split' . $e . qq{$1qq$2 $3}; next E_STRING_LOOP; }
  0         0  
4713 0         0 elsif ($string =~ /\G \b qq ((?>\s*)) (\<) [ ] (\>) /oxgc) { $e_string .= 'Ecyrillic::split' . $e . qq{$1qq$2 $3}; next E_STRING_LOOP; }
  0         0  
4714 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  
4715 0         0 elsif ($string =~ /\G \b q (\#) [ ] (\#) /oxgc) { $e_string .= 'Ecyrillic::split' . $e . qq {q$1 $2}; next E_STRING_LOOP; }
  0         0  
4716 0         0 elsif ($string =~ /\G \b q ((?>\s*)) (\() [ ] (\)) /oxgc) { $e_string .= 'Ecyrillic::split' . $e . qq {$1q$2 $3}; next E_STRING_LOOP; }
  0         0  
4717 0         0 elsif ($string =~ /\G \b q ((?>\s*)) (\{) [ ] (\}) /oxgc) { $e_string .= 'Ecyrillic::split' . $e . qq {$1q$2 $3}; next E_STRING_LOOP; }
  0         0  
4718 0         0 elsif ($string =~ /\G \b q ((?>\s*)) (\[) [ ] (\]) /oxgc) { $e_string .= 'Ecyrillic::split' . $e . qq {$1q$2 $3}; next E_STRING_LOOP; }
  0         0  
4719 0         0 elsif ($string =~ /\G \b q ((?>\s*)) (\<) [ ] (\>) /oxgc) { $e_string .= 'Ecyrillic::split' . $e . qq {$1q$2 $3}; next E_STRING_LOOP; }
  0         0  
4720 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  
4721             elsif ($string =~ /\G ' [ ] ' /oxgc) { $e_string .= 'Ecyrillic::split' . $e . qq {' '}; next E_STRING_LOOP; }
4722             elsif ($string =~ /\G " [ ] " /oxgc) { $e_string .= 'Ecyrillic::split' . $e . qq {" "}; next E_STRING_LOOP; }
4723              
4724 0 0       0 # split qq//
  0         0  
  0         0  
4725             elsif ($string =~ /\G \b (qq) \b /oxgc) {
4726 0         0 if ($string =~ /\G (\#) ((?:$qq_char)*?) (\#) /oxgc) { $e_string .= e_split($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # qq# # --> qr # #
4727 0 0       0 else {
  0 0       0  
    0          
    0          
    0          
    0          
    0          
4728 0         0 while ($string !~ /\G \z/oxgc) {
  0         0  
4729 0         0 if ($string =~ /\G ((?>\s+)|\#.*) /oxgc) { $e_string .= $e . $1; }
  0         0  
4730 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  
4731 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  
4732 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  
4733 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  
4734             elsif ($string =~ /\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) /oxgc) { $e_string .= e_split($e.'qr','{','}',$2,''); next E_STRING_LOOP; } # qq | | --> qr { }
4735 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 * *
4736             }
4737             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4738             }
4739             }
4740              
4741 0 0       0 # split qr//
  0         0  
  0         0  
4742             elsif ($string =~ /\G \b (qr) \b /oxgc) {
4743 0         0 if ($string =~ /\G (\#) ((?:$qq_char)*?) (\#) ([imosxpadlunbB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1,$3,$2,$4); next E_STRING_LOOP; } # qr# #
4744 0 0       0 else {
  0 0       0  
    0          
    0          
    0          
    0          
    0          
    0          
4745 0         0 while ($string !~ /\G \z/oxgc) {
  0         0  
4746 0         0 if ($string =~ /\G ((?>\s+)|\#.*) /oxgc) { $e_string .= $e . $1; }
  0         0  
4747 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  
4748 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  
4749 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  
4750 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  
4751 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  
4752             elsif ($string =~ /\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ([imosxpadlunbB]*) /oxgc) { $e_string .= e_split ($e.'qr','{','}',$2,$4); next E_STRING_LOOP; } # qr | | --> qr { }
4753 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 * *
4754             }
4755             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4756             }
4757             }
4758              
4759 0 0       0 # split q//
  0         0  
  0         0  
4760             elsif ($string =~ /\G \b (q) \b /oxgc) {
4761 0         0 if ($string =~ /\G (\#) ((?:\\\#|\\\\|$q_char)*?) (\#) /oxgc) { $e_string .= e_split_q($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # q# # --> qr # #
4762 0 0       0 else {
  0 0       0  
    0          
    0          
    0          
    0          
    0          
4763 0         0 while ($string !~ /\G \z/oxgc) {
  0         0  
4764 0         0 if ($string =~ /\G ((?>\s+)|\#.*) /oxgc) { $e_string .= $e . $1; }
  0         0  
4765 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  
4766 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  
4767 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  
4768 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  
4769             elsif ($string =~ /\G ([*\-:?\\^|]) ((?:$q_char)*?) (\1) /oxgc) { $e_string .= e_split_q($e.'qr','{','}',$2,''); next E_STRING_LOOP; } # q | | --> qr { }
4770 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 * *
4771             }
4772             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4773             }
4774             }
4775              
4776 0 0       0 # split m//
  0         0  
  0         0  
4777             elsif ($string =~ /\G \b (m) \b /oxgc) {
4778 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 # #
4779 0 0       0 else {
  0 0       0  
    0          
    0          
    0          
    0          
    0          
    0          
4780 0         0 while ($string !~ /\G \z/oxgc) {
  0         0  
4781 0         0 if ($string =~ /\G ((?>\s+)|\#.*) /oxgc) { $e_string .= $e . $1; }
  0         0  
4782 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  
4783 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  
4784 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  
4785 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  
4786 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  
4787             elsif ($string =~ /\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ([cgimosxpadlunbB]*) /oxgc) { $e_string .= e_split ($e.'qr','{','}',$2,$4); next E_STRING_LOOP; } # m | | --> qr { }
4788 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 * *
4789             }
4790             die __FILE__, ": Search pattern not terminated\n";
4791             }
4792             }
4793              
4794 0         0 # split ''
4795 0         0 elsif ($string =~ /\G (\') /oxgc) {
4796 0 0       0 my $q_string = '';
  0 0       0  
    0          
    0          
4797 0         0 while ($string !~ /\G \z/oxgc) {
4798 0         0 if ($string =~ /\G (\\\\) /oxgc) { $q_string .= $1; }
  0         0  
4799 0         0 elsif ($string =~ /\G (\\\') /oxgc) { $q_string .= $1; } # splitqr'' --> split qr''
4800             elsif ($string =~ /\G \' /oxgc) { $e_string .= e_split_q($e.q{ qr},"'","'",$q_string,''); next E_STRING_LOOP; } # ' ' --> qr ' '
4801 0         0 elsif ($string =~ /\G ($q_char) /oxgc) { $q_string .= $1; }
4802             }
4803             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4804             }
4805              
4806 0         0 # split ""
4807 0         0 elsif ($string =~ /\G (\") /oxgc) {
4808 0 0       0 my $qq_string = '';
  0 0       0  
    0          
    0          
4809 0         0 while ($string !~ /\G \z/oxgc) {
4810 0         0 if ($string =~ /\G (\\\\) /oxgc) { $qq_string .= $1; }
  0         0  
4811 0         0 elsif ($string =~ /\G (\\\") /oxgc) { $qq_string .= $1; } # splitqr"" --> split qr""
4812             elsif ($string =~ /\G \" /oxgc) { $e_string .= e_split($e.q{ qr},'"','"',$qq_string,''); next E_STRING_LOOP; } # " " --> qr " "
4813 0         0 elsif ($string =~ /\G ($q_char) /oxgc) { $qq_string .= $1; }
4814             }
4815             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4816             }
4817              
4818 0         0 # split //
4819 0         0 elsif ($string =~ /\G (\/) /oxgc) {
4820 0 0       0 my $regexp = '';
  0 0       0  
    0          
    0          
4821 0         0 while ($string !~ /\G \z/oxgc) {
4822 0         0 if ($string =~ /\G (\\\\) /oxgc) { $regexp .= $1; }
  0         0  
4823 0         0 elsif ($string =~ /\G (\\\/) /oxgc) { $regexp .= $1; } # splitqr// --> split qr//
4824             elsif ($string =~ /\G \/ ([cgimosxpadlunbB]*) /oxgc) { $e_string .= e_split($e.q{ qr}, '/','/',$regexp,$1); next E_STRING_LOOP; } # / / --> qr / /
4825 0         0 elsif ($string =~ /\G ($q_char) /oxgc) { $regexp .= $1; }
4826             }
4827             die __FILE__, ": Search pattern not terminated\n";
4828             }
4829             }
4830              
4831 0         0 # qq//
4832 0 0       0 elsif ($string =~ /\G \b (qq) \b /oxgc) {
4833 0         0 my $ope = $1;
4834             if ($string =~ /\G (\#) ((?:$qq_char)*?) (\#) /oxgc) { # qq# #
4835             $e_string .= e_qq($ope,$1,$3,$2);
4836 0         0 }
4837 0         0 else {
4838 0 0       0 my $e = '';
  0 0       0  
    0          
    0          
    0          
    0          
4839 0         0 while ($string !~ /\G \z/oxgc) {
  0         0  
4840 0         0 if ($string =~ /\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0         0  
4841 0         0 elsif ($string =~ /\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qq ( )
  0         0  
4842 0         0 elsif ($string =~ /\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qq { }
  0         0  
4843 0         0 elsif ($string =~ /\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qq [ ]
  0         0  
4844             elsif ($string =~ /\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qq < >
4845 0         0 elsif ($string =~ /\G (\S) ((?:$qq_char)*?) (\1) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qq * *
4846             }
4847             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4848             }
4849             }
4850              
4851 0         0 # qx//
4852 0 0       0 elsif ($string =~ /\G \b (qx) \b /oxgc) {
4853 0         0 my $ope = $1;
4854             if ($string =~ /\G (\#) ((?:$qq_char)*?) (\#) /oxgc) { # qx# #
4855             $e_string .= e_qq($ope,$1,$3,$2);
4856 0         0 }
4857 0         0 else {
4858 0 0       0 my $e = '';
  0 0       0  
    0          
    0          
    0          
    0          
    0          
4859 0         0 while ($string !~ /\G \z/oxgc) {
  0         0  
4860 0         0 if ($string =~ /\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0         0  
4861 0         0 elsif ($string =~ /\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qx ( )
  0         0  
4862 0         0 elsif ($string =~ /\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qx { }
  0         0  
4863 0         0 elsif ($string =~ /\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qx [ ]
  0         0  
4864 0         0 elsif ($string =~ /\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qx < >
  0         0  
4865             elsif ($string =~ /\G (\') ((?:$qq_char)*?) (\') /oxgc) { $e_string .= $e . e_q ($ope,$1,$3,$2); next E_STRING_LOOP; } # qx ' '
4866 0         0 elsif ($string =~ /\G (\S) ((?:$qq_char)*?) (\1) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qx * *
4867             }
4868             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4869             }
4870             }
4871              
4872 0         0 # q//
4873 0 0       0 elsif ($string =~ /\G \b (q) \b /oxgc) {
4874 0         0 my $ope = $1;
4875             if ($string =~ /\G (\#) ((?:\\\#|\\\\|$q_char)*?) (\#) /oxgc) { # q# #
4876             $e_string .= e_q($ope,$1,$3,$2);
4877 0         0 }
4878 0         0 else {
4879 0 0       0 my $e = '';
  0 0       0  
    0          
    0          
    0          
    0          
4880 0         0 while ($string !~ /\G \z/oxgc) {
  0         0  
4881 0         0 if ($string =~ /\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0         0  
4882 0         0 elsif ($string =~ /\G (\() ((?:\\\\|\\\)|\\\(|$q_paren)*?) (\)) /oxgc) { $e_string .= $e . e_q($ope,$1,$3,$2); next E_STRING_LOOP; } # q ( )
  0         0  
4883 0         0 elsif ($string =~ /\G (\{) ((?:\\\\|\\\}|\\\{|$q_brace)*?) (\}) /oxgc) { $e_string .= $e . e_q($ope,$1,$3,$2); next E_STRING_LOOP; } # q { }
  0         0  
4884 0         0 elsif ($string =~ /\G (\[) ((?:\\\\|\\\]|\\\[|$q_bracket)*?) (\]) /oxgc) { $e_string .= $e . e_q($ope,$1,$3,$2); next E_STRING_LOOP; } # q [ ]
  0         0  
4885             elsif ($string =~ /\G (\<) ((?:\\\\|\\\>|\\\<|$q_angle)*?) (\>) /oxgc) { $e_string .= $e . e_q($ope,$1,$3,$2); next E_STRING_LOOP; } # q < >
4886 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 * *
4887             }
4888             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4889             }
4890             }
4891 0         0  
4892             # ''
4893             elsif ($string =~ /\G (?
4894 0         0  
4895             # ""
4896             elsif ($string =~ /\G (\") ((?:$qq_char)*?) (\") /oxgc) { $e_string .= e_qq('',$1,$3,$2); }
4897 0         0  
4898             # ``
4899             elsif ($string =~ /\G (\`) ((?:$qq_char)*?) (\`) /oxgc) { $e_string .= e_qq('',$1,$3,$2); }
4900 0         0  
4901             # <<>> (a safer ARGV)
4902             elsif ($string =~ /\G ( <<>> ) /oxgc) { $e_string .= $1; }
4903 0         0  
4904             # <<= <=> <= < operator
4905             elsif ($string =~ /\G ( <<= | <=> | <= | < ) (?= (?>\s*) [A-Za-z_0-9'"`\$\@\&\*\(\+\-] )/oxgc) { $e_string .= $1; }
4906 0         0  
4907             #
4908             elsif ($string =~ /\G (<[\$]?[A-Za-z_][A-Za-z_0-9]*>) /oxgc) { $e_string .= $1; }
4909              
4910 0         0 # --- glob
4911             elsif ($string =~ /\G < ((?:$q_char)+?) > /oxgc) {
4912             $e_string .= 'Ecyrillic::glob("' . $1 . '")';
4913             }
4914              
4915 0         0 # << (bit shift) --- not here document
4916 0         0 elsif ($string =~ /\G ( << (?>\s*) ) (?= [0-9\$\@\&] ) /oxgc) {
4917             $slash = 'm//';
4918             $e_string .= $1;
4919             }
4920              
4921 0         0 # <<~'HEREDOC'
4922 0         0 elsif ($string =~ /\G ( <<~ [\t ]* '([a-zA-Z_0-9]*)' ) /oxgc) {
4923 0         0 $slash = 'm//';
4924             my $here_quote = $1;
4925             my $delimiter = $2;
4926 0 0       0  
4927 0         0 # get here document
4928 0         0 if ($here_script eq '') {
4929             $here_script = CORE::substr $_, pos $_;
4930 0 0       0 $here_script =~ s/.*?\n//oxm;
4931 0         0 }
4932 0         0 if ($here_script =~ s/\A (.*?) \n ([\t ]*) $delimiter \n //xms) {
4933 0         0 my $heredoc = $1;
4934 0         0 my $indent = $2;
4935 0         0 $heredoc =~ s{^$indent}{}msg; # no /ox
4936             push @heredoc, $heredoc . qq{\n$delimiter\n};
4937             push @heredoc_delimiter, qq{\\s*$delimiter};
4938 0         0 }
4939             else {
4940 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4941             }
4942             $e_string .= qq{<<'$delimiter'};
4943             }
4944              
4945 0         0 # <<~\HEREDOC
4946 0         0 elsif ($string =~ /\G ( <<~ \\([a-zA-Z_0-9]+) ) /oxgc) {
4947 0         0 $slash = 'm//';
4948             my $here_quote = $1;
4949             my $delimiter = $2;
4950 0 0       0  
4951 0         0 # get here document
4952 0         0 if ($here_script eq '') {
4953             $here_script = CORE::substr $_, pos $_;
4954 0 0       0 $here_script =~ s/.*?\n//oxm;
4955 0         0 }
4956 0         0 if ($here_script =~ s/\A (.*?) \n ([\t ]*) $delimiter \n //xms) {
4957 0         0 my $heredoc = $1;
4958 0         0 my $indent = $2;
4959 0         0 $heredoc =~ s{^$indent}{}msg; # no /ox
4960             push @heredoc, $heredoc . qq{\n$delimiter\n};
4961             push @heredoc_delimiter, qq{\\s*$delimiter};
4962 0         0 }
4963             else {
4964 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4965             }
4966             $e_string .= qq{<<\\$delimiter};
4967             }
4968              
4969 0         0 # <<~"HEREDOC"
4970 0         0 elsif ($string =~ /\G ( <<~ [\t ]* "([a-zA-Z_0-9]*)" ) /oxgc) {
4971 0         0 $slash = 'm//';
4972             my $here_quote = $1;
4973             my $delimiter = $2;
4974 0 0       0  
4975 0         0 # get here document
4976 0         0 if ($here_script eq '') {
4977             $here_script = CORE::substr $_, pos $_;
4978 0 0       0 $here_script =~ s/.*?\n//oxm;
4979 0         0 }
4980 0         0 if ($here_script =~ s/\A (.*?) \n ([\t ]*) $delimiter \n //xms) {
4981 0         0 my $heredoc = $1;
4982 0         0 my $indent = $2;
4983 0         0 $heredoc =~ s{^$indent}{}msg; # no /ox
4984             push @heredoc, e_heredoc($heredoc) . qq{\n$delimiter\n};
4985             push @heredoc_delimiter, qq{\\s*$delimiter};
4986 0         0 }
4987             else {
4988 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4989             }
4990             $e_string .= qq{<<"$delimiter"};
4991             }
4992              
4993 0         0 # <<~HEREDOC
4994 0         0 elsif ($string =~ /\G ( <<~ ([a-zA-Z_0-9]+) ) /oxgc) {
4995 0         0 $slash = 'm//';
4996             my $here_quote = $1;
4997             my $delimiter = $2;
4998 0 0       0  
4999 0         0 # get here document
5000 0         0 if ($here_script eq '') {
5001             $here_script = CORE::substr $_, pos $_;
5002 0 0       0 $here_script =~ s/.*?\n//oxm;
5003 0         0 }
5004 0         0 if ($here_script =~ s/\A (.*?) \n ([\t ]*) $delimiter \n //xms) {
5005 0         0 my $heredoc = $1;
5006 0         0 my $indent = $2;
5007 0         0 $heredoc =~ s{^$indent}{}msg; # no /ox
5008             push @heredoc, e_heredoc($heredoc) . qq{\n$delimiter\n};
5009             push @heredoc_delimiter, qq{\\s*$delimiter};
5010 0         0 }
5011             else {
5012 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
5013             }
5014             $e_string .= qq{<<$delimiter};
5015             }
5016              
5017 0         0 # <<~`HEREDOC`
5018 0         0 elsif ($string =~ /\G ( <<~ [\t ]* `([a-zA-Z_0-9]*)` ) /oxgc) {
5019 0         0 $slash = 'm//';
5020             my $here_quote = $1;
5021             my $delimiter = $2;
5022 0 0       0  
5023 0         0 # get here document
5024 0         0 if ($here_script eq '') {
5025             $here_script = CORE::substr $_, pos $_;
5026 0 0       0 $here_script =~ s/.*?\n//oxm;
5027 0         0 }
5028 0         0 if ($here_script =~ s/\A (.*?) \n ([\t ]*) $delimiter \n //xms) {
5029 0         0 my $heredoc = $1;
5030 0         0 my $indent = $2;
5031 0         0 $heredoc =~ s{^$indent}{}msg; # no /ox
5032             push @heredoc, e_heredoc($heredoc) . qq{\n$delimiter\n};
5033             push @heredoc_delimiter, qq{\\s*$delimiter};
5034 0         0 }
5035             else {
5036 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
5037             }
5038             $e_string .= qq{<<`$delimiter`};
5039             }
5040              
5041 0         0 # <<'HEREDOC'
5042 0         0 elsif ($string =~ /\G ( << '([a-zA-Z_0-9]*)' ) /oxgc) {
5043 0         0 $slash = 'm//';
5044             my $here_quote = $1;
5045             my $delimiter = $2;
5046 0 0       0  
5047 0         0 # get here document
5048 0         0 if ($here_script eq '') {
5049             $here_script = CORE::substr $_, pos $_;
5050 0 0       0 $here_script =~ s/.*?\n//oxm;
5051 0         0 }
5052 0         0 if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
5053             push @heredoc, $1 . qq{\n$delimiter\n};
5054             push @heredoc_delimiter, $delimiter;
5055 0         0 }
5056             else {
5057 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
5058             }
5059             $e_string .= $here_quote;
5060             }
5061              
5062 0         0 # <<\HEREDOC
5063 0         0 elsif ($string =~ /\G ( << \\([a-zA-Z_0-9]+) ) /oxgc) {
5064 0         0 $slash = 'm//';
5065             my $here_quote = $1;
5066             my $delimiter = $2;
5067 0 0       0  
5068 0         0 # get here document
5069 0         0 if ($here_script eq '') {
5070             $here_script = CORE::substr $_, pos $_;
5071 0 0       0 $here_script =~ s/.*?\n//oxm;
5072 0         0 }
5073 0         0 if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
5074             push @heredoc, $1 . qq{\n$delimiter\n};
5075             push @heredoc_delimiter, $delimiter;
5076 0         0 }
5077             else {
5078 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
5079             }
5080             $e_string .= $here_quote;
5081             }
5082              
5083 0         0 # <<"HEREDOC"
5084 0         0 elsif ($string =~ /\G ( << "([a-zA-Z_0-9]*)" ) /oxgc) {
5085 0         0 $slash = 'm//';
5086             my $here_quote = $1;
5087             my $delimiter = $2;
5088 0 0       0  
5089 0         0 # get here document
5090 0         0 if ($here_script eq '') {
5091             $here_script = CORE::substr $_, pos $_;
5092 0 0       0 $here_script =~ s/.*?\n//oxm;
5093 0         0 }
5094 0         0 if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
5095             push @heredoc, e_heredoc($1) . qq{\n$delimiter\n};
5096             push @heredoc_delimiter, $delimiter;
5097 0         0 }
5098             else {
5099 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
5100             }
5101             $e_string .= $here_quote;
5102             }
5103              
5104 0         0 # <
5105 0         0 elsif ($string =~ /\G ( << ([a-zA-Z_0-9]+) ) /oxgc) {
5106 0         0 $slash = 'm//';
5107             my $here_quote = $1;
5108             my $delimiter = $2;
5109 0 0       0  
5110 0         0 # get here document
5111 0         0 if ($here_script eq '') {
5112             $here_script = CORE::substr $_, pos $_;
5113 0 0       0 $here_script =~ s/.*?\n//oxm;
5114 0         0 }
5115 0         0 if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
5116             push @heredoc, e_heredoc($1) . qq{\n$delimiter\n};
5117             push @heredoc_delimiter, $delimiter;
5118 0         0 }
5119             else {
5120 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
5121             }
5122             $e_string .= $here_quote;
5123             }
5124              
5125 0         0 # <<`HEREDOC`
5126 0         0 elsif ($string =~ /\G ( << `([a-zA-Z_0-9]*)` ) /oxgc) {
5127 0         0 $slash = 'm//';
5128             my $here_quote = $1;
5129             my $delimiter = $2;
5130 0 0       0  
5131 0         0 # get here document
5132 0         0 if ($here_script eq '') {
5133             $here_script = CORE::substr $_, pos $_;
5134 0 0       0 $here_script =~ s/.*?\n//oxm;
5135 0         0 }
5136 0         0 if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
5137             push @heredoc, e_heredoc($1) . qq{\n$delimiter\n};
5138             push @heredoc_delimiter, $delimiter;
5139 0         0 }
5140             else {
5141 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
5142             }
5143             $e_string .= $here_quote;
5144             }
5145              
5146             # any operator before div
5147             elsif ($string =~ /\G (
5148             -- | \+\+ |
5149 0         0 [\)\}\]]
  18         37  
5150              
5151             ) /oxgc) { $slash = 'div'; $e_string .= $1; }
5152              
5153             # yada-yada or triple-dot operator
5154             elsif ($string =~ /\G (
5155 18         152 \.\.\.
  0         0  
5156              
5157             ) /oxgc) { $slash = 'm//'; $e_string .= q{die('Unimplemented')}; }
5158              
5159             # any operator before m//
5160             elsif ($string =~ /\G ((?>
5161              
5162             !~~ | !~ | != | ! |
5163             %= | % |
5164             &&= | && | &= | &\.= | &\. | & |
5165             -= | -> | - |
5166             :(?>\s*)= |
5167             : |
5168             <<>> |
5169             <<= | <=> | <= | < |
5170             == | => | =~ | = |
5171             >>= | >> | >= | > |
5172             \*\*= | \*\* | \*= | \* |
5173             \+= | \+ |
5174             \.\. | \.= | \. |
5175             \/\/= | \/\/ |
5176             \/= | \/ |
5177             \? |
5178             \\ |
5179             \^= | \^\.= | \^\. | \^ |
5180             \b x= |
5181             \|\|= | \|\| | \|= | \|\.= | \|\. | \| |
5182             ~~ | ~\. | ~ |
5183             \b(?: and | cmp | eq | ge | gt | le | lt | ne | not | or | xor | x )\b |
5184             \b(?: print )\b |
5185              
5186 0         0 [,;\(\{\[]
  31         62  
5187              
5188             )) /oxgc) { $slash = 'm//'; $e_string .= $1; }
5189 31         117  
5190             # other any character
5191             elsif ($string =~ /\G ($q_char) /oxgc) { $e_string .= $1; }
5192              
5193 131         394 # system error
5194             else {
5195             die __FILE__, ": Oops, this shouldn't happen!\n";
5196             }
5197 0         0 }
5198              
5199             return $e_string;
5200             }
5201              
5202             #
5203             # character class
5204 17     1919 0 84 #
5205             sub character_class {
5206 1919 100       3546 my($char,$modifier) = @_;
5207 1919 100       3200  
5208 52         111 if ($char eq '.') {
5209             if ($modifier =~ /s/) {
5210             return '${Ecyrillic::dot_s}';
5211 17         40 }
5212             else {
5213             return '${Ecyrillic::dot}';
5214             }
5215 35         77 }
5216             else {
5217             return Ecyrillic::classic_character_class($char);
5218             }
5219             }
5220              
5221             #
5222             # escape capture ($1, $2, $3, ...)
5223             #
5224 1867     212 0 3526 sub e_capture {
5225              
5226             return join '', '${', $_[0], '}';
5227             }
5228              
5229             #
5230             # escape transliteration (tr/// or y///)
5231 212     3 0 924 #
5232 3         25 sub e_tr {
5233 3   50     6 my($variable,$charclass,$e,$charclass2,$modifier) = @_;
5234             my $e_tr = '';
5235 3         6 $modifier ||= '';
5236              
5237             $slash = 'div';
5238 3         5  
5239             # quote character class 1
5240             $charclass = q_tr($charclass);
5241 3         6  
5242             # quote character class 2
5243             $charclass2 = q_tr($charclass2);
5244 3 50       5  
5245 3 0       8 # /b /B modifier
5246 0         0 if ($modifier =~ tr/bB//d) {
5247             if ($variable eq '') {
5248             $e_tr = qq{tr$charclass$e$charclass2$modifier};
5249 0         0 }
5250             else {
5251             $e_tr = qq{$variable${bind_operator}tr$charclass$e$charclass2$modifier};
5252             }
5253 0 100       0 }
5254 3         8 else {
5255             if ($variable eq '') {
5256             $e_tr = qq{Ecyrillic::tr(\$_,' =~ ',$charclass,$e$charclass2,'$modifier')};
5257 2         7 }
5258             else {
5259             $e_tr = qq{Ecyrillic::tr($variable,'$bind_operator',$charclass,$e$charclass2,'$modifier')};
5260             }
5261             }
5262 1         4  
5263 3         4 # clear tr/// variable
5264             $tr_variable = '';
5265 3         4 $bind_operator = '';
5266              
5267             return $e_tr;
5268             }
5269              
5270             #
5271             # quote for escape transliteration (tr/// or y///)
5272 3     6 0 15 #
5273             sub q_tr {
5274             my($charclass) = @_;
5275 6 50       10  
    0          
    0          
    0          
    0          
    0          
5276 6         13 # quote character class
5277             if ($charclass !~ /'/oxms) {
5278             return e_q('', "'", "'", $charclass); # --> q' '
5279 6         8 }
5280             elsif ($charclass !~ /\//oxms) {
5281             return e_q('q', '/', '/', $charclass); # --> q/ /
5282 0         0 }
5283             elsif ($charclass !~ /\#/oxms) {
5284             return e_q('q', '#', '#', $charclass); # --> q# #
5285 0         0 }
5286             elsif ($charclass !~ /[\<\>]/oxms) {
5287             return e_q('q', '<', '>', $charclass); # --> q< >
5288 0         0 }
5289             elsif ($charclass !~ /[\(\)]/oxms) {
5290             return e_q('q', '(', ')', $charclass); # --> q( )
5291 0         0 }
5292             elsif ($charclass !~ /[\{\}]/oxms) {
5293             return e_q('q', '{', '}', $charclass); # --> q{ }
5294 0         0 }
5295 0 0       0 else {
5296 0         0 for my $char (qw( ! " $ % & * + . : = ? @ ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
5297             if ($charclass !~ /\Q$char\E/xms) {
5298             return e_q('q', $char, $char, $charclass);
5299             }
5300             }
5301 0         0 }
5302              
5303             return e_q('q', '{', '}', $charclass);
5304             }
5305              
5306             #
5307             # escape q string (q//, '')
5308 0     1264 0 0 #
5309             sub e_q {
5310 1264         3395 my($ope,$delimiter,$end_delimiter,$string) = @_;
5311              
5312 1264         2421 $slash = 'div';
5313              
5314             return join '', $ope, $delimiter, $string, $end_delimiter;
5315             }
5316              
5317             #
5318             # escape qq string (qq//, "", qx//, ``)
5319 1264     4120 0 7028 #
5320             sub e_qq {
5321 4120         9544 my($ope,$delimiter,$end_delimiter,$string) = @_;
5322              
5323 4120         7982 $slash = 'div';
5324 4120         5525  
5325             my $left_e = 0;
5326             my $right_e = 0;
5327 4120         4996  
5328             # split regexp
5329             my @char = $string =~ /\G((?>
5330             [^\\\$] |
5331             \\x\{ (?>[0-9A-Fa-f]+) \} |
5332             \\o\{ (?>[0-7]+) \} |
5333             \\N\{ (?>[^0-9\}][^\}]*) \} |
5334             \\ $q_char |
5335             \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} |
5336             \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} |
5337             \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} |
5338             \$ (?>\s* [0-9]+) |
5339             \$ (?>\s*) \{ (?>\s* [0-9]+ \s*) \} |
5340             \$ \$ (?![\w\{]) |
5341             \$ (?>\s*) \$ (?>\s*) $qq_variable |
5342             $q_char
5343 4120         173328 ))/oxmsg;
5344              
5345             for (my $i=0; $i <= $#char; $i++) {
5346 4120 50 33     13002  
    50 33        
    100          
    100          
    50          
5347 114232         389819 # "\L\u" --> "\u\L"
5348             if (($char[$i] eq '\L') and ($char[$i+1] eq '\u')) {
5349             @char[$i,$i+1] = @char[$i+1,$i];
5350             }
5351              
5352 0         0 # "\U\l" --> "\l\U"
5353             elsif (($char[$i] eq '\U') and ($char[$i+1] eq '\l')) {
5354             @char[$i,$i+1] = @char[$i+1,$i];
5355             }
5356              
5357 0         0 # octal escape sequence
5358             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
5359             $char[$i] = Ecyrillic::octchr($1);
5360             }
5361              
5362 1         5 # hexadecimal escape sequence
5363             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
5364             $char[$i] = Ecyrillic::hexchr($1);
5365             }
5366              
5367 1         4 # \N{CHARNAME} --> N{CHARNAME}
5368             elsif ($char[$i] =~ /\A \\ ( N\{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
5369             $char[$i] = $1;
5370 0 100       0 }
    50          
    50          
    50          
    50          
    100          
    50          
    100          
    50          
    50          
    100          
    50          
    50          
    100          
    50          
    50          
    50          
    50          
    100          
    100          
    100          
    50          
    50          
5371              
5372             if (0) {
5373             }
5374              
5375             # \F
5376             #
5377             # P.69 Table 2-6. Translation escapes
5378             # in Chapter 2: Bits and Pieces
5379             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
5380             # (and so on)
5381 114232         964677  
5382 0 50       0 # \u \l \U \L \F \Q \E
5383 484         17098 elsif ($char[$i] =~ /\A ([<>]) \z/oxms) {
5384             if ($right_e < $left_e) {
5385             $char[$i] = '\\' . $char[$i];
5386             }
5387             }
5388             elsif ($char[$i] eq '\u') {
5389              
5390             # "STRING @{[ LIST EXPR ]} MORE STRING"
5391              
5392             # P.257 Other Tricks You Can Do with Hard References
5393             # in Chapter 8: References
5394             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
5395              
5396             # P.353 Other Tricks You Can Do with Hard References
5397             # in Chapter 8: References
5398             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
5399              
5400 0         0 # (and so on)
5401 0         0  
5402             $char[$i] = '@{[Ecyrillic::ucfirst qq<';
5403             $left_e++;
5404 0         0 }
5405 0         0 elsif ($char[$i] eq '\l') {
5406             $char[$i] = '@{[Ecyrillic::lcfirst qq<';
5407             $left_e++;
5408 0         0 }
5409 0         0 elsif ($char[$i] eq '\U') {
5410             $char[$i] = '@{[Ecyrillic::uc qq<';
5411             $left_e++;
5412 0         0 }
5413 0         0 elsif ($char[$i] eq '\L') {
5414             $char[$i] = '@{[Ecyrillic::lc qq<';
5415             $left_e++;
5416 0         0 }
5417 24         38 elsif ($char[$i] eq '\F') {
5418             $char[$i] = '@{[Ecyrillic::fc qq<';
5419             $left_e++;
5420 24         49 }
5421 0         0 elsif ($char[$i] eq '\Q') {
5422             $char[$i] = '@{[CORE::quotemeta qq<';
5423             $left_e++;
5424 0 50       0 }
5425 24         37 elsif ($char[$i] eq '\E') {
5426 24         33 if ($right_e < $left_e) {
5427             $char[$i] = '>]}';
5428             $right_e++;
5429 24         100 }
5430             else {
5431             $char[$i] = '';
5432             }
5433 0         0 }
5434 0 0       0 elsif ($char[$i] eq '\Q') {
5435 0         0 while (1) {
5436             if (++$i > $#char) {
5437 0 0       0 last;
5438 0         0 }
5439             if ($char[$i] eq '\E') {
5440             last;
5441             }
5442             }
5443             }
5444             elsif ($char[$i] eq '\E') {
5445             }
5446              
5447             # $0 --> $0
5448             elsif ($char[$i] =~ /\A \$ 0 \z/oxms) {
5449             }
5450             elsif ($char[$i] =~ /\A \$ \{ (?>\s*) 0 (?>\s*) \} \z/oxms) {
5451             }
5452              
5453             # $$ --> $$
5454             elsif ($char[$i] =~ /\A \$\$ \z/oxms) {
5455             }
5456              
5457             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
5458 0         0 # $1, $2, $3 --> $1, $2, $3 otherwise
5459             elsif ($char[$i] =~ /\A \$ ((?>[1-9][0-9]*)) \z/oxms) {
5460             $char[$i] = e_capture($1);
5461 205         401 }
5462             elsif ($char[$i] =~ /\A \$ \{ (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} \z/oxms) {
5463             $char[$i] = e_capture($1);
5464             }
5465              
5466 0         0 # $$foo[ ... ] --> $ $foo->[ ... ]
5467             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \[ (?:$qq_bracket)*? \] ) \z/oxms) {
5468             $char[$i] = e_capture($1.'->'.$2);
5469             }
5470              
5471 0         0 # $$foo{ ... } --> $ $foo->{ ... }
5472             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \{ (?:$qq_brace)*? \} ) \z/oxms) {
5473             $char[$i] = e_capture($1.'->'.$2);
5474             }
5475              
5476 0         0 # $$foo
5477             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) \z/oxms) {
5478             $char[$i] = e_capture($1);
5479             }
5480              
5481 0         0 # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Ecyrillic::PREMATCH()
5482             elsif ($char[$i] =~ /\A ( \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} ) \z/oxmsgc) {
5483             $char[$i] = '@{[Ecyrillic::PREMATCH()]}';
5484             }
5485              
5486 44         123 # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Ecyrillic::MATCH()
5487             elsif ($char[$i] =~ /\A ( \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} ) \z/oxmsgc) {
5488             $char[$i] = '@{[Ecyrillic::MATCH()]}';
5489             }
5490              
5491 45         131 # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Ecyrillic::POSTMATCH()
5492             elsif ($char[$i] =~ /\A ( \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} ) \z/oxmsgc) {
5493             $char[$i] = '@{[Ecyrillic::POSTMATCH()]}';
5494             }
5495              
5496             # ${ foo } --> ${ foo }
5497             elsif ($char[$i] =~ /\A \$ (?>\s*) \{ (?> \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* ) \} \z/oxms) {
5498             }
5499              
5500 33         90 # ${ ... }
5501             elsif ($char[$i] =~ /\A \$ (?>\s*) \{ ( .+ ) \} \z/oxms) {
5502             $char[$i] = e_capture($1);
5503             }
5504             }
5505 0 50       0  
5506 4120         8275 # return string
5507             if ($left_e > $right_e) {
5508 0         0 return join '', $ope, $delimiter, @char, '>]}' x ($left_e - $right_e), $end_delimiter;
5509             }
5510             return join '', $ope, $delimiter, @char, $end_delimiter;
5511             }
5512              
5513             #
5514             # escape qw string (qw//)
5515 4120     16 0 37783 #
5516             sub e_qw {
5517 16         80 my($ope,$delimiter,$end_delimiter,$string) = @_;
5518              
5519             $slash = 'div';
5520 16         36  
  16         237  
5521 483 50       761 # choice again delimiter
    0          
    0          
    0          
    0          
5522 16         96 my %octet = map {$_ => 1} ($string =~ /\G ([\x00-\xFF]) /oxmsg);
5523             if (not $octet{$end_delimiter}) {
5524             return join '', $ope, $delimiter, $string, $end_delimiter;
5525 16         134 }
5526             elsif (not $octet{')'}) {
5527             return join '', $ope, '(', $string, ')';
5528 0         0 }
5529             elsif (not $octet{'}'}) {
5530             return join '', $ope, '{', $string, '}';
5531 0         0 }
5532             elsif (not $octet{']'}) {
5533             return join '', $ope, '[', $string, ']';
5534 0         0 }
5535             elsif (not $octet{'>'}) {
5536             return join '', $ope, '<', $string, '>';
5537 0         0 }
5538 0 0       0 else {
5539 0         0 for my $char (qw( ! " $ % & * + - . / : = ? @ ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
5540             if (not $octet{$char}) {
5541             return join '', $ope, $char, $string, $char;
5542             }
5543             }
5544             }
5545 0         0  
5546 0         0 # qw/AAA BBB C'CC/ --> ('AAA', 'BBB', 'C\'CC')
5547 0         0 my @string = CORE::split(/\s+/, $string);
5548 0         0 for my $string (@string) {
5549 0 0       0 my @octet = $string =~ /\G ([\x00-\xFF]) /oxmsg;
5550 0         0 for my $octet (@octet) {
5551             if ($octet =~ /\A (['\\]) \z/oxms) {
5552             $octet = '\\' . $1;
5553 0         0 }
5554             }
5555 0         0 $string = join '', @octet;
  0         0  
5556             }
5557             return join '', '(', (join ', ', map { "'$_'" } @string), ')';
5558             }
5559              
5560             #
5561             # escape here document (<<"HEREDOC", <
5562 0     93 0 0 #
5563             sub e_heredoc {
5564 93         405 my($string) = @_;
5565              
5566 93         493 $slash = 'm//';
5567              
5568 93         342 my $metachar = qr/[\@\\|]/oxms; # '|' is for <<`HEREDOC`
5569 93         161  
5570             my $left_e = 0;
5571             my $right_e = 0;
5572 93         143  
5573             # split regexp
5574             my @char = $string =~ /\G((?>
5575             [^\\\$] |
5576             \\x\{ (?>[0-9A-Fa-f]+) \} |
5577             \\o\{ (?>[0-7]+) \} |
5578             \\N\{ (?>[^0-9\}][^\}]*) \} |
5579             \\ $q_char |
5580             \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} |
5581             \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} |
5582             \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} |
5583             \$ (?>\s* [0-9]+) |
5584             \$ (?>\s*) \{ (?>\s* [0-9]+ \s*) \} |
5585             \$ \$ (?![\w\{]) |
5586             \$ (?>\s*) \$ (?>\s*) $qq_variable |
5587             $q_char
5588 93         9150 ))/oxmsg;
5589              
5590             for (my $i=0; $i <= $#char; $i++) {
5591 93 50 33     537  
    50 33        
    100          
    100          
    50          
5592 3229         10791 # "\L\u" --> "\u\L"
5593             if (($char[$i] eq '\L') and ($char[$i+1] eq '\u')) {
5594             @char[$i,$i+1] = @char[$i+1,$i];
5595             }
5596              
5597 0         0 # "\U\l" --> "\l\U"
5598             elsif (($char[$i] eq '\U') and ($char[$i+1] eq '\l')) {
5599             @char[$i,$i+1] = @char[$i+1,$i];
5600             }
5601              
5602 0         0 # octal escape sequence
5603             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
5604             $char[$i] = Ecyrillic::octchr($1);
5605             }
5606              
5607 1         4 # hexadecimal escape sequence
5608             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
5609             $char[$i] = Ecyrillic::hexchr($1);
5610             }
5611              
5612 1         4 # \N{CHARNAME} --> N{CHARNAME}
5613             elsif ($char[$i] =~ /\A \\ ( N\{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
5614             $char[$i] = $1;
5615 0 50       0 }
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    100          
    100          
    100          
    50          
    50          
5616              
5617             if (0) {
5618             }
5619 3229         28875  
5620 0 0       0 # \u \l \U \L \F \Q \E
5621 0         0 elsif ($char[$i] =~ /\A ([<>]) \z/oxms) {
5622             if ($right_e < $left_e) {
5623             $char[$i] = '\\' . $char[$i];
5624             }
5625 0         0 }
5626 0         0 elsif ($char[$i] eq '\u') {
5627             $char[$i] = '@{[Ecyrillic::ucfirst qq<';
5628             $left_e++;
5629 0         0 }
5630 0         0 elsif ($char[$i] eq '\l') {
5631             $char[$i] = '@{[Ecyrillic::lcfirst qq<';
5632             $left_e++;
5633 0         0 }
5634 0         0 elsif ($char[$i] eq '\U') {
5635             $char[$i] = '@{[Ecyrillic::uc qq<';
5636             $left_e++;
5637 0         0 }
5638 0         0 elsif ($char[$i] eq '\L') {
5639             $char[$i] = '@{[Ecyrillic::lc qq<';
5640             $left_e++;
5641 0         0 }
5642 0         0 elsif ($char[$i] eq '\F') {
5643             $char[$i] = '@{[Ecyrillic::fc qq<';
5644             $left_e++;
5645 0         0 }
5646 0         0 elsif ($char[$i] eq '\Q') {
5647             $char[$i] = '@{[CORE::quotemeta qq<';
5648             $left_e++;
5649 0 0       0 }
5650 0         0 elsif ($char[$i] eq '\E') {
5651 0         0 if ($right_e < $left_e) {
5652             $char[$i] = '>]}';
5653             $right_e++;
5654 0         0 }
5655             else {
5656             $char[$i] = '';
5657             }
5658 0         0 }
5659 0 0       0 elsif ($char[$i] eq '\Q') {
5660 0         0 while (1) {
5661             if (++$i > $#char) {
5662 0 0       0 last;
5663 0         0 }
5664             if ($char[$i] eq '\E') {
5665             last;
5666             }
5667             }
5668             }
5669             elsif ($char[$i] eq '\E') {
5670             }
5671              
5672             # $0 --> $0
5673             elsif ($char[$i] =~ /\A \$ 0 \z/oxms) {
5674             }
5675             elsif ($char[$i] =~ /\A \$ \{ (?>\s*) 0 (?>\s*) \} \z/oxms) {
5676             }
5677              
5678             # $$ --> $$
5679             elsif ($char[$i] =~ /\A \$\$ \z/oxms) {
5680             }
5681              
5682             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
5683 0         0 # $1, $2, $3 --> $1, $2, $3 otherwise
5684             elsif ($char[$i] =~ /\A \$ ((?>[1-9][0-9]*)) \z/oxms) {
5685             $char[$i] = e_capture($1);
5686 0         0 }
5687             elsif ($char[$i] =~ /\A \$ \{ (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} \z/oxms) {
5688             $char[$i] = e_capture($1);
5689             }
5690              
5691 0         0 # $$foo[ ... ] --> $ $foo->[ ... ]
5692             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \[ (?:$qq_bracket)*? \] ) \z/oxms) {
5693             $char[$i] = e_capture($1.'->'.$2);
5694             }
5695              
5696 0         0 # $$foo{ ... } --> $ $foo->{ ... }
5697             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \{ (?:$qq_brace)*? \} ) \z/oxms) {
5698             $char[$i] = e_capture($1.'->'.$2);
5699             }
5700              
5701 0         0 # $$foo
5702             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) \z/oxms) {
5703             $char[$i] = e_capture($1);
5704             }
5705              
5706 0         0 # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Ecyrillic::PREMATCH()
5707             elsif ($char[$i] =~ /\A ( \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} ) \z/oxmsgc) {
5708             $char[$i] = '@{[Ecyrillic::PREMATCH()]}';
5709             }
5710              
5711 8         45 # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Ecyrillic::MATCH()
5712             elsif ($char[$i] =~ /\A ( \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} ) \z/oxmsgc) {
5713             $char[$i] = '@{[Ecyrillic::MATCH()]}';
5714             }
5715              
5716 8         50 # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Ecyrillic::POSTMATCH()
5717             elsif ($char[$i] =~ /\A ( \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} ) \z/oxmsgc) {
5718             $char[$i] = '@{[Ecyrillic::POSTMATCH()]}';
5719             }
5720              
5721             # ${ foo } --> ${ foo }
5722             elsif ($char[$i] =~ /\A \$ (?>\s*) \{ (?> \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* ) \} \z/oxms) {
5723             }
5724              
5725 6         34 # ${ ... }
5726             elsif ($char[$i] =~ /\A \$ (?>\s*) \{ ( .+ ) \} \z/oxms) {
5727             $char[$i] = e_capture($1);
5728             }
5729             }
5730 0 50       0  
5731 93         220 # return string
5732             if ($left_e > $right_e) {
5733 0         0 return join '', @char, '>]}' x ($left_e - $right_e);
5734             }
5735             return join '', @char;
5736             }
5737              
5738             #
5739             # escape regexp (m//, qr//)
5740 93     652 0 804 #
5741 652   100     3517 sub e_qr {
5742             my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
5743 652         3088 $modifier ||= '';
5744 652 50       1272  
5745 652         2268 $modifier =~ tr/p//d;
5746 0         0 if ($modifier =~ /([adlu])/oxms) {
5747 0 0       0 my $line = 0;
5748 0         0 for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
5749 0         0 if ($filename ne __FILE__) {
5750             $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
5751             last;
5752 0         0 }
5753             }
5754             die qq{Unsupported modifier "$1" used at line $line.\n};
5755 0         0 }
5756              
5757             $slash = 'div';
5758 652 100       1169  
    100          
5759 652         2447 # literal null string pattern
5760 8         10 if ($string eq '') {
5761 8         12 $modifier =~ tr/bB//d;
5762             $modifier =~ tr/i//d;
5763             return join '', $ope, $delimiter, $end_delimiter, $modifier;
5764             }
5765              
5766             # /b /B modifier
5767             elsif ($modifier =~ tr/bB//d) {
5768 8 50       44  
5769 2         13 # choice again delimiter
5770 0         0 if ($delimiter =~ / [\@:] /oxms) {
  0         0  
5771 0 0       0 my @char = $string =~ /\G ([\x00-\xFF]) /oxmsg;
    0          
    0          
    0          
5772 0         0 my %octet = map {$_ => 1} @char;
5773 0         0 if (not $octet{')'}) {
5774             $delimiter = '(';
5775             $end_delimiter = ')';
5776 0         0 }
5777 0         0 elsif (not $octet{'}'}) {
5778             $delimiter = '{';
5779             $end_delimiter = '}';
5780 0         0 }
5781 0         0 elsif (not $octet{']'}) {
5782             $delimiter = '[';
5783             $end_delimiter = ']';
5784 0         0 }
5785 0         0 elsif (not $octet{'>'}) {
5786             $delimiter = '<';
5787             $end_delimiter = '>';
5788 0         0 }
5789 0 0       0 else {
5790 0         0 for my $char (qw( ! " $ % & * + - . / = ? ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
5791 0         0 if (not $octet{$char}) {
5792 0         0 $delimiter = $char;
5793             $end_delimiter = $char;
5794             last;
5795             }
5796             }
5797             }
5798 0 50 33     0 }
5799 2         13  
5800             if (($ope =~ /\A m? \z/oxms) and ($delimiter eq '?')) {
5801             return join '', $ope, $delimiter, $string, $matched, $end_delimiter, $modifier;
5802 0         0 }
5803             else {
5804             return join '', $ope, $delimiter, '(?:', $string, ')', $matched, $end_delimiter, $modifier;
5805             }
5806 2 100       11 }
5807 642         1573  
5808             my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
5809             my $metachar = qr/[\@\\|[\]{^]/oxms;
5810 642         2404  
5811             # split regexp
5812             my @char = $string =~ /\G((?>
5813             [^\\\$\@\[\(] |
5814             \\x (?>[0-9A-Fa-f]{1,2}) |
5815             \\ (?>[0-7]{2,3}) |
5816             \\c [\x40-\x5F] |
5817             \\x\{ (?>[0-9A-Fa-f]+) \} |
5818             \\o\{ (?>[0-7]+) \} |
5819             \\[bBNpP]\{ (?>[^0-9\}][^\}]*) \} |
5820             \\ $q_char |
5821             \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} |
5822             \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} |
5823             \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} |
5824             [\$\@] $qq_variable |
5825             \$ (?>\s* [0-9]+) |
5826             \$ (?>\s*) \{ (?>\s* [0-9]+ \s*) \} |
5827             \$ \$ (?![\w\{]) |
5828             \$ (?>\s*) \$ (?>\s*) $qq_variable |
5829             \[\^ |
5830             \[\: (?>[a-z]+) :\] |
5831             \[\:\^ (?>[a-z]+) :\] |
5832             \(\? |
5833             $q_char
5834             ))/oxmsg;
5835 642 50       94855  
5836 642         3415 # choice again delimiter
  0         0  
5837 0 0       0 if ($delimiter =~ / [\@:] /oxms) {
    0          
    0          
    0          
5838 0         0 my %octet = map {$_ => 1} @char;
5839 0         0 if (not $octet{')'}) {
5840             $delimiter = '(';
5841             $end_delimiter = ')';
5842 0         0 }
5843 0         0 elsif (not $octet{'}'}) {
5844             $delimiter = '{';
5845             $end_delimiter = '}';
5846 0         0 }
5847 0         0 elsif (not $octet{']'}) {
5848             $delimiter = '[';
5849             $end_delimiter = ']';
5850 0         0 }
5851 0         0 elsif (not $octet{'>'}) {
5852             $delimiter = '<';
5853             $end_delimiter = '>';
5854 0         0 }
5855 0 0       0 else {
5856 0         0 for my $char (qw( ! " $ % & * + - . / = ? ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
5857 0         0 if (not $octet{$char}) {
5858 0         0 $delimiter = $char;
5859             $end_delimiter = $char;
5860             last;
5861             }
5862             }
5863             }
5864 0         0 }
5865 642         1065  
5866 642         1173 my $left_e = 0;
5867             my $right_e = 0;
5868             for (my $i=0; $i <= $#char; $i++) {
5869 642 50 66     2007  
    50 66        
    100          
    100          
    100          
    100          
5870 1872         10772 # "\L\u" --> "\u\L"
5871             if (($char[$i] eq '\L') and ($char[$i+1] eq '\u')) {
5872             @char[$i,$i+1] = @char[$i+1,$i];
5873             }
5874              
5875 0         0 # "\U\l" --> "\l\U"
5876             elsif (($char[$i] eq '\U') and ($char[$i+1] eq '\l')) {
5877             @char[$i,$i+1] = @char[$i+1,$i];
5878             }
5879              
5880 0         0 # octal escape sequence
5881             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
5882             $char[$i] = Ecyrillic::octchr($1);
5883             }
5884              
5885 1         4 # hexadecimal escape sequence
5886             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
5887             $char[$i] = Ecyrillic::hexchr($1);
5888             }
5889              
5890             # \b{...} --> b\{...}
5891             # \B{...} --> B\{...}
5892             # \N{CHARNAME} --> N\{CHARNAME}
5893             # \p{PROPERTY} --> p\{PROPERTY}
5894 1         6 # \P{PROPERTY} --> P\{PROPERTY}
5895             elsif ($char[$i] =~ /\A \\ ([bBNpP]) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
5896             $char[$i] = $1 . '\\' . $2;
5897             }
5898              
5899 6         100 # \p, \P, \X --> p, P, X
5900             elsif ($char[$i] =~ /\A \\ ( [pPX] ) \z/oxms) {
5901             $char[$i] = $1;
5902 4 100 100     11 }
    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          
5903              
5904             if (0) {
5905             }
5906 1872         6643  
5907 0 50 33     0 # join separated multiple-octet
    50 33        
    50 33        
      33        
      66        
      33        
5908 6         86 elsif ($char[$i] =~ /\A (?: \\ [0-7]{2,3} | \\x [0-9A-Fa-f]{1,2}) \z/oxms) {
5909             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)) {
5910             $char[$i] .= join '', splice @char, $i+1, 3;
5911 0         0 }
5912             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)) {
5913             $char[$i] .= join '', splice @char, $i+1, 2;
5914 0         0 }
5915             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)) {
5916             $char[$i] .= join '', splice @char, $i+1, 1;
5917             }
5918             }
5919              
5920 0         0 # open character class [...]
5921             elsif ($char[$i] eq '[') {
5922             my $left = $i;
5923              
5924             # [] make die "Unmatched [] in regexp ...\n"
5925 328 100       486 # (and so on)
5926 328         930  
5927             if ($char[$i+1] eq ']') {
5928             $i++;
5929 3         6 }
5930 328 50       493  
5931 1379         2582 while (1) {
5932             if (++$i > $#char) {
5933 0 100       0 die __FILE__, ": Unmatched [] in regexp\n";
5934 1379         2381 }
5935             if ($char[$i] eq ']') {
5936             my $right = $i;
5937 328 100       453  
5938 328         1783 # [...]
  30         70  
5939             if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
5940             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);
5941 90         155 }
5942             else {
5943             splice @char, $left, $right-$left+1, Ecyrillic::charlist_qr(@char[$left+1..$right-1], $modifier);
5944 298         2691 }
5945 328         593  
5946             $i = $left;
5947             last;
5948             }
5949             }
5950             }
5951              
5952 328         888 # open character class [^...]
5953             elsif ($char[$i] eq '[^') {
5954             my $left = $i;
5955              
5956             # [^] make die "Unmatched [] in regexp ...\n"
5957 74 100       96 # (and so on)
5958 74         217  
5959             if ($char[$i+1] eq ']') {
5960             $i++;
5961 4         117 }
5962 74 50       88  
5963 272         514 while (1) {
5964             if (++$i > $#char) {
5965 0 100       0 die __FILE__, ": Unmatched [] in regexp\n";
5966 272         399 }
5967             if ($char[$i] eq ']') {
5968             my $right = $i;
5969 74 100       99  
5970 74         485 # [^...]
  30         92  
5971             if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
5972             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);
5973 90         160 }
5974             else {
5975             splice @char, $left, $right-$left+1, Ecyrillic::charlist_not_qr(@char[$left+1..$right-1], $modifier);
5976 44         398 }
5977 74         144  
5978             $i = $left;
5979             last;
5980             }
5981             }
5982             }
5983              
5984 74         199 # rewrite character class or escape character
5985             elsif (my $char = character_class($char[$i],$modifier)) {
5986             $char[$i] = $char;
5987             }
5988              
5989 139 50       346 # /i modifier
5990 20         32 elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Ecyrillic::uc($char[$i]) ne Ecyrillic::fc($char[$i]))) {
5991             if (CORE::length(Ecyrillic::fc($char[$i])) == 1) {
5992             $char[$i] = '[' . Ecyrillic::uc($char[$i]) . Ecyrillic::fc($char[$i]) . ']';
5993 20         42 }
5994             else {
5995             $char[$i] = '(?:' . Ecyrillic::uc($char[$i]) . '|' . Ecyrillic::fc($char[$i]) . ')';
5996             }
5997             }
5998              
5999 0 50       0 # \u \l \U \L \F \Q \E
6000 1         5 elsif ($char[$i] =~ /\A [<>] \z/oxms) {
6001             if ($right_e < $left_e) {
6002             $char[$i] = '\\' . $char[$i];
6003             }
6004 0         0 }
6005 0         0 elsif ($char[$i] eq '\u') {
6006             $char[$i] = '@{[Ecyrillic::ucfirst qq<';
6007             $left_e++;
6008 0         0 }
6009 0         0 elsif ($char[$i] eq '\l') {
6010             $char[$i] = '@{[Ecyrillic::lcfirst qq<';
6011             $left_e++;
6012 0         0 }
6013 1         3 elsif ($char[$i] eq '\U') {
6014             $char[$i] = '@{[Ecyrillic::uc qq<';
6015             $left_e++;
6016 1         3 }
6017 1         2 elsif ($char[$i] eq '\L') {
6018             $char[$i] = '@{[Ecyrillic::lc qq<';
6019             $left_e++;
6020 1         3 }
6021 18         34 elsif ($char[$i] eq '\F') {
6022             $char[$i] = '@{[Ecyrillic::fc qq<';
6023             $left_e++;
6024 18         39 }
6025 1         2 elsif ($char[$i] eq '\Q') {
6026             $char[$i] = '@{[CORE::quotemeta qq<';
6027             $left_e++;
6028 1 50       3 }
6029 21         44 elsif ($char[$i] eq '\E') {
6030 21         28 if ($right_e < $left_e) {
6031             $char[$i] = '>]}';
6032             $right_e++;
6033 21         46 }
6034             else {
6035             $char[$i] = '';
6036             }
6037 0         0 }
6038 0 0       0 elsif ($char[$i] eq '\Q') {
6039 0         0 while (1) {
6040             if (++$i > $#char) {
6041 0 0       0 last;
6042 0         0 }
6043             if ($char[$i] eq '\E') {
6044             last;
6045             }
6046             }
6047             }
6048             elsif ($char[$i] eq '\E') {
6049             }
6050              
6051 0 0       0 # $0 --> $0
6052 0         0 elsif ($char[$i] =~ /\A \$ 0 \z/oxms) {
6053             if ($ignorecase) {
6054             $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
6055             }
6056 0 0       0 }
6057 0         0 elsif ($char[$i] =~ /\A \$ \{ (?>\s*) 0 (?>\s*) \} \z/oxms) {
6058             if ($ignorecase) {
6059             $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
6060             }
6061             }
6062              
6063             # $$ --> $$
6064             elsif ($char[$i] =~ /\A \$\$ \z/oxms) {
6065             }
6066              
6067             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
6068 0         0 # $1, $2, $3 --> $1, $2, $3 otherwise
6069 0 0       0 elsif ($char[$i] =~ /\A \$ ((?>[1-9][0-9]*)) \z/oxms) {
6070 0         0 $char[$i] = e_capture($1);
6071             if ($ignorecase) {
6072             $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
6073             }
6074 0         0 }
6075 0 0       0 elsif ($char[$i] =~ /\A \$ \{ (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} \z/oxms) {
6076 0         0 $char[$i] = e_capture($1);
6077             if ($ignorecase) {
6078             $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
6079             }
6080             }
6081              
6082 0         0 # $$foo[ ... ] --> $ $foo->[ ... ]
6083 0 0       0 elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \[ (?:$qq_bracket)*? \] ) \z/oxms) {
6084 0         0 $char[$i] = e_capture($1.'->'.$2);
6085             if ($ignorecase) {
6086             $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
6087             }
6088             }
6089              
6090 0         0 # $$foo{ ... } --> $ $foo->{ ... }
6091 0 0       0 elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \{ (?:$qq_brace)*? \} ) \z/oxms) {
6092 0         0 $char[$i] = e_capture($1.'->'.$2);
6093             if ($ignorecase) {
6094             $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
6095             }
6096             }
6097              
6098 0         0 # $$foo
6099 0 0       0 elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) \z/oxms) {
6100 0         0 $char[$i] = e_capture($1);
6101             if ($ignorecase) {
6102             $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
6103             }
6104             }
6105              
6106 0 50       0 # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Ecyrillic::PREMATCH()
6107 8         25 elsif ($char[$i] =~ /\A ( \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} ) \z/oxmsgc) {
6108             if ($ignorecase) {
6109             $char[$i] = '@{[Ecyrillic::ignorecase(Ecyrillic::PREMATCH())]}';
6110 0         0 }
6111             else {
6112             $char[$i] = '@{[Ecyrillic::PREMATCH()]}';
6113             }
6114             }
6115              
6116 8 50       24 # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Ecyrillic::MATCH()
6117 8         23 elsif ($char[$i] =~ /\A ( \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} ) \z/oxmsgc) {
6118             if ($ignorecase) {
6119             $char[$i] = '@{[Ecyrillic::ignorecase(Ecyrillic::MATCH())]}';
6120 0         0 }
6121             else {
6122             $char[$i] = '@{[Ecyrillic::MATCH()]}';
6123             }
6124             }
6125              
6126 8 50       25 # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Ecyrillic::POSTMATCH()
6127 6         16 elsif ($char[$i] =~ /\A ( \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} ) \z/oxmsgc) {
6128             if ($ignorecase) {
6129             $char[$i] = '@{[Ecyrillic::ignorecase(Ecyrillic::POSTMATCH())]}';
6130 0         0 }
6131             else {
6132             $char[$i] = '@{[Ecyrillic::POSTMATCH()]}';
6133             }
6134             }
6135              
6136 6 0       66 # ${ foo }
6137 0         0 elsif ($char[$i] =~ /\A \$ (?>\s*) \{ ((?> \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* )) \} \z/oxms) {
6138             if ($ignorecase) {
6139             $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
6140             }
6141             }
6142              
6143 0         0 # ${ ... }
6144 0 0       0 elsif ($char[$i] =~ /\A \$ (?>\s*) \{ ( .+ ) \} \z/oxms) {
6145 0         0 $char[$i] = e_capture($1);
6146             if ($ignorecase) {
6147             $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
6148             }
6149             }
6150              
6151 0         0 # $scalar or @array
6152 21 100       52 elsif ($char[$i] =~ /\A [\$\@].+ /oxms) {
6153 21         121 $char[$i] = e_string($char[$i]);
6154             if ($ignorecase) {
6155             $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
6156             }
6157             }
6158              
6159 11 100 33     200 # quote character before ? + * {
    50          
6160             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
6161             if ($char[$i-1] =~ /\A (?:[\x00-\xFF]|\\[0-7]{2,3}|\\x[0-9-A-Fa-f]{1,2}) \z/oxms) {
6162 138         1162 }
6163 0 0       0 elsif (($ope =~ /\A m? \z/oxms) and ($delimiter eq '?')) {
6164 0         0 my $char = $char[$i-1];
6165             if ($char[$i] eq '{') {
6166             die __FILE__, qq{: "MULTIBYTE{n}" should be "(MULTIBYTE){n}" in m?? (and shift \$1,\$2,\$3,...) ($char){n}\n};
6167 0         0 }
6168             else {
6169             die __FILE__, qq{: "MULTIBYTE$char[$i]" should be "(MULTIBYTE)$char[$i]" in m?? (and shift \$1,\$2,\$3,...) ($char)$char[$i]\n};
6170             }
6171 0         0 }
6172             else {
6173             $char[$i-1] = '(?:' . $char[$i-1] . ')';
6174             }
6175             }
6176             }
6177 127         534  
6178 642 50       1391 # make regexp string
6179 642 0 0     3612 $modifier =~ tr/i//d;
6180 0         0 if ($left_e > $right_e) {
6181             if (($ope =~ /\A m? \z/oxms) and ($delimiter eq '?')) {
6182             return join '', $ope, $delimiter, $anchor, @char, '>]}' x ($left_e - $right_e), $matched, $end_delimiter, $modifier;
6183 0         0 }
6184             else {
6185             return join '', $ope, $delimiter, $anchor, '(?:', @char, '>]}' x ($left_e - $right_e), ')', $matched, $end_delimiter, $modifier;
6186 0 50 33     0 }
6187 642         4515 }
6188             if (($ope =~ /\A m? \z/oxms) and ($delimiter eq '?')) {
6189             return join '', $ope, $delimiter, $anchor, @char, $matched, $end_delimiter, $modifier;
6190 0         0 }
6191             else {
6192             return join '', $ope, $delimiter, $anchor, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
6193             }
6194             }
6195              
6196             #
6197             # double quote stuff
6198 642     180 0 6011 #
6199             sub qq_stuff {
6200             my($delimiter,$end_delimiter,$stuff) = @_;
6201 180 100       491  
6202 180         386 # scalar variable or array variable
6203             if ($stuff =~ /\A [\$\@] /oxms) {
6204             return $stuff;
6205             }
6206 100         393  
  80         192  
6207 80         351 # quote by delimiter
6208 80 50       206 my %octet = map {$_ => 1} ($stuff =~ /\G ([\x00-\xFF]) /oxmsg);
6209 80 50       153 for my $char (qw( ! " $ % & * + - . / : = ? @ ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
6210 80 50       120 next if $char eq $delimiter;
6211 80         144 next if $char eq $end_delimiter;
6212             if (not $octet{$char}) {
6213             return join '', 'qq', $char, $stuff, $char;
6214 80         401 }
6215             }
6216             return join '', 'qq', '<', $stuff, '>';
6217             }
6218              
6219             #
6220             # escape regexp (m'', qr'', and m''b, qr''b)
6221 0     10 0 0 #
6222 10   50     58 sub e_qr_q {
6223             my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6224 10         51 $modifier ||= '';
6225 10 50       17  
6226 10         24 $modifier =~ tr/p//d;
6227 0         0 if ($modifier =~ /([adlu])/oxms) {
6228 0 0       0 my $line = 0;
6229 0         0 for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
6230 0         0 if ($filename ne __FILE__) {
6231             $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
6232             last;
6233 0         0 }
6234             }
6235             die qq{Unsupported modifier "$1" used at line $line.\n};
6236 0         0 }
6237              
6238             $slash = 'div';
6239 10 100       15  
    50          
6240 10         30 # literal null string pattern
6241 8         10 if ($string eq '') {
6242 8         15 $modifier =~ tr/bB//d;
6243             $modifier =~ tr/i//d;
6244             return join '', $ope, $delimiter, $end_delimiter, $modifier;
6245             }
6246              
6247 8         149 # with /b /B modifier
6248             elsif ($modifier =~ tr/bB//d) {
6249             return e_qr_qb($ope,$delimiter,$end_delimiter,$string,$modifier);
6250             }
6251              
6252 0         0 # without /b /B modifier
6253             else {
6254             return e_qr_qt($ope,$delimiter,$end_delimiter,$string,$modifier);
6255             }
6256             }
6257              
6258             #
6259             # escape regexp (m'', qr'')
6260 2     2 0 9 #
6261             sub e_qr_qt {
6262 2 50       8 my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6263              
6264             my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
6265 2         6  
6266             # split regexp
6267             my @char = $string =~ /\G((?>
6268             [^\\\[\$\@\/] |
6269             [\x00-\xFF] |
6270             \[\^ |
6271             \[\: (?>[a-z]+) \:\] |
6272             \[\:\^ (?>[a-z]+) \:\] |
6273             [\$\@\/] |
6274             \\ (?:$q_char) |
6275             (?:$q_char)
6276             ))/oxmsg;
6277 2         70  
6278 2 50 33     12 # unescape character
    50 33        
    50 33        
    50          
    50          
    50          
6279             for (my $i=0; $i <= $#char; $i++) {
6280             if (0) {
6281             }
6282 2         35  
6283 0         0 # open character class [...]
6284 0 0       0 elsif ($char[$i] eq '[') {
6285 0         0 my $left = $i;
6286             if ($char[$i+1] eq ']') {
6287 0         0 $i++;
6288 0 0       0 }
6289 0         0 while (1) {
6290             if (++$i > $#char) {
6291 0 0       0 die __FILE__, ": Unmatched [] in regexp\n";
6292 0         0 }
6293             if ($char[$i] eq ']') {
6294             my $right = $i;
6295 0         0  
6296             # [...]
6297 0         0 splice @char, $left, $right-$left+1, Ecyrillic::charlist_qr(@char[$left+1..$right-1], $modifier);
6298 0         0  
6299             $i = $left;
6300             last;
6301             }
6302             }
6303             }
6304              
6305 0         0 # open character class [^...]
6306 0 0       0 elsif ($char[$i] eq '[^') {
6307 0         0 my $left = $i;
6308             if ($char[$i+1] eq ']') {
6309 0         0 $i++;
6310 0 0       0 }
6311 0         0 while (1) {
6312             if (++$i > $#char) {
6313 0 0       0 die __FILE__, ": Unmatched [] in regexp\n";
6314 0         0 }
6315             if ($char[$i] eq ']') {
6316             my $right = $i;
6317 0         0  
6318             # [^...]
6319 0         0 splice @char, $left, $right-$left+1, Ecyrillic::charlist_not_qr(@char[$left+1..$right-1], $modifier);
6320 0         0  
6321             $i = $left;
6322             last;
6323             }
6324             }
6325             }
6326              
6327 0         0 # escape $ @ / and \
6328             elsif ($char[$i] =~ /\A [\$\@\/\\] \z/oxms) {
6329             $char[$i] = '\\' . $char[$i];
6330             }
6331              
6332 0         0 # rewrite character class or escape character
6333             elsif (my $char = character_class($char[$i],$modifier)) {
6334             $char[$i] = $char;
6335             }
6336              
6337 0 0       0 # /i modifier
6338 0         0 elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Ecyrillic::uc($char[$i]) ne Ecyrillic::fc($char[$i]))) {
6339             if (CORE::length(Ecyrillic::fc($char[$i])) == 1) {
6340             $char[$i] = '[' . Ecyrillic::uc($char[$i]) . Ecyrillic::fc($char[$i]) . ']';
6341 0         0 }
6342             else {
6343             $char[$i] = '(?:' . Ecyrillic::uc($char[$i]) . '|' . Ecyrillic::fc($char[$i]) . ')';
6344             }
6345             }
6346              
6347 0 0       0 # quote character before ? + * {
6348             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
6349             if ($char[$i-1] =~ /\A [\x00-\xFF] \z/oxms) {
6350 0         0 }
6351             else {
6352             $char[$i-1] = '(?:' . $char[$i-1] . ')';
6353             }
6354             }
6355 0         0 }
6356 2         8  
6357             $delimiter = '/';
6358 2         3 $end_delimiter = '/';
6359 2         4  
6360             $modifier =~ tr/i//d;
6361             return join '', $ope, $delimiter, $anchor, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
6362             }
6363              
6364             #
6365             # escape regexp (m''b, qr''b)
6366 2     0 0 17 #
6367             sub e_qr_qb {
6368             my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6369 0         0  
6370             # split regexp
6371             my @char = $string =~ /\G ((?>[^\\]|\\\\)) /oxmsg;
6372 0         0  
6373 0 0       0 # unescape character
    0          
6374             for (my $i=0; $i <= $#char; $i++) {
6375             if (0) {
6376             }
6377 0         0  
6378             # remain \\
6379             elsif ($char[$i] eq '\\\\') {
6380             }
6381              
6382 0         0 # escape $ @ / and \
6383             elsif ($char[$i] =~ /\A [\$\@\/\\] \z/oxms) {
6384             $char[$i] = '\\' . $char[$i];
6385             }
6386 0         0 }
6387 0         0  
6388 0         0 $delimiter = '/';
6389             $end_delimiter = '/';
6390             return join '', $ope, $delimiter, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
6391             }
6392              
6393             #
6394             # escape regexp (s/here//)
6395 0     76 0 0 #
6396 76   100     279 sub e_s1 {
6397             my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6398 76         586 $modifier ||= '';
6399 76 50       126  
6400 76         321 $modifier =~ tr/p//d;
6401 0         0 if ($modifier =~ /([adlu])/oxms) {
6402 0 0       0 my $line = 0;
6403 0         0 for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
6404 0         0 if ($filename ne __FILE__) {
6405             $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
6406             last;
6407 0         0 }
6408             }
6409             die qq{Unsupported modifier "$1" used at line $line.\n};
6410 0         0 }
6411              
6412             $slash = 'div';
6413 76 100       152  
    50          
6414 76         266 # literal null string pattern
6415 8         11 if ($string eq '') {
6416 8         10 $modifier =~ tr/bB//d;
6417             $modifier =~ tr/i//d;
6418             return join '', $ope, $delimiter, $end_delimiter, $modifier;
6419             }
6420              
6421             # /b /B modifier
6422             elsif ($modifier =~ tr/bB//d) {
6423 8 0       107  
6424 0         0 # choice again delimiter
6425 0         0 if ($delimiter =~ / [\@:] /oxms) {
  0         0  
6426 0 0       0 my @char = $string =~ /\G ([\x00-\xFF]) /oxmsg;
    0          
    0          
    0          
6427 0         0 my %octet = map {$_ => 1} @char;
6428 0         0 if (not $octet{')'}) {
6429             $delimiter = '(';
6430             $end_delimiter = ')';
6431 0         0 }
6432 0         0 elsif (not $octet{'}'}) {
6433             $delimiter = '{';
6434             $end_delimiter = '}';
6435 0         0 }
6436 0         0 elsif (not $octet{']'}) {
6437             $delimiter = '[';
6438             $end_delimiter = ']';
6439 0         0 }
6440 0         0 elsif (not $octet{'>'}) {
6441             $delimiter = '<';
6442             $end_delimiter = '>';
6443 0         0 }
6444 0 0       0 else {
6445 0         0 for my $char (qw( ! " $ % & * + - . / = ? ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
6446 0         0 if (not $octet{$char}) {
6447 0         0 $delimiter = $char;
6448             $end_delimiter = $char;
6449             last;
6450             }
6451             }
6452             }
6453 0         0 }
6454 0         0  
6455             my $prematch = '';
6456             return join '', $ope, $delimiter, $prematch, '(?:', $string, ')', $matched, $end_delimiter, $modifier;
6457 0 100       0 }
6458 68         274  
6459             my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
6460             my $metachar = qr/[\@\\|[\]{^]/oxms;
6461 68         290  
6462             # split regexp
6463             my @char = $string =~ /\G((?>
6464             [^\\\$\@\[\(] |
6465             \\ (?>[1-9][0-9]*) |
6466             \\g (?>\s*) (?>[1-9][0-9]*) |
6467             \\g (?>\s*) \{ (?>\s*) (?>[1-9][0-9]*) (?>\s*) \} |
6468             \\g (?>\s*) \{ (?>\s*) - (?>\s*) (?>[1-9][0-9]*) (?>\s*) \} |
6469             \\x (?>[0-9A-Fa-f]{1,2}) |
6470             \\ (?>[0-7]{2,3}) |
6471             \\c [\x40-\x5F] |
6472             \\x\{ (?>[0-9A-Fa-f]+) \} |
6473             \\o\{ (?>[0-7]+) \} |
6474             \\[bBNpP]\{ (?>[^0-9\}][^\}]*) \} |
6475             \\ $q_char |
6476             \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} |
6477             \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} |
6478             \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} |
6479             [\$\@] $qq_variable |
6480             \$ (?>\s* [0-9]+) |
6481             \$ (?>\s*) \{ (?>\s* [0-9]+ \s*) \} |
6482             \$ \$ (?![\w\{]) |
6483             \$ (?>\s*) \$ (?>\s*) $qq_variable |
6484             \[\^ |
6485             \[\: (?>[a-z]+) :\] |
6486             \[\:\^ (?>[a-z]+) :\] |
6487             \(\? |
6488             $q_char
6489             ))/oxmsg;
6490 68 50       19645  
6491 68         474 # choice again delimiter
  0         0  
6492 0 0       0 if ($delimiter =~ / [\@:] /oxms) {
    0          
    0          
    0          
6493 0         0 my %octet = map {$_ => 1} @char;
6494 0         0 if (not $octet{')'}) {
6495             $delimiter = '(';
6496             $end_delimiter = ')';
6497 0         0 }
6498 0         0 elsif (not $octet{'}'}) {
6499             $delimiter = '{';
6500             $end_delimiter = '}';
6501 0         0 }
6502 0         0 elsif (not $octet{']'}) {
6503             $delimiter = '[';
6504             $end_delimiter = ']';
6505 0         0 }
6506 0         0 elsif (not $octet{'>'}) {
6507             $delimiter = '<';
6508             $end_delimiter = '>';
6509 0         0 }
6510 0 0       0 else {
6511 0         0 for my $char (qw( ! " $ % & * + - . / = ? ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
6512 0         0 if (not $octet{$char}) {
6513 0         0 $delimiter = $char;
6514             $end_delimiter = $char;
6515             last;
6516             }
6517             }
6518             }
6519             }
6520 0         0  
  68         159  
6521             # count '('
6522 253         480 my $parens = grep { $_ eq '(' } @char;
6523 68         110  
6524 68         109 my $left_e = 0;
6525             my $right_e = 0;
6526             for (my $i=0; $i <= $#char; $i++) {
6527 68 50 33     624  
    50 33        
    100          
    100          
    50          
    50          
6528 195         1149 # "\L\u" --> "\u\L"
6529             if (($char[$i] eq '\L') and ($char[$i+1] eq '\u')) {
6530             @char[$i,$i+1] = @char[$i+1,$i];
6531             }
6532              
6533 0         0 # "\U\l" --> "\l\U"
6534             elsif (($char[$i] eq '\U') and ($char[$i+1] eq '\l')) {
6535             @char[$i,$i+1] = @char[$i+1,$i];
6536             }
6537              
6538 0         0 # octal escape sequence
6539             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
6540             $char[$i] = Ecyrillic::octchr($1);
6541             }
6542              
6543 1         5 # hexadecimal escape sequence
6544             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
6545             $char[$i] = Ecyrillic::hexchr($1);
6546             }
6547              
6548             # \b{...} --> b\{...}
6549             # \B{...} --> B\{...}
6550             # \N{CHARNAME} --> N\{CHARNAME}
6551             # \p{PROPERTY} --> p\{PROPERTY}
6552 1         4 # \P{PROPERTY} --> P\{PROPERTY}
6553             elsif ($char[$i] =~ /\A \\ ([bBNpP]) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
6554             $char[$i] = $1 . '\\' . $2;
6555             }
6556              
6557 0         0 # \p, \P, \X --> p, P, X
6558             elsif ($char[$i] =~ /\A \\ ( [pPX] ) \z/oxms) {
6559             $char[$i] = $1;
6560 0 50 66     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          
6561              
6562             if (0) {
6563             }
6564 195         696  
6565 0 0 0     0 # join separated multiple-octet
    0 0        
    0 0        
      0        
      0        
      0        
6566 0         0 elsif ($char[$i] =~ /\A (?: \\ [0-7]{2,3} | \\x [0-9A-Fa-f]{1,2}) \z/oxms) {
6567             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)) {
6568             $char[$i] .= join '', splice @char, $i+1, 3;
6569 0         0 }
6570             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)) {
6571             $char[$i] .= join '', splice @char, $i+1, 2;
6572 0         0 }
6573             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)) {
6574             $char[$i] .= join '', splice @char, $i+1, 1;
6575             }
6576             }
6577              
6578 0         0 # open character class [...]
6579 13 50       20 elsif ($char[$i] eq '[') {
6580 13         48 my $left = $i;
6581             if ($char[$i+1] eq ']') {
6582 0         0 $i++;
6583 13 50       18 }
6584 58         85 while (1) {
6585             if (++$i > $#char) {
6586 0 100       0 die __FILE__, ": Unmatched [] in regexp\n";
6587 58         119 }
6588             if ($char[$i] eq ']') {
6589             my $right = $i;
6590 13 50       22  
6591 13         77 # [...]
  0         0  
6592             if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
6593             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);
6594 0         0 }
6595             else {
6596             splice @char, $left, $right-$left+1, Ecyrillic::charlist_qr(@char[$left+1..$right-1], $modifier);
6597 13         49 }
6598 13         30  
6599             $i = $left;
6600             last;
6601             }
6602             }
6603             }
6604              
6605 13         40 # open character class [^...]
6606 0 0       0 elsif ($char[$i] eq '[^') {
6607 0         0 my $left = $i;
6608             if ($char[$i+1] eq ']') {
6609 0         0 $i++;
6610 0 0       0 }
6611 0         0 while (1) {
6612             if (++$i > $#char) {
6613 0 0       0 die __FILE__, ": Unmatched [] in regexp\n";
6614 0         0 }
6615             if ($char[$i] eq ']') {
6616             my $right = $i;
6617 0 0       0  
6618 0         0 # [^...]
  0         0  
6619             if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
6620             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);
6621 0         0 }
6622             else {
6623             splice @char, $left, $right-$left+1, Ecyrillic::charlist_not_qr(@char[$left+1..$right-1], $modifier);
6624 0         0 }
6625 0         0  
6626             $i = $left;
6627             last;
6628             }
6629             }
6630             }
6631              
6632 0         0 # rewrite character class or escape character
6633             elsif (my $char = character_class($char[$i],$modifier)) {
6634             $char[$i] = $char;
6635             }
6636              
6637 7 50       17 # /i modifier
6638 3         5 elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Ecyrillic::uc($char[$i]) ne Ecyrillic::fc($char[$i]))) {
6639             if (CORE::length(Ecyrillic::fc($char[$i])) == 1) {
6640             $char[$i] = '[' . Ecyrillic::uc($char[$i]) . Ecyrillic::fc($char[$i]) . ']';
6641 3         6 }
6642             else {
6643             $char[$i] = '(?:' . Ecyrillic::uc($char[$i]) . '|' . Ecyrillic::fc($char[$i]) . ')';
6644             }
6645             }
6646              
6647 0 0       0 # \u \l \U \L \F \Q \E
6648 0         0 elsif ($char[$i] =~ /\A [<>] \z/oxms) {
6649             if ($right_e < $left_e) {
6650             $char[$i] = '\\' . $char[$i];
6651             }
6652 0         0 }
6653 0         0 elsif ($char[$i] eq '\u') {
6654             $char[$i] = '@{[Ecyrillic::ucfirst qq<';
6655             $left_e++;
6656 0         0 }
6657 0         0 elsif ($char[$i] eq '\l') {
6658             $char[$i] = '@{[Ecyrillic::lcfirst qq<';
6659             $left_e++;
6660 0         0 }
6661 0         0 elsif ($char[$i] eq '\U') {
6662             $char[$i] = '@{[Ecyrillic::uc qq<';
6663             $left_e++;
6664 0         0 }
6665 0         0 elsif ($char[$i] eq '\L') {
6666             $char[$i] = '@{[Ecyrillic::lc qq<';
6667             $left_e++;
6668 0         0 }
6669 0         0 elsif ($char[$i] eq '\F') {
6670             $char[$i] = '@{[Ecyrillic::fc qq<';
6671             $left_e++;
6672 0         0 }
6673 0         0 elsif ($char[$i] eq '\Q') {
6674             $char[$i] = '@{[CORE::quotemeta qq<';
6675             $left_e++;
6676 0 0       0 }
6677 0         0 elsif ($char[$i] eq '\E') {
6678 0         0 if ($right_e < $left_e) {
6679             $char[$i] = '>]}';
6680             $right_e++;
6681 0         0 }
6682             else {
6683             $char[$i] = '';
6684             }
6685 0         0 }
6686 0 0       0 elsif ($char[$i] eq '\Q') {
6687 0         0 while (1) {
6688             if (++$i > $#char) {
6689 0 0       0 last;
6690 0         0 }
6691             if ($char[$i] eq '\E') {
6692             last;
6693             }
6694             }
6695             }
6696             elsif ($char[$i] eq '\E') {
6697             }
6698              
6699             # \0 --> \0
6700             elsif ($char[$i] =~ /\A \\ (?>\s*) 0 \z/oxms) {
6701             }
6702              
6703             # \g{N}, \g{-N}
6704              
6705             # P.108 Using Simple Patterns
6706             # in Chapter 7: In the World of Regular Expressions
6707             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
6708              
6709             # P.221 Capturing
6710             # in Chapter 5: Pattern Matching
6711             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
6712              
6713             # \g{-1}, \g{-2}, \g{-3} --> \g{-1}, \g{-2}, \g{-3}
6714             elsif ($char[$i] =~ /\A \\g (?>\s*) \{ (?>\s*) - (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} \z/oxms) {
6715             }
6716              
6717             # \g{1}, \g{2}, \g{3} --> \g{2}, \g{3}, \g{4} (only when multibyte anchoring is enable)
6718             elsif ($char[$i] =~ /\A \\g (?>\s*) \{ (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} \z/oxms) {
6719             }
6720              
6721             # \g1, \g2, \g3 --> \g2, \g3, \g4 (only when multibyte anchoring is enable)
6722             elsif ($char[$i] =~ /\A \\g (?>\s*) ((?>[1-9][0-9]*)) \z/oxms) {
6723             }
6724              
6725             # \1, \2, \3 --> \2, \3, \4 (only when multibyte anchoring is enable)
6726             elsif ($char[$i] =~ /\A \\ (?>\s*) ((?>[1-9][0-9]*)) \z/oxms) {
6727             }
6728              
6729 0 0       0 # $0 --> $0
6730 0         0 elsif ($char[$i] =~ /\A \$ 0 \z/oxms) {
6731             if ($ignorecase) {
6732             $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
6733             }
6734 0 0       0 }
6735 0         0 elsif ($char[$i] =~ /\A \$ \{ (?>\s*) 0 (?>\s*) \} \z/oxms) {
6736             if ($ignorecase) {
6737             $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
6738             }
6739             }
6740              
6741             # $$ --> $$
6742             elsif ($char[$i] =~ /\A \$\$ \z/oxms) {
6743             }
6744              
6745             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
6746 0         0 # $1, $2, $3 --> $1, $2, $3 otherwise
6747 0 0       0 elsif ($char[$i] =~ /\A \$ ((?>[1-9][0-9]*)) \z/oxms) {
6748 0         0 $char[$i] = e_capture($1);
6749             if ($ignorecase) {
6750             $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
6751             }
6752 0         0 }
6753 0 0       0 elsif ($char[$i] =~ /\A \$ \{ (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} \z/oxms) {
6754 0         0 $char[$i] = e_capture($1);
6755             if ($ignorecase) {
6756             $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
6757             }
6758             }
6759              
6760 0         0 # $$foo[ ... ] --> $ $foo->[ ... ]
6761 0 0       0 elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \[ (?:$qq_bracket)*? \] ) \z/oxms) {
6762 0         0 $char[$i] = e_capture($1.'->'.$2);
6763             if ($ignorecase) {
6764             $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
6765             }
6766             }
6767              
6768 0         0 # $$foo{ ... } --> $ $foo->{ ... }
6769 0 0       0 elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \{ (?:$qq_brace)*? \} ) \z/oxms) {
6770 0         0 $char[$i] = e_capture($1.'->'.$2);
6771             if ($ignorecase) {
6772             $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
6773             }
6774             }
6775              
6776 0         0 # $$foo
6777 0 0       0 elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) \z/oxms) {
6778 0         0 $char[$i] = e_capture($1);
6779             if ($ignorecase) {
6780             $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
6781             }
6782             }
6783              
6784 0 50       0 # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Ecyrillic::PREMATCH()
6785 4         13 elsif ($char[$i] =~ /\A ( \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} ) \z/oxmsgc) {
6786             if ($ignorecase) {
6787             $char[$i] = '@{[Ecyrillic::ignorecase(Ecyrillic::PREMATCH())]}';
6788 0         0 }
6789             else {
6790             $char[$i] = '@{[Ecyrillic::PREMATCH()]}';
6791             }
6792             }
6793              
6794 4 50       15 # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Ecyrillic::MATCH()
6795 4         15 elsif ($char[$i] =~ /\A ( \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} ) \z/oxmsgc) {
6796             if ($ignorecase) {
6797             $char[$i] = '@{[Ecyrillic::ignorecase(Ecyrillic::MATCH())]}';
6798 0         0 }
6799             else {
6800             $char[$i] = '@{[Ecyrillic::MATCH()]}';
6801             }
6802             }
6803              
6804 4 50       15 # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Ecyrillic::POSTMATCH()
6805 3         9 elsif ($char[$i] =~ /\A ( \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} ) \z/oxmsgc) {
6806             if ($ignorecase) {
6807             $char[$i] = '@{[Ecyrillic::ignorecase(Ecyrillic::POSTMATCH())]}';
6808 0         0 }
6809             else {
6810             $char[$i] = '@{[Ecyrillic::POSTMATCH()]}';
6811             }
6812             }
6813              
6814 3 0       12 # ${ foo }
6815 0         0 elsif ($char[$i] =~ /\A \$ (?>\s*) \{ ((?> \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* )) \} \z/oxms) {
6816             if ($ignorecase) {
6817             $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
6818             }
6819             }
6820              
6821 0         0 # ${ ... }
6822 0 0       0 elsif ($char[$i] =~ /\A \$ (?>\s*) \{ ( .+ ) \} \z/oxms) {
6823 0         0 $char[$i] = e_capture($1);
6824             if ($ignorecase) {
6825             $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
6826             }
6827             }
6828              
6829 0         0 # $scalar or @array
6830 4 50       23 elsif ($char[$i] =~ /\A [\$\@].+ /oxms) {
6831 4         23 $char[$i] = e_string($char[$i]);
6832             if ($ignorecase) {
6833             $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
6834             }
6835             }
6836              
6837 0 50       0 # quote character before ? + * {
6838             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
6839             if ($char[$i-1] =~ /\A (?:[\x00-\xFF]|\\[0-7]{2,3}|\\x[0-9-A-Fa-f]{1,2}) \z/oxms) {
6840 13         70 }
6841             else {
6842             $char[$i-1] = '(?:' . $char[$i-1] . ')';
6843             }
6844             }
6845             }
6846 13         90  
6847 68         168 # make regexp string
6848 68 50       111 my $prematch = '';
6849 68         222 $modifier =~ tr/i//d;
6850             if ($left_e > $right_e) {
6851 0         0 return join '', $ope, $delimiter, $prematch, '(?:', @char, '>]}' x ($left_e - $right_e), ')', $matched, $end_delimiter, $modifier;
6852             }
6853             return join '', $ope, $delimiter, $prematch, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
6854             }
6855              
6856             #
6857             # escape regexp (s'here'' or s'here''b)
6858 68     21 0 762 #
6859 21   100     56 sub e_s1_q {
6860             my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6861 21         108 $modifier ||= '';
6862 21 50       108  
6863 21         133 $modifier =~ tr/p//d;
6864 0         0 if ($modifier =~ /([adlu])/oxms) {
6865 0 0       0 my $line = 0;
6866 0         0 for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
6867 0         0 if ($filename ne __FILE__) {
6868             $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
6869             last;
6870 0         0 }
6871             }
6872             die qq{Unsupported modifier "$1" used at line $line.\n};
6873 0         0 }
6874              
6875             $slash = 'div';
6876 21 100       46  
    50          
6877 21         59 # literal null string pattern
6878 8         13 if ($string eq '') {
6879 8         10 $modifier =~ tr/bB//d;
6880             $modifier =~ tr/i//d;
6881             return join '', $ope, $delimiter, $end_delimiter, $modifier;
6882             }
6883              
6884 8         103 # with /b /B modifier
6885             elsif ($modifier =~ tr/bB//d) {
6886             return e_s1_qb($ope,$delimiter,$end_delimiter,$string,$modifier);
6887             }
6888              
6889 0         0 # without /b /B modifier
6890             else {
6891             return e_s1_qt($ope,$delimiter,$end_delimiter,$string,$modifier);
6892             }
6893             }
6894              
6895             #
6896             # escape regexp (s'here'')
6897 13     13 0 36 #
6898             sub e_s1_qt {
6899 13 50       34 my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6900              
6901             my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
6902 13         24  
6903             # split regexp
6904             my @char = $string =~ /\G((?>
6905             [^\\\[\$\@\/] |
6906             [\x00-\xFF] |
6907             \[\^ |
6908             \[\: (?>[a-z]+) \:\] |
6909             \[\:\^ (?>[a-z]+) \:\] |
6910             [\$\@\/] |
6911             \\ (?:$q_char) |
6912             (?:$q_char)
6913             ))/oxmsg;
6914 13         235  
6915 13 50 33     43 # unescape character
    50 33        
    50 66        
    100          
    50          
    50          
6916             for (my $i=0; $i <= $#char; $i++) {
6917             if (0) {
6918             }
6919 25         111  
6920 0         0 # open character class [...]
6921 0 0       0 elsif ($char[$i] eq '[') {
6922 0         0 my $left = $i;
6923             if ($char[$i+1] eq ']') {
6924 0         0 $i++;
6925 0 0       0 }
6926 0         0 while (1) {
6927             if (++$i > $#char) {
6928 0 0       0 die __FILE__, ": Unmatched [] in regexp\n";
6929 0         0 }
6930             if ($char[$i] eq ']') {
6931             my $right = $i;
6932 0         0  
6933             # [...]
6934 0         0 splice @char, $left, $right-$left+1, Ecyrillic::charlist_qr(@char[$left+1..$right-1], $modifier);
6935 0         0  
6936             $i = $left;
6937             last;
6938             }
6939             }
6940             }
6941              
6942 0         0 # open character class [^...]
6943 0 0       0 elsif ($char[$i] eq '[^') {
6944 0         0 my $left = $i;
6945             if ($char[$i+1] eq ']') {
6946 0         0 $i++;
6947 0 0       0 }
6948 0         0 while (1) {
6949             if (++$i > $#char) {
6950 0 0       0 die __FILE__, ": Unmatched [] in regexp\n";
6951 0         0 }
6952             if ($char[$i] eq ']') {
6953             my $right = $i;
6954 0         0  
6955             # [^...]
6956 0         0 splice @char, $left, $right-$left+1, Ecyrillic::charlist_not_qr(@char[$left+1..$right-1], $modifier);
6957 0         0  
6958             $i = $left;
6959             last;
6960             }
6961             }
6962             }
6963              
6964 0         0 # escape $ @ / and \
6965             elsif ($char[$i] =~ /\A [\$\@\/\\] \z/oxms) {
6966             $char[$i] = '\\' . $char[$i];
6967             }
6968              
6969 0         0 # rewrite character class or escape character
6970             elsif (my $char = character_class($char[$i],$modifier)) {
6971             $char[$i] = $char;
6972             }
6973              
6974 6 0       12 # /i modifier
6975 0         0 elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Ecyrillic::uc($char[$i]) ne Ecyrillic::fc($char[$i]))) {
6976             if (CORE::length(Ecyrillic::fc($char[$i])) == 1) {
6977             $char[$i] = '[' . Ecyrillic::uc($char[$i]) . Ecyrillic::fc($char[$i]) . ']';
6978 0         0 }
6979             else {
6980             $char[$i] = '(?:' . Ecyrillic::uc($char[$i]) . '|' . Ecyrillic::fc($char[$i]) . ')';
6981             }
6982             }
6983              
6984 0 0       0 # quote character before ? + * {
6985             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
6986             if ($char[$i-1] =~ /\A [\x00-\xFF] \z/oxms) {
6987 0         0 }
6988             else {
6989             $char[$i-1] = '(?:' . $char[$i-1] . ')';
6990             }
6991             }
6992 0         0 }
6993 13         30  
6994 13         19 $modifier =~ tr/i//d;
6995 13         15 $delimiter = '/';
6996 13         18 $end_delimiter = '/';
6997             my $prematch = '';
6998             return join '', $ope, $delimiter, $prematch, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
6999             }
7000              
7001             #
7002             # escape regexp (s'here''b)
7003 13     0 0 99 #
7004             sub e_s1_qb {
7005             my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
7006 0         0  
7007             # split regexp
7008             my @char = $string =~ /\G (?>[^\\]|\\\\) /oxmsg;
7009 0         0  
7010 0 0       0 # unescape character
    0          
7011             for (my $i=0; $i <= $#char; $i++) {
7012             if (0) {
7013             }
7014 0         0  
7015             # remain \\
7016             elsif ($char[$i] eq '\\\\') {
7017             }
7018              
7019 0         0 # escape $ @ / and \
7020             elsif ($char[$i] =~ /\A [\$\@\/\\] \z/oxms) {
7021             $char[$i] = '\\' . $char[$i];
7022             }
7023 0         0 }
7024 0         0  
7025 0         0 $delimiter = '/';
7026 0         0 $end_delimiter = '/';
7027             my $prematch = '';
7028             return join '', $ope, $delimiter, $prematch, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
7029             }
7030              
7031             #
7032             # escape regexp (s''here')
7033 0     16 0 0 #
7034             sub e_s2_q {
7035 16         275 my($ope,$delimiter,$end_delimiter,$string) = @_;
7036              
7037 16         24 $slash = 'div';
7038 16         98  
7039 16 100       53 my @char = $string =~ / \G (?>[^\\]|\\\\|$q_char) /oxmsg;
    100          
7040             for (my $i=0; $i <= $#char; $i++) {
7041             if (0) {
7042             }
7043 9         30  
7044             # not escape \\
7045             elsif ($char[$i] =~ /\A \\\\ \z/oxms) {
7046             }
7047              
7048 0         0 # escape $ @ / and \
7049             elsif ($char[$i] =~ /\A [\$\@\/\\] \z/oxms) {
7050             $char[$i] = '\\' . $char[$i];
7051             }
7052 5         14 }
7053              
7054             return join '', $ope, $delimiter, @char, $end_delimiter;
7055             }
7056              
7057             #
7058             # escape regexp (s/here/and here/modifier)
7059 16     97 0 55 #
7060 97   100     816 sub e_sub {
7061             my($variable,$delimiter1,$pattern,$end_delimiter1,$delimiter2,$replacement,$end_delimiter2,$modifier) = @_;
7062 97         505 $modifier ||= '';
7063 97 50       189  
7064 97         274 $modifier =~ tr/p//d;
7065 0         0 if ($modifier =~ /([adlu])/oxms) {
7066 0 0       0 my $line = 0;
7067 0         0 for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
7068 0         0 if ($filename ne __FILE__) {
7069             $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
7070             last;
7071 0         0 }
7072             }
7073             die qq{Unsupported modifier "$1" used at line $line.\n};
7074 0 100       0 }
7075 97         325  
7076 36         47 if ($variable eq '') {
7077             $variable = '$_';
7078             $bind_operator = ' =~ ';
7079 36         56 }
7080              
7081             $slash = 'div';
7082              
7083             # P.128 Start of match (or end of previous match): \G
7084             # P.130 Advanced Use of \G with Perl
7085             # in Chapter 3: Overview of Regular Expression Features and Flavors
7086             # P.312 Iterative Matching: Scalar Context, with /g
7087             # in Chapter 7: Perl
7088             # of ISBN 0-596-00289-0 Mastering Regular Expressions, Second edition
7089              
7090             # P.181 Where You Left Off: The \G Assertion
7091             # in Chapter 5: Pattern Matching
7092             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
7093              
7094             # P.220 Where You Left Off: The \G Assertion
7095             # in Chapter 5: Pattern Matching
7096 97         173 # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
7097 97         270  
7098             my $e_modifier = $modifier =~ tr/e//d;
7099 97         243 my $r_modifier = $modifier =~ tr/r//d;
7100 97 50       162  
7101 97         253 my $my = '';
7102 0         0 if ($variable =~ s/\A \( (?>\s*) ( (?>(?: local \b | my \b | our \b | state \b )?) .+ ) \) \z/$1/oxms) {
7103 0         0 $my = $variable;
7104             $variable =~ s/ (?: local \b | my \b | our \b | state \b ) (?>\s*) //oxms;
7105             $variable =~ s/ = .+ \z//oxms;
7106 0         0 }
7107 97         268  
7108             (my $variable_basename = $variable) =~ s/ [\[\{].* \z//oxms;
7109             $variable_basename =~ s/ \s+ \z//oxms;
7110 97         204  
7111 97 100       155 # quote replacement string
7112 97         318 my $e_replacement = '';
7113 17         36 if ($e_modifier >= 1) {
7114             $e_replacement = e_qq('', '', '', $replacement);
7115             $e_modifier--;
7116 17 100       30 }
7117 80         210 else {
7118             if ($delimiter2 eq "'") {
7119             $e_replacement = e_s2_q('qq', '/', '/', $replacement);
7120 16         40 }
7121             else {
7122             $e_replacement = e_qq ('qq', $delimiter2, $end_delimiter2, $replacement);
7123             }
7124 64         168 }
7125              
7126             my $sub = '';
7127 97 100       182  
7128 97 100       207 # with /r
7129             if ($r_modifier) {
7130             if (0) {
7131             }
7132 8         19  
7133 0 50       0 # s///gr without multibyte anchoring
7134             elsif ($modifier =~ /g/oxms) {
7135             $sub = sprintf(
7136             # 1 2 3 4 5
7137             q,
7138              
7139             $variable, # 1
7140             ($delimiter1 eq "'") ? # 2
7141             e_s1_q('m', $delimiter1, $end_delimiter1, $pattern, $modifier) : # :
7142             e_s1 ('m', $delimiter1, $end_delimiter1, $pattern, $modifier), # :
7143             $s_matched, # 3
7144             $e_replacement, # 4
7145             '$Ecyrillic::re_r=CORE::eval $Ecyrillic::re_r; ' x $e_modifier, # 5
7146             );
7147             }
7148              
7149             # s///r
7150 4         17 else {
7151              
7152 4 50       6 my $prematch = q{$`};
7153              
7154             $sub = sprintf(
7155             # 1 2 3 4 5 6 7
7156             q<(%s =~ %s) ? CORE::eval{%s local $^W=0; local $Ecyrillic::re_r=%s; %s"%s$Ecyrillic::re_r$'" } : %s>,
7157              
7158             $variable, # 1
7159             ($delimiter1 eq "'") ? # 2
7160             e_s1_q('m', $delimiter1, $end_delimiter1, $pattern, $modifier) : # :
7161             e_s1 ('m', $delimiter1, $end_delimiter1, $pattern, $modifier), # :
7162             $s_matched, # 3
7163             $e_replacement, # 4
7164             '$Ecyrillic::re_r=CORE::eval $Ecyrillic::re_r; ' x $e_modifier, # 5
7165             $prematch, # 6
7166             $variable, # 7
7167             );
7168             }
7169 4 50       14  
7170 8         26 # $var !~ s///r doesn't make sense
7171             if ($bind_operator =~ / !~ /oxms) {
7172             $sub = q{die("$0: Using !~ with s///r doesn't make sense"), } . $sub;
7173             }
7174             }
7175              
7176 0 100       0 # without /r
7177             else {
7178             if (0) {
7179             }
7180 89         297  
7181 0 100       0 # s///g without multibyte anchoring
    100          
7182             elsif ($modifier =~ /g/oxms) {
7183             $sub = sprintf(
7184             # 1 2 3 4 5 6 7 8
7185             q,
7186              
7187             $variable, # 1
7188             ($delimiter1 eq "'") ? # 2
7189             e_s1_q('m', $delimiter1, $end_delimiter1, $pattern, $modifier) : # :
7190             e_s1 ('m', $delimiter1, $end_delimiter1, $pattern, $modifier), # :
7191             $s_matched, # 3
7192             $e_replacement, # 4
7193             '$Ecyrillic::re_r=CORE::eval $Ecyrillic::re_r; ' x $e_modifier, # 5
7194             $variable, # 6
7195             $variable, # 7
7196             ($bind_operator =~ / !~ /oxms) ? '!' : '', # 8
7197             );
7198             }
7199              
7200             # s///
7201 22         85 else {
7202              
7203 67 100       114 my $prematch = q{$`};
    100          
7204              
7205             $sub = sprintf(
7206              
7207             ($bind_operator =~ / =~ /oxms) ?
7208              
7209             # 1 2 3 4 5 6 7 8
7210             q<(%s%s%s) ? CORE::eval{%s local $^W=0; local $Ecyrillic::re_r=%s; %s%s="%s$Ecyrillic::re_r$'"; 1 } : undef> :
7211              
7212             # 1 2 3 4 5 6 7 8
7213             q<(%s%s%s) ? 1 : CORE::eval{%s local $^W=0; local $Ecyrillic::re_r=%s; %s%s="%s$Ecyrillic::re_r$'"; undef }>,
7214              
7215             $variable, # 1
7216             $bind_operator, # 2
7217             ($delimiter1 eq "'") ? # 3
7218             e_s1_q('m', $delimiter1, $end_delimiter1, $pattern, $modifier) : # :
7219             e_s1 ('m', $delimiter1, $end_delimiter1, $pattern, $modifier), # :
7220             $s_matched, # 4
7221             $e_replacement, # 5
7222             '$Ecyrillic::re_r=CORE::eval $Ecyrillic::re_r; ' x $e_modifier, # 6
7223             $variable, # 7
7224             $prematch, # 8
7225             );
7226             }
7227             }
7228 67 50       397  
7229 97         521 # (my $foo = $bar) =~ s/// --> (my $foo = $bar, CORE::eval { ... })[1]
7230             if ($my ne '') {
7231             $sub = "($my, $sub)[1]";
7232             }
7233 0         0  
7234 97         160 # clear s/// variable
7235             $sub_variable = '';
7236 97         141 $bind_operator = '';
7237              
7238             return $sub;
7239             }
7240              
7241             #
7242             # escape regexp of split qr//
7243 97     74 0 791 #
7244 74   100     418 sub e_split {
7245             my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
7246 74         367 $modifier ||= '';
7247 74 50       116  
7248 74         178 $modifier =~ tr/p//d;
7249 0         0 if ($modifier =~ /([adlu])/oxms) {
7250 0 0       0 my $line = 0;
7251 0         0 for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
7252 0         0 if ($filename ne __FILE__) {
7253             $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
7254             last;
7255 0         0 }
7256             }
7257             die qq{Unsupported modifier "$1" used at line $line.\n};
7258 0         0 }
7259              
7260             $slash = 'div';
7261 74 50       121  
7262 74         167 # /b /B modifier
7263             if ($modifier =~ tr/bB//d) {
7264             return join '', 'split', $ope, $delimiter, $string, $end_delimiter, $modifier;
7265 0 50       0 }
7266 74         190  
7267             my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
7268             my $metachar = qr/[\@\\|[\]{^]/oxms;
7269 74         266  
7270             # split regexp
7271             my @char = $string =~ /\G((?>
7272             [^\\\$\@\[\(] |
7273             \\x (?>[0-9A-Fa-f]{1,2}) |
7274             \\ (?>[0-7]{2,3}) |
7275             \\c [\x40-\x5F] |
7276             \\x\{ (?>[0-9A-Fa-f]+) \} |
7277             \\o\{ (?>[0-7]+) \} |
7278             \\[bBNpP]\{ (?>[^0-9\}][^\}]*) \} |
7279             \\ $q_char |
7280             \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} |
7281             \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} |
7282             \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} |
7283             [\$\@] $qq_variable |
7284             \$ (?>\s* [0-9]+) |
7285             \$ (?>\s*) \{ (?>\s* [0-9]+ \s*) \} |
7286             \$ \$ (?![\w\{]) |
7287             \$ (?>\s*) \$ (?>\s*) $qq_variable |
7288             \[\^ |
7289             \[\: (?>[a-z]+) :\] |
7290             \[\:\^ (?>[a-z]+) :\] |
7291             \(\? |
7292             $q_char
7293 74         9593 ))/oxmsg;
7294 74         269  
7295 74         112 my $left_e = 0;
7296             my $right_e = 0;
7297             for (my $i=0; $i <= $#char; $i++) {
7298 74 50 33     752  
    50 33        
    100          
    100          
    50          
    50          
7299 249         1261 # "\L\u" --> "\u\L"
7300             if (($char[$i] eq '\L') and ($char[$i+1] eq '\u')) {
7301             @char[$i,$i+1] = @char[$i+1,$i];
7302             }
7303              
7304 0         0 # "\U\l" --> "\l\U"
7305             elsif (($char[$i] eq '\U') and ($char[$i+1] eq '\l')) {
7306             @char[$i,$i+1] = @char[$i+1,$i];
7307             }
7308              
7309 0         0 # octal escape sequence
7310             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
7311             $char[$i] = Ecyrillic::octchr($1);
7312             }
7313              
7314 1         3 # hexadecimal escape sequence
7315             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
7316             $char[$i] = Ecyrillic::hexchr($1);
7317             }
7318              
7319             # \b{...} --> b\{...}
7320             # \B{...} --> B\{...}
7321             # \N{CHARNAME} --> N\{CHARNAME}
7322             # \p{PROPERTY} --> p\{PROPERTY}
7323 1         3 # \P{PROPERTY} --> P\{PROPERTY}
7324             elsif ($char[$i] =~ /\A \\ ([bBNpP]) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
7325             $char[$i] = $1 . '\\' . $2;
7326             }
7327              
7328 0         0 # \p, \P, \X --> p, P, X
7329             elsif ($char[$i] =~ /\A \\ ( [pPX] ) \z/oxms) {
7330             $char[$i] = $1;
7331 0 50 100     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          
7332              
7333             if (0) {
7334             }
7335 249         862  
7336 0 0 0     0 # join separated multiple-octet
    0 0        
    0 0        
      0        
      0        
      0        
7337 0         0 elsif ($char[$i] =~ /\A (?: \\ [0-7]{2,3} | \\x [0-9A-Fa-f]{1,2}) \z/oxms) {
7338             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)) {
7339             $char[$i] .= join '', splice @char, $i+1, 3;
7340 0         0 }
7341             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)) {
7342             $char[$i] .= join '', splice @char, $i+1, 2;
7343 0         0 }
7344             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)) {
7345             $char[$i] .= join '', splice @char, $i+1, 1;
7346             }
7347             }
7348              
7349 0         0 # open character class [...]
7350 3 50       5 elsif ($char[$i] eq '[') {
7351 3         9 my $left = $i;
7352             if ($char[$i+1] eq ']') {
7353 0         0 $i++;
7354 3 50       4 }
7355 7         10 while (1) {
7356             if (++$i > $#char) {
7357 0 100       0 die __FILE__, ": Unmatched [] in regexp\n";
7358 7         12 }
7359             if ($char[$i] eq ']') {
7360             my $right = $i;
7361 3 50       4  
7362 3         15 # [...]
  0         0  
7363             if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
7364             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);
7365 0         0 }
7366             else {
7367             splice @char, $left, $right-$left+1, Ecyrillic::charlist_qr(@char[$left+1..$right-1], $modifier);
7368 3         16 }
7369 3         6  
7370             $i = $left;
7371             last;
7372             }
7373             }
7374             }
7375              
7376 3         7 # open character class [^...]
7377 0 0       0 elsif ($char[$i] eq '[^') {
7378 0         0 my $left = $i;
7379             if ($char[$i+1] eq ']') {
7380 0         0 $i++;
7381 0 0       0 }
7382 0         0 while (1) {
7383             if (++$i > $#char) {
7384 0 0       0 die __FILE__, ": Unmatched [] in regexp\n";
7385 0         0 }
7386             if ($char[$i] eq ']') {
7387             my $right = $i;
7388 0 0       0  
7389 0         0 # [^...]
  0         0  
7390             if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
7391             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);
7392 0         0 }
7393             else {
7394             splice @char, $left, $right-$left+1, Ecyrillic::charlist_not_qr(@char[$left+1..$right-1], $modifier);
7395 0         0 }
7396 0         0  
7397             $i = $left;
7398             last;
7399             }
7400             }
7401             }
7402              
7403 0         0 # rewrite character class or escape character
7404             elsif (my $char = character_class($char[$i],$modifier)) {
7405             $char[$i] = $char;
7406             }
7407              
7408             # P.794 29.2.161. split
7409             # in Chapter 29: Functions
7410             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
7411              
7412             # P.951 split
7413             # in Chapter 27: Functions
7414             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
7415              
7416             # said "The //m modifier is assumed when you split on the pattern /^/",
7417             # but perl5.008 is not so. Therefore, this software adds //m.
7418             # (and so on)
7419              
7420 1         3 # split(m/^/) --> split(m/^/m)
7421             elsif (($char[$i] eq '^') and ($modifier !~ /m/oxms)) {
7422             $modifier .= 'm';
7423             }
7424              
7425 7 0       23 # /i modifier
7426 0         0 elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Ecyrillic::uc($char[$i]) ne Ecyrillic::fc($char[$i]))) {
7427             if (CORE::length(Ecyrillic::fc($char[$i])) == 1) {
7428             $char[$i] = '[' . Ecyrillic::uc($char[$i]) . Ecyrillic::fc($char[$i]) . ']';
7429 0         0 }
7430             else {
7431             $char[$i] = '(?:' . Ecyrillic::uc($char[$i]) . '|' . Ecyrillic::fc($char[$i]) . ')';
7432             }
7433             }
7434              
7435 0 0       0 # \u \l \U \L \F \Q \E
7436 0         0 elsif ($char[$i] =~ /\A ([<>]) \z/oxms) {
7437             if ($right_e < $left_e) {
7438             $char[$i] = '\\' . $char[$i];
7439             }
7440 0         0 }
7441 0         0 elsif ($char[$i] eq '\u') {
7442             $char[$i] = '@{[Ecyrillic::ucfirst qq<';
7443             $left_e++;
7444 0         0 }
7445 0         0 elsif ($char[$i] eq '\l') {
7446             $char[$i] = '@{[Ecyrillic::lcfirst qq<';
7447             $left_e++;
7448 0         0 }
7449 0         0 elsif ($char[$i] eq '\U') {
7450             $char[$i] = '@{[Ecyrillic::uc qq<';
7451             $left_e++;
7452 0         0 }
7453 0         0 elsif ($char[$i] eq '\L') {
7454             $char[$i] = '@{[Ecyrillic::lc qq<';
7455             $left_e++;
7456 0         0 }
7457 0         0 elsif ($char[$i] eq '\F') {
7458             $char[$i] = '@{[Ecyrillic::fc qq<';
7459             $left_e++;
7460 0         0 }
7461 0         0 elsif ($char[$i] eq '\Q') {
7462             $char[$i] = '@{[CORE::quotemeta qq<';
7463             $left_e++;
7464 0 0       0 }
7465 0         0 elsif ($char[$i] eq '\E') {
7466 0         0 if ($right_e < $left_e) {
7467             $char[$i] = '>]}';
7468             $right_e++;
7469 0         0 }
7470             else {
7471             $char[$i] = '';
7472             }
7473 0         0 }
7474 0 0       0 elsif ($char[$i] eq '\Q') {
7475 0         0 while (1) {
7476             if (++$i > $#char) {
7477 0 0       0 last;
7478 0         0 }
7479             if ($char[$i] eq '\E') {
7480             last;
7481             }
7482             }
7483             }
7484             elsif ($char[$i] eq '\E') {
7485             }
7486              
7487 0 0       0 # $0 --> $0
7488 0         0 elsif ($char[$i] =~ /\A \$ 0 \z/oxms) {
7489             if ($ignorecase) {
7490             $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
7491             }
7492 0 0       0 }
7493 0         0 elsif ($char[$i] =~ /\A \$ \{ (?>\s*) 0 (?>\s*) \} \z/oxms) {
7494             if ($ignorecase) {
7495             $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
7496             }
7497             }
7498              
7499             # $$ --> $$
7500             elsif ($char[$i] =~ /\A \$\$ \z/oxms) {
7501             }
7502              
7503             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
7504 0         0 # $1, $2, $3 --> $1, $2, $3 otherwise
7505 0 0       0 elsif ($char[$i] =~ /\A \$ ((?>[1-9][0-9]*)) \z/oxms) {
7506 0         0 $char[$i] = e_capture($1);
7507             if ($ignorecase) {
7508             $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
7509             }
7510 0         0 }
7511 0 0       0 elsif ($char[$i] =~ /\A \$ \{ (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} \z/oxms) {
7512 0         0 $char[$i] = e_capture($1);
7513             if ($ignorecase) {
7514             $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
7515             }
7516             }
7517              
7518 0         0 # $$foo[ ... ] --> $ $foo->[ ... ]
7519 0 0       0 elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \[ (?:$qq_bracket)*? \] ) \z/oxms) {
7520 0         0 $char[$i] = e_capture($1.'->'.$2);
7521             if ($ignorecase) {
7522             $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
7523             }
7524             }
7525              
7526 0         0 # $$foo{ ... } --> $ $foo->{ ... }
7527 0 0       0 elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \{ (?:$qq_brace)*? \} ) \z/oxms) {
7528 0         0 $char[$i] = e_capture($1.'->'.$2);
7529             if ($ignorecase) {
7530             $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
7531             }
7532             }
7533              
7534 0         0 # $$foo
7535 0 0       0 elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) \z/oxms) {
7536 0         0 $char[$i] = e_capture($1);
7537             if ($ignorecase) {
7538             $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
7539             }
7540             }
7541              
7542 0 50       0 # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Ecyrillic::PREMATCH()
7543 12         35 elsif ($char[$i] =~ /\A ( \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} ) \z/oxmsgc) {
7544             if ($ignorecase) {
7545             $char[$i] = '@{[Ecyrillic::ignorecase(Ecyrillic::PREMATCH())]}';
7546 0         0 }
7547             else {
7548             $char[$i] = '@{[Ecyrillic::PREMATCH()]}';
7549             }
7550             }
7551              
7552 12 50       54 # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Ecyrillic::MATCH()
7553 12         36 elsif ($char[$i] =~ /\A ( \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} ) \z/oxmsgc) {
7554             if ($ignorecase) {
7555             $char[$i] = '@{[Ecyrillic::ignorecase(Ecyrillic::MATCH())]}';
7556 0         0 }
7557             else {
7558             $char[$i] = '@{[Ecyrillic::MATCH()]}';
7559             }
7560             }
7561              
7562 12 50       54 # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Ecyrillic::POSTMATCH()
7563 9         25 elsif ($char[$i] =~ /\A ( \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} ) \z/oxmsgc) {
7564             if ($ignorecase) {
7565             $char[$i] = '@{[Ecyrillic::ignorecase(Ecyrillic::POSTMATCH())]}';
7566 0         0 }
7567             else {
7568             $char[$i] = '@{[Ecyrillic::POSTMATCH()]}';
7569             }
7570             }
7571              
7572 9 0       42 # ${ foo }
7573 0         0 elsif ($char[$i] =~ /\A \$ (?>\s*) \{ ((?> \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* )) \} \z/oxms) {
7574             if ($ignorecase) {
7575             $char[$i] = '@{[Ecyrillic::ignorecase(' . $1 . ')]}';
7576             }
7577             }
7578              
7579 0         0 # ${ ... }
7580 0 0       0 elsif ($char[$i] =~ /\A \$ (?>\s*) \{ ( .+ ) \} \z/oxms) {
7581 0         0 $char[$i] = e_capture($1);
7582             if ($ignorecase) {
7583             $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
7584             }
7585             }
7586              
7587 0         0 # $scalar or @array
7588 3 50       9 elsif ($char[$i] =~ /\A [\$\@].+ /oxms) {
7589 3         14 $char[$i] = e_string($char[$i]);
7590             if ($ignorecase) {
7591             $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
7592             }
7593             }
7594              
7595 0 50       0 # quote character before ? + * {
7596             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
7597             if ($char[$i-1] =~ /\A (?:[\x00-\xFF]|\\[0-7]{2,3}|\\x[0-9-A-Fa-f]{1,2}) \z/oxms) {
7598 1         7 }
7599             else {
7600             $char[$i-1] = '(?:' . $char[$i-1] . ')';
7601             }
7602             }
7603             }
7604 0         0  
7605 74 50       214 # make regexp string
7606 74         157 $modifier =~ tr/i//d;
7607             if ($left_e > $right_e) {
7608 0         0 return join '', 'Ecyrillic::split', $ope, $delimiter, @char, '>]}' x ($left_e - $right_e), $end_delimiter, $modifier;
7609             }
7610             return join '', 'Ecyrillic::split', $ope, $delimiter, @char, $end_delimiter, $modifier;
7611             }
7612              
7613             #
7614             # escape regexp of split qr''
7615 74     0 0 745 #
7616 0   0       sub e_split_q {
7617             my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
7618 0           $modifier ||= '';
7619 0 0          
7620 0           $modifier =~ tr/p//d;
7621 0           if ($modifier =~ /([adlu])/oxms) {
7622 0 0         my $line = 0;
7623 0           for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
7624 0           if ($filename ne __FILE__) {
7625             $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
7626             last;
7627 0           }
7628             }
7629             die qq{Unsupported modifier "$1" used at line $line.\n};
7630 0           }
7631              
7632             $slash = 'div';
7633 0 0          
7634 0           # /b /B modifier
7635             if ($modifier =~ tr/bB//d) {
7636             return join '', 'split', $ope, $delimiter, $string, $end_delimiter, $modifier;
7637 0 0         }
7638              
7639             my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
7640 0            
7641             # split regexp
7642             my @char = $string =~ /\G((?>
7643             [^\\\[] |
7644             [\x00-\xFF] |
7645             \[\^ |
7646             \[\: (?>[a-z]+) \:\] |
7647             \[\:\^ (?>[a-z]+) \:\] |
7648             \\ (?:$q_char) |
7649             (?:$q_char)
7650             ))/oxmsg;
7651 0            
7652 0 0 0       # unescape character
    0 0        
    0 0        
    0 0        
    0          
    0          
7653             for (my $i=0; $i <= $#char; $i++) {
7654             if (0) {
7655             }
7656 0            
7657 0           # open character class [...]
7658 0 0         elsif ($char[$i] eq '[') {
7659 0           my $left = $i;
7660             if ($char[$i+1] eq ']') {
7661 0           $i++;
7662 0 0         }
7663 0           while (1) {
7664             if (++$i > $#char) {
7665 0 0         die __FILE__, ": Unmatched [] in regexp\n";
7666 0           }
7667             if ($char[$i] eq ']') {
7668             my $right = $i;
7669 0            
7670             # [...]
7671 0           splice @char, $left, $right-$left+1, Ecyrillic::charlist_qr(@char[$left+1..$right-1], $modifier);
7672 0            
7673             $i = $left;
7674             last;
7675             }
7676             }
7677             }
7678              
7679 0           # open character class [^...]
7680 0 0         elsif ($char[$i] eq '[^') {
7681 0           my $left = $i;
7682             if ($char[$i+1] eq ']') {
7683 0           $i++;
7684 0 0         }
7685 0           while (1) {
7686             if (++$i > $#char) {
7687 0 0         die __FILE__, ": Unmatched [] in regexp\n";
7688 0           }
7689             if ($char[$i] eq ']') {
7690             my $right = $i;
7691 0            
7692             # [^...]
7693 0           splice @char, $left, $right-$left+1, Ecyrillic::charlist_not_qr(@char[$left+1..$right-1], $modifier);
7694 0            
7695             $i = $left;
7696             last;
7697             }
7698             }
7699             }
7700              
7701 0           # rewrite character class or escape character
7702             elsif (my $char = character_class($char[$i],$modifier)) {
7703             $char[$i] = $char;
7704             }
7705              
7706 0           # split(m/^/) --> split(m/^/m)
7707             elsif (($char[$i] eq '^') and ($modifier !~ /m/oxms)) {
7708             $modifier .= 'm';
7709             }
7710              
7711 0 0         # /i modifier
7712 0           elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Ecyrillic::uc($char[$i]) ne Ecyrillic::fc($char[$i]))) {
7713             if (CORE::length(Ecyrillic::fc($char[$i])) == 1) {
7714             $char[$i] = '[' . Ecyrillic::uc($char[$i]) . Ecyrillic::fc($char[$i]) . ']';
7715 0           }
7716             else {
7717             $char[$i] = '(?:' . Ecyrillic::uc($char[$i]) . '|' . Ecyrillic::fc($char[$i]) . ')';
7718             }
7719             }
7720              
7721 0 0         # quote character before ? + * {
7722             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
7723             if ($char[$i-1] =~ /\A [\x00-\xFF] \z/oxms) {
7724 0           }
7725             else {
7726             $char[$i-1] = '(?:' . $char[$i-1] . ')';
7727             }
7728             }
7729 0           }
7730 0            
7731             $modifier =~ tr/i//d;
7732             return join '', 'Ecyrillic::split', $ope, $delimiter, @char, $end_delimiter, $modifier;
7733             }
7734              
7735             #
7736             # instead of Carp::carp
7737 0     0 0   #
7738 0           sub carp {
7739             my($package,$filename,$line) = caller(1);
7740             print STDERR "@_ at $filename line $line.\n";
7741             }
7742              
7743             #
7744             # instead of Carp::croak
7745 0     0 0   #
7746 0           sub croak {
7747 0           my($package,$filename,$line) = caller(1);
7748             print STDERR "@_ at $filename line $line.\n";
7749             die "\n";
7750             }
7751              
7752             #
7753             # instead of Carp::cluck
7754 0     0 0   #
7755 0           sub cluck {
7756 0           my $i = 0;
7757 0           my @cluck = ();
7758 0           while (my($package,$filename,$line,$subroutine) = caller($i)) {
7759             push @cluck, "[$i] $filename($line) $package::$subroutine\n";
7760 0           $i++;
7761 0           }
7762 0           print STDERR CORE::reverse @cluck;
7763             print STDERR "\n";
7764             print STDERR @_;
7765             }
7766              
7767             #
7768             # instead of Carp::confess
7769 0     0 0   #
7770 0           sub confess {
7771 0           my $i = 0;
7772 0           my @confess = ();
7773 0           while (my($package,$filename,$line,$subroutine) = caller($i)) {
7774             push @confess, "[$i] $filename($line) $package::$subroutine\n";
7775 0           $i++;
7776 0           }
7777 0           print STDERR CORE::reverse @confess;
7778 0           print STDERR "\n";
7779             print STDERR @_;
7780             die "\n";
7781             }
7782              
7783             1;
7784              
7785             __END__