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   2002 use strict;
  204         526  
  204         10877  
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   2911 use 5.00503; # Galapagos Consensus 1998 for primetools
  204         569  
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   949 use vars qw($VERSION);
  204         369  
  204         33347  
28             $VERSION = '1.13';
29             $VERSION = $VERSION;
30              
31             BEGIN {
32 204 50   204   1989 if ($^X =~ / jperl /oxmsi) {
33 0         0 die __FILE__, ": needs perl(not jperl) 5.00503 or later. (\$^X==$^X)\n";
34             }
35 204         385 if (CORE::ord('A') == 193) {
36             die __FILE__, ": is not US-ASCII script (may be EBCDIC or EBCDIK script).\n";
37             }
38 204         55839 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   18489 CORE::eval q{
  204     204   1318  
  204     58   4488  
  204         24771  
  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       80506 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   1470 no strict qw(refs);
  204         418  
  204         13900  
118 0         0 return \*{ qualify $_[0], $_[1] };
  0         0  
119             }
120             else {
121 204     204   1626 no strict qw(refs);
  204     0   568  
  204         38722  
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   1368 use vars qw($qq_char); $qq_char = qr/\\c[\x40-\x5F]|\\?(?:$your_char)/oxms;
  204         404  
  204         13147  
154 204     204   1288 use vars qw($q_char); $q_char = qr/$your_char/oxms;
  204         413  
  204         470550  
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         21732 use vars qw(
445             $re_a
446             $re_t
447             $re_n
448             $re_r
449 204     204   1606 );
  204         515  
450              
451             #
452             # Character class
453             #
454 204         2360739 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   1210 );
  204         439  
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         341 my $s = shift @_;
1004 174 50 33     222 if (@_ and wantarray) {
1005 174 0       335 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         559  
1009             }
1010             }
1011             else {
1012 174         681 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         465 my $s = shift @_;
1030 197 50 33     281 if (@_ and wantarray) {
1031 197 0       356 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         575  
1035             }
1036             }
1037             else {
1038 197         1038 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     2646 }->{$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 69107 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       321 if ($length == 1) {
1537 182         371 my($a1) = unpack 'C', $_[0];
1538 182         501 my($z1) = unpack 'C', $_[1];
1539              
1540 182 50       406 if ($a1 > $z1) {
1541 182         366 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         602 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         1140 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         380 my @range_regexp = ();
1566 182 50       245 if (not exists $range_tr{$length}) {
1567 182         517 return @range_regexp;
1568             }
1569              
1570 0         0 my @ranges = @{ $range_tr{$length} };
  182         257  
1571 182         393 while (my @range = splice(@ranges,0,$length)) {
1572 182         546 my $min = '';
1573 182         277 my $max = '';
1574 182         228 for (my $i=0; $i < $length; $i++) {
1575 182         420 $min .= pack 'C', $range[$i][0];
1576 182         633 $max .= pack 'C', $range[$i][-1];
1577             }
1578              
1579             # min___max
1580             # FIRST_____________LAST
1581             # (nothing)
1582              
1583 182 50 33     475 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         1752 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         452 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   380 my $modifier = pop @_;
1652 358         622 my @char = @_;
1653              
1654 358 100       815 my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
1655              
1656             # unescape character
1657 358         810 for (my $i=0; $i <= $#char; $i++) {
1658              
1659             # escape - to ...
1660 358 100 100     1524 if ($char[$i] eq '-') {
    50          
    50          
    50          
    50          
    50          
    100          
    50          
    100          
    100          
    100          
    100          
1661 1125 100 100     8985 if ((0 < $i) and ($i < $#char)) {
1662 206         738 $char[$i] = '...';
1663             }
1664             }
1665              
1666             # octal escape sequence
1667             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
1668 182         372 $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         100 $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         487 }->{$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         71 }->{$1};
1791             }
1792             elsif ($char[$i] =~ /\A \\ ($q_char) \z/oxms) {
1793 70         1610 $char[$i] = $1;
1794             }
1795             }
1796              
1797             # open character list
1798 7         33 my @singleoctet = ();
1799 358         618 my @multipleoctet = ();
1800 358         512 for (my $i=0; $i <= $#char; ) {
1801              
1802             # escaped -
1803 358 100 100     844 if (defined($char[$i+1]) and ($char[$i+1] eq '...')) {
    100          
    100          
    50          
    50          
    100          
1804 943         4213 $i += 1;
1805 182         236 next;
1806             }
1807              
1808             # make range regexp
1809             elsif ($char[$i] eq '...') {
1810              
1811             # range error
1812 182 50       328 if (CORE::length($char[$i-1]) > CORE::length($char[$i+1])) {
    50          
1813 182         679 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         488 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         504 my @regexp = ();
1824              
1825             # is first and last
1826 182 50 33     254 if (($length == CORE::length($char[$i-1])) and ($length == CORE::length($char[$i+1]))) {
    0 0        
    0          
    0          
1827 182         741 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         508 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         337 push @singleoctet, @regexp;
1851             }
1852             else {
1853 182         452 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       416 if ($modifier =~ /i/oxms) {
1863 493         756 my $uc = Ecyrillic::uc($char[$i]);
1864 24         64 my $fc = Ecyrillic::fc($char[$i]);
1865 24 100       56 if ($uc ne $fc) {
1866 24 50       280 if (CORE::length($fc) == 1) {
1867 12         28 push @singleoctet, $uc, $fc;
1868             }
1869             else {
1870 12         29 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         26 push @singleoctet, $char[$i];
1880             }
1881 469         675 $i += 1;
1882             }
1883              
1884             # single character of single octet code
1885             elsif ($char[$i] =~ /\A (?: \\h ) \z/oxms) {
1886 493         852 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         6 $i += 1;
1896             }
1897              
1898             # single character of multiple-octet code
1899             else {
1900 2         4 push @multipleoctet, $char[$i];
1901 84         170 $i += 1;
1902             }
1903             }
1904              
1905             # quote metachar
1906 84         154 for (@singleoctet) {
1907 358 50       772 if ($_ eq '...') {
    100          
    100          
    100          
    100          
1908 689         3003 $_ = '-';
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         197 $_ = quotemeta $_;
1921             }
1922             }
1923              
1924             # return character list
1925 429         784 return \@singleoctet, \@multipleoctet;
1926             }
1927              
1928             #
1929             # Cyrillic octal escape sequence
1930             #
1931             sub octchr {
1932 358     5 0 1180 my($octdigit) = @_;
1933              
1934 5         13 my @binary = ();
1935 5         9 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         22 }->{$octal};
1946             }
1947 50         178 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         15 }->{CORE::length($binary) % 8};
1961              
1962 5         61 return $octchr;
1963             }
1964              
1965             #
1966             # Cyrillic hexadecimal escape sequence
1967             #
1968             sub hexchr {
1969 5     5 0 20 my($hexdigit) = @_;
1970              
1971             my $hexchr = {
1972             1 => pack('H*', "0$hexdigit"),
1973             0 => pack('H*', "$hexdigit"),
1974              
1975 5         14 }->{CORE::length($_[0]) % 2};
1976              
1977 5         39 return $hexchr;
1978             }
1979              
1980             #
1981             # Cyrillic open character list for qr
1982             #
1983             sub charlist_qr {
1984              
1985 5     314 0 16 my $modifier = pop @_;
1986 314         750 my @char = @_;
1987              
1988 314         758 my($singleoctet, $multipleoctet) = _charlist(@char, $modifier);
1989 314         1017 my @singleoctet = @$singleoctet;
1990 314         796 my @multipleoctet = @$multipleoctet;
1991              
1992             # return character list
1993 314 100       512 if (scalar(@singleoctet) >= 1) {
1994              
1995             # with /i modifier
1996 314 100       2012 if ($modifier =~ m/i/oxms) {
1997 236         486 my %singleoctet_ignorecase = ();
1998 22         35 for (@singleoctet) {
1999 22   100     38 while (s/ \A \\x(..) - \\x(..) //oxms or s/ \A \\x((..)) //oxms) {
2000 46         202 for my $ord (hex($1) .. hex($2)) {
2001 46         138 my $char = CORE::chr($ord);
2002 66         110 my $uc = Ecyrillic::uc($char);
2003 66         102 my $fc = Ecyrillic::fc($char);
2004 66 100       101 if ($uc eq $fc) {
2005 66         112 $singleoctet_ignorecase{unpack 'C*', $char} = 1;
2006             }
2007             else {
2008 12 50       88 if (CORE::length($fc) == 1) {
2009 54         80 $singleoctet_ignorecase{unpack 'C*', $uc} = 1;
2010 54         124 $singleoctet_ignorecase{unpack 'C*', $fc} = 1;
2011             }
2012             else {
2013 54         195 $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         94 $singleoctet_ignorecase{unpack 'C*', $_} = 1;
2021             }
2022             }
2023 0         0 my $i = 0;
2024 22         30 my @singleoctet_ignorecase = ();
2025 22         31 for my $ord (0 .. 255) {
2026 22 100       47 if (exists $singleoctet_ignorecase{$ord}) {
2027 5632         7565 push @{$singleoctet_ignorecase[$i]}, $ord;
  96         92  
2028             }
2029             else {
2030 96         233 $i++;
2031             }
2032             }
2033 5536         7528 @singleoctet = ();
2034 22         40 for my $range (@singleoctet_ignorecase) {
2035 22 100       67 if (ref $range) {
2036 3648 100       7630 if (scalar(@{$range}) == 1) {
  56 50       343  
2037 56         101 push @singleoctet, sprintf('\x%02X', @{$range}[0]);
  36         45  
2038             }
2039 36         173 elsif (scalar(@{$range}) == 2) {
2040 20         26 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         23  
  20         23  
2044             }
2045             }
2046             }
2047             }
2048              
2049 20         75 my $not_anchor = '';
2050              
2051 236         340 push @multipleoctet, join('', $not_anchor, '[', @singleoctet, ']' );
2052             }
2053 236 100       782 if (scalar(@multipleoctet) >= 2) {
2054 314         688 return '(?:' . join('|', @multipleoctet) . ')';
2055             }
2056             else {
2057 6         37 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 1337 my $modifier = pop @_;
2067 44         123 my @char = @_;
2068              
2069 44         116 my($singleoctet, $multipleoctet) = _charlist(@char, $modifier);
2070 44         134 my @singleoctet = @$singleoctet;
2071 44         95 my @multipleoctet = @$multipleoctet;
2072              
2073             # with /i modifier
2074 44 100       79 if ($modifier =~ m/i/oxms) {
2075 44         124 my %singleoctet_ignorecase = ();
2076 10         14 for (@singleoctet) {
2077 10   66     13 while (s/ \A \\x(..) - \\x(..) //oxms or s/ \A \\x((..)) //oxms) {
2078 10         47 for my $ord (hex($1) .. hex($2)) {
2079 10         28 my $char = CORE::chr($ord);
2080 30         50 my $uc = Ecyrillic::uc($char);
2081 30         45 my $fc = Ecyrillic::fc($char);
2082 30 50       44 if ($uc eq $fc) {
2083 30         49 $singleoctet_ignorecase{unpack 'C*', $char} = 1;
2084             }
2085             else {
2086 0 50       0 if (CORE::length($fc) == 1) {
2087 30         40 $singleoctet_ignorecase{unpack 'C*', $uc} = 1;
2088 30         59 $singleoctet_ignorecase{unpack 'C*', $fc} = 1;
2089             }
2090             else {
2091 30         93 $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         21 $singleoctet_ignorecase{unpack 'C*', $_} = 1;
2099             }
2100             }
2101 0         0 my $i = 0;
2102 10         11 my @singleoctet_ignorecase = ();
2103 10         11 for my $ord (0 .. 255) {
2104 10 100       18 if (exists $singleoctet_ignorecase{$ord}) {
2105 2560         3002 push @{$singleoctet_ignorecase[$i]}, $ord;
  60         57  
2106             }
2107             else {
2108 60         95 $i++;
2109             }
2110             }
2111 2500         2678 @singleoctet = ();
2112 10         15 for my $range (@singleoctet_ignorecase) {
2113 10 100       24 if (ref $range) {
2114 960 50       1453 if (scalar(@{$range}) == 1) {
  20 50       20  
2115 20         31 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         22  
  20         24  
2122             }
2123             }
2124             }
2125             }
2126              
2127             # return character list
2128 20 50       73 if (scalar(@multipleoctet) >= 1) {
2129 44 0       117 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         136 return '(?:[^' . join('', @singleoctet) . '])';
2145             }
2146             else {
2147              
2148             # any character
2149 44         261 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   2277 use Fcntl qw(O_RDONLY);
  204         1665  
  204         44250  
2160 408         1153 return CORE::sysopen($_[0], $file, &O_RDONLY);
2161             }
2162              
2163             #
2164             # open file in append mode
2165             #
2166             sub _open_a {
2167 408     204   24171 my(undef,$file) = @_;
2168 204     204   1667 use Fcntl qw(O_WRONLY O_APPEND O_CREAT);
  204         3381  
  204         734085  
2169 204         668 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   25388 $| = 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         660 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         1973 return CORE::system { $_[0] } @_; # safe even with one-argument list
  204         447  
2252             }
2253              
2254             #
2255             # Cyrillic order to character (with parameter)
2256             #
2257             sub Ecyrillic::chr(;$) {
2258              
2259 204 0   0 0 20576587 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 181100 # 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   1752 # when 'm//', '/' means regexp match 'm//' and '?' means regexp match '??'
  204         414  
  204         35329  
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   1570 my $anchor = '';
  204     0   448  
  204         10036410  
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         765 # 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         390 # of ISBN 0-596-00289-0 Mastering Regular Expressions, Second edition
3054 204         412  
3055 204         975 my $e_script = '';
3056             while (not /\G \z/oxgc) { # member
3057             $e_script .= Cyrillic::escape_token();
3058 75395         134077 }
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 2856 # \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     95111 # 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         3045484  
3089 12549 100       18515 if (/\G ( \n ) /oxgc) { # another member (and so on)
3090 12549         21840 my $heredoc = '';
3091             if (scalar(@heredoc_delimiter) >= 1) {
3092 174         312 $slash = 'm//';
3093 174         334  
3094             $heredoc = join '', @heredoc;
3095             @heredoc = ();
3096 174         292  
3097 174         330 # skip here document
3098             for my $heredoc_delimiter (@heredoc_delimiter) {
3099 174         1102 /\G .*? \n $heredoc_delimiter \n/xmsgc;
3100             }
3101 174         357 @heredoc_delimiter = ();
3102              
3103 174         225 $here_script = '';
3104             }
3105             return "\n" . $heredoc;
3106             }
3107 12549         40891  
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         57596  
3123 1401         2073 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         4505  
3143             elsif (/\G ( \( (?>\s*) (?: local \b | my \b | our \b | state \b )? (?>\s*) \$ $qq_scalar ) /oxgc) {
3144 86 50       184 my $e_string = e_string($1);
    50          
3145 86         1949  
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         144 else {
3159             $slash = 'div';
3160             return $e_string;
3161             }
3162             }
3163              
3164 86         314 # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Ecyrillic::PREMATCH()
3165 4         9 elsif (/\G ( \$` | \$\{`\} | \$ (?>\s*) PREMATCH \b | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} ) /oxmsgc) {
3166             $slash = 'div';
3167             return q{Ecyrillic::PREMATCH()};
3168             }
3169              
3170 4         11 # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Ecyrillic::MATCH()
3171 28         63 elsif (/\G ( \$& | \$\{&\} | \$ (?>\s*) MATCH \b | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} ) /oxmsgc) {
3172             $slash = 'div';
3173             return q{Ecyrillic::MATCH()};
3174             }
3175              
3176 28         85 # $', ${'} --> $', ${'}
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       3593 my $scalar = e_string($1);
    100          
3194 1671         6530  
3195 1         3 if (/\G ( (?>\s*) (?: =~ | !~ ) (?>\s*) ) (?= (?: tr | y ) \b ) /oxgc) {
3196 1         2 $tr_variable = $scalar;
3197 1         3 $bind_operator = $1;
3198             $slash = 'm//';
3199             return '';
3200 1         3 }
3201 61         123 elsif (/\G ( (?>\s*) (?: =~ | !~ ) (?>\s*) ) (?= s \b ) /oxgc) {
3202 61         114 $sub_variable = $scalar;
3203 61         91 $bind_operator = $1;
3204             $slash = 'm//';
3205             return '';
3206 61         178 }
3207 1609         2405 else {
3208             $slash = 'div';
3209             return $scalar;
3210             }
3211             }
3212              
3213 1609         4864 # end of statement
3214             elsif (/\G ( [,;] ) /oxgc) {
3215             $slash = 'm//';
3216 5025         7912  
3217             # clear tr/// variable
3218             $tr_variable = '';
3219 5025         5942  
3220             # clear s/// variable
3221 5025         6232 $sub_variable = '';
3222              
3223 5025         5717 $bind_operator = '';
3224              
3225             return $1;
3226             }
3227              
3228 5025         20102 # bareword
3229             elsif (/\G ( \{ (?>\s*) (?: tr | index | rindex | reverse ) (?>\s*) \} ) /oxmsgc) {
3230             return $1;
3231             }
3232              
3233 0         0 # $0 --> $0
3234 2         4 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         7 elsif (/\G \$ ((?>[1-9][0-9]*)) /oxmsgc) {
3252             $slash = 'div';
3253             return e_capture($1);
3254 4         7 }
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         77 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         134 # $ @ # \ ' " / ? ( ) [ ] < >
3298 62         206 elsif (/\G ( \$[\$\@\#\\\'\"\/\?\(\)\[\]\<\>] ) /oxmsgc) {
3299             $slash = 'div';
3300             return $1;
3301             }
3302              
3303 62         214 # 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         549  
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         922  
  19         33  
3329 19         62 # 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         20  
3331 13         34 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         180  
3333 114         335 elsif (/\G \b Char::eval \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'eval Char::escape'; }
  2         7  
3334 2         10 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         4  
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         7 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         3  
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         2  
3346 1         3 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         11  
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         18  
  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         9  
3373 2         8  
  2         5  
3374 2         7 elsif (/\G \b bytes::length (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'length'; }
  36         63  
3375 36         129 elsif (/\G \b bytes::chr (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'chr'; }
  2         6  
3376 2         8 elsif (/\G \b chr (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Ecyrillic::chr'; }
  8         14  
3377 8         24 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         31 # split
3396             elsif (/\G \b (split) \b (?! (?>\s*) => ) /oxgc) {
3397 87         173 $slash = 'm//';
3398 87         142  
3399 87         311 my $e = '';
3400             while (/\G ( (?>\s+) | \( | \#.* ) /oxgc) {
3401             $e .= $1;
3402             }
3403 85 100       323  
  87 100       5949  
    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         5  
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         43 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         482  
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       68 else {
  12 50       3987  
    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         88 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         462  
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       79 else {
  18 50       4613  
    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         143 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         120 elsif (/\G (\/) /oxgc) {
3522 44 50       178 my $regexp = '';
  381 50       2202  
    100          
    50          
3523 0         0 while (not /\G \z/oxgc) {
3524 0         0 if (/\G (\\\\) /oxgc) { $regexp .= $1; }
3525 44         308 elsif (/\G (\\\/) /oxgc) { $regexp .= $1; } # splitqr// --> split qr//
3526             elsif (/\G \/ ([cgimosxpadlunbB]*) /oxgc) { return e_split($e.q{ qr}, '/','/',$regexp,$1); } # / / --> qr / /
3527 337         801 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         40 # $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         6 else {
3550 3 50       7 my $e = '';
  3 50       217  
    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         12 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         13 }
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       5169  
3615 2180         4743 # 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         8972 else {
3628 2180 50       5590 my $e = '';
  2180 50       8317  
    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         3089 elsif (/\G (\{) /oxgc) { # qq { }
3651 2150         3125 my $qq_string = '';
3652 2150 100       5667 local $nest = 1;
  84032 50       304183  
    100          
    100          
    50          
3653 722         1541 while (not /\G \z/oxgc) {
3654 0         0 if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  1153         1814  
3655             elsif (/\G (\\\}) /oxgc) { $qq_string .= $1; }
3656 1153 100       3149 elsif (/\G (\{) /oxgc) { $qq_string .= $1; $nest++; }
  3303         5058  
3657 2150         4617 elsif (/\G (\}) /oxgc) {
3658             if (--$nest == 0) { return $e . e_qq($ope,'{','}',$qq_string); }
3659 1153         2327 else { $qq_string .= $1; }
3660             }
3661 78854         173223 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         52 elsif (/\G (\<) /oxgc) { # qq < >
3685 30         72 my $qq_string = '';
3686 30 100       103 local $nest = 1;
  1166 50       3950  
    50          
    100          
    50          
3687 22         53 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         66  
3691 30         71 elsif (/\G (\>) /oxgc) {
3692             if (--$nest == 0) { return $e . e_qq($ope,'<','>',$qq_string); }
3693 0         0 else { $qq_string .= $1; }
3694             }
3695 1114         2327 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       71 elsif (/\G \b (qw) \b /oxgc) {
3741 16         92 my $ope = $1;
3742             if (/\G (\#) (.*?) (\#) /oxmsgc) { # qw# #
3743             return e_qw($ope,$1,$3,$2);
3744 0         0 }
3745 16         32 else {
3746 16 50       69 my $e = '';
  16 50       144  
    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         59  
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       1131 # (and so on)
3798 410         983  
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         691 else {
3811 410 50       1189 my $e = '';
  410 50       3261  
    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         672 elsif (/\G (\{) /oxgc) { # q { }
3835 404         660 my $q_string = '';
3836 404 50       1099 local $nest = 1;
  6796 50       25167  
    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         204  
3840             elsif (/\G (\\\{) /oxgc) { $q_string .= $1; }
3841 107 100       230 elsif (/\G (\{) /oxgc) { $q_string .= $1; $nest++; }
  511         1157  
3842 404         1097 elsif (/\G (\}) /oxgc) {
3843             if (--$nest == 0) { return $e . e_q($ope,'{','}',$q_string); }
3844 107         215 else { $q_string .= $1; }
3845             }
3846 6178         14568 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         10 elsif (/\G (\<) /oxgc) { # q < >
3871 5         11 my $q_string = '';
3872 5 50       17 local $nest = 1;
  88 50       369  
    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         19  
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         164 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         3 elsif (/\G (\S) /oxgc) { # q * *
3889 1         2 my $delimiter = $1;
3890 1 50       4 my $q_string = '';
  14 50       67  
    100          
    50          
3891 0         0 while (not /\G \z/oxgc) {
3892 0         0 if (/\G (\\\\) /oxgc) { $q_string .= $1; }
3893 1         2 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         26 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       664 elsif (/\G \b (m) \b /oxgc) {
3906 209         1312 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         302 else {
3911 209 50       517 my $e = '';
  209 50       9971  
    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         29 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         616 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       454  
3937 97         2004 # $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         5 }
3941 96         179 else {
3942 96 50       280 my $e = '';
  96 50       12738  
    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         66 # $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         333 }
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         298 # 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         13 # 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         2172 elsif (/\G (?
4078 848 100       2185 my $q_string = '';
  8280 100       26100  
    100          
    50          
4079 4         11 while (not /\G \z/oxgc) {
4080 48         92 if (/\G (\\\\) /oxgc) { $q_string .= $1; }
4081 848         1935 elsif (/\G (\\\') /oxgc) { $q_string .= $1; }
4082             elsif (/\G \' /oxgc) { return e_q('', "'","'",$q_string); }
4083 7380         20281 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         4065 elsif (/\G (\") /oxgc) {
4090 1858 100       5081 my $qq_string = '';
  35661 100       104504  
    100          
    50          
4091 67         156 while (not /\G \z/oxgc) {
4092 12         25 if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
4093 1858         4246 elsif (/\G (\\\") /oxgc) { $qq_string .= $1; }
4094             elsif (/\G \" /oxgc) { return e_qq('', '"','"',$qq_string); }
4095 33724         69591 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         12 elsif (/\G (\`) /oxgc) {
4102 1 50       5 my $qx_string = '';
  19 50       99  
    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         38 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         1445 elsif (($slash eq 'm//') and /\G (\/) /oxgc) {
4114 453 50       1264 my $regexp = '';
  4496 50       16618  
    100          
    50          
4115 0         0 while (not /\G \z/oxgc) {
4116 0         0 if (/\G (\\\\) /oxgc) { $regexp .= $1; }
4117 453         1646 elsif (/\G (\\\/) /oxgc) { $regexp .= $1; }
4118             elsif (/\G \/ ([cgimosxpadlunbB]*) /oxgc) { return e_qr('', '/','/',$regexp,$1); }
4119 4043         9279 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         15 elsif (/\G ( <<~ [\t ]* '([a-zA-Z_0-9]*)' ) /oxgc) {
4144 6         10 $slash = 'm//';
4145             my $here_quote = $1;
4146             my $delimiter = $2;
4147 6 50       10  
4148 6         12 # get here document
4149 6         34 if ($here_script eq '') {
4150             $here_script = CORE::substr $_, pos $_;
4151 6 50       30 $here_script =~ s/.*?\n//oxm;
4152 6         53 }
4153 6         13 if ($here_script =~ s/\A (.*?) \n ([\t ]*) $delimiter \n //xms) {
4154 6         7 my $heredoc = $1;
4155 6         42 my $indent = $2;
4156 6         17 $heredoc =~ s{^$indent}{}msg; # no /ox
4157             push @heredoc, $heredoc . qq{\n$delimiter\n};
4158             push @heredoc_delimiter, qq{\\s*$delimiter};
4159 6         12 }
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         20  
4176 3         7 elsif (/\G ( <<~ \\([a-zA-Z_0-9]+) ) /oxgc) {
4177 3         7 $slash = 'm//';
4178             my $here_quote = $1;
4179             my $delimiter = $2;
4180 3 50       5  
4181 3         5 # get here document
4182 3         11 if ($here_script eq '') {
4183             $here_script = CORE::substr $_, pos $_;
4184 3 50       22 $here_script =~ s/.*?\n//oxm;
4185 3         37 }
4186 3         7 if ($here_script =~ s/\A (.*?) \n ([\t ]*) $delimiter \n //xms) {
4187 3         5 my $heredoc = $1;
4188 3         32 my $indent = $2;
4189 3         17 $heredoc =~ s{^$indent}{}msg; # no /ox
4190             push @heredoc, $heredoc . qq{\n$delimiter\n};
4191             push @heredoc_delimiter, qq{\\s*$delimiter};
4192 3         7 }
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         11 elsif (/\G ( <<~ [\t ]* "([a-zA-Z_0-9]*)" ) /oxgc) {
4201 6         11 $slash = 'm//';
4202             my $here_quote = $1;
4203             my $delimiter = $2;
4204 6 50       11  
4205 6         11 # get here document
4206 6         28 if ($here_script eq '') {
4207             $here_script = CORE::substr $_, pos $_;
4208 6 50       28 $here_script =~ s/.*?\n//oxm;
4209 6         54 }
4210 6         12 if ($here_script =~ s/\A (.*?) \n ([\t ]*) $delimiter \n //xms) {
4211 6         8 my $heredoc = $1;
4212 6         44 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         16 }
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         21 # <<~HEREDOC
4224 3         5 elsif (/\G ( <<~ ([a-zA-Z_0-9]+) ) /oxgc) {
4225 3         7 $slash = 'm//';
4226             my $here_quote = $1;
4227             my $delimiter = $2;
4228 3 50       6  
4229 3         7 # get here document
4230 3         18 if ($here_script eq '') {
4231             $here_script = CORE::substr $_, pos $_;
4232 3 50       16 $here_script =~ s/.*?\n//oxm;
4233 3         42 }
4234 3         7 if ($here_script =~ s/\A (.*?) \n ([\t ]*) $delimiter \n //xms) {
4235 3         5 my $heredoc = $1;
4236 3         35 my $indent = $2;
4237 3         9 $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         7 }
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         14 # <<~`HEREDOC`
4248 6         13 elsif (/\G ( <<~ [\t ]* `([a-zA-Z_0-9]*)` ) /oxgc) {
4249 6         12 $slash = 'm//';
4250             my $here_quote = $1;
4251             my $delimiter = $2;
4252 6 50       11  
4253 6         15 # get here document
4254 6         31 if ($here_script eq '') {
4255             $here_script = CORE::substr $_, pos $_;
4256 6 50       31 $here_script =~ s/.*?\n//oxm;
4257 6         71 }
4258 6         16 if ($here_script =~ s/\A (.*?) \n ([\t ]*) $delimiter \n //xms) {
4259 6         10 my $heredoc = $1;
4260 6         52 my $indent = $2;
4261 6         31 $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         17 }
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         21 # <<'HEREDOC'
4272 72         153 elsif (/\G ( << '([a-zA-Z_0-9]*)' ) /oxgc) {
4273 72         149 $slash = 'm//';
4274             my $here_quote = $1;
4275             my $delimiter = $2;
4276 72 50       113  
4277 72         144 # get here document
4278 72         343 if ($here_script eq '') {
4279             $here_script = CORE::substr $_, pos $_;
4280 72 50       477 $here_script =~ s/.*?\n//oxm;
4281 72         541 }
4282 72         243 if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4283             push @heredoc, $1 . qq{\n$delimiter\n};
4284             push @heredoc_delimiter, $delimiter;
4285 72         121 }
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         268  
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         81 elsif (/\G ( << "([a-zA-Z_0-9]*)" ) /oxgc) {
4324 36         77 $slash = 'm//';
4325             my $here_quote = $1;
4326             my $delimiter = $2;
4327 36 50       66  
4328 36         370 # get here document
4329 36         291 if ($here_script eq '') {
4330             $here_script = CORE::substr $_, pos $_;
4331 36 50       206 $here_script =~ s/.*?\n//oxm;
4332 36         462 }
4333 36         127 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         84 }
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         195 # <
4344 42         97 elsif (/\G ( << ([a-zA-Z_0-9]+) ) /oxgc) {
4345 42         122 $slash = 'm//';
4346             my $here_quote = $1;
4347             my $delimiter = $2;
4348 42 50       71  
4349 42         123 # get here document
4350 42         290 if ($here_script eq '') {
4351             $here_script = CORE::substr $_, pos $_;
4352 42 50       296 $here_script =~ s/.*?\n//oxm;
4353 42         624 }
4354 42         142 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         101 }
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         227 # <<`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         66 #
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         1641 # 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         11401  
4428              
4429             ) /oxgc) { $slash = 'div'; return $1; }
4430              
4431             # yada-yada or triple-dot operator
4432             elsif (/\G (
4433 5081         25973 \.\.\.
  7         19  
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         195 [,;\(\{\[]
  8873         18667  
4490              
4491             )) /oxgc) { $slash = 'm//'; return $1; }
4492 8873         43078  
  15385         31912  
4493             # other any character
4494             elsif (/\G ($q_char) /oxgc) { $slash = 'div'; return $1; }
4495              
4496 15385         73672 # 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         4267 sub e_string {
4504             my($string) = @_;
4505 1786         2529 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         2550 # (and so on)
4512              
4513             my @char = $string =~ / \G (?>[^\\]|\\$q_char|$q_char) /oxmsg;
4514 1786 100 66     16221  
4515 1786 50       7496 # without { ... }
4516 1769         4392 if (not (grep(/\A \{ \z/xms, @char) and grep(/\A \} \z/xms, @char))) {
4517             if ($string !~ /<
4518             return $string;
4519             }
4520             }
4521 1769         4822  
4522 17 50       53 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         12446  
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         11 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         14 # $ @ % & * $ #
4616 7         22 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         22 # $ @ # \ ' " / ? ( ) [ ] < >
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         60 \.\.\.
  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         65  
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         359 # 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 79 #
5205             sub character_class {
5206 1919 100       4319 my($char,$modifier) = @_;
5207 1919 100       4311  
5208 52         103 if ($char eq '.') {
5209             if ($modifier =~ /s/) {
5210             return '${Ecyrillic::dot_s}';
5211 17         40 }
5212             else {
5213             return '${Ecyrillic::dot}';
5214             }
5215 35         83 }
5216             else {
5217             return Ecyrillic::classic_character_class($char);
5218             }
5219             }
5220              
5221             #
5222             # escape capture ($1, $2, $3, ...)
5223             #
5224 1867     212 0 3147 sub e_capture {
5225              
5226             return join '', '${', $_[0], '}';
5227             }
5228              
5229             #
5230             # escape transliteration (tr/// or y///)
5231 212     3 0 809 #
5232 3         16 sub e_tr {
5233 3   50     6 my($variable,$charclass,$e,$charclass2,$modifier) = @_;
5234             my $e_tr = '';
5235 3         7 $modifier ||= '';
5236              
5237             $slash = 'div';
5238 3         4  
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         7 else {
5255             if ($variable eq '') {
5256             $e_tr = qq{Ecyrillic::tr(\$_,' =~ ',$charclass,$e$charclass2,'$modifier')};
5257 2         8 }
5258             else {
5259             $e_tr = qq{Ecyrillic::tr($variable,'$bind_operator',$charclass,$e$charclass2,'$modifier')};
5260             }
5261             }
5262 1         4  
5263 3         6 # 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 14 #
5273             sub q_tr {
5274             my($charclass) = @_;
5275 6 50       9  
    0          
    0          
    0          
    0          
    0          
5276 6         11 # quote character class
5277             if ($charclass !~ /'/oxms) {
5278             return e_q('', "'", "'", $charclass); # --> q' '
5279 6         11 }
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         3120 my($ope,$delimiter,$end_delimiter,$string) = @_;
5311              
5312 1264         1763 $slash = 'div';
5313              
5314             return join '', $ope, $delimiter, $string, $end_delimiter;
5315             }
5316              
5317             #
5318             # escape qq string (qq//, "", qx//, ``)
5319 1264     4120 0 6215 #
5320             sub e_qq {
5321 4120         14426 my($ope,$delimiter,$end_delimiter,$string) = @_;
5322              
5323 4120         5817 $slash = 'div';
5324 4120         4936  
5325             my $left_e = 0;
5326             my $right_e = 0;
5327 4120         4453  
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         153980 ))/oxmsg;
5344              
5345             for (my $i=0; $i <= $#char; $i++) {
5346 4120 50 33     15322  
    50 33        
    100          
    100          
    50          
5347 114232         401820 # "\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         3 # 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         1021034  
5382 0 50       0 # \u \l \U \L \F \Q \E
5383 484         1081 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         39 elsif ($char[$i] eq '\F') {
5418             $char[$i] = '@{[Ecyrillic::fc qq<';
5419             $left_e++;
5420 24         44 }
5421 0         0 elsif ($char[$i] eq '\Q') {
5422             $char[$i] = '@{[CORE::quotemeta qq<';
5423             $left_e++;
5424 0 50       0 }
5425 24         42 elsif ($char[$i] eq '\E') {
5426 24         30 if ($right_e < $left_e) {
5427             $char[$i] = '>]}';
5428             $right_e++;
5429 24         44 }
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         388 }
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         115 # $&, ${&}, $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         125 # $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         87 # ${ ... }
5501             elsif ($char[$i] =~ /\A \$ (?>\s*) \{ ( .+ ) \} \z/oxms) {
5502             $char[$i] = e_capture($1);
5503             }
5504             }
5505 0 50       0  
5506 4120         9775 # 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 34506 #
5516             sub e_qw {
5517 16         78 my($ope,$delimiter,$end_delimiter,$string) = @_;
5518              
5519             $slash = 'div';
5520 16         35  
  16         251  
5521 483 50       16870 # choice again delimiter
    0          
    0          
    0          
    0          
5522 16         111 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         154 }
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         249 my($string) = @_;
5565              
5566 93         169 $slash = 'm//';
5567              
5568 93         302 my $metachar = qr/[\@\\|]/oxms; # '|' is for <<`HEREDOC`
5569 93         152  
5570             my $left_e = 0;
5571             my $right_e = 0;
5572 93         135  
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         8370 ))/oxmsg;
5589              
5590             for (my $i=0; $i <= $#char; $i++) {
5591 93 50 33     429  
    50 33        
    100          
    100          
    50          
5592 3229         9226 # "\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         5 # \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         25411  
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         44 # $&, ${&}, $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         53 # $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         32 # ${ ... }
5726             elsif ($char[$i] =~ /\A \$ (?>\s*) \{ ( .+ ) \} \z/oxms) {
5727             $char[$i] = e_capture($1);
5728             }
5729             }
5730 0 50       0  
5731 93         196 # 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 705 #
5741 652   100     2820 sub e_qr {
5742             my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
5743 652         2790 $modifier ||= '';
5744 652 50       1149  
5745 652         2749 $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       1128  
    100          
5759 652         2268 # literal null string pattern
5760 8         13 if ($string eq '') {
5761 8         8 $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       38  
5769 2         10 # 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         12  
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       12 }
5807 642         1446  
5808             my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
5809             my $metachar = qr/[\@\\|[\]{^]/oxms;
5810 642         2685  
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       63726  
5836 642         3005 # 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         1060  
5866 642         999 my $left_e = 0;
5867             my $right_e = 0;
5868             for (my $i=0; $i <= $#char; $i++) {
5869 642 50 66     1770  
    50 66        
    100          
    100          
    100          
    100          
5870 1872         10474 # "\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         5 # 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         4 # \P{PROPERTY} --> P\{PROPERTY}
5895             elsif ($char[$i] =~ /\A \\ ([bBNpP]) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
5896             $char[$i] = $1 . '\\' . $2;
5897             }
5898              
5899 6         19 # \p, \P, \X --> p, P, X
5900             elsif ($char[$i] =~ /\A \\ ( [pPX] ) \z/oxms) {
5901             $char[$i] = $1;
5902 4 100 100     13 }
    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         8612  
5907 0 50 33     0 # join separated multiple-octet
    50 33        
    50 33        
      33        
      66        
      33        
5908 6         112 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       448 # (and so on)
5926 328         726  
5927             if ($char[$i+1] eq ']') {
5928             $i++;
5929 3         6 }
5930 328 50       404  
5931 1379         2015 while (1) {
5932             if (++$i > $#char) {
5933 0 100       0 die __FILE__, ": Unmatched [] in regexp\n";
5934 1379         2120 }
5935             if ($char[$i] eq ']') {
5936             my $right = $i;
5937 328 100       550  
5938 328         1626 # [...]
  30         62  
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         135 }
5942             else {
5943             splice @char, $left, $right-$left+1, Ecyrillic::charlist_qr(@char[$left+1..$right-1], $modifier);
5944 298         1114 }
5945 328         811  
5946             $i = $left;
5947             last;
5948             }
5949             }
5950             }
5951              
5952 328         834 # open character class [^...]
5953             elsif ($char[$i] eq '[^') {
5954             my $left = $i;
5955              
5956             # [^] make die "Unmatched [] in regexp ...\n"
5957 74 100       112 # (and so on)
5958 74         157  
5959             if ($char[$i+1] eq ']') {
5960             $i++;
5961 4         7 }
5962 74 50       91  
5963 272         446 while (1) {
5964             if (++$i > $#char) {
5965 0 100       0 die __FILE__, ": Unmatched [] in regexp\n";
5966 272         398 }
5967             if ($char[$i] eq ']') {
5968             my $right = $i;
5969 74 100       87  
5970 74         363 # [^...]
  30         125  
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         150 }
5974             else {
5975             splice @char, $left, $right-$left+1, Ecyrillic::charlist_not_qr(@char[$left+1..$right-1], $modifier);
5976 44         229 }
5977 74         188  
5978             $i = $left;
5979             last;
5980             }
5981             }
5982             }
5983              
5984 74         192 # rewrite character class or escape character
5985             elsif (my $char = character_class($char[$i],$modifier)) {
5986             $char[$i] = $char;
5987             }
5988              
5989 139 50       391 # /i modifier
5990 20         34 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         54 }
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         7 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         2 elsif ($char[$i] eq '\U') {
6014             $char[$i] = '@{[Ecyrillic::uc qq<';
6015             $left_e++;
6016 1         3 }
6017 1         3 elsif ($char[$i] eq '\L') {
6018             $char[$i] = '@{[Ecyrillic::lc qq<';
6019             $left_e++;
6020 1         3 }
6021 18         35 elsif ($char[$i] eq '\F') {
6022             $char[$i] = '@{[Ecyrillic::fc qq<';
6023             $left_e++;
6024 18         41 }
6025 1         2 elsif ($char[$i] eq '\Q') {
6026             $char[$i] = '@{[CORE::quotemeta qq<';
6027             $left_e++;
6028 1 50       3 }
6029 21         45 elsif ($char[$i] eq '\E') {
6030 21         29 if ($right_e < $left_e) {
6031             $char[$i] = '>]}';
6032             $right_e++;
6033 21         44 }
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         24 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       25 # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Ecyrillic::MATCH()
6117 8         21 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       23 # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Ecyrillic::POSTMATCH()
6127 6         18 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       19 # ${ 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       56 elsif ($char[$i] =~ /\A [\$\@].+ /oxms) {
6153 21         118 $char[$i] = e_string($char[$i]);
6154             if ($ignorecase) {
6155             $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
6156             }
6157             }
6158              
6159 11 100 33     36 # 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         1007 }
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         474  
6178 642 50       1245 # make regexp string
6179 642 0 0     1590 $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         3453 }
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 5181 #
6199             sub qq_stuff {
6200             my($delimiter,$end_delimiter,$stuff) = @_;
6201 180 100       250  
6202 180         368 # scalar variable or array variable
6203             if ($stuff =~ /\A [\$\@] /oxms) {
6204             return $stuff;
6205             }
6206 100         369  
  80         168  
6207 80         214 # quote by delimiter
6208 80 50       182 my %octet = map {$_ => 1} ($stuff =~ /\G ([\x00-\xFF]) /oxmsg);
6209 80 50       131 for my $char (qw( ! " $ % & * + - . / : = ? @ ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
6210 80 50       118 next if $char eq $delimiter;
6211 80         128 next if $char eq $end_delimiter;
6212             if (not $octet{$char}) {
6213             return join '', 'qq', $char, $stuff, $char;
6214 80         304 }
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     68 sub e_qr_q {
6223             my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6224 10         44 $modifier ||= '';
6225 10 50       17  
6226 10         21 $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       32  
    50          
6240 10         23 # literal null string pattern
6241 8         10 if ($string eq '') {
6242 8         85 $modifier =~ tr/bB//d;
6243             $modifier =~ tr/i//d;
6244             return join '', $ope, $delimiter, $end_delimiter, $modifier;
6245             }
6246              
6247 8         42 # 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       7 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         61  
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         31  
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         4  
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 15 #
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     224 sub e_s1 {
6397             my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6398 76         298 $modifier ||= '';
6399 76 50       115  
6400 76         197 $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       151  
    50          
6414 76         248 # literal null string pattern
6415 8         10 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       45  
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         176  
6459             my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
6460             my $metachar = qr/[\@\\|[\]{^]/oxms;
6461 68         256  
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       16937  
6491 68         460 # 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         167  
6521             # count '('
6522 253         434 my $parens = grep { $_ eq '(' } @char;
6523 68         106  
6524 68         109 my $left_e = 0;
6525             my $right_e = 0;
6526             for (my $i=0; $i <= $#char; $i++) {
6527 68 50 33     214  
    50 33        
    100          
    100          
    50          
    50          
6528 195         1100 # "\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         3 # 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         3 # \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         680  
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         49 my $left = $i;
6581             if ($char[$i+1] eq ']') {
6582 0         0 $i++;
6583 13 50       18 }
6584 58         83 while (1) {
6585             if (++$i > $#char) {
6586 0 100       0 die __FILE__, ": Unmatched [] in regexp\n";
6587 58         129 }
6588             if ($char[$i] eq ']') {
6589             my $right = $i;
6590 13 50       24  
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         55 }
6598 13         25  
6599             $i = $left;
6600             last;
6601             }
6602             }
6603             }
6604              
6605 13         46 # 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       99 # /i modifier
6638 3         6 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         16 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       14 # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Ecyrillic::MATCH()
6795 4         14 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         12 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         22 $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         68 }
6841             else {
6842             $char[$i-1] = '(?:' . $char[$i-1] . ')';
6843             }
6844             }
6845             }
6846 13         63  
6847 68         163 # make regexp string
6848 68 50       162 my $prematch = '';
6849 68         193 $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 786 #
6859 21   100     55 sub e_s1_q {
6860             my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6861 21         74 $modifier ||= '';
6862 21 50       31  
6863 21         61 $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       38  
    50          
6877 21         62 # literal null string pattern
6878 8         10 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         50 # 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 34 #
6898             sub e_s1_qt {
6899 13 50       30 my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6900              
6901             my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
6902 13         29  
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         249  
6915 13 50 33     346 # unescape character
    50 33        
    50 66        
    100          
    50          
    50          
6916             for (my $i=0; $i <= $#char; $i++) {
6917             if (0) {
6918             }
6919 25         116  
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       13 # /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         26  
6994 13         26 $modifier =~ tr/i//d;
6995 13         21 $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 102 #
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         36 my($ope,$delimiter,$end_delimiter,$string) = @_;
7036              
7037 16         24 $slash = 'div';
7038 16         90  
7039 16 100       48 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         15 }
7053              
7054             return join '', $ope, $delimiter, @char, $end_delimiter;
7055             }
7056              
7057             #
7058             # escape regexp (s/here/and here/modifier)
7059 16     97 0 48 #
7060 97   100     804 sub e_sub {
7061             my($variable,$delimiter1,$pattern,$end_delimiter1,$delimiter2,$replacement,$end_delimiter2,$modifier) = @_;
7062 97         414 $modifier ||= '';
7063 97 50       179  
7064 97         272 $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         275  
7076 36         48 if ($variable eq '') {
7077             $variable = '$_';
7078             $bind_operator = ' =~ ';
7079 36         49 }
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         154 # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
7097 97         153  
7098             my $e_modifier = $modifier =~ tr/e//d;
7099 97         136 my $r_modifier = $modifier =~ tr/r//d;
7100 97 50       147  
7101 97         239 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         901  
7108             (my $variable_basename = $variable) =~ s/ [\[\{].* \z//oxms;
7109             $variable_basename =~ s/ \s+ \z//oxms;
7110 97         207  
7111 97 100       154 # quote replacement string
7112 97         240 my $e_replacement = '';
7113 17         40 if ($e_modifier >= 1) {
7114             $e_replacement = e_qq('', '', '', $replacement);
7115             $e_modifier--;
7116 17 100       30 }
7117 80         197 else {
7118             if ($delimiter2 eq "'") {
7119             $e_replacement = e_s2_q('qq', '/', '/', $replacement);
7120 16         37 }
7121             else {
7122             $e_replacement = e_qq ('qq', $delimiter2, $end_delimiter2, $replacement);
7123             }
7124 64         216 }
7125              
7126             my $sub = '';
7127 97 100       181  
7128 97 100       210 # 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         14 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       13  
7170 8         23 # $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         219  
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         268 else {
7202              
7203 67 100       99 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       348  
7229 97         266 # (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         152 # clear s/// variable
7235             $sub_variable = '';
7236 97         134 $bind_operator = '';
7237              
7238             return $sub;
7239             }
7240              
7241             #
7242             # escape regexp of split qr//
7243 97     74 0 752 #
7244 74   100     354 sub e_split {
7245             my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
7246 74         352 $modifier ||= '';
7247 74 50       119  
7248 74         239 $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       133  
7262 74         164 # /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         179  
7267             my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
7268             my $metachar = qr/[\@\\|[\]{^]/oxms;
7269 74         252  
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         8926 ))/oxmsg;
7294 74         247  
7295 74         120 my $left_e = 0;
7296             my $right_e = 0;
7297             for (my $i=0; $i <= $#char; $i++) {
7298 74 50 33     512  
    50 33        
    100          
    100          
    50          
    50          
7299 249         1284 # "\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         811  
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         10 my $left = $i;
7352             if ($char[$i+1] eq ']') {
7353 0         0 $i++;
7354 3 50       4 }
7355 7         12 while (1) {
7356             if (++$i > $#char) {
7357 0 100       0 die __FILE__, ": Unmatched [] in regexp\n";
7358 7         13 }
7359             if ($char[$i] eq ']') {
7360             my $right = $i;
7361 3 50       4  
7362 3         19 # [...]
  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         15 }
7369 3         4  
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         2 # 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         31 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       53 # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Ecyrillic::MATCH()
7553 12         46 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       142 # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Ecyrillic::POSTMATCH()
7563 9         24 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       38 # ${ 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       12 elsif ($char[$i] =~ /\A [\$\@].+ /oxms) {
7589 3         107 $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       210 # make regexp string
7606 74         160 $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 782 #
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__