File Coverage

blib/lib/Ecyrillic.pm
Criterion Covered Total %
statement 905 2814 32.1
branch 890 2412 36.9
condition 98 355 27.6
subroutine 54 113 47.7
pod 7 74 9.4
total 1954 5768 33.8


line stmt bran cond sub pod time code
1             package Ecyrillic;
2 206     206   1342 use strict;
  206         327  
  206         8378  
3 206 50   206   3601 BEGIN { $INC{'warnings.pm'} = '' if $] < 5.006 } use warnings;
  206     206   842  
  206         331  
  206         6595  
4             ######################################################################
5             #
6             # Ecyrillic - Run-time routines for Cyrillic.pm
7             #
8             # http://search.cpan.org/dist/Char-Cyrillic/
9             #
10             # Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2018, 2019 INABA Hitoshi
11             ######################################################################
12              
13 206     206   3167 use 5.00503; # Galapagos Consensus 1998 for primetools
  206         822  
14             # use 5.008001; # Lancaster Consensus 2013 for toolchains
15              
16             # 12.3. Delaying use Until Runtime
17             # in Chapter 12. Packages, Libraries, and Modules
18             # of ISBN 0-596-00313-7 Perl Cookbook, 2nd Edition.
19             # (and so on)
20              
21             # Version numbers should be boring
22             # http://www.dagolden.com/index.php/369/version-numbers-should-be-boring/
23             # For the impatient, the disinterested or those who just want to follow
24             # a recipe, my advice for all modules is this:
25             # our $VERSION = "0.001"; # or "0.001_001" for a dev release
26             # $VERSION = eval $VERSION; # No!! because '1.10' makes '1.1'
27              
28 206     206   1066 use vars qw($VERSION);
  206         392  
  206         26909  
29             $VERSION = '1.22';
30             $VERSION = $VERSION;
31              
32             BEGIN {
33 206 50   206   1347 if ($^X =~ / jperl /oxmsi) {
34 0         0 die __FILE__, ": needs perl(not jperl) 5.00503 or later. (\$^X==$^X)\n";
35             }
36 206         345 if (CORE::ord('A') == 193) {
37             die __FILE__, ": is not US-ASCII script (may be EBCDIC or EBCDIK script).\n";
38             }
39 206         25411 if (CORE::ord('A') != 0x41) {
40             die __FILE__, ": is not US-ASCII script (must be US-ASCII script).\n";
41             }
42             }
43              
44             BEGIN {
45              
46             # instead of utf8.pm
47 206     206   14324 CORE::eval q{
  206     206   1198  
  206     80   460  
  206         23068  
  0         0  
  0         0  
  0         0  
  0         0  
48             no warnings qw(redefine);
49             *utf8::upgrade = sub { CORE::length $_[0] };
50             *utf8::downgrade = sub { 1 };
51             *utf8::encode = sub { };
52             *utf8::decode = sub { 1 };
53             *utf8::is_utf8 = sub { };
54             *utf8::valid = sub { 1 };
55             };
56 206 50       93069 if ($@) {
57 0         0 *utf8::upgrade = sub { CORE::length $_[0] };
  0         0  
58 0         0 *utf8::downgrade = sub { 1 };
  0         0  
59 0         0 *utf8::encode = sub { };
60 0         0 *utf8::decode = sub { 1 };
  0         0  
61 0         0 *utf8::is_utf8 = sub { };
62 0         0 *utf8::valid = sub { 1 };
  0         0  
63             }
64             }
65              
66             # instead of Symbol.pm
67 0         0 BEGIN {
68             sub gensym () {
69 0 0   0 0 0 if ($] < 5.006) {
70 0         0 return \do { local *_ };
  0         0  
71             }
72             else {
73 0         0 return undef;
74             }
75             }
76              
77             sub qualify ($$) {
78 0     0 0 0 my($name) = @_;
79              
80 0 0       0 if (ref $name) {
    0          
    0          
    0          
    0          
    0          
    0          
81 0         0 return $name;
82             }
83             elsif (Ecyrillic::index($name,'::') >= 0) {
84 0         0 return $name;
85             }
86             elsif (Ecyrillic::index($name,"'") >= 0) {
87 0         0 return $name;
88             }
89              
90             # special character, "^xyz"
91             elsif ($name =~ /\A \^ [ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_]+ \z/x) {
92              
93             # RGS 2001-11-05 : translate leading ^X to control-char
94 0         0 $name =~ s{\A \^ ([ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_]) }{'qq(\c'.$1.')'}xee;
  0         0  
95 0         0 return 'main::' . $name;
96             }
97              
98             # Global names
99             elsif ($name =~ /\A (?: ARGV | ARGVOUT | ENV | INC | SIG | STDERR | STDIN | STDOUT ) \z/x) {
100 0         0 return 'main::' . $name;
101             }
102              
103             # or other
104             elsif ($name =~ /\A [^ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz] \z/x) {
105 0         0 return 'main::' . $name;
106             }
107              
108             elsif (defined $_[1]) {
109 0         0 return $_[1] . '::' . $name;
110             }
111             else {
112 0         0 return (caller)[0] . '::' . $name;
113             }
114             }
115              
116             sub qualify_to_ref ($;$) {
117 0 0   0 0 0 if (defined $_[1]) {
118 206     206   1412 no strict qw(refs);
  206         403  
  206         13763  
119 0         0 return \*{ qualify $_[0], $_[1] };
  0         0  
120             }
121             else {
122 206     206   1157 no strict qw(refs);
  206     0   400  
  206         35388  
123 0         0 return \*{ qualify $_[0], (caller)[0] };
  0         0  
124             }
125             }
126             }
127              
128             # P.714 29.2.39. flock
129             # in Chapter 29: Functions
130             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
131              
132             # P.863 flock
133             # in Chapter 27: Functions
134             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
135              
136             sub LOCK_SH() {1}
137             sub LOCK_EX() {2}
138             sub LOCK_UN() {8}
139             sub LOCK_NB() {4}
140              
141             # instead of Carp.pm
142             sub carp;
143             sub croak;
144             sub cluck;
145             sub confess;
146              
147             # 6.18. Matching Multiple-Byte Characters
148             # in Chapter 6. Pattern Matching
149             # of ISBN 978-1-56592-243-3 Perl Perl Cookbook.
150             # (and so on)
151              
152             # regexp of character
153             my $your_char = q{[\x00-\xFF]};
154 206     206   1515 use vars qw($qq_char); $qq_char = qr/\\c[\x40-\x5F]|\\?(?:$your_char)/oxms;
  206         368  
  206         11693  
155 206     206   1161 use vars qw($q_char); $q_char = qr/$your_char/oxms;
  206         448  
  206         399483  
156              
157             #
158             # Cyrillic character range per length
159             #
160             my %range_tr = ();
161              
162             #
163             # Cyrillic case conversion
164             #
165             my %lc = ();
166             @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)} =
167             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);
168             my %uc = ();
169             @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)} =
170             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);
171             my %fc = ();
172             @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)} =
173             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);
174              
175             if (0) {
176             }
177              
178             elsif (__PACKAGE__ =~ / \b Ecyrillic \z/oxms) {
179             %range_tr = (
180             1 => [ [0x00..0xFF],
181             ],
182             );
183              
184             %lc = (%lc,
185             "\xA1" => "\xF1", # CYRILLIC LETTER IO
186             "\xA2" => "\xF2", # CYRILLIC LETTER DJE
187             "\xA3" => "\xF3", # CYRILLIC LETTER GJE
188             "\xA4" => "\xF4", # CYRILLIC LETTER UKRAINIAN IE
189             "\xA5" => "\xF5", # CYRILLIC LETTER DZE
190             "\xA6" => "\xF6", # CYRILLIC LETTER BYELORUSSIAN-UKRAINIAN I
191             "\xA7" => "\xF7", # CYRILLIC LETTER YI
192             "\xA8" => "\xF8", # CYRILLIC LETTER JE
193             "\xA9" => "\xF9", # CYRILLIC LETTER LJE
194             "\xAA" => "\xFA", # CYRILLIC LETTER NJE
195             "\xAB" => "\xFB", # CYRILLIC LETTER TSHE
196             "\xAC" => "\xFC", # CYRILLIC LETTER KJE
197             "\xAE" => "\xFE", # CYRILLIC LETTER SHORT U
198             "\xAF" => "\xFF", # CYRILLIC LETTER DZHE
199             "\xB0" => "\xD0", # CYRILLIC LETTER A
200             "\xB1" => "\xD1", # CYRILLIC LETTER BE
201             "\xB2" => "\xD2", # CYRILLIC LETTER VE
202             "\xB3" => "\xD3", # CYRILLIC LETTER GHE
203             "\xB4" => "\xD4", # CYRILLIC LETTER DE
204             "\xB5" => "\xD5", # CYRILLIC LETTER IE
205             "\xB6" => "\xD6", # CYRILLIC LETTER ZHE
206             "\xB7" => "\xD7", # CYRILLIC LETTER ZE
207             "\xB8" => "\xD8", # CYRILLIC LETTER I
208             "\xB9" => "\xD9", # CYRILLIC LETTER SHORT I
209             "\xBA" => "\xDA", # CYRILLIC LETTER KA
210             "\xBB" => "\xDB", # CYRILLIC LETTER EL
211             "\xBC" => "\xDC", # CYRILLIC LETTER EM
212             "\xBD" => "\xDD", # CYRILLIC LETTER EN
213             "\xBE" => "\xDE", # CYRILLIC LETTER O
214             "\xBF" => "\xDF", # CYRILLIC LETTER PE
215             "\xC0" => "\xE0", # CYRILLIC LETTER ER
216             "\xC1" => "\xE1", # CYRILLIC LETTER ES
217             "\xC2" => "\xE2", # CYRILLIC LETTER TE
218             "\xC3" => "\xE3", # CYRILLIC LETTER U
219             "\xC4" => "\xE4", # CYRILLIC LETTER EF
220             "\xC5" => "\xE5", # CYRILLIC LETTER HA
221             "\xC6" => "\xE6", # CYRILLIC LETTER TSE
222             "\xC7" => "\xE7", # CYRILLIC LETTER CHE
223             "\xC8" => "\xE8", # CYRILLIC LETTER SHA
224             "\xC9" => "\xE9", # CYRILLIC LETTER SHCHA
225             "\xCA" => "\xEA", # CYRILLIC LETTER HARD SIGN
226             "\xCB" => "\xEB", # CYRILLIC LETTER YERU
227             "\xCC" => "\xEC", # CYRILLIC LETTER SOFT SIGN
228             "\xCD" => "\xED", # CYRILLIC LETTER E
229             "\xCE" => "\xEE", # CYRILLIC LETTER YU
230             "\xCF" => "\xEF", # CYRILLIC LETTER YA
231             );
232              
233             %uc = (%uc,
234             "\xD0" => "\xB0", # CYRILLIC LETTER A
235             "\xD1" => "\xB1", # CYRILLIC LETTER BE
236             "\xD2" => "\xB2", # CYRILLIC LETTER VE
237             "\xD3" => "\xB3", # CYRILLIC LETTER GHE
238             "\xD4" => "\xB4", # CYRILLIC LETTER DE
239             "\xD5" => "\xB5", # CYRILLIC LETTER IE
240             "\xD6" => "\xB6", # CYRILLIC LETTER ZHE
241             "\xD7" => "\xB7", # CYRILLIC LETTER ZE
242             "\xD8" => "\xB8", # CYRILLIC LETTER I
243             "\xD9" => "\xB9", # CYRILLIC LETTER SHORT I
244             "\xDA" => "\xBA", # CYRILLIC LETTER KA
245             "\xDB" => "\xBB", # CYRILLIC LETTER EL
246             "\xDC" => "\xBC", # CYRILLIC LETTER EM
247             "\xDD" => "\xBD", # CYRILLIC LETTER EN
248             "\xDE" => "\xBE", # CYRILLIC LETTER O
249             "\xDF" => "\xBF", # CYRILLIC LETTER PE
250             "\xE0" => "\xC0", # CYRILLIC LETTER ER
251             "\xE1" => "\xC1", # CYRILLIC LETTER ES
252             "\xE2" => "\xC2", # CYRILLIC LETTER TE
253             "\xE3" => "\xC3", # CYRILLIC LETTER U
254             "\xE4" => "\xC4", # CYRILLIC LETTER EF
255             "\xE5" => "\xC5", # CYRILLIC LETTER HA
256             "\xE6" => "\xC6", # CYRILLIC LETTER TSE
257             "\xE7" => "\xC7", # CYRILLIC LETTER CHE
258             "\xE8" => "\xC8", # CYRILLIC LETTER SHA
259             "\xE9" => "\xC9", # CYRILLIC LETTER SHCHA
260             "\xEA" => "\xCA", # CYRILLIC LETTER HARD SIGN
261             "\xEB" => "\xCB", # CYRILLIC LETTER YERU
262             "\xEC" => "\xCC", # CYRILLIC LETTER SOFT SIGN
263             "\xED" => "\xCD", # CYRILLIC LETTER E
264             "\xEE" => "\xCE", # CYRILLIC LETTER YU
265             "\xEF" => "\xCF", # CYRILLIC LETTER YA
266             "\xF1" => "\xA1", # CYRILLIC LETTER IO
267             "\xF2" => "\xA2", # CYRILLIC LETTER DJE
268             "\xF3" => "\xA3", # CYRILLIC LETTER GJE
269             "\xF4" => "\xA4", # CYRILLIC LETTER UKRAINIAN IE
270             "\xF5" => "\xA5", # CYRILLIC LETTER DZE
271             "\xF6" => "\xA6", # CYRILLIC LETTER BYELORUSSIAN-UKRAINIAN I
272             "\xF7" => "\xA7", # CYRILLIC LETTER YI
273             "\xF8" => "\xA8", # CYRILLIC LETTER JE
274             "\xF9" => "\xA9", # CYRILLIC LETTER LJE
275             "\xFA" => "\xAA", # CYRILLIC LETTER NJE
276             "\xFB" => "\xAB", # CYRILLIC LETTER TSHE
277             "\xFC" => "\xAC", # CYRILLIC LETTER KJE
278             "\xFE" => "\xAE", # CYRILLIC LETTER SHORT U
279             "\xFF" => "\xAF", # CYRILLIC LETTER DZHE
280             );
281              
282             %fc = (%fc,
283             "\xA1" => "\xF1", # CYRILLIC CAPITAL LETTER IO --> CYRILLIC SMALL LETTER IO
284             "\xA2" => "\xF2", # CYRILLIC CAPITAL LETTER DJE --> CYRILLIC SMALL LETTER DJE
285             "\xA3" => "\xF3", # CYRILLIC CAPITAL LETTER GJE --> CYRILLIC SMALL LETTER GJE
286             "\xA4" => "\xF4", # CYRILLIC CAPITAL LETTER UKRAINIAN IE --> CYRILLIC SMALL LETTER UKRAINIAN IE
287             "\xA5" => "\xF5", # CYRILLIC CAPITAL LETTER DZE --> CYRILLIC SMALL LETTER DZE
288             "\xA6" => "\xF6", # CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I --> CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I
289             "\xA7" => "\xF7", # CYRILLIC CAPITAL LETTER YI --> CYRILLIC SMALL LETTER YI
290             "\xA8" => "\xF8", # CYRILLIC CAPITAL LETTER JE --> CYRILLIC SMALL LETTER JE
291             "\xA9" => "\xF9", # CYRILLIC CAPITAL LETTER LJE --> CYRILLIC SMALL LETTER LJE
292             "\xAA" => "\xFA", # CYRILLIC CAPITAL LETTER NJE --> CYRILLIC SMALL LETTER NJE
293             "\xAB" => "\xFB", # CYRILLIC CAPITAL LETTER TSHE --> CYRILLIC SMALL LETTER TSHE
294             "\xAC" => "\xFC", # CYRILLIC CAPITAL LETTER KJE --> CYRILLIC SMALL LETTER KJE
295             "\xAE" => "\xFE", # CYRILLIC CAPITAL LETTER SHORT U --> CYRILLIC SMALL LETTER SHORT U
296             "\xAF" => "\xFF", # CYRILLIC CAPITAL LETTER DZHE --> CYRILLIC SMALL LETTER DZHE
297             "\xB0" => "\xD0", # CYRILLIC CAPITAL LETTER A --> CYRILLIC SMALL LETTER A
298             "\xB1" => "\xD1", # CYRILLIC CAPITAL LETTER BE --> CYRILLIC SMALL LETTER BE
299             "\xB2" => "\xD2", # CYRILLIC CAPITAL LETTER VE --> CYRILLIC SMALL LETTER VE
300             "\xB3" => "\xD3", # CYRILLIC CAPITAL LETTER GHE --> CYRILLIC SMALL LETTER GHE
301             "\xB4" => "\xD4", # CYRILLIC CAPITAL LETTER DE --> CYRILLIC SMALL LETTER DE
302             "\xB5" => "\xD5", # CYRILLIC CAPITAL LETTER IE --> CYRILLIC SMALL LETTER IE
303             "\xB6" => "\xD6", # CYRILLIC CAPITAL LETTER ZHE --> CYRILLIC SMALL LETTER ZHE
304             "\xB7" => "\xD7", # CYRILLIC CAPITAL LETTER ZE --> CYRILLIC SMALL LETTER ZE
305             "\xB8" => "\xD8", # CYRILLIC CAPITAL LETTER I --> CYRILLIC SMALL LETTER I
306             "\xB9" => "\xD9", # CYRILLIC CAPITAL LETTER SHORT I --> CYRILLIC SMALL LETTER SHORT I
307             "\xBA" => "\xDA", # CYRILLIC CAPITAL LETTER KA --> CYRILLIC SMALL LETTER KA
308             "\xBB" => "\xDB", # CYRILLIC CAPITAL LETTER EL --> CYRILLIC SMALL LETTER EL
309             "\xBC" => "\xDC", # CYRILLIC CAPITAL LETTER EM --> CYRILLIC SMALL LETTER EM
310             "\xBD" => "\xDD", # CYRILLIC CAPITAL LETTER EN --> CYRILLIC SMALL LETTER EN
311             "\xBE" => "\xDE", # CYRILLIC CAPITAL LETTER O --> CYRILLIC SMALL LETTER O
312             "\xBF" => "\xDF", # CYRILLIC CAPITAL LETTER PE --> CYRILLIC SMALL LETTER PE
313             "\xC0" => "\xE0", # CYRILLIC CAPITAL LETTER ER --> CYRILLIC SMALL LETTER ER
314             "\xC1" => "\xE1", # CYRILLIC CAPITAL LETTER ES --> CYRILLIC SMALL LETTER ES
315             "\xC2" => "\xE2", # CYRILLIC CAPITAL LETTER TE --> CYRILLIC SMALL LETTER TE
316             "\xC3" => "\xE3", # CYRILLIC CAPITAL LETTER U --> CYRILLIC SMALL LETTER U
317             "\xC4" => "\xE4", # CYRILLIC CAPITAL LETTER EF --> CYRILLIC SMALL LETTER EF
318             "\xC5" => "\xE5", # CYRILLIC CAPITAL LETTER HA --> CYRILLIC SMALL LETTER HA
319             "\xC6" => "\xE6", # CYRILLIC CAPITAL LETTER TSE --> CYRILLIC SMALL LETTER TSE
320             "\xC7" => "\xE7", # CYRILLIC CAPITAL LETTER CHE --> CYRILLIC SMALL LETTER CHE
321             "\xC8" => "\xE8", # CYRILLIC CAPITAL LETTER SHA --> CYRILLIC SMALL LETTER SHA
322             "\xC9" => "\xE9", # CYRILLIC CAPITAL LETTER SHCHA --> CYRILLIC SMALL LETTER SHCHA
323             "\xCA" => "\xEA", # CYRILLIC CAPITAL LETTER HARD SIGN --> CYRILLIC SMALL LETTER HARD SIGN
324             "\xCB" => "\xEB", # CYRILLIC CAPITAL LETTER YERU --> CYRILLIC SMALL LETTER YERU
325             "\xCC" => "\xEC", # CYRILLIC CAPITAL LETTER SOFT SIGN --> CYRILLIC SMALL LETTER SOFT SIGN
326             "\xCD" => "\xED", # CYRILLIC CAPITAL LETTER E --> CYRILLIC SMALL LETTER E
327             "\xCE" => "\xEE", # CYRILLIC CAPITAL LETTER YU --> CYRILLIC SMALL LETTER YU
328             "\xCF" => "\xEF", # CYRILLIC CAPITAL LETTER YA --> CYRILLIC SMALL LETTER YA
329             );
330             }
331              
332             else {
333             croak "Don't know my package name '@{[__PACKAGE__]}'";
334             }
335              
336             #
337             # @ARGV wildcard globbing
338             #
339             sub import {
340              
341 0 0   0   0 if ($^O =~ /\A (?: MSWin32 | NetWare | symbian | dos ) \z/oxms) {
342 0         0 my @argv = ();
343 0         0 for (@ARGV) {
344              
345             # has space
346 0 0       0 if (/\A (?:$q_char)*? [ ] /oxms) {
    0          
347 0 0       0 if (my @glob = Ecyrillic::glob(qq{"$_"})) {
348 0         0 push @argv, @glob;
349             }
350             else {
351 0         0 push @argv, $_;
352             }
353             }
354              
355             # has wildcard metachar
356             elsif (/\A (?:$q_char)*? [*?] /oxms) {
357 0 0       0 if (my @glob = Ecyrillic::glob($_)) {
358 0         0 push @argv, @glob;
359             }
360             else {
361 0         0 push @argv, $_;
362             }
363             }
364              
365             # no wildcard globbing
366             else {
367 0         0 push @argv, $_;
368             }
369             }
370 0         0 @ARGV = @argv;
371             }
372              
373 0         0 *Char::ord = \&Cyrillic::ord;
374 0         0 *Char::ord_ = \&Cyrillic::ord_;
375 0         0 *Char::reverse = \&Cyrillic::reverse;
376 0         0 *Char::getc = \&Cyrillic::getc;
377 0         0 *Char::length = \&Cyrillic::length;
378 0         0 *Char::substr = \&Cyrillic::substr;
379 0         0 *Char::index = \&Cyrillic::index;
380 0         0 *Char::rindex = \&Cyrillic::rindex;
381 0         0 *Char::eval = \&Cyrillic::eval;
382 0         0 *Char::escape = \&Cyrillic::escape;
383 0         0 *Char::escape_token = \&Cyrillic::escape_token;
384 0         0 *Char::escape_script = \&Cyrillic::escape_script;
385             }
386              
387             # P.230 Care with Prototypes
388             # in Chapter 6: Subroutines
389             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
390             #
391             # If you aren't careful, you can get yourself into trouble with prototypes.
392             # But if you are careful, you can do a lot of neat things with them. This is
393             # all very powerful, of course, and should only be used in moderation to make
394             # the world a better place.
395              
396             # P.332 Care with Prototypes
397             # in Chapter 7: Subroutines
398             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
399             #
400             # If you aren't careful, you can get yourself into trouble with prototypes.
401             # But if you are careful, you can do a lot of neat things with them. This is
402             # all very powerful, of course, and should only be used in moderation to make
403             # the world a better place.
404              
405             #
406             # Prototypes of subroutines
407             #
408       0     sub unimport {}
409             sub Ecyrillic::split(;$$$);
410             sub Ecyrillic::tr($$$$;$);
411             sub Ecyrillic::chop(@);
412             sub Ecyrillic::index($$;$);
413             sub Ecyrillic::rindex($$;$);
414             sub Ecyrillic::lcfirst(@);
415             sub Ecyrillic::lcfirst_();
416             sub Ecyrillic::lc(@);
417             sub Ecyrillic::lc_();
418             sub Ecyrillic::ucfirst(@);
419             sub Ecyrillic::ucfirst_();
420             sub Ecyrillic::uc(@);
421             sub Ecyrillic::uc_();
422             sub Ecyrillic::fc(@);
423             sub Ecyrillic::fc_();
424             sub Ecyrillic::ignorecase;
425             sub Ecyrillic::classic_character_class;
426             sub Ecyrillic::capture;
427             sub Ecyrillic::chr(;$);
428             sub Ecyrillic::chr_();
429             sub Ecyrillic::glob($);
430             sub Ecyrillic::glob_();
431              
432             sub Cyrillic::ord(;$);
433             sub Cyrillic::ord_();
434             sub Cyrillic::reverse(@);
435             sub Cyrillic::getc(;*@);
436             sub Cyrillic::length(;$);
437             sub Cyrillic::substr($$;$$);
438             sub Cyrillic::index($$;$);
439             sub Cyrillic::rindex($$;$);
440             sub Cyrillic::escape(;$);
441              
442             #
443             # Regexp work
444             #
445 206         15997 use vars qw(
446             $re_a
447             $re_t
448             $re_n
449             $re_r
450 206     206   1551 );
  206         410  
451              
452             #
453             # Character class
454             #
455 206         1858275 use vars qw(
456             $dot
457             $dot_s
458             $eD
459             $eS
460             $eW
461             $eH
462             $eV
463             $eR
464             $eN
465             $not_alnum
466             $not_alpha
467             $not_ascii
468             $not_blank
469             $not_cntrl
470             $not_digit
471             $not_graph
472             $not_lower
473             $not_lower_i
474             $not_print
475             $not_punct
476             $not_space
477             $not_upper
478             $not_upper_i
479             $not_word
480             $not_xdigit
481             $eb
482             $eB
483 206     206   1484 );
  206         565  
