File Coverage

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