484              
485             ${Ecyrillic::dot} = qr{(?>[^\x0A])};
486             ${Ecyrillic::dot_s} = qr{(?>[\x00-\xFF])};
487             ${Ecyrillic::eD} = qr{(?>[^0-9])};
488              
489             # Vertical tabs are now whitespace
490             # \s in a regex now matches a vertical tab in all circumstances.
491             # http://search.cpan.org/dist/perl-5.18.0/pod/perldelta.pod#Vertical_tabs_are_now_whitespace
492             # ${Ecyrillic::eS} = qr{(?>[^\x09\x0A \x0C\x0D\x20])};
493             # ${Ecyrillic::eS} = qr{(?>[^\x09\x0A\x0B\x0C\x0D\x20])};
494             ${Ecyrillic::eS} = qr{(?>[^\s])};
495              
496             ${Ecyrillic::eW} = qr{(?>[^0-9A-Z_a-z])};
497             ${Ecyrillic::eH} = qr{(?>[^\x09\x20])};
498             ${Ecyrillic::eV} = qr{(?>[^\x0A\x0B\x0C\x0D])};
499             ${Ecyrillic::eR} = qr{(?>\x0D\x0A|[\x0A\x0D])};
500             ${Ecyrillic::eN} = qr{(?>[^\x0A])};
501             ${Ecyrillic::not_alnum} = qr{(?>[^\x30-\x39\x41-\x5A\x61-\x7A])};
502             ${Ecyrillic::not_alpha} = qr{(?>[^\x41-\x5A\x61-\x7A])};
503             ${Ecyrillic::not_ascii} = qr{(?>[^\x00-\x7F])};
504             ${Ecyrillic::not_blank} = qr{(?>[^\x09\x20])};
505             ${Ecyrillic::not_cntrl} = qr{(?>[^\x00-\x1F\x7F])};
506             ${Ecyrillic::not_digit} = qr{(?>[^\x30-\x39])};
507             ${Ecyrillic::not_graph} = qr{(?>[^\x21-\x7F])};
508             ${Ecyrillic::not_lower} = qr{(?>[^\x61-\x7A])};
509             ${Ecyrillic::not_lower_i} = qr{(?>[^\x41-\x5A\x61-\x7A])}; # Perl 5.16 compatible
510             # ${Ecyrillic::not_lower_i} = qr{(?>[\x00-\xFF])}; # older Perl compatible
511             ${Ecyrillic::not_print} = qr{(?>[^\x20-\x7F])};
512             ${Ecyrillic::not_punct} = qr{(?>[^\x21-\x2F\x3A-\x3F\x40\x5B-\x5F\x60\x7B-\x7E])};
513             ${Ecyrillic::not_space} = qr{(?>[^\s\x0B])};
514             ${Ecyrillic::not_upper} = qr{(?>[^\x41-\x5A])};
515             ${Ecyrillic::not_upper_i} = qr{(?>[^\x41-\x5A\x61-\x7A])}; # Perl 5.16 compatible
516             # ${Ecyrillic::not_upper_i} = qr{(?>[\x00-\xFF])}; # older Perl compatible
517             ${Ecyrillic::not_word} = qr{(?>[^\x30-\x39\x41-\x5A\x5F\x61-\x7A])};
518             ${Ecyrillic::not_xdigit} = qr{(?>[^\x30-\x39\x41-\x46\x61-\x66])};
519             ${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))};
520             ${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]))};
521              
522             # avoid: Name "Ecyrillic::foo" used only once: possible typo at here.
523             ${Ecyrillic::dot} = ${Ecyrillic::dot};
524             ${Ecyrillic::dot_s} = ${Ecyrillic::dot_s};
525             ${Ecyrillic::eD} = ${Ecyrillic::eD};
526             ${Ecyrillic::eS} = ${Ecyrillic::eS};
527             ${Ecyrillic::eW} = ${Ecyrillic::eW};
528             ${Ecyrillic::eH} = ${Ecyrillic::eH};
529             ${Ecyrillic::eV} = ${Ecyrillic::eV};
530             ${Ecyrillic::eR} = ${Ecyrillic::eR};
531             ${Ecyrillic::eN} = ${Ecyrillic::eN};
532             ${Ecyrillic::not_alnum} = ${Ecyrillic::not_alnum};
533             ${Ecyrillic::not_alpha} = ${Ecyrillic::not_alpha};
534             ${Ecyrillic::not_ascii} = ${Ecyrillic::not_ascii};
535             ${Ecyrillic::not_blank} = ${Ecyrillic::not_blank};
536             ${Ecyrillic::not_cntrl} = ${Ecyrillic::not_cntrl};
537             ${Ecyrillic::not_digit} = ${Ecyrillic::not_digit};
538             ${Ecyrillic::not_graph} = ${Ecyrillic::not_graph};
539             ${Ecyrillic::not_lower} = ${Ecyrillic::not_lower};
540             ${Ecyrillic::not_lower_i} = ${Ecyrillic::not_lower_i};
541             ${Ecyrillic::not_print} = ${Ecyrillic::not_print};
542             ${Ecyrillic::not_punct} = ${Ecyrillic::not_punct};
543             ${Ecyrillic::not_space} = ${Ecyrillic::not_space};
544             ${Ecyrillic::not_upper} = ${Ecyrillic::not_upper};
545             ${Ecyrillic::not_upper_i} = ${Ecyrillic::not_upper_i};
546             ${Ecyrillic::not_word} = ${Ecyrillic::not_word};
547             ${Ecyrillic::not_xdigit} = ${Ecyrillic::not_xdigit};
548             ${Ecyrillic::eb} = ${Ecyrillic::eb};
549             ${Ecyrillic::eB} = ${Ecyrillic::eB};
550              
551             #
552             # Cyrillic split
553             #
554             sub Ecyrillic::split(;$$$) {
555              
556             # P.794 29.2.161. split
557             # in Chapter 29: Functions
558             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
559              
560             # P.951 split
561             # in Chapter 27: Functions
562             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
563              
564 0     0 0 0 my $pattern = $_[0];
565 0         0 my $string = $_[1];
566 0         0 my $limit = $_[2];
567              
568             # if $pattern is also omitted or is the literal space, " "
569 0 0       0 if (not defined $pattern) {
570 0         0 $pattern = ' ';
571             }
572              
573             # if $string is omitted, the function splits the $_ string
574 0 0       0 if (not defined $string) {
575 0 0       0 if (defined $_) {
576 0         0 $string = $_;
577             }
578             else {
579 0         0 $string = '';
580             }
581             }
582              
583 0         0 my @split = ();
584              
585             # when string is empty
586 0 0       0 if ($string eq '') {
    0          
587              
588             # resulting list value in list context
589 0 0       0 if (wantarray) {
590 0         0 return @split;
591             }
592              
593             # count of substrings in scalar context
594             else {
595 0 0       0 carp "Use of implicit split to \@_ is deprecated" if $^W;
596 0         0 @_ = @split;
597 0         0 return scalar @_;
598             }
599             }
600              
601             # split's first argument is more consistently interpreted
602             #
603             # After some changes earlier in v5.17, split's behavior has been simplified:
604             # if the PATTERN argument evaluates to a string containing one space, it is
605             # treated the way that a literal string containing one space once was.
606             # http://search.cpan.org/dist/perl-5.18.0/pod/perldelta.pod#split's_first_argument_is_more_consistently_interpreted
607              
608             # if $pattern is also omitted or is the literal space, " ", the function splits
609             # on whitespace, /\s+/, after skipping any leading whitespace
610             # (and so on)
611              
612             elsif ($pattern eq ' ') {
613 0 0       0 if (not defined $limit) {
614 0         0 return CORE::split(' ', $string);
615             }
616             else {
617 0         0 return CORE::split(' ', $string, $limit);
618             }
619             }
620              
621             # if $limit is negative, it is treated as if an arbitrarily large $limit has been specified
622 0 0 0     0 if ((not defined $limit) or ($limit <= 0)) {
    0          
623              
624             # a pattern capable of matching either the null string or something longer than the
625             # null string will split the value of $string into separate characters wherever it
626             # matches the null string between characters
627             # (and so on)
628              
629 0 0       0 if ('' =~ / \A $pattern \z /xms) {
630 0         0 my $last_subexpression_offsets = _last_subexpression_offsets($pattern);
631 0         0 my $limit = scalar(() = $string =~ /($pattern)/oxmsg);
632              
633             # P.1024 Appendix W.10 Multibyte Processing
634             # of ISBN 1-56592-224-7 CJKV Information Processing
635             # (and so on)
636              
637             # the //m modifier is assumed when you split on the pattern /^/
638             # (and so on)
639              
640 0         0 eval q{ no warnings }; # avoid: Complex regular subexpression recursion limit (32766) exceeded at ...
641             # V
642 0   0     0 while ((--$limit > 0) and ($string =~ s/\A((?:$q_char)+?)$pattern//m)) {
643              
644             # if the $pattern contains parentheses, then the substring matched by each pair of parentheses
645             # is included in the resulting list, interspersed with the fields that are ordinarily returned
646             # (and so on)
647              
648 0         0 local $@;
649 0         0 eval q{ no warnings }; # avoid: Complex regular subexpression recursion limit (32766) exceeded at ...
650 0         0 for (my $digit=1; $digit <= ($last_subexpression_offsets + 1); $digit++) {
651 0         0 push @split, CORE::eval('$' . $digit);
652             }
653             }
654             }
655              
656             else {
657 0         0 my $last_subexpression_offsets = _last_subexpression_offsets($pattern);
658              
659 0         0 eval q{ no warnings }; # avoid: Complex regular subexpression recursion limit (32766) exceeded at ...
660             # V
661 0         0 while ($string =~ s/\A((?:$q_char)*?)$pattern//m) {
662 0         0 local $@;
663 0         0 eval q{ no warnings }; # avoid: Complex regular subexpression recursion limit (32766) exceeded at ...
664 0         0 for (my $digit=1; $digit <= ($last_subexpression_offsets + 1); $digit++) {
665 0         0 push @split, CORE::eval('$' . $digit);
666             }
667             }
668             }
669             }
670              
671             elsif ($limit > 0) {
672 0 0       0 if ('' =~ / \A $pattern \z /xms) {
673 0         0 my $last_subexpression_offsets = _last_subexpression_offsets($pattern);
674 0   0     0 while ((--$limit > 0) and (CORE::length($string) > 0)) {
675              
676 0         0 eval q{ no warnings }; # avoid: Complex regular subexpression recursion limit (32766) exceeded at ...
677             # V
678 0 0       0 if ($string =~ s/\A((?:$q_char)+?)$pattern//m) {
679 0         0 local $@;
680 0         0 for (my $digit=1; $digit <= ($last_subexpression_offsets + 1); $digit++) {
681 0         0 push @split, CORE::eval('$' . $digit);
682             }
683             }
684             }
685             }
686             else {
687 0         0 my $last_subexpression_offsets = _last_subexpression_offsets($pattern);
688 0   0     0 while ((--$limit > 0) and (CORE::length($string) > 0)) {
689              
690 0         0 eval q{ no warnings }; # avoid: Complex regular subexpression recursion limit (32766) exceeded at ...
691             # V
692 0 0       0 if ($string =~ s/\A((?:$q_char)*?)$pattern//m) {
693 0         0 local $@;
694 0         0 for (my $digit=1; $digit <= ($last_subexpression_offsets + 1); $digit++) {
695 0         0 push @split, CORE::eval('$' . $digit);
696             }
697             }
698             }
699             }
700             }
701              
702 0 0       0 if (CORE::length($string) > 0) {
703 0         0 push @split, $string;
704             }
705              
706             # if $_[2] (NOT "$limit") is omitted or zero, trailing null fields are stripped from the result
707 0 0 0     0 if ((not defined $_[2]) or ($_[2] == 0)) {
708 0   0     0 while ((scalar(@split) >= 1) and ($split[-1] eq '')) {
709 0         0 pop @split;
710             }
711             }
712              
713             # resulting list value in list context
714 0 0       0 if (wantarray) {
715 0         0 return @split;
716             }
717              
718             # count of substrings in scalar context
719             else {
720 0 0       0 carp "Use of implicit split to \@_ is deprecated" if $^W;
721 0         0 @_ = @split;
722 0         0 return scalar @_;
723             }
724             }
725              
726             #
727             # get last subexpression offsets
728             #
729             sub _last_subexpression_offsets {
730 0     0   0 my $pattern = $_[0];
731              
732             # remove comment
733 0         0 $pattern =~ s/\(\?\# .*? \)//oxmsg;
734              
735 0         0 my $modifier = '';
736 0 0       0 if ($pattern =~ /\(\?\^? ([\-A-Za-z]+) :/oxms) {
737 0         0 $modifier = $1;
738 0         0 $modifier =~ s/-[A-Za-z]*//;
739             }
740              
741             # with /x modifier
742 0         0 my @char = ();
743 0 0       0 if ($modifier =~ /x/oxms) {
744 0         0 @char = $pattern =~ /\G((?>
745             [^\\\#\[\(] |
746             \\ $q_char |
747             \# (?>[^\n]*) $ |
748             \[ (?>(?:[^\\\]]|\\\\|\\\]|$q_char)+) \] |
749             \(\? |
750             $q_char
751             ))/oxmsg;
752             }
753              
754             # without /x modifier
755             else {
756 0         0 @char = $pattern =~ /\G((?>
757             [^\\\[\(] |
758             \\ $q_char |
759             \[ (?>(?:[^\\\]]|\\\\|\\\]|$q_char)+) \] |
760             \(\? |
761             $q_char
762             ))/oxmsg;
763             }
764              
765 0         0 return scalar grep { $_ eq '(' } @char;
  0         0  
766             }
767              
768             #
769             # Cyrillic transliteration (tr///)
770             #
771             sub Ecyrillic::tr($$$$;$) {
772              
773 0     0 0 0 my $bind_operator = $_[1];
774 0         0 my $searchlist = $_[2];
775 0         0 my $replacementlist = $_[3];
776 0   0     0 my $modifier = $_[4] || '';
777              
778 0 0       0 if ($modifier =~ /r/oxms) {
779 0 0       0 if ($bind_operator =~ / !~ /oxms) {
780 0         0 croak "Using !~ with tr///r doesn't make sense";
781             }
782             }
783              
784 0         0 my @char = $_[0] =~ /\G (?>$q_char) /oxmsg;
785 0         0 my @searchlist = _charlist_tr($searchlist);
786 0         0 my @replacementlist = _charlist_tr($replacementlist);
787              
788 0         0 my %tr = ();
789 0         0 for (my $i=0; $i <= $#searchlist; $i++) {
790 0 0       0 if (not exists $tr{$searchlist[$i]}) {
791 0 0 0     0 if (defined $replacementlist[$i] and ($replacementlist[$i] ne '')) {
    0 0        
    0          
792 0         0 $tr{$searchlist[$i]} = $replacementlist[$i];
793             }
794             elsif ($modifier =~ /d/oxms) {
795 0         0 $tr{$searchlist[$i]} = '';
796             }
797             elsif (defined $replacementlist[-1] and ($replacementlist[-1] ne '')) {
798 0         0 $tr{$searchlist[$i]} = $replacementlist[-1];
799             }
800             else {
801 0         0 $tr{$searchlist[$i]} = $searchlist[$i];
802             }
803             }
804             }
805              
806 0         0 my $tr = 0;
807 0         0 my $replaced = '';
808 0 0       0 if ($modifier =~ /c/oxms) {
809 0         0 while (defined(my $char = shift @char)) {
810 0 0       0 if (not exists $tr{$char}) {
811 0 0       0 if (defined $replacementlist[-1]) {
812 0         0 $replaced .= $replacementlist[-1];
813             }
814 0         0 $tr++;
815 0 0       0 if ($modifier =~ /s/oxms) {
816 0   0     0 while (@char and (not exists $tr{$char[0]})) {
817 0         0 shift @char;
818 0         0 $tr++;
819             }
820             }
821             }
822             else {
823 0         0 $replaced .= $char;
824             }
825             }
826             }
827             else {
828 0         0 while (defined(my $char = shift @char)) {
829 0 0       0 if (exists $tr{$char}) {
830 0         0 $replaced .= $tr{$char};
831 0         0 $tr++;
832 0 0       0 if ($modifier =~ /s/oxms) {
833 0   0     0 while (@char and (exists $tr{$char[0]}) and ($tr{$char[0]} eq $tr{$char})) {
      0        
834 0         0 shift @char;
835 0         0 $tr++;
836             }
837             }
838             }
839             else {
840 0         0 $replaced .= $char;
841             }
842             }
843             }
844              
845 0 0       0 if ($modifier =~ /r/oxms) {
846 0         0 return $replaced;
847             }
848             else {
849 0         0 $_[0] = $replaced;
850 0 0       0 if ($bind_operator =~ / !~ /oxms) {
851 0         0 return not $tr;
852             }
853             else {
854 0         0 return $tr;
855             }
856             }
857             }
858              
859             #
860             # Cyrillic chop
861             #
862             sub Ecyrillic::chop(@) {
863              
864 0     0 0 0 my $chop;
865 0 0       0 if (@_ == 0) {
866 0         0 my @char = /\G (?>$q_char) /oxmsg;
867 0         0 $chop = pop @char;
868 0         0 $_ = join '', @char;
869             }
870             else {
871 0         0 for (@_) {
872 0         0 my @char = /\G (?>$q_char) /oxmsg;
873 0         0 $chop = pop @char;
874 0         0 $_ = join '', @char;
875             }
876             }
877 0         0 return $chop;
878             }
879              
880             #
881             # Cyrillic index by octet
882             #
883             sub Ecyrillic::index($$;$) {
884              
885 0     0 1 0 my($str,$substr,$position) = @_;
886 0   0     0 $position ||= 0;
887 0         0 my $pos = 0;
888              
889 0         0 while ($pos < CORE::length($str)) {
890 0 0       0 if (CORE::substr($str,$pos,CORE::length($substr)) eq $substr) {
891 0 0       0 if ($pos >= $position) {
892 0         0 return $pos;
893             }
894             }
895 0 0       0 if (CORE::substr($str,$pos) =~ /\A ($q_char) /oxms) {
896 0         0 $pos += CORE::length($1);
897             }
898             else {
899 0         0 $pos += 1;
900             }
901             }
902 0         0 return -1;
903             }
904              
905             #
906             # Cyrillic reverse index
907             #
908             sub Ecyrillic::rindex($$;$) {
909              
910 0     0 0 0 my($str,$substr,$position) = @_;
911 0   0     0 $position ||= CORE::length($str) - 1;
912 0         0 my $pos = 0;
913 0         0 my $rindex = -1;
914              
915 0   0     0 while (($pos < CORE::length($str)) and ($pos <= $position)) {
916 0 0       0 if (CORE::substr($str,$pos,CORE::length($substr)) eq $substr) {
917 0         0 $rindex = $pos;
918             }
919 0 0       0 if (CORE::substr($str,$pos) =~ /\A ($q_char) /oxms) {
920 0         0 $pos += CORE::length($1);
921             }
922             else {
923 0         0 $pos += 1;
924             }
925             }
926 0         0 return $rindex;
927             }
928              
929             #
930             # Cyrillic lower case first with parameter
931             #
932             sub Ecyrillic::lcfirst(@) {
933 0 0   0 0 0 if (@_) {
934 0         0 my $s = shift @_;
935 0 0 0     0 if (@_ and wantarray) {
936 0         0 return Ecyrillic::lc(CORE::substr($s,0,1)) . CORE::substr($s,1), @_;
937             }
938             else {
939 0         0 return Ecyrillic::lc(CORE::substr($s,0,1)) . CORE::substr($s,1);
940             }
941             }
942             else {
943 0         0 return Ecyrillic::lc(CORE::substr($_,0,1)) . CORE::substr($_,1);
944             }
945             }
946              
947             #
948             # Cyrillic lower case first without parameter
949             #
950             sub Ecyrillic::lcfirst_() {
951 0     0 0 0 return Ecyrillic::lc(CORE::substr($_,0,1)) . CORE::substr($_,1);
952             }
953              
954             #
955             # Cyrillic lower case with parameter
956             #
957             sub Ecyrillic::lc(@) {
958 0 0   0 0 0 if (@_) {
959 0         0 my $s = shift @_;
960 0 0 0     0 if (@_ and wantarray) {
961 0 0       0 return join('', map {defined($lc{$_}) ? $lc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg)), @_;
  0         0  
962             }
963             else {
964 0 0       0 return join('', map {defined($lc{$_}) ? $lc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg));
  0         0  
965             }
966             }
967             else {
968 0         0 return Ecyrillic::lc_();
969             }
970             }
971              
972             #
973             # Cyrillic lower case without parameter
974             #
975             sub Ecyrillic::lc_() {
976 0     0 0 0 my $s = $_;
977 0 0       0 return join '', map {defined($lc{$_}) ? $lc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg);
  0         0  
978             }
979              
980             #
981             # Cyrillic upper case first with parameter
982             #
983             sub Ecyrillic::ucfirst(@) {
984 0 0   0 0 0 if (@_) {
985 0         0 my $s = shift @_;
986 0 0 0     0 if (@_ and wantarray) {
987 0         0 return Ecyrillic::uc(CORE::substr($s,0,1)) . CORE::substr($s,1), @_;
988             }
989             else {
990 0         0 return Ecyrillic::uc(CORE::substr($s,0,1)) . CORE::substr($s,1);
991             }
992             }
993             else {
994 0         0 return Ecyrillic::uc(CORE::substr($_,0,1)) . CORE::substr($_,1);
995             }
996             }
997              
998             #
999             # Cyrillic upper case first without parameter
1000             #
1001             sub Ecyrillic::ucfirst_() {
1002 0     0 0 0 return Ecyrillic::uc(CORE::substr($_,0,1)) . CORE::substr($_,1);
1003             }
1004              
1005             #
1006             # Cyrillic upper case with parameter
1007             #
1008             sub Ecyrillic::uc(@) {
1009 0 50   174 0 0 if (@_) {
1010 174         265 my $s = shift @_;
1011 174 50 33     247 if (@_ and wantarray) {
1012 174 0       317 return join('', map {defined($uc{$_}) ? $uc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg)), @_;
  0         0  
1013             }
1014             else {
1015 0 100       0 return join('', map {defined($uc{$_}) ? $uc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg));
  174         530  
1016             }
1017             }
1018             else {
1019 174         609 return Ecyrillic::uc_();
1020             }
1021             }
1022              
1023             #
1024             # Cyrillic upper case without parameter
1025             #
1026             sub Ecyrillic::uc_() {
1027 0     0 0 0 my $s = $_;
1028 0 0       0 return join '', map {defined($uc{$_}) ? $uc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg);
  0         0  
1029             }
1030              
1031             #
1032             # Cyrillic fold case with parameter
1033             #
1034             sub Ecyrillic::fc(@) {
1035 0 50   197 0 0 if (@_) {
1036 197         273 my $s = shift @_;
1037 197 50 33     227 if (@_ and wantarray) {
1038 197 0       322 return join('', map {defined($fc{$_}) ? $fc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg)), @_;
  0         0  
1039             }
1040             else {
1041 0 100       0 return join('', map {defined($fc{$_}) ? $fc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg));
  197         475  
1042             }
1043             }
1044             else {
1045 197         1025 return Ecyrillic::fc_();
1046             }
1047             }
1048              
1049             #
1050             # Cyrillic fold case without parameter
1051             #
1052             sub Ecyrillic::fc_() {
1053 0     0 0 0 my $s = $_;
1054 0 0       0 return join '', map {defined($fc{$_}) ? $fc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg);
  0         0  
1055             }
1056              
1057             #
1058             # Cyrillic regexp capture
1059             #
1060             {
1061             sub Ecyrillic::capture {
1062 0     0 1 0 return $_[0];
1063             }
1064             }
1065              
1066             #
1067             # Cyrillic regexp ignore case modifier
1068             #
1069             sub Ecyrillic::ignorecase {
1070              
1071 0     0 0 0 my @string = @_;
1072 0         0 my $metachar = qr/[\@\\|[\]{]/oxms;
1073              
1074             # ignore case of $scalar or @array
1075 0         0 for my $string (@string) {
1076              
1077             # split regexp
1078 0         0 my @char = $string =~ /\G (?>\[\^|\\$q_char|$q_char) /oxmsg;
1079              
1080             # unescape character
1081 0         0 for (my $i=0; $i <= $#char; $i++) {
1082 0 0       0 next if not defined $char[$i];
1083              
1084             # open character class [...]
1085 0 0       0 if ($char[$i] eq '[') {
    0          
    0          
    0          
1086 0         0 my $left = $i;
1087              
1088             # [] make die "unmatched [] in regexp ...\n"
1089              
1090 0 0       0 if ($char[$i+1] eq ']') {
1091 0         0 $i++;
1092             }
1093              
1094 0         0 while (1) {
1095 0 0       0 if (++$i > $#char) {
1096 0         0 croak "Unmatched [] in regexp";
1097             }
1098 0 0       0 if ($char[$i] eq ']') {
1099 0         0 my $right = $i;
1100 0         0 my @charlist = charlist_qr(@char[$left+1..$right-1], 'i');
1101              
1102             # escape character
1103 0         0 for my $char (@charlist) {
1104 0 0       0 if (0) {
1105             }
1106              
1107 0         0 elsif ($char =~ /\A [.|)] \z/oxms) {
1108 0         0 $char = '\\' . $char;
1109             }
1110             }
1111              
1112             # [...]
1113 0         0 splice @char, $left, $right-$left+1, '(?:' . join('|', @charlist) . ')';
1114              
1115 0         0 $i = $left;
1116 0         0 last;
1117             }
1118             }
1119             }
1120              
1121             # open character class [^...]
1122             elsif ($char[$i] eq '[^') {
1123 0         0 my $left = $i;
1124              
1125             # [^] make die "unmatched [] in regexp ...\n"
1126              
1127 0 0       0 if ($char[$i+1] eq ']') {
1128 0         0 $i++;
1129             }
1130              
1131 0         0 while (1) {
1132 0 0       0 if (++$i > $#char) {
1133 0         0 croak "Unmatched [] in regexp";
1134             }
1135 0 0       0 if ($char[$i] eq ']') {
1136 0         0 my $right = $i;
1137 0         0 my @charlist = charlist_not_qr(@char[$left+1..$right-1], 'i');
1138              
1139             # escape character
1140 0         0 for my $char (@charlist) {
1141 0 0       0 if (0) {
1142             }
1143              
1144 0         0 elsif ($char =~ /\A [.|)] \z/oxms) {
1145 0         0 $char = '\\' . $char;
1146             }
1147             }
1148              
1149             # [^...]
1150 0         0 splice @char, $left, $right-$left+1, '(?!' . join('|', @charlist) . ")(?:$your_char)";
1151              
1152 0         0 $i = $left;
1153 0         0 last;
1154             }
1155             }
1156             }
1157              
1158             # rewrite classic character class or escape character
1159             elsif (my $char = classic_character_class($char[$i])) {
1160 0         0 $char[$i] = $char;
1161             }
1162              
1163             # with /i modifier
1164             elsif ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) {
1165 0         0 my $uc = Ecyrillic::uc($char[$i]);
1166 0         0 my $fc = Ecyrillic::fc($char[$i]);
1167 0 0       0 if ($uc ne $fc) {
1168 0 0       0 if (CORE::length($fc) == 1) {
1169 0         0 $char[$i] = '[' . $uc . $fc . ']';
1170             }
1171             else {
1172 0         0 $char[$i] = '(?:' . $uc . '|' . $fc . ')';
1173             }
1174             }
1175             }
1176             }
1177              
1178             # characterize
1179 0         0 for (my $i=0; $i <= $#char; $i++) {
1180 0 0       0 next if not defined $char[$i];
1181              
1182 0 0       0 if (0) {
1183             }
1184              
1185             # quote character before ? + * {
1186 0 0       0 elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
1187 0 0       0 if ($char[$i-1] !~ /\A [\x00-\xFF] \z/oxms) {
1188 0         0 $char[$i-1] = '(?:' . $char[$i-1] . ')';
1189             }
1190             }
1191             }
1192              
1193 0         0 $string = join '', @char;
1194             }
1195              
1196             # make regexp string
1197 0         0 return @string;
1198             }
1199              
1200             #
1201             # classic character class ( \D \S \W \d \s \w \C \X \H \V \h \v \R \N \b \B )
1202             #
1203             sub Ecyrillic::classic_character_class {
1204 0     1867 0 0 my($char) = @_;
1205              
1206             return {
1207             '\D' => '${Ecyrillic::eD}',
1208             '\S' => '${Ecyrillic::eS}',
1209             '\W' => '${Ecyrillic::eW}',
1210             '\d' => '[0-9]',
1211              
1212             # Before Perl 5.6, \s only matched the five whitespace characters
1213             # tab, newline, form-feed, carriage return, and the space character
1214             # itself, which, taken together, is the character class [\t\n\f\r ].
1215              
1216             # Vertical tabs are now whitespace
1217             # \s in a regex now matches a vertical tab in all circumstances.
1218             # http://search.cpan.org/dist/perl-5.18.0/pod/perldelta.pod#Vertical_tabs_are_now_whitespace
1219             # \t \n \v \f \r space
1220             # '\s' => '[\x09\x0A \x0C\x0D\x20]',
1221             # '\s' => '[\x09\x0A\x0B\x0C\x0D\x20]',
1222             '\s' => '\s',
1223              
1224             '\w' => '[0-9A-Z_a-z]',
1225             '\C' => '[\x00-\xFF]',
1226             '\X' => 'X',
1227              
1228             # \h \v \H \V
1229              
1230             # P.114 Character Class Shortcuts
1231             # in Chapter 7: In the World of Regular Expressions
1232             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
1233              
1234             # P.357 13.2.3 Whitespace
1235             # in Chapter 13: perlrecharclass: Perl Regular Expression Character Classes
1236             # of ISBN-13: 978-1-906966-02-7 The Perl Language Reference Manual (for Perl version 5.12.1)
1237             #
1238             # 0x00009 CHARACTER TABULATION h s
1239             # 0x0000a LINE FEED (LF) vs
1240             # 0x0000b LINE TABULATION v
1241             # 0x0000c FORM FEED (FF) vs
1242             # 0x0000d CARRIAGE RETURN (CR) vs
1243             # 0x00020 SPACE h s
1244              
1245             # P.196 Table 5-9. Alphanumeric regex metasymbols
1246             # in Chapter 5. Pattern Matching
1247             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
1248              
1249             # (and so on)
1250              
1251             '\H' => '${Ecyrillic::eH}',
1252             '\V' => '${Ecyrillic::eV}',
1253             '\h' => '[\x09\x20]',
1254             '\v' => '[\x0A\x0B\x0C\x0D]',
1255             '\R' => '${Ecyrillic::eR}',
1256              
1257             # \N
1258             #
1259             # http://perldoc.perl.org/perlre.html
1260             # Character Classes and other Special Escapes
1261             # Any character but \n (experimental). Not affected by /s modifier
1262              
1263             '\N' => '${Ecyrillic::eN}',
1264              
1265             # \b \B
1266              
1267             # P.180 Boundaries: The \b and \B Assertions
1268             # in Chapter 5: Pattern Matching
1269             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
1270              
1271             # P.219 Boundaries: The \b and \B Assertions
1272             # in Chapter 5: Pattern Matching
1273             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
1274              
1275             # \b really means (?:(?<=\w)(?!\w)|(?
1276             # or (?:(?<=\A|\W)(?=\w)|(?<=\w)(?=\W|\z))
1277             '\b' => '${Ecyrillic::eb}',
1278              
1279             # \B really means (?:(?<=\w)(?=\w)|(?
1280             # or (?:(?<=\w)(?=\w)|(?<=\W)(?=\W))
1281             '\B' => '${Ecyrillic::eB}',
1282              
1283 1867   100     2513 }->{$char} || '';
1284             }
1285              
1286             #
1287             # prepare Cyrillic characters per length
1288             #
1289              
1290             # 1 octet characters
1291             my @chars1 = ();
1292             sub chars1 {
1293 1867 0   0 0 66440 if (@chars1) {
1294 0         0 return @chars1;
1295             }
1296 0 0       0 if (exists $range_tr{1}) {
1297 0         0 my @ranges = @{ $range_tr{1} };
  0         0  
1298 0         0 while (my @range = splice(@ranges,0,1)) {
1299 0         0 for my $oct0 (@{$range[0]}) {
  0         0  
1300 0         0 push @chars1, pack 'C', $oct0;
1301             }
1302             }
1303             }
1304 0         0 return @chars1;
1305             }
1306              
1307             # 2 octets characters
1308             my @chars2 = ();
1309             sub chars2 {
1310 0 0   0 0 0 if (@chars2) {
1311 0         0 return @chars2;
1312             }
1313 0 0       0 if (exists $range_tr{2}) {
1314 0         0 my @ranges = @{ $range_tr{2} };
  0         0  
1315 0         0 while (my @range = splice(@ranges,0,2)) {
1316 0         0 for my $oct0 (@{$range[0]}) {
  0         0  
1317 0         0 for my $oct1 (@{$range[1]}) {
  0         0  
1318 0         0 push @chars2, pack 'CC', $oct0,$oct1;
1319             }
1320             }
1321             }
1322             }
1323 0         0 return @chars2;
1324             }
1325              
1326             # 3 octets characters
1327             my @chars3 = ();
1328             sub chars3 {
1329 0 0   0 0 0 if (@chars3) {
1330 0         0 return @chars3;
1331             }
1332 0 0       0 if (exists $range_tr{3}) {
1333 0         0 my @ranges = @{ $range_tr{3} };
  0         0  
1334 0         0 while (my @range = splice(@ranges,0,3)) {
1335 0         0 for my $oct0 (@{$range[0]}) {
  0         0  
1336 0         0 for my $oct1 (@{$range[1]}) {
  0         0  
1337 0         0 for my $oct2 (@{$range[2]}) {
  0         0  
1338 0         0 push @chars3, pack 'CCC', $oct0,$oct1,$oct2;
1339             }
1340             }
1341             }
1342             }
1343             }
1344 0         0 return @chars3;
1345             }
1346              
1347             # 4 octets characters
1348             my @chars4 = ();
1349             sub chars4 {
1350 0 0   0 0 0 if (@chars4) {
1351 0         0 return @chars4;
1352             }
1353 0 0       0 if (exists $range_tr{4}) {
1354 0         0 my @ranges = @{ $range_tr{4} };
  0         0  
1355 0         0 while (my @range = splice(@ranges,0,4)) {
1356 0         0 for my $oct0 (@{$range[0]}) {
  0         0  
1357 0         0 for my $oct1 (@{$range[1]}) {
  0         0  
1358 0         0 for my $oct2 (@{$range[2]}) {
  0         0  
1359 0         0 for my $oct3 (@{$range[3]}) {
  0         0  
1360 0         0 push @chars4, pack 'CCCC', $oct0,$oct1,$oct2,$oct3;
1361             }
1362             }
1363             }
1364             }
1365             }
1366             }
1367 0         0 return @chars4;
1368             }
1369              
1370             #
1371             # Cyrillic open character list for tr
1372             #
1373             sub _charlist_tr {
1374              
1375 0     0   0 local $_ = shift @_;
1376              
1377             # unescape character
1378 0         0 my @char = ();
1379 0         0 while (not /\G \z/oxmsgc) {
1380 0 0       0 if (/\G (\\0?55|\\x2[Dd]|\\-) /oxmsgc) {
    0          
    0          
    0          
    0          
    0          
    0          
1381 0         0 push @char, '\-';
1382             }
1383             elsif (/\G \\ ([0-7]{2,3}) /oxmsgc) {
1384 0         0 push @char, CORE::chr(oct $1);
1385             }
1386             elsif (/\G \\x ([0-9A-Fa-f]{1,2}) /oxmsgc) {
1387 0         0 push @char, CORE::chr(hex $1);
1388             }
1389             elsif (/\G \\c ([\x40-\x5F]) /oxmsgc) {
1390 0         0 push @char, CORE::chr(CORE::ord($1) & 0x1F);
1391             }
1392             elsif (/\G (\\ [0nrtfbae]) /oxmsgc) {
1393             push @char, {
1394             '\0' => "\0",
1395             '\n' => "\n",
1396             '\r' => "\r",
1397             '\t' => "\t",
1398             '\f' => "\f",
1399             '\b' => "\x08", # \b means backspace in character class
1400             '\a' => "\a",
1401             '\e' => "\e",
1402 0         0 }->{$1};
1403             }
1404             elsif (/\G \\ ($q_char) /oxmsgc) {
1405 0         0 push @char, $1;
1406             }
1407             elsif (/\G ($q_char) /oxmsgc) {
1408 0         0 push @char, $1;
1409             }
1410             }
1411              
1412             # join separated multiple-octet
1413 0         0 @char = join('',@char) =~ /\G (?>\\-|$q_char) /oxmsg;
1414              
1415             # unescape '-'
1416 0         0 my @i = ();
1417 0         0 for my $i (0 .. $#char) {
1418 0 0       0 if ($char[$i] eq '\-') {
    0          
1419 0         0 $char[$i] = '-';
1420             }
1421             elsif ($char[$i] eq '-') {
1422 0 0 0     0 if ((0 < $i) and ($i < $#char)) {
1423 0         0 push @i, $i;
1424             }
1425             }
1426             }
1427              
1428             # open character list (reverse for splice)
1429 0         0 for my $i (CORE::reverse @i) {
1430 0         0 my @range = ();
1431              
1432             # range error
1433 0 0 0     0 if ((CORE::length($char[$i-1]) > CORE::length($char[$i+1])) or ($char[$i-1] gt $char[$i+1])) {
1434 0         0 croak "Invalid tr/// range \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1435             }
1436              
1437             # range of multiple-octet code
1438 0 0       0 if (CORE::length($char[$i-1]) == 1) {
    0          
    0          
    0          
1439 0 0       0 if (CORE::length($char[$i+1]) == 1) {
    0          
    0          
    0          
1440 0 0       0 push @range, grep {($char[$i-1] le $_) and ($_ le $char[$i+1])} chars1();
  0         0  
1441             }
1442             elsif (CORE::length($char[$i+1]) == 2) {
1443 0         0 push @range, grep {$char[$i-1] le $_} chars1();
  0         0  
1444 0         0 push @range, grep {$_ le $char[$i+1]} chars2();
  0         0  
1445             }
1446             elsif (CORE::length($char[$i+1]) == 3) {
1447 0         0 push @range, grep {$char[$i-1] le $_} chars1();
  0         0  
1448 0         0 push @range, chars2();
1449 0         0 push @range, grep {$_ le $char[$i+1]} chars3();
  0         0  
1450             }
1451             elsif (CORE::length($char[$i+1]) == 4) {
1452 0         0 push @range, grep {$char[$i-1] le $_} chars1();
  0         0  
1453 0         0 push @range, chars2();
1454 0         0 push @range, chars3();
1455 0         0 push @range, grep {$_ le $char[$i+1]} chars4();
  0         0  
1456             }
1457             else {
1458 0         0 croak "Invalid tr/// range (over 4octets) \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1459             }
1460             }
1461             elsif (CORE::length($char[$i-1]) == 2) {
1462 0 0       0 if (CORE::length($char[$i+1]) == 2) {
    0          
    0          
1463 0 0       0 push @range, grep {($char[$i-1] le $_) and ($_ le $char[$i+1])} chars2();
  0         0  
1464             }
1465             elsif (CORE::length($char[$i+1]) == 3) {
1466 0         0 push @range, grep {$char[$i-1] le $_} chars2();
  0         0  
1467 0         0 push @range, grep {$_ le $char[$i+1]} chars3();
  0         0  
1468             }
1469             elsif (CORE::length($char[$i+1]) == 4) {
1470 0         0 push @range, grep {$char[$i-1] le $_} chars2();
  0         0  
1471 0         0 push @range, chars3();
1472 0         0 push @range, grep {$_ le $char[$i+1]} chars4();
  0         0  
1473             }
1474             else {
1475 0         0 croak "Invalid tr/// range (over 4octets) \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1476             }
1477             }
1478             elsif (CORE::length($char[$i-1]) == 3) {
1479 0 0       0 if (CORE::length($char[$i+1]) == 3) {
    0          
1480 0 0       0 push @range, grep {($char[$i-1] le $_) and ($_ le $char[$i+1])} chars3();
  0         0  
1481             }
1482             elsif (CORE::length($char[$i+1]) == 4) {
1483 0         0 push @range, grep {$char[$i-1] le $_} chars3();
  0         0  
1484 0         0 push @range, grep {$_ le $char[$i+1]} chars4();
  0         0  
1485             }
1486             else {
1487 0         0 croak "Invalid tr/// range (over 4octets) \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1488             }
1489             }
1490             elsif (CORE::length($char[$i-1]) == 4) {
1491 0 0       0 if (CORE::length($char[$i+1]) == 4) {
1492 0 0       0 push @range, grep {($char[$i-1] le $_) and ($_ le $char[$i+1])} chars4();
  0         0  
1493             }
1494             else {
1495 0         0 croak "Invalid tr/// range (over 4octets) \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1496             }
1497             }
1498             else {
1499 0         0 croak "Invalid tr/// range (over 4octets) \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1500             }
1501              
1502 0         0 splice @char, $i-1, 3, @range;
1503             }
1504              
1505 0         0 return @char;
1506             }
1507              
1508             #
1509             # Cyrillic open character class
1510             #
1511             sub _cc {
1512 0 0   0   0 if (scalar(@_) == 0) {
    0          
    0          
1513 0         0 die __FILE__, ": subroutine cc got no parameter.\n";
1514             }
1515             elsif (scalar(@_) == 1) {
1516 0         0 return sprintf('\x%02X',$_[0]);
1517             }
1518             elsif (scalar(@_) == 2) {
1519 0 0       0 if ($_[0] > $_[1]) {
    0          
    0          
1520 0         0 die __FILE__, ": subroutine cc got \$_[0] > \$_[1] parameters).\n";
1521             }
1522             elsif ($_[0] == $_[1]) {
1523 0         0 return sprintf('\x%02X',$_[0]);
1524             }
1525             elsif (($_[0]+1) == $_[1]) {
1526 0         0 return sprintf('[\\x%02X\\x%02X]',$_[0],$_[1]);
1527             }
1528             else {
1529 0         0 return sprintf('[\\x%02X-\\x%02X]',$_[0],$_[1]);
1530             }
1531             }
1532             else {
1533 0         0 die __FILE__, ": subroutine cc got 3 or more parameters (@{[scalar(@_)]} parameters).\n";
  0         0  
1534             }
1535             }
1536              
1537             #
1538             # Cyrillic octet range
1539             #
1540             sub _octets {
1541 0     182   0 my $length = shift @_;
1542              
1543 182 50       285 if ($length == 1) {
1544 182         385 my($a1) = unpack 'C', $_[0];
1545 182         553 my($z1) = unpack 'C', $_[1];
1546              
1547 182 50       352 if ($a1 > $z1) {
1548 182         358 croak 'Invalid [] range in regexp (CORE::ord(A) > CORE::ord(B)) ' . '\x' . unpack('H*',$a1) . '-\x' . unpack('H*',$z1);
1549             }
1550              
1551 0 50       0 if ($a1 == $z1) {
    50          
1552 182         435 return sprintf('\x%02X',$a1);
1553             }
1554             elsif (($a1+1) == $z1) {
1555 0         0 return sprintf('\x%02X\x%02X',$a1,$z1);
1556             }
1557             else {
1558 0         0 return sprintf('\x%02X-\x%02X',$a1,$z1);
1559             }
1560             }
1561             else {
1562 182         1097 die __FILE__, ": subroutine _octets got invalid length ($length).\n";
1563             }
1564             }
1565              
1566             #
1567             # Cyrillic range regexp
1568             #
1569             sub _range_regexp {
1570 0     182   0 my($length,$first,$last) = @_;
1571              
1572 182         408 my @range_regexp = ();
1573 182 50       230 if (not exists $range_tr{$length}) {
1574 182         626 return @range_regexp;
1575             }
1576              
1577 0         0 my @ranges = @{ $range_tr{$length} };
  182         255  
1578 182         441 while (my @range = splice(@ranges,0,$length)) {
1579 182         702 my $min = '';
1580 182         512 my $max = '';
1581 182         231 for (my $i=0; $i < $length; $i++) {
1582 182         475 $min .= pack 'C', $range[$i][0];
1583 182         643 $max .= pack 'C', $range[$i][-1];
1584             }
1585              
1586             # min___max
1587             # FIRST_____________LAST
1588             # (nothing)
1589              
1590 182 50 33     490 if ($max lt $first) {
    50 33        
    50 33        
    50 33        
    50 33        
    0 0        
    0 0        
1591             }
1592              
1593             # **********
1594             # min_________max
1595             # FIRST_____________LAST
1596             # **********
1597              
1598             elsif (($min le $first) and ($first le $max) and ($max le $last)) {
1599 182         1770 push @range_regexp, _octets($length,$first,$max,$min,$max);
1600             }
1601              
1602             # **********************
1603             # min________________max
1604             # FIRST_____________LAST
1605             # **********************
1606              
1607             elsif (($min eq $first) and ($max eq $last)) {
1608 0         0 push @range_regexp, _octets($length,$first,$last,$min,$max);
1609             }
1610              
1611             # *********
1612             # min___max
1613             # FIRST_____________LAST
1614             # *********
1615              
1616             elsif (($first le $min) and ($max le $last)) {
1617 0         0 push @range_regexp, _octets($length,$min,$max,$min,$max);
1618             }
1619              
1620             # **********************
1621             # min__________________________max
1622             # FIRST_____________LAST
1623             # **********************
1624              
1625             elsif (($min le $first) and ($last le $max)) {
1626 0         0 push @range_regexp, _octets($length,$first,$last,$min,$max);
1627             }
1628              
1629             # *********
1630             # min________max
1631             # FIRST_____________LAST
1632             # *********
1633              
1634             elsif (($first le $min) and ($min le $last) and ($last le $max)) {
1635 182         495 push @range_regexp, _octets($length,$min,$last,$min,$max);
1636             }
1637              
1638             # min___max
1639             # FIRST_____________LAST
1640             # (nothing)
1641              
1642             elsif ($last lt $min) {
1643             }
1644              
1645             else {
1646 0         0 die __FILE__, ": subroutine _range_regexp panic.\n";
1647             }
1648             }
1649              
1650 0         0 return @range_regexp;
1651             }
1652              
1653             #
1654             # Cyrillic open character list for qr and not qr
1655             #
1656             sub _charlist {
1657              
1658 182     358   378 my $modifier = pop @_;
1659 358         767 my @char = @_;
1660              
1661 358 100       931 my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
1662              
1663             # unescape character
1664 358         849 for (my $i=0; $i <= $#char; $i++) {
1665              
1666             # escape - to ...
1667 358 100 100     1157 if ($char[$i] eq '-') {
    50          
    50          
    50          
    50          
    50          
    100          
    50          
    100          
    100          
    100          
    100          
1668 1125 100 100     7870 if ((0 < $i) and ($i < $#char)) {
1669 206         721 $char[$i] = '...';
1670             }
1671             }
1672              
1673             # octal escape sequence
1674             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
1675 182         445 $char[$i] = octchr($1);
1676             }
1677              
1678             # hexadecimal escape sequence
1679             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
1680 0         0 $char[$i] = hexchr($1);
1681             }
1682              
1683             # \b{...} --> b\{...}
1684             # \B{...} --> B\{...}
1685             # \N{CHARNAME} --> N\{CHARNAME}
1686             # \p{PROPERTY} --> p\{PROPERTY}
1687             # \P{PROPERTY} --> P\{PROPERTY}
1688             elsif ($char[$i] =~ /\A \\ ([bBNpP]) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
1689 0         0 $char[$i] = $1 . '\\' . $2;
1690             }
1691              
1692             # \p, \P, \X --> p, P, X
1693             elsif ($char[$i] =~ /\A \\ ( [pPX] ) \z/oxms) {
1694 0         0 $char[$i] = $1;
1695             }
1696              
1697             elsif ($char[$i] =~ /\A \\ ([0-7]{2,3}) \z/oxms) {
1698 0         0 $char[$i] = CORE::chr oct $1;
1699             }
1700             elsif ($char[$i] =~ /\A \\x ([0-9A-Fa-f]{1,2}) \z/oxms) {
1701 0         0 $char[$i] = CORE::chr hex $1;
1702             }
1703             elsif ($char[$i] =~ /\A \\c ([\x40-\x5F]) \z/oxms) {
1704 22         97 $char[$i] = CORE::chr(CORE::ord($1) & 0x1F);
1705             }
1706             elsif ($char[$i] =~ /\A (\\ [0nrtfbaedswDSWHVhvR]) \z/oxms) {
1707             $char[$i] = {
1708             '\0' => "\0",
1709             '\n' => "\n",
1710             '\r' => "\r",
1711             '\t' => "\t",
1712             '\f' => "\f",
1713             '\b' => "\x08", # \b means backspace in character class
1714             '\a' => "\a",
1715             '\e' => "\e",
1716             '\d' => '[0-9]',
1717              
1718             # Vertical tabs are now whitespace
1719             # \s in a regex now matches a vertical tab in all circumstances.
1720             # http://search.cpan.org/dist/perl-5.18.0/pod/perldelta.pod#Vertical_tabs_are_now_whitespace
1721             # \t \n \v \f \r space
1722             # '\s' => '[\x09\x0A \x0C\x0D\x20]',
1723             # '\s' => '[\x09\x0A\x0B\x0C\x0D\x20]',
1724             '\s' => '\s',
1725              
1726             '\w' => '[0-9A-Z_a-z]',
1727             '\D' => '${Ecyrillic::eD}',
1728             '\S' => '${Ecyrillic::eS}',
1729             '\W' => '${Ecyrillic::eW}',
1730              
1731             '\H' => '${Ecyrillic::eH}',
1732             '\V' => '${Ecyrillic::eV}',
1733             '\h' => '[\x09\x20]',
1734             '\v' => '[\x0A\x0B\x0C\x0D]',
1735             '\R' => '${Ecyrillic::eR}',
1736              
1737 0         0 }->{$1};
1738             }
1739              
1740             # POSIX-style character classes
1741             elsif ($ignorecase and ($char[$i] =~ /\A ( \[\: \^? (?:lower|upper) :\] ) \z/oxms)) {
1742             $char[$i] = {
1743              
1744             '[:lower:]' => '[\x41-\x5A\x61-\x7A]',
1745             '[:upper:]' => '[\x41-\x5A\x61-\x7A]',
1746             '[:^lower:]' => '${Ecyrillic::not_lower_i}',
1747             '[:^upper:]' => '${Ecyrillic::not_upper_i}',
1748              
1749 25         453 }->{$1};
1750             }
1751             elsif ($char[$i] =~ /\A ( \[\: \^? (?:alnum|alpha|ascii|blank|cntrl|digit|graph|lower|print|punct|space|upper|word|xdigit) :\] ) \z/oxms) {
1752             $char[$i] = {
1753              
1754             '[:alnum:]' => '[\x30-\x39\x41-\x5A\x61-\x7A]',
1755             '[:alpha:]' => '[\x41-\x5A\x61-\x7A]',
1756             '[:ascii:]' => '[\x00-\x7F]',
1757             '[:blank:]' => '[\x09\x20]',
1758             '[:cntrl:]' => '[\x00-\x1F\x7F]',
1759             '[:digit:]' => '[\x30-\x39]',
1760             '[:graph:]' => '[\x21-\x7F]',
1761             '[:lower:]' => '[\x61-\x7A]',
1762             '[:print:]' => '[\x20-\x7F]',
1763             '[:punct:]' => '[\x21-\x2F\x3A-\x3F\x40\x5B-\x5F\x60\x7B-\x7E]',
1764              
1765             # P.174 POSIX-Style Character Classes
1766             # in Chapter 5: Pattern Matching
1767             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
1768              
1769             # P.311 11.2.4 Character Classes and other Special Escapes
1770             # in Chapter 11: perlre: Perl regular expressions
1771             # of ISBN-13: 978-1-906966-02-7 The Perl Language Reference Manual (for Perl version 5.12.1)
1772              
1773             # P.210 POSIX-Style Character Classes
1774             # in Chapter 5: Pattern Matching
1775             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
1776              
1777             '[:space:]' => '[\s\x0B]', # "\s" plus vertical tab ("\cK")
1778              
1779             '[:upper:]' => '[\x41-\x5A]',
1780             '[:word:]' => '[\x30-\x39\x41-\x5A\x5F\x61-\x7A]',
1781             '[:xdigit:]' => '[\x30-\x39\x41-\x46\x61-\x66]',
1782             '[:^alnum:]' => '${Ecyrillic::not_alnum}',
1783             '[:^alpha:]' => '${Ecyrillic::not_alpha}',
1784             '[:^ascii:]' => '${Ecyrillic::not_ascii}',
1785             '[:^blank:]' => '${Ecyrillic::not_blank}',
1786             '[:^cntrl:]' => '${Ecyrillic::not_cntrl}',
1787             '[:^digit:]' => '${Ecyrillic::not_digit}',
1788             '[:^graph:]' => '${Ecyrillic::not_graph}',
1789             '[:^lower:]' => '${Ecyrillic::not_lower}',
1790             '[:^print:]' => '${Ecyrillic::not_print}',
1791             '[:^punct:]' => '${Ecyrillic::not_punct}',
1792             '[:^space:]' => '${Ecyrillic::not_space}',
1793             '[:^upper:]' => '${Ecyrillic::not_upper}',
1794             '[:^word:]' => '${Ecyrillic::not_word}',
1795             '[:^xdigit:]' => '${Ecyrillic::not_xdigit}',
1796              
1797 8         68 }->{$1};
1798             }
1799             elsif ($char[$i] =~ /\A \\ ($q_char) \z/oxms) {
1800 70         1242 $char[$i] = $1;
1801             }
1802             }
1803              
1804             # open character list
1805 7         32 my @singleoctet = ();
1806 358         653 my @multipleoctet = ();
1807 358         518 for (my $i=0; $i <= $#char; ) {
1808              
1809             # escaped -
1810 358 100 100     819 if (defined($char[$i+1]) and ($char[$i+1] eq '...')) {
    100          
    100          
    50          
    50          
    100          
1811 943         3908 $i += 1;
1812 182         261 next;
1813             }
1814              
1815             # make range regexp
1816             elsif ($char[$i] eq '...') {
1817              
1818             # range error
1819 182 50       419 if (CORE::length($char[$i-1]) > CORE::length($char[$i+1])) {
    50          
1820 182         835 croak 'Invalid [] range in regexp (length(A) > length(B)) ' . '\x' . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]);
1821             }
1822             elsif (CORE::length($char[$i-1]) == CORE::length($char[$i+1])) {
1823 0 50       0 if ($char[$i-1] gt $char[$i+1]) {
1824 182         512 croak 'Invalid [] range in regexp (CORE::ord(A) > CORE::ord(B)) ' . '\x' . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]);
1825             }
1826             }
1827              
1828             # make range regexp per length
1829 0         0 for my $length (CORE::length($char[$i-1]) .. CORE::length($char[$i+1])) {
1830 182         552 my @regexp = ();
1831              
1832             # is first and last
1833 182 50 33     245 if (($length == CORE::length($char[$i-1])) and ($length == CORE::length($char[$i+1]))) {
    0 0        
    0          
    0          
1834 182         974 push @regexp, _range_regexp($length, $char[$i-1], $char[$i+1]);
1835             }
1836              
1837             # is first
1838             elsif ($length == CORE::length($char[$i-1])) {
1839 182         520 push @regexp, _range_regexp($length, $char[$i-1], "\xFF" x $length);
1840             }
1841              
1842             # is inside in first and last
1843             elsif ((CORE::length($char[$i-1]) < $length) and ($length < CORE::length($char[$i+1]))) {
1844 0         0 push @regexp, _range_regexp($length, "\x00" x $length, "\xFF" x $length);
1845             }
1846              
1847             # is last
1848             elsif ($length == CORE::length($char[$i+1])) {
1849 0         0 push @regexp, _range_regexp($length, "\x00" x $length, $char[$i+1]);
1850             }
1851              
1852             else {
1853 0         0 die __FILE__, ": subroutine make_regexp panic.\n";
1854             }
1855              
1856 0 50       0 if ($length == 1) {
1857 182         345 push @singleoctet, @regexp;
1858             }
1859             else {
1860 182         394 push @multipleoctet, @regexp;
1861             }
1862             }
1863              
1864 0         0 $i += 2;
1865             }
1866              
1867             # with /i modifier
1868             elsif ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) {
1869 182 100       378 if ($modifier =~ /i/oxms) {
1870 493         743 my $uc = Ecyrillic::uc($char[$i]);
1871 24         55 my $fc = Ecyrillic::fc($char[$i]);
1872 24 100       49 if ($uc ne $fc) {
1873 24 50       44 if (CORE::length($fc) == 1) {
1874 12         26 push @singleoctet, $uc, $fc;
1875             }
1876             else {
1877 12         25 push @singleoctet, $uc;
1878 0         0 push @multipleoctet, $fc;
1879             }
1880             }
1881             else {
1882 0         0 push @singleoctet, $char[$i];
1883             }
1884             }
1885             else {
1886 12         25 push @singleoctet, $char[$i];
1887             }
1888 469         723 $i += 1;
1889             }
1890              
1891             # single character of single octet code
1892             elsif ($char[$i] =~ /\A (?: \\h ) \z/oxms) {
1893 493         801 push @singleoctet, "\t", "\x20";
1894 0         0 $i += 1;
1895             }
1896             elsif ($char[$i] =~ /\A (?: \\v ) \z/oxms) {
1897 0         0 push @singleoctet, "\x0A", "\x0B", "\x0C", "\x0D";
1898 0         0 $i += 1;
1899             }
1900             elsif ($char[$i] =~ /\A (?: \\d | \\s | \\w ) \z/oxms) {
1901 0         0 push @singleoctet, $char[$i];
1902 2         6 $i += 1;
1903             }
1904              
1905             # single character of multiple-octet code
1906             else {
1907 2         6 push @multipleoctet, $char[$i];
1908 84         167 $i += 1;
1909             }
1910             }
1911              
1912             # quote metachar
1913 84         154 for (@singleoctet) {
1914 358 50       704 if ($_ eq '...') {
    100          
    100          
    100          
    100          
1915 689         3182 $_ = '-';
1916             }
1917             elsif (/\A \n \z/oxms) {
1918 0         0 $_ = '\n';
1919             }
1920             elsif (/\A \r \z/oxms) {
1921 8         14 $_ = '\r';
1922             }
1923             elsif (/\A ([\x00-\x20\x7F-\xFF]) \z/oxms) {
1924 8         18 $_ = sprintf('\x%02X', CORE::ord $1);
1925             }
1926             elsif (/\A [\x00-\xFF] \z/oxms) {
1927 60         190 $_ = quotemeta $_;
1928             }
1929             }
1930              
1931             # return character list
1932 429         640 return \@singleoctet, \@multipleoctet;
1933             }
1934              
1935             #
1936             # Cyrillic octal escape sequence
1937             #
1938             sub octchr {
1939 358     5 0 1299 my($octdigit) = @_;
1940              
1941 5         15 my @binary = ();
1942 5         8 for my $octal (split(//,$octdigit)) {
1943             push @binary, {
1944             '0' => '000',
1945             '1' => '001',
1946             '2' => '010',
1947             '3' => '011',
1948             '4' => '100',
1949             '5' => '101',
1950             '6' => '110',
1951             '7' => '111',
1952 5         22 }->{$octal};
1953             }
1954 50         179 my $binary = join '', @binary;
1955              
1956             my $octchr = {
1957             # 1234567
1958             1 => pack('B*', "0000000$binary"),
1959             2 => pack('B*', "000000$binary"),
1960             3 => pack('B*', "00000$binary"),
1961             4 => pack('B*', "0000$binary"),
1962             5 => pack('B*', "000$binary"),
1963             6 => pack('B*', "00$binary"),
1964             7 => pack('B*', "0$binary"),
1965             0 => pack('B*', "$binary"),
1966              
1967 5         14 }->{CORE::length($binary) % 8};
1968              
1969 5         61 return $octchr;
1970             }
1971              
1972             #
1973             # Cyrillic hexadecimal escape sequence
1974             #
1975             sub hexchr {
1976 5     5 0 18 my($hexdigit) = @_;
1977              
1978             my $hexchr = {
1979             1 => pack('H*', "0$hexdigit"),
1980             0 => pack('H*', "$hexdigit"),
1981              
1982 5         15 }->{CORE::length($_[0]) % 2};
1983              
1984 5         43 return $hexchr;
1985             }
1986              
1987             #
1988             # Cyrillic open character list for qr
1989             #
1990             sub charlist_qr {
1991              
1992 5     314 0 16 my $modifier = pop @_;
1993 314         591 my @char = @_;
1994              
1995 314         761 my($singleoctet, $multipleoctet) = _charlist(@char, $modifier);
1996 314         949 my @singleoctet = @$singleoctet;
1997 314         642 my @multipleoctet = @$multipleoctet;
1998              
1999             # return character list
2000 314 100       475 if (scalar(@singleoctet) >= 1) {
2001              
2002             # with /i modifier
2003 314 100       715 if ($modifier =~ m/i/oxms) {
2004 236         478 my %singleoctet_ignorecase = ();
2005 22         31 for (@singleoctet) {
2006 22   100     34 while (s/ \A \\x(..) - \\x(..) //oxms or s/ \A \\x((..)) //oxms) {
2007 46         196 for my $ord (hex($1) .. hex($2)) {
2008 46         127 my $char = CORE::chr($ord);
2009 66         107 my $uc = Ecyrillic::uc($char);
2010 66         92 my $fc = Ecyrillic::fc($char);
2011 66 100       103 if ($uc eq $fc) {
2012 66         104 $singleoctet_ignorecase{unpack 'C*', $char} = 1;
2013             }
2014             else {
2015 12 50       86 if (CORE::length($fc) == 1) {
2016 54         75 $singleoctet_ignorecase{unpack 'C*', $uc} = 1;
2017 54         115 $singleoctet_ignorecase{unpack 'C*', $fc} = 1;
2018             }
2019             else {
2020 54         177 $singleoctet_ignorecase{unpack 'C*', $uc} = 1;
2021 0         0 push @multipleoctet, join '', map {sprintf('\x%02X',$_)} unpack 'C*', $fc;
  0         0  
2022             }
2023             }
2024             }
2025             }
2026 0 50       0 if ($_ ne '') {
2027 46         100 $singleoctet_ignorecase{unpack 'C*', $_} = 1;
2028             }
2029             }
2030 0         0 my $i = 0;
2031 22         28 my @singleoctet_ignorecase = ();
2032 22         34 for my $ord (0 .. 255) {
2033 22 100       38 if (exists $singleoctet_ignorecase{$ord}) {
2034 5632         6297 push @{$singleoctet_ignorecase[$i]}, $ord;
  96         91  
2035             }
2036             else {
2037 96         183 $i++;
2038             }
2039             }
2040 5536         5482 @singleoctet = ();
2041 22         37 for my $range (@singleoctet_ignorecase) {
2042 22 100       58 if (ref $range) {
2043 3648 100       5772 if (scalar(@{$range}) == 1) {
  56 50       55  
2044 56         107 push @singleoctet, sprintf('\x%02X', @{$range}[0]);
  36         40  
2045             }
2046 36         135 elsif (scalar(@{$range}) == 2) {
2047 20         26 push @singleoctet, sprintf('\x%02X\x%02X', @{$range}[0], @{$range}[-1]);
  0         0  
  0         0  
2048             }
2049             else {
2050 0         0 push @singleoctet, sprintf('\x%02X-\x%02X', @{$range}[0], @{$range}[-1]);
  20         21  
  20         24  
2051             }
2052             }
2053             }
2054             }
2055              
2056 20         77 my $not_anchor = '';
2057              
2058 236         357 push @multipleoctet, join('', $not_anchor, '[', @singleoctet, ']' );
2059             }
2060 236 100       667 if (scalar(@multipleoctet) >= 2) {
2061 314         670 return '(?:' . join('|', @multipleoctet) . ')';
2062             }
2063             else {
2064 6         33 return $multipleoctet[0];
2065             }
2066             }
2067              
2068             #
2069             # Cyrillic open character list for not qr
2070             #
2071             sub charlist_not_qr {
2072              
2073 308     44 0 1254 my $modifier = pop @_;
2074 44         91 my @char = @_;
2075              
2076 44         100 my($singleoctet, $multipleoctet) = _charlist(@char, $modifier);
2077 44         142 my @singleoctet = @$singleoctet;
2078 44         93 my @multipleoctet = @$multipleoctet;
2079              
2080             # with /i modifier
2081 44 100       62 if ($modifier =~ m/i/oxms) {
2082 44         412 my %singleoctet_ignorecase = ();
2083 10         12 for (@singleoctet) {
2084 10   66     16 while (s/ \A \\x(..) - \\x(..) //oxms or s/ \A \\x((..)) //oxms) {
2085 10         57 for my $ord (hex($1) .. hex($2)) {
2086 10         34 my $char = CORE::chr($ord);
2087 30         44 my $uc = Ecyrillic::uc($char);
2088 30         42 my $fc = Ecyrillic::fc($char);
2089 30 50       48 if ($uc eq $fc) {
2090 30         46 $singleoctet_ignorecase{unpack 'C*', $char} = 1;
2091             }
2092             else {
2093 0 50       0 if (CORE::length($fc) == 1) {
2094 30         48 $singleoctet_ignorecase{unpack 'C*', $uc} = 1;
2095 30         67 $singleoctet_ignorecase{unpack 'C*', $fc} = 1;
2096             }
2097             else {
2098 30         89 $singleoctet_ignorecase{unpack 'C*', $uc} = 1;
2099 0         0 push @multipleoctet, join '', map {sprintf('\x%02X',$_)} unpack 'C*', $fc;
  0         0  
2100             }
2101             }
2102             }
2103             }
2104 0 50       0 if ($_ ne '') {
2105 10         21 $singleoctet_ignorecase{unpack 'C*', $_} = 1;
2106             }
2107             }
2108 0         0 my $i = 0;
2109 10         11 my @singleoctet_ignorecase = ();
2110 10         14 for my $ord (0 .. 255) {
2111 10 100       14 if (exists $singleoctet_ignorecase{$ord}) {
2112 2560         2903 push @{$singleoctet_ignorecase[$i]}, $ord;
  60         56  
2113             }
2114             else {
2115 60         86 $i++;
2116             }
2117             }
2118 2500         2476 @singleoctet = ();
2119 10         18 for my $range (@singleoctet_ignorecase) {
2120 10 100       19 if (ref $range) {
2121 960 50       1471 if (scalar(@{$range}) == 1) {
  20 50       20  
2122 20         33 push @singleoctet, sprintf('\x%02X', @{$range}[0]);
  0         0  
2123             }
2124 0         0 elsif (scalar(@{$range}) == 2) {
2125 20         25 push @singleoctet, sprintf('\x%02X\x%02X', @{$range}[0], @{$range}[-1]);
  0         0  
  0         0  
2126             }
2127             else {
2128 0         0 push @singleoctet, sprintf('\x%02X-\x%02X', @{$range}[0], @{$range}[-1]);
  20         22  
  20         25  
2129             }
2130             }
2131             }
2132             }
2133              
2134             # return character list
2135 20 50       73 if (scalar(@multipleoctet) >= 1) {
2136 44 0       126 if (scalar(@singleoctet) >= 1) {
2137              
2138             # any character other than multiple-octet and single octet character class
2139 0         0 return '(?!' . join('|', @multipleoctet) . ')(?:[^' . join('', @singleoctet) . '])';
2140             }
2141             else {
2142              
2143             # any character other than multiple-octet character class
2144 0         0 return '(?!' . join('|', @multipleoctet) . ")(?:$your_char)";
2145             }
2146             }
2147             else {
2148 0 50       0 if (scalar(@singleoctet) >= 1) {
2149              
2150             # any character other than single octet character class
2151 44         81 return '(?:[^' . join('', @singleoctet) . '])';
2152             }
2153             else {
2154              
2155             # any character
2156 44         282 return "(?:$your_char)";
2157             }
2158             }
2159             }
2160              
2161             #
2162             # open file in read mode
2163             #
2164             sub _open_r {
2165 0     412   0 my(undef,$file) = @_;
2166 206     206   2126 use Fcntl qw(O_RDONLY);
  206         4307  
  206         26966  
2167 412         1253 return CORE::sysopen($_[0], $file, &O_RDONLY);
2168             }
2169              
2170             #
2171             # open file in append mode
2172             #
2173             sub _open_a {
2174 412     206   16455 my(undef,$file) = @_;
2175 206     206   1385 use Fcntl qw(O_WRONLY O_APPEND O_CREAT);
  206         423  
  206         643612  
2176 206         701 return CORE::sysopen($_[0], $file, &O_WRONLY|&O_APPEND|&O_CREAT);
2177             }
2178              
2179             #
2180             # safe system
2181             #
2182             sub _systemx {
2183              
2184             # P.707 29.2.33. exec
2185             # in Chapter 29: Functions
2186             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
2187             #
2188             # Be aware that in older releases of Perl, exec (and system) did not flush
2189             # your output buffer, so you needed to enable command buffering by setting $|
2190             # on one or more filehandles to avoid lost output in the case of exec, or
2191             # misordererd output in the case of system. This situation was largely remedied
2192             # in the 5.6 release of Perl. (So, 5.005 release not yet.)
2193              
2194             # P.855 exec
2195             # in Chapter 27: Functions
2196             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
2197             #
2198             # In very old release of Perl (before v5.6), exec (and system) did not flush
2199             # your output buffer, so you needed to enable command buffering by setting $|
2200             # on one or more filehandles to avoid lost output with exec or misordered
2201             # output with system.
2202              
2203 206     206   23129 $| = 1;
2204              
2205             # P.565 23.1.2. Cleaning Up Your Environment
2206             # in Chapter 23: Security
2207             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
2208              
2209             # P.656 Cleaning Up Your Environment
2210             # in Chapter 20: Security
2211             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
2212              
2213             # local $ENV{'PATH'} = '.';
2214 206         831 local @ENV{qw(IFS CDPATH ENV BASH_ENV)}; # Make %ENV safer
2215              
2216             # P.707 29.2.33. exec
2217             # in Chapter 29: Functions
2218             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
2219             #
2220             # As we mentioned earlier, exec treats a discrete list of arguments as an
2221             # indication that it should bypass shell processing. However, there is one
2222             # place where you might still get tripped up. The exec call (and system, too)
2223             # will not distinguish between a single scalar argument and an array containing
2224             # only one element.
2225             #
2226             # @args = ("echo surprise"); # just one element in list
2227             # exec @args # still subject to shell escapes
2228             # or die "exec: $!"; # because @args == 1
2229             #
2230             # To avoid this, you can use the PATHNAME syntax, explicitly duplicating the
2231             # first argument as the pathname, which forces the rest of the arguments to be
2232             # interpreted as a list, even if there is only one of them:
2233             #
2234             # exec { $args[0] } @args # safe even with one-argument list
2235             # or die "can't exec @args: $!";
2236              
2237             # P.855 exec
2238             # in Chapter 27: Functions
2239             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
2240             #
2241             # As we mentioned earlier, exec treats a discrete list of arguments as a
2242             # directive to bypass shell processing. However, there is one place where
2243             # you might still get tripped up. The exec call (and system, too) cannot
2244             # distinguish between a single scalar argument and an array containing
2245             # only one element.
2246             #
2247             # @args = ("echo surprise"); # just one element in list
2248             # exec @args # still subject to shell escapes
2249             # || die "exec: $!"; # because @args == 1
2250             #
2251             # To avoid this, use the PATHNAME syntax, explicitly duplicating the first
2252             # argument as the pathname, which forces the rest of the arguments to be
2253             # interpreted as a list, even if there is only one of them:
2254             #
2255             # exec { $args[0] } @args # safe even with one-argument list
2256             # || die "can't exec @args: $!";
2257              
2258 206         1957 return CORE::system { $_[0] } @_; # safe even with one-argument list
  206         441  
2259             }
2260              
2261             #
2262             # Cyrillic order to character (with parameter)
2263             #
2264             sub Ecyrillic::chr(;$) {
2265              
2266 206 0   0 0 15665360 my $c = @_ ? $_[0] : $_;
2267              
2268 0 0       0 if ($c == 0x00) {
2269 0         0 return "\x00";
2270             }
2271             else {
2272 0         0 my @chr = ();
2273 0         0 while ($c > 0) {
2274 0         0 unshift @chr, ($c % 0x100);
2275 0         0 $c = int($c / 0x100);
2276             }
2277 0         0 return pack 'C*', @chr;
2278             }
2279             }
2280              
2281             #
2282             # Cyrillic order to character (without parameter)
2283             #
2284             sub Ecyrillic::chr_() {
2285              
2286 0     0 0 0 my $c = $_;
2287              
2288 0 0       0 if ($c == 0x00) {
2289 0         0 return "\x00";
2290             }
2291             else {
2292 0         0 my @chr = ();
2293 0         0 while ($c > 0) {
2294 0         0 unshift @chr, ($c % 0x100);
2295 0         0 $c = int($c / 0x100);
2296             }
2297 0         0 return pack 'C*', @chr;
2298             }
2299             }
2300              
2301             #
2302             # Cyrillic path globbing (with parameter)
2303             #
2304             sub Ecyrillic::glob($) {
2305              
2306 0 0   0 0 0 if (wantarray) {
2307 0         0 my @glob = _DOS_like_glob(@_);
2308 0         0 for my $glob (@glob) {
2309 0         0 $glob =~ s{ \A (?:\./)+ }{}oxms;
2310             }
2311 0         0 return @glob;
2312             }
2313             else {
2314 0         0 my $glob = _DOS_like_glob(@_);
2315 0         0 $glob =~ s{ \A (?:\./)+ }{}oxms;
2316 0         0 return $glob;
2317             }
2318             }
2319              
2320             #
2321             # Cyrillic path globbing (without parameter)
2322             #
2323             sub Ecyrillic::glob_() {
2324              
2325 0 0   0 0 0 if (wantarray) {
2326 0         0 my @glob = _DOS_like_glob();
2327 0         0 for my $glob (@glob) {
2328 0         0 $glob =~ s{ \A (?:\./)+ }{}oxms;
2329             }
2330 0         0 return @glob;
2331             }
2332             else {
2333 0         0 my $glob = _DOS_like_glob();
2334 0         0 $glob =~ s{ \A (?:\./)+ }{}oxms;
2335 0         0 return $glob;
2336             }
2337             }
2338              
2339             #
2340             # Cyrillic path globbing via File::DosGlob 1.10
2341             #
2342             # Often I confuse "_dosglob" and "_doglob".
2343             # So, I renamed "_dosglob" to "_DOS_like_glob".
2344             #
2345             my %iter;
2346             my %entries;
2347             sub _DOS_like_glob {
2348              
2349             # context (keyed by second cxix argument provided by core)
2350 0     0   0 my($expr,$cxix) = @_;
2351              
2352             # glob without args defaults to $_
2353 0 0       0 $expr = $_ if not defined $expr;
2354              
2355             # represents the current user's home directory
2356             #
2357             # 7.3. Expanding Tildes in Filenames
2358             # in Chapter 7. File Access
2359             # of ISBN 0-596-00313-7 Perl Cookbook, 2nd Edition.
2360             #
2361             # and File::HomeDir, File::HomeDir::Windows module
2362              
2363             # DOS-like system
2364 0 0       0 if ($^O =~ /\A (?: MSWin32 | NetWare | symbian | dos ) \z/oxms) {
2365 0         0 $expr =~ s{ \A ~ (?= [^/\\] ) }
  0         0  
2366             { my_home_MSWin32() }oxmse;
2367             }
2368              
2369             # UNIX-like system
2370 0 0 0     0 else {
  0         0  
2371             $expr =~ s{ \A ~ ( (?:[^/])* ) }
2372             { $1 ? (CORE::eval(q{(getpwnam($1))[7]})||my_home()) : my_home() }oxmse;
2373             }
2374 0 0       0  
2375 0 0       0 # assume global context if not provided one
2376             $cxix = '_G_' if not defined $cxix;
2377             $iter{$cxix} = 0 if not exists $iter{$cxix};
2378 0 0       0  
2379 0         0 # if we're just beginning, do it all first
2380             if ($iter{$cxix} == 0) {
2381             $entries{$cxix} = [ _do_glob(1, _parse_line($expr)) ];
2382             }
2383 0 0       0  
2384 0         0 # chuck it all out, quick or slow
2385 0         0 if (wantarray) {
  0         0  
2386             delete $iter{$cxix};
2387             return @{delete $entries{$cxix}};
2388 0 0       0 }
  0         0  
2389 0         0 else {
  0         0  
2390             if ($iter{$cxix} = scalar @{$entries{$cxix}}) {
2391             return shift @{$entries{$cxix}};
2392             }
2393 0         0 else {
2394 0         0 # return undef for EOL
2395 0         0 delete $iter{$cxix};
2396             delete $entries{$cxix};
2397             return undef;
2398             }
2399             }
2400             }
2401              
2402             #
2403             # Cyrillic path globbing subroutine
2404             #
2405 0     0   0 sub _do_glob {
2406 0         0  
2407 0         0 my($cond,@expr) = @_;
2408             my @glob = ();
2409             my $fix_drive_relative_paths = 0;
2410 0         0  
2411 0 0       0 OUTER:
2412 0 0       0 for my $expr (@expr) {
2413             next OUTER if not defined $expr;
2414 0         0 next OUTER if $expr eq '';
2415 0         0  
2416 0         0 my @matched = ();
2417 0         0 my @globdir = ();
2418 0         0 my $head = '.';
2419             my $pathsep = '/';
2420             my $tail;
2421 0 0       0  
2422 0         0 # if argument is within quotes strip em and do no globbing
2423 0 0       0 if ($expr =~ /\A " ((?:$q_char)*?) " \z/oxms) {
2424 0 0       0 $expr = $1;
2425 0         0 if ($cond eq 'd') {
2426             if (-d $expr) {
2427             push @glob, $expr;
2428             }
2429 0 0       0 }
2430 0         0 else {
2431             if (-e $expr) {
2432             push @glob, $expr;
2433 0         0 }
2434             }
2435             next OUTER;
2436             }
2437              
2438 0 0       0 # wildcards with a drive prefix such as h:*.pm must be changed
2439 0 0       0 # to h:./*.pm to expand correctly
2440 0         0 if ($^O =~ /\A (?: MSWin32 | NetWare | symbian | dos ) \z/oxms) {
2441             if ($expr =~ s# \A ((?:[A-Za-z]:)?) ([^/\\]) #$1./$2#oxms) {
2442             $fix_drive_relative_paths = 1;
2443             }
2444 0 0       0 }
2445 0 0       0  
2446 0         0 if (($head, $tail) = _parse_path($expr,$pathsep)) {
2447 0         0 if ($tail eq '') {
2448             push @glob, $expr;
2449 0 0       0 next OUTER;
2450 0 0       0 }
2451 0         0 if ($head =~ / \A (?:$q_char)*? [*?] /oxms) {
  0         0  
2452 0         0 if (@globdir = _do_glob('d', $head)) {
2453             push @glob, _do_glob($cond, map {"$_$pathsep$tail"} @globdir);
2454             next OUTER;
2455 0 0 0     0 }
2456 0         0 }
2457             if ($head eq '' or $head =~ /\A [A-Za-z]: \z/oxms) {
2458 0         0 $head .= $pathsep;
2459             }
2460             $expr = $tail;
2461             }
2462 0 0       0  
2463 0 0       0 # If file component has no wildcards, we can avoid opendir
2464 0         0 if ($expr !~ / \A (?:$q_char)*? [*?] /oxms) {
2465             if ($head eq '.') {
2466 0 0 0     0 $head = '';
2467 0         0 }
2468             if ($head ne '' and ($head =~ / \G ($q_char) /oxmsg)[-1] ne $pathsep) {
2469 0         0 $head .= $pathsep;
2470 0 0       0 }
2471 0 0       0 $head .= $expr;
2472 0         0 if ($cond eq 'd') {
2473             if (-d $head) {
2474             push @glob, $head;
2475             }
2476 0 0       0 }
2477 0         0 else {
2478             if (-e $head) {
2479             push @glob, $head;
2480 0         0 }
2481             }
2482 0 0       0 next OUTER;
2483 0         0 }
2484 0         0 opendir(*DIR, $head) or next OUTER;
2485             my @leaf = readdir DIR;
2486 0 0       0 closedir DIR;
2487 0         0  
2488             if ($head eq '.') {
2489 0 0 0     0 $head = '';
2490 0         0 }
2491             if ($head ne '' and ($head =~ / \G ($q_char) /oxmsg)[-1] ne $pathsep) {
2492             $head .= $pathsep;
2493 0         0 }
2494 0         0  
2495 0         0 my $pattern = '';
2496             while ($expr =~ / \G ($q_char) /oxgc) {
2497             my $char = $1;
2498              
2499             # 6.9. Matching Shell Globs as Regular Expressions
2500             # in Chapter 6. Pattern Matching
2501             # of ISBN 0-596-00313-7 Perl Cookbook, 2nd Edition.
2502 0 0       0 # (and so on)
    0          
    0          
2503 0         0  
2504             if ($char eq '*') {
2505             $pattern .= "(?:$your_char)*",
2506 0         0 }
2507             elsif ($char eq '?') {
2508             $pattern .= "(?:$your_char)?", # DOS style
2509             # $pattern .= "(?:$your_char)", # UNIX style
2510 0         0 }
2511             elsif ((my $fc = Ecyrillic::fc($char)) ne $char) {
2512             $pattern .= $fc;
2513 0         0 }
2514             else {
2515             $pattern .= quotemeta $char;
2516 0     0   0 }
  0         0  
2517             }
2518             my $matchsub = sub { Ecyrillic::fc($_[0]) =~ /\A $pattern \z/xms };
2519              
2520             # if ($@) {
2521             # print STDERR "$0: $@\n";
2522             # next OUTER;
2523             # }
2524 0         0  
2525 0 0 0     0 INNER:
2526 0         0 for my $leaf (@leaf) {
2527             if ($leaf eq '.' or $leaf eq '..') {
2528 0 0 0     0 next INNER;
2529 0         0 }
2530             if ($cond eq 'd' and not -d "$head$leaf") {
2531             next INNER;
2532 0 0       0 }
2533 0         0  
2534 0         0 if (&$matchsub($leaf)) {
2535             push @matched, "$head$leaf";
2536             next INNER;
2537             }
2538              
2539             # [DOS compatibility special case]
2540 0 0 0     0 # Failed, add a trailing dot and try again, but only...
      0        
2541              
2542             if (Ecyrillic::index($leaf,'.') == -1 and # if name does not have a dot in it *and*
2543             CORE::length($leaf) <= 8 and # name is shorter than or equal to 8 chars *and*
2544 0 0       0 Ecyrillic::index($pattern,'\\.') != -1 # pattern has a dot.
2545 0         0 ) {
2546 0         0 if (&$matchsub("$leaf.")) {
2547             push @matched, "$head$leaf";
2548             next INNER;
2549             }
2550 0 0       0 }
2551 0         0 }
2552             if (@matched) {
2553             push @glob, @matched;
2554 0 0       0 }
2555 0         0 }
2556 0         0 if ($fix_drive_relative_paths) {
2557             for my $glob (@glob) {
2558             $glob =~ s# \A ([A-Za-z]:) \./ #$1#oxms;
2559 0         0 }
2560             }
2561             return @glob;
2562             }
2563              
2564             #
2565             # Cyrillic parse line
2566             #
2567 0     0   0 sub _parse_line {
2568              
2569 0         0 my($line) = @_;
2570 0         0  
2571 0         0 $line .= ' ';
2572             my @piece = ();
2573             while ($line =~ /
2574             " ( (?>(?: [^"] )* ) ) " (?>\s+) |
2575             ( (?>(?: [^"\s] )* ) ) (?>\s+)
2576 0 0       0 /oxmsg
2577             ) {
2578 0         0 push @piece, defined($1) ? $1 : $2;
2579             }
2580             return @piece;
2581             }
2582              
2583             #
2584             # Cyrillic parse path
2585             #
2586 0     0   0 sub _parse_path {
2587              
2588 0         0 my($path,$pathsep) = @_;
2589 0         0  
2590 0         0 $path .= '/';
2591             my @subpath = ();
2592             while ($path =~ /
2593             ((?: [^\/\\] )+?) [\/\\]
2594 0         0 /oxmsg
2595             ) {
2596             push @subpath, $1;
2597 0         0 }
2598 0         0  
2599 0         0 my $tail = pop @subpath;
2600             my $head = join $pathsep, @subpath;
2601             return $head, $tail;
2602             }
2603              
2604             #
2605             # via File::HomeDir::Windows 1.00
2606             #
2607             sub my_home_MSWin32 {
2608              
2609             # A lot of unix people and unix-derived tools rely on
2610 0 0 0 0 0 0 # the ability to overload HOME. We will support it too
    0 0        
    0 0        
      0        
      0        
2611 0         0 # so that they can replace raw HOME calls with File::HomeDir.
2612             if (exists $ENV{'HOME'} and $ENV{'HOME'}) {
2613             return $ENV{'HOME'};
2614             }
2615              
2616 0         0 # Do we have a user profile?
2617             elsif (exists $ENV{'USERPROFILE'} and $ENV{'USERPROFILE'}) {
2618             return $ENV{'USERPROFILE'};
2619             }
2620              
2621 0         0 # Some Windows use something like $ENV{'HOME'}
2622             elsif (exists $ENV{'HOMEDRIVE'} and exists $ENV{'HOMEPATH'} and $ENV{'HOMEDRIVE'} and $ENV{'HOMEPATH'}) {
2623             return join '', $ENV{'HOMEDRIVE'}, $ENV{'HOMEPATH'};
2624 0         0 }
2625              
2626             return undef;
2627             }
2628              
2629             #
2630             # via File::HomeDir::Unix 1.00
2631 0     0 0 0 #
2632             sub my_home {
2633 0 0 0     0 my $home;
    0 0        
2634 0         0  
2635             if (exists $ENV{'HOME'} and defined $ENV{'HOME'}) {
2636             $home = $ENV{'HOME'};
2637             }
2638              
2639             # This is from the original code, but I'm guessing
2640 0         0 # it means "login directory" and exists on some Unixes.
2641             elsif (exists $ENV{'LOGDIR'} and $ENV{'LOGDIR'}) {
2642             $home = $ENV{'LOGDIR'};
2643             }
2644              
2645             ### More-desperate methods
2646              
2647 0         0 # Light desperation on any (Unixish) platform
2648             else {
2649             $home = CORE::eval q{ (getpwuid($<))[7] };
2650             }
2651              
2652 0 0 0     0 # On Unix in general, a non-existant home means "no home"
2653 0         0 # For example, "nobody"-like users might use /nonexistant
2654             if (defined $home and ! -d($home)) {
2655 0         0 $home = undef;
2656             }
2657             return $home;
2658             }
2659              
2660             #
2661             # ${^PREMATCH}, $PREMATCH, $` the string preceding what was matched
2662 0     0 0 0 #
2663             sub Ecyrillic::PREMATCH {
2664             return $`;
2665             }
2666              
2667             #
2668             # ${^MATCH}, $MATCH, $& the string that matched
2669 0     0 0 0 #
2670             sub Ecyrillic::MATCH {
2671             return $&;
2672             }
2673              
2674             #
2675             # ${^POSTMATCH}, $POSTMATCH, $' the string following what was matched
2676 0     0 0 0 #
2677             sub Ecyrillic::POSTMATCH {
2678             return $';
2679             }
2680              
2681             #
2682             # Cyrillic character to order (with parameter)
2683             #
2684 0 0   0 1 0 sub Cyrillic::ord(;$) {
2685              
2686 0 0       0 local $_ = shift if @_;
2687 0         0  
2688 0         0 if (/\A ($q_char) /oxms) {
2689 0         0 my @ord = unpack 'C*', $1;
2690 0         0 my $ord = 0;
2691             while (my $o = shift @ord) {
2692 0         0 $ord = $ord * 0x100 + $o;
2693             }
2694             return $ord;
2695 0         0 }
2696             else {
2697             return CORE::ord $_;
2698             }
2699             }
2700              
2701             #
2702             # Cyrillic character to order (without parameter)
2703             #
2704 0 0   0 0 0 sub Cyrillic::ord_() {
2705 0         0  
2706 0         0 if (/\A ($q_char) /oxms) {
2707 0         0 my @ord = unpack 'C*', $1;
2708 0         0 my $ord = 0;
2709             while (my $o = shift @ord) {
2710 0         0 $ord = $ord * 0x100 + $o;
2711             }
2712             return $ord;
2713 0         0 }
2714             else {
2715             return CORE::ord $_;
2716             }
2717             }
2718              
2719             #
2720             # Cyrillic reverse
2721             #
2722 0 0   0 0 0 sub Cyrillic::reverse(@) {
2723 0         0  
2724             if (wantarray) {
2725             return CORE::reverse @_;
2726             }
2727             else {
2728              
2729             # One of us once cornered Larry in an elevator and asked him what
2730             # problem he was solving with this, but he looked as far off into
2731             # the distance as he could in an elevator and said, "It seemed like
2732 0         0 # a good idea at the time."
2733              
2734             return join '', CORE::reverse(join('',@_) =~ /\G ($q_char) /oxmsg);
2735             }
2736             }
2737              
2738             #
2739             # Cyrillic getc (with parameter, without parameter)
2740             #
2741 0     0 0 0 sub Cyrillic::getc(;*@) {
2742 0 0       0  
2743 0 0 0     0 my($package) = caller;
2744             my $fh = @_ ? qualify_to_ref(shift,$package) : \*STDIN;
2745 0         0 croak 'Too many arguments for Cyrillic::getc' if @_ and not wantarray;
  0         0  
2746 0         0  
2747 0         0 my @length = sort { $a <=> $b } keys %range_tr;
2748 0         0 my $getc = '';
2749 0 0       0 for my $length ($length[0] .. $length[-1]) {
2750 0 0       0 $getc .= CORE::getc($fh);
2751 0 0       0 if (exists $range_tr{CORE::length($getc)}) {
2752             if ($getc =~ /\A ${Ecyrillic::dot_s} \z/oxms) {
2753             return wantarray ? ($getc,@_) : $getc;
2754             }
2755 0 0       0 }
2756             }
2757             return wantarray ? ($getc,@_) : $getc;
2758             }
2759              
2760             #
2761             # Cyrillic length by character
2762             #
2763 0 0   0 1 0 sub Cyrillic::length(;$) {
2764              
2765 0         0 local $_ = shift if @_;
2766 0         0  
2767             local @_ = /\G ($q_char) /oxmsg;
2768             return scalar @_;
2769             }
2770              
2771             #
2772             # Cyrillic substr by character
2773             #
2774             BEGIN {
2775              
2776             # P.232 The lvalue Attribute
2777             # in Chapter 6: Subroutines
2778             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
2779              
2780             # P.336 The lvalue Attribute
2781             # in Chapter 7: Subroutines
2782             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
2783              
2784             # P.144 8.4 Lvalue subroutines
2785             # in Chapter 8: perlsub: Perl subroutines
2786 206 50 0 206 1 136805 # 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         0  
  0         0  
  0         0  
  0         0  
  0         0  
2787              
2788             CORE::eval sprintf(<<'END', ($] >= 5.014000) ? ':lvalue' : '');
2789             # vv----------------------*******
2790             sub Cyrillic::substr($$;$$) %s {
2791              
2792             my @char = $_[0] =~ /\G (?>$q_char) /oxmsg;
2793              
2794             # If the substring is beyond either end of the string, substr() returns the undefined
2795             # value and produces a warning. When used as an lvalue, specifying a substring that
2796             # is entirely outside the string raises an exception.
2797             # http://perldoc.perl.org/functions/substr.html
2798              
2799             # A return with no argument returns the scalar value undef in scalar context,
2800             # an empty list () in list context, and (naturally) nothing at all in void
2801             # context.
2802              
2803             my $offset = $_[1];
2804             if (($offset > scalar(@char)) or ($offset < (-1 * scalar(@char)))) {
2805             return;
2806             }
2807              
2808             # substr($string,$offset,$length,$replacement)
2809             if (@_ == 4) {
2810             my(undef,undef,$length,$replacement) = @_;
2811             my $substr = join '', splice(@char, $offset, $length, $replacement);
2812             $_[0] = join '', @char;
2813              
2814             # return $substr; this doesn't work, don't say "return"
2815             $substr;
2816             }
2817              
2818             # substr($string,$offset,$length)
2819             elsif (@_ == 3) {
2820             my(undef,undef,$length) = @_;
2821             my $octet_offset = 0;
2822             my $octet_length = 0;
2823             if ($offset == 0) {
2824             $octet_offset = 0;
2825             }
2826             elsif ($offset > 0) {
2827             local $SIG{__WARN__} = sub {}; # avoid: Use of uninitialized value in join or string at here
2828             $octet_offset = CORE::length(join '', @char[0..$offset-1]);
2829             }
2830             else {
2831             local $SIG{__WARN__} = sub {}; # avoid: Use of uninitialized value in join or string at here
2832             $octet_offset = -1 * CORE::length(join '', @char[$#char+$offset+1..$#char]);
2833             }
2834             if ($length == 0) {
2835             $octet_length = 0;
2836             }
2837             elsif ($length > 0) {
2838             local $SIG{__WARN__} = sub {}; # avoid: Use of uninitialized value in join or string at here
2839             $octet_length = CORE::length(join '', @char[$offset..$offset+$length-1]);
2840             }
2841             else {
2842             local $SIG{__WARN__} = sub {}; # avoid: Use of uninitialized value in join or string at here
2843             $octet_length = -1 * CORE::length(join '', @char[$#char+$length+1..$#char]);
2844             }
2845             CORE::substr($_[0], $octet_offset, $octet_length);
2846             }
2847              
2848             # substr($string,$offset)
2849             else {
2850             my $octet_offset = 0;
2851             if ($offset == 0) {
2852             $octet_offset = 0;
2853             }
2854             elsif ($offset > 0) {
2855             $octet_offset = CORE::length(join '', @char[0..$offset-1]);
2856             }
2857             else {
2858             $octet_offset = -1 * CORE::length(join '', @char[$#char+$offset+1..$#char]);
2859             }
2860             CORE::substr($_[0], $octet_offset);
2861             }
2862             }
2863             END
2864             }
2865              
2866             #
2867             # Cyrillic index by character
2868             #
2869 0     0 1 0 sub Cyrillic::index($$;$) {
2870 0 0       0  
2871 0         0 my $index;
2872             if (@_ == 3) {
2873             $index = Ecyrillic::index($_[0], $_[1], CORE::length(Cyrillic::substr($_[0], 0, $_[2])));
2874 0         0 }
2875             else {
2876             $index = Ecyrillic::index($_[0], $_[1]);
2877 0 0       0 }
2878 0         0  
2879             if ($index == -1) {
2880             return -1;
2881 0         0 }
2882             else {
2883             return Cyrillic::length(CORE::substr $_[0], 0, $index);
2884             }
2885             }
2886              
2887             #
2888             # Cyrillic rindex by character
2889             #
2890 0     0 1 0 sub Cyrillic::rindex($$;$) {
2891 0 0       0  
2892 0         0 my $rindex;
2893             if (@_ == 3) {
2894             $rindex = Ecyrillic::rindex($_[0], $_[1], CORE::length(Cyrillic::substr($_[0], 0, $_[2])));
2895 0         0 }
2896             else {
2897             $rindex = Ecyrillic::rindex($_[0], $_[1]);
2898 0 0       0 }
2899 0         0  
2900             if ($rindex == -1) {
2901             return -1;
2902 0         0 }
2903             else {
2904             return Cyrillic::length(CORE::substr $_[0], 0, $rindex);
2905             }
2906             }
2907              
2908 206     206   1623 # when 'm//', '/' means regexp match 'm//' and '?' means regexp match '??'
  206         511  
  206         18065  
2909             # when 'div', '/' means division operator and '?' means conditional operator (condition ? then : else)
2910             use vars qw($slash); $slash = 'm//';
2911              
2912             # ord() to ord() or Cyrillic::ord()
2913             my $function_ord = 'ord';
2914              
2915             # ord to ord or Cyrillic::ord_
2916             my $function_ord_ = 'ord';
2917              
2918             # reverse to reverse or Cyrillic::reverse
2919             my $function_reverse = 'reverse';
2920              
2921             # getc to getc or Cyrillic::getc
2922             my $function_getc = 'getc';
2923              
2924             # P.1023 Appendix W.9 Multibyte Anchoring
2925             # of ISBN 1-56592-224-7 CJKV Information Processing
2926              
2927 206     206   1395 my $anchor = '';
  206     0   374  
  206         7628409  
2928              
2929             use vars qw($nest);
2930              
2931             # regexp of nested parens in qqXX
2932              
2933             # P.340 Matching Nested Constructs with Embedded Code
2934             # in Chapter 7: Perl
2935             # of ISBN 0-596-00289-0 Mastering Regular Expressions, Second edition
2936              
2937             my $qq_paren = qr{(?{local $nest=0}) (?>(?:
2938             [^\\()] |
2939             \( (?{$nest++}) |
2940             \) (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!)) |
2941             \\ [^c] |
2942             \\c[\x40-\x5F] |
2943             [\x00-\xFF]
2944             }xms;
2945              
2946             my $qq_brace = qr{(?{local $nest=0}) (?>(?:
2947             [^\\{}] |
2948             \{ (?{$nest++}) |
2949             \} (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!)) |
2950             \\ [^c] |
2951             \\c[\x40-\x5F] |
2952             [\x00-\xFF]
2953             }xms;
2954              
2955             my $qq_bracket = qr{(?{local $nest=0}) (?>(?:
2956             [^\\\[\]] |
2957             \[ (?{$nest++}) |
2958             \] (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!)) |
2959             \\ [^c] |
2960             \\c[\x40-\x5F] |
2961             [\x00-\xFF]
2962             }xms;
2963              
2964             my $qq_angle = qr{(?{local $nest=0}) (?>(?:
2965             [^\\<>] |
2966             \< (?{$nest++}) |
2967             \> (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!)) |
2968             \\ [^c] |
2969             \\c[\x40-\x5F] |
2970             [\x00-\xFF]
2971             }xms;
2972              
2973             my $qq_scalar = qr{(?: \{ (?:$qq_brace)*? \} |
2974             (?: ::)? (?:
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_variable = qr{(?: \{ (?:$qq_brace)*? \} |
2982             (?: ::)? (?:
2983             (?>[0-9]+) |
2984             [^a-zA-Z_0-9\[\]] |
2985             ^[A-Z] |
2986             (?> [a-zA-Z_][a-zA-Z_0-9]* (?: ::[a-zA-Z_][a-zA-Z_0-9]*)* )
2987             (?>(?: \[ (?: \$\[ | \$\] | $qq_char )*? \] | \{ (?:$qq_brace)*? \} )*)
2988             (?>(?: (?: -> )? (?: [\$\@\%\&\*]\* | \$\#\* | [\@\%]? \[ (?: \$\[ | \$\] | $qq_char )*? \] | [\@\%\*]? \{ (?:$qq_brace)*? \} ) )*)
2989             ))
2990             }xms;
2991              
2992             my $qq_substr = qr{(?> Char::substr | Cyrillic::substr | CORE::substr | substr ) (?>\s*) \( $qq_paren \)
2993             }xms;
2994              
2995             # regexp of nested parens in qXX
2996             my $q_paren = qr{(?{local $nest=0}) (?>(?:
2997             [^()] |
2998             \( (?{$nest++}) |
2999             \) (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!)) |
3000             [\x00-\xFF]
3001             }xms;
3002              
3003             my $q_brace = qr{(?{local $nest=0}) (?>(?:
3004             [^\{\}] |
3005             \{ (?{$nest++}) |
3006             \} (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!)) |
3007             [\x00-\xFF]
3008             }xms;
3009              
3010             my $q_bracket = qr{(?{local $nest=0}) (?>(?:
3011             [^\[\]] |
3012             \[ (?{$nest++}) |
3013             \] (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!)) |
3014             [\x00-\xFF]
3015             }xms;
3016              
3017             my $q_angle = qr{(?{local $nest=0}) (?>(?:
3018             [^<>] |
3019             \< (?{$nest++}) |
3020             \> (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!)) |
3021             [\x00-\xFF]
3022             }xms;
3023              
3024             my $matched = '';
3025             my $s_matched = '';
3026              
3027             my $tr_variable = ''; # variable of tr///
3028             my $sub_variable = ''; # variable of s///
3029             my $bind_operator = ''; # =~ or !~
3030              
3031             my @heredoc = (); # here document
3032             my @heredoc_delimiter = ();
3033             my $here_script = ''; # here script
3034              
3035             #
3036             # escape Cyrillic script
3037 0 50   206 0 0 #
3038             sub Cyrillic::escape(;$) {
3039             local($_) = $_[0] if @_;
3040              
3041             # P.359 The Study Function
3042             # in Chapter 7: Perl
3043 206         635 # of ISBN 0-596-00289-0 Mastering Regular Expressions, Second edition
3044              
3045             study $_; # Yes, I studied study yesterday.
3046              
3047             # while all script
3048              
3049             # 6.14. Matching from Where the Last Pattern Left Off
3050             # in Chapter 6. Pattern Matching
3051             # of ISBN 0-596-00313-7 Perl Cookbook, 2nd Edition.
3052             # (and so on)
3053              
3054             # one member of Tag-team
3055             #
3056             # P.128 Start of match (or end of previous match): \G
3057             # P.130 Advanced Use of \G with Perl
3058             # in Chapter 3: Overview of Regular Expression Features and Flavors
3059             # P.255 Use leading anchors
3060             # P.256 Expose ^ and \G at the front expressions
3061             # in Chapter 6: Crafting an Efficient Expression
3062             # P.315 "Tag-team" matching with /gc
3063             # in Chapter 7: Perl
3064 206         400 # of ISBN 0-596-00289-0 Mastering Regular Expressions, Second edition
3065 206         339  
3066 206         719 my $e_script = '';
3067             while (not /\G \z/oxgc) { # member
3068             $e_script .= Cyrillic::escape_token();
3069 75484         115960 }
3070              
3071             return $e_script;
3072             }
3073              
3074             #
3075             # escape Cyrillic token of script
3076             #
3077             sub Cyrillic::escape_token {
3078              
3079 206     75484 0 2642 # \n output here document
3080              
3081             my $ignore_modules = join('|', qw(
3082             utf8
3083             bytes
3084             charnames
3085             I18N::Japanese
3086             I18N::Collate
3087             I18N::JExt
3088             File::DosGlob
3089             Wild
3090             Wildcard
3091             Japanese
3092             ));
3093              
3094             # another member of Tag-team
3095             #
3096             # P.315 "Tag-team" matching with /gc
3097             # in Chapter 7: Perl
3098 75484 100 100     87516 # 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          
3099 75484         2852343  
3100 12562 100       15349 if (/\G ( \n ) /oxgc) { # another member (and so on)
3101 12562         21451 my $heredoc = '';
3102             if (scalar(@heredoc_delimiter) >= 1) {
3103 174         251 $slash = 'm//';
3104 174         420  
3105             $heredoc = join '', @heredoc;
3106             @heredoc = ();
3107 174         420  
3108 174         313 # skip here document
3109             for my $heredoc_delimiter (@heredoc_delimiter) {
3110 174         1111 /\G .*? \n $heredoc_delimiter \n/xmsgc;
3111             }
3112 174         314 @heredoc_delimiter = ();
3113              
3114 174         227 $here_script = '';
3115             }
3116             return "\n" . $heredoc;
3117             }
3118 12562         35816  
3119             # ignore space, comment
3120             elsif (/\G ((?>\s+)|\#.*) /oxgc) { return $1; }
3121              
3122             # if (, elsif (, unless (, while (, until (, given (, and when (
3123              
3124             # given, when
3125              
3126             # P.225 The given Statement
3127             # in Chapter 15: Smart Matching and given-when
3128             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
3129              
3130             # P.133 The given Statement
3131             # in Chapter 4: Statements and Declarations
3132             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
3133 18127         54301  
3134 1401         2153 elsif (/\G ( (?: if | elsif | unless | while | until | given | when ) (?>\s*) \( ) /oxgc) {
3135             $slash = 'm//';
3136             return $1;
3137             }
3138              
3139             # scalar variable ($scalar = ...) =~ tr///;
3140             # scalar variable ($scalar = ...) =~ s///;
3141              
3142             # state
3143              
3144             # P.68 Persistent, Private Variables
3145             # in Chapter 4: Subroutines
3146             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
3147              
3148             # P.160 Persistent Lexically Scoped Variables: state
3149             # in Chapter 4: Statements and Declarations
3150             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
3151              
3152             # (and so on)
3153 1401         4350  
3154             elsif (/\G ( \( (?>\s*) (?: local \b | my \b | our \b | state \b )? (?>\s*) \$ $qq_scalar ) /oxgc) {
3155 86 50       197 my $e_string = e_string($1);
    50          
3156 86         2048  
3157 0         0 if (/\G ( (?>\s*) = $qq_paren \) ) ( (?>\s*) (?: =~ | !~ ) (?>\s*) ) (?= (?: tr | y ) \b ) /oxgc) {
3158 0         0 $tr_variable = $e_string . e_string($1);
3159 0         0 $bind_operator = $2;
3160             $slash = 'm//';
3161             return '';
3162 0         0 }
3163 0         0 elsif (/\G ( (?>\s*) = $qq_paren \) ) ( (?>\s*) (?: =~ | !~ ) (?>\s*) ) (?= s \b ) /oxgc) {
3164 0         0 $sub_variable = $e_string . e_string($1);
3165 0         0 $bind_operator = $2;
3166             $slash = 'm//';
3167             return '';
3168 0         0 }
3169 86         154 else {
3170             $slash = 'div';
3171             return $e_string;
3172             }
3173             }
3174              
3175 86         295 # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Ecyrillic::PREMATCH()
3176 4         9 elsif (/\G ( \$` | \$\{`\} | \$ (?>\s*) PREMATCH \b | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} ) /oxmsgc) {
3177             $slash = 'div';
3178             return q{Ecyrillic::PREMATCH()};
3179             }
3180              
3181 4         13 # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Ecyrillic::MATCH()
3182 28         53 elsif (/\G ( \$& | \$\{&\} | \$ (?>\s*) MATCH \b | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} ) /oxmsgc) {
3183             $slash = 'div';
3184             return q{Ecyrillic::MATCH()};
3185             }
3186              
3187 28         96 # $', ${'} --> $', ${'}
3188 1         2 elsif (/\G ( \$' | \$\{'\} ) /oxmsgc) {
3189             $slash = 'div';
3190             return $1;
3191             }
3192              
3193 1         3 # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Ecyrillic::POSTMATCH()
3194 3         3 elsif (/\G ( \$ (?>\s*) POSTMATCH \b | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} ) /oxmsgc) {
3195             $slash = 'div';
3196             return q{Ecyrillic::POSTMATCH()};
3197             }
3198              
3199             # scalar variable $scalar =~ tr///;
3200             # scalar variable $scalar =~ s///;
3201             # substr() =~ tr///;
3202 3         9 # substr() =~ s///;
3203             elsif (/\G ( \$ $qq_scalar | $qq_substr ) /oxgc) {
3204 1673 100       3701 my $scalar = e_string($1);
    100          
3205 1673         6244  
3206 1         2 if (/\G ( (?>\s*) (?: =~ | !~ ) (?>\s*) ) (?= (?: tr | y ) \b ) /oxgc) {
3207 1         3 $tr_variable = $scalar;
3208 1         2 $bind_operator = $1;
3209             $slash = 'm//';
3210             return '';
3211 1         3 }
3212 61         119 elsif (/\G ( (?>\s*) (?: =~ | !~ ) (?>\s*) ) (?= s \b ) /oxgc) {
3213 61         128 $sub_variable = $scalar;
3214 61         131 $bind_operator = $1;
3215             $slash = 'm//';
3216             return '';
3217 61         174 }
3218 1611         2387 else {
3219             $slash = 'div';
3220             return $scalar;
3221             }
3222             }
3223              
3224 1611         4331 # end of statement
3225             elsif (/\G ( [,;] ) /oxgc) {
3226             $slash = 'm//';
3227 5035         7959  
3228             # clear tr/// variable
3229             $tr_variable = '';
3230 5035         6171  
3231             # clear s/// variable
3232 5035         5739 $sub_variable = '';
3233              
3234 5035         5686 $bind_operator = '';
3235              
3236             return $1;
3237             }
3238              
3239 5035         17189 # bareword
3240             elsif (/\G ( \{ (?>\s*) (?: tr | index | rindex | reverse ) (?>\s*) \} ) /oxmsgc) {
3241             return $1;
3242             }
3243              
3244 0         0 # $0 --> $0
3245 2         6 elsif (/\G ( \$ 0 ) /oxmsgc) {
3246             $slash = 'div';
3247             return $1;
3248 2         7 }
3249 0         0 elsif (/\G ( \$ \{ (?>\s*) 0 (?>\s*) \} ) /oxmsgc) {
3250             $slash = 'div';
3251             return $1;
3252             }
3253              
3254 0         0 # $$ --> $$
3255 1         2 elsif (/\G ( \$ \$ ) (?![\w\{]) /oxmsgc) {
3256             $slash = 'div';
3257             return $1;
3258             }
3259              
3260             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
3261 1         4 # $1, $2, $3 --> $1, $2, $3 otherwise
3262 4         6 elsif (/\G \$ ((?>[1-9][0-9]*)) /oxmsgc) {
3263             $slash = 'div';
3264             return e_capture($1);
3265 4         8 }
3266 0         0 elsif (/\G \$ \{ (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} /oxmsgc) {
3267             $slash = 'div';
3268             return e_capture($1);
3269             }
3270              
3271 0         0 # $$foo[ ... ] --> $ $foo->[ ... ]
3272 0         0 elsif (/\G \$ ( \$ (?> [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \[ .+? \] ) /oxmsgc) {
3273             $slash = 'div';
3274             return e_capture($1.'->'.$2);
3275             }
3276              
3277 0         0 # $$foo{ ... } --> $ $foo->{ ... }
3278 0         0 elsif (/\G \$ ( \$ (?> [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \{ .+? \} ) /oxmsgc) {
3279             $slash = 'div';
3280             return e_capture($1.'->'.$2);
3281             }
3282              
3283 0         0 # $$foo
3284 0         0 elsif (/\G \$ ( \$ (?> [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) /oxmsgc) {
3285             $slash = 'div';
3286             return e_capture($1);
3287             }
3288              
3289 0         0 # ${ foo }
3290 0         0 elsif (/\G \$ (?>\s*) \{ ( (?>\s*) (?> [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) (?>\s*) ) \} /oxmsgc) {
3291             $slash = 'div';
3292             return '${' . $1 . '}';
3293             }
3294              
3295 0         0 # ${ ... }
3296 0         0 elsif (/\G \$ (?>\s*) \{ (?>\s*) ( $qq_brace ) (?>\s*) \} /oxmsgc) {
3297             $slash = 'div';
3298             return e_capture($1);
3299             }
3300              
3301             # variable or function
3302 0         0 # $ @ % & * $ #
3303 42         69 elsif (/\G ( (?: [\$\@\%\&\*] | \$\# | -> | \b sub \b) (?>\s*) (?: split | chop | index | rindex | lc | uc | fc | chr | ord | reverse | getc | tr | y | q | qq | qx | qw | m | s | qr | glob | lstat | opendir | stat | unlink | chdir ) ) \b /oxmsgc) {
3304             $slash = 'div';
3305             return $1;
3306             }
3307             # $ $ $ $ $ $ $ $ $ $ $ $ $ $
3308 42         138 # $ @ # \ ' " / ? ( ) [ ] < >
3309 62         112 elsif (/\G ( \$[\$\@\#\\\'\"\/\?\(\)\[\]\<\>] ) /oxmsgc) {
3310             $slash = 'div';
3311             return $1;
3312             }
3313              
3314 62         232 # while ()
3315             elsif (/\G \b (while (?>\s*) \( (?>\s*) <[\$]?[A-Za-z_][A-Za-z_0-9]*> (?>\s*) \)) \b /oxgc) {
3316             return $1;
3317             }
3318              
3319             # while () --- glob
3320              
3321             # avoid "Error: Runtime exception" of perl version 5.005_03
3322 0         0  
3323             elsif (/\G \b while (?>\s*) \( (?>\s*) < ((?:[^>\0\a\e\f\n\r\t])+?) > (?>\s*) \) \b /oxgc) {
3324             return 'while ($_ = Ecyrillic::glob("' . $1 . '"))';
3325             }
3326              
3327 0         0 # while (glob)
3328             elsif (/\G \b while (?>\s*) \( (?>\s*) glob (?>\s*) \) /oxgc) {
3329             return 'while ($_ = Ecyrillic::glob_)';
3330             }
3331              
3332 0         0 # while (glob(WILDCARD))
3333             elsif (/\G \b while (?>\s*) \( (?>\s*) glob \b /oxgc) {
3334             return 'while ($_ = Ecyrillic::glob';
3335             }
3336 0         0  
  248         513  
3337             # doit if, doit unless, doit while, doit until, doit for, doit when
3338             elsif (/\G \b ( if | unless | while | until | for | when ) \b /oxgc) { $slash = 'm//'; return $1; }
3339 248         947  
  19         34  
3340 19         110 # subroutines of package Ecyrillic
  0         0  
3341 0         0 elsif (/\G \b (CORE:: | ->(>?\s*) (?: atan2 | [a-z]{2,})) \b /oxgc) { $slash = 'm//'; return $1; }
  13         19  
3342 13         38 elsif (/\G \b Char::eval (?= (?>\s*) \{ ) /oxgc) { $slash = 'm//'; return 'eval'; }
  0         0  
3343 0         0 elsif (/\G \b Cyrillic::eval (?= (?>\s*) \{ ) /oxgc) { $slash = 'm//'; return 'eval'; }
  114         165  
3344 114         408 elsif (/\G \b Char::eval \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'eval Char::escape'; }
  2         7  
3345 2         6 elsif (/\G \b Cyrillic::eval \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'eval Cyrillic::escape'; }
  0         0  
3346 0         0 elsif (/\G \b bytes::substr \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'substr'; }
  2         3  
3347 2         5 elsif (/\G \b chop \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Ecyrillic::chop'; }
  0         0  
3348 0         0 elsif (/\G \b bytes::index \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'index'; }
  0         0  
3349 0         0 elsif (/\G \b Char::index \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Char::index'; }
  0         0  
3350 0         0 elsif (/\G \b Cyrillic::index \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Cyrillic::index'; }
  2         7  
3351 2         7 elsif (/\G \b index \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Ecyrillic::index'; }
  0         0  
3352 0         0 elsif (/\G \b bytes::rindex \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'rindex'; }
  0         0  
3353 0         0 elsif (/\G \b Char::rindex \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Char::rindex'; }
  0         0  
3354 0         0 elsif (/\G \b Cyrillic::rindex \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Cyrillic::rindex'; }
  1         3  
3355 1         4 elsif (/\G \b rindex \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Ecyrillic::rindex'; }
  0         0  
3356 0         0 elsif (/\G \b lc (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Ecyrillic::lc'; }
  1         3  
3357 1         3 elsif (/\G \b lcfirst (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Ecyrillic::lcfirst'; }
  0         0  
3358 0         0 elsif (/\G \b uc (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Ecyrillic::uc'; }
  6         10  
3359             elsif (/\G \b ucfirst (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Ecyrillic::ucfirst'; }
3360             elsif (/\G \b fc (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Ecyrillic::fc'; }
3361 6         16  
  0         0  
3362 0         0 # "-s '' ..." means file test "-s 'filename' ..." (not means "- s/// ...")
  0         0  
3363 0         0 elsif (/\G -s (?>\s*) (\") ((?:$qq_char)+?) (\") /oxgc) { $slash = 'm//'; return '-s ' . e_qq('', $1,$3,$2); }
  0         0  
3364 0         0 elsif (/\G -s (?>\s+) qq (?>\s*) (\#) ((?:$qq_char)+?) (\#) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0         0  
3365 0         0 elsif (/\G -s (?>\s+) qq (?>\s*) (\() ((?:$qq_paren)+?) (\)) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0         0  
3366 0         0 elsif (/\G -s (?>\s+) qq (?>\s*) (\{) ((?:$qq_brace)+?) (\}) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0         0  
3367 0         0 elsif (/\G -s (?>\s+) qq (?>\s*) (\[) ((?:$qq_bracket)+?) (\]) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0         0  
3368             elsif (/\G -s (?>\s+) qq (?>\s*) (\<) ((?:$qq_angle)+?) (\>) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
3369 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  
3370 0         0  
  0         0  
3371 0         0 elsif (/\G -s (?>\s*) (\') ((?:\\\'|\\\\|$q_char)+?) (\') /oxgc) { $slash = 'm//'; return '-s ' . e_q ('', $1,$3,$2); }
  0         0  
3372 0         0 elsif (/\G -s (?>\s+) q (?>\s*) (\#) ((?:\\\#|\\\\|$q_char)+?) (\#) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0         0  
3373 0         0 elsif (/\G -s (?>\s+) q (?>\s*) (\() ((?:\\\)|\\\\|$q_paren)+?) (\)) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0         0  
3374 0         0 elsif (/\G -s (?>\s+) q (?>\s*) (\{) ((?:\\\}|\\\\|$q_brace)+?) (\}) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0         0  
3375 0         0 elsif (/\G -s (?>\s+) q (?>\s*) (\[) ((?:\\\]|\\\\|$q_bracket)+?) (\]) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0         0  
3376             elsif (/\G -s (?>\s+) q (?>\s*) (\<) ((?:\\\>|\\\\|$q_angle)+?) (\>) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
3377             elsif (/\G -s (?>\s+) q (?>\s*) (\S) ((?:\\\1|\\\\|$q_char)+?) (\1) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
3378 0         0  
  0         0  
3379 0         0 elsif (/\G -s (?>\s*) (\$ (?> \w+ (?: ::\w+)* ) (?: (?: ->)? (?: [\$\@\%\&\*]\* | \$\#\* | \( (?:$qq_paren)*? \) | [\@\%\*]? \{ (?:$qq_brace)+? \} | [\@\%]? \[ (?:$qq_bracket)+? \] ) )*) /oxgc)
  0         0  
3380 0         0 { $slash = 'm//'; return "-s $1"; }
  0         0  
3381 0         0 elsif (/\G -s (?>\s*) \( ((?:$qq_paren)*?) \) /oxgc) { $slash = 'm//'; return "-s ($1)"; }
  0         0  
3382             elsif (/\G -s (?= (?>\s+) [a-z]+) /oxgc) { $slash = 'm//'; return '-s'; }
3383 0         0 elsif (/\G -s (?>\s+) ((?>\w+)) /oxgc) { $slash = 'm//'; return "-s $1"; }
  2         8  
3384 2         9  
  2         5  
3385 2         7 elsif (/\G \b bytes::length (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'length'; }
  36         63  
3386 36         117 elsif (/\G \b bytes::chr (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'chr'; }
  2         5  
3387 2         7 elsif (/\G \b chr (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Ecyrillic::chr'; }
  8         16  
3388 8         22 elsif (/\G \b bytes::ord (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'div'; return 'ord'; }
  0         0  
3389 0         0 elsif (/\G \b ord (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'div'; return $function_ord; }
  0         0  
3390 0         0 elsif (/\G \b glob (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Ecyrillic::glob'; }
  0         0  
3391 0         0 elsif (/\G \b lc \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Ecyrillic::lc_'; }
  0         0  
3392 0         0 elsif (/\G \b lcfirst \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Ecyrillic::lcfirst_'; }
  0         0  
3393 0         0 elsif (/\G \b uc \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Ecyrillic::uc_'; }
  0         0  
3394 0         0 elsif (/\G \b ucfirst \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Ecyrillic::ucfirst_'; }
  0         0  
3395             elsif (/\G \b fc \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Ecyrillic::fc_'; }
3396 0         0 elsif (/\G -s \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return '-s '; }
  0         0  
3397 0         0  
  0         0  
3398 0         0 elsif (/\G \b bytes::length \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'length'; }
  0         0  
3399 0         0 elsif (/\G \b bytes::chr \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'chr'; }
  0         0  
3400 0         0 elsif (/\G \b chr \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Ecyrillic::chr_'; }
  0         0  
3401 0         0 elsif (/\G \b bytes::ord \b (?! (?>\s*) => ) /oxgc) { $slash = 'div'; return 'ord'; }
  0         0  
3402 0         0 elsif (/\G \b ord \b (?! (?>\s*) => ) /oxgc) { $slash = 'div'; return $function_ord_; }
  0         0  
3403 0         0 elsif (/\G \b glob \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Ecyrillic::glob_'; }
  8         30  
3404             elsif (/\G \b reverse \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return $function_reverse; }
3405             elsif (/\G \b getc \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return $function_getc; }
3406 8         32 # split
3407             elsif (/\G \b (split) \b (?! (?>\s*) => ) /oxgc) {
3408 87         177 $slash = 'm//';
3409 87         141  
3410 87         313 my $e = '';
3411             while (/\G ( (?>\s+) | \( | \#.* ) /oxgc) {
3412             $e .= $1;
3413             }
3414 85 100       308  
  87 100       5702  
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    100          
    50          
    50          
    100          
    50          
    100          
    50          
    50          
    50          
3415             # end of split
3416             if (/\G (?= [,;\)\}\]] ) /oxgc) { return 'Ecyrillic::split' . $e; }
3417 2         9  
3418             # split scalar value
3419             elsif (/\G ( [\$\@\&\*] $qq_scalar ) /oxgc) { return 'Ecyrillic::split' . $e . e_string($1); }
3420 1         7  
3421 0         0 # split literal space
3422 0         0 elsif (/\G \b qq (\#) [ ] (\#) /oxgc) { return 'Ecyrillic::split' . $e . qq {qq$1 $2}; }
3423 0         0 elsif (/\G \b qq ((?>\s*)) (\() [ ] (\)) /oxgc) { return 'Ecyrillic::split' . $e . qq{$1qq$2 $3}; }
3424 0         0 elsif (/\G \b qq ((?>\s*)) (\{) [ ] (\}) /oxgc) { return 'Ecyrillic::split' . $e . qq{$1qq$2 $3}; }
3425 0         0 elsif (/\G \b qq ((?>\s*)) (\[) [ ] (\]) /oxgc) { return 'Ecyrillic::split' . $e . qq{$1qq$2 $3}; }
3426 0         0 elsif (/\G \b qq ((?>\s*)) (\<) [ ] (\>) /oxgc) { return 'Ecyrillic::split' . $e . qq{$1qq$2 $3}; }
3427 0         0 elsif (/\G \b qq ((?>\s*)) (\S) [ ] (\2) /oxgc) { return 'Ecyrillic::split' . $e . qq{$1qq$2 $3}; }
3428 0         0 elsif (/\G \b q (\#) [ ] (\#) /oxgc) { return 'Ecyrillic::split' . $e . qq {q$1 $2}; }
3429 0         0 elsif (/\G \b q ((?>\s*)) (\() [ ] (\)) /oxgc) { return 'Ecyrillic::split' . $e . qq {$1q$2 $3}; }
3430 0         0 elsif (/\G \b q ((?>\s*)) (\{) [ ] (\}) /oxgc) { return 'Ecyrillic::split' . $e . qq {$1q$2 $3}; }
3431 0         0 elsif (/\G \b q ((?>\s*)) (\[) [ ] (\]) /oxgc) { return 'Ecyrillic::split' . $e . qq {$1q$2 $3}; }
3432 0         0 elsif (/\G \b q ((?>\s*)) (\<) [ ] (\>) /oxgc) { return 'Ecyrillic::split' . $e . qq {$1q$2 $3}; }
3433 10         44 elsif (/\G \b q ((?>\s*)) (\S) [ ] (\2) /oxgc) { return 'Ecyrillic::split' . $e . qq {$1q$2 $3}; }
3434             elsif (/\G ' [ ] ' /oxgc) { return 'Ecyrillic::split' . $e . qq {' '}; }
3435             elsif (/\G " [ ] " /oxgc) { return 'Ecyrillic::split' . $e . qq {" "}; }
3436              
3437 0 0       0 # split qq//
  0         0  
3438             elsif (/\G \b (qq) \b /oxgc) {
3439 0         0 if (/\G (\#) ((?:$qq_char)*?) (\#) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq# # --> qr # #
3440 0 0       0 else {
  0 0       0  
    0          
    0          
    0          
    0          
    0          
3441 0         0 while (not /\G \z/oxgc) {
3442 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3443 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq ( ) --> qr ( )
3444 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq { } --> qr { }
3445 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq [ ] --> qr [ ]
3446 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq < > --> qr < >
3447             elsif (/\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) /oxgc) { return e_split($e.'qr','{','}',$2,''); } # qq | | --> qr { }
3448 0         0 elsif (/\G (\S) ((?:$qq_char)*?) (\1) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq * * --> qr * *
3449             }
3450             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3451             }
3452             }
3453              
3454 0 50       0 # split qr//
  12         411  
3455             elsif (/\G \b (qr) \b /oxgc) {
3456 0         0 if (/\G (\#) ((?:$qq_char)*?) (\#) ([imosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1,$3,$2,$4); } # qr# #
3457 12 50       68 else {
  12 50       3281  
    50          
    50          
    50          
    50          
    50          
    50          
3458 0         0 while (not /\G \z/oxgc) {
3459 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3460 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([imosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # qr ( )
3461 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([imosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # qr { }
3462 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([imosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # qr [ ]
3463 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([imosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # qr < >
3464 0         0 elsif (/\G (\') ((?:$qq_char)*?) (\') ([imosxpadlunbB]*) /oxgc) { return e_split_q($e.'qr',$1, $3, $2,$4); } # qr ' '
3465             elsif (/\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ([imosxpadlunbB]*) /oxgc) { return e_split ($e.'qr','{','}',$2,$4); } # qr | | --> qr { }
3466 12         85 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([imosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # qr * *
3467             }
3468             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3469             }
3470             }
3471              
3472 0 0       0 # split q//
  0         0  
3473             elsif (/\G \b (q) \b /oxgc) {
3474 0         0 if (/\G (\#) ((?:\\\#|\\\\|$q_char)*?) (\#) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q# # --> qr # #
3475 0 0       0 else {
  0 0       0  
    0          
    0          
    0          
    0          
    0          
3476 0         0 while (not /\G \z/oxgc) {
3477 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3478 0         0 elsif (/\G (\() ((?:\\\\|\\\)|\\\(|$q_paren)*?) (\)) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q ( ) --> qr ( )
3479 0         0 elsif (/\G (\{) ((?:\\\\|\\\}|\\\{|$q_brace)*?) (\}) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q { } --> qr { }
3480 0         0 elsif (/\G (\[) ((?:\\\\|\\\]|\\\[|$q_bracket)*?) (\]) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q [ ] --> qr [ ]
3481 0         0 elsif (/\G (\<) ((?:\\\\|\\\>|\\\<|$q_angle)*?) (\>) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q < > --> qr < >
3482             elsif (/\G ([*\-:?\\^|]) ((?:$q_char)*?) (\1) /oxgc) { return e_split_q($e.'qr','{','}',$2,''); } # q | | --> qr { }
3483 0         0 elsif (/\G (\S) ((?:\\\\|\\\1| $q_char)*?) (\1) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q * * --> qr * *
3484             }
3485             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3486             }
3487             }
3488              
3489 0 50       0 # split m//
  18         500  
3490             elsif (/\G \b (m) \b /oxgc) {
3491 0         0 if (/\G (\#) ((?:$qq_char)*?) (\#) ([cgimosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1,$3,$2,$4); } # m# # --> qr # #
3492 18 50       78 else {
  18 50       3705  
    50          
    50          
    50          
    50          
    50          
    50          
3493 0         0 while (not /\G \z/oxgc) {
3494 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3495 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cgimosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # m ( ) --> qr ( )
3496 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cgimosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # m { } --> qr { }
3497 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cgimosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # m [ ] --> qr [ ]
3498 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cgimosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # m < > --> qr < >
3499 0         0 elsif (/\G (\') ((?:$qq_char)*?) (\') ([cgimosxpadlunbB]*) /oxgc) { return e_split_q($e.'qr',$1, $3, $2,$4); } # m ' ' --> qr ' '
3500             elsif (/\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ([cgimosxpadlunbB]*) /oxgc) { return e_split ($e.'qr','{','}',$2,$4); } # m | | --> qr { }
3501 18         108 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cgimosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # m * * --> qr * *
3502             }
3503             die __FILE__, ": Search pattern not terminated\n";
3504             }
3505             }
3506              
3507 0         0 # split ''
3508 0         0 elsif (/\G (\') /oxgc) {
3509 0 0       0 my $q_string = '';
  0 0       0  
    0          
    0          
3510 0         0 while (not /\G \z/oxgc) {
3511 0         0 if (/\G (\\\\) /oxgc) { $q_string .= $1; }
3512 0         0 elsif (/\G (\\\') /oxgc) { $q_string .= $1; } # splitqr'' --> split qr''
3513             elsif (/\G \' /oxgc) { return e_split_q($e.q{ qr},"'","'",$q_string,''); } # ' ' --> qr ' '
3514 0         0 elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3515             }
3516             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3517             }
3518              
3519 0         0 # split ""
3520 0         0 elsif (/\G (\") /oxgc) {
3521 0 0       0 my $qq_string = '';
  0 0       0  
    0          
    0          
3522 0         0 while (not /\G \z/oxgc) {
3523 0         0 if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
3524 0         0 elsif (/\G (\\\") /oxgc) { $qq_string .= $1; } # splitqr"" --> split qr""
3525             elsif (/\G \" /oxgc) { return e_split($e.q{ qr},'"','"',$qq_string,''); } # " " --> qr " "
3526 0         0 elsif (/\G ($q_char) /oxgc) { $qq_string .= $1; }
3527             }
3528             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3529             }
3530              
3531 0         0 # split //
3532 44         134 elsif (/\G (\/) /oxgc) {
3533 44 50       139 my $regexp = '';
  381 50       1474  
    100          
    50          
3534 0         0 while (not /\G \z/oxgc) {
3535 0         0 if (/\G (\\\\) /oxgc) { $regexp .= $1; }
3536 44         202 elsif (/\G (\\\/) /oxgc) { $regexp .= $1; } # splitqr// --> split qr//
3537             elsif (/\G \/ ([cgimosxpadlunbB]*) /oxgc) { return e_split($e.q{ qr}, '/','/',$regexp,$1); } # / / --> qr / /
3538 337         725 elsif (/\G ($q_char) /oxgc) { $regexp .= $1; }
3539             }
3540             die __FILE__, ": Search pattern not terminated\n";
3541             }
3542             }
3543              
3544             # tr/// or y///
3545              
3546             # about [cdsrbB]* (/B modifier)
3547             #
3548             # P.559 appendix C
3549             # of ISBN 4-89052-384-7 Programming perl
3550             # (Japanese title is: Perl puroguramingu)
3551 0         0  
3552             elsif (/\G \b ( tr | y ) \b /oxgc) {
3553             my $ope = $1;
3554 3 50       9  
3555 3         47 # $1 $2 $3 $4 $5 $6
3556 0         0 if (/\G (\#) ((?:$qq_char)*?) (\#) ((?:$qq_char)*?) (\#) ([cdsrbB]*) /oxgc) { # tr# # #
3557             my @tr = ($tr_variable,$2);
3558             return e_tr(@tr,'',$4,$6);
3559 0         0 }
3560 3         19 else {
3561 3 50       10 my $e = '';
  3 50       227  
    50          
    50          
    50          
    50          
3562             while (not /\G \z/oxgc) {
3563 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3564 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) /oxgc) {
3565 0 0       0 my @tr = ($tr_variable,$2);
  0 0       0  
    0          
    0          
    0          
    0          
3566 0         0 while (not /\G \z/oxgc) {
3567 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3568 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr ( ) ( )
3569 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr ( ) { }
3570 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr ( ) [ ]
3571             elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr ( ) < >
3572 0         0 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr ( ) * *
3573             }
3574             die __FILE__, ": Transliteration replacement not terminated\n";
3575 0         0 }
3576 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) {
3577 0 0       0 my @tr = ($tr_variable,$2);
  0 0       0  
    0          
    0          
    0          
    0          
3578 0         0 while (not /\G \z/oxgc) {
3579 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3580 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr { } ( )
3581 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr { } { }
3582 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr { } [ ]
3583             elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr { } < >
3584 0         0 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr { } * *
3585             }
3586             die __FILE__, ": Transliteration replacement not terminated\n";
3587 0         0 }
3588 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) {
3589 0 0       0 my @tr = ($tr_variable,$2);
  0 0       0  
    0          
    0          
    0          
    0          
3590 0         0 while (not /\G \z/oxgc) {
3591 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3592 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr [ ] ( )
3593 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr [ ] { }
3594 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr [ ] [ ]
3595             elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr [ ] < >
3596 0         0 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr [ ] * *
3597             }
3598             die __FILE__, ": Transliteration replacement not terminated\n";
3599 0         0 }
3600 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) {
3601 0 0       0 my @tr = ($tr_variable,$2);
  0 0       0  
    0          
    0          
    0          
    0          
3602 0         0 while (not /\G \z/oxgc) {
3603 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3604 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr < > ( )
3605 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr < > { }
3606 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr < > [ ]
3607             elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr < > < >
3608 0         0 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr < > * *
3609             }
3610             die __FILE__, ": Transliteration replacement not terminated\n";
3611             }
3612 0         0 # $1 $2 $3 $4 $5 $6
3613 3         12 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ((?:$qq_char)*?) (\1) ([cdsrbB]*) /oxgc) { # tr * * *
3614             my @tr = ($tr_variable,$2);
3615             return e_tr(@tr,'',$4,$6);
3616 3         9 }
3617             }
3618             die __FILE__, ": Transliteration pattern not terminated\n";
3619             }
3620             }
3621              
3622 0         0 # qq//
3623             elsif (/\G \b (qq) \b /oxgc) {
3624             my $ope = $1;
3625 2180 50       4790  
3626 2180         3981 # if (/\G (\#) ((?:$qq_char)*?) (\#) /oxgc) { return e_qq($ope,$1,$3,$2); } # qq# #
3627 0         0 if (/\G (\#) /oxgc) { # qq# #
3628 0 0       0 my $qq_string = '';
  0 0       0  
    0          
    0          
3629 0         0 while (not /\G \z/oxgc) {
3630 0         0 if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
3631 0         0 elsif (/\G (\\\#) /oxgc) { $qq_string .= $1; }
3632             elsif (/\G (\#) /oxgc) { return e_qq($ope,'#','#',$qq_string); }
3633 0         0 elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3634             }
3635             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3636             }
3637 0         0  
3638 2180         2875 else {
3639 2180 50       5053 my $e = '';
  2180 50       8175  
    100          
    50          
    50          
    0          
3640             while (not /\G \z/oxgc) {
3641             if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3642              
3643 0         0 # elsif (/\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qq ( )
3644 0         0 elsif (/\G (\() /oxgc) { # qq ( )
3645 0         0 my $qq_string = '';
3646 0 0       0 local $nest = 1;
  0 0       0  
    0          
    0          
    0          
3647 0         0 while (not /\G \z/oxgc) {
3648 0         0 if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0         0  
3649             elsif (/\G (\\\)) /oxgc) { $qq_string .= $1; }
3650 0 0       0 elsif (/\G (\() /oxgc) { $qq_string .= $1; $nest++; }
  0         0  
3651 0         0 elsif (/\G (\)) /oxgc) {
3652             if (--$nest == 0) { return $e . e_qq($ope,'(',')',$qq_string); }
3653 0         0 else { $qq_string .= $1; }
3654             }
3655 0         0 elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3656             }
3657             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3658             }
3659              
3660 0         0 # elsif (/\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qq { }
3661 2150         2955 elsif (/\G (\{) /oxgc) { # qq { }
3662 2150         3094 my $qq_string = '';
3663 2150 100       4177 local $nest = 1;
  84032 50       250647  
    100          
    100          
    50          
3664 722         1430 while (not /\G \z/oxgc) {
3665 0         0 if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  1153         1525  
3666             elsif (/\G (\\\}) /oxgc) { $qq_string .= $1; }
3667 1153 100       1941 elsif (/\G (\{) /oxgc) { $qq_string .= $1; $nest++; }
  3303         5021  
3668 2150         4142 elsif (/\G (\}) /oxgc) {
3669             if (--$nest == 0) { return $e . e_qq($ope,'{','}',$qq_string); }
3670 1153         2280 else { $qq_string .= $1; }
3671             }
3672 78854         150201 elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3673             }
3674             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3675             }
3676              
3677 0         0 # elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qq [ ]
3678 0         0 elsif (/\G (\[) /oxgc) { # qq [ ]
3679 0         0 my $qq_string = '';
3680 0 0       0 local $nest = 1;
  0 0       0  
    0          
    0          
    0          
3681 0         0 while (not /\G \z/oxgc) {
3682 0         0 if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0         0  
3683             elsif (/\G (\\\]) /oxgc) { $qq_string .= $1; }
3684 0 0       0 elsif (/\G (\[) /oxgc) { $qq_string .= $1; $nest++; }
  0         0  
3685 0         0 elsif (/\G (\]) /oxgc) {
3686             if (--$nest == 0) { return $e . e_qq($ope,'[',']',$qq_string); }
3687 0         0 else { $qq_string .= $1; }
3688             }
3689 0         0 elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3690             }
3691             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3692             }
3693              
3694 0         0 # elsif (/\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qq < >
3695 30         47 elsif (/\G (\<) /oxgc) { # qq < >
3696 30         49 my $qq_string = '';
3697 30 100       90 local $nest = 1;
  1166 50       3986  
    50          
    100          
    50          
3698 22         50 while (not /\G \z/oxgc) {
3699 0         0 if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0         0  
3700             elsif (/\G (\\\>) /oxgc) { $qq_string .= $1; }
3701 0 50       0 elsif (/\G (\<) /oxgc) { $qq_string .= $1; $nest++; }
  30         77  
3702 30         77 elsif (/\G (\>) /oxgc) {
3703             if (--$nest == 0) { return $e . e_qq($ope,'<','>',$qq_string); }
3704 0         0 else { $qq_string .= $1; }
3705             }
3706 1114         2824 elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3707             }
3708             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3709             }
3710              
3711 0         0 # elsif (/\G (\S) ((?:$qq_char)*?) (\1) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qq * *
3712 0         0 elsif (/\G (\S) /oxgc) { # qq * *
3713 0         0 my $delimiter = $1;
3714 0 0       0 my $qq_string = '';
  0 0       0  
    0          
    0          
3715 0         0 while (not /\G \z/oxgc) {
3716 0         0 if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
3717 0         0 elsif (/\G (\\\Q$delimiter\E) /oxgc) { $qq_string .= $1; }
3718             elsif (/\G (\Q$delimiter\E) /oxgc) { return $e . e_qq($ope,$delimiter,$delimiter,$qq_string); }
3719 0         0 elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3720             }
3721             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3722 0         0 }
3723             }
3724             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3725             }
3726             }
3727              
3728 0         0 # qr//
3729 0 0       0 elsif (/\G \b (qr) \b /oxgc) {
3730 0         0 my $ope = $1;
3731             if (/\G (\#) ((?:$qq_char)*?) (\#) ([imosxpadlunbB]*) /oxgc) { # qr# # #
3732             return e_qr($ope,$1,$3,$2,$4);
3733 0         0 }
3734 0         0 else {
3735 0 0       0 my $e = '';
  0 0       0  
    0          
    0          
    0          
    0          
    0          
    0          
3736 0         0 while (not /\G \z/oxgc) {
3737 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3738 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([imosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # qr ( )
3739 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([imosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # qr { }
3740 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([imosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # qr [ ]
3741 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([imosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # qr < >
3742 0         0 elsif (/\G (\') ((?:$qq_char)*?) (\') ([imosxpadlunbB]*) /oxgc) { return $e . e_qr_q($ope,$1, $3, $2,$4); } # qr ' '
3743             elsif (/\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ([imosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,'{','}',$2,$4); } # qr | | --> qr { }
3744 0         0 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([imosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # qr * *
3745             }
3746             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3747             }
3748             }
3749              
3750 0         0 # qw//
3751 16 50       52 elsif (/\G \b (qw) \b /oxgc) {
3752 16         77 my $ope = $1;
3753             if (/\G (\#) (.*?) (\#) /oxmsgc) { # qw# #
3754             return e_qw($ope,$1,$3,$2);
3755 0         0 }
3756 16         31 else {
3757 16 50       55 my $e = '';
  16 50       108  
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
3758             while (not /\G \z/oxgc) {
3759 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3760 16         58  
3761             elsif (/\G (\() ([^(]*?) (\)) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw ( )
3762 0         0 elsif (/\G (\() ((?:$q_paren)*?) (\)) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw ( )
3763 0         0  
3764             elsif (/\G (\{) ([^{]*?) (\}) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw { }
3765 0         0 elsif (/\G (\{) ((?:$q_brace)*?) (\}) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw { }
3766 0         0  
3767             elsif (/\G (\[) ([^[]*?) (\]) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw [ ]
3768 0         0 elsif (/\G (\[) ((?:$q_bracket)*?) (\]) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw [ ]
3769 0         0  
3770             elsif (/\G (\<) ([^<]*?) (\>) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw < >
3771 0         0 elsif (/\G (\<) ((?:$q_angle)*?) (\>) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw < >
3772 0         0  
3773             elsif (/\G ([\x21-\x3F]) (.*?) (\1) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw * *
3774 0         0 elsif (/\G (\S) ((?:$q_char)*?) (\1) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw * *
3775             }
3776             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3777             }
3778             }
3779              
3780 0         0 # qx//
3781 0 0       0 elsif (/\G \b (qx) \b /oxgc) {
3782 0         0 my $ope = $1;
3783             if (/\G (\#) ((?:$qq_char)*?) (\#) /oxgc) { # qx# #
3784             return e_qq($ope,$1,$3,$2);
3785 0         0 }
3786 0         0 else {
3787 0 0       0 my $e = '';
  0 0       0  
    0          
    0          
    0          
    0          
    0          
3788 0         0 while (not /\G \z/oxgc) {
3789 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3790 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qx ( )
3791 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qx { }
3792 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qx [ ]
3793 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qx < >
3794             elsif (/\G (\') ((?:$qq_char)*?) (\') /oxgc) { return $e . e_q ($ope,$1,$3,$2); } # qx ' '
3795 0         0 elsif (/\G (\S) ((?:$qq_char)*?) (\1) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qx * *
3796             }
3797             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3798             }
3799             }
3800              
3801 0         0 # q//
3802             elsif (/\G \b (q) \b /oxgc) {
3803             my $ope = $1;
3804              
3805             # if (/\G (\#) ((?:\\\#|\\\\|$q_char)*?) (\#) /oxgc) { return e_q($ope,$1,$3,$2); } # q# #
3806              
3807             # avoid "Error: Runtime exception" of perl version 5.005_03
3808 410 50       1095 # (and so on)
3809 410         1053  
3810 0         0 if (/\G (\#) /oxgc) { # q# #
3811 0 0       0 my $q_string = '';
  0 0       0  
    0          
    0          
3812 0         0 while (not /\G \z/oxgc) {
3813 0         0 if (/\G (\\\\) /oxgc) { $q_string .= $1; }
3814 0         0 elsif (/\G (\\\#) /oxgc) { $q_string .= $1; }
3815             elsif (/\G (\#) /oxgc) { return e_q($ope,'#','#',$q_string); }
3816 0         0 elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3817             }
3818             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3819             }
3820 0         0  
3821 410         678 else {
3822 410 50       1225 my $e = '';
  410 50       2171  
    100          
    50          
    100          
    50          
3823             while (not /\G \z/oxgc) {
3824             if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3825              
3826 0         0 # elsif (/\G (\() ((?:\\\)|\\\\|$q_paren)*?) (\)) /oxgc) { return $e . e_q($ope,$1,$3,$2); } # q ( )
3827 0         0 elsif (/\G (\() /oxgc) { # q ( )
3828 0         0 my $q_string = '';
3829 0 0       0 local $nest = 1;
  0 0       0  
    0          
    0          
    0          
    0          
3830 0         0 while (not /\G \z/oxgc) {
3831 0         0 if (/\G (\\\\) /oxgc) { $q_string .= $1; }
3832 0         0 elsif (/\G (\\\)) /oxgc) { $q_string .= $1; }
  0         0  
3833             elsif (/\G (\\\() /oxgc) { $q_string .= $1; }
3834 0 0       0 elsif (/\G (\() /oxgc) { $q_string .= $1; $nest++; }
  0         0  
3835 0         0 elsif (/\G (\)) /oxgc) {
3836             if (--$nest == 0) { return $e . e_q($ope,'(',')',$q_string); }
3837 0         0 else { $q_string .= $1; }
3838             }
3839 0         0 elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3840             }
3841             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3842             }
3843              
3844 0         0 # elsif (/\G (\{) ((?:\\\}|\\\\|$q_brace)*?) (\}) /oxgc) { return $e . e_q($ope,$1,$3,$2); } # q { }
3845 404         741 elsif (/\G (\{) /oxgc) { # q { }
3846 404         740 my $q_string = '';
3847 404 50       1042 local $nest = 1;
  6796 50       24735  
    50          
    100          
    100          
    50          
3848 0         0 while (not /\G \z/oxgc) {
3849 0         0 if (/\G (\\\\) /oxgc) { $q_string .= $1; }
3850 0         0 elsif (/\G (\\\}) /oxgc) { $q_string .= $1; }
  107         177  
3851             elsif (/\G (\\\{) /oxgc) { $q_string .= $1; }
3852 107 100       186 elsif (/\G (\{) /oxgc) { $q_string .= $1; $nest++; }
  511         1376  
3853 404         1133 elsif (/\G (\}) /oxgc) {
3854             if (--$nest == 0) { return $e . e_q($ope,'{','}',$q_string); }
3855 107         238 else { $q_string .= $1; }
3856             }
3857 6178         14425 elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3858             }
3859             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3860             }
3861              
3862 0         0 # elsif (/\G (\[) ((?:\\\]|\\\\|$q_bracket)*?) (\]) /oxgc) { return $e . e_q($ope,$1,$3,$2); } # q [ ]
3863 0         0 elsif (/\G (\[) /oxgc) { # q [ ]
3864 0         0 my $q_string = '';
3865 0 0       0 local $nest = 1;
  0 0       0  
    0          
    0          
    0          
    0          
3866 0         0 while (not /\G \z/oxgc) {
3867 0         0 if (/\G (\\\\) /oxgc) { $q_string .= $1; }
3868 0         0 elsif (/\G (\\\]) /oxgc) { $q_string .= $1; }
  0         0  
3869             elsif (/\G (\\\[) /oxgc) { $q_string .= $1; }
3870 0 0       0 elsif (/\G (\[) /oxgc) { $q_string .= $1; $nest++; }
  0         0  
3871 0         0 elsif (/\G (\]) /oxgc) {
3872             if (--$nest == 0) { return $e . e_q($ope,'[',']',$q_string); }
3873 0         0 else { $q_string .= $1; }
3874             }
3875 0         0 elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3876             }
3877             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3878             }
3879              
3880 0         0 # elsif (/\G (\<) ((?:\\\>|\\\\|$q_angle)*?) (\>) /oxgc) { return $e . e_q($ope,$1,$3,$2); } # q < >
3881 5         10 elsif (/\G (\<) /oxgc) { # q < >
3882 5         10 my $q_string = '';
3883 5 50       29 local $nest = 1;
  88 50       395  
    50          
    50          
    100          
    50          
3884 0         0 while (not /\G \z/oxgc) {
3885 0         0 if (/\G (\\\\) /oxgc) { $q_string .= $1; }
3886 0         0 elsif (/\G (\\\>) /oxgc) { $q_string .= $1; }
  0         0  
3887             elsif (/\G (\\\<) /oxgc) { $q_string .= $1; }
3888 0 50       0 elsif (/\G (\<) /oxgc) { $q_string .= $1; $nest++; }
  5         14  
3889 5         15 elsif (/\G (\>) /oxgc) {
3890             if (--$nest == 0) { return $e . e_q($ope,'<','>',$q_string); }
3891 0         0 else { $q_string .= $1; }
3892             }
3893 83         161 elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3894             }
3895             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3896             }
3897              
3898 0         0 # elsif (/\G (\S) ((?:\\\1|\\\\|$q_char)*?) (\1) /oxgc) { return $e . e_q($ope,$1,$3,$2); } # q * *
3899 1         2 elsif (/\G (\S) /oxgc) { # q * *
3900 1         3 my $delimiter = $1;
3901 1 50       3 my $q_string = '';
  14 50       65  
    100          
    50          
3902 0         0 while (not /\G \z/oxgc) {
3903 0         0 if (/\G (\\\\) /oxgc) { $q_string .= $1; }
3904 1         2 elsif (/\G (\\\Q$delimiter\E) /oxgc) { $q_string .= $1; }
3905             elsif (/\G (\Q$delimiter\E) /oxgc) { return $e . e_q($ope,$delimiter,$delimiter,$q_string); }
3906 13         25 elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3907             }
3908             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3909 0         0 }
3910             }
3911             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3912             }
3913             }
3914              
3915 0         0 # m//
3916 209 50       495 elsif (/\G \b (m) \b /oxgc) {
3917 209         1478 my $ope = $1;
3918             if (/\G (\#) ((?:$qq_char)*?) (\#) ([cgimosxpadlunbB]*) /oxgc) { # m# #
3919             return e_qr($ope,$1,$3,$2,$4);
3920 0         0 }
3921 209         307 else {
3922 209 50       532 my $e = '';
  209 50       10784  
    50          
    50          
    50          
    50          
    100          
    50          
    50          
3923 0         0 while (not /\G \z/oxgc) {
3924 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3925 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cgimosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m ( )
3926 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cgimosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m { }
3927 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cgimosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m [ ]
3928 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cgimosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m < >
3929 10         74 elsif (/\G (\?) ((?:$qq_char)*?) (\?) ([cgimosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m ? ?
3930 0         0 elsif (/\G (\') ((?:$qq_char)*?) (\') ([cgimosxpadlunbB]*) /oxgc) { return $e . e_qr_q($ope,$1, $3, $2,$4); } # m ' '
3931             elsif (/\G ([*\-:\\^|]) ((?:$qq_char)*?) (\1) ([cgimosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,'{','}',$2,$4); } # m | | --> m { }
3932 199         635 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cgimosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m * *
3933             }
3934             die __FILE__, ": Search pattern not terminated\n";
3935             }
3936             }
3937              
3938             # s///
3939              
3940             # about [cegimosxpradlunbB]* (/cg modifier)
3941             #
3942             # P.67 Pattern-Matching Operators
3943             # of ISBN 0-596-00241-6 Perl in a Nutshell, Second Edition.
3944 0         0  
3945             elsif (/\G \b (s) \b /oxgc) {
3946             my $ope = $1;
3947 97 100       261  
3948 97         1640 # $1 $2 $3 $4 $5 $6
3949             if (/\G (\#) ((?:$qq_char)*?) (\#) ((?:$qq_char)*?) (\#) ([cegimosxpradlunbB]*) /oxgc) { # s# # #
3950             return e_sub($sub_variable,$1,$2,$3,$3,$4,$5,$6);
3951 1         4 }
3952 96         191 else {
3953 96 50       313 my $e = '';
  96 50       12569  
    50          
    50          
    50          
    100          
    50          
    50          
    50          
3954             while (not /\G \z/oxgc) {
3955 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3956 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) /oxgc) {
3957 0 0       0 my @s = ($1,$2,$3);
  0 0       0  
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
3958             while (not /\G \z/oxgc) {
3959 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3960 0         0 # $1 $2 $3 $4
3961 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3962 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3963 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3964 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3965 0         0 elsif (/\G (\') ((?:$qq_char)*?) (\') ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3966 0         0 elsif (/\G (\$) ((?:$qq_char)*?) (\$) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3967 0         0 elsif (/\G (\:) ((?:$qq_char)*?) (\:) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3968             elsif (/\G (\@) ((?:$qq_char)*?) (\@) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3969 0         0 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3970             }
3971             die __FILE__, ": Substitution replacement not terminated\n";
3972 0         0 }
3973 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) {
3974 0 0       0 my @s = ($1,$2,$3);
  0 0       0  
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
3975             while (not /\G \z/oxgc) {
3976 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3977 0         0 # $1 $2 $3 $4
3978 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3979 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3980 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3981 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3982 0         0 elsif (/\G (\') ((?:$qq_char)*?) (\') ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3983 0         0 elsif (/\G (\$) ((?:$qq_char)*?) (\$) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3984 0         0 elsif (/\G (\:) ((?:$qq_char)*?) (\:) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3985             elsif (/\G (\@) ((?:$qq_char)*?) (\@) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3986 0         0 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3987             }
3988             die __FILE__, ": Substitution replacement not terminated\n";
3989 0         0 }
3990 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) {
3991 0 0       0 my @s = ($1,$2,$3);
  0 0       0  
    0          
    0          
    0          
    0          
    0          
    0          
3992             while (not /\G \z/oxgc) {
3993 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3994 0         0 # $1 $2 $3 $4
3995 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3996 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3997 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3998 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3999 0         0 elsif (/\G (\') ((?:$qq_char)*?) (\') ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
4000             elsif (/\G (\$) ((?:$qq_char)*?) (\$) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
4001 0         0 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
4002             }
4003             die __FILE__, ": Substitution replacement not terminated\n";
4004 0         0 }
4005 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) {
4006 0 0       0 my @s = ($1,$2,$3);
  0 0       0  
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
4007             while (not /\G \z/oxgc) {
4008 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
4009 0         0 # $1 $2 $3 $4
4010 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
4011 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
4012 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
4013 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
4014 0         0 elsif (/\G (\') ((?:$qq_char)*?) (\') ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
4015 0         0 elsif (/\G (\$) ((?:$qq_char)*?) (\$) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
4016 0         0 elsif (/\G (\:) ((?:$qq_char)*?) (\:) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
4017             elsif (/\G (\@) ((?:$qq_char)*?) (\@) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
4018 0         0 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
4019             }
4020             die __FILE__, ": Substitution replacement not terminated\n";
4021             }
4022 0         0 # $1 $2 $3 $4 $5 $6
4023             elsif (/\G (\') ((?:$qq_char)*?) (\') ((?:$qq_char)*?) (\') ([cegimosxpradlunbB]*) /oxgc) {
4024             return e_sub($sub_variable,$1,$2,$3,$3,$4,$5,$6);
4025             }
4026 21         59 # $1 $2 $3 $4 $5 $6
4027             elsif (/\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ((?:$qq_char)*?) (\1) ([cegimosxpradlunbB]*) /oxgc) {
4028             return e_sub($sub_variable,'{',$2,'}','{',$4,'}',$6); # s | | | --> s { } { }
4029             }
4030 0         0 # $1 $2 $3 $4 $5 $6
4031             elsif (/\G (\$) ((?:$qq_char)*?) (\1) ((?:$qq_char)*?) (\1) ([cegimosxpradlunbB]*) /oxgc) {
4032             return e_sub($sub_variable,$1,$2,$3,$3,$4,$5,$6);
4033             }
4034 0         0 # $1 $2 $3 $4 $5 $6
4035             elsif (/\G (\S) ((?:$qq_char)*?) (\1) ((?:$qq_char)*?) (\1) ([cegimosxpradlunbB]*) /oxgc) {
4036             return e_sub($sub_variable,$1,$2,$3,$3,$4,$5,$6);
4037 75         355 }
4038             }
4039             die __FILE__, ": Substitution pattern not terminated\n";
4040             }
4041             }
4042 0         0  
4043 0         0 # require ignore module
4044 0         0 elsif (/\G \b require ((?>\s+) (?:$ignore_modules) .*? ;) ([ \t]* [#\n]) /oxmsgc) { return "# require$1$2"; }
4045             elsif (/\G \b require ((?>\s+) (?:$ignore_modules) .*? ;) ([ \t]* [^#]) /oxmsgc) { return "# require$1\n$2"; }
4046             elsif (/\G \b require ((?>\s+) (?:$ignore_modules)) \b /oxmsgc) { return "# require$1"; }
4047 0         0  
4048 37         336 # use strict; --> use strict; no strict qw(refs);
4049 0         0 elsif (/\G \b use ((?>\s+) strict .*? ;) ([ \t]* [#\n]) /oxmsgc) { return "use$1 no strict qw(refs);$2"; }
4050             elsif (/\G \b use ((?>\s+) strict .*? ;) ([ \t]* [^#]) /oxmsgc) { return "use$1 no strict qw(refs);\n$2"; }
4051             elsif (/\G \b use ((?>\s+) strict) \b /oxmsgc) { return "use$1; no strict qw(refs)"; }
4052              
4053 0 50 33     0 # use 5.12.0; --> use 5.12.0; no strict qw(refs);
      33        
4054 2         23 elsif (/\G \b use (?>\s+) ((?>([1-9][0-9_]*)(?:\.([0-9_]+))*)) (?>\s*) ; /oxmsgc) {
4055             if (($2 >= 6) or (($2 == 5) and ($3 ge '012'))) {
4056             return "use $1; no strict qw(refs);";
4057 0         0 }
4058             else {
4059             return "use $1;";
4060             }
4061 2 0 0     12 }
      0        
4062 0         0 elsif (/\G \b use (?>\s+) ((?>v([0-9][0-9_]*)(?:\.([0-9_]+))*)) (?>\s*) ; /oxmsgc) {
4063             if (($2 >= 6) or (($2 == 5) and ($3 >= 12))) {
4064             return "use $1; no strict qw(refs);";
4065 0         0 }
4066             else {
4067             return "use $1;";
4068             }
4069             }
4070 0         0  
4071 2         15 # ignore use module
4072 0         0 elsif (/\G \b use ((?>\s+) (?:$ignore_modules) .*? ;) ([ \t]* [#\n]) /oxmsgc) { return "# use$1$2"; }
4073             elsif (/\G \b use ((?>\s+) (?:$ignore_modules) .*? ;) ([ \t]* [^#]) /oxmsgc) { return "# use$1\n$2"; }
4074             elsif (/\G \b use ((?>\s+) (?:$ignore_modules)) \b /oxmsgc) { return "# use$1"; }
4075 0         0  
4076 0         0 # ignore no module
4077 0         0 elsif (/\G \b no ((?>\s+) (?:$ignore_modules) .*? ;) ([ \t]* [#\n]) /oxmsgc) { return "# no$1$2"; }
4078             elsif (/\G \b no ((?>\s+) (?:$ignore_modules) .*? ;) ([ \t]* [^#]) /oxmsgc) { return "# no$1\n$2"; }
4079             elsif (/\G \b no ((?>\s+) (?:$ignore_modules)) \b /oxmsgc) { return "# no$1"; }
4080 0         0  
4081             # use else
4082             elsif (/\G \b use \b /oxmsgc) { return "use"; }
4083 0         0  
4084             # use else
4085             elsif (/\G \b no \b /oxmsgc) { return "no"; }
4086              
4087 2         9 # ''
4088 848         1704 elsif (/\G (?
4089 848 100       2343 my $q_string = '';
  8280 100       24186  
    100          
    50          
4090 4         9 while (not /\G \z/oxgc) {
4091 48         87 if (/\G (\\\\) /oxgc) { $q_string .= $1; }
4092 848         1909 elsif (/\G (\\\') /oxgc) { $q_string .= $1; }
4093             elsif (/\G \' /oxgc) { return e_q('', "'","'",$q_string); }
4094 7380         14361 elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
4095             }
4096             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4097             }
4098              
4099 0         0 # ""
4100 1862         3734 elsif (/\G (\") /oxgc) {
4101 1862 100       4361 my $qq_string = '';
  35693 100       100514  
    100          
    50          
4102 67         152 while (not /\G \z/oxgc) {
4103 12         27 if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
4104 1862         5548 elsif (/\G (\\\") /oxgc) { $qq_string .= $1; }
4105             elsif (/\G \" /oxgc) { return e_qq('', '"','"',$qq_string); }
4106 33752         67934 elsif (/\G ($q_char) /oxgc) { $qq_string .= $1; }
4107             }
4108             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4109             }
4110              
4111 0         0 # ``
4112 1         3 elsif (/\G (\`) /oxgc) {
4113 1 50       4 my $qx_string = '';
  19 50       79  
    100          
    50          
4114 0         0 while (not /\G \z/oxgc) {
4115 0         0 if (/\G (\\\\) /oxgc) { $qx_string .= $1; }
4116 1         3 elsif (/\G (\\\`) /oxgc) { $qx_string .= $1; }
4117             elsif (/\G \` /oxgc) { return e_qq('', '`','`',$qx_string); }
4118 18         37 elsif (/\G ($q_char) /oxgc) { $qx_string .= $1; }
4119             }
4120             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4121             }
4122              
4123 0         0 # // --- not divide operator (num / num), not defined-or
4124 453         1096 elsif (($slash eq 'm//') and /\G (\/) /oxgc) {
4125 453 50       1536 my $regexp = '';
  4496 50       14436  
    100          
    50          
4126 0         0 while (not /\G \z/oxgc) {
4127 0         0 if (/\G (\\\\) /oxgc) { $regexp .= $1; }
4128 453         1143 elsif (/\G (\\\/) /oxgc) { $regexp .= $1; }
4129             elsif (/\G \/ ([cgimosxpadlunbB]*) /oxgc) { return e_qr('', '/','/',$regexp,$1); }
4130 4043         7907 elsif (/\G ($q_char) /oxgc) { $regexp .= $1; }
4131             }
4132             die __FILE__, ": Search pattern not terminated\n";
4133             }
4134              
4135 0         0 # ?? --- not conditional operator (condition ? then : else)
4136 0         0 elsif (($slash eq 'm//') and /\G (\?) /oxgc) {
4137 0 0       0 my $regexp = '';
  0 0       0  
    0          
    0          
4138 0         0 while (not /\G \z/oxgc) {
4139 0         0 if (/\G (\\\\) /oxgc) { $regexp .= $1; }
4140 0         0 elsif (/\G (\\\?) /oxgc) { $regexp .= $1; }
4141             elsif (/\G \? ([cgimosxpadlunbB]*) /oxgc) { return e_qr('m','?','?',$regexp,$1); }
4142 0         0 elsif (/\G ($q_char) /oxgc) { $regexp .= $1; }
4143             }
4144             die __FILE__, ": Search pattern not terminated\n";
4145             }
4146 0         0  
  0         0  
4147             # <<>> (a safer ARGV)
4148             elsif (/\G ( <<>> ) /oxgc) { $slash = 'm//'; return $1; }
4149 0         0  
  0         0  
4150             # << (bit shift) --- not here document
4151             elsif (/\G ( << (?>\s*) ) (?= [0-9\$\@\&] ) /oxgc) { $slash = 'm//'; return $1; }
4152              
4153 0         0 # <<~'HEREDOC'
4154 6         16 elsif (/\G ( <<~ [\t ]* '([a-zA-Z_0-9]*)' ) /oxgc) {
4155 6         15 $slash = 'm//';
4156             my $here_quote = $1;
4157             my $delimiter = $2;
4158 6 50       15  
4159 6         19 # get here document
4160 6         39 if ($here_script eq '') {
4161             $here_script = CORE::substr $_, pos $_;
4162 6 50       35 $here_script =~ s/.*?\n//oxm;
4163 6         83 }
4164 6         15 if ($here_script =~ s/\A (.*?) \n ([\t ]*) $delimiter \n //xms) {
4165 6         13 my $heredoc = $1;
4166 6         57 my $indent = $2;
4167 6         23 $heredoc =~ s{^$indent}{}msg; # no /ox
4168             push @heredoc, $heredoc . qq{\n$delimiter\n};
4169             push @heredoc_delimiter, qq{\\s*$delimiter};
4170 6         15 }
4171             else {
4172 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4173             }
4174             return qq{<<'$delimiter'};
4175             }
4176              
4177             # <<~\HEREDOC
4178              
4179             # P.66 2.6.6. "Here" Documents
4180             # in Chapter 2: Bits and Pieces
4181             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
4182              
4183             # P.73 "Here" Documents
4184             # in Chapter 2: Bits and Pieces
4185             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
4186 6         26  
4187 3         9 elsif (/\G ( <<~ \\([a-zA-Z_0-9]+) ) /oxgc) {
4188 3         6 $slash = 'm//';
4189             my $here_quote = $1;
4190             my $delimiter = $2;
4191 3 50       30  
4192 3         14 # get here document
4193 3         18 if ($here_script eq '') {
4194             $here_script = CORE::substr $_, pos $_;
4195 3 50       19 $here_script =~ s/.*?\n//oxm;
4196 3         46 }
4197 3         9 if ($here_script =~ s/\A (.*?) \n ([\t ]*) $delimiter \n //xms) {
4198 3         5 my $heredoc = $1;
4199 3         46 my $indent = $2;
4200 3         10 $heredoc =~ s{^$indent}{}msg; # no /ox
4201             push @heredoc, $heredoc . qq{\n$delimiter\n};
4202             push @heredoc_delimiter, qq{\\s*$delimiter};
4203 3         9 }
4204             else {
4205 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4206             }
4207             return qq{<<\\$delimiter};
4208             }
4209              
4210 3         15 # <<~"HEREDOC"
4211 6         11 elsif (/\G ( <<~ [\t ]* "([a-zA-Z_0-9]*)" ) /oxgc) {
4212 6         12 $slash = 'm//';
4213             my $here_quote = $1;
4214             my $delimiter = $2;
4215 6 50       8  
4216 6         14 # get here document
4217 6         57 if ($here_script eq '') {
4218             $here_script = CORE::substr $_, pos $_;
4219 6 50       35 $here_script =~ s/.*?\n//oxm;
4220 6         55 }
4221 6         14 if ($here_script =~ s/\A (.*?) \n ([\t ]*) $delimiter \n //xms) {
4222 6         9 my $heredoc = $1;
4223 6         45 my $indent = $2;
4224 6         23 $heredoc =~ s{^$indent}{}msg; # no /ox
4225             push @heredoc, e_heredoc($heredoc) . qq{\n$delimiter\n};
4226             push @heredoc_delimiter, qq{\\s*$delimiter};
4227 6         15 }
4228             else {
4229 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4230             }
4231             return qq{<<"$delimiter"};
4232             }
4233              
4234 6         34 # <<~HEREDOC
4235 3         6 elsif (/\G ( <<~ ([a-zA-Z_0-9]+) ) /oxgc) {
4236 3         7 $slash = 'm//';
4237             my $here_quote = $1;
4238             my $delimiter = $2;
4239 3 50       5  
4240 3         20 # get here document
4241 3         15 if ($here_script eq '') {
4242             $here_script = CORE::substr $_, pos $_;
4243 3 50       17 $here_script =~ s/.*?\n//oxm;
4244 3         64 }
4245 3         9 if ($here_script =~ s/\A (.*?) \n ([\t ]*) $delimiter \n //xms) {
4246 3         5 my $heredoc = $1;
4247 3         62 my $indent = $2;
4248 3         12 $heredoc =~ s{^$indent}{}msg; # no /ox
4249             push @heredoc, e_heredoc($heredoc) . qq{\n$delimiter\n};
4250             push @heredoc_delimiter, qq{\\s*$delimiter};
4251 3         9 }
4252             else {
4253 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4254             }
4255             return qq{<<$delimiter};
4256             }
4257              
4258 3         14 # <<~`HEREDOC`
4259 6         12 elsif (/\G ( <<~ [\t ]* `([a-zA-Z_0-9]*)` ) /oxgc) {
4260 6         9 $slash = 'm//';
4261             my $here_quote = $1;
4262             my $delimiter = $2;
4263 6 50       23  
4264 6         19 # get here document
4265 6         18 if ($here_script eq '') {
4266             $here_script = CORE::substr $_, pos $_;
4267 6 50       38 $here_script =~ s/.*?\n//oxm;
4268 6         57 }
4269 6         13 if ($here_script =~ s/\A (.*?) \n ([\t ]*) $delimiter \n //xms) {
4270 6         10 my $heredoc = $1;
4271 6         136 my $indent = $2;
4272 6         20 $heredoc =~ s{^$indent}{}msg; # no /ox
4273             push @heredoc, e_heredoc($heredoc) . qq{\n$delimiter\n};
4274             push @heredoc_delimiter, qq{\\s*$delimiter};
4275 6         12 }
4276             else {
4277 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4278             }
4279             return qq{<<`$delimiter`};
4280             }
4281              
4282 6         26 # <<'HEREDOC'
4283 72         134 elsif (/\G ( << '([a-zA-Z_0-9]*)' ) /oxgc) {
4284 72         168 $slash = 'm//';
4285             my $here_quote = $1;
4286             my $delimiter = $2;
4287 72 50       141  
4288 72         130 # get here document
4289 72         387 if ($here_script eq '') {
4290             $here_script = CORE::substr $_, pos $_;
4291 72 50       421 $here_script =~ s/.*?\n//oxm;
4292 72         1196 }
4293 72         239 if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4294             push @heredoc, $1 . qq{\n$delimiter\n};
4295             push @heredoc_delimiter, $delimiter;
4296 72         128 }
4297             else {
4298 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4299             }
4300             return $here_quote;
4301             }
4302              
4303             # <<\HEREDOC
4304              
4305             # P.66 2.6.6. "Here" Documents
4306             # in Chapter 2: Bits and Pieces
4307             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
4308              
4309             # P.73 "Here" Documents
4310             # in Chapter 2: Bits and Pieces
4311             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
4312 72         277  
4313 0         0 elsif (/\G ( << \\([a-zA-Z_0-9]+) ) /oxgc) {
4314 0         0 $slash = 'm//';
4315             my $here_quote = $1;
4316             my $delimiter = $2;
4317 0 0       0  
4318 0         0 # get here document
4319 0         0 if ($here_script eq '') {
4320             $here_script = CORE::substr $_, pos $_;
4321 0 0       0 $here_script =~ s/.*?\n//oxm;
4322 0         0 }
4323 0         0 if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4324             push @heredoc, $1 . qq{\n$delimiter\n};
4325             push @heredoc_delimiter, $delimiter;
4326 0         0 }
4327             else {
4328 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4329             }
4330             return $here_quote;
4331             }
4332              
4333 0         0 # <<"HEREDOC"
4334 36         97 elsif (/\G ( << "([a-zA-Z_0-9]*)" ) /oxgc) {
4335 36         87 $slash = 'm//';
4336             my $here_quote = $1;
4337             my $delimiter = $2;
4338 36 50       505  
4339 36         141 # get here document
4340 36         265 if ($here_script eq '') {
4341             $here_script = CORE::substr $_, pos $_;
4342 36 50       274 $here_script =~ s/.*?\n//oxm;
4343 36         808 }
4344 36         132 if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4345             push @heredoc, e_heredoc($1) . qq{\n$delimiter\n};
4346             push @heredoc_delimiter, $delimiter;
4347 36         154 }
4348             else {
4349 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4350             }
4351             return $here_quote;
4352             }
4353              
4354 36         146 # <
4355 42         102 elsif (/\G ( << ([a-zA-Z_0-9]+) ) /oxgc) {
4356 42         103 $slash = 'm//';
4357             my $here_quote = $1;
4358             my $delimiter = $2;
4359 42 50       84  
4360 42         120 # get here document
4361 42         409 if ($here_script eq '') {
4362             $here_script = CORE::substr $_, pos $_;
4363 42 50       359 $here_script =~ s/.*?\n//oxm;
4364 42         699 }
4365 42         172 if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4366             push @heredoc, e_heredoc($1) . qq{\n$delimiter\n};
4367             push @heredoc_delimiter, $delimiter;
4368 42         107 }
4369             else {
4370 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4371             }
4372             return $here_quote;
4373             }
4374              
4375 42         188 # <<`HEREDOC`
4376 0         0 elsif (/\G ( << `([a-zA-Z_0-9]*)` ) /oxgc) {
4377 0         0 $slash = 'm//';
4378             my $here_quote = $1;
4379             my $delimiter = $2;
4380 0 0       0  
4381 0         0 # get here document
4382 0         0 if ($here_script eq '') {
4383             $here_script = CORE::substr $_, pos $_;
4384 0 0       0 $here_script =~ s/.*?\n//oxm;
4385 0         0 }
4386 0         0 if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4387             push @heredoc, e_heredoc($1) . qq{\n$delimiter\n};
4388             push @heredoc_delimiter, $delimiter;
4389 0         0 }
4390             else {
4391 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4392             }
4393             return $here_quote;
4394             }
4395              
4396 0         0 # <<= <=> <= < operator
4397             elsif (/\G ( <<= | <=> | <= | < ) (?= (?>\s*) [A-Za-z_0-9'"`\$\@\&\*\(\+\-] )/oxgc) {
4398             return $1;
4399             }
4400              
4401 12         61 #
4402             elsif (/\G (<[\$]?[A-Za-z_][A-Za-z_0-9]*>) /oxgc) {
4403             return $1;
4404             }
4405              
4406             # --- glob
4407              
4408             # avoid "Error: Runtime exception" of perl version 5.005_03
4409 0         0  
4410             elsif (/\G < ((?:[^>\0\a\e\f\n\r\t])+?) > /oxgc) {
4411             return 'Ecyrillic::glob("' . $1 . '")';
4412             }
4413 0         0  
4414             # __DATA__
4415             elsif (/\G ^ ( __DATA__ \n .*) \z /oxmsgc) { return $1; }
4416 0         0  
4417             # __END__
4418             elsif (/\G ^ ( __END__ \n .*) \z /oxmsgc) { return $1; }
4419              
4420             # \cD Control-D
4421              
4422             # P.68 2.6.8. Other Literal Tokens
4423             # in Chapter 2: Bits and Pieces
4424             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
4425              
4426             # P.76 Other Literal Tokens
4427             # in Chapter 2: Bits and Pieces
4428 204         1471 # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
4429              
4430             elsif (/\G ( \cD .*) \z /oxmsgc) { return $1; }
4431 0         0  
4432             # \cZ Control-Z
4433             elsif (/\G ( \cZ .*) \z /oxmsgc) { return $1; }
4434              
4435             # any operator before div
4436             elsif (/\G (
4437             -- | \+\+ |
4438 0         0 [\)\}\]]
  5083         10059  
4439              
4440             ) /oxgc) { $slash = 'div'; return $1; }
4441              
4442             # yada-yada or triple-dot operator
4443             elsif (/\G (
4444 5083         22451 \.\.\.
  7         12  
4445              
4446             ) /oxgc) { $slash = 'm//'; return q{die('Unimplemented')}; }
4447              
4448             # any operator before m//
4449              
4450             # //, //= (defined-or)
4451              
4452             # P.164 Logical Operators
4453             # in Chapter 10: More Control Structures
4454             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
4455              
4456             # P.119 C-Style Logical (Short-Circuit) Operators
4457             # in Chapter 3: Unary and Binary Operators
4458             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
4459              
4460             # (and so on)
4461              
4462             # ~~
4463              
4464             # P.221 The Smart Match Operator
4465             # in Chapter 15: Smart Matching and given-when
4466             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
4467              
4468             # P.112 Smartmatch Operator
4469             # in Chapter 3: Unary and Binary Operators
4470             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
4471              
4472             # (and so on)
4473              
4474             elsif (/\G ((?>
4475              
4476             !~~ | !~ | != | ! |
4477             %= | % |
4478             &&= | && | &= | &\.= | &\. | & |
4479             -= | -> | - |
4480             :(?>\s*)= |
4481             : |
4482             <<>> |
4483             <<= | <=> | <= | < |
4484             == | => | =~ | = |
4485             >>= | >> | >= | > |
4486             \*\*= | \*\* | \*= | \* |
4487             \+= | \+ |
4488             \.\. | \.= | \. |
4489             \/\/= | \/\/ |
4490             \/= | \/ |
4491             \? |
4492             \\ |
4493             \^= | \^\.= | \^\. | \^ |
4494             \b x= |
4495             \|\|= | \|\| | \|= | \|\.= | \|\. | \| |
4496             ~~ | ~\. | ~ |
4497             \b(?: and | cmp | eq | ge | gt | le | lt | ne | not | or | xor | x )\b |
4498             \b(?: print )\b |
4499              
4500 7         23 [,;\(\{\[]
  8885         16764  
4501              
4502             )) /oxgc) { $slash = 'm//'; return $1; }
4503 8885         38770  
  15413         28841  
4504             # other any character
4505             elsif (/\G ($q_char) /oxgc) { $slash = 'div'; return $1; }
4506              
4507 15413         67461 # system error
4508             else {
4509             die __FILE__, ": Oops, this shouldn't happen!\n";
4510             }
4511             }
4512              
4513 0     1788 0 0 # escape Cyrillic string
4514 1788         4718 sub e_string {
4515             my($string) = @_;
4516 1788         2581 my $e_string = '';
4517              
4518             local $slash = 'm//';
4519              
4520             # P.1024 Appendix W.10 Multibyte Processing
4521             # of ISBN 1-56592-224-7 CJKV Information Processing
4522 1788         2619 # (and so on)
4523              
4524             my @char = $string =~ / \G (?>[^\\]|\\$q_char|$q_char) /oxmsg;
4525 1788 100 66     13142  
4526 1788 50       8735 # without { ... }
4527 1769         4199 if (not (grep(/\A \{ \z/xms, @char) and grep(/\A \} \z/xms, @char))) {
4528             if ($string !~ /<
4529             return $string;
4530             }
4531             }
4532 1769         4582  
4533 19 50       173 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          
4534             while ($string !~ /\G \z/oxgc) {
4535             if (0) {
4536             }
4537 223         3936  
4538 0         0 # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> @{[Ecyrillic::PREMATCH()]}
4539 0         0 elsif ($string =~ /\G ( \$` | \$\{`\} | \$ (?>\s*) PREMATCH \b | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} ) /oxmsgc) {
4540             $e_string .= q{Ecyrillic::PREMATCH()};
4541             $slash = 'div';
4542             }
4543              
4544 0         0 # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> @{[Ecyrillic::MATCH()]}
4545 0         0 elsif ($string =~ /\G ( \$& | \$\{&\} | \$ (?>\s*) MATCH \b | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} ) /oxmsgc) {
4546             $e_string .= q{Ecyrillic::MATCH()};
4547             $slash = 'div';
4548             }
4549              
4550 0         0 # $', ${'} --> $', ${'}
4551 0         0 elsif ($string =~ /\G ( \$' | \$\{'\} ) /oxmsgc) {
4552             $e_string .= $1;
4553             $slash = 'div';
4554             }
4555              
4556 0         0 # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> @{[Ecyrillic::POSTMATCH()]}
4557 0         0 elsif ($string =~ /\G ( \$ (?>\s*) POSTMATCH \b | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} ) /oxmsgc) {
4558             $e_string .= q{Ecyrillic::POSTMATCH()};
4559             $slash = 'div';
4560             }
4561              
4562 0         0 # bareword
4563 0         0 elsif ($string =~ /\G ( \{ (?>\s*) (?: tr | index | rindex | reverse ) (?>\s*) \} ) /oxmsgc) {
4564             $e_string .= $1;
4565             $slash = 'div';
4566             }
4567              
4568 0         0 # $0 --> $0
4569 0         0 elsif ($string =~ /\G ( \$ 0 ) /oxmsgc) {
4570             $e_string .= $1;
4571             $slash = 'div';
4572 0         0 }
4573 0         0 elsif ($string =~ /\G ( \$ \{ (?>\s*) 0 (?>\s*) \} ) /oxmsgc) {
4574             $e_string .= $1;
4575             $slash = 'div';
4576             }
4577              
4578 0         0 # $$ --> $$
4579 0         0 elsif ($string =~ /\G ( \$ \$ ) (?![\w\{]) /oxmsgc) {
4580             $e_string .= $1;
4581             $slash = 'div';
4582             }
4583              
4584             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
4585 0         0 # $1, $2, $3 --> $1, $2, $3 otherwise
4586 0         0 elsif ($string =~ /\G \$ ((?>[1-9][0-9]*)) /oxmsgc) {
4587             $e_string .= e_capture($1);
4588             $slash = 'div';
4589 0         0 }
4590 0         0 elsif ($string =~ /\G \$ \{ (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} /oxmsgc) {
4591             $e_string .= e_capture($1);
4592             $slash = 'div';
4593             }
4594              
4595 0         0 # $$foo[ ... ] --> $ $foo->[ ... ]
4596 0         0 elsif ($string =~ /\G \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \[ .+? \] ) /oxmsgc) {
4597             $e_string .= e_capture($1.'->'.$2);
4598             $slash = 'div';
4599             }
4600              
4601 0         0 # $$foo{ ... } --> $ $foo->{ ... }
4602 0         0 elsif ($string =~ /\G \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \{ .+? \} ) /oxmsgc) {
4603             $e_string .= e_capture($1.'->'.$2);
4604             $slash = 'div';
4605             }
4606              
4607 0         0 # $$foo
4608 0         0 elsif ($string =~ /\G \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) /oxmsgc) {
4609             $e_string .= e_capture($1);
4610             $slash = 'div';
4611             }
4612              
4613 0         0 # ${ foo }
4614 0         0 elsif ($string =~ /\G \$ (?>\s*) \{ ((?> \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* )) \} /oxmsgc) {
4615             $e_string .= '${' . $1 . '}';
4616             $slash = 'div';
4617             }
4618              
4619 0         0 # ${ ... }
4620 3         11 elsif ($string =~ /\G \$ (?>\s*) \{ (?>\s*) ( $qq_brace ) (?>\s*) \} /oxmsgc) {
4621             $e_string .= e_capture($1);
4622             $slash = 'div';
4623             }
4624              
4625             # variable or function
4626 3         15 # $ @ % & * $ #
4627 7         20 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) {
4628             $e_string .= $1;
4629             $slash = 'div';
4630             }
4631             # $ $ $ $ $ $ $ $ $ $ $ $ $ $
4632 7         25 # $ @ # \ ' " / ? ( ) [ ] < >
4633 0         0 elsif ($string =~ /\G ( \$[\$\@\#\\\'\"\/\?\(\)\[\]\<\>] ) /oxmsgc) {
4634             $e_string .= $1;
4635             $slash = 'div';
4636             }
4637              
4638 0         0 # qq//
4639 0 0       0 elsif ($string =~ /\G \b (qq) \b /oxgc) {
4640 0         0 my $ope = $1;
4641             if ($string =~ /\G (\#) ((?:$qq_char)*?) (\#) /oxgc) { # qq# #
4642             $e_string .= e_qq($ope,$1,$3,$2);
4643 0         0 }
4644 0         0 else {
4645 0 0       0 my $e = '';
  0 0       0  
    0          
    0          
    0          
    0          
4646 0         0 while ($string !~ /\G \z/oxgc) {
  0         0  
4647 0         0 if ($string =~ /\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0         0  
4648 0         0 elsif ($string =~ /\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qq ( )
  0         0  
4649 0         0 elsif ($string =~ /\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qq { }
  0         0  
4650 0         0 elsif ($string =~ /\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qq [ ]
  0         0  
4651             elsif ($string =~ /\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qq < >
4652 0         0 elsif ($string =~ /\G (\S) ((?:$qq_char)*?) (\1) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qq * *
4653             }
4654             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4655             }
4656             }
4657              
4658 0         0 # qx//
4659 0 0       0 elsif ($string =~ /\G \b (qx) \b /oxgc) {
4660 0         0 my $ope = $1;
4661             if ($string =~ /\G (\#) ((?:$qq_char)*?) (\#) /oxgc) { # qx# #
4662             $e_string .= e_qq($ope,$1,$3,$2);
4663 0         0 }
4664 0         0 else {
4665 0 0       0 my $e = '';
  0 0       0  
    0          
    0          
    0          
    0          
    0          
4666 0         0 while ($string !~ /\G \z/oxgc) {
  0         0  
4667 0         0 if ($string =~ /\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0         0  
4668 0         0 elsif ($string =~ /\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qx ( )
  0         0  
4669 0         0 elsif ($string =~ /\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qx { }
  0         0  
4670 0         0 elsif ($string =~ /\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qx [ ]
  0         0  
4671 0         0 elsif ($string =~ /\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qx < >
  0         0  
4672             elsif ($string =~ /\G (\') ((?:$qq_char)*?) (\') /oxgc) { $e_string .= $e . e_q ($ope,$1,$3,$2); next E_STRING_LOOP; } # qx ' '
4673 0         0 elsif ($string =~ /\G (\S) ((?:$qq_char)*?) (\1) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qx * *
4674             }
4675             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4676             }
4677             }
4678              
4679 0         0 # q//
4680 0 0       0 elsif ($string =~ /\G \b (q) \b /oxgc) {
4681 0         0 my $ope = $1;
4682             if ($string =~ /\G (\#) ((?:\\\#|\\\\|$q_char)*?) (\#) /oxgc) { # q# #
4683             $e_string .= e_q($ope,$1,$3,$2);
4684 0         0 }
4685 0         0 else {
4686 0 0       0 my $e = '';
  0 0       0  
    0          
    0          
    0          
    0          
4687 0         0 while ($string !~ /\G \z/oxgc) {
  0         0  
4688 0         0 if ($string =~ /\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0         0  
4689 0         0 elsif ($string =~ /\G (\() ((?:\\\\|\\\)|\\\(|$q_paren)*?) (\)) /oxgc) { $e_string .= $e . e_q($ope,$1,$3,$2); next E_STRING_LOOP; } # q ( )
  0         0  
4690 0         0 elsif ($string =~ /\G (\{) ((?:\\\\|\\\}|\\\{|$q_brace)*?) (\}) /oxgc) { $e_string .= $e . e_q($ope,$1,$3,$2); next E_STRING_LOOP; } # q { }
  0         0  
4691 0         0 elsif ($string =~ /\G (\[) ((?:\\\\|\\\]|\\\[|$q_bracket)*?) (\]) /oxgc) { $e_string .= $e . e_q($ope,$1,$3,$2); next E_STRING_LOOP; } # q [ ]
  0         0  
4692             elsif ($string =~ /\G (\<) ((?:\\\\|\\\>|\\\<|$q_angle)*?) (\>) /oxgc) { $e_string .= $e . e_q($ope,$1,$3,$2); next E_STRING_LOOP; } # q < >
4693 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 * *
4694             }
4695             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4696             }
4697             }
4698 0         0  
4699             # ''
4700             elsif ($string =~ /\G (?
4701 0         0  
4702             # ""
4703             elsif ($string =~ /\G (\") ((?:$qq_char)*?) (\") /oxgc) { $e_string .= e_qq('',$1,$3,$2); }
4704 0         0  
4705             # ``
4706             elsif ($string =~ /\G (\`) ((?:$qq_char)*?) (\`) /oxgc) { $e_string .= e_qq('',$1,$3,$2); }
4707 0         0  
4708             # other any character
4709             elsif ($string =~ /\G ($q_char) /oxgc) { $e_string .= $1; }
4710              
4711 213         522 # system error
4712             else {
4713             die __FILE__, ": Oops, this shouldn't happen!\n";
4714             }
4715 0         0 }
4716              
4717             return $e_string;
4718             }
4719              
4720             #
4721             # character class
4722 19     1919 0 79 #
4723             sub character_class {
4724 1919 100       3262 my($char,$modifier) = @_;
4725 1919 100       2862  
4726 52         94 if ($char eq '.') {
4727             if ($modifier =~ /s/) {
4728             return '${Ecyrillic::dot_s}';
4729 17         36 }
4730             else {
4731             return '${Ecyrillic::dot}';
4732             }
4733 35         84 }
4734             else {
4735             return Ecyrillic::classic_character_class($char);
4736             }
4737             }
4738              
4739             #
4740             # escape capture ($1, $2, $3, ...)
4741             #
4742 1867     212 0 3181 sub e_capture {
4743              
4744             return join '', '${', $_[0], '}';
4745             }
4746              
4747             #
4748             # escape transliteration (tr/// or y///)
4749 212     3 0 1084 #
4750 3         11 sub e_tr {
4751 3   50     5 my($variable,$charclass,$e,$charclass2,$modifier) = @_;
4752             my $e_tr = '';
4753 3         5 $modifier ||= '';
4754              
4755             $slash = 'div';
4756 3         6  
4757             # quote character class 1
4758             $charclass = q_tr($charclass);
4759 3         5  
4760             # quote character class 2
4761             $charclass2 = q_tr($charclass2);
4762 3 50       29  
4763 3 0       9 # /b /B modifier
4764 0         0 if ($modifier =~ tr/bB//d) {
4765             if ($variable eq '') {
4766             $e_tr = qq{tr$charclass$e$charclass2$modifier};
4767 0         0 }
4768             else {
4769             $e_tr = qq{$variable${bind_operator}tr$charclass$e$charclass2$modifier};
4770             }
4771 0 100       0 }
4772 3         7 else {
4773             if ($variable eq '') {
4774             $e_tr = qq{Ecyrillic::tr(\$_,' =~ ',$charclass,$e$charclass2,'$modifier')};
4775 2         17 }
4776             else {
4777             $e_tr = qq{Ecyrillic::tr($variable,'$bind_operator',$charclass,$e$charclass2,'$modifier')};
4778             }
4779             }
4780 1         5  
4781 3         6 # clear tr/// variable
4782             $tr_variable = '';
4783 3         3 $bind_operator = '';
4784              
4785             return $e_tr;
4786             }
4787              
4788             #
4789             # quote for escape transliteration (tr/// or y///)
4790 3     6 0 17 #
4791             sub q_tr {
4792             my($charclass) = @_;
4793 6 50       11  
    0          
    0          
    0          
    0          
    0          
4794 6         11 # quote character class
4795             if ($charclass !~ /'/oxms) {
4796             return e_q('', "'", "'", $charclass); # --> q' '
4797 6         8 }
4798             elsif ($charclass !~ /\//oxms) {
4799             return e_q('q', '/', '/', $charclass); # --> q/ /
4800 0         0 }
4801             elsif ($charclass !~ /\#/oxms) {
4802             return e_q('q', '#', '#', $charclass); # --> q# #
4803 0         0 }
4804             elsif ($charclass !~ /[\<\>]/oxms) {
4805             return e_q('q', '<', '>', $charclass); # --> q< >
4806 0         0 }
4807             elsif ($charclass !~ /[\(\)]/oxms) {
4808             return e_q('q', '(', ')', $charclass); # --> q( )
4809 0         0 }
4810             elsif ($charclass !~ /[\{\}]/oxms) {
4811             return e_q('q', '{', '}', $charclass); # --> q{ }
4812 0         0 }
4813 0 0       0 else {
4814 0         0 for my $char (qw( ! " $ % & * + . : = ? @ ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
4815             if ($charclass !~ /\Q$char\E/xms) {
4816             return e_q('q', $char, $char, $charclass);
4817             }
4818             }
4819 0         0 }
4820              
4821             return e_q('q', '{', '}', $charclass);
4822             }
4823              
4824             #
4825             # escape q string (q//, '')
4826 0     1264 0 0 #
4827             sub e_q {
4828 1264         3025 my($ope,$delimiter,$end_delimiter,$string) = @_;
4829              
4830 1264         2136 $slash = 'div';
4831              
4832             return join '', $ope, $delimiter, $string, $end_delimiter;
4833             }
4834              
4835             #
4836             # escape qq string (qq//, "", qx//, ``)
4837 1264     4124 0 6012 #
4838             sub e_qq {
4839 4124         9525 my($ope,$delimiter,$end_delimiter,$string) = @_;
4840              
4841 4124         5229 $slash = 'div';
4842 4124         4833  
4843             my $left_e = 0;
4844             my $right_e = 0;
4845 4124         4484  
4846             # split regexp
4847             my @char = $string =~ /\G((?>
4848             [^\\\$] |
4849             \\x\{ (?>[0-9A-Fa-f]+) \} |
4850             \\o\{ (?>[0-7]+) \} |
4851             \\N\{ (?>[^0-9\}][^\}]*) \} |
4852             \\ $q_char |
4853             \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} |
4854             \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} |
4855             \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} |
4856             \$ (?>\s* [0-9]+) |
4857             \$ (?>\s*) \{ (?>\s* [0-9]+ \s*) \} |
4858             \$ \$ (?![\w\{]) |
4859             \$ (?>\s*) \$ (?>\s*) $qq_variable |
4860             $q_char
4861 4124         132870 ))/oxmsg;
4862              
4863             for (my $i=0; $i <= $#char; $i++) {
4864 4124 50 33     12339  
    50 33        
    100          
    100          
    50          
4865 114256         375202 # "\L\u" --> "\u\L"
4866             if (($char[$i] eq '\L') and ($char[$i+1] eq '\u')) {
4867             @char[$i,$i+1] = @char[$i+1,$i];
4868             }
4869              
4870 0         0 # "\U\l" --> "\l\U"
4871             elsif (($char[$i] eq '\U') and ($char[$i+1] eq '\l')) {
4872             @char[$i,$i+1] = @char[$i+1,$i];
4873             }
4874              
4875 0         0 # octal escape sequence
4876             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
4877             $char[$i] = Ecyrillic::octchr($1);
4878             }
4879              
4880 1         4 # hexadecimal escape sequence
4881             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
4882             $char[$i] = Ecyrillic::hexchr($1);
4883             }
4884              
4885 1         4 # \N{CHARNAME} --> N{CHARNAME}
4886             elsif ($char[$i] =~ /\A \\ ( N\{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
4887             $char[$i] = $1;
4888 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          
4889              
4890             if (0) {
4891             }
4892              
4893             # \F
4894             #
4895             # P.69 Table 2-6. Translation escapes
4896             # in Chapter 2: Bits and Pieces
4897             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
4898             # (and so on)
4899 114256         894109  
4900 0 50       0 # \u \l \U \L \F \Q \E
4901 484         1031 elsif ($char[$i] =~ /\A ([<>]) \z/oxms) {
4902             if ($right_e < $left_e) {
4903             $char[$i] = '\\' . $char[$i];
4904             }
4905             }
4906             elsif ($char[$i] eq '\u') {
4907              
4908             # "STRING @{[ LIST EXPR ]} MORE STRING"
4909              
4910             # P.257 Other Tricks You Can Do with Hard References
4911             # in Chapter 8: References
4912             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
4913              
4914             # P.353 Other Tricks You Can Do with Hard References
4915             # in Chapter 8: References
4916             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
4917              
4918 0         0 # (and so on)
4919 0         0  
4920             $char[$i] = '@{[Ecyrillic::ucfirst qq<';
4921             $left_e++;
4922 0         0 }
4923 0         0 elsif ($char[$i] eq '\l') {
4924             $char[$i] = '@{[Ecyrillic::lcfirst qq<';
4925             $left_e++;
4926 0         0 }
4927 0         0 elsif ($char[$i] eq '\U') {
4928             $char[$i] = '@{[Ecyrillic::uc qq<';
4929             $left_e++;
4930 0         0 }
4931 0         0 elsif ($char[$i] eq '\L') {
4932             $char[$i] = '@{[Ecyrillic::lc qq<';
4933             $left_e++;
4934 0         0 }
4935 24         34 elsif ($char[$i] eq '\F') {
4936             $char[$i] = '@{[Ecyrillic::fc qq<';
4937             $left_e++;
4938 24         43 }
4939 0         0 elsif ($char[$i] eq '\Q') {
4940             $char[$i] = '@{[CORE::quotemeta qq<';
4941             $left_e++;
4942 0 50       0 }
4943 24         40 elsif ($char[$i] eq '\E') {
4944 24         28 if ($right_e < $left_e) {
4945             $char[$i] = '>]}';
4946             $right_e++;
4947 24         46 }
4948             else {
4949             $char[$i] = '';
4950             }
4951 0         0 }
4952 0 0       0 elsif ($char[$i] eq '\Q') {
4953 0         0 while (1) {
4954             if (++$i > $#char) {
4955 0 0       0 last;
4956 0         0 }
4957             if ($char[$i] eq '\E') {
4958             last;
4959             }
4960             }
4961             }
4962             elsif ($char[$i] eq '\E') {
4963             }
4964              
4965             # $0 --> $0
4966             elsif ($char[$i] =~ /\A \$ 0 \z/oxms) {
4967             }
4968             elsif ($char[$i] =~ /\A \$ \{ (?>\s*) 0 (?>\s*) \} \z/oxms) {
4969             }
4970              
4971             # $$ --> $$
4972             elsif ($char[$i] =~ /\A \$\$ \z/oxms) {
4973             }
4974              
4975             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
4976 0         0 # $1, $2, $3 --> $1, $2, $3 otherwise
4977             elsif ($char[$i] =~ /\A \$ ((?>[1-9][0-9]*)) \z/oxms) {
4978             $char[$i] = e_capture($1);
4979 205         387 }
4980             elsif ($char[$i] =~ /\A \$ \{ (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} \z/oxms) {
4981             $char[$i] = e_capture($1);
4982             }
4983              
4984 0         0 # $$foo[ ... ] --> $ $foo->[ ... ]
4985             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \[ (?:$qq_bracket)*? \] ) \z/oxms) {
4986             $char[$i] = e_capture($1.'->'.$2);
4987             }
4988              
4989 0         0 # $$foo{ ... } --> $ $foo->{ ... }
4990             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \{ (?:$qq_brace)*? \} ) \z/oxms) {
4991             $char[$i] = e_capture($1.'->'.$2);
4992             }
4993              
4994 0         0 # $$foo
4995             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) \z/oxms) {
4996             $char[$i] = e_capture($1);
4997             }
4998              
4999 0         0 # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Ecyrillic::PREMATCH()
5000             elsif ($char[$i] =~ /\A ( \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} ) \z/oxmsgc) {
5001             $char[$i] = '@{[Ecyrillic::PREMATCH()]}';
5002             }
5003              
5004 44         125 # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Ecyrillic::MATCH()
5005             elsif ($char[$i] =~ /\A ( \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} ) \z/oxmsgc) {
5006             $char[$i] = '@{[Ecyrillic::MATCH()]}';
5007             }
5008              
5009 45         110 # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Ecyrillic::POSTMATCH()
5010             elsif ($char[$i] =~ /\A ( \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} ) \z/oxmsgc) {
5011             $char[$i] = '@{[Ecyrillic::POSTMATCH()]}';
5012             }
5013              
5014             # ${ foo } --> ${ foo }
5015             elsif ($char[$i] =~ /\A \$ (?>\s*) \{ (?> \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* ) \} \z/oxms) {
5016             }
5017              
5018 33         89 # ${ ... }
5019             elsif ($char[$i] =~ /\A \$ (?>\s*) \{ ( .+ ) \} \z/oxms) {
5020             $char[$i] = e_capture($1);
5021             }
5022             }
5023 0 50       0  
5024 4124         7318 # return string
5025             if ($left_e > $right_e) {
5026 0         0 return join '', $ope, $delimiter, @char, '>]}' x ($left_e - $right_e), $end_delimiter;
5027             }
5028             return join '', $ope, $delimiter, @char, $end_delimiter;
5029             }
5030              
5031             #
5032             # escape qw string (qw//)
5033 4124     16 0 32564 #
5034             sub e_qw {
5035 16         121 my($ope,$delimiter,$end_delimiter,$string) = @_;
5036              
5037             $slash = 'div';
5038 16         51  
  16         235  
5039 483 50       880 # choice again delimiter
    0          
    0          
    0          
    0          
5040 16         100 my %octet = map {$_ => 1} ($string =~ /\G ([\x00-\xFF]) /oxmsg);
5041             if (not $octet{$end_delimiter}) {
5042             return join '', $ope, $delimiter, $string, $end_delimiter;
5043 16         134 }
5044             elsif (not $octet{')'}) {
5045             return join '', $ope, '(', $string, ')';
5046 0         0 }
5047             elsif (not $octet{'}'}) {
5048             return join '', $ope, '{', $string, '}';
5049 0         0 }
5050             elsif (not $octet{']'}) {
5051             return join '', $ope, '[', $string, ']';
5052 0         0 }
5053             elsif (not $octet{'>'}) {
5054             return join '', $ope, '<', $string, '>';
5055 0         0 }
5056 0 0       0 else {
5057 0         0 for my $char (qw( ! " $ % & * + - . / : = ? @ ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
5058             if (not $octet{$char}) {
5059             return join '', $ope, $char, $string, $char;
5060             }
5061             }
5062             }
5063 0         0  
5064 0         0 # qw/AAA BBB C'CC/ --> ('AAA', 'BBB', 'C\'CC')
5065 0         0 my @string = CORE::split(/\s+/, $string);
5066 0         0 for my $string (@string) {
5067 0 0       0 my @octet = $string =~ /\G ([\x00-\xFF]) /oxmsg;
5068 0         0 for my $octet (@octet) {
5069             if ($octet =~ /\A (['\\]) \z/oxms) {
5070             $octet = '\\' . $1;
5071 0         0 }
5072             }
5073 0         0 $string = join '', @octet;
  0         0  
5074             }
5075             return join '', '(', (join ', ', map { "'$_'" } @string), ')';
5076             }
5077              
5078             #
5079             # escape here document (<<"HEREDOC", <
5080 0     93 0 0 #
5081             sub e_heredoc {
5082 93         276 my($string) = @_;
5083              
5084 93         153 $slash = 'm//';
5085              
5086 93         310 my $metachar = qr/[\@\\|]/oxms; # '|' is for <<`HEREDOC`
5087 93         174  
5088             my $left_e = 0;
5089             my $right_e = 0;
5090 93         149  
5091             # split regexp
5092             my @char = $string =~ /\G((?>
5093             [^\\\$] |
5094             \\x\{ (?>[0-9A-Fa-f]+) \} |
5095             \\o\{ (?>[0-7]+) \} |
5096             \\N\{ (?>[^0-9\}][^\}]*) \} |
5097             \\ $q_char |
5098             \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} |
5099             \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} |
5100             \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} |
5101             \$ (?>\s* [0-9]+) |
5102             \$ (?>\s*) \{ (?>\s* [0-9]+ \s*) \} |
5103             \$ \$ (?![\w\{]) |
5104             \$ (?>\s*) \$ (?>\s*) $qq_variable |
5105             $q_char
5106 93         8432 ))/oxmsg;
5107              
5108             for (my $i=0; $i <= $#char; $i++) {
5109 93 50 33     422  
    50 33        
    100          
    100          
    50          
5110 3229         10253 # "\L\u" --> "\u\L"
5111             if (($char[$i] eq '\L') and ($char[$i+1] eq '\u')) {
5112             @char[$i,$i+1] = @char[$i+1,$i];
5113             }
5114              
5115 0         0 # "\U\l" --> "\l\U"
5116             elsif (($char[$i] eq '\U') and ($char[$i+1] eq '\l')) {
5117             @char[$i,$i+1] = @char[$i+1,$i];
5118             }
5119              
5120 0         0 # octal escape sequence
5121             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
5122             $char[$i] = Ecyrillic::octchr($1);
5123             }
5124              
5125 1         3 # hexadecimal escape sequence
5126             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
5127             $char[$i] = Ecyrillic::hexchr($1);
5128             }
5129              
5130 1         3 # \N{CHARNAME} --> N{CHARNAME}
5131             elsif ($char[$i] =~ /\A \\ ( N\{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
5132             $char[$i] = $1;
5133 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          
5134              
5135             if (0) {
5136             }
5137 3229         26002  
5138 0 0       0 # \u \l \U \L \F \Q \E
5139 0         0 elsif ($char[$i] =~ /\A ([<>]) \z/oxms) {
5140             if ($right_e < $left_e) {
5141             $char[$i] = '\\' . $char[$i];
5142             }
5143 0         0 }
5144 0         0 elsif ($char[$i] eq '\u') {
5145             $char[$i] = '@{[Ecyrillic::ucfirst qq<';
5146             $left_e++;
5147 0         0 }
5148 0         0 elsif ($char[$i] eq '\l') {
5149             $char[$i] = '@{[Ecyrillic::lcfirst qq<';
5150             $left_e++;
5151 0         0 }
5152 0         0 elsif ($char[$i] eq '\U') {
5153             $char[$i] = '@{[Ecyrillic::uc qq<';
5154             $left_e++;
5155 0         0 }
5156 0         0 elsif ($char[$i] eq '\L') {
5157             $char[$i] = '@{[Ecyrillic::lc qq<';
5158             $left_e++;
5159 0         0 }
5160 0         0 elsif ($char[$i] eq '\F') {
5161             $char[$i] = '@{[Ecyrillic::fc qq<';
5162             $left_e++;
5163 0         0 }
5164 0         0 elsif ($char[$i] eq '\Q') {
5165             $char[$i] = '@{[CORE::quotemeta qq<';
5166             $left_e++;
5167 0 0       0 }
5168 0         0 elsif ($char[$i] eq '\E') {
5169 0         0 if ($right_e < $left_e) {
5170             $char[$i] = '>]}';
5171             $right_e++;
5172 0         0 }
5173             else {
5174             $char[$i] = '';
5175             }
5176 0         0 }
5177 0 0       0 elsif ($char[$i] eq '\Q') {
5178 0         0 while (1) {
5179             if (++$i > $#char) {
5180 0 0       0 last;
5181 0         0 }
5182             if ($char[$i] eq '\E') {
5183             last;
5184             }
5185             }
5186             }
5187             elsif ($char[$i] eq '\E') {
5188             }
5189              
5190             # $0 --> $0
5191             elsif ($char[$i] =~ /\A \$ 0 \z/oxms) {
5192             }
5193             elsif ($char[$i] =~ /\A \$ \{ (?>\s*) 0 (?>\s*) \} \z/oxms) {
5194             }
5195              
5196             # $$ --> $$
5197             elsif ($char[$i] =~ /\A \$\$ \z/oxms) {
5198             }
5199              
5200             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
5201 0         0 # $1, $2, $3 --> $1, $2, $3 otherwise
5202             elsif ($char[$i] =~ /\A \$ ((?>[1-9][0-9]*)) \z/oxms) {
5203             $char[$i] = e_capture($1);
5204 0         0 }
5205             elsif ($char[$i] =~ /\A \$ \{ (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} \z/oxms) {
5206             $char[$i] = e_capture($1);
5207             }
5208              
5209 0         0 # $$foo[ ... ] --> $ $foo->[ ... ]
5210             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \[ (?:$qq_bracket)*? \] ) \z/oxms) {
5211             $char[$i] = e_capture($1.'->'.$2);
5212             }
5213              
5214 0         0 # $$foo{ ... } --> $ $foo->{ ... }
5215             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \{ (?:$qq_brace)*? \} ) \z/oxms) {
5216             $char[$i] = e_capture($1.'->'.$2);
5217             }
5218              
5219 0         0 # $$foo
5220             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) \z/oxms) {
5221             $char[$i] = e_capture($1);
5222             }
5223              
5224 0         0 # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Ecyrillic::PREMATCH()
5225             elsif ($char[$i] =~ /\A ( \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} ) \z/oxmsgc) {
5226             $char[$i] = '@{[Ecyrillic::PREMATCH()]}';
5227             }
5228              
5229 8         49 # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Ecyrillic::MATCH()
5230             elsif ($char[$i] =~ /\A ( \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} ) \z/oxmsgc) {
5231             $char[$i] = '@{[Ecyrillic::MATCH()]}';
5232             }
5233              
5234 8         42 # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Ecyrillic::POSTMATCH()
5235             elsif ($char[$i] =~ /\A ( \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} ) \z/oxmsgc) {
5236             $char[$i] = '@{[Ecyrillic::POSTMATCH()]}';
5237             }
5238              
5239             # ${ foo } --> ${ foo }
5240             elsif ($char[$i] =~ /\A \$ (?>\s*) \{ (?> \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* ) \} \z/oxms) {
5241             }
5242              
5243 6         33 # ${ ... }
5244             elsif ($char[$i] =~ /\A \$ (?>\s*) \{ ( .+ ) \} \z/oxms) {
5245             $char[$i] = e_capture($1);
5246             }
5247             }
5248 0 50       0  
5249 93         199 # return string
5250             if ($left_e > $right_e) {
5251 0         0 return join '', @char, '>]}' x ($left_e - $right_e);
5252             }
5253             return join '', @char;
5254             }
5255              
5256             #
5257             # escape regexp (m//, qr//)
5258 93     652 0 738 #
5259 652   100     2571 sub e_qr {
5260             my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
5261 652         2477 $modifier ||= '';
5262 652 50       1080  
5263 652         1529 $modifier =~ tr/p//d;
5264 0         0 if ($modifier =~ /([adlu])/oxms) {
5265 0 0       0 my $line = 0;
5266 0         0 for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
5267 0         0 if ($filename ne __FILE__) {
5268             $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
5269             last;
5270 0         0 }
5271             }
5272             die qq{Unsupported modifier "$1" used at line $line.\n};
5273 0         0 }
5274              
5275             $slash = 'div';
5276 652 100       1162  
    100          
5277 652         1812 # literal null string pattern
5278 8         9 if ($string eq '') {
5279 8         11 $modifier =~ tr/bB//d;
5280             $modifier =~ tr/i//d;
5281             return join '', $ope, $delimiter, $end_delimiter, $modifier;
5282             }
5283              
5284             # /b /B modifier
5285             elsif ($modifier =~ tr/bB//d) {
5286 8 50       50  
5287 2         9 # choice again delimiter
5288 0         0 if ($delimiter =~ / [\@:] /oxms) {
  0         0  
5289 0 0       0 my @char = $string =~ /\G ([\x00-\xFF]) /oxmsg;
    0          
    0          
    0          
5290 0         0 my %octet = map {$_ => 1} @char;
5291 0         0 if (not $octet{')'}) {
5292             $delimiter = '(';
5293             $end_delimiter = ')';
5294 0         0 }
5295 0         0 elsif (not $octet{'}'}) {
5296             $delimiter = '{';
5297             $end_delimiter = '}';
5298 0         0 }
5299 0         0 elsif (not $octet{']'}) {
5300             $delimiter = '[';
5301             $end_delimiter = ']';
5302 0         0 }
5303 0         0 elsif (not $octet{'>'}) {
5304             $delimiter = '<';
5305             $end_delimiter = '>';
5306 0         0 }
5307 0 0       0 else {
5308 0         0 for my $char (qw( ! " $ % & * + - . / = ? ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
5309 0         0 if (not $octet{$char}) {
5310 0         0 $delimiter = $char;
5311             $end_delimiter = $char;
5312             last;
5313             }
5314             }
5315             }
5316 0 50 33     0 }
5317 2         13  
5318             if (($ope =~ /\A m? \z/oxms) and ($delimiter eq '?')) {
5319             return join '', $ope, $delimiter, $string, $matched, $end_delimiter, $modifier;
5320 0         0 }
5321             else {
5322             return join '', $ope, $delimiter, '(?:', $string, ')', $matched, $end_delimiter, $modifier;
5323             }
5324 2 100       12 }
5325 642         1387  
5326             my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
5327             my $metachar = qr/[\@\\|[\]{^]/oxms;
5328 642         2178  
5329             # split regexp
5330             my @char = $string =~ /\G((?>
5331             [^\\\$\@\[\(] |
5332             \\x (?>[0-9A-Fa-f]{1,2}) |
5333             \\ (?>[0-7]{2,3}) |
5334             \\c [\x40-\x5F] |
5335             \\x\{ (?>[0-9A-Fa-f]+) \} |
5336             \\o\{ (?>[0-7]+) \} |
5337             \\[bBNpP]\{ (?>[^0-9\}][^\}]*) \} |
5338             \\ $q_char |
5339             \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} |
5340             \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} |
5341             \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} |
5342             [\$\@] $qq_variable |
5343             \$ (?>\s* [0-9]+) |
5344             \$ (?>\s*) \{ (?>\s* [0-9]+ \s*) \} |
5345             \$ \$ (?![\w\{]) |
5346             \$ (?>\s*) \$ (?>\s*) $qq_variable |
5347             \[\^ |
5348             \[\: (?>[a-z]+) :\] |
5349             \[\:\^ (?>[a-z]+) :\] |
5350             \(\? |
5351             $q_char
5352             ))/oxmsg;
5353 642 50       61033  
5354 642         2575 # choice again delimiter
  0         0  
5355 0 0       0 if ($delimiter =~ / [\@:] /oxms) {
    0          
    0          
    0          
5356 0         0 my %octet = map {$_ => 1} @char;
5357 0         0 if (not $octet{')'}) {
5358             $delimiter = '(';
5359             $end_delimiter = ')';
5360 0         0 }
5361 0         0 elsif (not $octet{'}'}) {
5362             $delimiter = '{';
5363             $end_delimiter = '}';
5364 0         0 }
5365 0         0 elsif (not $octet{']'}) {
5366             $delimiter = '[';
5367             $end_delimiter = ']';
5368 0         0 }
5369 0         0 elsif (not $octet{'>'}) {
5370             $delimiter = '<';
5371             $end_delimiter = '>';
5372 0         0 }
5373 0 0       0 else {
5374 0         0 for my $char (qw( ! " $ % & * + - . / = ? ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
5375 0         0 if (not $octet{$char}) {
5376 0         0 $delimiter = $char;
5377             $end_delimiter = $char;
5378             last;
5379             }
5380             }
5381             }
5382 0         0 }
5383 642         986  
5384 642         850 my $left_e = 0;
5385             my $right_e = 0;
5386             for (my $i=0; $i <= $#char; $i++) {
5387 642 50 66     1568  
    50 66        
    100          
    100          
    100          
    100          
5388 1872         9169 # "\L\u" --> "\u\L"
5389             if (($char[$i] eq '\L') and ($char[$i+1] eq '\u')) {
5390             @char[$i,$i+1] = @char[$i+1,$i];
5391             }
5392              
5393 0         0 # "\U\l" --> "\l\U"
5394             elsif (($char[$i] eq '\U') and ($char[$i+1] eq '\l')) {
5395             @char[$i,$i+1] = @char[$i+1,$i];
5396             }
5397              
5398 0         0 # octal escape sequence
5399             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
5400             $char[$i] = Ecyrillic::octchr($1);
5401             }
5402              
5403 1         4 # hexadecimal escape sequence
5404             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
5405             $char[$i] = Ecyrillic::hexchr($1);
5406             }
5407              
5408             # \b{...} --> b\{...}
5409             # \B{...} --> B\{...}
5410             # \N{CHARNAME} --> N\{CHARNAME}
5411             # \p{PROPERTY} --> p\{PROPERTY}
5412 1         3 # \P{PROPERTY} --> P\{PROPERTY}
5413             elsif ($char[$i] =~ /\A \\ ([bBNpP]) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
5414             $char[$i] = $1 . '\\' . $2;
5415             }
5416              
5417 6         19 # \p, \P, \X --> p, P, X
5418             elsif ($char[$i] =~ /\A \\ ( [pPX] ) \z/oxms) {
5419             $char[$i] = $1;
5420 4 100 100     10 }
    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          
5421              
5422             if (0) {
5423             }
5424 1872         5265  
5425 0 50 33     0 # join separated multiple-octet
    50 33        
    50 33        
      33        
      66        
      33        
5426 6         94 elsif ($char[$i] =~ /\A (?: \\ [0-7]{2,3} | \\x [0-9A-Fa-f]{1,2}) \z/oxms) {
5427             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)) {
5428             $char[$i] .= join '', splice @char, $i+1, 3;
5429 0         0 }
5430             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)) {
5431             $char[$i] .= join '', splice @char, $i+1, 2;
5432 0         0 }
5433             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)) {
5434             $char[$i] .= join '', splice @char, $i+1, 1;
5435             }
5436             }
5437              
5438 0         0 # open character class [...]
5439             elsif ($char[$i] eq '[') {
5440             my $left = $i;
5441              
5442             # [] make die "Unmatched [] in regexp ...\n"
5443 328 100       438 # (and so on)
5444 328         807  
5445             if ($char[$i+1] eq ']') {
5446             $i++;
5447 3         5 }
5448 328 50       410  
5449 1379         2219 while (1) {
5450             if (++$i > $#char) {
5451 0 100       0 die __FILE__, ": Unmatched [] in regexp\n";
5452 1379         2196 }
5453             if ($char[$i] eq ']') {
5454             my $right = $i;
5455 328 100       406  
5456 328         1623 # [...]
  30         61  
5457             if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
5458             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);
5459 90         140 }
5460             else {
5461             splice @char, $left, $right-$left+1, Ecyrillic::charlist_qr(@char[$left+1..$right-1], $modifier);
5462 298         1224 }
5463 328         569  
5464             $i = $left;
5465             last;
5466             }
5467             }
5468             }
5469              
5470 328         863 # open character class [^...]
5471             elsif ($char[$i] eq '[^') {
5472             my $left = $i;
5473              
5474             # [^] make die "Unmatched [] in regexp ...\n"
5475 74 100       93 # (and so on)
5476 74         161  
5477             if ($char[$i+1] eq ']') {
5478             $i++;
5479 4         5 }
5480 74 50       105  
5481 272         387 while (1) {
5482             if (++$i > $#char) {
5483 0 100       0 die __FILE__, ": Unmatched [] in regexp\n";
5484 272         448 }
5485             if ($char[$i] eq ']') {
5486             my $right = $i;
5487 74 100       85  
5488 74         336 # [^...]
  30         65  
5489             if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
5490             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);
5491 90         133 }
5492             else {
5493             splice @char, $left, $right-$left+1, Ecyrillic::charlist_not_qr(@char[$left+1..$right-1], $modifier);
5494 44         186 }
5495 74         133  
5496             $i = $left;
5497             last;
5498             }
5499             }
5500             }
5501              
5502 74         174 # rewrite character class or escape character
5503             elsif (my $char = character_class($char[$i],$modifier)) {
5504             $char[$i] = $char;
5505             }
5506              
5507 139 50       454 # /i modifier
5508 20         33 elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Ecyrillic::uc($char[$i]) ne Ecyrillic::fc($char[$i]))) {
5509             if (CORE::length(Ecyrillic::fc($char[$i])) == 1) {
5510             $char[$i] = '[' . Ecyrillic::uc($char[$i]) . Ecyrillic::fc($char[$i]) . ']';
5511 20         33 }
5512             else {
5513             $char[$i] = '(?:' . Ecyrillic::uc($char[$i]) . '|' . Ecyrillic::fc($char[$i]) . ')';
5514             }
5515             }
5516              
5517 0 50       0 # \u \l \U \L \F \Q \E
5518 1         4 elsif ($char[$i] =~ /\A [<>] \z/oxms) {
5519             if ($right_e < $left_e) {
5520             $char[$i] = '\\' . $char[$i];
5521             }
5522 0         0 }
5523 0         0 elsif ($char[$i] eq '\u') {
5524             $char[$i] = '@{[Ecyrillic::ucfirst qq<';
5525             $left_e++;
5526 0         0 }
5527 0         0 elsif ($char[$i] eq '\l') {
5528             $char[$i] = '@{[Ecyrillic::lcfirst qq<';
5529             $left_e++;
5530 0         0 }
5531 1         3 elsif ($char[$i] eq '\U') {
5532             $char[$i] = '@{[Ecyrillic::uc qq<';
5533             $left_e++;
5534 1         4 }
5535 1         3 elsif ($char[$i] eq '\L') {
5536             $char[$i] = '@{[Ecyrillic::lc qq<';
5537             $left_e++;
5538 1         2 }
5539 18         42 elsif ($char[$i] eq '\F') {
5540             $char[$i] = '@{[Ecyrillic::fc qq<';
5541             $left_e++;
5542 18         36 }
5543 1         2 elsif ($char[$i] eq '\Q') {
5544             $char[$i] = '@{[CORE::quotemeta qq<';
5545             $left_e++;
5546 1 50       3 }
5547 21         41 elsif ($char[$i] eq '\E') {
5548 21         26 if ($right_e < $left_e) {
5549             $char[$i] = '>]}';
5550             $right_e++;
5551 21         43 }
5552             else {
5553             $char[$i] = '';
5554             }
5555 0         0 }
5556 0 0       0 elsif ($char[$i] eq '\Q') {
5557 0         0 while (1) {
5558             if (++$i > $#char) {
5559 0 0       0 last;
5560 0         0 }
5561             if ($char[$i] eq '\E') {
5562             last;
5563             }
5564             }
5565             }
5566             elsif ($char[$i] eq '\E') {
5567             }
5568              
5569 0 0       0 # $0 --> $0
5570 0         0 elsif ($char[$i] =~ /\A \$ 0 \z/oxms) {
5571             if ($ignorecase) {
5572             $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
5573             }
5574 0 0       0 }
5575 0         0 elsif ($char[$i] =~ /\A \$ \{ (?>\s*) 0 (?>\s*) \} \z/oxms) {
5576             if ($ignorecase) {
5577             $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
5578             }
5579             }
5580              
5581             # $$ --> $$
5582             elsif ($char[$i] =~ /\A \$\$ \z/oxms) {
5583             }
5584              
5585             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
5586 0         0 # $1, $2, $3 --> $1, $2, $3 otherwise
5587 0 0       0 elsif ($char[$i] =~ /\A \$ ((?>[1-9][0-9]*)) \z/oxms) {
5588 0         0 $char[$i] = e_capture($1);
5589             if ($ignorecase) {
5590             $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
5591             }
5592 0         0 }
5593 0 0       0 elsif ($char[$i] =~ /\A \$ \{ (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} \z/oxms) {
5594 0         0 $char[$i] = e_capture($1);
5595             if ($ignorecase) {
5596             $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
5597             }
5598             }
5599              
5600 0         0 # $$foo[ ... ] --> $ $foo->[ ... ]
5601 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) {
5602 0         0 $char[$i] = e_capture($1.'->'.$2);
5603             if ($ignorecase) {
5604             $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
5605             }
5606             }
5607              
5608 0         0 # $$foo{ ... } --> $ $foo->{ ... }
5609 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) {
5610 0         0 $char[$i] = e_capture($1.'->'.$2);
5611             if ($ignorecase) {
5612             $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
5613             }
5614             }
5615              
5616 0         0 # $$foo
5617 0 0       0 elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) \z/oxms) {
5618 0         0 $char[$i] = e_capture($1);
5619             if ($ignorecase) {
5620             $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
5621             }
5622             }
5623              
5624 0 50       0 # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Ecyrillic::PREMATCH()
5625 8         22 elsif ($char[$i] =~ /\A ( \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} ) \z/oxmsgc) {
5626             if ($ignorecase) {
5627             $char[$i] = '@{[Ecyrillic::ignorecase(Ecyrillic::PREMATCH())]}';
5628 0         0 }
5629             else {
5630             $char[$i] = '@{[Ecyrillic::PREMATCH()]}';
5631             }
5632             }
5633              
5634 8 50       22 # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Ecyrillic::MATCH()
5635 8         22 elsif ($char[$i] =~ /\A ( \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} ) \z/oxmsgc) {
5636             if ($ignorecase) {
5637             $char[$i] = '@{[Ecyrillic::ignorecase(Ecyrillic::MATCH())]}';
5638 0         0 }
5639             else {
5640             $char[$i] = '@{[Ecyrillic::MATCH()]}';
5641             }
5642             }
5643              
5644 8 50       49 # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Ecyrillic::POSTMATCH()
5645 6         18 elsif ($char[$i] =~ /\A ( \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} ) \z/oxmsgc) {
5646             if ($ignorecase) {
5647             $char[$i] = '@{[Ecyrillic::ignorecase(Ecyrillic::POSTMATCH())]}';
5648 0         0 }
5649             else {
5650             $char[$i] = '@{[Ecyrillic::POSTMATCH()]}';
5651             }
5652             }
5653              
5654 6 0       20 # ${ foo }
5655 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) {
5656             if ($ignorecase) {
5657             $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
5658             }
5659             }
5660              
5661 0         0 # ${ ... }
5662 0 0       0 elsif ($char[$i] =~ /\A \$ (?>\s*) \{ ( .+ ) \} \z/oxms) {
5663 0         0 $char[$i] = e_capture($1);
5664             if ($ignorecase) {
5665             $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
5666             }
5667             }
5668              
5669 0         0 # $scalar or @array
5670 21 100       57 elsif ($char[$i] =~ /\A [\$\@].+ /oxms) {
5671 21         53 $char[$i] = e_string($char[$i]);
5672             if ($ignorecase) {
5673             $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
5674             }
5675             }
5676              
5677 11 100 33     34 # quote character before ? + * {
    50          
5678             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
5679             if ($char[$i-1] =~ /\A (?:[\x00-\xFF]|\\[0-7]{2,3}|\\x[0-9-A-Fa-f]{1,2}) \z/oxms) {
5680 138         943 }
5681 0 0       0 elsif (($ope =~ /\A m? \z/oxms) and ($delimiter eq '?')) {
5682 0         0 my $char = $char[$i-1];
5683             if ($char[$i] eq '{') {
5684             die __FILE__, qq{: "MULTIBYTE{n}" should be "(MULTIBYTE){n}" in m?? (and shift \$1,\$2,\$3,...) ($char){n}\n};
5685 0         0 }
5686             else {
5687             die __FILE__, qq{: "MULTIBYTE$char[$i]" should be "(MULTIBYTE)$char[$i]" in m?? (and shift \$1,\$2,\$3,...) ($char)$char[$i]\n};
5688             }
5689 0         0 }
5690             else {
5691             $char[$i-1] = '(?:' . $char[$i-1] . ')';
5692             }
5693             }
5694             }
5695 127         474  
5696 642 50       1182 # make regexp string
5697 642 0 0     1322 $modifier =~ tr/i//d;
5698 0         0 if ($left_e > $right_e) {
5699             if (($ope =~ /\A m? \z/oxms) and ($delimiter eq '?')) {
5700             return join '', $ope, $delimiter, $anchor, @char, '>]}' x ($left_e - $right_e), $matched, $end_delimiter, $modifier;
5701 0         0 }
5702             else {
5703             return join '', $ope, $delimiter, $anchor, '(?:', @char, '>]}' x ($left_e - $right_e), ')', $matched, $end_delimiter, $modifier;
5704 0 50 33     0 }
5705 642         3414 }
5706             if (($ope =~ /\A m? \z/oxms) and ($delimiter eq '?')) {
5707             return join '', $ope, $delimiter, $anchor, @char, $matched, $end_delimiter, $modifier;
5708 0         0 }
5709             else {
5710             return join '', $ope, $delimiter, $anchor, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
5711             }
5712             }
5713              
5714             #
5715             # double quote stuff
5716 642     180 0 5019 #
5717             sub qq_stuff {
5718             my($delimiter,$end_delimiter,$stuff) = @_;
5719 180 100       264  
5720 180         340 # scalar variable or array variable
5721             if ($stuff =~ /\A [\$\@] /oxms) {
5722             return $stuff;
5723             }
5724 100         335  
  80         165  
5725 80         212 # quote by delimiter
5726 80 50       181 my %octet = map {$_ => 1} ($stuff =~ /\G ([\x00-\xFF]) /oxmsg);
5727 80 50       136 for my $char (qw( ! " $ % & * + - . / : = ? @ ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
5728 80 50       131 next if $char eq $delimiter;
5729 80         132 next if $char eq $end_delimiter;
5730             if (not $octet{$char}) {
5731             return join '', 'qq', $char, $stuff, $char;
5732 80         356 }
5733             }
5734             return join '', 'qq', '<', $stuff, '>';
5735             }
5736              
5737             #
5738             # escape regexp (m'', qr'', and m''b, qr''b)
5739 0     10 0 0 #
5740 10   50     49 sub e_qr_q {
5741             my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
5742 10         41 $modifier ||= '';
5743 10 50       27  
5744 10         20 $modifier =~ tr/p//d;
5745 0         0 if ($modifier =~ /([adlu])/oxms) {
5746 0 0       0 my $line = 0;
5747 0         0 for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
5748 0         0 if ($filename ne __FILE__) {
5749             $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
5750             last;
5751 0         0 }
5752             }
5753             die qq{Unsupported modifier "$1" used at line $line.\n};
5754 0         0 }
5755              
5756             $slash = 'div';
5757 10 100       15  
    50          
5758 10         24 # literal null string pattern
5759 8         11 if ($string eq '') {
5760 8         9 $modifier =~ tr/bB//d;
5761             $modifier =~ tr/i//d;
5762             return join '', $ope, $delimiter, $end_delimiter, $modifier;
5763             }
5764              
5765 8         48 # with /b /B modifier
5766             elsif ($modifier =~ tr/bB//d) {
5767             return e_qr_qb($ope,$delimiter,$end_delimiter,$string,$modifier);
5768             }
5769              
5770 0         0 # without /b /B modifier
5771             else {
5772             return e_qr_qt($ope,$delimiter,$end_delimiter,$string,$modifier);
5773             }
5774             }
5775              
5776             #
5777             # escape regexp (m'', qr'')
5778 2     2 0 7 #
5779             sub e_qr_qt {
5780 2 50       8 my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
5781              
5782             my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
5783 2         5  
5784             # split regexp
5785             my @char = $string =~ /\G((?>
5786             [^\\\[\$\@\/] |
5787             [\x00-\xFF] |
5788             \[\^ |
5789             \[\: (?>[a-z]+) \:\] |
5790             \[\:\^ (?>[a-z]+) \:\] |
5791             [\$\@\/] |
5792             \\ (?:$q_char) |
5793             (?:$q_char)
5794             ))/oxmsg;
5795 2         64  
5796 2 50 33     29 # unescape character
    50 33        
    50 33        
    50          
    50          
    50          
5797             for (my $i=0; $i <= $#char; $i++) {
5798             if (0) {
5799             }
5800 2         18  
5801 0         0 # open character class [...]
5802 0 0       0 elsif ($char[$i] eq '[') {
5803 0         0 my $left = $i;
5804             if ($char[$i+1] eq ']') {
5805 0         0 $i++;
5806 0 0       0 }
5807 0         0 while (1) {
5808             if (++$i > $#char) {
5809 0 0       0 die __FILE__, ": Unmatched [] in regexp\n";
5810 0         0 }
5811             if ($char[$i] eq ']') {
5812             my $right = $i;
5813 0         0  
5814             # [...]
5815 0         0 splice @char, $left, $right-$left+1, Ecyrillic::charlist_qr(@char[$left+1..$right-1], $modifier);
5816 0         0  
5817             $i = $left;
5818             last;
5819             }
5820             }
5821             }
5822              
5823 0         0 # open character class [^...]
5824 0 0       0 elsif ($char[$i] eq '[^') {
5825 0         0 my $left = $i;
5826             if ($char[$i+1] eq ']') {
5827 0         0 $i++;
5828 0 0       0 }
5829 0         0 while (1) {
5830             if (++$i > $#char) {
5831 0 0       0 die __FILE__, ": Unmatched [] in regexp\n";
5832 0         0 }
5833             if ($char[$i] eq ']') {
5834             my $right = $i;
5835 0         0  
5836             # [^...]
5837 0         0 splice @char, $left, $right-$left+1, Ecyrillic::charlist_not_qr(@char[$left+1..$right-1], $modifier);
5838 0         0  
5839             $i = $left;
5840             last;
5841             }
5842             }
5843             }
5844              
5845 0         0 # escape $ @ / and \
5846             elsif ($char[$i] =~ /\A [\$\@\/\\] \z/oxms) {
5847             $char[$i] = '\\' . $char[$i];
5848             }
5849              
5850 0         0 # rewrite character class or escape character
5851             elsif (my $char = character_class($char[$i],$modifier)) {
5852             $char[$i] = $char;
5853             }
5854              
5855 0 0       0 # /i modifier
5856 0         0 elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Ecyrillic::uc($char[$i]) ne Ecyrillic::fc($char[$i]))) {
5857             if (CORE::length(Ecyrillic::fc($char[$i])) == 1) {
5858             $char[$i] = '[' . Ecyrillic::uc($char[$i]) . Ecyrillic::fc($char[$i]) . ']';
5859 0         0 }
5860             else {
5861             $char[$i] = '(?:' . Ecyrillic::uc($char[$i]) . '|' . Ecyrillic::fc($char[$i]) . ')';
5862             }
5863             }
5864              
5865 0 0       0 # quote character before ? + * {
5866             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
5867             if ($char[$i-1] =~ /\A [\x00-\xFF] \z/oxms) {
5868 0         0 }
5869             else {
5870             $char[$i-1] = '(?:' . $char[$i-1] . ')';
5871             }
5872             }
5873 0         0 }
5874 2         6  
5875             $delimiter = '/';
5876 2         3 $end_delimiter = '/';
5877 2         11  
5878             $modifier =~ tr/i//d;
5879             return join '', $ope, $delimiter, $anchor, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
5880             }
5881              
5882             #
5883             # escape regexp (m''b, qr''b)
5884 2     0 0 18 #
5885             sub e_qr_qb {
5886             my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
5887 0         0  
5888             # split regexp
5889             my @char = $string =~ /\G ((?>[^\\]|\\\\)) /oxmsg;
5890 0         0  
5891 0 0       0 # unescape character
    0          
5892             for (my $i=0; $i <= $#char; $i++) {
5893             if (0) {
5894             }
5895 0         0  
5896             # remain \\
5897             elsif ($char[$i] eq '\\\\') {
5898             }
5899              
5900 0         0 # escape $ @ / and \
5901             elsif ($char[$i] =~ /\A [\$\@\/\\] \z/oxms) {
5902             $char[$i] = '\\' . $char[$i];
5903             }
5904 0         0 }
5905 0         0  
5906 0         0 $delimiter = '/';
5907             $end_delimiter = '/';
5908             return join '', $ope, $delimiter, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
5909             }
5910              
5911             #
5912             # escape regexp (s/here//)
5913 0     76 0 0 #
5914 76   100     208 sub e_s1 {
5915             my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
5916 76         338 $modifier ||= '';
5917 76 50       122  
5918 76         205 $modifier =~ tr/p//d;
5919 0         0 if ($modifier =~ /([adlu])/oxms) {
5920 0 0       0 my $line = 0;
5921 0         0 for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
5922 0         0 if ($filename ne __FILE__) {
5923             $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
5924             last;
5925 0         0 }
5926             }
5927             die qq{Unsupported modifier "$1" used at line $line.\n};
5928 0         0 }
5929              
5930             $slash = 'div';
5931 76 100       144  
    50          
5932 76         711 # literal null string pattern
5933 8         9 if ($string eq '') {
5934 8         10 $modifier =~ tr/bB//d;
5935             $modifier =~ tr/i//d;
5936             return join '', $ope, $delimiter, $end_delimiter, $modifier;
5937             }
5938              
5939             # /b /B modifier
5940             elsif ($modifier =~ tr/bB//d) {
5941 8 0       220  
5942 0         0 # choice again delimiter
5943 0         0 if ($delimiter =~ / [\@:] /oxms) {
  0         0  
5944 0 0       0 my @char = $string =~ /\G ([\x00-\xFF]) /oxmsg;
    0          
    0          
    0          
5945 0         0 my %octet = map {$_ => 1} @char;
5946 0         0 if (not $octet{')'}) {
5947             $delimiter = '(';
5948             $end_delimiter = ')';
5949 0         0 }
5950 0         0 elsif (not $octet{'}'}) {
5951             $delimiter = '{';
5952             $end_delimiter = '}';
5953 0         0 }
5954 0         0 elsif (not $octet{']'}) {
5955             $delimiter = '[';
5956             $end_delimiter = ']';
5957 0         0 }
5958 0         0 elsif (not $octet{'>'}) {
5959             $delimiter = '<';
5960             $end_delimiter = '>';
5961 0         0 }
5962 0 0       0 else {
5963 0         0 for my $char (qw( ! " $ % & * + - . / = ? ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
5964 0         0 if (not $octet{$char}) {
5965 0         0 $delimiter = $char;
5966             $end_delimiter = $char;
5967             last;
5968             }
5969             }
5970             }
5971 0         0 }
5972 0         0  
5973             my $prematch = '';
5974             return join '', $ope, $delimiter, $prematch, '(?:', $string, ')', $matched, $end_delimiter, $modifier;
5975 0 100       0 }
5976 68         186  
5977             my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
5978             my $metachar = qr/[\@\\|[\]{^]/oxms;
5979 68         290  
5980             # split regexp
5981             my @char = $string =~ /\G((?>
5982             [^\\\$\@\[\(] |
5983             \\ (?>[1-9][0-9]*) |
5984             \\g (?>\s*) (?>[1-9][0-9]*) |
5985             \\g (?>\s*) \{ (?>\s*) (?>[1-9][0-9]*) (?>\s*) \} |
5986             \\g (?>\s*) \{ (?>\s*) - (?>\s*) (?>[1-9][0-9]*) (?>\s*) \} |
5987             \\x (?>[0-9A-Fa-f]{1,2}) |
5988             \\ (?>[0-7]{2,3}) |
5989             \\c [\x40-\x5F] |
5990             \\x\{ (?>[0-9A-Fa-f]+) \} |
5991             \\o\{ (?>[0-7]+) \} |
5992             \\[bBNpP]\{ (?>[^0-9\}][^\}]*) \} |
5993             \\ $q_char |
5994             \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} |
5995             \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} |
5996             \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} |
5997             [\$\@] $qq_variable |
5998             \$ (?>\s* [0-9]+) |
5999             \$ (?>\s*) \{ (?>\s* [0-9]+ \s*) \} |
6000             \$ \$ (?![\w\{]) |
6001             \$ (?>\s*) \$ (?>\s*) $qq_variable |
6002             \[\^ |
6003             \[\: (?>[a-z]+) :\] |
6004             \[\:\^ (?>[a-z]+) :\] |
6005             \(\? |
6006             $q_char
6007             ))/oxmsg;
6008 68 50       19206  
6009 68         471 # choice again delimiter
  0         0  
6010 0 0       0 if ($delimiter =~ / [\@:] /oxms) {
    0          
    0          
    0          
6011 0         0 my %octet = map {$_ => 1} @char;
6012 0         0 if (not $octet{')'}) {
6013             $delimiter = '(';
6014             $end_delimiter = ')';
6015 0         0 }
6016 0         0 elsif (not $octet{'}'}) {
6017             $delimiter = '{';
6018             $end_delimiter = '}';
6019 0         0 }
6020 0         0 elsif (not $octet{']'}) {
6021             $delimiter = '[';
6022             $end_delimiter = ']';
6023 0         0 }
6024 0         0 elsif (not $octet{'>'}) {
6025             $delimiter = '<';
6026             $end_delimiter = '>';
6027 0         0 }
6028 0 0       0 else {
6029 0         0 for my $char (qw( ! " $ % & * + - . / = ? ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
6030 0         0 if (not $octet{$char}) {
6031 0         0 $delimiter = $char;
6032             $end_delimiter = $char;
6033             last;
6034             }
6035             }
6036             }
6037             }
6038 0         0  
  68         136  
6039             # count '('
6040 253         428 my $parens = grep { $_ eq '(' } @char;
6041 68         97  
6042 68         93 my $left_e = 0;
6043             my $right_e = 0;
6044             for (my $i=0; $i <= $#char; $i++) {
6045 68 50 33     196  
    50 33        
    100          
    100          
    50          
    50          
6046 195         1214 # "\L\u" --> "\u\L"
6047             if (($char[$i] eq '\L') and ($char[$i+1] eq '\u')) {
6048             @char[$i,$i+1] = @char[$i+1,$i];
6049             }
6050              
6051 0         0 # "\U\l" --> "\l\U"
6052             elsif (($char[$i] eq '\U') and ($char[$i+1] eq '\l')) {
6053             @char[$i,$i+1] = @char[$i+1,$i];
6054             }
6055              
6056 0         0 # octal escape sequence
6057             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
6058             $char[$i] = Ecyrillic::octchr($1);
6059             }
6060              
6061 1         4 # hexadecimal escape sequence
6062             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
6063             $char[$i] = Ecyrillic::hexchr($1);
6064             }
6065              
6066             # \b{...} --> b\{...}
6067             # \B{...} --> B\{...}
6068             # \N{CHARNAME} --> N\{CHARNAME}
6069             # \p{PROPERTY} --> p\{PROPERTY}
6070 1         3 # \P{PROPERTY} --> P\{PROPERTY}
6071             elsif ($char[$i] =~ /\A \\ ([bBNpP]) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
6072             $char[$i] = $1 . '\\' . $2;
6073             }
6074              
6075 0         0 # \p, \P, \X --> p, P, X
6076             elsif ($char[$i] =~ /\A \\ ( [pPX] ) \z/oxms) {
6077             $char[$i] = $1;
6078 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          
6079              
6080             if (0) {
6081             }
6082 195         1042  
6083 0 0 0     0 # join separated multiple-octet
    0 0        
    0 0        
      0        
      0        
      0        
6084 0         0 elsif ($char[$i] =~ /\A (?: \\ [0-7]{2,3} | \\x [0-9A-Fa-f]{1,2}) \z/oxms) {
6085             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)) {
6086             $char[$i] .= join '', splice @char, $i+1, 3;
6087 0         0 }
6088             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)) {
6089             $char[$i] .= join '', splice @char, $i+1, 2;
6090 0         0 }
6091             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)) {
6092             $char[$i] .= join '', splice @char, $i+1, 1;
6093             }
6094             }
6095              
6096 0         0 # open character class [...]
6097 13 50       22 elsif ($char[$i] eq '[') {
6098 13         40 my $left = $i;
6099             if ($char[$i+1] eq ']') {
6100 0         0 $i++;
6101 13 50       43 }
6102 58         104 while (1) {
6103             if (++$i > $#char) {
6104 0 100       0 die __FILE__, ": Unmatched [] in regexp\n";
6105 58         128 }
6106             if ($char[$i] eq ']') {
6107             my $right = $i;
6108 13 50       21  
6109 13         83 # [...]
  0         0  
6110             if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
6111             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);
6112 0         0 }
6113             else {
6114             splice @char, $left, $right-$left+1, Ecyrillic::charlist_qr(@char[$left+1..$right-1], $modifier);
6115 13         60 }
6116 13         32  
6117             $i = $left;
6118             last;
6119             }
6120             }
6121             }
6122              
6123 13         35 # open character class [^...]
6124 0 0       0 elsif ($char[$i] eq '[^') {
6125 0         0 my $left = $i;
6126             if ($char[$i+1] eq ']') {
6127 0         0 $i++;
6128 0 0       0 }
6129 0         0 while (1) {
6130             if (++$i > $#char) {
6131 0 0       0 die __FILE__, ": Unmatched [] in regexp\n";
6132 0         0 }
6133             if ($char[$i] eq ']') {
6134             my $right = $i;
6135 0 0       0  
6136 0         0 # [^...]
  0         0  
6137             if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
6138             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);
6139 0         0 }
6140             else {
6141             splice @char, $left, $right-$left+1, Ecyrillic::charlist_not_qr(@char[$left+1..$right-1], $modifier);
6142 0         0 }
6143 0         0  
6144             $i = $left;
6145             last;
6146             }
6147             }
6148             }
6149              
6150 0         0 # rewrite character class or escape character
6151             elsif (my $char = character_class($char[$i],$modifier)) {
6152             $char[$i] = $char;
6153             }
6154              
6155 7 50       13 # /i modifier
6156 3         6 elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Ecyrillic::uc($char[$i]) ne Ecyrillic::fc($char[$i]))) {
6157             if (CORE::length(Ecyrillic::fc($char[$i])) == 1) {
6158             $char[$i] = '[' . Ecyrillic::uc($char[$i]) . Ecyrillic::fc($char[$i]) . ']';
6159 3         10 }
6160             else {
6161             $char[$i] = '(?:' . Ecyrillic::uc($char[$i]) . '|' . Ecyrillic::fc($char[$i]) . ')';
6162             }
6163             }
6164              
6165 0 0       0 # \u \l \U \L \F \Q \E
6166 0         0 elsif ($char[$i] =~ /\A [<>] \z/oxms) {
6167             if ($right_e < $left_e) {
6168             $char[$i] = '\\' . $char[$i];
6169             }
6170 0         0 }
6171 0         0 elsif ($char[$i] eq '\u') {
6172             $char[$i] = '@{[Ecyrillic::ucfirst qq<';
6173             $left_e++;
6174 0         0 }
6175 0         0 elsif ($char[$i] eq '\l') {
6176             $char[$i] = '@{[Ecyrillic::lcfirst qq<';
6177             $left_e++;
6178 0         0 }
6179 0         0 elsif ($char[$i] eq '\U') {
6180             $char[$i] = '@{[Ecyrillic::uc qq<';
6181             $left_e++;
6182 0         0 }
6183 0         0 elsif ($char[$i] eq '\L') {
6184             $char[$i] = '@{[Ecyrillic::lc qq<';
6185             $left_e++;
6186 0         0 }
6187 0         0 elsif ($char[$i] eq '\F') {
6188             $char[$i] = '@{[Ecyrillic::fc qq<';
6189             $left_e++;
6190 0         0 }
6191 0         0 elsif ($char[$i] eq '\Q') {
6192             $char[$i] = '@{[CORE::quotemeta qq<';
6193             $left_e++;
6194 0 0       0 }
6195 0         0 elsif ($char[$i] eq '\E') {
6196 0         0 if ($right_e < $left_e) {
6197             $char[$i] = '>]}';
6198             $right_e++;
6199 0         0 }
6200             else {
6201             $char[$i] = '';
6202             }
6203 0         0 }
6204 0 0       0 elsif ($char[$i] eq '\Q') {
6205 0         0 while (1) {
6206             if (++$i > $#char) {
6207 0 0       0 last;
6208 0         0 }
6209             if ($char[$i] eq '\E') {
6210             last;
6211             }
6212             }
6213             }
6214             elsif ($char[$i] eq '\E') {
6215             }
6216              
6217             # \0 --> \0
6218             elsif ($char[$i] =~ /\A \\ (?>\s*) 0 \z/oxms) {
6219             }
6220              
6221             # \g{N}, \g{-N}
6222              
6223             # P.108 Using Simple Patterns
6224             # in Chapter 7: In the World of Regular Expressions
6225             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
6226              
6227             # P.221 Capturing
6228             # in Chapter 5: Pattern Matching
6229             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
6230              
6231             # \g{-1}, \g{-2}, \g{-3} --> \g{-1}, \g{-2}, \g{-3}
6232             elsif ($char[$i] =~ /\A \\g (?>\s*) \{ (?>\s*) - (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} \z/oxms) {
6233             }
6234              
6235             # \g{1}, \g{2}, \g{3} --> \g{2}, \g{3}, \g{4} (only when multibyte anchoring is enable)
6236             elsif ($char[$i] =~ /\A \\g (?>\s*) \{ (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} \z/oxms) {
6237             }
6238              
6239             # \g1, \g2, \g3 --> \g2, \g3, \g4 (only when multibyte anchoring is enable)
6240             elsif ($char[$i] =~ /\A \\g (?>\s*) ((?>[1-9][0-9]*)) \z/oxms) {
6241             }
6242              
6243             # \1, \2, \3 --> \2, \3, \4 (only when multibyte anchoring is enable)
6244             elsif ($char[$i] =~ /\A \\ (?>\s*) ((?>[1-9][0-9]*)) \z/oxms) {
6245             }
6246              
6247 0 0       0 # $0 --> $0
6248 0         0 elsif ($char[$i] =~ /\A \$ 0 \z/oxms) {
6249             if ($ignorecase) {
6250             $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
6251             }
6252 0 0       0 }
6253 0         0 elsif ($char[$i] =~ /\A \$ \{ (?>\s*) 0 (?>\s*) \} \z/oxms) {
6254             if ($ignorecase) {
6255             $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
6256             }
6257             }
6258              
6259             # $$ --> $$
6260             elsif ($char[$i] =~ /\A \$\$ \z/oxms) {
6261             }
6262              
6263             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
6264 0         0 # $1, $2, $3 --> $1, $2, $3 otherwise
6265 0 0       0 elsif ($char[$i] =~ /\A \$ ((?>[1-9][0-9]*)) \z/oxms) {
6266 0         0 $char[$i] = e_capture($1);
6267             if ($ignorecase) {
6268             $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
6269             }
6270 0         0 }
6271 0 0       0 elsif ($char[$i] =~ /\A \$ \{ (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} \z/oxms) {
6272 0         0 $char[$i] = e_capture($1);
6273             if ($ignorecase) {
6274             $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
6275             }
6276             }
6277              
6278 0         0 # $$foo[ ... ] --> $ $foo->[ ... ]
6279 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) {
6280 0         0 $char[$i] = e_capture($1.'->'.$2);
6281             if ($ignorecase) {
6282             $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
6283             }
6284             }
6285              
6286 0         0 # $$foo{ ... } --> $ $foo->{ ... }
6287 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) {
6288 0         0 $char[$i] = e_capture($1.'->'.$2);
6289             if ($ignorecase) {
6290             $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
6291             }
6292             }
6293              
6294 0         0 # $$foo
6295 0 0       0 elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) \z/oxms) {
6296 0         0 $char[$i] = e_capture($1);
6297             if ($ignorecase) {
6298             $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
6299             }
6300             }
6301              
6302 0 50       0 # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Ecyrillic::PREMATCH()
6303 4         15 elsif ($char[$i] =~ /\A ( \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} ) \z/oxmsgc) {
6304             if ($ignorecase) {
6305             $char[$i] = '@{[Ecyrillic::ignorecase(Ecyrillic::PREMATCH())]}';
6306 0         0 }
6307             else {
6308             $char[$i] = '@{[Ecyrillic::PREMATCH()]}';
6309             }
6310             }
6311              
6312 4 50       15 # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Ecyrillic::MATCH()
6313 4         13 elsif ($char[$i] =~ /\A ( \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} ) \z/oxmsgc) {
6314             if ($ignorecase) {
6315             $char[$i] = '@{[Ecyrillic::ignorecase(Ecyrillic::MATCH())]}';
6316 0         0 }
6317             else {
6318             $char[$i] = '@{[Ecyrillic::MATCH()]}';
6319             }
6320             }
6321              
6322 4 50       14 # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Ecyrillic::POSTMATCH()
6323 3         11 elsif ($char[$i] =~ /\A ( \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} ) \z/oxmsgc) {
6324             if ($ignorecase) {
6325             $char[$i] = '@{[Ecyrillic::ignorecase(Ecyrillic::POSTMATCH())]}';
6326 0         0 }
6327             else {
6328             $char[$i] = '@{[Ecyrillic::POSTMATCH()]}';
6329             }
6330             }
6331              
6332 3 0       10 # ${ foo }
6333 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) {
6334             if ($ignorecase) {
6335             $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
6336             }
6337             }
6338              
6339 0         0 # ${ ... }
6340 0 0       0 elsif ($char[$i] =~ /\A \$ (?>\s*) \{ ( .+ ) \} \z/oxms) {
6341 0         0 $char[$i] = e_capture($1);
6342             if ($ignorecase) {
6343             $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
6344             }
6345             }
6346              
6347 0         0 # $scalar or @array
6348 4 50       15 elsif ($char[$i] =~ /\A [\$\@].+ /oxms) {
6349 4         24 $char[$i] = e_string($char[$i]);
6350             if ($ignorecase) {
6351             $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
6352             }
6353             }
6354              
6355 0 50       0 # quote character before ? + * {
6356             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
6357             if ($char[$i-1] =~ /\A (?:[\x00-\xFF]|\\[0-7]{2,3}|\\x[0-9-A-Fa-f]{1,2}) \z/oxms) {
6358 13         93 }
6359             else {
6360             $char[$i-1] = '(?:' . $char[$i-1] . ')';
6361             }
6362             }
6363             }
6364 13         115  
6365 68         155 # make regexp string
6366 68 50       112 my $prematch = '';
6367 68         185 $modifier =~ tr/i//d;
6368             if ($left_e > $right_e) {
6369 0         0 return join '', $ope, $delimiter, $prematch, '(?:', @char, '>]}' x ($left_e - $right_e), ')', $matched, $end_delimiter, $modifier;
6370             }
6371             return join '', $ope, $delimiter, $prematch, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
6372             }
6373              
6374             #
6375             # escape regexp (s'here'' or s'here''b)
6376 68     21 0 834 #
6377 21   100     46 sub e_s1_q {
6378             my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6379 21         81 $modifier ||= '';
6380 21 50       24  
6381 21         43 $modifier =~ tr/p//d;
6382 0         0 if ($modifier =~ /([adlu])/oxms) {
6383 0 0       0 my $line = 0;
6384 0         0 for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
6385 0         0 if ($filename ne __FILE__) {
6386             $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
6387             last;
6388 0         0 }
6389             }
6390             die qq{Unsupported modifier "$1" used at line $line.\n};
6391 0         0 }
6392              
6393             $slash = 'div';
6394 21 100       30  
    50          
6395 21         56 # literal null string pattern
6396 8         10 if ($string eq '') {
6397 8         9 $modifier =~ tr/bB//d;
6398             $modifier =~ tr/i//d;
6399             return join '', $ope, $delimiter, $end_delimiter, $modifier;
6400             }
6401              
6402 8         47 # with /b /B modifier
6403             elsif ($modifier =~ tr/bB//d) {
6404             return e_s1_qb($ope,$delimiter,$end_delimiter,$string,$modifier);
6405             }
6406              
6407 0         0 # without /b /B modifier
6408             else {
6409             return e_s1_qt($ope,$delimiter,$end_delimiter,$string,$modifier);
6410             }
6411             }
6412              
6413             #
6414             # escape regexp (s'here'')
6415 13     13 0 32 #
6416             sub e_s1_qt {
6417 13 50       26 my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6418              
6419             my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
6420 13         29  
6421             # split regexp
6422             my @char = $string =~ /\G((?>
6423             [^\\\[\$\@\/] |
6424             [\x00-\xFF] |
6425             \[\^ |
6426             \[\: (?>[a-z]+) \:\] |
6427             \[\:\^ (?>[a-z]+) \:\] |
6428             [\$\@\/] |
6429             \\ (?:$q_char) |
6430             (?:$q_char)
6431             ))/oxmsg;
6432 13         205  
6433 13 50 33     41 # unescape character
    50 33        
    50 66        
    100          
    50          
    50          
6434             for (my $i=0; $i <= $#char; $i++) {
6435             if (0) {
6436             }
6437 25         115  
6438 0         0 # open character class [...]
6439 0 0       0 elsif ($char[$i] eq '[') {
6440 0         0 my $left = $i;
6441             if ($char[$i+1] eq ']') {
6442 0         0 $i++;
6443 0 0       0 }
6444 0         0 while (1) {
6445             if (++$i > $#char) {
6446 0 0       0 die __FILE__, ": Unmatched [] in regexp\n";
6447 0         0 }
6448             if ($char[$i] eq ']') {
6449             my $right = $i;
6450 0         0  
6451             # [...]
6452 0         0 splice @char, $left, $right-$left+1, Ecyrillic::charlist_qr(@char[$left+1..$right-1], $modifier);
6453 0         0  
6454             $i = $left;
6455             last;
6456             }
6457             }
6458             }
6459              
6460 0         0 # open character class [^...]
6461 0 0       0 elsif ($char[$i] eq '[^') {
6462 0         0 my $left = $i;
6463             if ($char[$i+1] eq ']') {
6464 0         0 $i++;
6465 0 0       0 }
6466 0         0 while (1) {
6467             if (++$i > $#char) {
6468 0 0       0 die __FILE__, ": Unmatched [] in regexp\n";
6469 0         0 }
6470             if ($char[$i] eq ']') {
6471             my $right = $i;
6472 0         0  
6473             # [^...]
6474 0         0 splice @char, $left, $right-$left+1, Ecyrillic::charlist_not_qr(@char[$left+1..$right-1], $modifier);
6475 0         0  
6476             $i = $left;
6477             last;
6478             }
6479             }
6480             }
6481              
6482 0         0 # escape $ @ / and \
6483             elsif ($char[$i] =~ /\A [\$\@\/\\] \z/oxms) {
6484             $char[$i] = '\\' . $char[$i];
6485             }
6486              
6487 0         0 # rewrite character class or escape character
6488             elsif (my $char = character_class($char[$i],$modifier)) {
6489             $char[$i] = $char;
6490             }
6491              
6492 6 0       13 # /i modifier
6493 0         0 elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Ecyrillic::uc($char[$i]) ne Ecyrillic::fc($char[$i]))) {
6494             if (CORE::length(Ecyrillic::fc($char[$i])) == 1) {
6495             $char[$i] = '[' . Ecyrillic::uc($char[$i]) . Ecyrillic::fc($char[$i]) . ']';
6496 0         0 }
6497             else {
6498             $char[$i] = '(?:' . Ecyrillic::uc($char[$i]) . '|' . Ecyrillic::fc($char[$i]) . ')';
6499             }
6500             }
6501              
6502 0 0       0 # quote character before ? + * {
6503             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
6504             if ($char[$i-1] =~ /\A [\x00-\xFF] \z/oxms) {
6505 0         0 }
6506             else {
6507             $char[$i-1] = '(?:' . $char[$i-1] . ')';
6508             }
6509             }
6510 0         0 }
6511 13         23  
6512 13         20 $modifier =~ tr/i//d;
6513 13         17 $delimiter = '/';
6514 13         17 $end_delimiter = '/';
6515             my $prematch = '';
6516             return join '', $ope, $delimiter, $prematch, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
6517             }
6518              
6519             #
6520             # escape regexp (s'here''b)
6521 13     0 0 94 #
6522             sub e_s1_qb {
6523             my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6524 0         0  
6525             # split regexp
6526             my @char = $string =~ /\G (?>[^\\]|\\\\) /oxmsg;
6527 0         0  
6528 0 0       0 # unescape character
    0          
6529             for (my $i=0; $i <= $#char; $i++) {
6530             if (0) {
6531             }
6532 0         0  
6533             # remain \\
6534             elsif ($char[$i] eq '\\\\') {
6535             }
6536              
6537 0         0 # escape $ @ / and \
6538             elsif ($char[$i] =~ /\A [\$\@\/\\] \z/oxms) {
6539             $char[$i] = '\\' . $char[$i];
6540             }
6541 0         0 }
6542 0         0  
6543 0         0 $delimiter = '/';
6544 0         0 $end_delimiter = '/';
6545             my $prematch = '';
6546             return join '', $ope, $delimiter, $prematch, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
6547             }
6548              
6549             #
6550             # escape regexp (s''here')
6551 0     16 0 0 #
6552             sub e_s2_q {
6553 16         49 my($ope,$delimiter,$end_delimiter,$string) = @_;
6554              
6555 16         23 $slash = 'div';
6556 16         94  
6557 16 100       47 my @char = $string =~ / \G (?>[^\\]|\\\\|$q_char) /oxmsg;
    100          
6558             for (my $i=0; $i <= $#char; $i++) {
6559             if (0) {
6560             }
6561 9         34  
6562             # not escape \\
6563             elsif ($char[$i] =~ /\A \\\\ \z/oxms) {
6564             }
6565              
6566 0         0 # escape $ @ / and \
6567             elsif ($char[$i] =~ /\A [\$\@\/\\] \z/oxms) {
6568             $char[$i] = '\\' . $char[$i];
6569             }
6570 5         16 }
6571              
6572             return join '', $ope, $delimiter, @char, $end_delimiter;
6573             }
6574              
6575             #
6576             # escape regexp (s/here/and here/modifier)
6577 16     97 0 48 #
6578 97   100     713 sub e_sub {
6579             my($variable,$delimiter1,$pattern,$end_delimiter1,$delimiter2,$replacement,$end_delimiter2,$modifier) = @_;
6580 97         402 $modifier ||= '';
6581 97 50       220  
6582 97         266 $modifier =~ tr/p//d;
6583 0         0 if ($modifier =~ /([adlu])/oxms) {
6584 0 0       0 my $line = 0;
6585 0         0 for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
6586 0         0 if ($filename ne __FILE__) {
6587             $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
6588             last;
6589 0         0 }
6590             }
6591             die qq{Unsupported modifier "$1" used at line $line.\n};
6592 0 100       0 }
6593 97         291  
6594 36         43 if ($variable eq '') {
6595             $variable = '$_';
6596             $bind_operator = ' =~ ';
6597 36         45 }
6598              
6599             $slash = 'div';
6600              
6601             # P.128 Start of match (or end of previous match): \G
6602             # P.130 Advanced Use of \G with Perl
6603             # in Chapter 3: Overview of Regular Expression Features and Flavors
6604             # P.312 Iterative Matching: Scalar Context, with /g
6605             # in Chapter 7: Perl
6606             # of ISBN 0-596-00289-0 Mastering Regular Expressions, Second edition
6607              
6608             # P.181 Where You Left Off: The \G Assertion
6609             # in Chapter 5: Pattern Matching
6610             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
6611              
6612             # P.220 Where You Left Off: The \G Assertion
6613             # in Chapter 5: Pattern Matching
6614 97         168 # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
6615 97         143  
6616             my $e_modifier = $modifier =~ tr/e//d;
6617 97         152 my $r_modifier = $modifier =~ tr/r//d;
6618 97 50       158  
6619 97         245 my $my = '';
6620 0         0 if ($variable =~ s/\A \( (?>\s*) ( (?>(?: local \b | my \b | our \b | state \b )?) .+ ) \) \z/$1/oxms) {
6621 0         0 $my = $variable;
6622             $variable =~ s/ (?: local \b | my \b | our \b | state \b ) (?>\s*) //oxms;
6623             $variable =~ s/ = .+ \z//oxms;
6624 0         0 }
6625 97         230  
6626             (my $variable_basename = $variable) =~ s/ [\[\{].* \z//oxms;
6627             $variable_basename =~ s/ \s+ \z//oxms;
6628 97         175  
6629 97 100       144 # quote replacement string
6630 97         227 my $e_replacement = '';
6631 17         34 if ($e_modifier >= 1) {
6632             $e_replacement = e_qq('', '', '', $replacement);
6633             $e_modifier--;
6634 17 100       19 }
6635 80         194 else {
6636             if ($delimiter2 eq "'") {
6637             $e_replacement = e_s2_q('qq', '/', '/', $replacement);
6638 16         31 }
6639             else {
6640             $e_replacement = e_qq ('qq', $delimiter2, $end_delimiter2, $replacement);
6641             }
6642 64         162 }
6643              
6644             my $sub = '';
6645 97 100       185  
6646 97 100       195 # with /r
6647             if ($r_modifier) {
6648             if (0) {
6649             }
6650 8         17  
6651 0 50       0 # s///gr without multibyte anchoring
6652             elsif ($modifier =~ /g/oxms) {
6653             $sub = sprintf(
6654             # 1 2 3 4 5
6655             q,
6656              
6657             $variable, # 1
6658             ($delimiter1 eq "'") ? # 2
6659             e_s1_q('m', $delimiter1, $end_delimiter1, $pattern, $modifier) : # :
6660             e_s1 ('m', $delimiter1, $end_delimiter1, $pattern, $modifier), # :
6661             $s_matched, # 3
6662             $e_replacement, # 4
6663             '$Ecyrillic::re_r=CORE::eval $Ecyrillic::re_r; ' x $e_modifier, # 5
6664             );
6665             }
6666              
6667             # s///r
6668 4         13 else {
6669              
6670 4 50       4 my $prematch = q{$`};
6671              
6672             $sub = sprintf(
6673             # 1 2 3 4 5 6 7
6674             q<(%s =~ %s) ? CORE::eval{%s local $^W=0; local $Ecyrillic::re_r=%s; %s"%s$Ecyrillic::re_r$'" } : %s>,
6675              
6676             $variable, # 1
6677             ($delimiter1 eq "'") ? # 2
6678             e_s1_q('m', $delimiter1, $end_delimiter1, $pattern, $modifier) : # :
6679             e_s1 ('m', $delimiter1, $end_delimiter1, $pattern, $modifier), # :
6680             $s_matched, # 3
6681             $e_replacement, # 4
6682             '$Ecyrillic::re_r=CORE::eval $Ecyrillic::re_r; ' x $e_modifier, # 5
6683             $prematch, # 6
6684             $variable, # 7
6685             );
6686             }
6687 4 50       12  
6688 8         22 # $var !~ s///r doesn't make sense
6689             if ($bind_operator =~ / !~ /oxms) {
6690             $sub = q{die("$0: Using !~ with s///r doesn't make sense"), } . $sub;
6691             }
6692             }
6693              
6694 0 100       0 # without /r
6695             else {
6696             if (0) {
6697             }
6698 89         208  
6699 0 100       0 # s///g without multibyte anchoring
    100          
6700             elsif ($modifier =~ /g/oxms) {
6701             $sub = sprintf(
6702             # 1 2 3 4 5 6 7 8
6703             q,
6704              
6705             $variable, # 1
6706             ($delimiter1 eq "'") ? # 2
6707             e_s1_q('m', $delimiter1, $end_delimiter1, $pattern, $modifier) : # :
6708             e_s1 ('m', $delimiter1, $end_delimiter1, $pattern, $modifier), # :
6709             $s_matched, # 3
6710             $e_replacement, # 4
6711             '$Ecyrillic::re_r=CORE::eval $Ecyrillic::re_r; ' x $e_modifier, # 5
6712             $variable, # 6
6713             $variable, # 7
6714             ($bind_operator =~ / !~ /oxms) ? '!' : '', # 8
6715             );
6716             }
6717              
6718             # s///
6719 22         76 else {
6720              
6721 67 100       115 my $prematch = q{$`};
    100          
6722              
6723             $sub = sprintf(
6724              
6725             ($bind_operator =~ / =~ /oxms) ?
6726              
6727             # 1 2 3 4 5 6 7 8
6728             q<(%s%s%s) ? CORE::eval{%s local $^W=0; local $Ecyrillic::re_r=%s; %s%s="%s$Ecyrillic::re_r$'"; 1 } : undef> :
6729              
6730             # 1 2 3 4 5 6 7 8
6731             q<(%s%s%s) ? 1 : CORE::eval{%s local $^W=0; local $Ecyrillic::re_r=%s; %s%s="%s$Ecyrillic::re_r$'"; undef }>,
6732              
6733             $variable, # 1
6734             $bind_operator, # 2
6735             ($delimiter1 eq "'") ? # 3
6736             e_s1_q('m', $delimiter1, $end_delimiter1, $pattern, $modifier) : # :
6737             e_s1 ('m', $delimiter1, $end_delimiter1, $pattern, $modifier), # :
6738             $s_matched, # 4
6739             $e_replacement, # 5
6740             '$Ecyrillic::re_r=CORE::eval $Ecyrillic::re_r; ' x $e_modifier, # 6
6741             $variable, # 7
6742             $prematch, # 8
6743             );
6744             }
6745             }
6746 67 50       386  
6747 97         495 # (my $foo = $bar) =~ s/// --> (my $foo = $bar, CORE::eval { ... })[1]
6748             if ($my ne '') {
6749             $sub = "($my, $sub)[1]";
6750             }
6751 0         0  
6752 97         309 # clear s/// variable
6753             $sub_variable = '';
6754 97         155 $bind_operator = '';
6755              
6756             return $sub;
6757             }
6758              
6759             #
6760             # escape regexp of split qr//
6761 97     74 0 703 #
6762 74   100     312 sub e_split {
6763             my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6764 74         315 $modifier ||= '';
6765 74 50       126  
6766 74         335 $modifier =~ tr/p//d;
6767 0         0 if ($modifier =~ /([adlu])/oxms) {
6768 0 0       0 my $line = 0;
6769 0         0 for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
6770 0         0 if ($filename ne __FILE__) {
6771             $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
6772             last;
6773 0         0 }
6774             }
6775             die qq{Unsupported modifier "$1" used at line $line.\n};
6776 0         0 }
6777              
6778             $slash = 'div';
6779 74 50       143  
6780 74         167 # /b /B modifier
6781             if ($modifier =~ tr/bB//d) {
6782             return join '', 'split', $ope, $delimiter, $string, $end_delimiter, $modifier;
6783 0 50       0 }
6784 74         170  
6785             my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
6786             my $metachar = qr/[\@\\|[\]{^]/oxms;
6787 74         312  
6788             # split regexp
6789             my @char = $string =~ /\G((?>
6790             [^\\\$\@\[\(] |
6791             \\x (?>[0-9A-Fa-f]{1,2}) |
6792             \\ (?>[0-7]{2,3}) |
6793             \\c [\x40-\x5F] |
6794             \\x\{ (?>[0-9A-Fa-f]+) \} |
6795             \\o\{ (?>[0-7]+) \} |
6796             \\[bBNpP]\{ (?>[^0-9\}][^\}]*) \} |
6797             \\ $q_char |
6798             \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} |
6799             \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} |
6800             \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} |
6801             [\$\@] $qq_variable |
6802             \$ (?>\s* [0-9]+) |
6803             \$ (?>\s*) \{ (?>\s* [0-9]+ \s*) \} |
6804             \$ \$ (?![\w\{]) |
6805             \$ (?>\s*) \$ (?>\s*) $qq_variable |
6806             \[\^ |
6807             \[\: (?>[a-z]+) :\] |
6808             \[\:\^ (?>[a-z]+) :\] |
6809             \(\? |
6810             $q_char
6811 74         8958 ))/oxmsg;
6812 74         251  
6813 74         106 my $left_e = 0;
6814             my $right_e = 0;
6815             for (my $i=0; $i <= $#char; $i++) {
6816 74 50 33     279  
    50 33        
    100          
    100          
    50          
    50          
6817 249         1328 # "\L\u" --> "\u\L"
6818             if (($char[$i] eq '\L') and ($char[$i+1] eq '\u')) {
6819             @char[$i,$i+1] = @char[$i+1,$i];
6820             }
6821              
6822 0         0 # "\U\l" --> "\l\U"
6823             elsif (($char[$i] eq '\U') and ($char[$i+1] eq '\l')) {
6824             @char[$i,$i+1] = @char[$i+1,$i];
6825             }
6826              
6827 0         0 # octal escape sequence
6828             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
6829             $char[$i] = Ecyrillic::octchr($1);
6830             }
6831              
6832 1         3 # hexadecimal escape sequence
6833             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
6834             $char[$i] = Ecyrillic::hexchr($1);
6835             }
6836              
6837             # \b{...} --> b\{...}
6838             # \B{...} --> B\{...}
6839             # \N{CHARNAME} --> N\{CHARNAME}
6840             # \p{PROPERTY} --> p\{PROPERTY}
6841 1         4 # \P{PROPERTY} --> P\{PROPERTY}
6842             elsif ($char[$i] =~ /\A \\ ([bBNpP]) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
6843             $char[$i] = $1 . '\\' . $2;
6844             }
6845              
6846 0         0 # \p, \P, \X --> p, P, X
6847             elsif ($char[$i] =~ /\A \\ ( [pPX] ) \z/oxms) {
6848             $char[$i] = $1;
6849 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          
6850              
6851             if (0) {
6852             }
6853 249         788  
6854 0 0 0     0 # join separated multiple-octet
    0 0        
    0 0        
      0        
      0        
      0        
6855 0         0 elsif ($char[$i] =~ /\A (?: \\ [0-7]{2,3} | \\x [0-9A-Fa-f]{1,2}) \z/oxms) {
6856             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)) {
6857             $char[$i] .= join '', splice @char, $i+1, 3;
6858 0         0 }
6859             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)) {
6860             $char[$i] .= join '', splice @char, $i+1, 2;
6861 0         0 }
6862             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)) {
6863             $char[$i] .= join '', splice @char, $i+1, 1;
6864             }
6865             }
6866              
6867 0         0 # open character class [...]
6868 3 50       6 elsif ($char[$i] eq '[') {
6869 3         11 my $left = $i;
6870             if ($char[$i+1] eq ']') {
6871 0         0 $i++;
6872 3 50       4 }
6873 7         21 while (1) {
6874             if (++$i > $#char) {
6875 0 100       0 die __FILE__, ": Unmatched [] in regexp\n";
6876 7         16 }
6877             if ($char[$i] eq ']') {
6878             my $right = $i;
6879 3 50       19  
6880 3         16 # [...]
  0         0  
6881             if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
6882             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);
6883 0         0 }
6884             else {
6885             splice @char, $left, $right-$left+1, Ecyrillic::charlist_qr(@char[$left+1..$right-1], $modifier);
6886 3         15 }
6887 3         6  
6888             $i = $left;
6889             last;
6890             }
6891             }
6892             }
6893              
6894 3         7 # open character class [^...]
6895 0 0       0 elsif ($char[$i] eq '[^') {
6896 0         0 my $left = $i;
6897             if ($char[$i+1] eq ']') {
6898 0         0 $i++;
6899 0 0       0 }
6900 0         0 while (1) {
6901             if (++$i > $#char) {
6902 0 0       0 die __FILE__, ": Unmatched [] in regexp\n";
6903 0         0 }
6904             if ($char[$i] eq ']') {
6905             my $right = $i;
6906 0 0       0  
6907 0         0 # [^...]
  0         0  
6908             if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
6909             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);
6910 0         0 }
6911             else {
6912             splice @char, $left, $right-$left+1, Ecyrillic::charlist_not_qr(@char[$left+1..$right-1], $modifier);
6913 0         0 }
6914 0         0  
6915             $i = $left;
6916             last;
6917             }
6918             }
6919             }
6920              
6921 0         0 # rewrite character class or escape character
6922             elsif (my $char = character_class($char[$i],$modifier)) {
6923             $char[$i] = $char;
6924             }
6925              
6926             # P.794 29.2.161. split
6927             # in Chapter 29: Functions
6928             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
6929              
6930             # P.951 split
6931             # in Chapter 27: Functions
6932             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
6933              
6934             # said "The //m modifier is assumed when you split on the pattern /^/",
6935             # but perl5.008 is not so. Therefore, this software adds //m.
6936             # (and so on)
6937              
6938 1         3 # split(m/^/) --> split(m/^/m)
6939             elsif (($char[$i] eq '^') and ($modifier !~ /m/oxms)) {
6940             $modifier .= 'm';
6941             }
6942              
6943 7 0       24 # /i modifier
6944 0         0 elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Ecyrillic::uc($char[$i]) ne Ecyrillic::fc($char[$i]))) {
6945             if (CORE::length(Ecyrillic::fc($char[$i])) == 1) {
6946             $char[$i] = '[' . Ecyrillic::uc($char[$i]) . Ecyrillic::fc($char[$i]) . ']';
6947 0         0 }
6948             else {
6949             $char[$i] = '(?:' . Ecyrillic::uc($char[$i]) . '|' . Ecyrillic::fc($char[$i]) . ')';
6950             }
6951             }
6952              
6953 0 0       0 # \u \l \U \L \F \Q \E
6954 0         0 elsif ($char[$i] =~ /\A ([<>]) \z/oxms) {
6955             if ($right_e < $left_e) {
6956             $char[$i] = '\\' . $char[$i];
6957             }
6958 0         0 }
6959 0         0 elsif ($char[$i] eq '\u') {
6960             $char[$i] = '@{[Ecyrillic::ucfirst qq<';
6961             $left_e++;
6962 0         0 }
6963 0         0 elsif ($char[$i] eq '\l') {
6964             $char[$i] = '@{[Ecyrillic::lcfirst qq<';
6965             $left_e++;
6966 0         0 }
6967 0         0 elsif ($char[$i] eq '\U') {
6968             $char[$i] = '@{[Ecyrillic::uc qq<';
6969             $left_e++;
6970 0         0 }
6971 0         0 elsif ($char[$i] eq '\L') {
6972             $char[$i] = '@{[Ecyrillic::lc qq<';
6973             $left_e++;
6974 0         0 }
6975 0         0 elsif ($char[$i] eq '\F') {
6976             $char[$i] = '@{[Ecyrillic::fc qq<';
6977             $left_e++;
6978 0         0 }
6979 0         0 elsif ($char[$i] eq '\Q') {
6980             $char[$i] = '@{[CORE::quotemeta qq<';
6981             $left_e++;
6982 0 0       0 }
6983 0         0 elsif ($char[$i] eq '\E') {
6984 0         0 if ($right_e < $left_e) {
6985             $char[$i] = '>]}';
6986             $right_e++;
6987 0         0 }
6988             else {
6989             $char[$i] = '';
6990             }
6991 0         0 }
6992 0 0       0 elsif ($char[$i] eq '\Q') {
6993 0         0 while (1) {
6994             if (++$i > $#char) {
6995 0 0       0 last;
6996 0         0 }
6997             if ($char[$i] eq '\E') {
6998             last;
6999             }
7000             }
7001             }
7002             elsif ($char[$i] eq '\E') {
7003             }
7004              
7005 0 0       0 # $0 --> $0
7006 0         0 elsif ($char[$i] =~ /\A \$ 0 \z/oxms) {
7007             if ($ignorecase) {
7008             $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
7009             }
7010 0 0       0 }
7011 0         0 elsif ($char[$i] =~ /\A \$ \{ (?>\s*) 0 (?>\s*) \} \z/oxms) {
7012             if ($ignorecase) {
7013             $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
7014             }
7015             }
7016              
7017             # $$ --> $$
7018             elsif ($char[$i] =~ /\A \$\$ \z/oxms) {
7019             }
7020              
7021             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
7022 0         0 # $1, $2, $3 --> $1, $2, $3 otherwise
7023 0 0       0 elsif ($char[$i] =~ /\A \$ ((?>[1-9][0-9]*)) \z/oxms) {
7024 0         0 $char[$i] = e_capture($1);
7025             if ($ignorecase) {
7026             $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
7027             }
7028 0         0 }
7029 0 0       0 elsif ($char[$i] =~ /\A \$ \{ (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} \z/oxms) {
7030 0         0 $char[$i] = e_capture($1);
7031             if ($ignorecase) {
7032             $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
7033             }
7034             }
7035              
7036 0         0 # $$foo[ ... ] --> $ $foo->[ ... ]
7037 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) {
7038 0         0 $char[$i] = e_capture($1.'->'.$2);
7039             if ($ignorecase) {
7040             $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
7041             }
7042             }
7043              
7044 0         0 # $$foo{ ... } --> $ $foo->{ ... }
7045 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) {
7046 0         0 $char[$i] = e_capture($1.'->'.$2);
7047             if ($ignorecase) {
7048             $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
7049             }
7050             }
7051              
7052 0         0 # $$foo
7053 0 0       0 elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) \z/oxms) {
7054 0         0 $char[$i] = e_capture($1);
7055             if ($ignorecase) {
7056             $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
7057             }
7058             }
7059              
7060 0 50       0 # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Ecyrillic::PREMATCH()
7061 12         35 elsif ($char[$i] =~ /\A ( \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} ) \z/oxmsgc) {
7062             if ($ignorecase) {
7063             $char[$i] = '@{[Ecyrillic::ignorecase(Ecyrillic::PREMATCH())]}';
7064 0         0 }
7065             else {
7066             $char[$i] = '@{[Ecyrillic::PREMATCH()]}';
7067             }
7068             }
7069              
7070 12 50       53 # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Ecyrillic::MATCH()
7071 12         48 elsif ($char[$i] =~ /\A ( \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} ) \z/oxmsgc) {
7072             if ($ignorecase) {
7073             $char[$i] = '@{[Ecyrillic::ignorecase(Ecyrillic::MATCH())]}';
7074 0         0 }
7075             else {
7076             $char[$i] = '@{[Ecyrillic::MATCH()]}';
7077             }
7078             }
7079              
7080 12 50       55 # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Ecyrillic::POSTMATCH()
7081 9         32 elsif ($char[$i] =~ /\A ( \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} ) \z/oxmsgc) {
7082             if ($ignorecase) {
7083             $char[$i] = '@{[Ecyrillic::ignorecase(Ecyrillic::POSTMATCH())]}';
7084 0         0 }
7085             else {
7086             $char[$i] = '@{[Ecyrillic::POSTMATCH()]}';
7087             }
7088             }
7089              
7090 9 0       54 # ${ foo }
7091 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) {
7092             if ($ignorecase) {
7093             $char[$i] = '@{[Ecyrillic::ignorecase(' . $1 . ')]}';
7094             }
7095             }
7096              
7097 0         0 # ${ ... }
7098 0 0       0 elsif ($char[$i] =~ /\A \$ (?>\s*) \{ ( .+ ) \} \z/oxms) {
7099 0         0 $char[$i] = e_capture($1);
7100             if ($ignorecase) {
7101             $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
7102             }
7103             }
7104              
7105 0         0 # $scalar or @array
7106 3 50       11 elsif ($char[$i] =~ /\A [\$\@].+ /oxms) {
7107 3         13 $char[$i] = e_string($char[$i]);
7108             if ($ignorecase) {
7109             $char[$i] = '@{[Ecyrillic::ignorecase(' . $char[$i] . ')]}';
7110             }
7111             }
7112              
7113 0 50       0 # quote character before ? + * {
7114             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
7115             if ($char[$i-1] =~ /\A (?:[\x00-\xFF]|\\[0-7]{2,3}|\\x[0-9-A-Fa-f]{1,2}) \z/oxms) {
7116 1         7 }
7117             else {
7118             $char[$i-1] = '(?:' . $char[$i-1] . ')';
7119             }
7120             }
7121             }
7122 0         0  
7123 74 50       152 # make regexp string
7124 74         156 $modifier =~ tr/i//d;
7125             if ($left_e > $right_e) {
7126 0         0 return join '', 'Ecyrillic::split', $ope, $delimiter, @char, '>]}' x ($left_e - $right_e), $end_delimiter, $modifier;
7127             }
7128             return join '', 'Ecyrillic::split', $ope, $delimiter, @char, $end_delimiter, $modifier;
7129             }
7130              
7131             #
7132             # escape regexp of split qr''
7133 74     0 0 725 #
7134 0   0       sub e_split_q {
7135             my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
7136 0           $modifier ||= '';
7137 0 0          
7138 0           $modifier =~ tr/p//d;
7139 0           if ($modifier =~ /([adlu])/oxms) {
7140 0 0         my $line = 0;
7141 0           for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
7142 0           if ($filename ne __FILE__) {
7143             $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
7144             last;
7145 0           }
7146             }
7147             die qq{Unsupported modifier "$1" used at line $line.\n};
7148 0           }
7149              
7150             $slash = 'div';
7151 0 0          
7152 0           # /b /B modifier
7153             if ($modifier =~ tr/bB//d) {
7154             return join '', 'split', $ope, $delimiter, $string, $end_delimiter, $modifier;
7155 0 0         }
7156              
7157             my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
7158 0            
7159             # split regexp
7160             my @char = $string =~ /\G((?>
7161             [^\\\[] |
7162             [\x00-\xFF] |
7163             \[\^ |
7164             \[\: (?>[a-z]+) \:\] |
7165             \[\:\^ (?>[a-z]+) \:\] |
7166             \\ (?:$q_char) |
7167             (?:$q_char)
7168             ))/oxmsg;
7169 0            
7170 0 0 0       # unescape character
    0 0        
    0 0        
    0 0        
    0          
    0          
7171             for (my $i=0; $i <= $#char; $i++) {
7172             if (0) {
7173             }
7174 0            
7175 0           # open character class [...]
7176 0 0         elsif ($char[$i] eq '[') {
7177 0           my $left = $i;
7178             if ($char[$i+1] eq ']') {
7179 0           $i++;
7180 0 0         }
7181 0           while (1) {
7182             if (++$i > $#char) {
7183 0 0         die __FILE__, ": Unmatched [] in regexp\n";
7184 0           }
7185             if ($char[$i] eq ']') {
7186             my $right = $i;
7187 0            
7188             # [...]
7189 0           splice @char, $left, $right-$left+1, Ecyrillic::charlist_qr(@char[$left+1..$right-1], $modifier);
7190 0            
7191             $i = $left;
7192             last;
7193             }
7194             }
7195             }
7196              
7197 0           # open character class [^...]
7198 0 0         elsif ($char[$i] eq '[^') {
7199 0           my $left = $i;
7200             if ($char[$i+1] eq ']') {
7201 0           $i++;
7202 0 0         }
7203 0           while (1) {
7204             if (++$i > $#char) {
7205 0 0         die __FILE__, ": Unmatched [] in regexp\n";
7206 0           }
7207             if ($char[$i] eq ']') {
7208             my $right = $i;
7209 0            
7210             # [^...]
7211 0           splice @char, $left, $right-$left+1, Ecyrillic::charlist_not_qr(@char[$left+1..$right-1], $modifier);
7212 0            
7213             $i = $left;
7214             last;
7215             }
7216             }
7217             }
7218              
7219 0           # rewrite character class or escape character
7220             elsif (my $char = character_class($char[$i],$modifier)) {
7221             $char[$i] = $char;
7222             }
7223              
7224 0           # split(m/^/) --> split(m/^/m)
7225             elsif (($char[$i] eq '^') and ($modifier !~ /m/oxms)) {
7226             $modifier .= 'm';
7227             }
7228              
7229 0 0         # /i modifier
7230 0           elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Ecyrillic::uc($char[$i]) ne Ecyrillic::fc($char[$i]))) {
7231             if (CORE::length(Ecyrillic::fc($char[$i])) == 1) {
7232             $char[$i] = '[' . Ecyrillic::uc($char[$i]) . Ecyrillic::fc($char[$i]) . ']';
7233 0           }
7234             else {
7235             $char[$i] = '(?:' . Ecyrillic::uc($char[$i]) . '|' . Ecyrillic::fc($char[$i]) . ')';
7236             }
7237             }
7238              
7239 0 0         # quote character before ? + * {
7240             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
7241             if ($char[$i-1] =~ /\A [\x00-\xFF] \z/oxms) {
7242 0           }
7243             else {
7244             $char[$i-1] = '(?:' . $char[$i-1] . ')';
7245             }
7246             }
7247 0           }
7248 0            
7249             $modifier =~ tr/i//d;
7250             return join '', 'Ecyrillic::split', $ope, $delimiter, @char, $end_delimiter, $modifier;
7251             }
7252              
7253             #
7254             # instead of Carp::carp
7255 0     0 0   #
7256 0           sub carp {
7257             my($package,$filename,$line) = caller(1);
7258             print STDERR "@_ at $filename line $line.\n";
7259             }
7260              
7261             #
7262             # instead of Carp::croak
7263 0     0 0   #
7264 0           sub croak {
7265 0           my($package,$filename,$line) = caller(1);
7266             print STDERR "@_ at $filename line $line.\n";
7267             die "\n";
7268             }
7269              
7270             #
7271             # instead of Carp::cluck
7272 0     0 0   #
7273 0           sub cluck {
7274 0           my $i = 0;
7275 0           my @cluck = ();
7276 0           while (my($package,$filename,$line,$subroutine) = caller($i)) {
7277             push @cluck, "[$i] $filename($line) $package::$subroutine\n";
7278 0           $i++;
7279 0           }
7280 0           print STDERR CORE::reverse @cluck;
7281             print STDERR "\n";
7282             print STDERR @_;
7283             }
7284              
7285             #
7286             # instead of Carp::confess
7287 0     0 0   #
7288 0           sub confess {
7289 0           my $i = 0;
7290 0           my @confess = ();
7291 0           while (my($package,$filename,$line,$subroutine) = caller($i)) {
7292             push @confess, "[$i] $filename($line) $package::$subroutine\n";
7293 0           $i++;
7294 0           }
7295 0           print STDERR CORE::reverse @confess;
7296 0           print STDERR "\n";
7297             print STDERR @_;
7298             die "\n";
7299             }
7300              
7301             1;
7302              
7303             __END__