File Coverage

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


line stmt bran cond sub pod time code
1             package Ekoi8r;
2             ######################################################################
3             #
4             # Ekoi8r - Run-time routines for KOI8R.pm
5             #
6             # http://search.cpan.org/dist/Char-KOI8R/
7             #
8             # Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 INABA Hitoshi
9             ######################################################################
10              
11 200     200   3521 use 5.00503; # Galapagos Consensus 1998 for primetools
  200         550  
12             # use 5.008001; # Lancaster Consensus 2013 for toolchains
13              
14             # 12.3. Delaying use Until Runtime
15             # in Chapter 12. Packages, Libraries, and Modules
16             # of ISBN 0-596-00313-7 Perl Cookbook, 2nd Edition.
17             # (and so on)
18              
19             # Version numbers should be boring
20             # http://www.dagolden.com/index.php/369/version-numbers-should-be-boring/
21             # For the impatient, the disinterested or those who just want to follow
22             # a recipe, my advice for all modules is this:
23             # our $VERSION = "0.001"; # or "0.001_001" for a dev release
24             # $VERSION = eval $VERSION;
25              
26 200     200   12616 BEGIN { CORE::eval q{ use vars qw($VERSION) } }
  200     200   1051  
  200         301  
  200         28751  
27             $VERSION = '1.08';
28             $VERSION = CORE::eval $VERSION;
29              
30             BEGIN {
31 200 50   200   1212 if ($^X =~ / jperl /oxmsi) {
32 0         0 die __FILE__, ": needs perl(not jperl) 5.00503 or later. (\$^X==$^X)\n";
33             }
34 200         271 if (CORE::ord('A') == 193) {
35             die __FILE__, ": is not US-ASCII script (may be EBCDIC or EBCDIK script).\n";
36             }
37 200         27156 if (CORE::ord('A') != 0x41) {
38             die __FILE__, ": is not US-ASCII script (must be US-ASCII script).\n";
39             }
40             }
41              
42             BEGIN {
43              
44             # instead of utf8.pm
45 200     200   12600 CORE::eval q{
  200     200   1003  
  200     75   303  
  200         24094  
  59         5327  
  34         3068  
  48         4305  
  59         5765  
46             no warnings qw(redefine);
47             *utf8::upgrade = sub { CORE::length $_[0] };
48             *utf8::downgrade = sub { 1 };
49             *utf8::encode = sub { };
50             *utf8::decode = sub { 1 };
51             *utf8::is_utf8 = sub { };
52             *utf8::valid = sub { 1 };
53             };
54 200 50       105031 if ($@) {
55 0         0 *utf8::upgrade = sub { CORE::length $_[0] };
  0         0  
56 0         0 *utf8::downgrade = sub { 1 };
  0         0  
57 0         0 *utf8::encode = sub { };
58 0         0 *utf8::decode = sub { 1 };
  0         0  
59 0         0 *utf8::is_utf8 = sub { };
60 0         0 *utf8::valid = sub { 1 };
  0         0  
61             }
62             }
63              
64             # instead of Symbol.pm
65 0         0 BEGIN {
66 200     200   490 my $genpkg = "Symbol::";
67 200         9372 my $genseq = 0;
68              
69             sub gensym () {
70 0     0 0 0 my $name = "GEN" . $genseq++;
71              
72             # here, no strict qw(refs); if strict.pm exists
73              
74 0         0 my $ref = \*{$genpkg . $name};
  0         0  
75 0         0 delete $$genpkg{$name};
76 0         0 return $ref;
77             }
78              
79             sub qualify ($;$) {
80 0     0 0 0 my ($name) = @_;
81 0 0 0     0 if (!ref($name) && (Ekoi8r::index($name, '::') == -1) && (Ekoi8r::index($name, "'") == -1)) {
      0        
82 0         0 my $pkg;
83 0         0 my %global = map {$_ => 1} qw(ARGV ARGVOUT ENV INC SIG STDERR STDIN STDOUT DATA);
  0         0  
84              
85             # Global names: special character, "^xyz", or other.
86 0 0 0     0 if ($name =~ /^(([^a-z])|(\^[a-z_]+))\z/i || $global{$name}) {
87             # RGS 2001-11-05 : translate leading ^X to control-char
88 0         0 $name =~ s/^\^([a-z_])/'qq(\c'.$1.')'/eei;
  0         0  
89 0         0 $pkg = "main";
90             }
91             else {
92 0 0       0 $pkg = (@_ > 1) ? $_[1] : caller;
93             }
94 0         0 $name = $pkg . "::" . $name;
95             }
96 0         0 return $name;
97             }
98              
99             sub qualify_to_ref ($;$) {
100              
101             # here, no strict qw(refs); if strict.pm exists
102              
103 0 0   0 0 0 return \*{ qualify $_[0], @_ > 1 ? $_[1] : caller };
  0         0  
104             }
105             }
106              
107             # Column: local $@
108             # in Chapter 9. Osaete okitai Perl no kiso
109             # of ISBN 10: 4798119172 | ISBN 13: 978-4798119175 MODAN Perl NYUMON
110             # (and so on)
111              
112             # use strict; if strict.pm exists
113             BEGIN {
114 200 50   200   357 if (CORE::eval { local $@; CORE::require strict }) {
  200         324  
  200         1980  
115 200         21479 strict::->import;
116             }
117             }
118              
119             # P.714 29.2.39. flock
120             # in Chapter 29: Functions
121             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
122              
123             # P.863 flock
124             # in Chapter 27: Functions
125             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
126              
127             sub LOCK_SH() {1}
128             sub LOCK_EX() {2}
129             sub LOCK_UN() {8}
130             sub LOCK_NB() {4}
131              
132             # instead of Carp.pm
133             sub carp;
134             sub croak;
135             sub cluck;
136             sub confess;
137              
138             # 6.18. Matching Multiple-Byte Characters
139             # in Chapter 6. Pattern Matching
140             # of ISBN 978-1-56592-243-3 Perl Perl Cookbook.
141             # (and so on)
142              
143             # regexp of character
144 200     200   13607 BEGIN { CORE::eval q{ use vars qw($your_char) } } $your_char = q{[\x00-\xFF]};
  200     200   1144  
  200         262  
  200         10857  
145 200     200   11464 BEGIN { CORE::eval q{ use vars qw($qq_char ) } } $qq_char = qr/\\c[\x40-\x5F]|\\?(?:$your_char)/oxms;
  200     200   926  
  200         276  
  200         11644  
146 200     200   10961 BEGIN { CORE::eval q{ use vars qw($q_char ) } } $q_char = qr/$your_char/oxms;
  200     200   896  
  200         274  
  200         16614  
147              
148             #
149             # KOI8-R character range per length
150             #
151             my %range_tr = ();
152              
153             #
154             # alias of encoding name
155             #
156 200     200   11502 BEGIN { CORE::eval q{ use vars qw($encoding_alias) } }
  200     200   1021  
  200         345  
  200         314478  
157              
158             #
159             # KOI8-R case conversion
160             #
161             my %lc = ();
162             @lc{qw(A B C D E F G H I J K L M N O P Q R S T U V W X Y Z)} =
163             qw(a b c d e f g h i j k l m n o p q r s t u v w x y z);
164             my %uc = ();
165             @uc{qw(a b c d e f g h i j k l m n o p q r s t u v w x y z)} =
166             qw(A B C D E F G H I J K L M N O P Q R S T U V W X Y Z);
167             my %fc = ();
168             @fc{qw(A B C D E F G H I J K L M N O P Q R S T U V W X Y Z)} =
169             qw(a b c d e f g h i j k l m n o p q r s t u v w x y z);
170              
171             if (0) {
172             }
173              
174             elsif (__PACKAGE__ =~ / \b Ekoi8r \z/oxms) {
175             %range_tr = (
176             1 => [ [0x00..0xFF],
177             ],
178             );
179             $encoding_alias = qr/ \b (?: koi8-?r ) \b /oxmsi;
180              
181             %lc = (%lc,
182             "\xB3" => "\xA3", # CYRILLIC LETTER IO
183             "\xE0" => "\xC0", # CYRILLIC LETTER IU
184             "\xE1" => "\xC1", # CYRILLIC LETTER A
185             "\xE2" => "\xC2", # CYRILLIC LETTER BE
186             "\xE3" => "\xC3", # CYRILLIC LETTER TSE
187             "\xE4" => "\xC4", # CYRILLIC LETTER DE
188             "\xE5" => "\xC5", # CYRILLIC LETTER IE
189             "\xE6" => "\xC6", # CYRILLIC LETTER EF
190             "\xE7" => "\xC7", # CYRILLIC LETTER GE
191             "\xE8" => "\xC8", # CYRILLIC LETTER KHA
192             "\xE9" => "\xC9", # CYRILLIC LETTER II
193             "\xEA" => "\xCA", # CYRILLIC LETTER SHORT II
194             "\xEB" => "\xCB", # CYRILLIC LETTER KA
195             "\xEC" => "\xCC", # CYRILLIC LETTER EL
196             "\xED" => "\xCD", # CYRILLIC LETTER EM
197             "\xEE" => "\xCE", # CYRILLIC LETTER EN
198             "\xEF" => "\xCF", # CYRILLIC LETTER O
199             "\xF0" => "\xD0", # CYRILLIC LETTER PE
200             "\xF1" => "\xD1", # CYRILLIC LETTER IA
201             "\xF2" => "\xD2", # CYRILLIC LETTER ER
202             "\xF3" => "\xD3", # CYRILLIC LETTER ES
203             "\xF4" => "\xD4", # CYRILLIC LETTER TE
204             "\xF5" => "\xD5", # CYRILLIC LETTER U
205             "\xF6" => "\xD6", # CYRILLIC LETTER ZHE
206             "\xF7" => "\xD7", # CYRILLIC LETTER VE
207             "\xF8" => "\xD8", # CYRILLIC LETTER SOFT SIGN
208             "\xF9" => "\xD9", # CYRILLIC LETTER YERI
209             "\xFA" => "\xDA", # CYRILLIC LETTER ZE
210             "\xFB" => "\xDB", # CYRILLIC LETTER SHA
211             "\xFC" => "\xDC", # CYRILLIC LETTER REVERSED E
212             "\xFD" => "\xDD", # CYRILLIC LETTER SHCHA
213             "\xFE" => "\xDE", # CYRILLIC LETTER CHE
214             "\xFF" => "\xDF", # CYRILLIC LETTER HARD SIGN
215             );
216              
217             %uc = (%uc,
218             "\xA3" => "\xB3", # CYRILLIC LETTER IO
219             "\xC0" => "\xE0", # CYRILLIC LETTER IU
220             "\xC1" => "\xE1", # CYRILLIC LETTER A
221             "\xC2" => "\xE2", # CYRILLIC LETTER BE
222             "\xC3" => "\xE3", # CYRILLIC LETTER TSE
223             "\xC4" => "\xE4", # CYRILLIC LETTER DE
224             "\xC5" => "\xE5", # CYRILLIC LETTER IE
225             "\xC6" => "\xE6", # CYRILLIC LETTER EF
226             "\xC7" => "\xE7", # CYRILLIC LETTER GE
227             "\xC8" => "\xE8", # CYRILLIC LETTER KHA
228             "\xC9" => "\xE9", # CYRILLIC LETTER II
229             "\xCA" => "\xEA", # CYRILLIC LETTER SHORT II
230             "\xCB" => "\xEB", # CYRILLIC LETTER KA
231             "\xCC" => "\xEC", # CYRILLIC LETTER EL
232             "\xCD" => "\xED", # CYRILLIC LETTER EM
233             "\xCE" => "\xEE", # CYRILLIC LETTER EN
234             "\xCF" => "\xEF", # CYRILLIC LETTER O
235             "\xD0" => "\xF0", # CYRILLIC LETTER PE
236             "\xD1" => "\xF1", # CYRILLIC LETTER IA
237             "\xD2" => "\xF2", # CYRILLIC LETTER ER
238             "\xD3" => "\xF3", # CYRILLIC LETTER ES
239             "\xD4" => "\xF4", # CYRILLIC LETTER TE
240             "\xD5" => "\xF5", # CYRILLIC LETTER U
241             "\xD6" => "\xF6", # CYRILLIC LETTER ZHE
242             "\xD7" => "\xF7", # CYRILLIC LETTER VE
243             "\xD8" => "\xF8", # CYRILLIC LETTER SOFT SIGN
244             "\xD9" => "\xF9", # CYRILLIC LETTER YERI
245             "\xDA" => "\xFA", # CYRILLIC LETTER ZE
246             "\xDB" => "\xFB", # CYRILLIC LETTER SHA
247             "\xDC" => "\xFC", # CYRILLIC LETTER REVERSED E
248             "\xDD" => "\xFD", # CYRILLIC LETTER SHCHA
249             "\xDE" => "\xFE", # CYRILLIC LETTER CHE
250             "\xDF" => "\xFF", # CYRILLIC LETTER HARD SIGN
251             );
252              
253             %fc = (%fc,
254             "\xB3" => "\xA3", # CYRILLIC CAPITAL LETTER IO --> CYRILLIC SMALL LETTER IO
255             "\xE0" => "\xC0", # CYRILLIC CAPITAL LETTER YU --> CYRILLIC SMALL LETTER YU
256             "\xE1" => "\xC1", # CYRILLIC CAPITAL LETTER A --> CYRILLIC SMALL LETTER A
257             "\xE2" => "\xC2", # CYRILLIC CAPITAL LETTER BE --> CYRILLIC SMALL LETTER BE
258             "\xE3" => "\xC3", # CYRILLIC CAPITAL LETTER TSE --> CYRILLIC SMALL LETTER TSE
259             "\xE4" => "\xC4", # CYRILLIC CAPITAL LETTER DE --> CYRILLIC SMALL LETTER DE
260             "\xE5" => "\xC5", # CYRILLIC CAPITAL LETTER IE --> CYRILLIC SMALL LETTER IE
261             "\xE6" => "\xC6", # CYRILLIC CAPITAL LETTER EF --> CYRILLIC SMALL LETTER EF
262             "\xE7" => "\xC7", # CYRILLIC CAPITAL LETTER GHE --> CYRILLIC SMALL LETTER GHE
263             "\xE8" => "\xC8", # CYRILLIC CAPITAL LETTER HA --> CYRILLIC SMALL LETTER HA
264             "\xE9" => "\xC9", # CYRILLIC CAPITAL LETTER I --> CYRILLIC SMALL LETTER I
265             "\xEA" => "\xCA", # CYRILLIC CAPITAL LETTER SHORT I --> CYRILLIC SMALL LETTER SHORT I
266             "\xEB" => "\xCB", # CYRILLIC CAPITAL LETTER KA --> CYRILLIC SMALL LETTER KA
267             "\xEC" => "\xCC", # CYRILLIC CAPITAL LETTER EL --> CYRILLIC SMALL LETTER EL
268             "\xED" => "\xCD", # CYRILLIC CAPITAL LETTER EM --> CYRILLIC SMALL LETTER EM
269             "\xEE" => "\xCE", # CYRILLIC CAPITAL LETTER EN --> CYRILLIC SMALL LETTER EN
270             "\xEF" => "\xCF", # CYRILLIC CAPITAL LETTER O --> CYRILLIC SMALL LETTER O
271             "\xF0" => "\xD0", # CYRILLIC CAPITAL LETTER PE --> CYRILLIC SMALL LETTER PE
272             "\xF1" => "\xD1", # CYRILLIC CAPITAL LETTER YA --> CYRILLIC SMALL LETTER YA
273             "\xF2" => "\xD2", # CYRILLIC CAPITAL LETTER ER --> CYRILLIC SMALL LETTER ER
274             "\xF3" => "\xD3", # CYRILLIC CAPITAL LETTER ES --> CYRILLIC SMALL LETTER ES
275             "\xF4" => "\xD4", # CYRILLIC CAPITAL LETTER TE --> CYRILLIC SMALL LETTER TE
276             "\xF5" => "\xD5", # CYRILLIC CAPITAL LETTER U --> CYRILLIC SMALL LETTER U
277             "\xF6" => "\xD6", # CYRILLIC CAPITAL LETTER ZHE --> CYRILLIC SMALL LETTER ZHE
278             "\xF7" => "\xD7", # CYRILLIC CAPITAL LETTER VE --> CYRILLIC SMALL LETTER VE
279             "\xF8" => "\xD8", # CYRILLIC CAPITAL LETTER SOFT SIGN --> CYRILLIC SMALL LETTER SOFT SIGN
280             "\xF9" => "\xD9", # CYRILLIC CAPITAL LETTER YERU --> CYRILLIC SMALL LETTER YERU
281             "\xFA" => "\xDA", # CYRILLIC CAPITAL LETTER ZE --> CYRILLIC SMALL LETTER ZE
282             "\xFB" => "\xDB", # CYRILLIC CAPITAL LETTER SHA --> CYRILLIC SMALL LETTER SHA
283             "\xFC" => "\xDC", # CYRILLIC CAPITAL LETTER E --> CYRILLIC SMALL LETTER E
284             "\xFD" => "\xDD", # CYRILLIC CAPITAL LETTER SHCHA --> CYRILLIC SMALL LETTER SHCHA
285             "\xFE" => "\xDE", # CYRILLIC CAPITAL LETTER CHE --> CYRILLIC SMALL LETTER CHE
286             "\xFF" => "\xDF", # CYRILLIC CAPITAL LETTER HARD SIGN --> CYRILLIC SMALL LETTER HARD SIGN
287             );
288             }
289              
290             else {
291             croak "Don't know my package name '@{[__PACKAGE__]}'";
292             }
293              
294             #
295             # @ARGV wildcard globbing
296             #
297             sub import {
298              
299 0 0   0   0 if ($^O =~ /\A (?: MSWin32 | NetWare | symbian | dos ) \z/oxms) {
300 0         0 my @argv = ();
301 0         0 for (@ARGV) {
302              
303             # has space
304 0 0       0 if (/\A (?:$q_char)*? [ ] /oxms) {
    0          
305 0 0       0 if (my @glob = Ekoi8r::glob(qq{"$_"})) {
306 0         0 push @argv, @glob;
307             }
308             else {
309 0         0 push @argv, $_;
310             }
311             }
312              
313             # has wildcard metachar
314             elsif (/\A (?:$q_char)*? [*?] /oxms) {
315 0 0       0 if (my @glob = Ekoi8r::glob($_)) {
316 0         0 push @argv, @glob;
317             }
318             else {
319 0         0 push @argv, $_;
320             }
321             }
322              
323             # no wildcard globbing
324             else {
325 0         0 push @argv, $_;
326             }
327             }
328 0         0 @ARGV = @argv;
329             }
330              
331 0         0 *Char::ord = \&KOI8R::ord;
332 0         0 *Char::ord_ = \&KOI8R::ord_;
333 0         0 *Char::reverse = \&KOI8R::reverse;
334 0         0 *Char::getc = \&KOI8R::getc;
335 0         0 *Char::length = \&KOI8R::length;
336 0         0 *Char::substr = \&KOI8R::substr;
337 0         0 *Char::index = \&KOI8R::index;
338 0         0 *Char::rindex = \&KOI8R::rindex;
339 0         0 *Char::eval = \&KOI8R::eval;
340 0         0 *Char::escape = \&KOI8R::escape;
341 0         0 *Char::escape_token = \&KOI8R::escape_token;
342 0         0 *Char::escape_script = \&KOI8R::escape_script;
343             }
344              
345             # P.230 Care with Prototypes
346             # in Chapter 6: Subroutines
347             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
348             #
349             # If you aren't careful, you can get yourself into trouble with prototypes.
350             # But if you are careful, you can do a lot of neat things with them. This is
351             # all very powerful, of course, and should only be used in moderation to make
352             # the world a better place.
353              
354             # P.332 Care with Prototypes
355             # in Chapter 7: Subroutines
356             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
357             #
358             # If you aren't careful, you can get yourself into trouble with prototypes.
359             # But if you are careful, you can do a lot of neat things with them. This is
360             # all very powerful, of course, and should only be used in moderation to make
361             # the world a better place.
362              
363             #
364             # Prototypes of subroutines
365             #
366       0     sub unimport {}
367             sub Ekoi8r::split(;$$$);
368             sub Ekoi8r::tr($$$$;$);
369             sub Ekoi8r::chop(@);
370             sub Ekoi8r::index($$;$);
371             sub Ekoi8r::rindex($$;$);
372             sub Ekoi8r::lcfirst(@);
373             sub Ekoi8r::lcfirst_();
374             sub Ekoi8r::lc(@);
375             sub Ekoi8r::lc_();
376             sub Ekoi8r::ucfirst(@);
377             sub Ekoi8r::ucfirst_();
378             sub Ekoi8r::uc(@);
379             sub Ekoi8r::uc_();
380             sub Ekoi8r::fc(@);
381             sub Ekoi8r::fc_();
382             sub Ekoi8r::ignorecase;
383             sub Ekoi8r::classic_character_class;
384             sub Ekoi8r::capture;
385             sub Ekoi8r::chr(;$);
386             sub Ekoi8r::chr_();
387             sub Ekoi8r::glob($);
388             sub Ekoi8r::glob_();
389              
390             sub KOI8R::ord(;$);
391             sub KOI8R::ord_();
392             sub KOI8R::reverse(@);
393             sub KOI8R::getc(;*@);
394             sub KOI8R::length(;$);
395             sub KOI8R::substr($$;$$);
396             sub KOI8R::index($$;$);
397             sub KOI8R::rindex($$;$);
398             sub KOI8R::escape(;$);
399              
400             #
401             # Regexp work
402             #
403 200     200   14266 BEGIN { CORE::eval q{ use vars qw(
  200     200   1450  
  200         303  
  200         72088  
404             $KOI8R::re_a
405             $KOI8R::re_t
406             $KOI8R::re_n
407             $KOI8R::re_r
408             ) } }
409              
410             #
411             # Character class
412             #
413 200     200   14773 BEGIN { CORE::eval q{ use vars qw(
  200     200   1001  
  200         303  
  200         2520815  
414             $dot
415             $dot_s
416             $eD
417             $eS
418             $eW
419             $eH
420             $eV
421             $eR
422             $eN
423             $not_alnum
424             $not_alpha
425             $not_ascii
426             $not_blank
427             $not_cntrl
428             $not_digit
429             $not_graph
430             $not_lower
431             $not_lower_i
432             $not_print
433             $not_punct
434             $not_space
435             $not_upper
436             $not_upper_i
437             $not_word
438             $not_xdigit
439             $eb
440             $eB
441             ) } }
442              
443             ${Ekoi8r::dot} = qr{(?>[^\x0A])};
444             ${Ekoi8r::dot_s} = qr{(?>[\x00-\xFF])};
445             ${Ekoi8r::eD} = qr{(?>[^0-9])};
446              
447             # Vertical tabs are now whitespace
448             # \s in a regex now matches a vertical tab in all circumstances.
449             # http://search.cpan.org/dist/perl-5.18.0/pod/perldelta.pod#Vertical_tabs_are_now_whitespace
450             # ${Ekoi8r::eS} = qr{(?>[^\x09\x0A \x0C\x0D\x20])};
451             # ${Ekoi8r::eS} = qr{(?>[^\x09\x0A\x0B\x0C\x0D\x20])};
452             ${Ekoi8r::eS} = qr{(?>[^\s])};
453              
454             ${Ekoi8r::eW} = qr{(?>[^0-9A-Z_a-z])};
455             ${Ekoi8r::eH} = qr{(?>[^\x09\x20])};
456             ${Ekoi8r::eV} = qr{(?>[^\x0A\x0B\x0C\x0D])};
457             ${Ekoi8r::eR} = qr{(?>\x0D\x0A|[\x0A\x0D])};
458             ${Ekoi8r::eN} = qr{(?>[^\x0A])};
459             ${Ekoi8r::not_alnum} = qr{(?>[^\x30-\x39\x41-\x5A\x61-\x7A])};
460             ${Ekoi8r::not_alpha} = qr{(?>[^\x41-\x5A\x61-\x7A])};
461             ${Ekoi8r::not_ascii} = qr{(?>[^\x00-\x7F])};
462             ${Ekoi8r::not_blank} = qr{(?>[^\x09\x20])};
463             ${Ekoi8r::not_cntrl} = qr{(?>[^\x00-\x1F\x7F])};
464             ${Ekoi8r::not_digit} = qr{(?>[^\x30-\x39])};
465             ${Ekoi8r::not_graph} = qr{(?>[^\x21-\x7F])};
466             ${Ekoi8r::not_lower} = qr{(?>[^\x61-\x7A])};
467             ${Ekoi8r::not_lower_i} = qr{(?>[^\x41-\x5A\x61-\x7A])}; # Perl 5.16 compatible
468             # ${Ekoi8r::not_lower_i} = qr{(?>[\x00-\xFF])}; # older Perl compatible
469             ${Ekoi8r::not_print} = qr{(?>[^\x20-\x7F])};
470             ${Ekoi8r::not_punct} = qr{(?>[^\x21-\x2F\x3A-\x3F\x40\x5B-\x5F\x60\x7B-\x7E])};
471             ${Ekoi8r::not_space} = qr{(?>[^\s\x0B])};
472             ${Ekoi8r::not_upper} = qr{(?>[^\x41-\x5A])};
473             ${Ekoi8r::not_upper_i} = qr{(?>[^\x41-\x5A\x61-\x7A])}; # Perl 5.16 compatible
474             # ${Ekoi8r::not_upper_i} = qr{(?>[\x00-\xFF])}; # older Perl compatible
475             ${Ekoi8r::not_word} = qr{(?>[^\x30-\x39\x41-\x5A\x5F\x61-\x7A])};
476             ${Ekoi8r::not_xdigit} = qr{(?>[^\x30-\x39\x41-\x46\x61-\x66])};
477             ${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))};
478             ${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]))};
479              
480             # avoid: Name "Ekoi8r::foo" used only once: possible typo at here.
481             ${Ekoi8r::dot} = ${Ekoi8r::dot};
482             ${Ekoi8r::dot_s} = ${Ekoi8r::dot_s};
483             ${Ekoi8r::eD} = ${Ekoi8r::eD};
484             ${Ekoi8r::eS} = ${Ekoi8r::eS};
485             ${Ekoi8r::eW} = ${Ekoi8r::eW};
486             ${Ekoi8r::eH} = ${Ekoi8r::eH};
487             ${Ekoi8r::eV} = ${Ekoi8r::eV};
488             ${Ekoi8r::eR} = ${Ekoi8r::eR};
489             ${Ekoi8r::eN} = ${Ekoi8r::eN};
490             ${Ekoi8r::not_alnum} = ${Ekoi8r::not_alnum};
491             ${Ekoi8r::not_alpha} = ${Ekoi8r::not_alpha};
492             ${Ekoi8r::not_ascii} = ${Ekoi8r::not_ascii};
493             ${Ekoi8r::not_blank} = ${Ekoi8r::not_blank};
494             ${Ekoi8r::not_cntrl} = ${Ekoi8r::not_cntrl};
495             ${Ekoi8r::not_digit} = ${Ekoi8r::not_digit};
496             ${Ekoi8r::not_graph} = ${Ekoi8r::not_graph};
497             ${Ekoi8r::not_lower} = ${Ekoi8r::not_lower};
498             ${Ekoi8r::not_lower_i} = ${Ekoi8r::not_lower_i};
499             ${Ekoi8r::not_print} = ${Ekoi8r::not_print};
500             ${Ekoi8r::not_punct} = ${Ekoi8r::not_punct};
501             ${Ekoi8r::not_space} = ${Ekoi8r::not_space};
502             ${Ekoi8r::not_upper} = ${Ekoi8r::not_upper};
503             ${Ekoi8r::not_upper_i} = ${Ekoi8r::not_upper_i};
504             ${Ekoi8r::not_word} = ${Ekoi8r::not_word};
505             ${Ekoi8r::not_xdigit} = ${Ekoi8r::not_xdigit};
506             ${Ekoi8r::eb} = ${Ekoi8r::eb};
507             ${Ekoi8r::eB} = ${Ekoi8r::eB};
508              
509             #
510             # KOI8-R split
511             #
512             sub Ekoi8r::split(;$$$) {
513              
514             # P.794 29.2.161. split
515             # in Chapter 29: Functions
516             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
517              
518             # P.951 split
519             # in Chapter 27: Functions
520             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
521              
522 0     0 0 0 my $pattern = $_[0];
523 0         0 my $string = $_[1];
524 0         0 my $limit = $_[2];
525              
526             # if $pattern is also omitted or is the literal space, " "
527 0 0       0 if (not defined $pattern) {
528 0         0 $pattern = ' ';
529             }
530              
531             # if $string is omitted, the function splits the $_ string
532 0 0       0 if (not defined $string) {
533 0 0       0 if (defined $_) {
534 0         0 $string = $_;
535             }
536             else {
537 0         0 $string = '';
538             }
539             }
540              
541 0         0 my @split = ();
542              
543             # when string is empty
544 0 0       0 if ($string eq '') {
    0          
545              
546             # resulting list value in list context
547 0 0       0 if (wantarray) {
548 0         0 return @split;
549             }
550              
551             # count of substrings in scalar context
552             else {
553 0 0       0 carp "Use of implicit split to \@_ is deprecated" if $^W;
554 0         0 @_ = @split;
555 0         0 return scalar @_;
556             }
557             }
558              
559             # split's first argument is more consistently interpreted
560             #
561             # After some changes earlier in v5.17, split's behavior has been simplified:
562             # if the PATTERN argument evaluates to a string containing one space, it is
563             # treated the way that a literal string containing one space once was.
564             # http://search.cpan.org/dist/perl-5.18.0/pod/perldelta.pod#split's_first_argument_is_more_consistently_interpreted
565              
566             # if $pattern is also omitted or is the literal space, " ", the function splits
567             # on whitespace, /\s+/, after skipping any leading whitespace
568             # (and so on)
569              
570             elsif ($pattern eq ' ') {
571 0 0       0 if (not defined $limit) {
572 0         0 return CORE::split(' ', $string);
573             }
574             else {
575 0         0 return CORE::split(' ', $string, $limit);
576             }
577             }
578              
579             # if $limit is negative, it is treated as if an arbitrarily large $limit has been specified
580 0 0 0     0 if ((not defined $limit) or ($limit <= 0)) {
    0          
581              
582             # a pattern capable of matching either the null string or something longer than the
583             # null string will split the value of $string into separate characters wherever it
584             # matches the null string between characters
585             # (and so on)
586              
587 0 0       0 if ('' =~ / \A $pattern \z /xms) {
588 0         0 my $last_subexpression_offsets = _last_subexpression_offsets($pattern);
589 0         0 my $limit = scalar(() = $string =~ /($pattern)/oxmsg);
590              
591             # P.1024 Appendix W.10 Multibyte Processing
592             # of ISBN 1-56592-224-7 CJKV Information Processing
593             # (and so on)
594              
595             # the //m modifier is assumed when you split on the pattern /^/
596             # (and so on)
597              
598             # V
599 0   0     0 while ((--$limit > 0) and ($string =~ s/\A((?:$q_char)+?)$pattern//m)) {
600              
601             # if the $pattern contains parentheses, then the substring matched by each pair of parentheses
602             # is included in the resulting list, interspersed with the fields that are ordinarily returned
603             # (and so on)
604              
605 0         0 local $@;
606 0         0 for (my $digit=1; $digit <= ($last_subexpression_offsets + 1); $digit++) {
607 0         0 push @split, CORE::eval('$' . $digit);
608             }
609             }
610             }
611              
612             else {
613 0         0 my $last_subexpression_offsets = _last_subexpression_offsets($pattern);
614              
615             # V
616 0         0 while ($string =~ s/\A((?:$q_char)*?)$pattern//m) {
617 0         0 local $@;
618 0         0 for (my $digit=1; $digit <= ($last_subexpression_offsets + 1); $digit++) {
619 0         0 push @split, CORE::eval('$' . $digit);
620             }
621             }
622             }
623             }
624              
625             elsif ($limit > 0) {
626 0 0       0 if ('' =~ / \A $pattern \z /xms) {
627 0         0 my $last_subexpression_offsets = _last_subexpression_offsets($pattern);
628 0   0     0 while ((--$limit > 0) and (CORE::length($string) > 0)) {
629              
630             # V
631 0 0       0 if ($string =~ s/\A((?:$q_char)+?)$pattern//m) {
632 0         0 local $@;
633 0         0 for (my $digit=1; $digit <= ($last_subexpression_offsets + 1); $digit++) {
634 0         0 push @split, CORE::eval('$' . $digit);
635             }
636             }
637             }
638             }
639             else {
640 0         0 my $last_subexpression_offsets = _last_subexpression_offsets($pattern);
641 0   0     0 while ((--$limit > 0) and (CORE::length($string) > 0)) {
642              
643             # V
644 0 0       0 if ($string =~ s/\A((?:$q_char)*?)$pattern//m) {
645 0         0 local $@;
646 0         0 for (my $digit=1; $digit <= ($last_subexpression_offsets + 1); $digit++) {
647 0         0 push @split, CORE::eval('$' . $digit);
648             }
649             }
650             }
651             }
652             }
653              
654 0 0       0 if (CORE::length($string) > 0) {
655 0         0 push @split, $string;
656             }
657              
658             # if $_[2] (NOT "$limit") is omitted or zero, trailing null fields are stripped from the result
659 0 0 0     0 if ((not defined $_[2]) or ($_[2] == 0)) {
660 0   0     0 while ((scalar(@split) >= 1) and ($split[-1] eq '')) {
661 0         0 pop @split;
662             }
663             }
664              
665             # resulting list value in list context
666 0 0       0 if (wantarray) {
667 0         0 return @split;
668             }
669              
670             # count of substrings in scalar context
671             else {
672 0 0       0 carp "Use of implicit split to \@_ is deprecated" if $^W;
673 0         0 @_ = @split;
674 0         0 return scalar @_;
675             }
676             }
677              
678             #
679             # get last subexpression offsets
680             #
681             sub _last_subexpression_offsets {
682 0     0   0 my $pattern = $_[0];
683              
684             # remove comment
685 0         0 $pattern =~ s/\(\?\# .*? \)//oxmsg;
686              
687 0         0 my $modifier = '';
688 0 0       0 if ($pattern =~ /\(\?\^? ([\-A-Za-z]+) :/oxms) {
689 0         0 $modifier = $1;
690 0         0 $modifier =~ s/-[A-Za-z]*//;
691             }
692              
693             # with /x modifier
694 0         0 my @char = ();
695 0 0       0 if ($modifier =~ /x/oxms) {
696 0         0 @char = $pattern =~ /\G((?>
697             [^\\\#\[\(] |
698             \\ $q_char |
699             \# (?>[^\n]*) $ |
700             \[ (?>(?:[^\\\]]|\\\\|\\\]|$q_char)+) \] |
701             \(\? |
702             $q_char
703             ))/oxmsg;
704             }
705              
706             # without /x modifier
707             else {
708 0         0 @char = $pattern =~ /\G((?>
709             [^\\\[\(] |
710             \\ $q_char |
711             \[ (?>(?:[^\\\]]|\\\\|\\\]|$q_char)+) \] |
712             \(\? |
713             $q_char
714             ))/oxmsg;
715             }
716              
717 0         0 return scalar grep { $_ eq '(' } @char;
  0         0  
718             }
719              
720             #
721             # KOI8-R transliteration (tr///)
722             #
723             sub Ekoi8r::tr($$$$;$) {
724              
725 0     0 0 0 my $bind_operator = $_[1];
726 0         0 my $searchlist = $_[2];
727 0         0 my $replacementlist = $_[3];
728 0   0     0 my $modifier = $_[4] || '';
729              
730 0 0       0 if ($modifier =~ /r/oxms) {
731 0 0       0 if ($bind_operator =~ / !~ /oxms) {
732 0         0 croak "Using !~ with tr///r doesn't make sense";
733             }
734             }
735              
736 0         0 my @char = $_[0] =~ /\G (?>$q_char) /oxmsg;
737 0         0 my @searchlist = _charlist_tr($searchlist);
738 0         0 my @replacementlist = _charlist_tr($replacementlist);
739              
740 0         0 my %tr = ();
741 0         0 for (my $i=0; $i <= $#searchlist; $i++) {
742 0 0       0 if (not exists $tr{$searchlist[$i]}) {
743 0 0 0     0 if (defined $replacementlist[$i] and ($replacementlist[$i] ne '')) {
    0 0        
    0          
744 0         0 $tr{$searchlist[$i]} = $replacementlist[$i];
745             }
746             elsif ($modifier =~ /d/oxms) {
747 0         0 $tr{$searchlist[$i]} = '';
748             }
749             elsif (defined $replacementlist[-1] and ($replacementlist[-1] ne '')) {
750 0         0 $tr{$searchlist[$i]} = $replacementlist[-1];
751             }
752             else {
753 0         0 $tr{$searchlist[$i]} = $searchlist[$i];
754             }
755             }
756             }
757              
758 0         0 my $tr = 0;
759 0         0 my $replaced = '';
760 0 0       0 if ($modifier =~ /c/oxms) {
761 0         0 while (defined(my $char = shift @char)) {
762 0 0       0 if (not exists $tr{$char}) {
763 0 0       0 if (defined $replacementlist[0]) {
764 0         0 $replaced .= $replacementlist[0];
765             }
766 0         0 $tr++;
767 0 0       0 if ($modifier =~ /s/oxms) {
768 0   0     0 while (@char and (not exists $tr{$char[0]})) {
769 0         0 shift @char;
770 0         0 $tr++;
771             }
772             }
773             }
774             else {
775 0         0 $replaced .= $char;
776             }
777             }
778             }
779             else {
780 0         0 while (defined(my $char = shift @char)) {
781 0 0       0 if (exists $tr{$char}) {
782 0         0 $replaced .= $tr{$char};
783 0         0 $tr++;
784 0 0       0 if ($modifier =~ /s/oxms) {
785 0   0     0 while (@char and (exists $tr{$char[0]}) and ($tr{$char[0]} eq $tr{$char})) {
      0        
786 0         0 shift @char;
787 0         0 $tr++;
788             }
789             }
790             }
791             else {
792 0         0 $replaced .= $char;
793             }
794             }
795             }
796              
797 0 0       0 if ($modifier =~ /r/oxms) {
798 0         0 return $replaced;
799             }
800             else {
801 0         0 $_[0] = $replaced;
802 0 0       0 if ($bind_operator =~ / !~ /oxms) {
803 0         0 return not $tr;
804             }
805             else {
806 0         0 return $tr;
807             }
808             }
809             }
810              
811             #
812             # KOI8-R chop
813             #
814             sub Ekoi8r::chop(@) {
815              
816 0     0 0 0 my $chop;
817 0 0       0 if (@_ == 0) {
818 0         0 my @char = /\G (?>$q_char) /oxmsg;
819 0         0 $chop = pop @char;
820 0         0 $_ = join '', @char;
821             }
822             else {
823 0         0 for (@_) {
824 0         0 my @char = /\G (?>$q_char) /oxmsg;
825 0         0 $chop = pop @char;
826 0         0 $_ = join '', @char;
827             }
828             }
829 0         0 return $chop;
830             }
831              
832             #
833             # KOI8-R index by octet
834             #
835             sub Ekoi8r::index($$;$) {
836              
837 0     0 1 0 my($str,$substr,$position) = @_;
838 0   0     0 $position ||= 0;
839 0         0 my $pos = 0;
840              
841 0         0 while ($pos < CORE::length($str)) {
842 0 0       0 if (CORE::substr($str,$pos,CORE::length($substr)) eq $substr) {
843 0 0       0 if ($pos >= $position) {
844 0         0 return $pos;
845             }
846             }
847 0 0       0 if (CORE::substr($str,$pos) =~ /\A ($q_char) /oxms) {
848 0         0 $pos += CORE::length($1);
849             }
850             else {
851 0         0 $pos += 1;
852             }
853             }
854 0         0 return -1;
855             }
856              
857             #
858             # KOI8-R reverse index
859             #
860             sub Ekoi8r::rindex($$;$) {
861              
862 0     0 0 0 my($str,$substr,$position) = @_;
863 0   0     0 $position ||= CORE::length($str) - 1;
864 0         0 my $pos = 0;
865 0         0 my $rindex = -1;
866              
867 0   0     0 while (($pos < CORE::length($str)) and ($pos <= $position)) {
868 0 0       0 if (CORE::substr($str,$pos,CORE::length($substr)) eq $substr) {
869 0         0 $rindex = $pos;
870             }
871 0 0       0 if (CORE::substr($str,$pos) =~ /\A ($q_char) /oxms) {
872 0         0 $pos += CORE::length($1);
873             }
874             else {
875 0         0 $pos += 1;
876             }
877             }
878 0         0 return $rindex;
879             }
880              
881             #
882             # KOI8-R lower case first with parameter
883             #
884             sub Ekoi8r::lcfirst(@) {
885 0 0   0 0 0 if (@_) {
886 0         0 my $s = shift @_;
887 0 0 0     0 if (@_ and wantarray) {
888 0         0 return Ekoi8r::lc(CORE::substr($s,0,1)) . CORE::substr($s,1), @_;
889             }
890             else {
891 0         0 return Ekoi8r::lc(CORE::substr($s,0,1)) . CORE::substr($s,1);
892             }
893             }
894             else {
895 0         0 return Ekoi8r::lc(CORE::substr($_,0,1)) . CORE::substr($_,1);
896             }
897             }
898              
899             #
900             # KOI8-R lower case first without parameter
901             #
902             sub Ekoi8r::lcfirst_() {
903 0     0 0 0 return Ekoi8r::lc(CORE::substr($_,0,1)) . CORE::substr($_,1);
904             }
905              
906             #
907             # KOI8-R lower case with parameter
908             #
909             sub Ekoi8r::lc(@) {
910 0 0   0 0 0 if (@_) {
911 0         0 my $s = shift @_;
912 0 0 0     0 if (@_ and wantarray) {
913 0 0       0 return join('', map {defined($lc{$_}) ? $lc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg)), @_;
  0         0  
914             }
915             else {
916 0 0       0 return join('', map {defined($lc{$_}) ? $lc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg));
  0         0  
917             }
918             }
919             else {
920 0         0 return Ekoi8r::lc_();
921             }
922             }
923              
924             #
925             # KOI8-R lower case without parameter
926             #
927             sub Ekoi8r::lc_() {
928 0     0 0 0 my $s = $_;
929 0 0       0 return join '', map {defined($lc{$_}) ? $lc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg);
  0         0  
930             }
931              
932             #
933             # KOI8-R upper case first with parameter
934             #
935             sub Ekoi8r::ucfirst(@) {
936 0 0   0 0 0 if (@_) {
937 0         0 my $s = shift @_;
938 0 0 0     0 if (@_ and wantarray) {
939 0         0 return Ekoi8r::uc(CORE::substr($s,0,1)) . CORE::substr($s,1), @_;
940             }
941             else {
942 0         0 return Ekoi8r::uc(CORE::substr($s,0,1)) . CORE::substr($s,1);
943             }
944             }
945             else {
946 0         0 return Ekoi8r::uc(CORE::substr($_,0,1)) . CORE::substr($_,1);
947             }
948             }
949              
950             #
951             # KOI8-R upper case first without parameter
952             #
953             sub Ekoi8r::ucfirst_() {
954 0     0 0 0 return Ekoi8r::uc(CORE::substr($_,0,1)) . CORE::substr($_,1);
955             }
956              
957             #
958             # KOI8-R upper case with parameter
959             #
960             sub Ekoi8r::uc(@) {
961 174 50   174 0 276 if (@_) {
962 174         188 my $s = shift @_;
963 174 50 33     423 if (@_ and wantarray) {
964 0 0       0 return join('', map {defined($uc{$_}) ? $uc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg)), @_;
  0         0  
965             }
966             else {
967 174 100       608 return join('', map {defined($uc{$_}) ? $uc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg));
  174         655  
968             }
969             }
970             else {
971 0         0 return Ekoi8r::uc_();
972             }
973             }
974              
975             #
976             # KOI8-R upper case without parameter
977             #
978             sub Ekoi8r::uc_() {
979 0     0 0 0 my $s = $_;
980 0 0       0 return join '', map {defined($uc{$_}) ? $uc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg);
  0         0  
981             }
982              
983             #
984             # KOI8-R fold case with parameter
985             #
986             sub Ekoi8r::fc(@) {
987 197 50   197 0 275 if (@_) {
988 197         197 my $s = shift @_;
989 197 50 33     407 if (@_ and wantarray) {
990 0 0       0 return join('', map {defined($fc{$_}) ? $fc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg)), @_;
  0         0  
991             }
992             else {
993 197 100       527 return join('', map {defined($fc{$_}) ? $fc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg));
  197         1406  
994             }
995             }
996             else {
997 0         0 return Ekoi8r::fc_();
998             }
999             }
1000              
1001             #
1002             # KOI8-R fold case without parameter
1003             #
1004             sub Ekoi8r::fc_() {
1005 0     0 0 0 my $s = $_;
1006 0 0       0 return join '', map {defined($fc{$_}) ? $fc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg);
  0         0  
1007             }
1008              
1009             #
1010             # KOI8-R regexp capture
1011             #
1012             {
1013             sub Ekoi8r::capture {
1014 0     0 1 0 return $_[0];
1015             }
1016             }
1017              
1018             #
1019             # KOI8-R regexp ignore case modifier
1020             #
1021             sub Ekoi8r::ignorecase {
1022              
1023 0     0 0 0 my @string = @_;
1024 0         0 my $metachar = qr/[\@\\|[\]{]/oxms;
1025              
1026             # ignore case of $scalar or @array
1027 0         0 for my $string (@string) {
1028              
1029             # split regexp
1030 0         0 my @char = $string =~ /\G (?>\[\^|\\$q_char|$q_char) /oxmsg;
1031              
1032             # unescape character
1033 0         0 for (my $i=0; $i <= $#char; $i++) {
1034 0 0       0 next if not defined $char[$i];
1035              
1036             # open character class [...]
1037 0 0       0 if ($char[$i] eq '[') {
    0          
    0          
    0          
1038 0         0 my $left = $i;
1039              
1040             # [] make die "unmatched [] in regexp ...\n"
1041              
1042 0 0       0 if ($char[$i+1] eq ']') {
1043 0         0 $i++;
1044             }
1045              
1046 0         0 while (1) {
1047 0 0       0 if (++$i > $#char) {
1048 0         0 croak "Unmatched [] in regexp";
1049             }
1050 0 0       0 if ($char[$i] eq ']') {
1051 0         0 my $right = $i;
1052 0         0 my @charlist = charlist_qr(@char[$left+1..$right-1], 'i');
1053              
1054             # escape character
1055 0         0 for my $char (@charlist) {
1056 0 0       0 if (0) {
1057             }
1058              
1059 0         0 elsif ($char =~ /\A [.|)] \z/oxms) {
1060 0         0 $char = '\\' . $char;
1061             }
1062             }
1063              
1064             # [...]
1065 0         0 splice @char, $left, $right-$left+1, '(?:' . join('|', @charlist) . ')';
1066              
1067 0         0 $i = $left;
1068 0         0 last;
1069             }
1070             }
1071             }
1072              
1073             # open character class [^...]
1074             elsif ($char[$i] eq '[^') {
1075 0         0 my $left = $i;
1076              
1077             # [^] make die "unmatched [] in regexp ...\n"
1078              
1079 0 0       0 if ($char[$i+1] eq ']') {
1080 0         0 $i++;
1081             }
1082              
1083 0         0 while (1) {
1084 0 0       0 if (++$i > $#char) {
1085 0         0 croak "Unmatched [] in regexp";
1086             }
1087 0 0       0 if ($char[$i] eq ']') {
1088 0         0 my $right = $i;
1089 0         0 my @charlist = charlist_not_qr(@char[$left+1..$right-1], 'i');
1090              
1091             # escape character
1092 0         0 for my $char (@charlist) {
1093 0 0       0 if (0) {
1094             }
1095              
1096 0         0 elsif ($char =~ /\A [.|)] \z/oxms) {
1097 0         0 $char = '\\' . $char;
1098             }
1099             }
1100              
1101             # [^...]
1102 0         0 splice @char, $left, $right-$left+1, '(?!' . join('|', @charlist) . ")(?:$your_char)";
1103              
1104 0         0 $i = $left;
1105 0         0 last;
1106             }
1107             }
1108             }
1109              
1110             # rewrite classic character class or escape character
1111             elsif (my $char = classic_character_class($char[$i])) {
1112 0         0 $char[$i] = $char;
1113             }
1114              
1115             # with /i modifier
1116             elsif ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) {
1117 0         0 my $uc = Ekoi8r::uc($char[$i]);
1118 0         0 my $fc = Ekoi8r::fc($char[$i]);
1119 0 0       0 if ($uc ne $fc) {
1120 0 0       0 if (CORE::length($fc) == 1) {
1121 0         0 $char[$i] = '[' . $uc . $fc . ']';
1122             }
1123             else {
1124 0         0 $char[$i] = '(?:' . $uc . '|' . $fc . ')';
1125             }
1126             }
1127             }
1128             }
1129              
1130             # characterize
1131 0         0 for (my $i=0; $i <= $#char; $i++) {
1132 0 0       0 next if not defined $char[$i];
1133              
1134 0 0       0 if (0) {
1135             }
1136              
1137             # quote character before ? + * {
1138 0 0       0 elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
1139 0 0       0 if ($char[$i-1] !~ /\A [\x00-\xFF] \z/oxms) {
1140 0         0 $char[$i-1] = '(?:' . $char[$i-1] . ')';
1141             }
1142             }
1143             }
1144              
1145 0         0 $string = join '', @char;
1146             }
1147              
1148             # make regexp string
1149 0         0 return @string;
1150             }
1151              
1152             #
1153             # classic character class ( \D \S \W \d \s \w \C \X \H \V \h \v \R \N \b \B )
1154             #
1155             sub Ekoi8r::classic_character_class {
1156 1862     1862 0 1835 my($char) = @_;
1157              
1158             return {
1159             '\D' => '${Ekoi8r::eD}',
1160             '\S' => '${Ekoi8r::eS}',
1161             '\W' => '${Ekoi8r::eW}',
1162             '\d' => '[0-9]',
1163              
1164             # Before Perl 5.6, \s only matched the five whitespace characters
1165             # tab, newline, form-feed, carriage return, and the space character
1166             # itself, which, taken together, is the character class [\t\n\f\r ].
1167              
1168             # Vertical tabs are now whitespace
1169             # \s in a regex now matches a vertical tab in all circumstances.
1170             # http://search.cpan.org/dist/perl-5.18.0/pod/perldelta.pod#Vertical_tabs_are_now_whitespace
1171             # \t \n \v \f \r space
1172             # '\s' => '[\x09\x0A \x0C\x0D\x20]',
1173             # '\s' => '[\x09\x0A\x0B\x0C\x0D\x20]',
1174             '\s' => '\s',
1175              
1176             '\w' => '[0-9A-Z_a-z]',
1177             '\C' => '[\x00-\xFF]',
1178             '\X' => 'X',
1179              
1180             # \h \v \H \V
1181              
1182             # P.114 Character Class Shortcuts
1183             # in Chapter 7: In the World of Regular Expressions
1184             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
1185              
1186             # P.357 13.2.3 Whitespace
1187             # in Chapter 13: perlrecharclass: Perl Regular Expression Character Classes
1188             # of ISBN-13: 978-1-906966-02-7 The Perl Language Reference Manual (for Perl version 5.12.1)
1189             #
1190             # 0x00009 CHARACTER TABULATION h s
1191             # 0x0000a LINE FEED (LF) vs
1192             # 0x0000b LINE TABULATION v
1193             # 0x0000c FORM FEED (FF) vs
1194             # 0x0000d CARRIAGE RETURN (CR) vs
1195             # 0x00020 SPACE h s
1196              
1197             # P.196 Table 5-9. Alphanumeric regex metasymbols
1198             # in Chapter 5. Pattern Matching
1199             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
1200              
1201             # (and so on)
1202              
1203             '\H' => '${Ekoi8r::eH}',
1204             '\V' => '${Ekoi8r::eV}',
1205             '\h' => '[\x09\x20]',
1206             '\v' => '[\x0A\x0B\x0C\x0D]',
1207             '\R' => '${Ekoi8r::eR}',
1208              
1209             # \N
1210             #
1211             # http://perldoc.perl.org/perlre.html
1212             # Character Classes and other Special Escapes
1213             # Any character but \n (experimental). Not affected by /s modifier
1214              
1215             '\N' => '${Ekoi8r::eN}',
1216              
1217             # \b \B
1218              
1219             # P.180 Boundaries: The \b and \B Assertions
1220             # in Chapter 5: Pattern Matching
1221             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
1222              
1223             # P.219 Boundaries: The \b and \B Assertions
1224             # in Chapter 5: Pattern Matching
1225             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
1226              
1227             # \b really means (?:(?<=\w)(?!\w)|(?
1228             # or (?:(?<=\A|\W)(?=\w)|(?<=\w)(?=\W|\z))
1229             '\b' => '${Ekoi8r::eb}',
1230              
1231             # \B really means (?:(?<=\w)(?=\w)|(?
1232             # or (?:(?<=\w)(?=\w)|(?<=\W)(?=\W))
1233             '\B' => '${Ekoi8r::eB}',
1234              
1235 1862   100     80766 }->{$char} || '';
1236             }
1237              
1238             #
1239             # prepare KOI8-R characters per length
1240             #
1241              
1242             # 1 octet characters
1243             my @chars1 = ();
1244             sub chars1 {
1245 0 0   0 0 0 if (@chars1) {
1246 0         0 return @chars1;
1247             }
1248 0 0       0 if (exists $range_tr{1}) {
1249 0         0 my @ranges = @{ $range_tr{1} };
  0         0  
1250 0         0 while (my @range = splice(@ranges,0,1)) {
1251 0         0 for my $oct0 (@{$range[0]}) {
  0         0  
1252 0         0 push @chars1, pack 'C', $oct0;
1253             }
1254             }
1255             }
1256 0         0 return @chars1;
1257             }
1258              
1259             # 2 octets characters
1260             my @chars2 = ();
1261             sub chars2 {
1262 0 0   0 0 0 if (@chars2) {
1263 0         0 return @chars2;
1264             }
1265 0 0       0 if (exists $range_tr{2}) {
1266 0         0 my @ranges = @{ $range_tr{2} };
  0         0  
1267 0         0 while (my @range = splice(@ranges,0,2)) {
1268 0         0 for my $oct0 (@{$range[0]}) {
  0         0  
1269 0         0 for my $oct1 (@{$range[1]}) {
  0         0  
1270 0         0 push @chars2, pack 'CC', $oct0,$oct1;
1271             }
1272             }
1273             }
1274             }
1275 0         0 return @chars2;
1276             }
1277              
1278             # 3 octets characters
1279             my @chars3 = ();
1280             sub chars3 {
1281 0 0   0 0 0 if (@chars3) {
1282 0         0 return @chars3;
1283             }
1284 0 0       0 if (exists $range_tr{3}) {
1285 0         0 my @ranges = @{ $range_tr{3} };
  0         0  
1286 0         0 while (my @range = splice(@ranges,0,3)) {
1287 0         0 for my $oct0 (@{$range[0]}) {
  0         0  
1288 0         0 for my $oct1 (@{$range[1]}) {
  0         0  
1289 0         0 for my $oct2 (@{$range[2]}) {
  0         0  
1290 0         0 push @chars3, pack 'CCC', $oct0,$oct1,$oct2;
1291             }
1292             }
1293             }
1294             }
1295             }
1296 0         0 return @chars3;
1297             }
1298              
1299             # 4 octets characters
1300             my @chars4 = ();
1301             sub chars4 {
1302 0 0   0 0 0 if (@chars4) {
1303 0         0 return @chars4;
1304             }
1305 0 0       0 if (exists $range_tr{4}) {
1306 0         0 my @ranges = @{ $range_tr{4} };
  0         0  
1307 0         0 while (my @range = splice(@ranges,0,4)) {
1308 0         0 for my $oct0 (@{$range[0]}) {
  0         0  
1309 0         0 for my $oct1 (@{$range[1]}) {
  0         0  
1310 0         0 for my $oct2 (@{$range[2]}) {
  0         0  
1311 0         0 for my $oct3 (@{$range[3]}) {
  0         0  
1312 0         0 push @chars4, pack 'CCCC', $oct0,$oct1,$oct2,$oct3;
1313             }
1314             }
1315             }
1316             }
1317             }
1318             }
1319 0         0 return @chars4;
1320             }
1321              
1322             #
1323             # KOI8-R open character list for tr
1324             #
1325             sub _charlist_tr {
1326              
1327 0     0   0 local $_ = shift @_;
1328              
1329             # unescape character
1330 0         0 my @char = ();
1331 0         0 while (not /\G \z/oxmsgc) {
1332 0 0       0 if (/\G (\\0?55|\\x2[Dd]|\\-) /oxmsgc) {
    0          
    0          
    0          
    0          
    0          
    0          
1333 0         0 push @char, '\-';
1334             }
1335             elsif (/\G \\ ([0-7]{2,3}) /oxmsgc) {
1336 0         0 push @char, CORE::chr(oct $1);
1337             }
1338             elsif (/\G \\x ([0-9A-Fa-f]{1,2}) /oxmsgc) {
1339 0         0 push @char, CORE::chr(hex $1);
1340             }
1341             elsif (/\G \\c ([\x40-\x5F]) /oxmsgc) {
1342 0         0 push @char, CORE::chr(CORE::ord($1) & 0x1F);
1343             }
1344             elsif (/\G (\\ [0nrtfbae]) /oxmsgc) {
1345             push @char, {
1346             '\0' => "\0",
1347             '\n' => "\n",
1348             '\r' => "\r",
1349             '\t' => "\t",
1350             '\f' => "\f",
1351             '\b' => "\x08", # \b means backspace in character class
1352             '\a' => "\a",
1353             '\e' => "\e",
1354 0         0 }->{$1};
1355             }
1356             elsif (/\G \\ ($q_char) /oxmsgc) {
1357 0         0 push @char, $1;
1358             }
1359             elsif (/\G ($q_char) /oxmsgc) {
1360 0         0 push @char, $1;
1361             }
1362             }
1363              
1364             # join separated multiple-octet
1365 0         0 @char = join('',@char) =~ /\G (?>\\-|$q_char) /oxmsg;
1366              
1367             # unescape '-'
1368 0         0 my @i = ();
1369 0         0 for my $i (0 .. $#char) {
1370 0 0       0 if ($char[$i] eq '\-') {
    0          
1371 0         0 $char[$i] = '-';
1372             }
1373             elsif ($char[$i] eq '-') {
1374 0 0 0     0 if ((0 < $i) and ($i < $#char)) {
1375 0         0 push @i, $i;
1376             }
1377             }
1378             }
1379              
1380             # open character list (reverse for splice)
1381 0         0 for my $i (CORE::reverse @i) {
1382 0         0 my @range = ();
1383              
1384             # range error
1385 0 0 0     0 if ((CORE::length($char[$i-1]) > CORE::length($char[$i+1])) or ($char[$i-1] gt $char[$i+1])) {
1386 0         0 croak "Invalid tr/// range \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1387             }
1388              
1389             # range of multiple-octet code
1390 0 0       0 if (CORE::length($char[$i-1]) == 1) {
    0          
    0          
    0          
1391 0 0       0 if (CORE::length($char[$i+1]) == 1) {
    0          
    0          
    0          
1392 0 0       0 push @range, grep {($char[$i-1] le $_) and ($_ le $char[$i+1])} chars1();
  0         0  
1393             }
1394             elsif (CORE::length($char[$i+1]) == 2) {
1395 0         0 push @range, grep {$char[$i-1] le $_} chars1();
  0         0  
1396 0         0 push @range, grep {$_ le $char[$i+1]} chars2();
  0         0  
1397             }
1398             elsif (CORE::length($char[$i+1]) == 3) {
1399 0         0 push @range, grep {$char[$i-1] le $_} chars1();
  0         0  
1400 0         0 push @range, chars2();
1401 0         0 push @range, grep {$_ le $char[$i+1]} chars3();
  0         0  
1402             }
1403             elsif (CORE::length($char[$i+1]) == 4) {
1404 0         0 push @range, grep {$char[$i-1] le $_} chars1();
  0         0  
1405 0         0 push @range, chars2();
1406 0         0 push @range, chars3();
1407 0         0 push @range, grep {$_ le $char[$i+1]} chars4();
  0         0  
1408             }
1409             else {
1410 0         0 croak "Invalid tr/// range (over 4octets) \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1411             }
1412             }
1413             elsif (CORE::length($char[$i-1]) == 2) {
1414 0 0       0 if (CORE::length($char[$i+1]) == 2) {
    0          
    0          
1415 0 0       0 push @range, grep {($char[$i-1] le $_) and ($_ le $char[$i+1])} chars2();
  0         0  
1416             }
1417             elsif (CORE::length($char[$i+1]) == 3) {
1418 0         0 push @range, grep {$char[$i-1] le $_} chars2();
  0         0  
1419 0         0 push @range, grep {$_ le $char[$i+1]} chars3();
  0         0  
1420             }
1421             elsif (CORE::length($char[$i+1]) == 4) {
1422 0         0 push @range, grep {$char[$i-1] le $_} chars2();
  0         0  
1423 0         0 push @range, chars3();
1424 0         0 push @range, grep {$_ le $char[$i+1]} chars4();
  0         0  
1425             }
1426             else {
1427 0         0 croak "Invalid tr/// range (over 4octets) \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1428             }
1429             }
1430             elsif (CORE::length($char[$i-1]) == 3) {
1431 0 0       0 if (CORE::length($char[$i+1]) == 3) {
    0          
1432 0 0       0 push @range, grep {($char[$i-1] le $_) and ($_ le $char[$i+1])} chars3();
  0         0  
1433             }
1434             elsif (CORE::length($char[$i+1]) == 4) {
1435 0         0 push @range, grep {$char[$i-1] le $_} chars3();
  0         0  
1436 0         0 push @range, grep {$_ le $char[$i+1]} chars4();
  0         0  
1437             }
1438             else {
1439 0         0 croak "Invalid tr/// range (over 4octets) \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1440             }
1441             }
1442             elsif (CORE::length($char[$i-1]) == 4) {
1443 0 0       0 if (CORE::length($char[$i+1]) == 4) {
1444 0 0       0 push @range, grep {($char[$i-1] le $_) and ($_ le $char[$i+1])} chars4();
  0         0  
1445             }
1446             else {
1447 0         0 croak "Invalid tr/// range (over 4octets) \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1448             }
1449             }
1450             else {
1451 0         0 croak "Invalid tr/// range (over 4octets) \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1452             }
1453              
1454 0         0 splice @char, $i-1, 3, @range;
1455             }
1456              
1457 0         0 return @char;
1458             }
1459              
1460             #
1461             # KOI8-R open character class
1462             #
1463             sub _cc {
1464 0 0   0   0 if (scalar(@_) == 0) {
    0          
    0          
1465 0         0 die __FILE__, ": subroutine cc got no parameter.\n";
1466             }
1467             elsif (scalar(@_) == 1) {
1468 0         0 return sprintf('\x%02X',$_[0]);
1469             }
1470             elsif (scalar(@_) == 2) {
1471 0 0       0 if ($_[0] > $_[1]) {
    0          
    0          
1472 0         0 die __FILE__, ": subroutine cc got \$_[0] > \$_[1] parameters).\n";
1473             }
1474             elsif ($_[0] == $_[1]) {
1475 0         0 return sprintf('\x%02X',$_[0]);
1476             }
1477             elsif (($_[0]+1) == $_[1]) {
1478 0         0 return sprintf('[\\x%02X\\x%02X]',$_[0],$_[1]);
1479             }
1480             else {
1481 0         0 return sprintf('[\\x%02X-\\x%02X]',$_[0],$_[1]);
1482             }
1483             }
1484             else {
1485 0         0 die __FILE__, ": subroutine cc got 3 or more parameters (@{[scalar(@_)]} parameters).\n";
  0         0  
1486             }
1487             }
1488              
1489             #
1490             # KOI8-R octet range
1491             #
1492             sub _octets {
1493 182     182   298 my $length = shift @_;
1494              
1495 182 50       397 if ($length == 1) {
1496 182         605 my($a1) = unpack 'C', $_[0];
1497 182         335 my($z1) = unpack 'C', $_[1];
1498              
1499 182 50       395 if ($a1 > $z1) {
1500 0         0 croak 'Invalid [] range in regexp (CORE::ord(A) > CORE::ord(B)) ' . '\x' . unpack('H*',$a1) . '-\x' . unpack('H*',$z1);
1501             }
1502              
1503 182 50       528 if ($a1 == $z1) {
    50          
1504 0         0 return sprintf('\x%02X',$a1);
1505             }
1506             elsif (($a1+1) == $z1) {
1507 0         0 return sprintf('\x%02X\x%02X',$a1,$z1);
1508             }
1509             else {
1510 182         1487 return sprintf('\x%02X-\x%02X',$a1,$z1);
1511             }
1512             }
1513             else {
1514 0         0 die __FILE__, ": subroutine _octets got invalid length ($length).\n";
1515             }
1516             }
1517              
1518             #
1519             # KOI8-R range regexp
1520             #
1521             sub _range_regexp {
1522 182     182   310 my($length,$first,$last) = @_;
1523              
1524 182         250 my @range_regexp = ();
1525 182 50       555 if (not exists $range_tr{$length}) {
1526 0         0 return @range_regexp;
1527             }
1528              
1529 182         209 my @ranges = @{ $range_tr{$length} };
  182         470  
1530 182         693 while (my @range = splice(@ranges,0,$length)) {
1531 182         228 my $min = '';
1532 182         207 my $max = '';
1533 182         484 for (my $i=0; $i < $length; $i++) {
1534 182         842 $min .= pack 'C', $range[$i][0];
1535 182         600 $max .= pack 'C', $range[$i][-1];
1536             }
1537              
1538             # min___max
1539             # FIRST_____________LAST
1540             # (nothing)
1541              
1542 182 50 33     2651 if ($max lt $first) {
    50 33        
    50 33        
    50 33        
    50 33        
    0 0        
    0 0        
1543             }
1544              
1545             # **********
1546             # min_________max
1547             # FIRST_____________LAST
1548             # **********
1549              
1550             elsif (($min le $first) and ($first le $max) and ($max le $last)) {
1551 0         0 push @range_regexp, _octets($length,$first,$max,$min,$max);
1552             }
1553              
1554             # **********************
1555             # min________________max
1556             # FIRST_____________LAST
1557             # **********************
1558              
1559             elsif (($min eq $first) and ($max eq $last)) {
1560 0         0 push @range_regexp, _octets($length,$first,$last,$min,$max);
1561             }
1562              
1563             # *********
1564             # min___max
1565             # FIRST_____________LAST
1566             # *********
1567              
1568             elsif (($first le $min) and ($max le $last)) {
1569 0         0 push @range_regexp, _octets($length,$min,$max,$min,$max);
1570             }
1571              
1572             # **********************
1573             # min__________________________max
1574             # FIRST_____________LAST
1575             # **********************
1576              
1577             elsif (($min le $first) and ($last le $max)) {
1578 182         498 push @range_regexp, _octets($length,$first,$last,$min,$max);
1579             }
1580              
1581             # *********
1582             # min________max
1583             # FIRST_____________LAST
1584             # *********
1585              
1586             elsif (($first le $min) and ($min le $last) and ($last le $max)) {
1587 0         0 push @range_regexp, _octets($length,$min,$last,$min,$max);
1588             }
1589              
1590             # min___max
1591             # FIRST_____________LAST
1592             # (nothing)
1593              
1594             elsif ($last lt $min) {
1595             }
1596              
1597             else {
1598 0         0 die __FILE__, ": subroutine _range_regexp panic.\n";
1599             }
1600             }
1601              
1602 182         417 return @range_regexp;
1603             }
1604              
1605             #
1606             # KOI8-R open character list for qr and not qr
1607             #
1608             sub _charlist {
1609              
1610 358     358   569 my $modifier = pop @_;
1611 358         771 my @char = @_;
1612              
1613 358 100       822 my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
1614              
1615             # unescape character
1616 358         1188 for (my $i=0; $i <= $#char; $i++) {
1617              
1618             # escape - to ...
1619 1125 100 100     10680 if ($char[$i] eq '-') {
    50          
    50          
    50          
    50          
    50          
    100          
    50          
    100          
    100          
    100          
    100          
1620 206 100 100     1037 if ((0 < $i) and ($i < $#char)) {
1621 182         473 $char[$i] = '...';
1622             }
1623             }
1624              
1625             # octal escape sequence
1626             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
1627 0         0 $char[$i] = octchr($1);
1628             }
1629              
1630             # hexadecimal escape sequence
1631             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
1632 0         0 $char[$i] = hexchr($1);
1633             }
1634              
1635             # \b{...} --> b\{...}
1636             # \B{...} --> B\{...}
1637             # \N{CHARNAME} --> N\{CHARNAME}
1638             # \p{PROPERTY} --> p\{PROPERTY}
1639             # \P{PROPERTY} --> P\{PROPERTY}
1640             elsif ($char[$i] =~ /\A \\ ([bBNpP]) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
1641 0         0 $char[$i] = $1 . '\\' . $2;
1642             }
1643              
1644             # \p, \P, \X --> p, P, X
1645             elsif ($char[$i] =~ /\A \\ ( [pPX] ) \z/oxms) {
1646 0         0 $char[$i] = $1;
1647             }
1648              
1649             elsif ($char[$i] =~ /\A \\ ([0-7]{2,3}) \z/oxms) {
1650 0         0 $char[$i] = CORE::chr oct $1;
1651             }
1652             elsif ($char[$i] =~ /\A \\x ([0-9A-Fa-f]{1,2}) \z/oxms) {
1653 22         128 $char[$i] = CORE::chr hex $1;
1654             }
1655             elsif ($char[$i] =~ /\A \\c ([\x40-\x5F]) \z/oxms) {
1656 0         0 $char[$i] = CORE::chr(CORE::ord($1) & 0x1F);
1657             }
1658             elsif ($char[$i] =~ /\A (\\ [0nrtfbaedswDSWHVhvR]) \z/oxms) {
1659             $char[$i] = {
1660             '\0' => "\0",
1661             '\n' => "\n",
1662             '\r' => "\r",
1663             '\t' => "\t",
1664             '\f' => "\f",
1665             '\b' => "\x08", # \b means backspace in character class
1666             '\a' => "\a",
1667             '\e' => "\e",
1668             '\d' => '[0-9]',
1669              
1670             # Vertical tabs are now whitespace
1671             # \s in a regex now matches a vertical tab in all circumstances.
1672             # http://search.cpan.org/dist/perl-5.18.0/pod/perldelta.pod#Vertical_tabs_are_now_whitespace
1673             # \t \n \v \f \r space
1674             # '\s' => '[\x09\x0A \x0C\x0D\x20]',
1675             # '\s' => '[\x09\x0A\x0B\x0C\x0D\x20]',
1676             '\s' => '\s',
1677              
1678             '\w' => '[0-9A-Z_a-z]',
1679             '\D' => '${Ekoi8r::eD}',
1680             '\S' => '${Ekoi8r::eS}',
1681             '\W' => '${Ekoi8r::eW}',
1682              
1683             '\H' => '${Ekoi8r::eH}',
1684             '\V' => '${Ekoi8r::eV}',
1685             '\h' => '[\x09\x20]',
1686             '\v' => '[\x0A\x0B\x0C\x0D]',
1687             '\R' => '${Ekoi8r::eR}',
1688              
1689 25         419 }->{$1};
1690             }
1691              
1692             # POSIX-style character classes
1693             elsif ($ignorecase and ($char[$i] =~ /\A ( \[\: \^? (?:lower|upper) :\] ) \z/oxms)) {
1694             $char[$i] = {
1695              
1696             '[:lower:]' => '[\x41-\x5A\x61-\x7A]',
1697             '[:upper:]' => '[\x41-\x5A\x61-\x7A]',
1698             '[:^lower:]' => '${Ekoi8r::not_lower_i}',
1699             '[:^upper:]' => '${Ekoi8r::not_upper_i}',
1700              
1701 8         71 }->{$1};
1702             }
1703             elsif ($char[$i] =~ /\A ( \[\: \^? (?:alnum|alpha|ascii|blank|cntrl|digit|graph|lower|print|punct|space|upper|word|xdigit) :\] ) \z/oxms) {
1704             $char[$i] = {
1705              
1706             '[:alnum:]' => '[\x30-\x39\x41-\x5A\x61-\x7A]',
1707             '[:alpha:]' => '[\x41-\x5A\x61-\x7A]',
1708             '[:ascii:]' => '[\x00-\x7F]',
1709             '[:blank:]' => '[\x09\x20]',
1710             '[:cntrl:]' => '[\x00-\x1F\x7F]',
1711             '[:digit:]' => '[\x30-\x39]',
1712             '[:graph:]' => '[\x21-\x7F]',
1713             '[:lower:]' => '[\x61-\x7A]',
1714             '[:print:]' => '[\x20-\x7F]',
1715             '[:punct:]' => '[\x21-\x2F\x3A-\x3F\x40\x5B-\x5F\x60\x7B-\x7E]',
1716              
1717             # P.174 POSIX-Style Character Classes
1718             # in Chapter 5: Pattern Matching
1719             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
1720              
1721             # P.311 11.2.4 Character Classes and other Special Escapes
1722             # in Chapter 11: perlre: Perl regular expressions
1723             # of ISBN-13: 978-1-906966-02-7 The Perl Language Reference Manual (for Perl version 5.12.1)
1724              
1725             # P.210 POSIX-Style Character Classes
1726             # in Chapter 5: Pattern Matching
1727             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
1728              
1729             '[:space:]' => '[\s\x0B]', # "\s" plus vertical tab ("\cK")
1730              
1731             '[:upper:]' => '[\x41-\x5A]',
1732             '[:word:]' => '[\x30-\x39\x41-\x5A\x5F\x61-\x7A]',
1733             '[:xdigit:]' => '[\x30-\x39\x41-\x46\x61-\x66]',
1734             '[:^alnum:]' => '${Ekoi8r::not_alnum}',
1735             '[:^alpha:]' => '${Ekoi8r::not_alpha}',
1736             '[:^ascii:]' => '${Ekoi8r::not_ascii}',
1737             '[:^blank:]' => '${Ekoi8r::not_blank}',
1738             '[:^cntrl:]' => '${Ekoi8r::not_cntrl}',
1739             '[:^digit:]' => '${Ekoi8r::not_digit}',
1740             '[:^graph:]' => '${Ekoi8r::not_graph}',
1741             '[:^lower:]' => '${Ekoi8r::not_lower}',
1742             '[:^print:]' => '${Ekoi8r::not_print}',
1743             '[:^punct:]' => '${Ekoi8r::not_punct}',
1744             '[:^space:]' => '${Ekoi8r::not_space}',
1745             '[:^upper:]' => '${Ekoi8r::not_upper}',
1746             '[:^word:]' => '${Ekoi8r::not_word}',
1747             '[:^xdigit:]' => '${Ekoi8r::not_xdigit}',
1748              
1749 70         1539 }->{$1};
1750             }
1751             elsif ($char[$i] =~ /\A \\ ($q_char) \z/oxms) {
1752 7         36 $char[$i] = $1;
1753             }
1754             }
1755              
1756             # open character list
1757 358         585 my @singleoctet = ();
1758 358         485 my @multipleoctet = ();
1759 358         1017 for (my $i=0; $i <= $#char; ) {
1760              
1761             # escaped -
1762 943 100 100     4891 if (defined($char[$i+1]) and ($char[$i+1] eq '...')) {
    100          
    100          
    50          
    50          
    100          
1763 182         221 $i += 1;
1764 182         385 next;
1765             }
1766              
1767             # make range regexp
1768             elsif ($char[$i] eq '...') {
1769              
1770             # range error
1771 182 50       849 if (CORE::length($char[$i-1]) > CORE::length($char[$i+1])) {
    50          
1772 0         0 croak 'Invalid [] range in regexp (length(A) > length(B)) ' . '\x' . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]);
1773             }
1774             elsif (CORE::length($char[$i-1]) == CORE::length($char[$i+1])) {
1775 182 50       527 if ($char[$i-1] gt $char[$i+1]) {
1776 0         0 croak 'Invalid [] range in regexp (CORE::ord(A) > CORE::ord(B)) ' . '\x' . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]);
1777             }
1778             }
1779              
1780             # make range regexp per length
1781 182         619 for my $length (CORE::length($char[$i-1]) .. CORE::length($char[$i+1])) {
1782 182         259 my @regexp = ();
1783              
1784             # is first and last
1785 182 50 33     970 if (($length == CORE::length($char[$i-1])) and ($length == CORE::length($char[$i+1]))) {
    0 0        
    0          
    0          
1786 182         618 push @regexp, _range_regexp($length, $char[$i-1], $char[$i+1]);
1787             }
1788              
1789             # is first
1790             elsif ($length == CORE::length($char[$i-1])) {
1791 0         0 push @regexp, _range_regexp($length, $char[$i-1], "\xFF" x $length);
1792             }
1793              
1794             # is inside in first and last
1795             elsif ((CORE::length($char[$i-1]) < $length) and ($length < CORE::length($char[$i+1]))) {
1796 0         0 push @regexp, _range_regexp($length, "\x00" x $length, "\xFF" x $length);
1797             }
1798              
1799             # is last
1800             elsif ($length == CORE::length($char[$i+1])) {
1801 0         0 push @regexp, _range_regexp($length, "\x00" x $length, $char[$i+1]);
1802             }
1803              
1804             else {
1805 0         0 die __FILE__, ": subroutine make_regexp panic.\n";
1806             }
1807              
1808 182 50       437 if ($length == 1) {
1809 182         454 push @singleoctet, @regexp;
1810             }
1811             else {
1812 0         0 push @multipleoctet, @regexp;
1813             }
1814             }
1815              
1816 182         444 $i += 2;
1817             }
1818              
1819             # with /i modifier
1820             elsif ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) {
1821 493 100       626 if ($modifier =~ /i/oxms) {
1822 24         49 my $uc = Ekoi8r::uc($char[$i]);
1823 24         48 my $fc = Ekoi8r::fc($char[$i]);
1824 24 100       46 if ($uc ne $fc) {
1825 12 50       22 if (CORE::length($fc) == 1) {
1826 12         21 push @singleoctet, $uc, $fc;
1827             }
1828             else {
1829 0         0 push @singleoctet, $uc;
1830 0         0 push @multipleoctet, $fc;
1831             }
1832             }
1833             else {
1834 12         23 push @singleoctet, $char[$i];
1835             }
1836             }
1837             else {
1838 469         581 push @singleoctet, $char[$i];
1839             }
1840 493         748 $i += 1;
1841             }
1842              
1843             # single character of single octet code
1844             elsif ($char[$i] =~ /\A (?: \\h ) \z/oxms) {
1845 0         0 push @singleoctet, "\t", "\x20";
1846 0         0 $i += 1;
1847             }
1848             elsif ($char[$i] =~ /\A (?: \\v ) \z/oxms) {
1849 0         0 push @singleoctet, "\x0A", "\x0B", "\x0C", "\x0D";
1850 0         0 $i += 1;
1851             }
1852             elsif ($char[$i] =~ /\A (?: \\d | \\s | \\w ) \z/oxms) {
1853 2         5 push @singleoctet, $char[$i];
1854 2         6 $i += 1;
1855             }
1856              
1857             # single character of multiple-octet code
1858             else {
1859 84         142 push @multipleoctet, $char[$i];
1860 84         172 $i += 1;
1861             }
1862             }
1863              
1864             # quote metachar
1865 358         724 for (@singleoctet) {
1866 689 50       3502 if ($_ eq '...') {
    100          
    100          
    100          
    100          
1867 0         0 $_ = '-';
1868             }
1869             elsif (/\A \n \z/oxms) {
1870 8         19 $_ = '\n';
1871             }
1872             elsif (/\A \r \z/oxms) {
1873 8         19 $_ = '\r';
1874             }
1875             elsif (/\A ([\x00-\x20\x7F-\xFF]) \z/oxms) {
1876 60         201 $_ = sprintf('\x%02X', CORE::ord $1);
1877             }
1878             elsif (/\A [\x00-\xFF] \z/oxms) {
1879 429         519 $_ = quotemeta $_;
1880             }
1881             }
1882              
1883             # return character list
1884 358         1346 return \@singleoctet, \@multipleoctet;
1885             }
1886              
1887             #
1888             # KOI8-R octal escape sequence
1889             #
1890             sub octchr {
1891 5     5 0 10 my($octdigit) = @_;
1892              
1893 5         6 my @binary = ();
1894 5         17 for my $octal (split(//,$octdigit)) {
1895             push @binary, {
1896             '0' => '000',
1897             '1' => '001',
1898             '2' => '010',
1899             '3' => '011',
1900             '4' => '100',
1901             '5' => '101',
1902             '6' => '110',
1903             '7' => '111',
1904 50         169 }->{$octal};
1905             }
1906 5         14 my $binary = join '', @binary;
1907              
1908             my $octchr = {
1909             # 1234567
1910             1 => pack('B*', "0000000$binary"),
1911             2 => pack('B*', "000000$binary"),
1912             3 => pack('B*', "00000$binary"),
1913             4 => pack('B*', "0000$binary"),
1914             5 => pack('B*', "000$binary"),
1915             6 => pack('B*', "00$binary"),
1916             7 => pack('B*', "0$binary"),
1917             0 => pack('B*', "$binary"),
1918              
1919 5         59 }->{CORE::length($binary) % 8};
1920              
1921 5         17 return $octchr;
1922             }
1923              
1924             #
1925             # KOI8-R hexadecimal escape sequence
1926             #
1927             sub hexchr {
1928 5     5 0 16 my($hexdigit) = @_;
1929              
1930             my $hexchr = {
1931             1 => pack('H*', "0$hexdigit"),
1932             0 => pack('H*', "$hexdigit"),
1933              
1934 5         90 }->{CORE::length($_[0]) % 2};
1935              
1936 5         23 return $hexchr;
1937             }
1938              
1939             #
1940             # KOI8-R open character list for qr
1941             #
1942             sub charlist_qr {
1943              
1944 314     314 0 579 my $modifier = pop @_;
1945 314         779 my @char = @_;
1946              
1947 314         852 my($singleoctet, $multipleoctet) = _charlist(@char, $modifier);
1948 314         674 my @singleoctet = @$singleoctet;
1949 314         465 my @multipleoctet = @$multipleoctet;
1950              
1951             # return character list
1952 314 100       793 if (scalar(@singleoctet) >= 1) {
1953              
1954             # with /i modifier
1955 236 100       587 if ($modifier =~ m/i/oxms) {
1956 22         36 my %singleoctet_ignorecase = ();
1957 22         42 for (@singleoctet) {
1958 46   100     236 while (s/ \A \\x(..) - \\x(..) //oxms or s/ \A \\x((..)) //oxms) {
1959 46         138 for my $ord (hex($1) .. hex($2)) {
1960 66         94 my $char = CORE::chr($ord);
1961 66         91 my $uc = Ekoi8r::uc($char);
1962 66         113 my $fc = Ekoi8r::fc($char);
1963 66 100       110 if ($uc eq $fc) {
1964 12         102 $singleoctet_ignorecase{unpack 'C*', $char} = 1;
1965             }
1966             else {
1967 54 50       72 if (CORE::length($fc) == 1) {
1968 54         125 $singleoctet_ignorecase{unpack 'C*', $uc} = 1;
1969 54         233 $singleoctet_ignorecase{unpack 'C*', $fc} = 1;
1970             }
1971             else {
1972 0         0 $singleoctet_ignorecase{unpack 'C*', $uc} = 1;
1973 0         0 push @multipleoctet, join '', map {sprintf('\x%02X',$_)} unpack 'C*', $fc;
  0         0  
1974             }
1975             }
1976             }
1977             }
1978 46 50       88 if ($_ ne '') {
1979 0         0 $singleoctet_ignorecase{unpack 'C*', $_} = 1;
1980             }
1981             }
1982 22         24 my $i = 0;
1983 22         29 my @singleoctet_ignorecase = ();
1984 22         38 for my $ord (0 .. 255) {
1985 5632 100       5435 if (exists $singleoctet_ignorecase{$ord}) {
1986 96         72 push @{$singleoctet_ignorecase[$i]}, $ord;
  96         199  
1987             }
1988             else {
1989 5536         4140 $i++;
1990             }
1991             }
1992 22         50 @singleoctet = ();
1993 22         59 for my $range (@singleoctet_ignorecase) {
1994 3648 100       5931 if (ref $range) {
1995 56 100       37 if (scalar(@{$range}) == 1) {
  56 50       174  
1996 36         32 push @singleoctet, sprintf('\x%02X', @{$range}[0]);
  36         144  
1997             }
1998 20         24 elsif (scalar(@{$range}) == 2) {
1999 0         0 push @singleoctet, sprintf('\x%02X\x%02X', @{$range}[0], @{$range}[-1]);
  0         0  
  0         0  
2000             }
2001             else {
2002 20         15 push @singleoctet, sprintf('\x%02X-\x%02X', @{$range}[0], @{$range}[-1]);
  20         20  
  20         92  
2003             }
2004             }
2005             }
2006             }
2007              
2008 236         353 my $not_anchor = '';
2009              
2010 236         684 push @multipleoctet, join('', $not_anchor, '[', @singleoctet, ']' );
2011             }
2012 314 100       683 if (scalar(@multipleoctet) >= 2) {
2013 6         26 return '(?:' . join('|', @multipleoctet) . ')';
2014             }
2015             else {
2016 308         1438 return $multipleoctet[0];
2017             }
2018             }
2019              
2020             #
2021             # KOI8-R open character list for not qr
2022             #
2023             sub charlist_not_qr {
2024              
2025 44     44 0 93 my $modifier = pop @_;
2026 44         117 my @char = @_;
2027              
2028 44         128 my($singleoctet, $multipleoctet) = _charlist(@char, $modifier);
2029 44         95 my @singleoctet = @$singleoctet;
2030 44         65 my @multipleoctet = @$multipleoctet;
2031              
2032             # with /i modifier
2033 44 100       124 if ($modifier =~ m/i/oxms) {
2034 10         24 my %singleoctet_ignorecase = ();
2035 10         17 for (@singleoctet) {
2036 10   66     67 while (s/ \A \\x(..) - \\x(..) //oxms or s/ \A \\x((..)) //oxms) {
2037 10         54 for my $ord (hex($1) .. hex($2)) {
2038 30         51 my $char = CORE::chr($ord);
2039 30         178 my $uc = Ekoi8r::uc($char);
2040 30         66 my $fc = Ekoi8r::fc($char);
2041 30 50       62 if ($uc eq $fc) {
2042 0         0 $singleoctet_ignorecase{unpack 'C*', $char} = 1;
2043             }
2044             else {
2045 30 50       55 if (CORE::length($fc) == 1) {
2046 30         104 $singleoctet_ignorecase{unpack 'C*', $uc} = 1;
2047 30         160 $singleoctet_ignorecase{unpack 'C*', $fc} = 1;
2048             }
2049             else {
2050 0         0 $singleoctet_ignorecase{unpack 'C*', $uc} = 1;
2051 0         0 push @multipleoctet, join '', map {sprintf('\x%02X',$_)} unpack 'C*', $fc;
  0         0  
2052             }
2053             }
2054             }
2055             }
2056 10 50       33 if ($_ ne '') {
2057 0         0 $singleoctet_ignorecase{unpack 'C*', $_} = 1;
2058             }
2059             }
2060 10         14 my $i = 0;
2061 10         14 my @singleoctet_ignorecase = ();
2062 10         28 for my $ord (0 .. 255) {
2063 2560 100       3734 if (exists $singleoctet_ignorecase{$ord}) {
2064 60         42 push @{$singleoctet_ignorecase[$i]}, $ord;
  60         140  
2065             }
2066             else {
2067 2500         2652 $i++;
2068             }
2069             }
2070 10         30 @singleoctet = ();
2071 10         37 for my $range (@singleoctet_ignorecase) {
2072 960 100       2520 if (ref $range) {
2073 20 50       21 if (scalar(@{$range}) == 1) {
  20 50       51  
2074 0         0 push @singleoctet, sprintf('\x%02X', @{$range}[0]);
  0         0  
2075             }
2076 20         37 elsif (scalar(@{$range}) == 2) {
2077 0         0 push @singleoctet, sprintf('\x%02X\x%02X', @{$range}[0], @{$range}[-1]);
  0         0  
  0         0  
2078             }
2079             else {
2080 20         28 push @singleoctet, sprintf('\x%02X-\x%02X', @{$range}[0], @{$range}[-1]);
  20         30  
  20         143  
2081             }
2082             }
2083             }
2084             }
2085              
2086             # return character list
2087 44 50       111 if (scalar(@multipleoctet) >= 1) {
2088 0 0       0 if (scalar(@singleoctet) >= 1) {
2089              
2090             # any character other than multiple-octet and single octet character class
2091 0         0 return '(?!' . join('|', @multipleoctet) . ')(?:[^' . join('', @singleoctet) . '])';
2092             }
2093             else {
2094              
2095             # any character other than multiple-octet character class
2096 0         0 return '(?!' . join('|', @multipleoctet) . ")(?:$your_char)";
2097             }
2098             }
2099             else {
2100 44 50       96 if (scalar(@singleoctet) >= 1) {
2101              
2102             # any character other than single octet character class
2103 44         276 return '(?:[^' . join('', @singleoctet) . '])';
2104             }
2105             else {
2106              
2107             # any character
2108 0         0 return "(?:$your_char)";
2109             }
2110             }
2111             }
2112              
2113             #
2114             # open file in read mode
2115             #
2116             sub _open_r {
2117 400     400   1033 my(undef,$file) = @_;
2118 400         1886 $file =~ s#\A (\s) #./$1#oxms;
2119 400   33     32607 return CORE::eval(q{open($_[0],'<',$_[1])}) ||
2120             open($_[0],"< $file\0");
2121             }
2122              
2123             #
2124             # open file in write mode
2125             #
2126             sub _open_w {
2127 0     0   0 my(undef,$file) = @_;
2128 0         0 $file =~ s#\A (\s) #./$1#oxms;
2129 0   0     0 return CORE::eval(q{open($_[0],'>',$_[1])}) ||
2130             open($_[0],"> $file\0");
2131             }
2132              
2133             #
2134             # open file in append mode
2135             #
2136             sub _open_a {
2137 0     0   0 my(undef,$file) = @_;
2138 0         0 $file =~ s#\A (\s) #./$1#oxms;
2139 0   0     0 return CORE::eval(q{open($_[0],'>>',$_[1])}) ||
2140             open($_[0],">> $file\0");
2141             }
2142              
2143             #
2144             # safe system
2145             #
2146             sub _systemx {
2147              
2148             # P.707 29.2.33. exec
2149             # in Chapter 29: Functions
2150             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
2151             #
2152             # Be aware that in older releases of Perl, exec (and system) did not flush
2153             # your output buffer, so you needed to enable command buffering by setting $|
2154             # on one or more filehandles to avoid lost output in the case of exec, or
2155             # misordererd output in the case of system. This situation was largely remedied
2156             # in the 5.6 release of Perl. (So, 5.005 release not yet.)
2157              
2158             # P.855 exec
2159             # in Chapter 27: Functions
2160             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
2161             #
2162             # In very old release of Perl (before v5.6), exec (and system) did not flush
2163             # your output buffer, so you needed to enable command buffering by setting $|
2164             # on one or more filehandles to avoid lost output with exec or misordered
2165             # output with system.
2166              
2167 200     200   854 $| = 1;
2168              
2169             # P.565 23.1.2. Cleaning Up Your Environment
2170             # in Chapter 23: Security
2171             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
2172              
2173             # P.656 Cleaning Up Your Environment
2174             # in Chapter 20: Security
2175             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
2176              
2177             # local $ENV{'PATH'} = '.';
2178 200         1871 local @ENV{qw(IFS CDPATH ENV BASH_ENV)}; # Make %ENV safer
2179              
2180             # P.707 29.2.33. exec
2181             # in Chapter 29: Functions
2182             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
2183             #
2184             # As we mentioned earlier, exec treats a discrete list of arguments as an
2185             # indication that it should bypass shell processing. However, there is one
2186             # place where you might still get tripped up. The exec call (and system, too)
2187             # will not distinguish between a single scalar argument and an array containing
2188             # only one element.
2189             #
2190             # @args = ("echo surprise"); # just one element in list
2191             # exec @args # still subject to shell escapes
2192             # or die "exec: $!"; # because @args == 1
2193             #
2194             # To avoid this, you can use the PATHNAME syntax, explicitly duplicating the
2195             # first argument as the pathname, which forces the rest of the arguments to be
2196             # interpreted as a list, even if there is only one of them:
2197             #
2198             # exec { $args[0] } @args # safe even with one-argument list
2199             # or die "can't exec @args: $!";
2200              
2201             # P.855 exec
2202             # in Chapter 27: Functions
2203             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
2204             #
2205             # As we mentioned earlier, exec treats a discrete list of arguments as a
2206             # directive to bypass shell processing. However, there is one place where
2207             # you might still get tripped up. The exec call (and system, too) cannot
2208             # distinguish between a single scalar argument and an array containing
2209             # only one element.
2210             #
2211             # @args = ("echo surprise"); # just one element in list
2212             # exec @args # still subject to shell escapes
2213             # || die "exec: $!"; # because @args == 1
2214             #
2215             # To avoid this, use the PATHNAME syntax, explicitly duplicating the first
2216             # argument as the pathname, which forces the rest of the arguments to be
2217             # interpreted as a list, even if there is only one of them:
2218             #
2219             # exec { $args[0] } @args # safe even with one-argument list
2220             # || die "can't exec @args: $!";
2221              
2222 200         357 return CORE::system { $_[0] } @_; # safe even with one-argument list
  200         17385604  
2223             }
2224              
2225             #
2226             # KOI8-R order to character (with parameter)
2227             #
2228             sub Ekoi8r::chr(;$) {
2229              
2230 0 0   0 0 0 my $c = @_ ? $_[0] : $_;
2231              
2232 0 0       0 if ($c == 0x00) {
2233 0         0 return "\x00";
2234             }
2235             else {
2236 0         0 my @chr = ();
2237 0         0 while ($c > 0) {
2238 0         0 unshift @chr, ($c % 0x100);
2239 0         0 $c = int($c / 0x100);
2240             }
2241 0         0 return pack 'C*', @chr;
2242             }
2243             }
2244              
2245             #
2246             # KOI8-R order to character (without parameter)
2247             #
2248             sub Ekoi8r::chr_() {
2249              
2250 0     0 0 0 my $c = $_;
2251              
2252 0 0       0 if ($c == 0x00) {
2253 0         0 return "\x00";
2254             }
2255             else {
2256 0         0 my @chr = ();
2257 0         0 while ($c > 0) {
2258 0         0 unshift @chr, ($c % 0x100);
2259 0         0 $c = int($c / 0x100);
2260             }
2261 0         0 return pack 'C*', @chr;
2262             }
2263             }
2264              
2265             #
2266             # KOI8-R path globbing (with parameter)
2267             #
2268             sub Ekoi8r::glob($) {
2269              
2270 0 0   0 0 0 if (wantarray) {
2271 0         0 my @glob = _DOS_like_glob(@_);
2272 0         0 for my $glob (@glob) {
2273 0         0 $glob =~ s{ \A (?:\./)+ }{}oxms;
2274             }
2275 0         0 return @glob;
2276             }
2277             else {
2278 0         0 my $glob = _DOS_like_glob(@_);
2279 0         0 $glob =~ s{ \A (?:\./)+ }{}oxms;
2280 0         0 return $glob;
2281             }
2282             }
2283              
2284             #
2285             # KOI8-R path globbing (without parameter)
2286             #
2287             sub Ekoi8r::glob_() {
2288              
2289 0 0   0 0 0 if (wantarray) {
2290 0         0 my @glob = _DOS_like_glob();
2291 0         0 for my $glob (@glob) {
2292 0         0 $glob =~ s{ \A (?:\./)+ }{}oxms;
2293             }
2294 0         0 return @glob;
2295             }
2296             else {
2297 0         0 my $glob = _DOS_like_glob();
2298 0         0 $glob =~ s{ \A (?:\./)+ }{}oxms;
2299 0         0 return $glob;
2300             }
2301             }
2302              
2303             #
2304             # KOI8-R path globbing via File::DosGlob 1.10
2305             #
2306             # Often I confuse "_dosglob" and "_doglob".
2307             # So, I renamed "_dosglob" to "_DOS_like_glob".
2308             #
2309             my %iter;
2310             my %entries;
2311             sub _DOS_like_glob {
2312              
2313             # context (keyed by second cxix argument provided by core)
2314 0     0   0 my($expr,$cxix) = @_;
2315              
2316             # glob without args defaults to $_
2317 0 0       0 $expr = $_ if not defined $expr;
2318              
2319             # represents the current user's home directory
2320             #
2321             # 7.3. Expanding Tildes in Filenames
2322             # in Chapter 7. File Access
2323             # of ISBN 0-596-00313-7 Perl Cookbook, 2nd Edition.
2324             #
2325             # and File::HomeDir, File::HomeDir::Windows module
2326              
2327             # DOS-like system
2328 0 0       0 if ($^O =~ /\A (?: MSWin32 | NetWare | symbian | dos ) \z/oxms) {
2329 0         0 $expr =~ s{ \A ~ (?= [^/\\] ) }
2330 0         0 { my_home_MSWin32() }oxmse;
2331             }
2332              
2333             # UNIX-like system
2334             else {
2335 0         0 $expr =~ s{ \A ~ ( (?:[^/])* ) }
2336 0 0 0     0 { $1 ? (CORE::eval(q{(getpwnam($1))[7]})||my_home()) : my_home() }oxmse;
2337             }
2338              
2339             # assume global context if not provided one
2340 0 0       0 $cxix = '_G_' if not defined $cxix;
2341 0 0       0 $iter{$cxix} = 0 if not exists $iter{$cxix};
2342              
2343             # if we're just beginning, do it all first
2344 0 0       0 if ($iter{$cxix} == 0) {
2345 0         0 $entries{$cxix} = [ _do_glob(1, _parse_line($expr)) ];
2346             }
2347              
2348             # chuck it all out, quick or slow
2349 0 0       0 if (wantarray) {
2350 0         0 delete $iter{$cxix};
2351 0         0 return @{delete $entries{$cxix}};
  0         0  
2352             }
2353             else {
2354 0 0       0 if ($iter{$cxix} = scalar @{$entries{$cxix}}) {
  0         0  
2355 0         0 return shift @{$entries{$cxix}};
  0         0  
2356             }
2357             else {
2358             # return undef for EOL
2359 0         0 delete $iter{$cxix};
2360 0         0 delete $entries{$cxix};
2361 0         0 return undef;
2362             }
2363             }
2364             }
2365              
2366             #
2367             # KOI8-R path globbing subroutine
2368             #
2369             sub _do_glob {
2370              
2371 0     0   0 my($cond,@expr) = @_;
2372 0         0 my @glob = ();
2373 0         0 my $fix_drive_relative_paths = 0;
2374              
2375             OUTER:
2376 0         0 for my $expr (@expr) {
2377 0 0       0 next OUTER if not defined $expr;
2378 0 0       0 next OUTER if $expr eq '';
2379              
2380 0         0 my @matched = ();
2381 0         0 my @globdir = ();
2382 0         0 my $head = '.';
2383 0         0 my $pathsep = '/';
2384 0         0 my $tail;
2385              
2386             # if argument is within quotes strip em and do no globbing
2387 0 0       0 if ($expr =~ /\A " ((?:$q_char)*?) " \z/oxms) {
2388 0         0 $expr = $1;
2389 0 0       0 if ($cond eq 'd') {
2390 0 0       0 if (-d $expr) {
2391 0         0 push @glob, $expr;
2392             }
2393             }
2394             else {
2395 0 0       0 if (-e $expr) {
2396 0         0 push @glob, $expr;
2397             }
2398             }
2399 0         0 next OUTER;
2400             }
2401              
2402             # wildcards with a drive prefix such as h:*.pm must be changed
2403             # to h:./*.pm to expand correctly
2404 0 0       0 if ($^O =~ /\A (?: MSWin32 | NetWare | symbian | dos ) \z/oxms) {
2405 0 0       0 if ($expr =~ s# \A ((?:[A-Za-z]:)?) ([^/\\]) #$1./$2#oxms) {
2406 0         0 $fix_drive_relative_paths = 1;
2407             }
2408             }
2409              
2410 0 0       0 if (($head, $tail) = _parse_path($expr,$pathsep)) {
2411 0 0       0 if ($tail eq '') {
2412 0         0 push @glob, $expr;
2413 0         0 next OUTER;
2414             }
2415 0 0       0 if ($head =~ / \A (?:$q_char)*? [*?] /oxms) {
2416 0 0       0 if (@globdir = _do_glob('d', $head)) {
2417 0         0 push @glob, _do_glob($cond, map {"$_$pathsep$tail"} @globdir);
  0         0  
2418 0         0 next OUTER;
2419             }
2420             }
2421 0 0 0     0 if ($head eq '' or $head =~ /\A [A-Za-z]: \z/oxms) {
2422 0         0 $head .= $pathsep;
2423             }
2424 0         0 $expr = $tail;
2425             }
2426              
2427             # If file component has no wildcards, we can avoid opendir
2428 0 0       0 if ($expr !~ / \A (?:$q_char)*? [*?] /oxms) {
2429 0 0       0 if ($head eq '.') {
2430 0         0 $head = '';
2431             }
2432 0 0 0     0 if ($head ne '' and ($head =~ / \G ($q_char) /oxmsg)[-1] ne $pathsep) {
2433 0         0 $head .= $pathsep;
2434             }
2435 0         0 $head .= $expr;
2436 0 0       0 if ($cond eq 'd') {
2437 0 0       0 if (-d $head) {
2438 0         0 push @glob, $head;
2439             }
2440             }
2441             else {
2442 0 0       0 if (-e $head) {
2443 0         0 push @glob, $head;
2444             }
2445             }
2446 0         0 next OUTER;
2447             }
2448 0 0       0 opendir(*DIR, $head) or next OUTER;
2449 0         0 my @leaf = readdir DIR;
2450 0         0 closedir DIR;
2451              
2452 0 0       0 if ($head eq '.') {
2453 0         0 $head = '';
2454             }
2455 0 0 0     0 if ($head ne '' and ($head =~ / \G ($q_char) /oxmsg)[-1] ne $pathsep) {
2456 0         0 $head .= $pathsep;
2457             }
2458              
2459 0         0 my $pattern = '';
2460 0         0 while ($expr =~ / \G ($q_char) /oxgc) {
2461 0         0 my $char = $1;
2462              
2463             # 6.9. Matching Shell Globs as Regular Expressions
2464             # in Chapter 6. Pattern Matching
2465             # of ISBN 0-596-00313-7 Perl Cookbook, 2nd Edition.
2466             # (and so on)
2467              
2468 0 0       0 if ($char eq '*') {
    0          
    0          
2469 0         0 $pattern .= "(?:$your_char)*",
2470             }
2471             elsif ($char eq '?') {
2472 0         0 $pattern .= "(?:$your_char)?", # DOS style
2473             # $pattern .= "(?:$your_char)", # UNIX style
2474             }
2475             elsif ((my $fc = Ekoi8r::fc($char)) ne $char) {
2476 0         0 $pattern .= $fc;
2477             }
2478             else {
2479 0         0 $pattern .= quotemeta $char;
2480             }
2481             }
2482 0     0   0 my $matchsub = sub { Ekoi8r::fc($_[0]) =~ /\A $pattern \z/xms };
  0         0  
2483              
2484             # if ($@) {
2485             # print STDERR "$0: $@\n";
2486             # next OUTER;
2487             # }
2488              
2489             INNER:
2490 0         0 for my $leaf (@leaf) {
2491 0 0 0     0 if ($leaf eq '.' or $leaf eq '..') {
2492 0         0 next INNER;
2493             }
2494 0 0 0     0 if ($cond eq 'd' and not -d "$head$leaf") {
2495 0         0 next INNER;
2496             }
2497              
2498 0 0       0 if (&$matchsub($leaf)) {
2499 0         0 push @matched, "$head$leaf";
2500 0         0 next INNER;
2501             }
2502              
2503             # [DOS compatibility special case]
2504             # Failed, add a trailing dot and try again, but only...
2505              
2506 0 0 0     0 if (Ekoi8r::index($leaf,'.') == -1 and # if name does not have a dot in it *and*
      0        
2507             CORE::length($leaf) <= 8 and # name is shorter than or equal to 8 chars *and*
2508             Ekoi8r::index($pattern,'\\.') != -1 # pattern has a dot.
2509             ) {
2510 0 0       0 if (&$matchsub("$leaf.")) {
2511 0         0 push @matched, "$head$leaf";
2512 0         0 next INNER;
2513             }
2514             }
2515             }
2516 0 0       0 if (@matched) {
2517 0         0 push @glob, @matched;
2518             }
2519             }
2520 0 0       0 if ($fix_drive_relative_paths) {
2521 0         0 for my $glob (@glob) {
2522 0         0 $glob =~ s# \A ([A-Za-z]:) \./ #$1#oxms;
2523             }
2524             }
2525 0         0 return @glob;
2526             }
2527              
2528             #
2529             # KOI8-R parse line
2530             #
2531             sub _parse_line {
2532              
2533 0     0   0 my($line) = @_;
2534              
2535 0         0 $line .= ' ';
2536 0         0 my @piece = ();
2537 0         0 while ($line =~ /
2538             " ( (?>(?: [^"] )* ) ) " (?>\s+) |
2539             ( (?>(?: [^"\s] )* ) ) (?>\s+)
2540             /oxmsg
2541             ) {
2542 0 0       0 push @piece, defined($1) ? $1 : $2;
2543             }
2544 0         0 return @piece;
2545             }
2546              
2547             #
2548             # KOI8-R parse path
2549             #
2550             sub _parse_path {
2551              
2552 0     0   0 my($path,$pathsep) = @_;
2553              
2554 0         0 $path .= '/';
2555 0         0 my @subpath = ();
2556 0         0 while ($path =~ /
2557             ((?: [^\/\\] )+?) [\/\\]
2558             /oxmsg
2559             ) {
2560 0         0 push @subpath, $1;
2561             }
2562              
2563 0         0 my $tail = pop @subpath;
2564 0         0 my $head = join $pathsep, @subpath;
2565 0         0 return $head, $tail;
2566             }
2567              
2568             #
2569             # via File::HomeDir::Windows 1.00
2570             #
2571             sub my_home_MSWin32 {
2572              
2573             # A lot of unix people and unix-derived tools rely on
2574             # the ability to overload HOME. We will support it too
2575             # so that they can replace raw HOME calls with File::HomeDir.
2576 0 0 0 0 0 0 if (exists $ENV{'HOME'} and $ENV{'HOME'}) {
    0 0        
    0 0        
      0        
      0        
2577 0         0 return $ENV{'HOME'};
2578             }
2579              
2580             # Do we have a user profile?
2581             elsif (exists $ENV{'USERPROFILE'} and $ENV{'USERPROFILE'}) {
2582 0         0 return $ENV{'USERPROFILE'};
2583             }
2584              
2585             # Some Windows use something like $ENV{'HOME'}
2586             elsif (exists $ENV{'HOMEDRIVE'} and exists $ENV{'HOMEPATH'} and $ENV{'HOMEDRIVE'} and $ENV{'HOMEPATH'}) {
2587 0         0 return join '', $ENV{'HOMEDRIVE'}, $ENV{'HOMEPATH'};
2588             }
2589              
2590 0         0 return undef;
2591             }
2592              
2593             #
2594             # via File::HomeDir::Unix 1.00
2595             #
2596             sub my_home {
2597 0     0 0 0 my $home;
2598              
2599 0 0 0     0 if (exists $ENV{'HOME'} and defined $ENV{'HOME'}) {
    0 0        
2600 0         0 $home = $ENV{'HOME'};
2601             }
2602              
2603             # This is from the original code, but I'm guessing
2604             # it means "login directory" and exists on some Unixes.
2605             elsif (exists $ENV{'LOGDIR'} and $ENV{'LOGDIR'}) {
2606 0         0 $home = $ENV{'LOGDIR'};
2607             }
2608              
2609             ### More-desperate methods
2610              
2611             # Light desperation on any (Unixish) platform
2612             else {
2613 0         0 $home = CORE::eval q{ (getpwuid($<))[7] };
2614             }
2615              
2616             # On Unix in general, a non-existant home means "no home"
2617             # For example, "nobody"-like users might use /nonexistant
2618 0 0 0     0 if (defined $home and ! -d($home)) {
2619 0         0 $home = undef;
2620             }
2621 0         0 return $home;
2622             }
2623              
2624             #
2625             # ${^PREMATCH}, $PREMATCH, $` the string preceding what was matched
2626             #
2627             sub Ekoi8r::PREMATCH {
2628 0     0 0 0 return $`;
2629             }
2630              
2631             #
2632             # ${^MATCH}, $MATCH, $& the string that matched
2633             #
2634             sub Ekoi8r::MATCH {
2635 0     0 0 0 return $&;
2636             }
2637              
2638             #
2639             # ${^POSTMATCH}, $POSTMATCH, $' the string following what was matched
2640             #
2641             sub Ekoi8r::POSTMATCH {
2642 0     0 0 0 return $';
2643             }
2644              
2645             #
2646             # KOI8-R character to order (with parameter)
2647             #
2648             sub KOI8R::ord(;$) {
2649              
2650 0 0   0 1 0 local $_ = shift if @_;
2651              
2652 0 0       0 if (/\A ($q_char) /oxms) {
2653 0         0 my @ord = unpack 'C*', $1;
2654 0         0 my $ord = 0;
2655 0         0 while (my $o = shift @ord) {
2656 0         0 $ord = $ord * 0x100 + $o;
2657             }
2658 0         0 return $ord;
2659             }
2660             else {
2661 0         0 return CORE::ord $_;
2662             }
2663             }
2664              
2665             #
2666             # KOI8-R character to order (without parameter)
2667             #
2668             sub KOI8R::ord_() {
2669              
2670 0 0   0 0 0 if (/\A ($q_char) /oxms) {
2671 0         0 my @ord = unpack 'C*', $1;
2672 0         0 my $ord = 0;
2673 0         0 while (my $o = shift @ord) {
2674 0         0 $ord = $ord * 0x100 + $o;
2675             }
2676 0         0 return $ord;
2677             }
2678             else {
2679 0         0 return CORE::ord $_;
2680             }
2681             }
2682              
2683             #
2684             # KOI8-R reverse
2685             #
2686             sub KOI8R::reverse(@) {
2687              
2688 0 0   0 0 0 if (wantarray) {
2689 0         0 return CORE::reverse @_;
2690             }
2691             else {
2692              
2693             # One of us once cornered Larry in an elevator and asked him what
2694             # problem he was solving with this, but he looked as far off into
2695             # the distance as he could in an elevator and said, "It seemed like
2696             # a good idea at the time."
2697              
2698 0         0 return join '', CORE::reverse(join('',@_) =~ /\G ($q_char) /oxmsg);
2699             }
2700             }
2701              
2702             #
2703             # KOI8-R getc (with parameter, without parameter)
2704             #
2705             sub KOI8R::getc(;*@) {
2706              
2707 0     0 0 0 my($package) = caller;
2708 0 0       0 my $fh = @_ ? qualify_to_ref(shift,$package) : \*STDIN;
2709 0 0 0     0 croak 'Too many arguments for KOI8R::getc' if @_ and not wantarray;
2710              
2711 0         0 my @length = sort { $a <=> $b } keys %range_tr;
  0         0  
2712 0         0 my $getc = '';
2713 0         0 for my $length ($length[0] .. $length[-1]) {
2714 0         0 $getc .= CORE::getc($fh);
2715 0 0       0 if (exists $range_tr{CORE::length($getc)}) {
2716 0 0       0 if ($getc =~ /\A ${Ekoi8r::dot_s} \z/oxms) {
2717 0 0       0 return wantarray ? ($getc,@_) : $getc;
2718             }
2719             }
2720             }
2721 0 0       0 return wantarray ? ($getc,@_) : $getc;
2722             }
2723              
2724             #
2725             # KOI8-R length by character
2726             #
2727             sub KOI8R::length(;$) {
2728              
2729 0 0   0 1 0 local $_ = shift if @_;
2730              
2731 0         0 local @_ = /\G ($q_char) /oxmsg;
2732 0         0 return scalar @_;
2733             }
2734              
2735             #
2736             # KOI8-R substr by character
2737             #
2738             BEGIN {
2739              
2740             # P.232 The lvalue Attribute
2741             # in Chapter 6: Subroutines
2742             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
2743              
2744             # P.336 The lvalue Attribute
2745             # in Chapter 7: Subroutines
2746             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
2747              
2748             # P.144 8.4 Lvalue subroutines
2749             # in Chapter 8: perlsub: Perl subroutines
2750             # of ISBN-13: 978-1-906966-02-7 The Perl Language Reference Manual (for Perl version 5.12.1)
2751              
2752 200 50 0 200 1 119401 CORE::eval sprintf(<<'END', ($] >= 5.014000) ? ':lvalue' : '');
  0 0   0   0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
2753             # vv----------------------*******
2754             sub KOI8R::substr($$;$$) %s {
2755              
2756             my @char = $_[0] =~ /\G (?>$q_char) /oxmsg;
2757              
2758             # If the substring is beyond either end of the string, substr() returns the undefined
2759             # value and produces a warning. When used as an lvalue, specifying a substring that
2760             # is entirely outside the string raises an exception.
2761             # http://perldoc.perl.org/functions/substr.html
2762              
2763             # A return with no argument returns the scalar value undef in scalar context,
2764             # an empty list () in list context, and (naturally) nothing at all in void
2765             # context.
2766              
2767             my $offset = $_[1];
2768             if (($offset > scalar(@char)) or ($offset < (-1 * scalar(@char)))) {
2769             return;
2770             }
2771              
2772             # substr($string,$offset,$length,$replacement)
2773             if (@_ == 4) {
2774             my(undef,undef,$length,$replacement) = @_;
2775             my $substr = join '', splice(@char, $offset, $length, $replacement);
2776             $_[0] = join '', @char;
2777              
2778             # return $substr; this doesn't work, don't say "return"
2779             $substr;
2780             }
2781              
2782             # substr($string,$offset,$length)
2783             elsif (@_ == 3) {
2784             my(undef,undef,$length) = @_;
2785             my $octet_offset = 0;
2786             my $octet_length = 0;
2787             if ($offset == 0) {
2788             $octet_offset = 0;
2789             }
2790             elsif ($offset > 0) {
2791             $octet_offset = CORE::length(join '', @char[0..$offset-1]);
2792             }
2793             else {
2794             $octet_offset = -1 * CORE::length(join '', @char[$#char+$offset+1..$#char]);
2795             }
2796             if ($length == 0) {
2797             $octet_length = 0;
2798             }
2799             elsif ($length > 0) {
2800             $octet_length = CORE::length(join '', @char[$offset..$offset+$length-1]);
2801             }
2802             else {
2803             $octet_length = -1 * CORE::length(join '', @char[$#char+$length+1..$#char]);
2804             }
2805             CORE::substr($_[0], $octet_offset, $octet_length);
2806             }
2807              
2808             # substr($string,$offset)
2809             else {
2810             my $octet_offset = 0;
2811             if ($offset == 0) {
2812             $octet_offset = 0;
2813             }
2814             elsif ($offset > 0) {
2815             $octet_offset = CORE::length(join '', @char[0..$offset-1]);
2816             }
2817             else {
2818             $octet_offset = -1 * CORE::length(join '', @char[$#char+$offset+1..$#char]);
2819             }
2820             CORE::substr($_[0], $octet_offset);
2821             }
2822             }
2823             END
2824             }
2825              
2826             #
2827             # KOI8-R index by character
2828             #
2829             sub KOI8R::index($$;$) {
2830              
2831 0     0 1 0 my $index;
2832 0 0       0 if (@_ == 3) {
2833 0         0 $index = Ekoi8r::index($_[0], $_[1], CORE::length(KOI8R::substr($_[0], 0, $_[2])));
2834             }
2835             else {
2836 0         0 $index = Ekoi8r::index($_[0], $_[1]);
2837             }
2838              
2839 0 0       0 if ($index == -1) {
2840 0         0 return -1;
2841             }
2842             else {
2843 0         0 return KOI8R::length(CORE::substr $_[0], 0, $index);
2844             }
2845             }
2846              
2847             #
2848             # KOI8-R rindex by character
2849             #
2850             sub KOI8R::rindex($$;$) {
2851              
2852 0     0 1 0 my $rindex;
2853 0 0       0 if (@_ == 3) {
2854 0         0 $rindex = Ekoi8r::rindex($_[0], $_[1], CORE::length(KOI8R::substr($_[0], 0, $_[2])));
2855             }
2856             else {
2857 0         0 $rindex = Ekoi8r::rindex($_[0], $_[1]);
2858             }
2859              
2860 0 0       0 if ($rindex == -1) {
2861 0         0 return -1;
2862             }
2863             else {
2864 0         0 return KOI8R::length(CORE::substr $_[0], 0, $rindex);
2865             }
2866             }
2867              
2868             # when 'm//', '/' means regexp match 'm//' and '?' means regexp match '??'
2869             # when 'div', '/' means division operator and '?' means conditional operator (condition ? then : else)
2870 200     200   15833 BEGIN { CORE::eval q{ use vars qw($slash) } } $slash = 'm//';
  200     200   1627  
  200         339  
  200         13762  
2871              
2872             # ord() to ord() or KOI8R::ord()
2873 200     200   11716 BEGIN { CORE::eval q{ use vars qw($function_ord) } } $function_ord = 'ord';
  200     200   1021  
  200         385  
  200         10601  
2874              
2875             # ord to ord or KOI8R::ord_
2876 200     200   11801 BEGIN { CORE::eval q{ use vars qw($function_ord_) } } $function_ord_ = 'ord';
  200     200   1028  
  200         342  
  200         10366  
2877              
2878             # reverse to reverse or KOI8R::reverse
2879 200     200   11392 BEGIN { CORE::eval q{ use vars qw($function_reverse) } } $function_reverse = 'reverse';
  200     200   970  
  200         339  
  200         14674  
2880              
2881             # getc to getc or KOI8R::getc
2882 200     200   10854 BEGIN { CORE::eval q{ use vars qw($function_getc) } } $function_getc = 'getc';
  200     200   1017  
  200         305  
  200         11048  
2883              
2884             # P.1023 Appendix W.9 Multibyte Anchoring
2885             # of ISBN 1-56592-224-7 CJKV Information Processing
2886              
2887             my $anchor = '';
2888              
2889 200     200   11023 BEGIN { CORE::eval q{ use vars qw($nest) } }
  200     200   940  
  200         314  
  200         8860343  
2890              
2891             # regexp of nested parens in qqXX
2892              
2893             # P.340 Matching Nested Constructs with Embedded Code
2894             # in Chapter 7: Perl
2895             # of ISBN 0-596-00289-0 Mastering Regular Expressions, Second edition
2896              
2897             my $qq_paren = qr{(?{local $nest=0}) (?>(?:
2898             [^\\()] |
2899             \( (?{$nest++}) |
2900             \) (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!)) |
2901             \\ [^c] |
2902             \\c[\x40-\x5F] |
2903             [\x00-\xFF]
2904             }xms;
2905              
2906             my $qq_brace = qr{(?{local $nest=0}) (?>(?:
2907             [^\\{}] |
2908             \{ (?{$nest++}) |
2909             \} (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!)) |
2910             \\ [^c] |
2911             \\c[\x40-\x5F] |
2912             [\x00-\xFF]
2913             }xms;
2914              
2915             my $qq_bracket = qr{(?{local $nest=0}) (?>(?:
2916             [^\\\[\]] |
2917             \[ (?{$nest++}) |
2918             \] (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!)) |
2919             \\ [^c] |
2920             \\c[\x40-\x5F] |
2921             [\x00-\xFF]
2922             }xms;
2923              
2924             my $qq_angle = qr{(?{local $nest=0}) (?>(?:
2925             [^\\<>] |
2926             \< (?{$nest++}) |
2927             \> (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!)) |
2928             \\ [^c] |
2929             \\c[\x40-\x5F] |
2930             [\x00-\xFF]
2931             }xms;
2932              
2933             my $qq_scalar = qr{(?: \{ (?:$qq_brace)*? \} |
2934             (?: ::)? (?:
2935             (?> [a-zA-Z_][a-zA-Z_0-9]* (?: ::[a-zA-Z_][a-zA-Z_0-9]*)* )
2936             (?>(?: \[ (?: \$\[ | \$\] | $qq_char )*? \] | \{ (?:$qq_brace)*? \} )*)
2937             (?>(?: (?: -> )? (?: [\$\@\%\&\*]\* | \$\#\* | [\@\%]? \[ (?: \$\[ | \$\] | $qq_char )*? \] | [\@\%\*]? \{ (?:$qq_brace)*? \} ) )*)
2938             ))
2939             }xms;
2940              
2941             my $qq_variable = qr{(?: \{ (?:$qq_brace)*? \} |
2942             (?: ::)? (?:
2943             (?>[0-9]+) |
2944             [^a-zA-Z_0-9\[\]] |
2945             ^[A-Z] |
2946             (?> [a-zA-Z_][a-zA-Z_0-9]* (?: ::[a-zA-Z_][a-zA-Z_0-9]*)* )
2947             (?>(?: \[ (?: \$\[ | \$\] | $qq_char )*? \] | \{ (?:$qq_brace)*? \} )*)
2948             (?>(?: (?: -> )? (?: [\$\@\%\&\*]\* | \$\#\* | [\@\%]? \[ (?: \$\[ | \$\] | $qq_char )*? \] | [\@\%\*]? \{ (?:$qq_brace)*? \} ) )*)
2949             ))
2950             }xms;
2951              
2952             my $qq_substr = qr{(?> Char::substr | KOI8R::substr | CORE::substr | substr ) (?>\s*) \( $qq_paren \)
2953             }xms;
2954              
2955             # regexp of nested parens in qXX
2956             my $q_paren = qr{(?{local $nest=0}) (?>(?:
2957             [^()] |
2958             \( (?{$nest++}) |
2959             \) (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!)) |
2960             [\x00-\xFF]
2961             }xms;
2962              
2963             my $q_brace = qr{(?{local $nest=0}) (?>(?:
2964             [^\{\}] |
2965             \{ (?{$nest++}) |
2966             \} (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!)) |
2967             [\x00-\xFF]
2968             }xms;
2969              
2970             my $q_bracket = qr{(?{local $nest=0}) (?>(?:
2971             [^\[\]] |
2972             \[ (?{$nest++}) |
2973             \] (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!)) |
2974             [\x00-\xFF]
2975             }xms;
2976              
2977             my $q_angle = qr{(?{local $nest=0}) (?>(?:
2978             [^<>] |
2979             \< (?{$nest++}) |
2980             \> (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!)) |
2981             [\x00-\xFF]
2982             }xms;
2983              
2984             my $matched = '';
2985             my $s_matched = '';
2986              
2987             my $tr_variable = ''; # variable of tr///
2988             my $sub_variable = ''; # variable of s///
2989             my $bind_operator = ''; # =~ or !~
2990              
2991             my @heredoc = (); # here document
2992             my @heredoc_delimiter = ();
2993             my $here_script = ''; # here script
2994              
2995             #
2996             # escape KOI8-R script
2997             #
2998             sub KOI8R::escape(;$) {
2999 200 50   200 0 695 local($_) = $_[0] if @_;
3000              
3001             # P.359 The Study Function
3002             # in Chapter 7: Perl
3003             # of ISBN 0-596-00289-0 Mastering Regular Expressions, Second edition
3004              
3005 200         343 study $_; # Yes, I studied study yesterday.
3006              
3007             # while all script
3008              
3009             # 6.14. Matching from Where the Last Pattern Left Off
3010             # in Chapter 6. Pattern Matching
3011             # of ISBN 0-596-00313-7 Perl Cookbook, 2nd Edition.
3012             # (and so on)
3013              
3014             # one member of Tag-team
3015             #
3016             # P.128 Start of match (or end of previous match): \G
3017             # P.130 Advanced Use of \G with Perl
3018             # in Chapter 3: Overview of Regular Expression Features and Flavors
3019             # P.255 Use leading anchors
3020             # P.256 Expose ^ and \G at the front expressions
3021             # in Chapter 6: Crafting an Efficient Expression
3022             # P.315 "Tag-team" matching with /gc
3023             # in Chapter 7: Perl
3024             # of ISBN 0-596-00289-0 Mastering Regular Expressions, Second edition
3025              
3026 200         354 my $e_script = '';
3027 200         879 while (not /\G \z/oxgc) { # member
3028 71650         92288 $e_script .= KOI8R::escape_token();
3029             }
3030              
3031 200         2378 return $e_script;
3032             }
3033              
3034             #
3035             # escape KOI8-R token of script
3036             #
3037             sub KOI8R::escape_token {
3038              
3039             # \n output here document
3040              
3041 71650     71650 0 61615 my $ignore_modules = join('|', qw(
3042             utf8
3043             bytes
3044             charnames
3045             I18N::Japanese
3046             I18N::Collate
3047             I18N::JExt
3048             File::DosGlob
3049             Wild
3050             Wildcard
3051             Japanese
3052             ));
3053              
3054             # another member of Tag-team
3055             #
3056             # P.315 "Tag-team" matching with /gc
3057             # in Chapter 7: Perl
3058             # of ISBN 0-596-00289-0 Mastering Regular Expressions, Second edition
3059              
3060 71650 100 100     3998128 if (/\G ( \n ) /oxgc) { # another member (and so on)
    100 66        
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    50          
    100          
    50          
    100          
    100          
    50          
    50          
    50          
    50          
    50          
    50          
    100          
    100          
    50          
    50          
    50          
    50          
    100          
    100          
    50          
    100          
    50          
    100          
    100          
    50          
    100          
    50          
    50          
    50          
    100          
    50          
    50          
    50          
    100          
    50          
    100          
    50          
    100          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    100          
    100          
    100          
    100          
    100          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    100          
    100          
    100          
    100          
    50          
    100          
    50          
    100          
    100          
    100          
    50          
    50          
    50          
    100          
    50          
    50          
    100          
    50          
    100          
    50          
    50          
    50          
    50          
    50          
    50          
    100          
    100          
    100          
    100          
    100          
    50          
    50          
    50          
    100          
    50          
    100          
    100          
    50          
    100          
    50          
    50          
    50          
    100          
    50          
    50          
    100          
    100          
    100          
    50          
3061 12063         12594 my $heredoc = '';
3062 12063 100       21309 if (scalar(@heredoc_delimiter) >= 1) {
3063 150         170 $slash = 'm//';
3064              
3065 150         286 $heredoc = join '', @heredoc;
3066 150         381 @heredoc = ();
3067              
3068             # skip here document
3069 150         263 for my $heredoc_delimiter (@heredoc_delimiter) {
3070 150         1172 /\G .*? \n $heredoc_delimiter \n/xmsgc;
3071             }
3072 150         235 @heredoc_delimiter = ();
3073              
3074 150         192 $here_script = '';
3075             }
3076 12063         36054 return "\n" . $heredoc;
3077             }
3078              
3079             # ignore space, comment
3080 17212         51757 elsif (/\G ((?>\s+)|\#.*) /oxgc) { return $1; }
3081              
3082             # if (, elsif (, unless (, while (, until (, given (, and when (
3083              
3084             # given, when
3085              
3086             # P.225 The given Statement
3087             # in Chapter 15: Smart Matching and given-when
3088             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
3089              
3090             # P.133 The given Statement
3091             # in Chapter 4: Statements and Declarations
3092             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
3093              
3094             elsif (/\G ( (?: if | elsif | unless | while | until | given | when ) (?>\s*) \( ) /oxgc) {
3095 1373         1817 $slash = 'm//';
3096 1373         4367 return $1;
3097             }
3098              
3099             # scalar variable ($scalar = ...) =~ tr///;
3100             # scalar variable ($scalar = ...) =~ s///;
3101              
3102             # state
3103              
3104             # P.68 Persistent, Private Variables
3105             # in Chapter 4: Subroutines
3106             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
3107              
3108             # P.160 Persistent Lexically Scoped Variables: state
3109             # in Chapter 4: Statements and Declarations
3110             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
3111              
3112             # (and so on)
3113              
3114             elsif (/\G ( \( (?>\s*) (?: local \b | my \b | our \b | state \b )? (?>\s*) \$ $qq_scalar ) /oxgc) {
3115 85         205 my $e_string = e_string($1);
3116              
3117 85 50       2247 if (/\G ( (?>\s*) = $qq_paren \) ) ( (?>\s*) (?: =~ | !~ ) (?>\s*) ) (?= (?: tr | y ) \b ) /oxgc) {
    50          
3118 0         0 $tr_variable = $e_string . e_string($1);
3119 0         0 $bind_operator = $2;
3120 0         0 $slash = 'm//';
3121 0         0 return '';
3122             }
3123             elsif (/\G ( (?>\s*) = $qq_paren \) ) ( (?>\s*) (?: =~ | !~ ) (?>\s*) ) (?= s \b ) /oxgc) {
3124 0         0 $sub_variable = $e_string . e_string($1);
3125 0         0 $bind_operator = $2;
3126 0         0 $slash = 'm//';
3127 0         0 return '';
3128             }
3129             else {
3130 85         133 $slash = 'div';
3131 85         455 return $e_string;
3132             }
3133             }
3134              
3135             # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Ekoi8r::PREMATCH()
3136             elsif (/\G ( \$` | \$\{`\} | \$ (?>\s*) PREMATCH \b | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} ) /oxmsgc) {
3137 4         9 $slash = 'div';
3138 4         16 return q{Ekoi8r::PREMATCH()};
3139             }
3140              
3141             # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Ekoi8r::MATCH()
3142             elsif (/\G ( \$& | \$\{&\} | \$ (?>\s*) MATCH \b | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} ) /oxmsgc) {
3143 28         55 $slash = 'div';
3144 28         83 return q{Ekoi8r::MATCH()};
3145             }
3146              
3147             # $', ${'} --> $', ${'}
3148             elsif (/\G ( \$' | \$\{'\} ) /oxmsgc) {
3149 1         1 $slash = 'div';
3150 1         3 return $1;
3151             }
3152              
3153             # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Ekoi8r::POSTMATCH()
3154             elsif (/\G ( \$ (?>\s*) POSTMATCH \b | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} ) /oxmsgc) {
3155 3         7 $slash = 'div';
3156 3         14 return q{Ekoi8r::POSTMATCH()};
3157             }
3158              
3159             # scalar variable $scalar =~ tr///;
3160             # scalar variable $scalar =~ s///;
3161             # substr() =~ tr///;
3162             # substr() =~ s///;
3163             elsif (/\G ( \$ $qq_scalar | $qq_substr ) /oxgc) {
3164 1604         3326 my $scalar = e_string($1);
3165              
3166 1604 100       6951 if (/\G ( (?>\s*) (?: =~ | !~ ) (?>\s*) ) (?= (?: tr | y ) \b ) /oxgc) {
    100          
3167 1         2 $tr_variable = $scalar;
3168 1         2 $bind_operator = $1;
3169 1         2 $slash = 'm//';
3170 1         3 return '';
3171             }
3172             elsif (/\G ( (?>\s*) (?: =~ | !~ ) (?>\s*) ) (?= s \b ) /oxgc) {
3173 61         131 $sub_variable = $scalar;
3174 61         104 $bind_operator = $1;
3175 61         87 $slash = 'm//';
3176 61         188 return '';
3177             }
3178             else {
3179 1542         1737 $slash = 'div';
3180 1542         4635 return $scalar;
3181             }
3182             }
3183              
3184             # end of statement
3185             elsif (/\G ( [,;] ) /oxgc) {
3186 4558         5150 $slash = 'm//';
3187              
3188             # clear tr/// variable
3189 4558         4265 $tr_variable = '';
3190              
3191             # clear s/// variable
3192 4558         3820 $sub_variable = '';
3193              
3194 4558         3818 $bind_operator = '';
3195              
3196 4558         16222 return $1;
3197             }
3198              
3199             # bareword
3200             elsif (/\G ( \{ (?>\s*) (?: tr | index | rindex | reverse ) (?>\s*) \} ) /oxmsgc) {
3201 0         0 return $1;
3202             }
3203              
3204             # $0 --> $0
3205             elsif (/\G ( \$ 0 ) /oxmsgc) {
3206 2         7 $slash = 'div';
3207 2         10 return $1;
3208             }
3209             elsif (/\G ( \$ \{ (?>\s*) 0 (?>\s*) \} ) /oxmsgc) {
3210 0         0 $slash = 'div';
3211 0         0 return $1;
3212             }
3213              
3214             # $$ --> $$
3215             elsif (/\G ( \$ \$ ) (?![\w\{]) /oxmsgc) {
3216 1         2 $slash = 'div';
3217 1         3 return $1;
3218             }
3219              
3220             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
3221             # $1, $2, $3 --> $1, $2, $3 otherwise
3222             elsif (/\G \$ ((?>[1-9][0-9]*)) /oxmsgc) {
3223 4         6 $slash = 'div';
3224 4         10 return e_capture($1);
3225             }
3226             elsif (/\G \$ \{ (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} /oxmsgc) {
3227 0         0 $slash = 'div';
3228 0         0 return e_capture($1);
3229             }
3230              
3231             # $$foo[ ... ] --> $ $foo->[ ... ]
3232             elsif (/\G \$ ( \$ (?> [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \[ .+? \] ) /oxmsgc) {
3233 0         0 $slash = 'div';
3234 0         0 return e_capture($1.'->'.$2);
3235             }
3236              
3237             # $$foo{ ... } --> $ $foo->{ ... }
3238             elsif (/\G \$ ( \$ (?> [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \{ .+? \} ) /oxmsgc) {
3239 0         0 $slash = 'div';
3240 0         0 return e_capture($1.'->'.$2);
3241             }
3242              
3243             # $$foo
3244             elsif (/\G \$ ( \$ (?> [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) /oxmsgc) {
3245 0         0 $slash = 'div';
3246 0         0 return e_capture($1);
3247             }
3248              
3249             # ${ foo }
3250             elsif (/\G \$ (?>\s*) \{ ( (?>\s*) (?> [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) (?>\s*) ) \} /oxmsgc) {
3251 0         0 $slash = 'div';
3252 0         0 return '${' . $1 . '}';
3253             }
3254              
3255             # ${ ... }
3256             elsif (/\G \$ (?>\s*) \{ (?>\s*) ( $qq_brace ) (?>\s*) \} /oxmsgc) {
3257 0         0 $slash = 'div';
3258 0         0 return e_capture($1);
3259             }
3260              
3261             # variable or function
3262             # $ @ % & * $ #
3263             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) {
3264 42         58 $slash = 'div';
3265 42         147 return $1;
3266             }
3267             # $ $ $ $ $ $ $ $ $ $ $ $ $ $
3268             # $ @ # \ ' " / ? ( ) [ ] < >
3269             elsif (/\G ( \$[\$\@\#\\\'\"\/\?\(\)\[\]\<\>] ) /oxmsgc) {
3270 60         115 $slash = 'div';
3271 60         277 return $1;
3272             }
3273              
3274             # while ()
3275             elsif (/\G \b (while (?>\s*) \( (?>\s*) <[\$]?[A-Za-z_][A-Za-z_0-9]*> (?>\s*) \)) \b /oxgc) {
3276 0         0 return $1;
3277             }
3278              
3279             # while () --- glob
3280              
3281             # avoid "Error: Runtime exception" of perl version 5.005_03
3282              
3283             elsif (/\G \b while (?>\s*) \( (?>\s*) < ((?:[^>\0\a\e\f\n\r\t])+?) > (?>\s*) \) \b /oxgc) {
3284 0         0 return 'while ($_ = Ekoi8r::glob("' . $1 . '"))';
3285             }
3286              
3287             # while (glob)
3288             elsif (/\G \b while (?>\s*) \( (?>\s*) glob (?>\s*) \) /oxgc) {
3289 0         0 return 'while ($_ = Ekoi8r::glob_)';
3290             }
3291              
3292             # while (glob(WILDCARD))
3293             elsif (/\G \b while (?>\s*) \( (?>\s*) glob \b /oxgc) {
3294 0         0 return 'while ($_ = Ekoi8r::glob';
3295             }
3296              
3297             # doit if, doit unless, doit while, doit until, doit for, doit when
3298 241         494 elsif (/\G \b ( if | unless | while | until | for | when ) \b /oxgc) { $slash = 'm//'; return $1; }
  241         974  
3299              
3300             # subroutines of package Ekoi8r
3301 19         39 elsif (/\G \b (CORE:: | ->(>?\s*) (?: atan2 | [a-z]{2,})) \b /oxgc) { $slash = 'm//'; return $1; }
  19         80  
3302 0         0 elsif (/\G \b Char::eval (?= (?>\s*) \{ ) /oxgc) { $slash = 'm//'; return 'eval'; }
  0         0  
3303 13         19 elsif (/\G \b KOI8R::eval (?= (?>\s*) \{ ) /oxgc) { $slash = 'm//'; return 'eval'; }
  13         48  
3304 0         0 elsif (/\G \b Char::eval \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'eval Char::escape'; }
  0         0  
3305 114         137 elsif (/\G \b KOI8R::eval \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'eval KOI8R::escape'; }
  114         400  
3306 2         3 elsif (/\G \b bytes::substr \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'substr'; }
  2         7  
3307 0         0 elsif (/\G \b chop \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Ekoi8r::chop'; }
  0         0  
3308 2         2 elsif (/\G \b bytes::index \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'index'; }
  2         5  
3309 0         0 elsif (/\G \b Char::index \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Char::index'; }
  0         0  
3310 0         0 elsif (/\G \b KOI8R::index \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'KOI8R::index'; }
  0         0  
3311 0         0 elsif (/\G \b index \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Ekoi8r::index'; }
  0         0  
3312 2         3 elsif (/\G \b bytes::rindex \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'rindex'; }
  2         6  
3313 0         0 elsif (/\G \b Char::rindex \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Char::rindex'; }
  0         0  
3314 0         0 elsif (/\G \b KOI8R::rindex \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'KOI8R::rindex'; }
  0         0  
3315 0         0 elsif (/\G \b rindex \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Ekoi8r::rindex'; }
  0         0  
3316 1         3 elsif (/\G \b lc (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Ekoi8r::lc'; }
  1         4  
3317 0         0 elsif (/\G \b lcfirst (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Ekoi8r::lcfirst'; }
  0         0  
3318 1         4 elsif (/\G \b uc (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Ekoi8r::uc'; }
  1         7  
3319 0         0 elsif (/\G \b ucfirst (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Ekoi8r::ucfirst'; }
  0         0  
3320 6         7 elsif (/\G \b fc (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Ekoi8r::fc'; }
  6         29  
3321              
3322             # "-s '' ..." means file test "-s 'filename' ..." (not means "- s/// ...")
3323 0         0 elsif (/\G -s (?>\s*) (\") ((?:$qq_char)+?) (\") /oxgc) { $slash = 'm//'; return '-s ' . e_qq('', $1,$3,$2); }
  0         0  
3324 0         0 elsif (/\G -s (?>\s+) qq (?>\s*) (\#) ((?:$qq_char)+?) (\#) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0         0  
3325 0         0 elsif (/\G -s (?>\s+) qq (?>\s*) (\() ((?:$qq_paren)+?) (\)) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0         0  
3326 0         0 elsif (/\G -s (?>\s+) qq (?>\s*) (\{) ((?:$qq_brace)+?) (\}) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0         0  
3327 0         0 elsif (/\G -s (?>\s+) qq (?>\s*) (\[) ((?:$qq_bracket)+?) (\]) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0         0  
3328 0         0 elsif (/\G -s (?>\s+) qq (?>\s*) (\<) ((?:$qq_angle)+?) (\>) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0         0  
3329 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  
3330              
3331 0         0 elsif (/\G -s (?>\s*) (\') ((?:\\\'|\\\\|$q_char)+?) (\') /oxgc) { $slash = 'm//'; return '-s ' . e_q ('', $1,$3,$2); }
  0         0  
3332 0         0 elsif (/\G -s (?>\s+) q (?>\s*) (\#) ((?:\\\#|\\\\|$q_char)+?) (\#) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0         0  
3333 0         0 elsif (/\G -s (?>\s+) q (?>\s*) (\() ((?:\\\)|\\\\|$q_paren)+?) (\)) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0         0  
3334 0         0 elsif (/\G -s (?>\s+) q (?>\s*) (\{) ((?:\\\}|\\\\|$q_brace)+?) (\}) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0         0  
3335 0         0 elsif (/\G -s (?>\s+) q (?>\s*) (\[) ((?:\\\]|\\\\|$q_bracket)+?) (\]) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0         0  
3336 0         0 elsif (/\G -s (?>\s+) q (?>\s*) (\<) ((?:\\\>|\\\\|$q_angle)+?) (\>) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0         0  
3337 0         0 elsif (/\G -s (?>\s+) q (?>\s*) (\S) ((?:\\\1|\\\\|$q_char)+?) (\1) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0         0  
3338              
3339             elsif (/\G -s (?>\s*) (\$ (?> \w+ (?: ::\w+)* ) (?: (?: ->)? (?: [\$\@\%\&\*]\* | \$\#\* | \( (?:$qq_paren)*? \) | [\@\%\*]? \{ (?:$qq_brace)+? \} | [\@\%]? \[ (?:$qq_bracket)+? \] ) )*) /oxgc)
3340 0         0 { $slash = 'm//'; return "-s $1"; }
  0         0  
3341 0         0 elsif (/\G -s (?>\s*) \( ((?:$qq_paren)*?) \) /oxgc) { $slash = 'm//'; return "-s ($1)"; }
  0         0  
3342 0         0 elsif (/\G -s (?= (?>\s+) [a-z]+) /oxgc) { $slash = 'm//'; return '-s'; }
  0         0  
3343 0         0 elsif (/\G -s (?>\s+) ((?>\w+)) /oxgc) { $slash = 'm//'; return "-s $1"; }
  0         0  
3344              
3345 2         3 elsif (/\G \b bytes::length (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'length'; }
  2         6  
3346 2         2 elsif (/\G \b bytes::chr (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'chr'; }
  2         6  
3347 36         49 elsif (/\G \b chr (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Ekoi8r::chr'; }
  36         123  
3348 2         4 elsif (/\G \b bytes::ord (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'div'; return 'ord'; }
  2         6  
3349 8         13 elsif (/\G \b ord (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'div'; return $function_ord; }
  8         27  
3350 0         0 elsif (/\G \b glob (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Ekoi8r::glob'; }
  0         0  
3351 0         0 elsif (/\G \b lc \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Ekoi8r::lc_'; }
  0         0  
3352 0         0 elsif (/\G \b lcfirst \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Ekoi8r::lcfirst_'; }
  0         0  
3353 0         0 elsif (/\G \b uc \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Ekoi8r::uc_'; }
  0         0  
3354 0         0 elsif (/\G \b ucfirst \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Ekoi8r::ucfirst_'; }
  0         0  
3355 0         0 elsif (/\G \b fc \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Ekoi8r::fc_'; }
  0         0  
3356 0         0 elsif (/\G -s \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return '-s '; }
  0         0  
3357              
3358 0         0 elsif (/\G \b bytes::length \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'length'; }
  0         0  
3359 0         0 elsif (/\G \b bytes::chr \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'chr'; }
  0         0  
3360 0         0 elsif (/\G \b chr \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Ekoi8r::chr_'; }
  0         0  
3361 0         0 elsif (/\G \b bytes::ord \b (?! (?>\s*) => ) /oxgc) { $slash = 'div'; return 'ord'; }
  0         0  
3362 0         0 elsif (/\G \b ord \b (?! (?>\s*) => ) /oxgc) { $slash = 'div'; return $function_ord_; }
  0         0  
3363 0         0 elsif (/\G \b glob \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Ekoi8r::glob_'; }
  0         0  
3364 0         0 elsif (/\G \b reverse \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return $function_reverse; }
  0         0  
3365 8         19 elsif (/\G \b getc \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return $function_getc; }
  8         39  
3366             # split
3367             elsif (/\G \b (split) \b (?! (?>\s*) => ) /oxgc) {
3368 87         149 $slash = 'm//';
3369              
3370 87         125 my $e = '';
3371 87         371 while (/\G ( (?>\s+) | \( | \#.* ) /oxgc) {
3372 85         342 $e .= $1;
3373             }
3374              
3375             # end of split
3376 87 100       7762 if (/\G (?= [,;\)\}\]] ) /oxgc) { return 'Ekoi8r::split' . $e; }
  2 100       15  
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    100          
    50          
    50          
    100          
    50          
    100          
    50          
    50          
    50          
3377              
3378             # split scalar value
3379 1         5 elsif (/\G ( [\$\@\&\*] $qq_scalar ) /oxgc) { return 'Ekoi8r::split' . $e . e_string($1); }
3380              
3381             # split literal space
3382 0         0 elsif (/\G \b qq (\#) [ ] (\#) /oxgc) { return 'Ekoi8r::split' . $e . qq {qq$1 $2}; }
3383 0         0 elsif (/\G \b qq ((?>\s*)) (\() [ ] (\)) /oxgc) { return 'Ekoi8r::split' . $e . qq{$1qq$2 $3}; }
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*)) (\S) [ ] (\2) /oxgc) { return 'Ekoi8r::split' . $e . qq{$1qq$2 $3}; }
3388 0         0 elsif (/\G \b q (\#) [ ] (\#) /oxgc) { return 'Ekoi8r::split' . $e . qq {q$1 $2}; }
3389 0         0 elsif (/\G \b q ((?>\s*)) (\() [ ] (\)) /oxgc) { return 'Ekoi8r::split' . $e . qq {$1q$2 $3}; }
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*)) (\S) [ ] (\2) /oxgc) { return 'Ekoi8r::split' . $e . qq {$1q$2 $3}; }
3394 10         64 elsif (/\G ' [ ] ' /oxgc) { return 'Ekoi8r::split' . $e . qq {' '}; }
3395 0         0 elsif (/\G " [ ] " /oxgc) { return 'Ekoi8r::split' . $e . qq {" "}; }
3396              
3397             # split qq//
3398             elsif (/\G \b (qq) \b /oxgc) {
3399 0 0       0 if (/\G (\#) ((?:$qq_char)*?) (\#) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq# # --> qr # #
  0         0  
3400             else {
3401 0         0 while (not /\G \z/oxgc) {
3402 0 0       0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0       0  
    0          
    0          
    0          
    0          
    0          
3403 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq ( ) --> qr ( )
3404 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq { } --> qr { }
3405 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq [ ] --> qr [ ]
3406 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq < > --> qr < >
3407 0         0 elsif (/\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) /oxgc) { return e_split($e.'qr','{','}',$2,''); } # qq | | --> qr { }
3408 0         0 elsif (/\G (\S) ((?:$qq_char)*?) (\1) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq * * --> qr * *
3409             }
3410 0         0 die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3411             }
3412             }
3413              
3414             # split qr//
3415             elsif (/\G \b (qr) \b /oxgc) {
3416 12 50       546 if (/\G (\#) ((?:$qq_char)*?) (\#) ([imosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1,$3,$2,$4); } # qr# #
  0         0  
3417             else {
3418 12         67 while (not /\G \z/oxgc) {
3419 12 50       3734 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 50       0  
    50          
    50          
    50          
    50          
    50          
    50          
3420 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([imosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # qr ( )
3421 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([imosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # qr { }
3422 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([imosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # qr [ ]
3423 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([imosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # qr < >
3424 0         0 elsif (/\G (\') ((?:$qq_char)*?) (\') ([imosxpadlunbB]*) /oxgc) { return e_split_q($e.'qr',$1, $3, $2,$4); } # qr ' '
3425 0         0 elsif (/\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ([imosxpadlunbB]*) /oxgc) { return e_split ($e.'qr','{','}',$2,$4); } # qr | | --> qr { }
3426 12         70 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([imosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # qr * *
3427             }
3428 0         0 die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3429             }
3430             }
3431              
3432             # split q//
3433             elsif (/\G \b (q) \b /oxgc) {
3434 0 0       0 if (/\G (\#) ((?:\\\#|\\\\|$q_char)*?) (\#) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q# # --> qr # #
  0         0  
3435             else {
3436 0         0 while (not /\G \z/oxgc) {
3437 0 0       0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0       0  
    0          
    0          
    0          
    0          
    0          
3438 0         0 elsif (/\G (\() ((?:\\\\|\\\)|\\\(|$q_paren)*?) (\)) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q ( ) --> qr ( )
3439 0         0 elsif (/\G (\{) ((?:\\\\|\\\}|\\\{|$q_brace)*?) (\}) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q { } --> qr { }
3440 0         0 elsif (/\G (\[) ((?:\\\\|\\\]|\\\[|$q_bracket)*?) (\]) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q [ ] --> qr [ ]
3441 0         0 elsif (/\G (\<) ((?:\\\\|\\\>|\\\<|$q_angle)*?) (\>) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q < > --> qr < >
3442 0         0 elsif (/\G ([*\-:?\\^|]) ((?:$q_char)*?) (\1) /oxgc) { return e_split_q($e.'qr','{','}',$2,''); } # q | | --> qr { }
3443 0         0 elsif (/\G (\S) ((?:\\\\|\\\1| $q_char)*?) (\1) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q * * --> qr * *
3444             }
3445 0         0 die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3446             }
3447             }
3448              
3449             # split m//
3450             elsif (/\G \b (m) \b /oxgc) {
3451 18 50       543 if (/\G (\#) ((?:$qq_char)*?) (\#) ([cgimosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1,$3,$2,$4); } # m# # --> qr # #
  0         0  
3452             else {
3453 18         72 while (not /\G \z/oxgc) {
3454 18 50       4152 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 50       0  
    50          
    50          
    50          
    50          
    50          
    50          
3455 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cgimosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # m ( ) --> qr ( )
3456 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cgimosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # m { } --> qr { }
3457 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cgimosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # m [ ] --> qr [ ]
3458 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cgimosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # m < > --> qr < >
3459 0         0 elsif (/\G (\') ((?:$qq_char)*?) (\') ([cgimosxpadlunbB]*) /oxgc) { return e_split_q($e.'qr',$1, $3, $2,$4); } # m ' ' --> qr ' '
3460 0         0 elsif (/\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ([cgimosxpadlunbB]*) /oxgc) { return e_split ($e.'qr','{','}',$2,$4); } # m | | --> qr { }
3461 18         95 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cgimosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # m * * --> qr * *
3462             }
3463 0         0 die __FILE__, ": Search pattern not terminated\n";
3464             }
3465             }
3466              
3467             # split ''
3468             elsif (/\G (\') /oxgc) {
3469 0         0 my $q_string = '';
3470 0         0 while (not /\G \z/oxgc) {
3471 0 0       0 if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0       0  
    0          
    0          
3472 0         0 elsif (/\G (\\\') /oxgc) { $q_string .= $1; } # splitqr'' --> split qr''
3473 0         0 elsif (/\G \' /oxgc) { return e_split_q($e.q{ qr},"'","'",$q_string,''); } # ' ' --> qr ' '
3474 0         0 elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3475             }
3476 0         0 die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3477             }
3478              
3479             # split ""
3480             elsif (/\G (\") /oxgc) {
3481 0         0 my $qq_string = '';
3482 0         0 while (not /\G \z/oxgc) {
3483 0 0       0 if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0       0  
    0          
    0          
3484 0         0 elsif (/\G (\\\") /oxgc) { $qq_string .= $1; } # splitqr"" --> split qr""
3485 0         0 elsif (/\G \" /oxgc) { return e_split($e.q{ qr},'"','"',$qq_string,''); } # " " --> qr " "
3486 0         0 elsif (/\G ($q_char) /oxgc) { $qq_string .= $1; }
3487             }
3488 0         0 die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3489             }
3490              
3491             # split //
3492             elsif (/\G (\/) /oxgc) {
3493 44         81 my $regexp = '';
3494 44         157 while (not /\G \z/oxgc) {
3495 381 50       1575 if (/\G (\\\\) /oxgc) { $regexp .= $1; }
  0 50       0  
    100          
    50          
3496 0         0 elsif (/\G (\\\/) /oxgc) { $regexp .= $1; } # splitqr// --> split qr//
3497 44         209 elsif (/\G \/ ([cgimosxpadlunbB]*) /oxgc) { return e_split($e.q{ qr}, '/','/',$regexp,$1); } # / / --> qr / /
3498 337         673 elsif (/\G ($q_char) /oxgc) { $regexp .= $1; }
3499             }
3500 0         0 die __FILE__, ": Search pattern not terminated\n";
3501             }
3502             }
3503              
3504             # tr/// or y///
3505              
3506             # about [cdsrbB]* (/B modifier)
3507             #
3508             # P.559 appendix C
3509             # of ISBN 4-89052-384-7 Programming perl
3510             # (Japanese title is: Perl puroguramingu)
3511              
3512             elsif (/\G \b ( tr | y ) \b /oxgc) {
3513 3         5 my $ope = $1;
3514              
3515             # $1 $2 $3 $4 $5 $6
3516 3 50       39 if (/\G (\#) ((?:$qq_char)*?) (\#) ((?:$qq_char)*?) (\#) ([cdsrbB]*) /oxgc) { # tr# # #
3517 0         0 my @tr = ($tr_variable,$2);
3518 0         0 return e_tr(@tr,'',$4,$6);
3519             }
3520             else {
3521 3         4 my $e = '';
3522 3         6 while (not /\G \z/oxgc) {
3523 3 50       217 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 50       0  
    50          
    50          
    50          
    50          
3524             elsif (/\G (\() ((?:$qq_paren)*?) (\)) /oxgc) {
3525 0         0 my @tr = ($tr_variable,$2);
3526 0         0 while (not /\G \z/oxgc) {
3527 0 0       0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0       0  
    0          
    0          
    0          
    0          
3528 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr ( ) ( )
3529 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr ( ) { }
3530 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr ( ) [ ]
3531 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr ( ) < >
3532 0         0 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr ( ) * *
3533             }
3534 0         0 die __FILE__, ": Transliteration replacement not terminated\n";
3535             }
3536             elsif (/\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) {
3537 0         0 my @tr = ($tr_variable,$2);
3538 0         0 while (not /\G \z/oxgc) {
3539 0 0       0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0       0  
    0          
    0          
    0          
    0          
3540 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr { } ( )
3541 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr { } { }
3542 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr { } [ ]
3543 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr { } < >
3544 0         0 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr { } * *
3545             }
3546 0         0 die __FILE__, ": Transliteration replacement not terminated\n";
3547             }
3548             elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) {
3549 0         0 my @tr = ($tr_variable,$2);
3550 0         0 while (not /\G \z/oxgc) {
3551 0 0       0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0       0  
    0          
    0          
    0          
    0          
3552 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr [ ] ( )
3553 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr [ ] { }
3554 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr [ ] [ ]
3555 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr [ ] < >
3556 0         0 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr [ ] * *
3557             }
3558 0         0 die __FILE__, ": Transliteration replacement not terminated\n";
3559             }
3560             elsif (/\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) {
3561 0         0 my @tr = ($tr_variable,$2);
3562 0         0 while (not /\G \z/oxgc) {
3563 0 0       0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0       0  
    0          
    0          
    0          
    0          
3564 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr < > ( )
3565 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr < > { }
3566 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr < > [ ]
3567 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr < > < >
3568 0         0 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr < > * *
3569             }
3570 0         0 die __FILE__, ": Transliteration replacement not terminated\n";
3571             }
3572             # $1 $2 $3 $4 $5 $6
3573             elsif (/\G (\S) ((?:$qq_char)*?) (\1) ((?:$qq_char)*?) (\1) ([cdsrbB]*) /oxgc) { # tr * * *
3574 3         8 my @tr = ($tr_variable,$2);
3575 3         9 return e_tr(@tr,'',$4,$6);
3576             }
3577             }
3578 0         0 die __FILE__, ": Transliteration pattern not terminated\n";
3579             }
3580             }
3581              
3582             # qq//
3583             elsif (/\G \b (qq) \b /oxgc) {
3584 2130         4045 my $ope = $1;
3585              
3586             # if (/\G (\#) ((?:$qq_char)*?) (\#) /oxgc) { return e_qq($ope,$1,$3,$2); } # qq# #
3587 2130 50       3558 if (/\G (\#) /oxgc) { # qq# #
3588 0         0 my $qq_string = '';
3589 0         0 while (not /\G \z/oxgc) {
3590 0 0       0 if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0       0  
    0          
    0          
3591 0         0 elsif (/\G (\\\#) /oxgc) { $qq_string .= $1; }
3592 0         0 elsif (/\G (\#) /oxgc) { return e_qq($ope,'#','#',$qq_string); }
3593 0         0 elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3594             }
3595 0         0 die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3596             }
3597              
3598             else {
3599 2130         2278 my $e = '';
3600 2130         5122 while (not /\G \z/oxgc) {
3601 2130 50       8511 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 50       0  
    100          
    50          
    50          
    0          
3602              
3603             # elsif (/\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qq ( )
3604             elsif (/\G (\() /oxgc) { # qq ( )
3605 0         0 my $qq_string = '';
3606 0         0 local $nest = 1;
3607 0         0 while (not /\G \z/oxgc) {
3608 0 0       0 if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0       0  
    0          
    0          
    0          
3609 0         0 elsif (/\G (\\\)) /oxgc) { $qq_string .= $1; }
3610 0         0 elsif (/\G (\() /oxgc) { $qq_string .= $1; $nest++; }
  0         0  
3611             elsif (/\G (\)) /oxgc) {
3612 0 0       0 if (--$nest == 0) { return $e . e_qq($ope,'(',')',$qq_string); }
  0         0  
3613 0         0 else { $qq_string .= $1; }
3614             }
3615 0         0 elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3616             }
3617 0         0 die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3618             }
3619              
3620             # elsif (/\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qq { }
3621             elsif (/\G (\{) /oxgc) { # qq { }
3622 2100         2024 my $qq_string = '';
3623 2100         2567 local $nest = 1;
3624 2100         4383 while (not /\G \z/oxgc) {
3625 82631 100       283355 if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  722 50       1510  
    100          
    100          
    50          
3626 0         0 elsif (/\G (\\\}) /oxgc) { $qq_string .= $1; }
3627 1103         1238 elsif (/\G (\{) /oxgc) { $qq_string .= $1; $nest++; }
  1103         2129  
3628             elsif (/\G (\}) /oxgc) {
3629 3203 100       4303 if (--$nest == 0) { return $e . e_qq($ope,'{','}',$qq_string); }
  2100         4245  
3630 1103         2396 else { $qq_string .= $1; }
3631             }
3632 77603         155722 elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3633             }
3634 0         0 die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3635             }
3636              
3637             # elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qq [ ]
3638             elsif (/\G (\[) /oxgc) { # qq [ ]
3639 0         0 my $qq_string = '';
3640 0         0 local $nest = 1;
3641 0         0 while (not /\G \z/oxgc) {
3642 0 0       0 if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0       0  
    0          
    0          
    0          
3643 0         0 elsif (/\G (\\\]) /oxgc) { $qq_string .= $1; }
3644 0         0 elsif (/\G (\[) /oxgc) { $qq_string .= $1; $nest++; }
  0         0  
3645             elsif (/\G (\]) /oxgc) {
3646 0 0       0 if (--$nest == 0) { return $e . e_qq($ope,'[',']',$qq_string); }
  0         0  
3647 0         0 else { $qq_string .= $1; }
3648             }
3649 0         0 elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3650             }
3651 0         0 die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3652             }
3653              
3654             # elsif (/\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qq < >
3655             elsif (/\G (\<) /oxgc) { # qq < >
3656 30         85 my $qq_string = '';
3657 30         55 local $nest = 1;
3658 30         106 while (not /\G \z/oxgc) {
3659 1166 100       4806 if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  22 50       66  
    50          
    100          
    50          
3660 0         0 elsif (/\G (\\\>) /oxgc) { $qq_string .= $1; }
3661 0         0 elsif (/\G (\<) /oxgc) { $qq_string .= $1; $nest++; }
  0         0  
3662             elsif (/\G (\>) /oxgc) {
3663 30 50       74 if (--$nest == 0) { return $e . e_qq($ope,'<','>',$qq_string); }
  30         78  
3664 0         0 else { $qq_string .= $1; }
3665             }
3666 1114         2345 elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3667             }
3668 0         0 die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3669             }
3670              
3671             # elsif (/\G (\S) ((?:$qq_char)*?) (\1) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qq * *
3672             elsif (/\G (\S) /oxgc) { # qq * *
3673 0         0 my $delimiter = $1;
3674 0         0 my $qq_string = '';
3675 0         0 while (not /\G \z/oxgc) {
3676 0 0       0 if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0       0  
    0          
    0          
3677 0         0 elsif (/\G (\\\Q$delimiter\E) /oxgc) { $qq_string .= $1; }
3678 0         0 elsif (/\G (\Q$delimiter\E) /oxgc) { return $e . e_qq($ope,$delimiter,$delimiter,$qq_string); }
3679 0         0 elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3680             }
3681 0         0 die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3682             }
3683             }
3684 0         0 die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3685             }
3686             }
3687              
3688             # qr//
3689             elsif (/\G \b (qr) \b /oxgc) {
3690 0         0 my $ope = $1;
3691 0 0       0 if (/\G (\#) ((?:$qq_char)*?) (\#) ([imosxpadlunbB]*) /oxgc) { # qr# # #
3692 0         0 return e_qr($ope,$1,$3,$2,$4);
3693             }
3694             else {
3695 0         0 my $e = '';
3696 0         0 while (not /\G \z/oxgc) {
3697 0 0       0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0       0  
    0          
    0          
    0          
    0          
    0          
    0          
3698 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([imosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # qr ( )
3699 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([imosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # qr { }
3700 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([imosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # qr [ ]
3701 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([imosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # qr < >
3702 0         0 elsif (/\G (\') ((?:$qq_char)*?) (\') ([imosxpadlunbB]*) /oxgc) { return $e . e_qr_q($ope,$1, $3, $2,$4); } # qr ' '
3703 0         0 elsif (/\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ([imosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,'{','}',$2,$4); } # qr | | --> qr { }
3704 0         0 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([imosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # qr * *
3705             }
3706 0         0 die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3707             }
3708             }
3709              
3710             # qw//
3711             elsif (/\G \b (qw) \b /oxgc) {
3712 16         50 my $ope = $1;
3713 16 50       93 if (/\G (\#) (.*?) (\#) /oxmsgc) { # qw# #
3714 0         0 return e_qw($ope,$1,$3,$2);
3715             }
3716             else {
3717 16         26 my $e = '';
3718 16         56 while (not /\G \z/oxgc) {
3719 16 50       131 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 50       0  
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
3720              
3721 16         74 elsif (/\G (\() ([^(]*?) (\)) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw ( )
3722 0         0 elsif (/\G (\() ((?:$q_paren)*?) (\)) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw ( )
3723              
3724 0         0 elsif (/\G (\{) ([^{]*?) (\}) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw { }
3725 0         0 elsif (/\G (\{) ((?:$q_brace)*?) (\}) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw { }
3726              
3727 0         0 elsif (/\G (\[) ([^[]*?) (\]) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw [ ]
3728 0         0 elsif (/\G (\[) ((?:$q_bracket)*?) (\]) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw [ ]
3729              
3730 0         0 elsif (/\G (\<) ([^<]*?) (\>) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw < >
3731 0         0 elsif (/\G (\<) ((?:$q_angle)*?) (\>) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw < >
3732              
3733 0         0 elsif (/\G ([\x21-\x3F]) (.*?) (\1) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw * *
3734 0         0 elsif (/\G (\S) ((?:$q_char)*?) (\1) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw * *
3735             }
3736 0         0 die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3737             }
3738             }
3739              
3740             # qx//
3741             elsif (/\G \b (qx) \b /oxgc) {
3742 0         0 my $ope = $1;
3743 0 0       0 if (/\G (\#) ((?:$qq_char)*?) (\#) /oxgc) { # qx# #
3744 0         0 return e_qq($ope,$1,$3,$2);
3745             }
3746             else {
3747 0         0 my $e = '';
3748 0         0 while (not /\G \z/oxgc) {
3749 0 0       0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0       0  
    0          
    0          
    0          
    0          
    0          
3750 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qx ( )
3751 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qx { }
3752 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qx [ ]
3753 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qx < >
3754 0         0 elsif (/\G (\') ((?:$qq_char)*?) (\') /oxgc) { return $e . e_q ($ope,$1,$3,$2); } # qx ' '
3755 0         0 elsif (/\G (\S) ((?:$qq_char)*?) (\1) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qx * *
3756             }
3757 0         0 die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3758             }
3759             }
3760              
3761             # q//
3762             elsif (/\G \b (q) \b /oxgc) {
3763 245         727 my $ope = $1;
3764              
3765             # if (/\G (\#) ((?:\\\#|\\\\|$q_char)*?) (\#) /oxgc) { return e_q($ope,$1,$3,$2); } # q# #
3766              
3767             # avoid "Error: Runtime exception" of perl version 5.005_03
3768             # (and so on)
3769              
3770 245 50       818 if (/\G (\#) /oxgc) { # q# #
3771 0         0 my $q_string = '';
3772 0         0 while (not /\G \z/oxgc) {
3773 0 0       0 if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0       0  
    0          
    0          
3774 0         0 elsif (/\G (\\\#) /oxgc) { $q_string .= $1; }
3775 0         0 elsif (/\G (\#) /oxgc) { return e_q($ope,'#','#',$q_string); }
3776 0         0 elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3777             }
3778 0         0 die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3779             }
3780              
3781             else {
3782 245         453 my $e = '';
3783 245         975 while (not /\G \z/oxgc) {
3784 245 50       1960 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 50       0  
    100          
    50          
    100          
    50          
3785              
3786             # elsif (/\G (\() ((?:\\\)|\\\\|$q_paren)*?) (\)) /oxgc) { return $e . e_q($ope,$1,$3,$2); } # q ( )
3787             elsif (/\G (\() /oxgc) { # q ( )
3788 0         0 my $q_string = '';
3789 0         0 local $nest = 1;
3790 0         0 while (not /\G \z/oxgc) {
3791 0 0       0 if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0       0  
    0          
    0          
    0          
    0          
3792 0         0 elsif (/\G (\\\)) /oxgc) { $q_string .= $1; }
3793 0         0 elsif (/\G (\\\() /oxgc) { $q_string .= $1; }
3794 0         0 elsif (/\G (\() /oxgc) { $q_string .= $1; $nest++; }
  0         0  
3795             elsif (/\G (\)) /oxgc) {
3796 0 0       0 if (--$nest == 0) { return $e . e_q($ope,'(',')',$q_string); }
  0         0  
3797 0         0 else { $q_string .= $1; }
3798             }
3799 0         0 elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3800             }
3801 0         0 die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3802             }
3803              
3804             # elsif (/\G (\{) ((?:\\\}|\\\\|$q_brace)*?) (\}) /oxgc) { return $e . e_q($ope,$1,$3,$2); } # q { }
3805             elsif (/\G (\{) /oxgc) { # q { }
3806 239         419 my $q_string = '';
3807 239         471 local $nest = 1;
3808 239         906 while (not /\G \z/oxgc) {
3809 3624 50       20065 if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 50       0  
    50          
    100          
    100          
    50          
3810 0         0 elsif (/\G (\\\}) /oxgc) { $q_string .= $1; }
3811 0         0 elsif (/\G (\\\{) /oxgc) { $q_string .= $1; }
3812 107         172 elsif (/\G (\{) /oxgc) { $q_string .= $1; $nest++; }
  107         283  
3813             elsif (/\G (\}) /oxgc) {
3814 346 100       794 if (--$nest == 0) { return $e . e_q($ope,'{','}',$q_string); }
  239         919  
3815 107         291 else { $q_string .= $1; }
3816             }
3817 3171         7858 elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3818             }
3819 0         0 die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3820             }
3821              
3822             # elsif (/\G (\[) ((?:\\\]|\\\\|$q_bracket)*?) (\]) /oxgc) { return $e . e_q($ope,$1,$3,$2); } # q [ ]
3823             elsif (/\G (\[) /oxgc) { # q [ ]
3824 0         0 my $q_string = '';
3825 0         0 local $nest = 1;
3826 0         0 while (not /\G \z/oxgc) {
3827 0 0       0 if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0       0  
    0          
    0          
    0          
    0          
3828 0         0 elsif (/\G (\\\]) /oxgc) { $q_string .= $1; }
3829 0         0 elsif (/\G (\\\[) /oxgc) { $q_string .= $1; }
3830 0         0 elsif (/\G (\[) /oxgc) { $q_string .= $1; $nest++; }
  0         0  
3831             elsif (/\G (\]) /oxgc) {
3832 0 0       0 if (--$nest == 0) { return $e . e_q($ope,'[',']',$q_string); }
  0         0  
3833 0         0 else { $q_string .= $1; }
3834             }
3835 0         0 elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3836             }
3837 0         0 die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3838             }
3839              
3840             # elsif (/\G (\<) ((?:\\\>|\\\\|$q_angle)*?) (\>) /oxgc) { return $e . e_q($ope,$1,$3,$2); } # q < >
3841             elsif (/\G (\<) /oxgc) { # q < >
3842 5         13 my $q_string = '';
3843 5         9 local $nest = 1;
3844 5         78 while (not /\G \z/oxgc) {
3845 88 50       552 if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 50       0  
    50          
    50          
    100          
    50          
3846 0         0 elsif (/\G (\\\>) /oxgc) { $q_string .= $1; }
3847 0         0 elsif (/\G (\\\<) /oxgc) { $q_string .= $1; }
3848 0         0 elsif (/\G (\<) /oxgc) { $q_string .= $1; $nest++; }
  0         0  
3849             elsif (/\G (\>) /oxgc) {
3850 5 50       23 if (--$nest == 0) { return $e . e_q($ope,'<','>',$q_string); }
  5         27  
3851 0         0 else { $q_string .= $1; }
3852             }
3853 83         484 elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3854             }
3855 0         0 die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3856             }
3857              
3858             # elsif (/\G (\S) ((?:\\\1|\\\\|$q_char)*?) (\1) /oxgc) { return $e . e_q($ope,$1,$3,$2); } # q * *
3859             elsif (/\G (\S) /oxgc) { # q * *
3860 1         4 my $delimiter = $1;
3861 1         3 my $q_string = '';
3862 1         7 while (not /\G \z/oxgc) {
3863 14 50       114 if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 50       0  
    100          
    50          
3864 0         0 elsif (/\G (\\\Q$delimiter\E) /oxgc) { $q_string .= $1; }
3865 1         9 elsif (/\G (\Q$delimiter\E) /oxgc) { return $e . e_q($ope,$delimiter,$delimiter,$q_string); }
3866 13         41 elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3867             }
3868 0         0 die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3869             }
3870             }
3871 0         0 die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3872             }
3873             }
3874              
3875             # m//
3876             elsif (/\G \b (m) \b /oxgc) {
3877 209         452 my $ope = $1;
3878 209 50       2300 if (/\G (\#) ((?:$qq_char)*?) (\#) ([cgimosxpadlunbB]*) /oxgc) { # m# #
3879 0         0 return e_qr($ope,$1,$3,$2,$4);
3880             }
3881             else {
3882 209         281 my $e = '';
3883 209         635 while (not /\G \z/oxgc) {
3884 209 50       14842 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 50       0  
    50          
    50          
    50          
    50          
    100          
    50          
    50          
3885 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cgimosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m ( )
3886 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cgimosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m { }
3887 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cgimosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m [ ]
3888 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cgimosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m < >
3889 0         0 elsif (/\G (\?) ((?:$qq_char)*?) (\?) ([cgimosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m ? ?
3890 10         26 elsif (/\G (\') ((?:$qq_char)*?) (\') ([cgimosxpadlunbB]*) /oxgc) { return $e . e_qr_q($ope,$1, $3, $2,$4); } # m ' '
3891 0         0 elsif (/\G ([*\-:\\^|]) ((?:$qq_char)*?) (\1) ([cgimosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,'{','}',$2,$4); } # m | | --> m { }
3892 199         645 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cgimosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m * *
3893             }
3894 0         0 die __FILE__, ": Search pattern not terminated\n";
3895             }
3896             }
3897              
3898             # s///
3899              
3900             # about [cegimosxpradlunbB]* (/cg modifier)
3901             #
3902             # P.67 Pattern-Matching Operators
3903             # of ISBN 0-596-00241-6 Perl in a Nutshell, Second Edition.
3904              
3905             elsif (/\G \b (s) \b /oxgc) {
3906 97         275 my $ope = $1;
3907              
3908             # $1 $2 $3 $4 $5 $6
3909 97 100       2226 if (/\G (\#) ((?:$qq_char)*?) (\#) ((?:$qq_char)*?) (\#) ([cegimosxpradlunbB]*) /oxgc) { # s# # #
3910 1         6 return e_sub($sub_variable,$1,$2,$3,$3,$4,$5,$6);
3911             }
3912             else {
3913 96         180 my $e = '';
3914 96         358 while (not /\G \z/oxgc) {
3915 96 50       12948 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 50       0  
    50          
    50          
    50          
    100          
    50          
    50          
    50          
3916             elsif (/\G (\() ((?:$qq_paren)*?) (\)) /oxgc) {
3917 0         0 my @s = ($1,$2,$3);
3918 0         0 while (not /\G \z/oxgc) {
3919 0 0       0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0       0  
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
3920             # $1 $2 $3 $4
3921 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3922 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3923 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3924 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3925 0         0 elsif (/\G (\') ((?:$qq_char)*?) (\') ([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 0         0 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3930             }
3931 0         0 die __FILE__, ": Substitution replacement not terminated\n";
3932             }
3933             elsif (/\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) {
3934 0         0 my @s = ($1,$2,$3);
3935 0         0 while (not /\G \z/oxgc) {
3936 0 0       0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0       0  
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
3937             # $1 $2 $3 $4
3938 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3939 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3940 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3941 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3942 0         0 elsif (/\G (\') ((?:$qq_char)*?) (\') ([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 0         0 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3947             }
3948 0         0 die __FILE__, ": Substitution replacement not terminated\n";
3949             }
3950             elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) {
3951 0         0 my @s = ($1,$2,$3);
3952 0         0 while (not /\G \z/oxgc) {
3953 0 0       0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0       0  
    0          
    0          
    0          
    0          
    0          
    0          
3954             # $1 $2 $3 $4
3955 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3956 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3957 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3958 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3959 0         0 elsif (/\G (\') ((?:$qq_char)*?) (\') ([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 0         0 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3962             }
3963 0         0 die __FILE__, ": Substitution replacement not terminated\n";
3964             }
3965             elsif (/\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) {
3966 0         0 my @s = ($1,$2,$3);
3967 0         0 while (not /\G \z/oxgc) {
3968 0 0       0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0       0  
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
3969             # $1 $2 $3 $4
3970 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3971 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3972 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3973 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3974 0         0 elsif (/\G (\') ((?:$qq_char)*?) (\') ([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 0         0 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3979             }
3980 0         0 die __FILE__, ": Substitution replacement not terminated\n";
3981             }
3982             # $1 $2 $3 $4 $5 $6
3983             elsif (/\G (\') ((?:$qq_char)*?) (\') ((?:$qq_char)*?) (\') ([cegimosxpradlunbB]*) /oxgc) {
3984 21         67 return e_sub($sub_variable,$1,$2,$3,$3,$4,$5,$6);
3985             }
3986             # $1 $2 $3 $4 $5 $6
3987             elsif (/\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ((?:$qq_char)*?) (\1) ([cegimosxpradlunbB]*) /oxgc) {
3988 0         0 return e_sub($sub_variable,'{',$2,'}','{',$4,'}',$6); # s | | | --> s { } { }
3989             }
3990             # $1 $2 $3 $4 $5 $6
3991             elsif (/\G (\$) ((?:$qq_char)*?) (\1) ((?:$qq_char)*?) (\1) ([cegimosxpradlunbB]*) /oxgc) {
3992 0         0 return e_sub($sub_variable,$1,$2,$3,$3,$4,$5,$6);
3993             }
3994             # $1 $2 $3 $4 $5 $6
3995             elsif (/\G (\S) ((?:$qq_char)*?) (\1) ((?:$qq_char)*?) (\1) ([cegimosxpradlunbB]*) /oxgc) {
3996 75         341 return e_sub($sub_variable,$1,$2,$3,$3,$4,$5,$6);
3997             }
3998             }
3999 0         0 die __FILE__, ": Substitution pattern not terminated\n";
4000             }
4001             }
4002              
4003             # require ignore module
4004 0         0 elsif (/\G \b require ((?>\s+) (?:$ignore_modules) .*? ;) ([ \t]* [#\n]) /oxmsgc) { return "# require$1$2"; }
4005 0         0 elsif (/\G \b require ((?>\s+) (?:$ignore_modules) .*? ;) ([ \t]* [^#]) /oxmsgc) { return "# require$1\n$2"; }
4006 0         0 elsif (/\G \b require ((?>\s+) (?:$ignore_modules)) \b /oxmsgc) { return "# require$1"; }
4007              
4008             # use strict; --> use strict; no strict qw(refs);
4009 36         425 elsif (/\G \b use ((?>\s+) strict .*? ;) ([ \t]* [#\n]) /oxmsgc) { return "use$1 no strict qw(refs);$2"; }
4010 0         0 elsif (/\G \b use ((?>\s+) strict .*? ;) ([ \t]* [^#]) /oxmsgc) { return "use$1 no strict qw(refs);\n$2"; }
4011 0         0 elsif (/\G \b use ((?>\s+) strict) \b /oxmsgc) { return "use$1; no strict qw(refs)"; }
4012              
4013             # use 5.12.0; --> use 5.12.0; no strict qw(refs);
4014             elsif (/\G \b use (?>\s+) ((?>([1-9][0-9_]*)(?:\.([0-9_]+))*)) (?>\s*) ; /oxmsgc) {
4015 2 50 33     24 if (($2 >= 6) or (($2 == 5) and ($3 ge '012'))) {
      33        
4016 0         0 return "use $1; no strict qw(refs);";
4017             }
4018             else {
4019 2         10 return "use $1;";
4020             }
4021             }
4022             elsif (/\G \b use (?>\s+) ((?>v([0-9][0-9_]*)(?:\.([0-9_]+))*)) (?>\s*) ; /oxmsgc) {
4023 0 0 0     0 if (($2 >= 6) or (($2 == 5) and ($3 >= 12))) {
      0        
4024 0         0 return "use $1; no strict qw(refs);";
4025             }
4026             else {
4027 0         0 return "use $1;";
4028             }
4029             }
4030              
4031             # ignore use module
4032 2         18 elsif (/\G \b use ((?>\s+) (?:$ignore_modules) .*? ;) ([ \t]* [#\n]) /oxmsgc) { return "# use$1$2"; }
4033 0         0 elsif (/\G \b use ((?>\s+) (?:$ignore_modules) .*? ;) ([ \t]* [^#]) /oxmsgc) { return "# use$1\n$2"; }
4034 0         0 elsif (/\G \b use ((?>\s+) (?:$ignore_modules)) \b /oxmsgc) { return "# use$1"; }
4035              
4036             # ignore no module
4037 0         0 elsif (/\G \b no ((?>\s+) (?:$ignore_modules) .*? ;) ([ \t]* [#\n]) /oxmsgc) { return "# no$1$2"; }
4038 0         0 elsif (/\G \b no ((?>\s+) (?:$ignore_modules) .*? ;) ([ \t]* [^#]) /oxmsgc) { return "# no$1\n$2"; }
4039 0         0 elsif (/\G \b no ((?>\s+) (?:$ignore_modules)) \b /oxmsgc) { return "# no$1"; }
4040              
4041             # use else
4042 0         0 elsif (/\G \b use \b /oxmsgc) { return "use"; }
4043              
4044             # use else
4045 2         9 elsif (/\G \b no \b /oxmsgc) { return "no"; }
4046              
4047             # ''
4048             elsif (/\G (?
4049 841         1346 my $q_string = '';
4050 841         2332 while (not /\G \z/oxgc) {
4051 8196 100       28830 if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  4 100       10  
    100          
    50          
4052 48         95 elsif (/\G (\\\') /oxgc) { $q_string .= $1; }
4053 841         2004 elsif (/\G \' /oxgc) { return e_q('', "'","'",$q_string); }
4054 7303         14366 elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
4055             }
4056 0         0 die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4057             }
4058              
4059             # ""
4060             elsif (/\G (\") /oxgc) {
4061 1739         2625 my $qq_string = '';
4062 1739         4411 while (not /\G \z/oxgc) {
4063 34091 100       110357 if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  67 100       188  
    100          
    50          
4064 12         29 elsif (/\G (\\\") /oxgc) { $qq_string .= $1; }
4065 1739         4237 elsif (/\G \" /oxgc) { return e_qq('', '"','"',$qq_string); }
4066 32273         67545 elsif (/\G ($q_char) /oxgc) { $qq_string .= $1; }
4067             }
4068 0         0 die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4069             }
4070              
4071             # ``
4072             elsif (/\G (\`) /oxgc) {
4073 1         2 my $qx_string = '';
4074 1         3 while (not /\G \z/oxgc) {
4075 19 50       74 if (/\G (\\\\) /oxgc) { $qx_string .= $1; }
  0 50       0  
    100          
    50          
4076 0         0 elsif (/\G (\\\`) /oxgc) { $qx_string .= $1; }
4077 1         3 elsif (/\G \` /oxgc) { return e_qq('', '`','`',$qx_string); }
4078 18         27 elsif (/\G ($q_char) /oxgc) { $qx_string .= $1; }
4079             }
4080 0         0 die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4081             }
4082              
4083             # // --- not divide operator (num / num), not defined-or
4084             elsif (($slash eq 'm//') and /\G (\/) /oxgc) {
4085 452         775 my $regexp = '';
4086 452         1501 while (not /\G \z/oxgc) {
4087 4490 50       16449 if (/\G (\\\\) /oxgc) { $regexp .= $1; }
  0 50       0  
    100          
    50          
4088 0         0 elsif (/\G (\\\/) /oxgc) { $regexp .= $1; }
4089 452         1311 elsif (/\G \/ ([cgimosxpadlunbB]*) /oxgc) { return e_qr('', '/','/',$regexp,$1); }
4090 4038         8032 elsif (/\G ($q_char) /oxgc) { $regexp .= $1; }
4091             }
4092 0         0 die __FILE__, ": Search pattern not terminated\n";
4093             }
4094              
4095             # ?? --- not conditional operator (condition ? then : else)
4096             elsif (($slash eq 'm//') and /\G (\?) /oxgc) {
4097 0         0 my $regexp = '';
4098 0         0 while (not /\G \z/oxgc) {
4099 0 0       0 if (/\G (\\\\) /oxgc) { $regexp .= $1; }
  0 0       0  
    0          
    0          
4100 0         0 elsif (/\G (\\\?) /oxgc) { $regexp .= $1; }
4101 0         0 elsif (/\G \? ([cgimosxpadlunbB]*) /oxgc) { return e_qr('m','?','?',$regexp,$1); }
4102 0         0 elsif (/\G ($q_char) /oxgc) { $regexp .= $1; }
4103             }
4104 0         0 die __FILE__, ": Search pattern not terminated\n";
4105             }
4106              
4107             # <<>> (a safer ARGV)
4108 0         0 elsif (/\G ( <<>> ) /oxgc) { $slash = 'm//'; return $1; }
  0         0  
4109              
4110             # << (bit shift) --- not here document
4111 0         0 elsif (/\G ( << (?>\s*) ) (?= [0-9\$\@\&] ) /oxgc) { $slash = 'm//'; return $1; }
  0         0  
4112              
4113             # <<'HEREDOC'
4114             elsif (/\G ( << '([a-zA-Z_0-9]*)' ) /oxgc) {
4115 72         111 $slash = 'm//';
4116 72         150 my $here_quote = $1;
4117 72         135 my $delimiter = $2;
4118              
4119             # get here document
4120 72 50       161 if ($here_script eq '') {
4121 72         375 $here_script = CORE::substr $_, pos $_;
4122 72         425 $here_script =~ s/.*?\n//oxm;
4123             }
4124 72 50       660 if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4125 72         245 push @heredoc, $1 . qq{\n$delimiter\n};
4126 72         123 push @heredoc_delimiter, $delimiter;
4127             }
4128             else {
4129 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4130             }
4131 72         326 return $here_quote;
4132             }
4133              
4134             # <<\HEREDOC
4135              
4136             # P.66 2.6.6. "Here" Documents
4137             # in Chapter 2: Bits and Pieces
4138             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
4139              
4140             # P.73 "Here" Documents
4141             # in Chapter 2: Bits and Pieces
4142             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
4143              
4144             elsif (/\G ( << \\([a-zA-Z_0-9]+) ) /oxgc) {
4145 0         0 $slash = 'm//';
4146 0         0 my $here_quote = $1;
4147 0         0 my $delimiter = $2;
4148              
4149             # get here document
4150 0 0       0 if ($here_script eq '') {
4151 0         0 $here_script = CORE::substr $_, pos $_;
4152 0         0 $here_script =~ s/.*?\n//oxm;
4153             }
4154 0 0       0 if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4155 0         0 push @heredoc, $1 . qq{\n$delimiter\n};
4156 0         0 push @heredoc_delimiter, $delimiter;
4157             }
4158             else {
4159 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4160             }
4161 0         0 return $here_quote;
4162             }
4163              
4164             # <<"HEREDOC"
4165             elsif (/\G ( << "([a-zA-Z_0-9]*)" ) /oxgc) {
4166 36         59 $slash = 'm//';
4167 36         78 my $here_quote = $1;
4168 36         612 my $delimiter = $2;
4169              
4170             # get here document
4171 36 50       96 if ($here_script eq '') {
4172 36         517 $here_script = CORE::substr $_, pos $_;
4173 36         234 $here_script =~ s/.*?\n//oxm;
4174             }
4175 36 50       808 if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4176 36         100 push @heredoc, e_heredoc($1) . qq{\n$delimiter\n};
4177 36         170 push @heredoc_delimiter, $delimiter;
4178             }
4179             else {
4180 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4181             }
4182 36         154 return $here_quote;
4183             }
4184              
4185             # <
4186             elsif (/\G ( << ([a-zA-Z_0-9]+) ) /oxgc) {
4187 42         89 $slash = 'm//';
4188 42         103 my $here_quote = $1;
4189 42         81 my $delimiter = $2;
4190              
4191             # get here document
4192 42 50       130 if ($here_script eq '') {
4193 42         352 $here_script = CORE::substr $_, pos $_;
4194 42         325 $here_script =~ s/.*?\n//oxm;
4195             }
4196 42 50       690 if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4197 42         139 push @heredoc, e_heredoc($1) . qq{\n$delimiter\n};
4198 42         94 push @heredoc_delimiter, $delimiter;
4199             }
4200             else {
4201 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4202             }
4203 42         225 return $here_quote;
4204             }
4205              
4206             # <<`HEREDOC`
4207             elsif (/\G ( << `([a-zA-Z_0-9]*)` ) /oxgc) {
4208 0         0 $slash = 'm//';
4209 0         0 my $here_quote = $1;
4210 0         0 my $delimiter = $2;
4211              
4212             # get here document
4213 0 0       0 if ($here_script eq '') {
4214 0         0 $here_script = CORE::substr $_, pos $_;
4215 0         0 $here_script =~ s/.*?\n//oxm;
4216             }
4217 0 0       0 if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4218 0         0 push @heredoc, e_heredoc($1) . qq{\n$delimiter\n};
4219 0         0 push @heredoc_delimiter, $delimiter;
4220             }
4221             else {
4222 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4223             }
4224 0         0 return $here_quote;
4225             }
4226              
4227             # <<= <=> <= < operator
4228             elsif (/\G ( <<= | <=> | <= | < ) (?= (?>\s*) [A-Za-z_0-9'"`\$\@\&\*\(\+\-] )/oxgc) {
4229 11         70 return $1;
4230             }
4231              
4232             #
4233             elsif (/\G (<[\$]?[A-Za-z_][A-Za-z_0-9]*>) /oxgc) {
4234 0         0 return $1;
4235             }
4236              
4237             # --- glob
4238              
4239             # avoid "Error: Runtime exception" of perl version 5.005_03
4240              
4241             elsif (/\G < ((?:[^>\0\a\e\f\n\r\t])+?) > /oxgc) {
4242 0         0 return 'Ekoi8r::glob("' . $1 . '")';
4243             }
4244              
4245             # __DATA__
4246 0         0 elsif (/\G ^ ( __DATA__ \n .*) \z /oxmsgc) { return $1; }
4247              
4248             # __END__
4249 200         1487 elsif (/\G ^ ( __END__ \n .*) \z /oxmsgc) { return $1; }
4250              
4251             # \cD Control-D
4252              
4253             # P.68 2.6.8. Other Literal Tokens
4254             # in Chapter 2: Bits and Pieces
4255             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
4256              
4257             # P.76 Other Literal Tokens
4258             # in Chapter 2: Bits and Pieces
4259             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
4260              
4261 0         0 elsif (/\G ( \cD .*) \z /oxmsgc) { return $1; }
4262              
4263             # \cZ Control-Z
4264 0         0 elsif (/\G ( \cZ .*) \z /oxmsgc) { return $1; }
4265              
4266             # any operator before div
4267             elsif (/\G (
4268             -- | \+\+ |
4269             [\)\}\]]
4270              
4271 4824         6080 ) /oxgc) { $slash = 'div'; return $1; }
  4824         21831  
4272              
4273             # yada-yada or triple-dot operator
4274             elsif (/\G (
4275             \.\.\.
4276              
4277 7         10 ) /oxgc) { $slash = 'm//'; return q{die('Unimplemented')}; }
  7         24  
4278              
4279             # any operator before m//
4280              
4281             # //, //= (defined-or)
4282              
4283             # P.164 Logical Operators
4284             # in Chapter 10: More Control Structures
4285             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
4286              
4287             # P.119 C-Style Logical (Short-Circuit) Operators
4288             # in Chapter 3: Unary and Binary Operators
4289             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
4290              
4291             # (and so on)
4292              
4293             # ~~
4294              
4295             # P.221 The Smart Match Operator
4296             # in Chapter 15: Smart Matching and given-when
4297             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
4298              
4299             # P.112 Smartmatch Operator
4300             # in Chapter 3: Unary and Binary Operators
4301             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
4302              
4303             # (and so on)
4304              
4305             elsif (/\G ((?>
4306              
4307             !~~ | !~ | != | ! |
4308             %= | % |
4309             &&= | && | &= | &\.= | &\. | & |
4310             -= | -> | - |
4311             :(?>\s*)= |
4312             : |
4313             <<>> |
4314             <<= | <=> | <= | < |
4315             == | => | =~ | = |
4316             >>= | >> | >= | > |
4317             \*\*= | \*\* | \*= | \* |
4318             \+= | \+ |
4319             \.\. | \.= | \. |
4320             \/\/= | \/\/ |
4321             \/= | \/ |
4322             \? |
4323             \\ |
4324             \^= | \^\.= | \^\. | \^ |
4325             \b x= |
4326             \|\|= | \|\| | \|= | \|\.= | \|\. | \| |
4327             ~~ | ~\. | ~ |
4328             \b(?: and | cmp | eq | ge | gt | le | lt | ne | not | or | xor | x )\b |
4329             \b(?: print )\b |
4330              
4331             [,;\(\{\[]
4332              
4333 8481         10750 )) /oxgc) { $slash = 'm//'; return $1; }
  8481         37531  
4334              
4335             # other any character
4336 14616         17146 elsif (/\G ($q_char) /oxgc) { $slash = 'div'; return $1; }
  14616         65678  
4337              
4338             # system error
4339             else {
4340 0         0 die __FILE__, ": Oops, this shouldn't happen!\n";
4341             }
4342             }
4343              
4344             # escape KOI8-R string
4345             sub e_string {
4346 1718     1718 0 3383 my($string) = @_;
4347 1718         1975 my $e_string = '';
4348              
4349 1718         2214 local $slash = 'm//';
4350              
4351             # P.1024 Appendix W.10 Multibyte Processing
4352             # of ISBN 1-56592-224-7 CJKV Information Processing
4353             # (and so on)
4354              
4355 1718         17289 my @char = $string =~ / \G (?>[^\\]|\\$q_char|$q_char) /oxmsg;
4356              
4357             # without { ... }
4358 1718 100 66     8250 if (not (grep(/\A \{ \z/xms, @char) and grep(/\A \} \z/xms, @char))) {
4359 1701 50       3687 if ($string !~ /<
4360 1701         4573 return $string;
4361             }
4362             }
4363              
4364             E_STRING_LOOP:
4365 17         59 while ($string !~ /\G \z/oxgc) {
4366 190 50       15710 if (0) {
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    100          
    100          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    100          
    50          
    100          
    50          
4367             }
4368              
4369             # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> @{[Ekoi8r::PREMATCH()]}
4370 0         0 elsif ($string =~ /\G ( \$` | \$\{`\} | \$ (?>\s*) PREMATCH \b | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} ) /oxmsgc) {
4371 0         0 $e_string .= q{Ekoi8r::PREMATCH()};
4372 0         0 $slash = 'div';
4373             }
4374              
4375             # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> @{[Ekoi8r::MATCH()]}
4376             elsif ($string =~ /\G ( \$& | \$\{&\} | \$ (?>\s*) MATCH \b | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} ) /oxmsgc) {
4377 0         0 $e_string .= q{Ekoi8r::MATCH()};
4378 0         0 $slash = 'div';
4379             }
4380              
4381             # $', ${'} --> $', ${'}
4382             elsif ($string =~ /\G ( \$' | \$\{'\} ) /oxmsgc) {
4383 0         0 $e_string .= $1;
4384 0         0 $slash = 'div';
4385             }
4386              
4387             # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> @{[Ekoi8r::POSTMATCH()]}
4388             elsif ($string =~ /\G ( \$ (?>\s*) POSTMATCH \b | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} ) /oxmsgc) {
4389 0         0 $e_string .= q{Ekoi8r::POSTMATCH()};
4390 0         0 $slash = 'div';
4391             }
4392              
4393             # bareword
4394             elsif ($string =~ /\G ( \{ (?>\s*) (?: tr | index | rindex | reverse ) (?>\s*) \} ) /oxmsgc) {
4395 0         0 $e_string .= $1;
4396 0         0 $slash = 'div';
4397             }
4398              
4399             # $0 --> $0
4400             elsif ($string =~ /\G ( \$ 0 ) /oxmsgc) {
4401 0         0 $e_string .= $1;
4402 0         0 $slash = 'div';
4403             }
4404             elsif ($string =~ /\G ( \$ \{ (?>\s*) 0 (?>\s*) \} ) /oxmsgc) {
4405 0         0 $e_string .= $1;
4406 0         0 $slash = 'div';
4407             }
4408              
4409             # $$ --> $$
4410             elsif ($string =~ /\G ( \$ \$ ) (?![\w\{]) /oxmsgc) {
4411 0         0 $e_string .= $1;
4412 0         0 $slash = 'div';
4413             }
4414              
4415             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
4416             # $1, $2, $3 --> $1, $2, $3 otherwise
4417             elsif ($string =~ /\G \$ ((?>[1-9][0-9]*)) /oxmsgc) {
4418 0         0 $e_string .= e_capture($1);
4419 0         0 $slash = 'div';
4420             }
4421             elsif ($string =~ /\G \$ \{ (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} /oxmsgc) {
4422 0         0 $e_string .= e_capture($1);
4423 0         0 $slash = 'div';
4424             }
4425              
4426             # $$foo[ ... ] --> $ $foo->[ ... ]
4427             elsif ($string =~ /\G \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \[ .+? \] ) /oxmsgc) {
4428 0         0 $e_string .= e_capture($1.'->'.$2);
4429 0         0 $slash = 'div';
4430             }
4431              
4432             # $$foo{ ... } --> $ $foo->{ ... }
4433             elsif ($string =~ /\G \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \{ .+? \} ) /oxmsgc) {
4434 0         0 $e_string .= e_capture($1.'->'.$2);
4435 0         0 $slash = 'div';
4436             }
4437              
4438             # $$foo
4439             elsif ($string =~ /\G \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) /oxmsgc) {
4440 0         0 $e_string .= e_capture($1);
4441 0         0 $slash = 'div';
4442             }
4443              
4444             # ${ foo }
4445             elsif ($string =~ /\G \$ (?>\s*) \{ ((?> \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* )) \} /oxmsgc) {
4446 0         0 $e_string .= '${' . $1 . '}';
4447 0         0 $slash = 'div';
4448             }
4449              
4450             # ${ ... }
4451             elsif ($string =~ /\G \$ (?>\s*) \{ (?>\s*) ( $qq_brace ) (?>\s*) \} /oxmsgc) {
4452 3         10 $e_string .= e_capture($1);
4453 3         13 $slash = 'div';
4454             }
4455              
4456             # variable or function
4457             # $ @ % & * $ #
4458             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) {
4459 7         18 $e_string .= $1;
4460 7         23 $slash = 'div';
4461             }
4462             # $ $ $ $ $ $ $ $ $ $ $ $ $ $
4463             # $ @ # \ ' " / ? ( ) [ ] < >
4464             elsif ($string =~ /\G ( \$[\$\@\#\\\'\"\/\?\(\)\[\]\<\>] ) /oxmsgc) {
4465 0         0 $e_string .= $1;
4466 0         0 $slash = 'div';
4467             }
4468              
4469             # subroutines of package Ekoi8r
4470 0         0 elsif ($string =~ /\G \b (CORE:: | ->(>?\s*) (?: atan2 | [a-z]{2,})) \b /oxgc) { $e_string .= $1; $slash = 'm//'; }
  0         0  
4471 0         0 elsif ($string =~ /\G \b Char::eval (?= (?>\s*) \{ ) /oxgc) { $e_string .= 'eval'; $slash = 'm//'; }
  0         0  
4472 0         0 elsif ($string =~ /\G \b KOI8R::eval (?= (?>\s*) \{ ) /oxgc) { $e_string .= 'eval'; $slash = 'm//'; }
  0         0  
4473 0         0 elsif ($string =~ /\G \b Char::eval \b /oxgc) { $e_string .= 'eval Char::escape'; $slash = 'm//'; }
  0         0  
4474 0         0 elsif ($string =~ /\G \b KOI8R::eval \b /oxgc) { $e_string .= 'eval KOI8R::escape'; $slash = 'm//'; }
  0         0  
4475 0         0 elsif ($string =~ /\G \b bytes::substr \b /oxgc) { $e_string .= 'substr'; $slash = 'm//'; }
  0         0  
4476 0         0 elsif ($string =~ /\G \b chop \b /oxgc) { $e_string .= 'Ekoi8r::chop'; $slash = 'm//'; }
  0         0  
4477 0         0 elsif ($string =~ /\G \b bytes::index \b /oxgc) { $e_string .= 'index'; $slash = 'm//'; }
  0         0  
4478 0         0 elsif ($string =~ /\G \b Char::index \b /oxgc) { $e_string .= 'Char::index'; $slash = 'm//'; }
  0         0  
4479 0         0 elsif ($string =~ /\G \b KOI8R::index \b /oxgc) { $e_string .= 'KOI8R::index'; $slash = 'm//'; }
  0         0  
4480 0         0 elsif ($string =~ /\G \b index \b /oxgc) { $e_string .= 'Ekoi8r::index'; $slash = 'm//'; }
  0         0  
4481 0         0 elsif ($string =~ /\G \b bytes::rindex \b /oxgc) { $e_string .= 'rindex'; $slash = 'm//'; }
  0         0  
4482 0         0 elsif ($string =~ /\G \b Char::rindex \b /oxgc) { $e_string .= 'Char::rindex'; $slash = 'm//'; }
  0         0  
4483 0         0 elsif ($string =~ /\G \b KOI8R::rindex \b /oxgc) { $e_string .= 'KOI8R::rindex'; $slash = 'm//'; }
  0         0  
4484 0         0 elsif ($string =~ /\G \b rindex \b /oxgc) { $e_string .= 'Ekoi8r::rindex'; $slash = 'm//'; }
  0         0  
4485 0         0 elsif ($string =~ /\G \b lc (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Ekoi8r::lc'; $slash = 'm//'; }
  0         0  
4486 0         0 elsif ($string =~ /\G \b lcfirst (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Ekoi8r::lcfirst'; $slash = 'm//'; }
  0         0  
4487 0         0 elsif ($string =~ /\G \b uc (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Ekoi8r::uc'; $slash = 'm//'; }
  0         0  
4488 0         0 elsif ($string =~ /\G \b ucfirst (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Ekoi8r::ucfirst'; $slash = 'm//'; }
  0         0  
4489 0         0 elsif ($string =~ /\G \b fc (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Ekoi8r::fc'; $slash = 'm//'; }
  0         0  
4490              
4491             # "-s '' ..." means file test "-s 'filename' ..." (not means "- s/// ...")
4492 0         0 elsif ($string =~ /\G -s (?>\s*) (\") ((?:$qq_char)+?) (\") /oxgc) { $e_string .= '-s ' . e_qq('', $1,$3,$2); $slash = 'm//'; }
  0         0  
4493 0         0 elsif ($string =~ /\G -s (?>\s+) qq (?>\s*) (\#) ((?:$qq_char)+?) (\#) /oxgc) { $e_string .= '-s ' . e_qq('qq',$1,$3,$2); $slash = 'm//'; }
  0         0  
4494 0         0 elsif ($string =~ /\G -s (?>\s+) qq (?>\s*) (\() ((?:$qq_paren)+?) (\)) /oxgc) { $e_string .= '-s ' . e_qq('qq',$1,$3,$2); $slash = 'm//'; }
  0         0  
4495 0         0 elsif ($string =~ /\G -s (?>\s+) qq (?>\s*) (\{) ((?:$qq_brace)+?) (\}) /oxgc) { $e_string .= '-s ' . e_qq('qq',$1,$3,$2); $slash = 'm//'; }
  0         0  
4496 0         0 elsif ($string =~ /\G -s (?>\s+) qq (?>\s*) (\[) ((?:$qq_bracket)+?) (\]) /oxgc) { $e_string .= '-s ' . e_qq('qq',$1,$3,$2); $slash = 'm//'; }
  0         0  
4497 0         0 elsif ($string =~ /\G -s (?>\s+) qq (?>\s*) (\<) ((?:$qq_angle)+?) (\>) /oxgc) { $e_string .= '-s ' . e_qq('qq',$1,$3,$2); $slash = 'm//'; }
  0         0  
4498 0         0 elsif ($string =~ /\G -s (?>\s+) qq (?>\s*) (\S) ((?:$qq_char)+?) (\1) /oxgc) { $e_string .= '-s ' . e_qq('qq',$1,$3,$2); $slash = 'm//'; }
  0         0  
4499              
4500 0         0 elsif ($string =~ /\G -s (?>\s*) (\') ((?:\\\'|\\\\|$q_char)+?) (\') /oxgc) { $e_string .= '-s ' . e_q ('', $1,$3,$2); $slash = 'm//'; }
  0         0  
4501 0         0 elsif ($string =~ /\G -s (?>\s+) q (?>\s*) (\#) ((?:\\\#|\\\\|$q_char)+?) (\#) /oxgc) { $e_string .= '-s ' . e_q ('q', $1,$3,$2); $slash = 'm//'; }
  0         0  
4502 0         0 elsif ($string =~ /\G -s (?>\s+) q (?>\s*) (\() ((?:\\\)|\\\\|$q_paren)+?) (\)) /oxgc) { $e_string .= '-s ' . e_q ('q', $1,$3,$2); $slash = 'm//'; }
  0         0  
4503 0         0 elsif ($string =~ /\G -s (?>\s+) q (?>\s*) (\{) ((?:\\\}|\\\\|$q_brace)+?) (\}) /oxgc) { $e_string .= '-s ' . e_q ('q', $1,$3,$2); $slash = 'm//'; }
  0         0  
4504 0         0 elsif ($string =~ /\G -s (?>\s+) q (?>\s*) (\[) ((?:\\\]|\\\\|$q_bracket)+?) (\]) /oxgc) { $e_string .= '-s ' . e_q ('q', $1,$3,$2); $slash = 'm//'; }
  0         0  
4505 0         0 elsif ($string =~ /\G -s (?>\s+) q (?>\s*) (\<) ((?:\\\>|\\\\|$q_angle)+?) (\>) /oxgc) { $e_string .= '-s ' . e_q ('q', $1,$3,$2); $slash = 'm//'; }
  0         0  
4506 0         0 elsif ($string =~ /\G -s (?>\s+) q (?>\s*) (\S) ((?:\\\1|\\\\|$q_char)+?) (\1) /oxgc) { $e_string .= '-s ' . e_q ('q', $1,$3,$2); $slash = 'm//'; }
  0         0  
4507              
4508             elsif ($string =~ /\G -s (?>\s*) (\$ (?> \w+ (?: ::\w+)*) (?: (?: ->)? (?: [\$\@\%\&\*]\* | \$\#\* | \( (?:$qq_paren)*? \) | [\@\%\*]? \{ (?:$qq_brace)+? \} | [\@\%]? \[ (?:$qq_bracket)+? \] ))*) /oxgc)
4509 0         0 { $e_string .= "-s $1"; $slash = 'm//'; }
  0         0  
4510 0         0 elsif ($string =~ /\G -s (?>\s*) \( ((?:$qq_paren)*?) \) /oxgc) { $e_string .= "-s ($1)"; $slash = 'm//'; }
  0         0  
4511 0         0 elsif ($string =~ /\G -s (?= (?>\s+) [a-z]+) /oxgc) { $e_string .= '-s'; $slash = 'm//'; }
  0         0  
4512 0         0 elsif ($string =~ /\G -s (?>\s+) ((?>\w+)) /oxgc) { $e_string .= "-s $1"; $slash = 'm//'; }
  0         0  
4513              
4514 0         0 elsif ($string =~ /\G \b bytes::length (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'length'; $slash = 'm//'; }
  0         0  
4515 0         0 elsif ($string =~ /\G \b bytes::chr (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'chr'; $slash = 'm//'; }
  0         0  
4516 0         0 elsif ($string =~ /\G \b chr (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Ekoi8r::chr'; $slash = 'm//'; }
  0         0  
4517 0         0 elsif ($string =~ /\G \b bytes::ord (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'ord'; $slash = 'div'; }
  0         0  
4518 0         0 elsif ($string =~ /\G \b ord (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $e_string .= $function_ord; $slash = 'div'; }
  0         0  
4519 0         0 elsif ($string =~ /\G \b glob (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Ekoi8r::glob'; $slash = 'm//'; }
  0         0  
4520 0         0 elsif ($string =~ /\G \b lc \b /oxgc) { $e_string .= 'Ekoi8r::lc_'; $slash = 'm//'; }
  0         0  
4521 0         0 elsif ($string =~ /\G \b lcfirst \b /oxgc) { $e_string .= 'Ekoi8r::lcfirst_'; $slash = 'm//'; }
  0         0  
4522 0         0 elsif ($string =~ /\G \b uc \b /oxgc) { $e_string .= 'Ekoi8r::uc_'; $slash = 'm//'; }
  0         0  
4523 0         0 elsif ($string =~ /\G \b ucfirst \b /oxgc) { $e_string .= 'Ekoi8r::ucfirst_'; $slash = 'm//'; }
  0         0  
4524 0         0 elsif ($string =~ /\G \b fc \b /oxgc) { $e_string .= 'Ekoi8r::fc_'; $slash = 'm//'; }
  0         0  
4525 0         0 elsif ($string =~ /\G -s \b /oxgc) { $e_string .= '-s '; $slash = 'm//'; }
  0         0  
4526              
4527 0         0 elsif ($string =~ /\G \b bytes::length \b /oxgc) { $e_string .= 'length'; $slash = 'm//'; }
  0         0  
4528 0         0 elsif ($string =~ /\G \b bytes::chr \b /oxgc) { $e_string .= 'chr'; $slash = 'm//'; }
  0         0  
4529 0         0 elsif ($string =~ /\G \b chr \b /oxgc) { $e_string .= 'Ekoi8r::chr_'; $slash = 'm//'; }
  0         0  
4530 0         0 elsif ($string =~ /\G \b bytes::ord \b /oxgc) { $e_string .= 'ord'; $slash = 'div'; }
  0         0  
4531 0         0 elsif ($string =~ /\G \b ord \b /oxgc) { $e_string .= $function_ord_; $slash = 'div'; }
  0         0  
4532 0         0 elsif ($string =~ /\G \b glob \b /oxgc) { $e_string .= 'Ekoi8r::glob_'; $slash = 'm//'; }
  0         0  
4533 0         0 elsif ($string =~ /\G \b reverse \b /oxgc) { $e_string .= $function_reverse; $slash = 'm//'; }
  0         0  
4534 0         0 elsif ($string =~ /\G \b getc \b /oxgc) { $e_string .= $function_getc; $slash = 'm//'; }
  0         0  
4535             # split
4536             elsif ($string =~ /\G \b (split) \b (?! (?>\s*) => ) /oxgc) {
4537 0         0 $slash = 'm//';
4538              
4539 0         0 my $e = '';
4540 0         0 while ($string =~ /\G ( (?>\s+) | \( | \#.* ) /oxgc) {
4541 0         0 $e .= $1;
4542             }
4543              
4544             # end of split
4545 0 0       0 if ($string =~ /\G (?= [,;\)\}\]] ) /oxgc) { return 'Ekoi8r::split' . $e; }
  0 0       0  
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
4546              
4547             # split scalar value
4548 0         0 elsif ($string =~ /\G ( [\$\@\&\*] $qq_scalar ) /oxgc) { $e_string .= 'Ekoi8r::split' . $e . e_string($1); next E_STRING_LOOP; }
  0         0  
4549              
4550             # split literal space
4551 0         0 elsif ($string =~ /\G \b qq (\#) [ ] (\#) /oxgc) { $e_string .= 'Ekoi8r::split' . $e . qq {qq$1 $2}; next E_STRING_LOOP; }
  0         0  
4552 0         0 elsif ($string =~ /\G \b qq ((?>\s*)) (\() [ ] (\)) /oxgc) { $e_string .= 'Ekoi8r::split' . $e . qq{$1qq$2 $3}; next E_STRING_LOOP; }
  0         0  
4553 0         0 elsif ($string =~ /\G \b qq ((?>\s*)) (\{) [ ] (\}) /oxgc) { $e_string .= 'Ekoi8r::split' . $e . qq{$1qq$2 $3}; next E_STRING_LOOP; }
  0         0  
4554 0         0 elsif ($string =~ /\G \b qq ((?>\s*)) (\[) [ ] (\]) /oxgc) { $e_string .= 'Ekoi8r::split' . $e . qq{$1qq$2 $3}; next E_STRING_LOOP; }
  0         0  
4555 0         0 elsif ($string =~ /\G \b qq ((?>\s*)) (\<) [ ] (\>) /oxgc) { $e_string .= 'Ekoi8r::split' . $e . qq{$1qq$2 $3}; next E_STRING_LOOP; }
  0         0  
4556 0         0 elsif ($string =~ /\G \b qq ((?>\s*)) (\S) [ ] (\2) /oxgc) { $e_string .= 'Ekoi8r::split' . $e . qq{$1qq$2 $3}; next E_STRING_LOOP; }
  0         0  
4557 0         0 elsif ($string =~ /\G \b q (\#) [ ] (\#) /oxgc) { $e_string .= 'Ekoi8r::split' . $e . qq {q$1 $2}; next E_STRING_LOOP; }
  0         0  
4558 0         0 elsif ($string =~ /\G \b q ((?>\s*)) (\() [ ] (\)) /oxgc) { $e_string .= 'Ekoi8r::split' . $e . qq {$1q$2 $3}; next E_STRING_LOOP; }
  0         0  
4559 0         0 elsif ($string =~ /\G \b q ((?>\s*)) (\{) [ ] (\}) /oxgc) { $e_string .= 'Ekoi8r::split' . $e . qq {$1q$2 $3}; next E_STRING_LOOP; }
  0         0  
4560 0         0 elsif ($string =~ /\G \b q ((?>\s*)) (\[) [ ] (\]) /oxgc) { $e_string .= 'Ekoi8r::split' . $e . qq {$1q$2 $3}; next E_STRING_LOOP; }
  0         0  
4561 0         0 elsif ($string =~ /\G \b q ((?>\s*)) (\<) [ ] (\>) /oxgc) { $e_string .= 'Ekoi8r::split' . $e . qq {$1q$2 $3}; next E_STRING_LOOP; }
  0         0  
4562 0         0 elsif ($string =~ /\G \b q ((?>\s*)) (\S) [ ] (\2) /oxgc) { $e_string .= 'Ekoi8r::split' . $e . qq {$1q$2 $3}; next E_STRING_LOOP; }
  0         0  
4563 0         0 elsif ($string =~ /\G ' [ ] ' /oxgc) { $e_string .= 'Ekoi8r::split' . $e . qq {' '}; next E_STRING_LOOP; }
  0         0  
4564 0         0 elsif ($string =~ /\G " [ ] " /oxgc) { $e_string .= 'Ekoi8r::split' . $e . qq {" "}; next E_STRING_LOOP; }
  0         0  
4565              
4566             # split qq//
4567             elsif ($string =~ /\G \b (qq) \b /oxgc) {
4568 0 0       0 if ($string =~ /\G (\#) ((?:$qq_char)*?) (\#) /oxgc) { $e_string .= e_split($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # qq# # --> qr # #
  0         0  
  0         0  
4569             else {
4570 0         0 while ($string !~ /\G \z/oxgc) {
4571 0 0       0 if ($string =~ /\G ((?>\s+)|\#.*) /oxgc) { $e_string .= $e . $1; }
  0 0       0  
    0          
    0          
    0          
    0          
    0          
4572 0         0 elsif ($string =~ /\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { $e_string .= e_split($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # qq ( ) --> qr ( )
  0         0  
4573 0         0 elsif ($string =~ /\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { $e_string .= e_split($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # qq { } --> qr { }
  0         0  
4574 0         0 elsif ($string =~ /\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { $e_string .= e_split($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # qq [ ] --> qr [ ]
  0         0  
4575 0         0 elsif ($string =~ /\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { $e_string .= e_split($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # qq < > --> qr < >
  0         0  
4576 0         0 elsif ($string =~ /\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) /oxgc) { $e_string .= e_split($e.'qr','{','}',$2,''); next E_STRING_LOOP; } # qq | | --> qr { }
  0         0  
4577 0         0 elsif ($string =~ /\G (\S) ((?:$qq_char)*?) (\1) /oxgc) { $e_string .= e_split($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # qq * * --> qr * *
  0         0  
4578             }
4579 0         0 die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4580             }
4581             }
4582              
4583             # split qr//
4584             elsif ($string =~ /\G \b (qr) \b /oxgc) {
4585 0 0       0 if ($string =~ /\G (\#) ((?:$qq_char)*?) (\#) ([imosxpadlunbB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1,$3,$2,$4); next E_STRING_LOOP; } # qr# #
  0         0  
  0         0  
4586             else {
4587 0         0 while ($string !~ /\G \z/oxgc) {
4588 0 0       0 if ($string =~ /\G ((?>\s+)|\#.*) /oxgc) { $e_string .= $e . $1; }
  0 0       0  
    0          
    0          
    0          
    0          
    0          
    0          
4589 0         0 elsif ($string =~ /\G (\() ((?:$qq_paren)*?) (\)) ([imosxpadlunbB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # qr ( )
  0         0  
4590 0         0 elsif ($string =~ /\G (\{) ((?:$qq_brace)*?) (\}) ([imosxpadlunbB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # qr { }
  0         0  
4591 0         0 elsif ($string =~ /\G (\[) ((?:$qq_bracket)*?) (\]) ([imosxpadlunbB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # qr [ ]
  0         0  
4592 0         0 elsif ($string =~ /\G (\<) ((?:$qq_angle)*?) (\>) ([imosxpadlunbB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # qr < >
  0         0  
4593 0         0 elsif ($string =~ /\G (\') ((?:$qq_char)*?) (\') ([imosxpadlunbB]*) /oxgc) { $e_string .= e_split_q($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # qr ' '
  0         0  
4594 0         0 elsif ($string =~ /\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ([imosxpadlunbB]*) /oxgc) { $e_string .= e_split ($e.'qr','{','}',$2,$4); next E_STRING_LOOP; } # qr | | --> qr { }
  0         0  
4595 0         0 elsif ($string =~ /\G (\S) ((?:$qq_char)*?) (\1) ([imosxpadlunbB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # qr * *
  0         0  
4596             }
4597 0         0 die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4598             }
4599             }
4600              
4601             # split q//
4602             elsif ($string =~ /\G \b (q) \b /oxgc) {
4603 0 0       0 if ($string =~ /\G (\#) ((?:\\\#|\\\\|$q_char)*?) (\#) /oxgc) { $e_string .= e_split_q($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # q# # --> qr # #
  0         0  
  0         0  
4604             else {
4605 0         0 while ($string !~ /\G \z/oxgc) {
4606 0 0       0 if ($string =~ /\G ((?>\s+)|\#.*) /oxgc) { $e_string .= $e . $1; }
  0 0       0  
    0          
    0          
    0          
    0          
    0          
4607 0         0 elsif ($string =~ /\G (\() ((?:\\\\|\\\)|\\\(|$q_paren)*?) (\)) /oxgc) { $e_string .= e_split_q($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # q ( ) --> qr ( )
  0         0  
4608 0         0 elsif ($string =~ /\G (\{) ((?:\\\\|\\\}|\\\{|$q_brace)*?) (\}) /oxgc) { $e_string .= e_split_q($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # q { } --> qr { }
  0         0  
4609 0         0 elsif ($string =~ /\G (\[) ((?:\\\\|\\\]|\\\[|$q_bracket)*?) (\]) /oxgc) { $e_string .= e_split_q($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # q [ ] --> qr [ ]
  0         0  
4610 0         0 elsif ($string =~ /\G (\<) ((?:\\\\|\\\>|\\\<|$q_angle)*?) (\>) /oxgc) { $e_string .= e_split_q($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # q < > --> qr < >
  0         0  
4611 0         0 elsif ($string =~ /\G ([*\-:?\\^|]) ((?:$q_char)*?) (\1) /oxgc) { $e_string .= e_split_q($e.'qr','{','}',$2,''); next E_STRING_LOOP; } # q | | --> qr { }
  0         0  
4612 0         0 elsif ($string =~ /\G (\S) ((?:\\\\|\\\1| $q_char)*?) (\1) /oxgc) { $e_string .= e_split_q($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # q * * --> qr * *
  0         0  
4613             }
4614 0         0 die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4615             }
4616             }
4617              
4618             # split m//
4619             elsif ($string =~ /\G \b (m) \b /oxgc) {
4620 0 0       0 if ($string =~ /\G (\#) ((?:$qq_char)*?) (\#) ([cgimosxpadlunbB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1,$3,$2,$4); next E_STRING_LOOP; } # m# # --> qr # #
  0         0  
  0         0  
4621             else {
4622 0         0 while ($string !~ /\G \z/oxgc) {
4623 0 0       0 if ($string =~ /\G ((?>\s+)|\#.*) /oxgc) { $e_string .= $e . $1; }
  0 0       0  
    0          
    0          
    0          
    0          
    0          
    0          
4624 0         0 elsif ($string =~ /\G (\() ((?:$qq_paren)*?) (\)) ([cgimosxpadlunbB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # m ( ) --> qr ( )
  0         0  
4625 0         0 elsif ($string =~ /\G (\{) ((?:$qq_brace)*?) (\}) ([cgimosxpadlunbB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # m { } --> qr { }
  0         0  
4626 0         0 elsif ($string =~ /\G (\[) ((?:$qq_bracket)*?) (\]) ([cgimosxpadlunbB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # m [ ] --> qr [ ]
  0         0  
4627 0         0 elsif ($string =~ /\G (\<) ((?:$qq_angle)*?) (\>) ([cgimosxpadlunbB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # m < > --> qr < >
  0         0  
4628 0         0 elsif ($string =~ /\G (\') ((?:$qq_char)*?) (\') ([cgimosxpadlunbB]*) /oxgc) { $e_string .= e_split_q($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # m ' ' --> qr ' '
  0         0  
4629 0         0 elsif ($string =~ /\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ([cgimosxpadlunbB]*) /oxgc) { $e_string .= e_split ($e.'qr','{','}',$2,$4); next E_STRING_LOOP; } # m | | --> qr { }
  0         0  
4630 0         0 elsif ($string =~ /\G (\S) ((?:$qq_char)*?) (\1) ([cgimosxpadlunbB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # m * * --> qr * *
  0         0  
4631             }
4632 0         0 die __FILE__, ": Search pattern not terminated\n";
4633             }
4634             }
4635              
4636             # split ''
4637             elsif ($string =~ /\G (\') /oxgc) {
4638 0         0 my $q_string = '';
4639 0         0 while ($string !~ /\G \z/oxgc) {
4640 0 0       0 if ($string =~ /\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0       0  
    0          
    0          
4641 0         0 elsif ($string =~ /\G (\\\') /oxgc) { $q_string .= $1; } # splitqr'' --> split qr''
4642 0         0 elsif ($string =~ /\G \' /oxgc) { $e_string .= e_split_q($e.q{ qr},"'","'",$q_string,''); next E_STRING_LOOP; } # ' ' --> qr ' '
  0         0  
4643 0         0 elsif ($string =~ /\G ($q_char) /oxgc) { $q_string .= $1; }
4644             }
4645 0         0 die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4646             }
4647              
4648             # split ""
4649             elsif ($string =~ /\G (\") /oxgc) {
4650 0         0 my $qq_string = '';
4651 0         0 while ($string !~ /\G \z/oxgc) {
4652 0 0       0 if ($string =~ /\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0       0  
    0          
    0          
4653 0         0 elsif ($string =~ /\G (\\\") /oxgc) { $qq_string .= $1; } # splitqr"" --> split qr""
4654 0         0 elsif ($string =~ /\G \" /oxgc) { $e_string .= e_split($e.q{ qr},'"','"',$qq_string,''); next E_STRING_LOOP; } # " " --> qr " "
  0         0  
4655 0         0 elsif ($string =~ /\G ($q_char) /oxgc) { $qq_string .= $1; }
4656             }
4657 0         0 die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4658             }
4659              
4660             # split //
4661             elsif ($string =~ /\G (\/) /oxgc) {
4662 0         0 my $regexp = '';
4663 0         0 while ($string !~ /\G \z/oxgc) {
4664 0 0       0 if ($string =~ /\G (\\\\) /oxgc) { $regexp .= $1; }
  0 0       0  
    0          
    0          
4665 0         0 elsif ($string =~ /\G (\\\/) /oxgc) { $regexp .= $1; } # splitqr// --> split qr//
4666 0         0 elsif ($string =~ /\G \/ ([cgimosxpadlunbB]*) /oxgc) { $e_string .= e_split($e.q{ qr}, '/','/',$regexp,$1); next E_STRING_LOOP; } # / / --> qr / /
  0         0  
4667 0         0 elsif ($string =~ /\G ($q_char) /oxgc) { $regexp .= $1; }
4668             }
4669 0         0 die __FILE__, ": Search pattern not terminated\n";
4670             }
4671             }
4672              
4673             # qq//
4674             elsif ($string =~ /\G \b (qq) \b /oxgc) {
4675 0         0 my $ope = $1;
4676 0 0       0 if ($string =~ /\G (\#) ((?:$qq_char)*?) (\#) /oxgc) { # qq# #
4677 0         0 $e_string .= e_qq($ope,$1,$3,$2);
4678             }
4679             else {
4680 0         0 my $e = '';
4681 0         0 while ($string !~ /\G \z/oxgc) {
4682 0 0       0 if ($string =~ /\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0       0  
    0          
    0          
    0          
    0          
4683 0         0 elsif ($string =~ /\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qq ( )
  0         0  
4684 0         0 elsif ($string =~ /\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qq { }
  0         0  
4685 0         0 elsif ($string =~ /\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qq [ ]
  0         0  
4686 0         0 elsif ($string =~ /\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qq < >
  0         0  
4687 0         0 elsif ($string =~ /\G (\S) ((?:$qq_char)*?) (\1) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qq * *
  0         0  
4688             }
4689 0         0 die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4690             }
4691             }
4692              
4693             # qx//
4694             elsif ($string =~ /\G \b (qx) \b /oxgc) {
4695 0         0 my $ope = $1;
4696 0 0       0 if ($string =~ /\G (\#) ((?:$qq_char)*?) (\#) /oxgc) { # qx# #
4697 0         0 $e_string .= e_qq($ope,$1,$3,$2);
4698             }
4699             else {
4700 0         0 my $e = '';
4701 0         0 while ($string !~ /\G \z/oxgc) {
4702 0 0       0 if ($string =~ /\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0       0  
    0          
    0          
    0          
    0          
    0          
4703 0         0 elsif ($string =~ /\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qx ( )
  0         0  
4704 0         0 elsif ($string =~ /\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qx { }
  0         0  
4705 0         0 elsif ($string =~ /\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qx [ ]
  0         0  
4706 0         0 elsif ($string =~ /\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qx < >
  0         0  
4707 0         0 elsif ($string =~ /\G (\') ((?:$qq_char)*?) (\') /oxgc) { $e_string .= $e . e_q ($ope,$1,$3,$2); next E_STRING_LOOP; } # qx ' '
  0         0  
4708 0         0 elsif ($string =~ /\G (\S) ((?:$qq_char)*?) (\1) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qx * *
  0         0  
4709             }
4710 0         0 die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4711             }
4712             }
4713              
4714             # q//
4715             elsif ($string =~ /\G \b (q) \b /oxgc) {
4716 0         0 my $ope = $1;
4717 0 0       0 if ($string =~ /\G (\#) ((?:\\\#|\\\\|$q_char)*?) (\#) /oxgc) { # q# #
4718 0         0 $e_string .= e_q($ope,$1,$3,$2);
4719             }
4720             else {
4721 0         0 my $e = '';
4722 0         0 while ($string !~ /\G \z/oxgc) {
4723 0 0       0 if ($string =~ /\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0       0  
    0          
    0          
    0          
    0          
4724 0         0 elsif ($string =~ /\G (\() ((?:\\\\|\\\)|\\\(|$q_paren)*?) (\)) /oxgc) { $e_string .= $e . e_q($ope,$1,$3,$2); next E_STRING_LOOP; } # q ( )
  0         0  
4725 0         0 elsif ($string =~ /\G (\{) ((?:\\\\|\\\}|\\\{|$q_brace)*?) (\}) /oxgc) { $e_string .= $e . e_q($ope,$1,$3,$2); next E_STRING_LOOP; } # q { }
  0         0  
4726 0         0 elsif ($string =~ /\G (\[) ((?:\\\\|\\\]|\\\[|$q_bracket)*?) (\]) /oxgc) { $e_string .= $e . e_q($ope,$1,$3,$2); next E_STRING_LOOP; } # q [ ]
  0         0  
4727 0         0 elsif ($string =~ /\G (\<) ((?:\\\\|\\\>|\\\<|$q_angle)*?) (\>) /oxgc) { $e_string .= $e . e_q($ope,$1,$3,$2); next E_STRING_LOOP; } # q < >
  0         0  
4728 0         0 elsif ($string =~ /\G (\S) ((?:\\\\|\\\1| $q_char)*?) (\1) /oxgc) { $e_string .= $e . e_q($ope,$1,$3,$2); next E_STRING_LOOP; } # q * *
  0         0  
4729             }
4730 0         0 die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4731             }
4732             }
4733              
4734             # ''
4735 0         0 elsif ($string =~ /\G (?
4736              
4737             # ""
4738 0         0 elsif ($string =~ /\G (\") ((?:$qq_char)*?) (\") /oxgc) { $e_string .= e_qq('',$1,$3,$2); }
4739              
4740             # ``
4741 0         0 elsif ($string =~ /\G (\`) ((?:$qq_char)*?) (\`) /oxgc) { $e_string .= e_qq('',$1,$3,$2); }
4742              
4743             # <<>> (a safer ARGV)
4744 0         0 elsif ($string =~ /\G ( <<>> ) /oxgc) { $e_string .= $1; }
4745              
4746             # <<= <=> <= < operator
4747 0         0 elsif ($string =~ /\G ( <<= | <=> | <= | < ) (?= (?>\s*) [A-Za-z_0-9'"`\$\@\&\*\(\+\-] )/oxgc) { $e_string .= $1; }
4748              
4749             #
4750 0         0 elsif ($string =~ /\G (<[\$]?[A-Za-z_][A-Za-z_0-9]*>) /oxgc) { $e_string .= $1; }
4751              
4752             # --- glob
4753             elsif ($string =~ /\G < ((?:$q_char)+?) > /oxgc) {
4754 0         0 $e_string .= 'Ekoi8r::glob("' . $1 . '")';
4755             }
4756              
4757             # << (bit shift) --- not here document
4758 0         0 elsif ($string =~ /\G ( << (?>\s*) ) (?= [0-9\$\@\&] ) /oxgc) { $slash = 'm//'; $e_string .= $1; }
  0         0  
4759              
4760             # <<'HEREDOC'
4761             elsif ($string =~ /\G ( << '([a-zA-Z_0-9]*)' ) /oxgc) {
4762 0         0 $slash = 'm//';
4763 0         0 my $here_quote = $1;
4764 0         0 my $delimiter = $2;
4765              
4766             # get here document
4767 0 0       0 if ($here_script eq '') {
4768 0         0 $here_script = CORE::substr $_, pos $_;
4769 0         0 $here_script =~ s/.*?\n//oxm;
4770             }
4771 0 0       0 if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4772 0         0 push @heredoc, $1 . qq{\n$delimiter\n};
4773 0         0 push @heredoc_delimiter, $delimiter;
4774             }
4775             else {
4776 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4777             }
4778 0         0 $e_string .= $here_quote;
4779             }
4780              
4781             # <<\HEREDOC
4782             elsif ($string =~ /\G ( << \\([a-zA-Z_0-9]+) ) /oxgc) {
4783 0         0 $slash = 'm//';
4784 0         0 my $here_quote = $1;
4785 0         0 my $delimiter = $2;
4786              
4787             # get here document
4788 0 0       0 if ($here_script eq '') {
4789 0         0 $here_script = CORE::substr $_, pos $_;
4790 0         0 $here_script =~ s/.*?\n//oxm;
4791             }
4792 0 0       0 if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4793 0         0 push @heredoc, $1 . qq{\n$delimiter\n};
4794 0         0 push @heredoc_delimiter, $delimiter;
4795             }
4796             else {
4797 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4798             }
4799 0         0 $e_string .= $here_quote;
4800             }
4801              
4802             # <<"HEREDOC"
4803             elsif ($string =~ /\G ( << "([a-zA-Z_0-9]*)" ) /oxgc) {
4804 0         0 $slash = 'm//';
4805 0         0 my $here_quote = $1;
4806 0         0 my $delimiter = $2;
4807              
4808             # get here document
4809 0 0       0 if ($here_script eq '') {
4810 0         0 $here_script = CORE::substr $_, pos $_;
4811 0         0 $here_script =~ s/.*?\n//oxm;
4812             }
4813 0 0       0 if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4814 0         0 push @heredoc, e_heredoc($1) . qq{\n$delimiter\n};
4815 0         0 push @heredoc_delimiter, $delimiter;
4816             }
4817             else {
4818 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4819             }
4820 0         0 $e_string .= $here_quote;
4821             }
4822              
4823             # <
4824             elsif ($string =~ /\G ( << ([a-zA-Z_0-9]+) ) /oxgc) {
4825 0         0 $slash = 'm//';
4826 0         0 my $here_quote = $1;
4827 0         0 my $delimiter = $2;
4828              
4829             # get here document
4830 0 0       0 if ($here_script eq '') {
4831 0         0 $here_script = CORE::substr $_, pos $_;
4832 0         0 $here_script =~ s/.*?\n//oxm;
4833             }
4834 0 0       0 if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4835 0         0 push @heredoc, e_heredoc($1) . qq{\n$delimiter\n};
4836 0         0 push @heredoc_delimiter, $delimiter;
4837             }
4838             else {
4839 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4840             }
4841 0         0 $e_string .= $here_quote;
4842             }
4843              
4844             # <<`HEREDOC`
4845             elsif ($string =~ /\G ( << `([a-zA-Z_0-9]*)` ) /oxgc) {
4846 0         0 $slash = 'm//';
4847 0         0 my $here_quote = $1;
4848 0         0 my $delimiter = $2;
4849              
4850             # get here document
4851 0 0       0 if ($here_script eq '') {
4852 0         0 $here_script = CORE::substr $_, pos $_;
4853 0         0 $here_script =~ s/.*?\n//oxm;
4854             }
4855 0 0       0 if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4856 0         0 push @heredoc, e_heredoc($1) . qq{\n$delimiter\n};
4857 0         0 push @heredoc_delimiter, $delimiter;
4858             }
4859             else {
4860 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4861             }
4862 0         0 $e_string .= $here_quote;
4863             }
4864              
4865             # any operator before div
4866             elsif ($string =~ /\G (
4867             -- | \+\+ |
4868             [\)\}\]]
4869              
4870 18         30 ) /oxgc) { $slash = 'div'; $e_string .= $1; }
  18         69  
4871              
4872             # yada-yada or triple-dot operator
4873             elsif ($string =~ /\G (
4874             \.\.\.
4875              
4876 0         0 ) /oxgc) { $slash = 'm//'; $e_string .= q{die('Unimplemented')}; }
  0         0  
4877              
4878             # any operator before m//
4879             elsif ($string =~ /\G ((?>
4880              
4881             !~~ | !~ | != | ! |
4882             %= | % |
4883             &&= | && | &= | &\.= | &\. | & |
4884             -= | -> | - |
4885             :(?>\s*)= |
4886             : |
4887             <<>> |
4888             <<= | <=> | <= | < |
4889             == | => | =~ | = |
4890             >>= | >> | >= | > |
4891             \*\*= | \*\* | \*= | \* |
4892             \+= | \+ |
4893             \.\. | \.= | \. |
4894             \/\/= | \/\/ |
4895             \/= | \/ |
4896             \? |
4897             \\ |
4898             \^= | \^\.= | \^\. | \^ |
4899             \b x= |
4900             \|\|= | \|\| | \|= | \|\.= | \|\. | \| |
4901             ~~ | ~\. | ~ |
4902             \b(?: and | cmp | eq | ge | gt | le | lt | ne | not | or | xor | x )\b |
4903             \b(?: print )\b |
4904              
4905             [,;\(\{\[]
4906              
4907 31         45 )) /oxgc) { $slash = 'm//'; $e_string .= $1; }
  31         138  
4908              
4909             # other any character
4910 131         447 elsif ($string =~ /\G ($q_char) /oxgc) { $e_string .= $1; }
4911              
4912             # system error
4913             else {
4914 0         0 die __FILE__, ": Oops, this shouldn't happen!\n";
4915             }
4916             }
4917              
4918 17         78 return $e_string;
4919             }
4920              
4921             #
4922             # character class
4923             #
4924             sub character_class {
4925 1914     1914 0 2511 my($char,$modifier) = @_;
4926              
4927 1914 100       2689 if ($char eq '.') {
4928 52 100       94 if ($modifier =~ /s/) {
4929 17         37 return '${Ekoi8r::dot_s}';
4930             }
4931             else {
4932 35         76 return '${Ekoi8r::dot}';
4933             }
4934             }
4935             else {
4936 1862         3006 return Ekoi8r::classic_character_class($char);
4937             }
4938             }
4939              
4940             #
4941             # escape capture ($1, $2, $3, ...)
4942             #
4943             sub e_capture {
4944              
4945 212     212 0 921 return join '', '${', $_[0], '}';
4946             }
4947              
4948             #
4949             # escape transliteration (tr/// or y///)
4950             #
4951             sub e_tr {
4952 3     3 0 7 my($variable,$charclass,$e,$charclass2,$modifier) = @_;
4953 3         3 my $e_tr = '';
4954 3   50     5 $modifier ||= '';
4955              
4956 3         5 $slash = 'div';
4957              
4958             # quote character class 1
4959 3         6 $charclass = q_tr($charclass);
4960              
4961             # quote character class 2
4962 3         4 $charclass2 = q_tr($charclass2);
4963              
4964             # /b /B modifier
4965 3 50       8 if ($modifier =~ tr/bB//d) {
4966 0 0       0 if ($variable eq '') {
4967 0         0 $e_tr = qq{tr$charclass$e$charclass2$modifier};
4968             }
4969             else {
4970 0         0 $e_tr = qq{$variable${bind_operator}tr$charclass$e$charclass2$modifier};
4971             }
4972             }
4973             else {
4974 3 100       5 if ($variable eq '') {
4975 2         6 $e_tr = qq{Ekoi8r::tr(\$_,' =~ ',$charclass,$e$charclass2,'$modifier')};
4976             }
4977             else {
4978 1         4 $e_tr = qq{Ekoi8r::tr($variable,'$bind_operator',$charclass,$e$charclass2,'$modifier')};
4979             }
4980             }
4981              
4982             # clear tr/// variable
4983 3         3 $tr_variable = '';
4984 3         4 $bind_operator = '';
4985              
4986 3         13 return $e_tr;
4987             }
4988              
4989             #
4990             # quote for escape transliteration (tr/// or y///)
4991             #
4992             sub q_tr {
4993 6     6 0 6 my($charclass) = @_;
4994              
4995             # quote character class
4996 6 50       9 if ($charclass !~ /'/oxms) {
    0          
    0          
    0          
    0          
    0          
4997 6         9 return e_q('', "'", "'", $charclass); # --> q' '
4998             }
4999             elsif ($charclass !~ /\//oxms) {
5000 0         0 return e_q('q', '/', '/', $charclass); # --> q/ /
5001             }
5002             elsif ($charclass !~ /\#/oxms) {
5003 0         0 return e_q('q', '#', '#', $charclass); # --> q# #
5004             }
5005             elsif ($charclass !~ /[\<\>]/oxms) {
5006 0         0 return e_q('q', '<', '>', $charclass); # --> q< >
5007             }
5008             elsif ($charclass !~ /[\(\)]/oxms) {
5009 0         0 return e_q('q', '(', ')', $charclass); # --> q( )
5010             }
5011             elsif ($charclass !~ /[\{\}]/oxms) {
5012 0         0 return e_q('q', '{', '}', $charclass); # --> q{ }
5013             }
5014             else {
5015 0         0 for my $char (qw( ! " $ % & * + . : = ? @ ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
5016 0 0       0 if ($charclass !~ /\Q$char\E/xms) {
5017 0         0 return e_q('q', $char, $char, $charclass);
5018             }
5019             }
5020             }
5021              
5022 0         0 return e_q('q', '{', '}', $charclass);
5023             }
5024              
5025             #
5026             # escape q string (q//, '')
5027             #
5028             sub e_q {
5029 1092     1092 0 2092 my($ope,$delimiter,$end_delimiter,$string) = @_;
5030              
5031 1092         1325 $slash = 'div';
5032              
5033 1092         5862 return join '', $ope, $delimiter, $string, $end_delimiter;
5034             }
5035              
5036             #
5037             # escape qq string (qq//, "", qx//, ``)
5038             #
5039             sub e_qq {
5040 3951     3951 0 7093 my($ope,$delimiter,$end_delimiter,$string) = @_;
5041              
5042 3951         4237 $slash = 'div';
5043              
5044 3951         3489 my $left_e = 0;
5045 3951         3217 my $right_e = 0;
5046              
5047             # split regexp
5048 3951         156863 my @char = $string =~ /\G((?>
5049             [^\\\$] |
5050             \\x\{ (?>[0-9A-Fa-f]+) \} |
5051             \\o\{ (?>[0-7]+) \} |
5052             \\N\{ (?>[^0-9\}][^\}]*) \} |
5053             \\ $q_char |
5054             \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} |
5055             \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} |
5056             \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} |
5057             \$ (?>\s* [0-9]+) |
5058             \$ (?>\s*) \{ (?>\s* [0-9]+ \s*) \} |
5059             \$ \$ (?![\w\{]) |
5060             \$ (?>\s*) \$ (?>\s*) $qq_variable |
5061             $q_char
5062             ))/oxmsg;
5063              
5064 3951         14725 for (my $i=0; $i <= $#char; $i++) {
5065              
5066             # "\L\u" --> "\u\L"
5067 111623 50 33     459762 if (($char[$i] eq '\L') and ($char[$i+1] eq '\u')) {
    50 33        
    100          
    100          
    50          
5068 0         0 @char[$i,$i+1] = @char[$i+1,$i];
5069             }
5070              
5071             # "\U\l" --> "\l\U"
5072             elsif (($char[$i] eq '\U') and ($char[$i+1] eq '\l')) {
5073 0         0 @char[$i,$i+1] = @char[$i+1,$i];
5074             }
5075              
5076             # octal escape sequence
5077             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
5078 1         3 $char[$i] = Ekoi8r::octchr($1);
5079             }
5080              
5081             # hexadecimal escape sequence
5082             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
5083 1         5 $char[$i] = Ekoi8r::hexchr($1);
5084             }
5085              
5086             # \N{CHARNAME} --> N{CHARNAME}
5087             elsif ($char[$i] =~ /\A \\ ( N\{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
5088 0         0 $char[$i] = $1;
5089             }
5090              
5091 111623 100       1255468 if (0) {
    50          
    50          
    50          
    50          
    100          
    50          
    100          
    50          
    50          
    100          
    50          
    50          
    100          
    50          
    50          
    50          
    50          
    100          
    100          
    100          
    50          
    50          
5092             }
5093              
5094             # \F
5095             #
5096             # P.69 Table 2-6. Translation escapes
5097             # in Chapter 2: Bits and Pieces
5098             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
5099             # (and so on)
5100              
5101             # \u \l \U \L \F \Q \E
5102 0         0 elsif ($char[$i] =~ /\A ([<>]) \z/oxms) {
5103 484 50       1213 if ($right_e < $left_e) {
5104 0         0 $char[$i] = '\\' . $char[$i];
5105             }
5106             }
5107             elsif ($char[$i] eq '\u') {
5108              
5109             # "STRING @{[ LIST EXPR ]} MORE STRING"
5110              
5111             # P.257 Other Tricks You Can Do with Hard References
5112             # in Chapter 8: References
5113             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
5114              
5115             # P.353 Other Tricks You Can Do with Hard References
5116             # in Chapter 8: References
5117             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
5118              
5119             # (and so on)
5120              
5121 0         0 $char[$i] = '@{[Ekoi8r::ucfirst qq<';
5122 0         0 $left_e++;
5123             }
5124             elsif ($char[$i] eq '\l') {
5125 0         0 $char[$i] = '@{[Ekoi8r::lcfirst qq<';
5126 0         0 $left_e++;
5127             }
5128             elsif ($char[$i] eq '\U') {
5129 0         0 $char[$i] = '@{[Ekoi8r::uc qq<';
5130 0         0 $left_e++;
5131             }
5132             elsif ($char[$i] eq '\L') {
5133 0         0 $char[$i] = '@{[Ekoi8r::lc qq<';
5134 0         0 $left_e++;
5135             }
5136             elsif ($char[$i] eq '\F') {
5137 24         29 $char[$i] = '@{[Ekoi8r::fc qq<';
5138 24         44 $left_e++;
5139             }
5140             elsif ($char[$i] eq '\Q') {
5141 0         0 $char[$i] = '@{[CORE::quotemeta qq<';
5142 0         0 $left_e++;
5143             }
5144             elsif ($char[$i] eq '\E') {
5145 24 50       34 if ($right_e < $left_e) {
5146 24         32 $char[$i] = '>]}';
5147 24         46 $right_e++;
5148             }
5149             else {
5150 0         0 $char[$i] = '';
5151             }
5152             }
5153             elsif ($char[$i] eq '\Q') {
5154 0         0 while (1) {
5155 0 0       0 if (++$i > $#char) {
5156 0         0 last;
5157             }
5158 0 0       0 if ($char[$i] eq '\E') {
5159 0         0 last;
5160             }
5161             }
5162             }
5163             elsif ($char[$i] eq '\E') {
5164             }
5165              
5166             # $0 --> $0
5167             elsif ($char[$i] =~ /\A \$ 0 \z/oxms) {
5168             }
5169             elsif ($char[$i] =~ /\A \$ \{ (?>\s*) 0 (?>\s*) \} \z/oxms) {
5170             }
5171              
5172             # $$ --> $$
5173             elsif ($char[$i] =~ /\A \$\$ \z/oxms) {
5174             }
5175              
5176             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
5177             # $1, $2, $3 --> $1, $2, $3 otherwise
5178             elsif ($char[$i] =~ /\A \$ ((?>[1-9][0-9]*)) \z/oxms) {
5179 205         395 $char[$i] = e_capture($1);
5180             }
5181             elsif ($char[$i] =~ /\A \$ \{ (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} \z/oxms) {
5182 0         0 $char[$i] = e_capture($1);
5183             }
5184              
5185             # $$foo[ ... ] --> $ $foo->[ ... ]
5186             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \[ (?:$qq_bracket)*? \] ) \z/oxms) {
5187 0         0 $char[$i] = e_capture($1.'->'.$2);
5188             }
5189              
5190             # $$foo{ ... } --> $ $foo->{ ... }
5191             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \{ (?:$qq_brace)*? \} ) \z/oxms) {
5192 0         0 $char[$i] = e_capture($1.'->'.$2);
5193             }
5194              
5195             # $$foo
5196             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) \z/oxms) {
5197 0         0 $char[$i] = e_capture($1);
5198             }
5199              
5200             # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Ekoi8r::PREMATCH()
5201             elsif ($char[$i] =~ /\A ( \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} ) \z/oxmsgc) {
5202 44         132 $char[$i] = '@{[Ekoi8r::PREMATCH()]}';
5203             }
5204              
5205             # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Ekoi8r::MATCH()
5206             elsif ($char[$i] =~ /\A ( \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} ) \z/oxmsgc) {
5207 45         127 $char[$i] = '@{[Ekoi8r::MATCH()]}';
5208             }
5209              
5210             # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Ekoi8r::POSTMATCH()
5211             elsif ($char[$i] =~ /\A ( \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} ) \z/oxmsgc) {
5212 33         106 $char[$i] = '@{[Ekoi8r::POSTMATCH()]}';
5213             }
5214              
5215             # ${ foo } --> ${ foo }
5216             elsif ($char[$i] =~ /\A \$ (?>\s*) \{ (?> \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* ) \} \z/oxms) {
5217             }
5218              
5219             # ${ ... }
5220             elsif ($char[$i] =~ /\A \$ (?>\s*) \{ ( .+ ) \} \z/oxms) {
5221 0         0 $char[$i] = e_capture($1);
5222             }
5223             }
5224              
5225             # return string
5226 3951 50       7315 if ($left_e > $right_e) {
5227 0         0 return join '', $ope, $delimiter, @char, '>]}' x ($left_e - $right_e), $end_delimiter;
5228             }
5229 3951         38431 return join '', $ope, $delimiter, @char, $end_delimiter;
5230             }
5231              
5232             #
5233             # escape qw string (qw//)
5234             #
5235             sub e_qw {
5236 16     16 0 111 my($ope,$delimiter,$end_delimiter,$string) = @_;
5237              
5238 16         28 $slash = 'div';
5239              
5240             # choice again delimiter
5241 16         241 my %octet = map {$_ => 1} ($string =~ /\G ([\x00-\xFF]) /oxmsg);
  483         640  
5242 16 50       109 if (not $octet{$end_delimiter}) {
    0          
    0          
    0          
    0          
5243 16         141 return join '', $ope, $delimiter, $string, $end_delimiter;
5244             }
5245             elsif (not $octet{')'}) {
5246 0         0 return join '', $ope, '(', $string, ')';
5247             }
5248             elsif (not $octet{'}'}) {
5249 0         0 return join '', $ope, '{', $string, '}';
5250             }
5251             elsif (not $octet{']'}) {
5252 0         0 return join '', $ope, '[', $string, ']';
5253             }
5254             elsif (not $octet{'>'}) {
5255 0         0 return join '', $ope, '<', $string, '>';
5256             }
5257             else {
5258 0         0 for my $char (qw( ! " $ % & * + - . / : = ? @ ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
5259 0 0       0 if (not $octet{$char}) {
5260 0         0 return join '', $ope, $char, $string, $char;
5261             }
5262             }
5263             }
5264              
5265             # qw/AAA BBB C'CC/ --> ('AAA', 'BBB', 'C\'CC')
5266 0         0 my @string = CORE::split(/\s+/, $string);
5267 0         0 for my $string (@string) {
5268 0         0 my @octet = $string =~ /\G ([\x00-\xFF]) /oxmsg;
5269 0         0 for my $octet (@octet) {
5270 0 0       0 if ($octet =~ /\A (['\\]) \z/oxms) {
5271 0         0 $octet = '\\' . $1;
5272             }
5273             }
5274 0         0 $string = join '', @octet;
5275             }
5276 0         0 return join '', '(', (join ', ', map { "'$_'" } @string), ')';
  0         0  
5277             }
5278              
5279             #
5280             # escape here document (<<"HEREDOC", <
5281             #
5282             sub e_heredoc {
5283 78     78 0 311 my($string) = @_;
5284              
5285 78         97 $slash = 'm//';
5286              
5287 78         291 my $metachar = qr/[\@\\|]/oxms; # '|' is for <<`HEREDOC`
5288              
5289 78         96 my $left_e = 0;
5290 78         98 my $right_e = 0;
5291              
5292             # split regexp
5293 78         8377 my @char = $string =~ /\G((?>
5294             [^\\\$] |
5295             \\x\{ (?>[0-9A-Fa-f]+) \} |
5296             \\o\{ (?>[0-7]+) \} |
5297             \\N\{ (?>[^0-9\}][^\}]*) \} |
5298             \\ $q_char |
5299             \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} |
5300             \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} |
5301             \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} |
5302             \$ (?>\s* [0-9]+) |
5303             \$ (?>\s*) \{ (?>\s* [0-9]+ \s*) \} |
5304             \$ \$ (?![\w\{]) |
5305             \$ (?>\s*) \$ (?>\s*) $qq_variable |
5306             $q_char
5307             ))/oxmsg;
5308              
5309 78         482 for (my $i=0; $i <= $#char; $i++) {
5310              
5311             # "\L\u" --> "\u\L"
5312 2856 50 33     11010 if (($char[$i] eq '\L') and ($char[$i+1] eq '\u')) {
    50 33        
    100          
    100          
    50          
5313 0         0 @char[$i,$i+1] = @char[$i+1,$i];
5314             }
5315              
5316             # "\U\l" --> "\l\U"
5317             elsif (($char[$i] eq '\U') and ($char[$i+1] eq '\l')) {
5318 0         0 @char[$i,$i+1] = @char[$i+1,$i];
5319             }
5320              
5321             # octal escape sequence
5322             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
5323 1         3 $char[$i] = Ekoi8r::octchr($1);
5324             }
5325              
5326             # hexadecimal escape sequence
5327             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
5328 1         4 $char[$i] = Ekoi8r::hexchr($1);
5329             }
5330              
5331             # \N{CHARNAME} --> N{CHARNAME}
5332             elsif ($char[$i] =~ /\A \\ ( N\{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
5333 0         0 $char[$i] = $1;
5334             }
5335              
5336 2856 50       32607 if (0) {
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    100          
    100          
    100          
    50          
    50          
5337             }
5338              
5339             # \u \l \U \L \F \Q \E
5340 0         0 elsif ($char[$i] =~ /\A ([<>]) \z/oxms) {
5341 0 0       0 if ($right_e < $left_e) {
5342 0         0 $char[$i] = '\\' . $char[$i];
5343             }
5344             }
5345             elsif ($char[$i] eq '\u') {
5346 0         0 $char[$i] = '@{[Ekoi8r::ucfirst qq<';
5347 0         0 $left_e++;
5348             }
5349             elsif ($char[$i] eq '\l') {
5350 0         0 $char[$i] = '@{[Ekoi8r::lcfirst qq<';
5351 0         0 $left_e++;
5352             }
5353             elsif ($char[$i] eq '\U') {
5354 0         0 $char[$i] = '@{[Ekoi8r::uc qq<';
5355 0         0 $left_e++;
5356             }
5357             elsif ($char[$i] eq '\L') {
5358 0         0 $char[$i] = '@{[Ekoi8r::lc qq<';
5359 0         0 $left_e++;
5360             }
5361             elsif ($char[$i] eq '\F') {
5362 0         0 $char[$i] = '@{[Ekoi8r::fc qq<';
5363 0         0 $left_e++;
5364             }
5365             elsif ($char[$i] eq '\Q') {
5366 0         0 $char[$i] = '@{[CORE::quotemeta qq<';
5367 0         0 $left_e++;
5368             }
5369             elsif ($char[$i] eq '\E') {
5370 0 0       0 if ($right_e < $left_e) {
5371 0         0 $char[$i] = '>]}';
5372 0         0 $right_e++;
5373             }
5374             else {
5375 0         0 $char[$i] = '';
5376             }
5377             }
5378             elsif ($char[$i] eq '\Q') {
5379 0         0 while (1) {
5380 0 0       0 if (++$i > $#char) {
5381 0         0 last;
5382             }
5383 0 0       0 if ($char[$i] eq '\E') {
5384 0         0 last;
5385             }
5386             }
5387             }
5388             elsif ($char[$i] eq '\E') {
5389             }
5390              
5391             # $0 --> $0
5392             elsif ($char[$i] =~ /\A \$ 0 \z/oxms) {
5393             }
5394             elsif ($char[$i] =~ /\A \$ \{ (?>\s*) 0 (?>\s*) \} \z/oxms) {
5395             }
5396              
5397             # $$ --> $$
5398             elsif ($char[$i] =~ /\A \$\$ \z/oxms) {
5399             }
5400              
5401             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
5402             # $1, $2, $3 --> $1, $2, $3 otherwise
5403             elsif ($char[$i] =~ /\A \$ ((?>[1-9][0-9]*)) \z/oxms) {
5404 0         0 $char[$i] = e_capture($1);
5405             }
5406             elsif ($char[$i] =~ /\A \$ \{ (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} \z/oxms) {
5407 0         0 $char[$i] = e_capture($1);
5408             }
5409              
5410             # $$foo[ ... ] --> $ $foo->[ ... ]
5411             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \[ (?:$qq_bracket)*? \] ) \z/oxms) {
5412 0         0 $char[$i] = e_capture($1.'->'.$2);
5413             }
5414              
5415             # $$foo{ ... } --> $ $foo->{ ... }
5416             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \{ (?:$qq_brace)*? \} ) \z/oxms) {
5417 0         0 $char[$i] = e_capture($1.'->'.$2);
5418             }
5419              
5420             # $$foo
5421             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) \z/oxms) {
5422 0         0 $char[$i] = e_capture($1);
5423             }
5424              
5425             # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Ekoi8r::PREMATCH()
5426             elsif ($char[$i] =~ /\A ( \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} ) \z/oxmsgc) {
5427 8         50 $char[$i] = '@{[Ekoi8r::PREMATCH()]}';
5428             }
5429              
5430             # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Ekoi8r::MATCH()
5431             elsif ($char[$i] =~ /\A ( \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} ) \z/oxmsgc) {
5432 8         44 $char[$i] = '@{[Ekoi8r::MATCH()]}';
5433             }
5434              
5435             # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Ekoi8r::POSTMATCH()
5436             elsif ($char[$i] =~ /\A ( \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} ) \z/oxmsgc) {
5437 6         32 $char[$i] = '@{[Ekoi8r::POSTMATCH()]}';
5438             }
5439              
5440             # ${ foo } --> ${ foo }
5441             elsif ($char[$i] =~ /\A \$ (?>\s*) \{ (?> \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* ) \} \z/oxms) {
5442             }
5443              
5444             # ${ ... }
5445             elsif ($char[$i] =~ /\A \$ (?>\s*) \{ ( .+ ) \} \z/oxms) {
5446 0         0 $char[$i] = e_capture($1);
5447             }
5448             }
5449              
5450             # return string
5451 78 50       188 if ($left_e > $right_e) {
5452 0         0 return join '', @char, '>]}' x ($left_e - $right_e);
5453             }
5454 78         797 return join '', @char;
5455             }
5456              
5457             #
5458             # escape regexp (m//, qr//)
5459             #
5460             sub e_qr {
5461 651     651 0 1822 my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
5462 651   100     2261 $modifier ||= '';
5463              
5464 651         1015 $modifier =~ tr/p//d;
5465 651 50       1686 if ($modifier =~ /([adlu])/oxms) {
5466 0         0 my $line = 0;
5467 0         0 for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
5468 0 0       0 if ($filename ne __FILE__) {
5469 0         0 $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
5470 0         0 last;
5471             }
5472             }
5473 0         0 die qq{Unsupported modifier "$1" used at line $line.\n};
5474             }
5475              
5476 651         841 $slash = 'div';
5477              
5478             # literal null string pattern
5479 651 100       2125 if ($string eq '') {
    100          
5480 8         8 $modifier =~ tr/bB//d;
5481 8         8 $modifier =~ tr/i//d;
5482 8         40 return join '', $ope, $delimiter, $end_delimiter, $modifier;
5483             }
5484              
5485             # /b /B modifier
5486             elsif ($modifier =~ tr/bB//d) {
5487              
5488             # choice again delimiter
5489 2 50       14 if ($delimiter =~ / [\@:] /oxms) {
5490 0         0 my @char = $string =~ /\G ([\x00-\xFF]) /oxmsg;
5491 0         0 my %octet = map {$_ => 1} @char;
  0         0  
5492 0 0       0 if (not $octet{')'}) {
    0          
    0          
    0          
5493 0         0 $delimiter = '(';
5494 0         0 $end_delimiter = ')';
5495             }
5496             elsif (not $octet{'}'}) {
5497 0         0 $delimiter = '{';
5498 0         0 $end_delimiter = '}';
5499             }
5500             elsif (not $octet{']'}) {
5501 0         0 $delimiter = '[';
5502 0         0 $end_delimiter = ']';
5503             }
5504             elsif (not $octet{'>'}) {
5505 0         0 $delimiter = '<';
5506 0         0 $end_delimiter = '>';
5507             }
5508             else {
5509 0         0 for my $char (qw( ! " $ % & * + - . / = ? ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
5510 0 0       0 if (not $octet{$char}) {
5511 0         0 $delimiter = $char;
5512 0         0 $end_delimiter = $char;
5513 0         0 last;
5514             }
5515             }
5516             }
5517             }
5518              
5519 2 50 33     12 if (($ope =~ /\A m? \z/oxms) and ($delimiter eq '?')) {
5520 0         0 return join '', $ope, $delimiter, $string, $matched, $end_delimiter, $modifier;
5521             }
5522             else {
5523 2         11 return join '', $ope, $delimiter, '(?:', $string, ')', $matched, $end_delimiter, $modifier;
5524             }
5525             }
5526              
5527 641 100       1441 my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
5528 641         2498 my $metachar = qr/[\@\\|[\]{^]/oxms;
5529              
5530             # split regexp
5531 641         72744 my @char = $string =~ /\G((?>
5532             [^\\\$\@\[\(] |
5533             \\x (?>[0-9A-Fa-f]{1,2}) |
5534             \\ (?>[0-7]{2,3}) |
5535             \\c [\x40-\x5F] |
5536             \\x\{ (?>[0-9A-Fa-f]+) \} |
5537             \\o\{ (?>[0-7]+) \} |
5538             \\[bBNpP]\{ (?>[^0-9\}][^\}]*) \} |
5539             \\ $q_char |
5540             \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} |
5541             \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} |
5542             \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} |
5543             [\$\@] $qq_variable |
5544             \$ (?>\s* [0-9]+) |
5545             \$ (?>\s*) \{ (?>\s* [0-9]+ \s*) \} |
5546             \$ \$ (?![\w\{]) |
5547             \$ (?>\s*) \$ (?>\s*) $qq_variable |
5548             \[\^ |
5549             \[\: (?>[a-z]+) :\] |
5550             \[\:\^ (?>[a-z]+) :\] |
5551             \(\? |
5552             $q_char
5553             ))/oxmsg;
5554              
5555             # choice again delimiter
5556 641 50       3279 if ($delimiter =~ / [\@:] /oxms) {
5557 0         0 my %octet = map {$_ => 1} @char;
  0         0  
5558 0 0       0 if (not $octet{')'}) {
    0          
    0          
    0          
5559 0         0 $delimiter = '(';
5560 0         0 $end_delimiter = ')';
5561             }
5562             elsif (not $octet{'}'}) {
5563 0         0 $delimiter = '{';
5564 0         0 $end_delimiter = '}';
5565             }
5566             elsif (not $octet{']'}) {
5567 0         0 $delimiter = '[';
5568 0         0 $end_delimiter = ']';
5569             }
5570             elsif (not $octet{'>'}) {
5571 0         0 $delimiter = '<';
5572 0         0 $end_delimiter = '>';
5573             }
5574             else {
5575 0         0 for my $char (qw( ! " $ % & * + - . / = ? ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
5576 0 0       0 if (not $octet{$char}) {
5577 0         0 $delimiter = $char;
5578 0         0 $end_delimiter = $char;
5579 0         0 last;
5580             }
5581             }
5582             }
5583             }
5584              
5585 641         795 my $left_e = 0;
5586 641         681 my $right_e = 0;
5587 641         2085 for (my $i=0; $i <= $#char; $i++) {
5588              
5589             # "\L\u" --> "\u\L"
5590 1867 50 66     11894 if (($char[$i] eq '\L') and ($char[$i+1] eq '\u')) {
    50 66        
    100          
    100          
    100          
    100          
5591 0         0 @char[$i,$i+1] = @char[$i+1,$i];
5592             }
5593              
5594             # "\U\l" --> "\l\U"
5595             elsif (($char[$i] eq '\U') and ($char[$i+1] eq '\l')) {
5596 0         0 @char[$i,$i+1] = @char[$i+1,$i];
5597             }
5598              
5599             # octal escape sequence
5600             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
5601 1         3 $char[$i] = Ekoi8r::octchr($1);
5602             }
5603              
5604             # hexadecimal escape sequence
5605             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
5606 1         4 $char[$i] = Ekoi8r::hexchr($1);
5607             }
5608              
5609             # \b{...} --> b\{...}
5610             # \B{...} --> B\{...}
5611             # \N{CHARNAME} --> N\{CHARNAME}
5612             # \p{PROPERTY} --> p\{PROPERTY}
5613             # \P{PROPERTY} --> P\{PROPERTY}
5614             elsif ($char[$i] =~ /\A \\ ([bBNpP]) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
5615 6         18 $char[$i] = $1 . '\\' . $2;
5616             }
5617              
5618             # \p, \P, \X --> p, P, X
5619             elsif ($char[$i] =~ /\A \\ ( [pPX] ) \z/oxms) {
5620 4         10 $char[$i] = $1;
5621             }
5622              
5623 1867 100 100     5978 if (0) {
    100 100        
    100 100        
    100          
    100          
    100          
    50          
    50          
    100          
    100          
    100          
    100          
    100          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    100          
    100          
    100          
    50          
    50          
    100          
    100          
5624             }
5625              
5626             # join separated multiple-octet
5627 0         0 elsif ($char[$i] =~ /\A (?: \\ [0-7]{2,3} | \\x [0-9A-Fa-f]{1,2}) \z/oxms) {
5628 6 50 33     122 if ( ($i+3 <= $#char) and (grep(/\A (?: \\ [0-7]{2,3} | \\x [0-9A-Fa-f]{1,2}) \z/oxms, @char[$i+1..$i+3]) == 3) and (CORE::eval(sprintf '"%s%s%s%s"', @char[$i..$i+3]) =~ /\A $q_char \z/oxms)) {
    50 33        
    50 33        
      33        
      66        
      33        
5629 0         0 $char[$i] .= join '', splice @char, $i+1, 3;
5630             }
5631             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)) {
5632 0         0 $char[$i] .= join '', splice @char, $i+1, 2;
5633             }
5634             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)) {
5635 0         0 $char[$i] .= join '', splice @char, $i+1, 1;
5636             }
5637             }
5638              
5639             # open character class [...]
5640             elsif ($char[$i] eq '[') {
5641 328         395 my $left = $i;
5642              
5643             # [] make die "Unmatched [] in regexp ...\n"
5644             # (and so on)
5645              
5646 328 100       928 if ($char[$i+1] eq ']') {
5647 3         6 $i++;
5648             }
5649              
5650 328         339 while (1) {
5651 1379 50       1960 if (++$i > $#char) {
5652 0         0 die __FILE__, ": Unmatched [] in regexp\n";
5653             }
5654 1379 100       2259 if ($char[$i] eq ']') {
5655 328         322 my $right = $i;
5656              
5657             # [...]
5658 328 100       1934 if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
5659 30         72 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);
  90         141  
5660             }
5661             else {
5662 298         1243 splice @char, $left, $right-$left+1, Ekoi8r::charlist_qr(@char[$left+1..$right-1], $modifier);
5663             }
5664              
5665 328         508 $i = $left;
5666 328         980 last;
5667             }
5668             }
5669             }
5670              
5671             # open character class [^...]
5672             elsif ($char[$i] eq '[^') {
5673 74         78 my $left = $i;
5674              
5675             # [^] make die "Unmatched [] in regexp ...\n"
5676             # (and so on)
5677              
5678 74 100       185 if ($char[$i+1] eq ']') {
5679 4         9 $i++;
5680             }
5681              
5682 74         68 while (1) {
5683 272 50       380 if (++$i > $#char) {
5684 0         0 die __FILE__, ": Unmatched [] in regexp\n";
5685             }
5686 272 100       470 if ($char[$i] eq ']') {
5687 74         87 my $right = $i;
5688              
5689             # [^...]
5690 74 100       406 if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
5691 30         50 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);
  90         118  
5692             }
5693             else {
5694 44         215 splice @char, $left, $right-$left+1, Ekoi8r::charlist_not_qr(@char[$left+1..$right-1], $modifier);
5695             }
5696              
5697 74         103 $i = $left;
5698 74         293 last;
5699             }
5700             }
5701             }
5702              
5703             # rewrite character class or escape character
5704             elsif (my $char = character_class($char[$i],$modifier)) {
5705 139         574 $char[$i] = $char;
5706             }
5707              
5708             # /i modifier
5709             elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Ekoi8r::uc($char[$i]) ne Ekoi8r::fc($char[$i]))) {
5710 20 50       31 if (CORE::length(Ekoi8r::fc($char[$i])) == 1) {
5711 20         29 $char[$i] = '[' . Ekoi8r::uc($char[$i]) . Ekoi8r::fc($char[$i]) . ']';
5712             }
5713             else {
5714 0         0 $char[$i] = '(?:' . Ekoi8r::uc($char[$i]) . '|' . Ekoi8r::fc($char[$i]) . ')';
5715             }
5716             }
5717              
5718             # \u \l \U \L \F \Q \E
5719             elsif ($char[$i] =~ /\A [<>] \z/oxms) {
5720 1 50       17 if ($right_e < $left_e) {
5721 0         0 $char[$i] = '\\' . $char[$i];
5722             }
5723             }
5724             elsif ($char[$i] eq '\u') {
5725 0         0 $char[$i] = '@{[Ekoi8r::ucfirst qq<';
5726 0         0 $left_e++;
5727             }
5728             elsif ($char[$i] eq '\l') {
5729 0         0 $char[$i] = '@{[Ekoi8r::lcfirst qq<';
5730 0         0 $left_e++;
5731             }
5732             elsif ($char[$i] eq '\U') {
5733 1         3 $char[$i] = '@{[Ekoi8r::uc qq<';
5734 1         8 $left_e++;
5735             }
5736             elsif ($char[$i] eq '\L') {
5737 1         3 $char[$i] = '@{[Ekoi8r::lc qq<';
5738 1         7 $left_e++;
5739             }
5740             elsif ($char[$i] eq '\F') {
5741 18         22 $char[$i] = '@{[Ekoi8r::fc qq<';
5742 18         97 $left_e++;
5743             }
5744             elsif ($char[$i] eq '\Q') {
5745 1         3 $char[$i] = '@{[CORE::quotemeta qq<';
5746 1         7 $left_e++;
5747             }
5748             elsif ($char[$i] eq '\E') {
5749 21 50       38 if ($right_e < $left_e) {
5750 21         23 $char[$i] = '>]}';
5751 21         92 $right_e++;
5752             }
5753             else {
5754 0         0 $char[$i] = '';
5755             }
5756             }
5757             elsif ($char[$i] eq '\Q') {
5758 0         0 while (1) {
5759 0 0       0 if (++$i > $#char) {
5760 0         0 last;
5761             }
5762 0 0       0 if ($char[$i] eq '\E') {
5763 0         0 last;
5764             }
5765             }
5766             }
5767             elsif ($char[$i] eq '\E') {
5768             }
5769              
5770             # $0 --> $0
5771             elsif ($char[$i] =~ /\A \$ 0 \z/oxms) {
5772 0 0       0 if ($ignorecase) {
5773 0         0 $char[$i] = '@{[Ekoi8r::ignorecase(' . $char[$i] . ')]}';
5774             }
5775             }
5776             elsif ($char[$i] =~ /\A \$ \{ (?>\s*) 0 (?>\s*) \} \z/oxms) {
5777 0 0       0 if ($ignorecase) {
5778 0         0 $char[$i] = '@{[Ekoi8r::ignorecase(' . $char[$i] . ')]}';
5779             }
5780             }
5781              
5782             # $$ --> $$
5783             elsif ($char[$i] =~ /\A \$\$ \z/oxms) {
5784             }
5785              
5786             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
5787             # $1, $2, $3 --> $1, $2, $3 otherwise
5788             elsif ($char[$i] =~ /\A \$ ((?>[1-9][0-9]*)) \z/oxms) {
5789 0         0 $char[$i] = e_capture($1);
5790 0 0       0 if ($ignorecase) {
5791 0         0 $char[$i] = '@{[Ekoi8r::ignorecase(' . $char[$i] . ')]}';
5792             }
5793             }
5794             elsif ($char[$i] =~ /\A \$ \{ (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} \z/oxms) {
5795 0         0 $char[$i] = e_capture($1);
5796 0 0       0 if ($ignorecase) {
5797 0         0 $char[$i] = '@{[Ekoi8r::ignorecase(' . $char[$i] . ')]}';
5798             }
5799             }
5800              
5801             # $$foo[ ... ] --> $ $foo->[ ... ]
5802             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \[ (?:$qq_bracket)*? \] ) \z/oxms) {
5803 0         0 $char[$i] = e_capture($1.'->'.$2);
5804 0 0       0 if ($ignorecase) {
5805 0         0 $char[$i] = '@{[Ekoi8r::ignorecase(' . $char[$i] . ')]}';
5806             }
5807             }
5808              
5809             # $$foo{ ... } --> $ $foo->{ ... }
5810             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \{ (?:$qq_brace)*? \} ) \z/oxms) {
5811 0         0 $char[$i] = e_capture($1.'->'.$2);
5812 0 0       0 if ($ignorecase) {
5813 0         0 $char[$i] = '@{[Ekoi8r::ignorecase(' . $char[$i] . ')]}';
5814             }
5815             }
5816              
5817             # $$foo
5818             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) \z/oxms) {
5819 0         0 $char[$i] = e_capture($1);
5820 0 0       0 if ($ignorecase) {
5821 0         0 $char[$i] = '@{[Ekoi8r::ignorecase(' . $char[$i] . ')]}';
5822             }
5823             }
5824              
5825             # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Ekoi8r::PREMATCH()
5826             elsif ($char[$i] =~ /\A ( \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} ) \z/oxmsgc) {
5827 8 50       24 if ($ignorecase) {
5828 0         0 $char[$i] = '@{[Ekoi8r::ignorecase(Ekoi8r::PREMATCH())]}';
5829             }
5830             else {
5831 8         48 $char[$i] = '@{[Ekoi8r::PREMATCH()]}';
5832             }
5833             }
5834              
5835             # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Ekoi8r::MATCH()
5836             elsif ($char[$i] =~ /\A ( \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} ) \z/oxmsgc) {
5837 8 50       20 if ($ignorecase) {
5838 0         0 $char[$i] = '@{[Ekoi8r::ignorecase(Ekoi8r::MATCH())]}';
5839             }
5840             else {
5841 8         43 $char[$i] = '@{[Ekoi8r::MATCH()]}';
5842             }
5843             }
5844              
5845             # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Ekoi8r::POSTMATCH()
5846             elsif ($char[$i] =~ /\A ( \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} ) \z/oxmsgc) {
5847 6 50       12 if ($ignorecase) {
5848 0         0 $char[$i] = '@{[Ekoi8r::ignorecase(Ekoi8r::POSTMATCH())]}';
5849             }
5850             else {
5851 6         25 $char[$i] = '@{[Ekoi8r::POSTMATCH()]}';
5852             }
5853             }
5854              
5855             # ${ foo }
5856             elsif ($char[$i] =~ /\A \$ (?>\s*) \{ ((?> \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* )) \} \z/oxms) {
5857 0 0       0 if ($ignorecase) {
5858 0         0 $char[$i] = '@{[Ekoi8r::ignorecase(' . $char[$i] . ')]}';
5859             }
5860             }
5861              
5862             # ${ ... }
5863             elsif ($char[$i] =~ /\A \$ (?>\s*) \{ ( .+ ) \} \z/oxms) {
5864 0         0 $char[$i] = e_capture($1);
5865 0 0       0 if ($ignorecase) {
5866 0         0 $char[$i] = '@{[Ekoi8r::ignorecase(' . $char[$i] . ')]}';
5867             }
5868             }
5869              
5870             # $scalar or @array
5871             elsif ($char[$i] =~ /\A [\$\@].+ /oxms) {
5872 21         51 $char[$i] = e_string($char[$i]);
5873 21 100       117 if ($ignorecase) {
5874 11         65 $char[$i] = '@{[Ekoi8r::ignorecase(' . $char[$i] . ')]}';
5875             }
5876             }
5877              
5878             # quote character before ? + * {
5879             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
5880 138 100 33     1278 if ($char[$i-1] =~ /\A (?:[\x00-\xFF]|\\[0-7]{2,3}|\\x[0-9-A-Fa-f]{1,2}) \z/oxms) {
    50          
5881             }
5882             elsif (($ope =~ /\A m? \z/oxms) and ($delimiter eq '?')) {
5883 0         0 my $char = $char[$i-1];
5884 0 0       0 if ($char[$i] eq '{') {
5885 0         0 die __FILE__, qq{: "MULTIBYTE{n}" should be "(MULTIBYTE){n}" in m?? (and shift \$1,\$2,\$3,...) ($char){n}\n};
5886             }
5887             else {
5888 0         0 die __FILE__, qq{: "MULTIBYTE$char[$i]" should be "(MULTIBYTE)$char[$i]" in m?? (and shift \$1,\$2,\$3,...) ($char)$char[$i]\n};
5889             }
5890             }
5891             else {
5892 127         898 $char[$i-1] = '(?:' . $char[$i-1] . ')';
5893             }
5894             }
5895             }
5896              
5897             # make regexp string
5898 641         920 $modifier =~ tr/i//d;
5899 641 50       1553 if ($left_e > $right_e) {
5900 0 0 0     0 if (($ope =~ /\A m? \z/oxms) and ($delimiter eq '?')) {
5901 0         0 return join '', $ope, $delimiter, $anchor, @char, '>]}' x ($left_e - $right_e), $matched, $end_delimiter, $modifier;
5902             }
5903             else {
5904 0         0 return join '', $ope, $delimiter, $anchor, '(?:', @char, '>]}' x ($left_e - $right_e), ')', $matched, $end_delimiter, $modifier;
5905             }
5906             }
5907 641 50 33     4033 if (($ope =~ /\A m? \z/oxms) and ($delimiter eq '?')) {
5908 0         0 return join '', $ope, $delimiter, $anchor, @char, $matched, $end_delimiter, $modifier;
5909             }
5910             else {
5911 641         5699 return join '', $ope, $delimiter, $anchor, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
5912             }
5913             }
5914              
5915             #
5916             # double quote stuff
5917             #
5918             sub qq_stuff {
5919 180     180 0 179 my($delimiter,$end_delimiter,$stuff) = @_;
5920              
5921             # scalar variable or array variable
5922 180 100       335 if ($stuff =~ /\A [\$\@] /oxms) {
5923 100         328 return $stuff;
5924             }
5925              
5926             # quote by delimiter
5927 80         159 my %octet = map {$_ => 1} ($stuff =~ /\G ([\x00-\xFF]) /oxmsg);
  80         230  
5928 80         191 for my $char (qw( ! " $ % & * + - . / : = ? @ ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
5929 80 50       122 next if $char eq $delimiter;
5930 80 50       99 next if $char eq $end_delimiter;
5931 80 50       132 if (not $octet{$char}) {
5932 80         407 return join '', 'qq', $char, $stuff, $char;
5933             }
5934             }
5935 0         0 return join '', 'qq', '<', $stuff, '>';
5936             }
5937              
5938             #
5939             # escape regexp (m'', qr'', and m''b, qr''b)
5940             #
5941             sub e_qr_q {
5942 10     10 0 27 my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
5943 10   50     36 $modifier ||= '';
5944              
5945 10         13 $modifier =~ tr/p//d;
5946 10 50       20 if ($modifier =~ /([adlu])/oxms) {
5947 0         0 my $line = 0;
5948 0         0 for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
5949 0 0       0 if ($filename ne __FILE__) {
5950 0         0 $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
5951 0         0 last;
5952             }
5953             }
5954 0         0 die qq{Unsupported modifier "$1" used at line $line.\n};
5955             }
5956              
5957 10         10 $slash = 'div';
5958              
5959             # literal null string pattern
5960 10 100       20 if ($string eq '') {
    50          
5961 8         8 $modifier =~ tr/bB//d;
5962 8         5 $modifier =~ tr/i//d;
5963 8         45 return join '', $ope, $delimiter, $end_delimiter, $modifier;
5964             }
5965              
5966             # with /b /B modifier
5967             elsif ($modifier =~ tr/bB//d) {
5968 0         0 return e_qr_qb($ope,$delimiter,$end_delimiter,$string,$modifier);
5969             }
5970              
5971             # without /b /B modifier
5972             else {
5973 2         7 return e_qr_qt($ope,$delimiter,$end_delimiter,$string,$modifier);
5974             }
5975             }
5976              
5977             #
5978             # escape regexp (m'', qr'')
5979             #
5980             sub e_qr_qt {
5981 2     2 0 6 my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
5982              
5983 2 50       5 my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
5984              
5985             # split regexp
5986 2         74 my @char = $string =~ /\G((?>
5987             [^\\\[\$\@\/] |
5988             [\x00-\xFF] |
5989             \[\^ |
5990             \[\: (?>[a-z]+) \:\] |
5991             \[\:\^ (?>[a-z]+) \:\] |
5992             [\$\@\/] |
5993             \\ (?:$q_char) |
5994             (?:$q_char)
5995             ))/oxmsg;
5996              
5997             # unescape character
5998 2         9 for (my $i=0; $i <= $#char; $i++) {
5999 2 50 33     13 if (0) {
    50 33        
    50 33        
    50          
    50          
    50          
6000             }
6001              
6002             # open character class [...]
6003 0         0 elsif ($char[$i] eq '[') {
6004 0         0 my $left = $i;
6005 0 0       0 if ($char[$i+1] eq ']') {
6006 0         0 $i++;
6007             }
6008 0         0 while (1) {
6009 0 0       0 if (++$i > $#char) {
6010 0         0 die __FILE__, ": Unmatched [] in regexp\n";
6011             }
6012 0 0       0 if ($char[$i] eq ']') {
6013 0         0 my $right = $i;
6014              
6015             # [...]
6016 0         0 splice @char, $left, $right-$left+1, Ekoi8r::charlist_qr(@char[$left+1..$right-1], $modifier);
6017              
6018 0         0 $i = $left;
6019 0         0 last;
6020             }
6021             }
6022             }
6023              
6024             # open character class [^...]
6025             elsif ($char[$i] eq '[^') {
6026 0         0 my $left = $i;
6027 0 0       0 if ($char[$i+1] eq ']') {
6028 0         0 $i++;
6029             }
6030 0         0 while (1) {
6031 0 0       0 if (++$i > $#char) {
6032 0         0 die __FILE__, ": Unmatched [] in regexp\n";
6033             }
6034 0 0       0 if ($char[$i] eq ']') {
6035 0         0 my $right = $i;
6036              
6037             # [^...]
6038 0         0 splice @char, $left, $right-$left+1, Ekoi8r::charlist_not_qr(@char[$left+1..$right-1], $modifier);
6039              
6040 0         0 $i = $left;
6041 0         0 last;
6042             }
6043             }
6044             }
6045              
6046             # escape $ @ / and \
6047             elsif ($char[$i] =~ /\A [\$\@\/\\] \z/oxms) {
6048 0         0 $char[$i] = '\\' . $char[$i];
6049             }
6050              
6051             # rewrite character class or escape character
6052             elsif (my $char = character_class($char[$i],$modifier)) {
6053 0         0 $char[$i] = $char;
6054             }
6055              
6056             # /i modifier
6057             elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Ekoi8r::uc($char[$i]) ne Ekoi8r::fc($char[$i]))) {
6058 0 0       0 if (CORE::length(Ekoi8r::fc($char[$i])) == 1) {
6059 0         0 $char[$i] = '[' . Ekoi8r::uc($char[$i]) . Ekoi8r::fc($char[$i]) . ']';
6060             }
6061             else {
6062 0         0 $char[$i] = '(?:' . Ekoi8r::uc($char[$i]) . '|' . Ekoi8r::fc($char[$i]) . ')';
6063             }
6064             }
6065              
6066             # quote character before ? + * {
6067             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
6068 0 0       0 if ($char[$i-1] =~ /\A [\x00-\xFF] \z/oxms) {
6069             }
6070             else {
6071 0         0 $char[$i-1] = '(?:' . $char[$i-1] . ')';
6072             }
6073             }
6074             }
6075              
6076 2         2 $delimiter = '/';
6077 2         4 $end_delimiter = '/';
6078              
6079 2         2 $modifier =~ tr/i//d;
6080 2         17 return join '', $ope, $delimiter, $anchor, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
6081             }
6082              
6083             #
6084             # escape regexp (m''b, qr''b)
6085             #
6086             sub e_qr_qb {
6087 0     0 0 0 my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6088              
6089             # split regexp
6090 0         0 my @char = $string =~ /\G ((?>[^\\]|\\\\)) /oxmsg;
6091              
6092             # unescape character
6093 0         0 for (my $i=0; $i <= $#char; $i++) {
6094 0 0       0 if (0) {
    0          
6095             }
6096              
6097             # remain \\
6098 0         0 elsif ($char[$i] eq '\\\\') {
6099             }
6100              
6101             # escape $ @ / and \
6102             elsif ($char[$i] =~ /\A [\$\@\/\\] \z/oxms) {
6103 0         0 $char[$i] = '\\' . $char[$i];
6104             }
6105             }
6106              
6107 0         0 $delimiter = '/';
6108 0         0 $end_delimiter = '/';
6109 0         0 return join '', $ope, $delimiter, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
6110             }
6111              
6112             #
6113             # escape regexp (s/here//)
6114             #
6115             sub e_s1 {
6116 76     76 0 182 my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6117 76   100     285 $modifier ||= '';
6118              
6119 76         106 $modifier =~ tr/p//d;
6120 76 50       260 if ($modifier =~ /([adlu])/oxms) {
6121 0         0 my $line = 0;
6122 0         0 for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
6123 0 0       0 if ($filename ne __FILE__) {
6124 0         0 $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
6125 0         0 last;
6126             }
6127             }
6128 0         0 die qq{Unsupported modifier "$1" used at line $line.\n};
6129             }
6130              
6131 76         141 $slash = 'div';
6132              
6133             # literal null string pattern
6134 76 100       342 if ($string eq '') {
    50          
6135 8         7 $modifier =~ tr/bB//d;
6136 8         3 $modifier =~ tr/i//d;
6137 8         46 return join '', $ope, $delimiter, $end_delimiter, $modifier;
6138             }
6139              
6140             # /b /B modifier
6141             elsif ($modifier =~ tr/bB//d) {
6142              
6143             # choice again delimiter
6144 0 0       0 if ($delimiter =~ / [\@:] /oxms) {
6145 0         0 my @char = $string =~ /\G ([\x00-\xFF]) /oxmsg;
6146 0         0 my %octet = map {$_ => 1} @char;
  0         0  
6147 0 0       0 if (not $octet{')'}) {
    0          
    0          
    0          
6148 0         0 $delimiter = '(';
6149 0         0 $end_delimiter = ')';
6150             }
6151             elsif (not $octet{'}'}) {
6152 0         0 $delimiter = '{';
6153 0         0 $end_delimiter = '}';
6154             }
6155             elsif (not $octet{']'}) {
6156 0         0 $delimiter = '[';
6157 0         0 $end_delimiter = ']';
6158             }
6159             elsif (not $octet{'>'}) {
6160 0         0 $delimiter = '<';
6161 0         0 $end_delimiter = '>';
6162             }
6163             else {
6164 0         0 for my $char (qw( ! " $ % & * + - . / = ? ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
6165 0 0       0 if (not $octet{$char}) {
6166 0         0 $delimiter = $char;
6167 0         0 $end_delimiter = $char;
6168 0         0 last;
6169             }
6170             }
6171             }
6172             }
6173              
6174 0         0 my $prematch = '';
6175 0         0 return join '', $ope, $delimiter, $prematch, '(?:', $string, ')', $matched, $end_delimiter, $modifier;
6176             }
6177              
6178 68 100       218 my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
6179 68         331 my $metachar = qr/[\@\\|[\]{^]/oxms;
6180              
6181             # split regexp
6182 68         17579 my @char = $string =~ /\G((?>
6183             [^\\\$\@\[\(] |
6184             \\ (?>[1-9][0-9]*) |
6185             \\g (?>\s*) (?>[1-9][0-9]*) |
6186             \\g (?>\s*) \{ (?>\s*) (?>[1-9][0-9]*) (?>\s*) \} |
6187             \\g (?>\s*) \{ (?>\s*) - (?>\s*) (?>[1-9][0-9]*) (?>\s*) \} |
6188             \\x (?>[0-9A-Fa-f]{1,2}) |
6189             \\ (?>[0-7]{2,3}) |
6190             \\c [\x40-\x5F] |
6191             \\x\{ (?>[0-9A-Fa-f]+) \} |
6192             \\o\{ (?>[0-7]+) \} |
6193             \\[bBNpP]\{ (?>[^0-9\}][^\}]*) \} |
6194             \\ $q_char |
6195             \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} |
6196             \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} |
6197             \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} |
6198             [\$\@] $qq_variable |
6199             \$ (?>\s* [0-9]+) |
6200             \$ (?>\s*) \{ (?>\s* [0-9]+ \s*) \} |
6201             \$ \$ (?![\w\{]) |
6202             \$ (?>\s*) \$ (?>\s*) $qq_variable |
6203             \[\^ |
6204             \[\: (?>[a-z]+) :\] |
6205             \[\:\^ (?>[a-z]+) :\] |
6206             \(\? |
6207             $q_char
6208             ))/oxmsg;
6209              
6210             # choice again delimiter
6211 68 50       608 if ($delimiter =~ / [\@:] /oxms) {
6212 0         0 my %octet = map {$_ => 1} @char;
  0         0  
6213 0 0       0 if (not $octet{')'}) {
    0          
    0          
    0          
6214 0         0 $delimiter = '(';
6215 0         0 $end_delimiter = ')';
6216             }
6217             elsif (not $octet{'}'}) {
6218 0         0 $delimiter = '{';
6219 0         0 $end_delimiter = '}';
6220             }
6221             elsif (not $octet{']'}) {
6222 0         0 $delimiter = '[';
6223 0         0 $end_delimiter = ']';
6224             }
6225             elsif (not $octet{'>'}) {
6226 0         0 $delimiter = '<';
6227 0         0 $end_delimiter = '>';
6228             }
6229             else {
6230 0         0 for my $char (qw( ! " $ % & * + - . / = ? ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
6231 0 0       0 if (not $octet{$char}) {
6232 0         0 $delimiter = $char;
6233 0         0 $end_delimiter = $char;
6234 0         0 last;
6235             }
6236             }
6237             }
6238             }
6239              
6240             # count '('
6241 68         169 my $parens = grep { $_ eq '(' } @char;
  253         459  
6242              
6243 68         100 my $left_e = 0;
6244 68         121 my $right_e = 0;
6245 68         355 for (my $i=0; $i <= $#char; $i++) {
6246              
6247             # "\L\u" --> "\u\L"
6248 195 50 33     1527 if (($char[$i] eq '\L') and ($char[$i+1] eq '\u')) {
    50 33        
    100          
    100          
    50          
    50          
6249 0         0 @char[$i,$i+1] = @char[$i+1,$i];
6250             }
6251              
6252             # "\U\l" --> "\l\U"
6253             elsif (($char[$i] eq '\U') and ($char[$i+1] eq '\l')) {
6254 0         0 @char[$i,$i+1] = @char[$i+1,$i];
6255             }
6256              
6257             # octal escape sequence
6258             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
6259 1         3 $char[$i] = Ekoi8r::octchr($1);
6260             }
6261              
6262             # hexadecimal escape sequence
6263             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
6264 1         4 $char[$i] = Ekoi8r::hexchr($1);
6265             }
6266              
6267             # \b{...} --> b\{...}
6268             # \B{...} --> B\{...}
6269             # \N{CHARNAME} --> N\{CHARNAME}
6270             # \p{PROPERTY} --> p\{PROPERTY}
6271             # \P{PROPERTY} --> P\{PROPERTY}
6272             elsif ($char[$i] =~ /\A \\ ([bBNpP]) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
6273 0         0 $char[$i] = $1 . '\\' . $2;
6274             }
6275              
6276             # \p, \P, \X --> p, P, X
6277             elsif ($char[$i] =~ /\A \\ ( [pPX] ) \z/oxms) {
6278 0         0 $char[$i] = $1;
6279             }
6280              
6281 195 50 66     870 if (0) {
    100 66        
    50 100        
    100          
    100          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    100          
    100          
    100          
    50          
    50          
    100          
    100          
6282             }
6283              
6284             # join separated multiple-octet
6285 0         0 elsif ($char[$i] =~ /\A (?: \\ [0-7]{2,3} | \\x [0-9A-Fa-f]{1,2}) \z/oxms) {
6286 0 0 0     0 if ( ($i+3 <= $#char) and (grep(/\A (?: \\ [0-7]{2,3} | \\x [0-9A-Fa-f]{1,2}) \z/oxms, @char[$i+1..$i+3]) == 3) and (CORE::eval(sprintf '"%s%s%s%s"', @char[$i..$i+3]) =~ /\A $q_char \z/oxms)) {
    0 0        
    0 0        
      0        
      0        
      0        
6287 0         0 $char[$i] .= join '', splice @char, $i+1, 3;
6288             }
6289             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)) {
6290 0         0 $char[$i] .= join '', splice @char, $i+1, 2;
6291             }
6292             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)) {
6293 0         0 $char[$i] .= join '', splice @char, $i+1, 1;
6294             }
6295             }
6296              
6297             # open character class [...]
6298             elsif ($char[$i] eq '[') {
6299 13         18 my $left = $i;
6300 13 50       59 if ($char[$i+1] eq ']') {
6301 0         0 $i++;
6302             }
6303 13         19 while (1) {
6304 58 50       99 if (++$i > $#char) {
6305 0         0 die __FILE__, ": Unmatched [] in regexp\n";
6306             }
6307 58 100       109 if ($char[$i] eq ']') {
6308 13         20 my $right = $i;
6309              
6310             # [...]
6311 13 50       111 if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
6312 0         0 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);
  0         0  
6313             }
6314             else {
6315 13         105 splice @char, $left, $right-$left+1, Ekoi8r::charlist_qr(@char[$left+1..$right-1], $modifier);
6316             }
6317              
6318 13         23 $i = $left;
6319 13         45 last;
6320             }
6321             }
6322             }
6323              
6324             # open character class [^...]
6325             elsif ($char[$i] eq '[^') {
6326 0         0 my $left = $i;
6327 0 0       0 if ($char[$i+1] eq ']') {
6328 0         0 $i++;
6329             }
6330 0         0 while (1) {
6331 0 0       0 if (++$i > $#char) {
6332 0         0 die __FILE__, ": Unmatched [] in regexp\n";
6333             }
6334 0 0       0 if ($char[$i] eq ']') {
6335 0         0 my $right = $i;
6336              
6337             # [^...]
6338 0 0       0 if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
6339 0         0 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);
  0         0  
6340             }
6341             else {
6342 0         0 splice @char, $left, $right-$left+1, Ekoi8r::charlist_not_qr(@char[$left+1..$right-1], $modifier);
6343             }
6344              
6345 0         0 $i = $left;
6346 0         0 last;
6347             }
6348             }
6349             }
6350              
6351             # rewrite character class or escape character
6352             elsif (my $char = character_class($char[$i],$modifier)) {
6353 7         13 $char[$i] = $char;
6354             }
6355              
6356             # /i modifier
6357             elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Ekoi8r::uc($char[$i]) ne Ekoi8r::fc($char[$i]))) {
6358 3 50       4 if (CORE::length(Ekoi8r::fc($char[$i])) == 1) {
6359 3         4 $char[$i] = '[' . Ekoi8r::uc($char[$i]) . Ekoi8r::fc($char[$i]) . ']';
6360             }
6361             else {
6362 0         0 $char[$i] = '(?:' . Ekoi8r::uc($char[$i]) . '|' . Ekoi8r::fc($char[$i]) . ')';
6363             }
6364             }
6365              
6366             # \u \l \U \L \F \Q \E
6367             elsif ($char[$i] =~ /\A [<>] \z/oxms) {
6368 0 0       0 if ($right_e < $left_e) {
6369 0         0 $char[$i] = '\\' . $char[$i];
6370             }
6371             }
6372             elsif ($char[$i] eq '\u') {
6373 0         0 $char[$i] = '@{[Ekoi8r::ucfirst qq<';
6374 0         0 $left_e++;
6375             }
6376             elsif ($char[$i] eq '\l') {
6377 0         0 $char[$i] = '@{[Ekoi8r::lcfirst qq<';
6378 0         0 $left_e++;
6379             }
6380             elsif ($char[$i] eq '\U') {
6381 0         0 $char[$i] = '@{[Ekoi8r::uc qq<';
6382 0         0 $left_e++;
6383             }
6384             elsif ($char[$i] eq '\L') {
6385 0         0 $char[$i] = '@{[Ekoi8r::lc qq<';
6386 0         0 $left_e++;
6387             }
6388             elsif ($char[$i] eq '\F') {
6389 0         0 $char[$i] = '@{[Ekoi8r::fc qq<';
6390 0         0 $left_e++;
6391             }
6392             elsif ($char[$i] eq '\Q') {
6393 0         0 $char[$i] = '@{[CORE::quotemeta qq<';
6394 0         0 $left_e++;
6395             }
6396             elsif ($char[$i] eq '\E') {
6397 0 0       0 if ($right_e < $left_e) {
6398 0         0 $char[$i] = '>]}';
6399 0         0 $right_e++;
6400             }
6401             else {
6402 0         0 $char[$i] = '';
6403             }
6404             }
6405             elsif ($char[$i] eq '\Q') {
6406 0         0 while (1) {
6407 0 0       0 if (++$i > $#char) {
6408 0         0 last;
6409             }
6410 0 0       0 if ($char[$i] eq '\E') {
6411 0         0 last;
6412             }
6413             }
6414             }
6415             elsif ($char[$i] eq '\E') {
6416             }
6417              
6418             # \0 --> \0
6419             elsif ($char[$i] =~ /\A \\ (?>\s*) 0 \z/oxms) {
6420             }
6421              
6422             # \g{N}, \g{-N}
6423              
6424             # P.108 Using Simple Patterns
6425             # in Chapter 7: In the World of Regular Expressions
6426             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
6427              
6428             # P.221 Capturing
6429             # in Chapter 5: Pattern Matching
6430             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
6431              
6432             # \g{-1}, \g{-2}, \g{-3} --> \g{-1}, \g{-2}, \g{-3}
6433             elsif ($char[$i] =~ /\A \\g (?>\s*) \{ (?>\s*) - (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} \z/oxms) {
6434             }
6435              
6436             # \g{1}, \g{2}, \g{3} --> \g{2}, \g{3}, \g{4} (only when multibyte anchoring is enable)
6437             elsif ($char[$i] =~ /\A \\g (?>\s*) \{ (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} \z/oxms) {
6438             }
6439              
6440             # \g1, \g2, \g3 --> \g2, \g3, \g4 (only when multibyte anchoring is enable)
6441             elsif ($char[$i] =~ /\A \\g (?>\s*) ((?>[1-9][0-9]*)) \z/oxms) {
6442             }
6443              
6444             # \1, \2, \3 --> \2, \3, \4 (only when multibyte anchoring is enable)
6445             elsif ($char[$i] =~ /\A \\ (?>\s*) ((?>[1-9][0-9]*)) \z/oxms) {
6446             }
6447              
6448             # $0 --> $0
6449             elsif ($char[$i] =~ /\A \$ 0 \z/oxms) {
6450 0 0       0 if ($ignorecase) {
6451 0         0 $char[$i] = '@{[Ekoi8r::ignorecase(' . $char[$i] . ')]}';
6452             }
6453             }
6454             elsif ($char[$i] =~ /\A \$ \{ (?>\s*) 0 (?>\s*) \} \z/oxms) {
6455 0 0       0 if ($ignorecase) {
6456 0         0 $char[$i] = '@{[Ekoi8r::ignorecase(' . $char[$i] . ')]}';
6457             }
6458             }
6459              
6460             # $$ --> $$
6461             elsif ($char[$i] =~ /\A \$\$ \z/oxms) {
6462             }
6463              
6464             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
6465             # $1, $2, $3 --> $1, $2, $3 otherwise
6466             elsif ($char[$i] =~ /\A \$ ((?>[1-9][0-9]*)) \z/oxms) {
6467 0         0 $char[$i] = e_capture($1);
6468 0 0       0 if ($ignorecase) {
6469 0         0 $char[$i] = '@{[Ekoi8r::ignorecase(' . $char[$i] . ')]}';
6470             }
6471             }
6472             elsif ($char[$i] =~ /\A \$ \{ (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} \z/oxms) {
6473 0         0 $char[$i] = e_capture($1);
6474 0 0       0 if ($ignorecase) {
6475 0         0 $char[$i] = '@{[Ekoi8r::ignorecase(' . $char[$i] . ')]}';
6476             }
6477             }
6478              
6479             # $$foo[ ... ] --> $ $foo->[ ... ]
6480             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \[ (?:$qq_bracket)*? \] ) \z/oxms) {
6481 0         0 $char[$i] = e_capture($1.'->'.$2);
6482 0 0       0 if ($ignorecase) {
6483 0         0 $char[$i] = '@{[Ekoi8r::ignorecase(' . $char[$i] . ')]}';
6484             }
6485             }
6486              
6487             # $$foo{ ... } --> $ $foo->{ ... }
6488             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \{ (?:$qq_brace)*? \} ) \z/oxms) {
6489 0         0 $char[$i] = e_capture($1.'->'.$2);
6490 0 0       0 if ($ignorecase) {
6491 0         0 $char[$i] = '@{[Ekoi8r::ignorecase(' . $char[$i] . ')]}';
6492             }
6493             }
6494              
6495             # $$foo
6496             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) \z/oxms) {
6497 0         0 $char[$i] = e_capture($1);
6498 0 0       0 if ($ignorecase) {
6499 0         0 $char[$i] = '@{[Ekoi8r::ignorecase(' . $char[$i] . ')]}';
6500             }
6501             }
6502              
6503             # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Ekoi8r::PREMATCH()
6504             elsif ($char[$i] =~ /\A ( \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} ) \z/oxmsgc) {
6505 4 50       16 if ($ignorecase) {
6506 0         0 $char[$i] = '@{[Ekoi8r::ignorecase(Ekoi8r::PREMATCH())]}';
6507             }
6508             else {
6509 4         25 $char[$i] = '@{[Ekoi8r::PREMATCH()]}';
6510             }
6511             }
6512              
6513             # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Ekoi8r::MATCH()
6514             elsif ($char[$i] =~ /\A ( \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} ) \z/oxmsgc) {
6515 4 50       11 if ($ignorecase) {
6516 0         0 $char[$i] = '@{[Ekoi8r::ignorecase(Ekoi8r::MATCH())]}';
6517             }
6518             else {
6519 4         24 $char[$i] = '@{[Ekoi8r::MATCH()]}';
6520             }
6521             }
6522              
6523             # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Ekoi8r::POSTMATCH()
6524             elsif ($char[$i] =~ /\A ( \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} ) \z/oxmsgc) {
6525 3 50       10 if ($ignorecase) {
6526 0         0 $char[$i] = '@{[Ekoi8r::ignorecase(Ekoi8r::POSTMATCH())]}';
6527             }
6528             else {
6529 3         18 $char[$i] = '@{[Ekoi8r::POSTMATCH()]}';
6530             }
6531             }
6532              
6533             # ${ foo }
6534             elsif ($char[$i] =~ /\A \$ (?>\s*) \{ ((?> \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* )) \} \z/oxms) {
6535 0 0       0 if ($ignorecase) {
6536 0         0 $char[$i] = '@{[Ekoi8r::ignorecase(' . $char[$i] . ')]}';
6537             }
6538             }
6539              
6540             # ${ ... }
6541             elsif ($char[$i] =~ /\A \$ (?>\s*) \{ ( .+ ) \} \z/oxms) {
6542 0         0 $char[$i] = e_capture($1);
6543 0 0       0 if ($ignorecase) {
6544 0         0 $char[$i] = '@{[Ekoi8r::ignorecase(' . $char[$i] . ')]}';
6545             }
6546             }
6547              
6548             # $scalar or @array
6549             elsif ($char[$i] =~ /\A [\$\@].+ /oxms) {
6550 4         19 $char[$i] = e_string($char[$i]);
6551 4 50       40 if ($ignorecase) {
6552 0         0 $char[$i] = '@{[Ekoi8r::ignorecase(' . $char[$i] . ')]}';
6553             }
6554             }
6555              
6556             # quote character before ? + * {
6557             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
6558 13 50       81 if ($char[$i-1] =~ /\A (?:[\x00-\xFF]|\\[0-7]{2,3}|\\x[0-9-A-Fa-f]{1,2}) \z/oxms) {
6559             }
6560             else {
6561 13         128 $char[$i-1] = '(?:' . $char[$i-1] . ')';
6562             }
6563             }
6564             }
6565              
6566             # make regexp string
6567 68         140 my $prematch = '';
6568 68         122 $modifier =~ tr/i//d;
6569 68 50       247 if ($left_e > $right_e) {
6570 0         0 return join '', $ope, $delimiter, $prematch, '(?:', @char, '>]}' x ($left_e - $right_e), ')', $matched, $end_delimiter, $modifier;
6571             }
6572 68         1004 return join '', $ope, $delimiter, $prematch, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
6573             }
6574              
6575             #
6576             # escape regexp (s'here'' or s'here''b)
6577             #
6578             sub e_s1_q {
6579 21     21 0 41 my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6580 21   100     78 $modifier ||= '';
6581              
6582 21         24 $modifier =~ tr/p//d;
6583 21 50       53 if ($modifier =~ /([adlu])/oxms) {
6584 0         0 my $line = 0;
6585 0         0 for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
6586 0 0       0 if ($filename ne __FILE__) {
6587 0         0 $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
6588 0         0 last;
6589             }
6590             }
6591 0         0 die qq{Unsupported modifier "$1" used at line $line.\n};
6592             }
6593              
6594 21         25 $slash = 'div';
6595              
6596             # literal null string pattern
6597 21 100       81 if ($string eq '') {
    50          
6598 8         5 $modifier =~ tr/bB//d;
6599 8         6 $modifier =~ tr/i//d;
6600 8         54 return join '', $ope, $delimiter, $end_delimiter, $modifier;
6601             }
6602              
6603             # with /b /B modifier
6604             elsif ($modifier =~ tr/bB//d) {
6605 0         0 return e_s1_qb($ope,$delimiter,$end_delimiter,$string,$modifier);
6606             }
6607              
6608             # without /b /B modifier
6609             else {
6610 13         35 return e_s1_qt($ope,$delimiter,$end_delimiter,$string,$modifier);
6611             }
6612             }
6613              
6614             #
6615             # escape regexp (s'here'')
6616             #
6617             sub e_s1_qt {
6618 13     13 0 30 my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6619              
6620 13 50       35 my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
6621              
6622             # split regexp
6623 13         279 my @char = $string =~ /\G((?>
6624             [^\\\[\$\@\/] |
6625             [\x00-\xFF] |
6626             \[\^ |
6627             \[\: (?>[a-z]+) \:\] |
6628             \[\:\^ (?>[a-z]+) \:\] |
6629             [\$\@\/] |
6630             \\ (?:$q_char) |
6631             (?:$q_char)
6632             ))/oxmsg;
6633              
6634             # unescape character
6635 13         51 for (my $i=0; $i <= $#char; $i++) {
6636 25 50 33     152 if (0) {
    50 33        
    50 66        
    100          
    50          
    50          
6637             }
6638              
6639             # open character class [...]
6640 0         0 elsif ($char[$i] eq '[') {
6641 0         0 my $left = $i;
6642 0 0       0 if ($char[$i+1] eq ']') {
6643 0         0 $i++;
6644             }
6645 0         0 while (1) {
6646 0 0       0 if (++$i > $#char) {
6647 0         0 die __FILE__, ": Unmatched [] in regexp\n";
6648             }
6649 0 0       0 if ($char[$i] eq ']') {
6650 0         0 my $right = $i;
6651              
6652             # [...]
6653 0         0 splice @char, $left, $right-$left+1, Ekoi8r::charlist_qr(@char[$left+1..$right-1], $modifier);
6654              
6655 0         0 $i = $left;
6656 0         0 last;
6657             }
6658             }
6659             }
6660              
6661             # open character class [^...]
6662             elsif ($char[$i] eq '[^') {
6663 0         0 my $left = $i;
6664 0 0       0 if ($char[$i+1] eq ']') {
6665 0         0 $i++;
6666             }
6667 0         0 while (1) {
6668 0 0       0 if (++$i > $#char) {
6669 0         0 die __FILE__, ": Unmatched [] in regexp\n";
6670             }
6671 0 0       0 if ($char[$i] eq ']') {
6672 0         0 my $right = $i;
6673              
6674             # [^...]
6675 0         0 splice @char, $left, $right-$left+1, Ekoi8r::charlist_not_qr(@char[$left+1..$right-1], $modifier);
6676              
6677 0         0 $i = $left;
6678 0         0 last;
6679             }
6680             }
6681             }
6682              
6683             # escape $ @ / and \
6684             elsif ($char[$i] =~ /\A [\$\@\/\\] \z/oxms) {
6685 0         0 $char[$i] = '\\' . $char[$i];
6686             }
6687              
6688             # rewrite character class or escape character
6689             elsif (my $char = character_class($char[$i],$modifier)) {
6690 6         12 $char[$i] = $char;
6691             }
6692              
6693             # /i modifier
6694             elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Ekoi8r::uc($char[$i]) ne Ekoi8r::fc($char[$i]))) {
6695 0 0       0 if (CORE::length(Ekoi8r::fc($char[$i])) == 1) {
6696 0         0 $char[$i] = '[' . Ekoi8r::uc($char[$i]) . Ekoi8r::fc($char[$i]) . ']';
6697             }
6698             else {
6699 0         0 $char[$i] = '(?:' . Ekoi8r::uc($char[$i]) . '|' . Ekoi8r::fc($char[$i]) . ')';
6700             }
6701             }
6702              
6703             # quote character before ? + * {
6704             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
6705 0 0       0 if ($char[$i-1] =~ /\A [\x00-\xFF] \z/oxms) {
6706             }
6707             else {
6708 0         0 $char[$i-1] = '(?:' . $char[$i-1] . ')';
6709             }
6710             }
6711             }
6712              
6713 13         22 $modifier =~ tr/i//d;
6714 13         19 $delimiter = '/';
6715 13         16 $end_delimiter = '/';
6716 13         19 my $prematch = '';
6717 13         133 return join '', $ope, $delimiter, $prematch, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
6718             }
6719              
6720             #
6721             # escape regexp (s'here''b)
6722             #
6723             sub e_s1_qb {
6724 0     0 0 0 my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6725              
6726             # split regexp
6727 0         0 my @char = $string =~ /\G (?>[^\\]|\\\\) /oxmsg;
6728              
6729             # unescape character
6730 0         0 for (my $i=0; $i <= $#char; $i++) {
6731 0 0       0 if (0) {
    0          
6732             }
6733              
6734             # remain \\
6735 0         0 elsif ($char[$i] eq '\\\\') {
6736             }
6737              
6738             # escape $ @ / and \
6739             elsif ($char[$i] =~ /\A [\$\@\/\\] \z/oxms) {
6740 0         0 $char[$i] = '\\' . $char[$i];
6741             }
6742             }
6743              
6744 0         0 $delimiter = '/';
6745 0         0 $end_delimiter = '/';
6746 0         0 my $prematch = '';
6747 0         0 return join '', $ope, $delimiter, $prematch, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
6748             }
6749              
6750             #
6751             # escape regexp (s''here')
6752             #
6753             sub e_s2_q {
6754 16     16 0 30 my($ope,$delimiter,$end_delimiter,$string) = @_;
6755              
6756 16         20 $slash = 'div';
6757              
6758 16         114 my @char = $string =~ / \G (?>[^\\]|\\\\|$q_char) /oxmsg;
6759 16         53 for (my $i=0; $i <= $#char; $i++) {
6760 9 100       45 if (0) {
    100          
6761             }
6762              
6763             # not escape \\
6764 0         0 elsif ($char[$i] =~ /\A \\\\ \z/oxms) {
6765             }
6766              
6767             # escape $ @ / and \
6768             elsif ($char[$i] =~ /\A [\$\@\/\\] \z/oxms) {
6769 5         19 $char[$i] = '\\' . $char[$i];
6770             }
6771             }
6772              
6773 16         63 return join '', $ope, $delimiter, @char, $end_delimiter;
6774             }
6775              
6776             #
6777             # escape regexp (s/here/and here/modifier)
6778             #
6779             sub e_sub {
6780 97     97 0 534 my($variable,$delimiter1,$pattern,$end_delimiter1,$delimiter2,$replacement,$end_delimiter2,$modifier) = @_;
6781 97   100     378 $modifier ||= '';
6782              
6783 97         192 $modifier =~ tr/p//d;
6784 97 50       316 if ($modifier =~ /([adlu])/oxms) {
6785 0         0 my $line = 0;
6786 0         0 for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
6787 0 0       0 if ($filename ne __FILE__) {
6788 0         0 $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
6789 0         0 last;
6790             }
6791             }
6792 0         0 die qq{Unsupported modifier "$1" used at line $line.\n};
6793             }
6794              
6795 97 100       262 if ($variable eq '') {
6796 36         56 $variable = '$_';
6797 36         58 $bind_operator = ' =~ ';
6798             }
6799              
6800 97         147 $slash = 'div';
6801              
6802             # P.128 Start of match (or end of previous match): \G
6803             # P.130 Advanced Use of \G with Perl
6804             # in Chapter 3: Overview of Regular Expression Features and Flavors
6805             # P.312 Iterative Matching: Scalar Context, with /g
6806             # in Chapter 7: Perl
6807             # of ISBN 0-596-00289-0 Mastering Regular Expressions, Second edition
6808              
6809             # P.181 Where You Left Off: The \G Assertion
6810             # in Chapter 5: Pattern Matching
6811             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
6812              
6813             # P.220 Where You Left Off: The \G Assertion
6814             # in Chapter 5: Pattern Matching
6815             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
6816              
6817 97         146 my $e_modifier = $modifier =~ tr/e//d;
6818 97         134 my $r_modifier = $modifier =~ tr/r//d;
6819              
6820 97         129 my $my = '';
6821 97 50       303 if ($variable =~ s/\A \( (?>\s*) ( (?>(?: local \b | my \b | our \b | state \b )?) .+ ) \) \z/$1/oxms) {
6822 0         0 $my = $variable;
6823 0         0 $variable =~ s/ (?: local \b | my \b | our \b | state \b ) (?>\s*) //oxms;
6824 0         0 $variable =~ s/ = .+ \z//oxms;
6825             }
6826              
6827 97         264 (my $variable_basename = $variable) =~ s/ [\[\{].* \z//oxms;
6828 97         247 $variable_basename =~ s/ \s+ \z//oxms;
6829              
6830             # quote replacement string
6831 97         144 my $e_replacement = '';
6832 97 100       250 if ($e_modifier >= 1) {
6833 17         47 $e_replacement = e_qq('', '', '', $replacement);
6834 17         30 $e_modifier--;
6835             }
6836             else {
6837 80 100       185 if ($delimiter2 eq "'") {
6838 16         34 $e_replacement = e_s2_q('qq', '/', '/', $replacement);
6839             }
6840             else {
6841 64         162 $e_replacement = e_qq ('qq', $delimiter2, $end_delimiter2, $replacement);
6842             }
6843             }
6844              
6845 97         160 my $sub = '';
6846              
6847             # with /r
6848 97 100       227 if ($r_modifier) {
6849 8 100       20 if (0) {
6850             }
6851              
6852             # s///gr without multibyte anchoring
6853 0         0 elsif ($modifier =~ /g/oxms) {
6854 4 50       18 $sub = sprintf(
6855             # 1 2 3 4 5
6856             q,
6857              
6858             $variable, # 1
6859             ($delimiter1 eq "'") ? # 2
6860             e_s1_q('m', $delimiter1, $end_delimiter1, $pattern, $modifier) : # :
6861             e_s1 ('m', $delimiter1, $end_delimiter1, $pattern, $modifier), # :
6862             $s_matched, # 3
6863             $e_replacement, # 4
6864             '$KOI8R::re_r=CORE::eval $KOI8R::re_r; ' x $e_modifier, # 5
6865             );
6866             }
6867              
6868             # s///r
6869             else {
6870              
6871 4         6 my $prematch = q{$`};
6872              
6873 4 50       20 $sub = sprintf(
6874             # 1 2 3 4 5 6 7
6875             q<(%s =~ %s) ? CORE::eval{%s local $^W=0; local $KOI8R::re_r=%s; %s"%s$KOI8R::re_r$'" } : %s>,
6876              
6877             $variable, # 1
6878             ($delimiter1 eq "'") ? # 2
6879             e_s1_q('m', $delimiter1, $end_delimiter1, $pattern, $modifier) : # :
6880             e_s1 ('m', $delimiter1, $end_delimiter1, $pattern, $modifier), # :
6881             $s_matched, # 3
6882             $e_replacement, # 4
6883             '$KOI8R::re_r=CORE::eval $KOI8R::re_r; ' x $e_modifier, # 5
6884             $prematch, # 6
6885             $variable, # 7
6886             );
6887             }
6888              
6889             # $var !~ s///r doesn't make sense
6890 8 50       24 if ($bind_operator =~ / !~ /oxms) {
6891 0         0 $sub = q{die("$0: Using !~ with s///r doesn't make sense"), } . $sub;
6892             }
6893             }
6894              
6895             # without /r
6896             else {
6897 89 100       263 if (0) {
6898             }
6899              
6900             # s///g without multibyte anchoring
6901 0         0 elsif ($modifier =~ /g/oxms) {
6902 22 100       119 $sub = sprintf(
    100          
6903             # 1 2 3 4 5 6 7 8
6904             q,
6905              
6906             $variable, # 1
6907             ($delimiter1 eq "'") ? # 2
6908             e_s1_q('m', $delimiter1, $end_delimiter1, $pattern, $modifier) : # :
6909             e_s1 ('m', $delimiter1, $end_delimiter1, $pattern, $modifier), # :
6910             $s_matched, # 3
6911             $e_replacement, # 4
6912             '$KOI8R::re_r=CORE::eval $KOI8R::re_r; ' x $e_modifier, # 5
6913             $variable, # 6
6914             $variable, # 7
6915             ($bind_operator =~ / !~ /oxms) ? '!' : '', # 8
6916             );
6917             }
6918              
6919             # s///
6920             else {
6921              
6922 67         108 my $prematch = q{$`};
6923              
6924 67 100       470 $sub = sprintf(
    100          
6925              
6926             ($bind_operator =~ / =~ /oxms) ?
6927              
6928             # 1 2 3 4 5 6 7 8
6929             q<(%s%s%s) ? CORE::eval{%s local $^W=0; local $KOI8R::re_r=%s; %s%s="%s$KOI8R::re_r$'"; 1 } : undef> :
6930              
6931             # 1 2 3 4 5 6 7 8
6932             q<(%s%s%s) ? 1 : CORE::eval{%s local $^W=0; local $KOI8R::re_r=%s; %s%s="%s$KOI8R::re_r$'"; undef }>,
6933              
6934             $variable, # 1
6935             $bind_operator, # 2
6936             ($delimiter1 eq "'") ? # 3
6937             e_s1_q('m', $delimiter1, $end_delimiter1, $pattern, $modifier) : # :
6938             e_s1 ('m', $delimiter1, $end_delimiter1, $pattern, $modifier), # :
6939             $s_matched, # 4
6940             $e_replacement, # 5
6941             '$KOI8R::re_r=CORE::eval $KOI8R::re_r; ' x $e_modifier, # 6
6942             $variable, # 7
6943             $prematch, # 8
6944             );
6945             }
6946             }
6947              
6948             # (my $foo = $bar) =~ s/// --> (my $foo = $bar, CORE::eval { ... })[1]
6949 97 50       325 if ($my ne '') {
6950 0         0 $sub = "($my, $sub)[1]";
6951             }
6952              
6953             # clear s/// variable
6954 97         138 $sub_variable = '';
6955 97         115 $bind_operator = '';
6956              
6957 97         792 return $sub;
6958             }
6959              
6960             #
6961             # escape regexp of split qr//
6962             #
6963             sub e_split {
6964 74     74 0 242 my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6965 74   100     351 $modifier ||= '';
6966              
6967 74         107 $modifier =~ tr/p//d;
6968 74 50       357 if ($modifier =~ /([adlu])/oxms) {
6969 0         0 my $line = 0;
6970 0         0 for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
6971 0 0       0 if ($filename ne __FILE__) {
6972 0         0 $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
6973 0         0 last;
6974             }
6975             }
6976 0         0 die qq{Unsupported modifier "$1" used at line $line.\n};
6977             }
6978              
6979 74         114 $slash = 'div';
6980              
6981             # /b /B modifier
6982 74 50       165 if ($modifier =~ tr/bB//d) {
6983 0         0 return join '', 'split', $ope, $delimiter, $string, $end_delimiter, $modifier;
6984             }
6985              
6986 74 50       205 my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
6987 74         368 my $metachar = qr/[\@\\|[\]{^]/oxms;
6988              
6989             # split regexp
6990 74         9992 my @char = $string =~ /\G((?>
6991             [^\\\$\@\[\(] |
6992             \\x (?>[0-9A-Fa-f]{1,2}) |
6993             \\ (?>[0-7]{2,3}) |
6994             \\c [\x40-\x5F] |
6995             \\x\{ (?>[0-9A-Fa-f]+) \} |
6996             \\o\{ (?>[0-7]+) \} |
6997             \\[bBNpP]\{ (?>[^0-9\}][^\}]*) \} |
6998             \\ $q_char |
6999             \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} |
7000             \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} |
7001             \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} |
7002             [\$\@] $qq_variable |
7003             \$ (?>\s* [0-9]+) |
7004             \$ (?>\s*) \{ (?>\s* [0-9]+ \s*) \} |
7005             \$ \$ (?![\w\{]) |
7006             \$ (?>\s*) \$ (?>\s*) $qq_variable |
7007             \[\^ |
7008             \[\: (?>[a-z]+) :\] |
7009             \[\:\^ (?>[a-z]+) :\] |
7010             \(\? |
7011             $q_char
7012             ))/oxmsg;
7013              
7014 74         256 my $left_e = 0;
7015 74         85 my $right_e = 0;
7016 74         317 for (my $i=0; $i <= $#char; $i++) {
7017              
7018             # "\L\u" --> "\u\L"
7019 249 50 33     1794 if (($char[$i] eq '\L') and ($char[$i+1] eq '\u')) {
    50 33        
    100          
    100          
    50          
    50          
7020 0         0 @char[$i,$i+1] = @char[$i+1,$i];
7021             }
7022              
7023             # "\U\l" --> "\l\U"
7024             elsif (($char[$i] eq '\U') and ($char[$i+1] eq '\l')) {
7025 0         0 @char[$i,$i+1] = @char[$i+1,$i];
7026             }
7027              
7028             # octal escape sequence
7029             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
7030 1         2 $char[$i] = Ekoi8r::octchr($1);
7031             }
7032              
7033             # hexadecimal escape sequence
7034             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
7035 1         4 $char[$i] = Ekoi8r::hexchr($1);
7036             }
7037              
7038             # \b{...} --> b\{...}
7039             # \B{...} --> B\{...}
7040             # \N{CHARNAME} --> N\{CHARNAME}
7041             # \p{PROPERTY} --> p\{PROPERTY}
7042             # \P{PROPERTY} --> P\{PROPERTY}
7043             elsif ($char[$i] =~ /\A \\ ([bBNpP]) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
7044 0         0 $char[$i] = $1 . '\\' . $2;
7045             }
7046              
7047             # \p, \P, \X --> p, P, X
7048             elsif ($char[$i] =~ /\A \\ ( [pPX] ) \z/oxms) {
7049 0         0 $char[$i] = $1;
7050             }
7051              
7052 249 50 100     833 if (0) {
    100 33        
    50 33        
    100 100        
    100          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    100          
    100          
    100          
    50          
    50          
    100          
    100          
7053             }
7054              
7055             # join separated multiple-octet
7056 0         0 elsif ($char[$i] =~ /\A (?: \\ [0-7]{2,3} | \\x [0-9A-Fa-f]{1,2}) \z/oxms) {
7057 0 0 0     0 if ( ($i+3 <= $#char) and (grep(/\A (?: \\ [0-7]{2,3} | \\x [0-9A-Fa-f]{1,2}) \z/oxms, @char[$i+1..$i+3]) == 3) and (CORE::eval(sprintf '"%s%s%s%s"', @char[$i..$i+3]) =~ /\A $q_char \z/oxms)) {
    0 0        
    0 0        
      0        
      0        
      0        
7058 0         0 $char[$i] .= join '', splice @char, $i+1, 3;
7059             }
7060             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)) {
7061 0         0 $char[$i] .= join '', splice @char, $i+1, 2;
7062             }
7063             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)) {
7064 0         0 $char[$i] .= join '', splice @char, $i+1, 1;
7065             }
7066             }
7067              
7068             # open character class [...]
7069             elsif ($char[$i] eq '[') {
7070 3         7 my $left = $i;
7071 3 50       10 if ($char[$i+1] eq ']') {
7072 0         0 $i++;
7073             }
7074 3         5 while (1) {
7075 7 50       21 if (++$i > $#char) {
7076 0         0 die __FILE__, ": Unmatched [] in regexp\n";
7077             }
7078 7 100       15 if ($char[$i] eq ']') {
7079 3         5 my $right = $i;
7080              
7081             # [...]
7082 3 50       24 if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
7083 0         0 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);
  0         0  
7084             }
7085             else {
7086 3         20 splice @char, $left, $right-$left+1, Ekoi8r::charlist_qr(@char[$left+1..$right-1], $modifier);
7087             }
7088              
7089 3         3 $i = $left;
7090 3         9 last;
7091             }
7092             }
7093             }
7094              
7095             # open character class [^...]
7096             elsif ($char[$i] eq '[^') {
7097 0         0 my $left = $i;
7098 0 0       0 if ($char[$i+1] eq ']') {
7099 0         0 $i++;
7100             }
7101 0         0 while (1) {
7102 0 0       0 if (++$i > $#char) {
7103 0         0 die __FILE__, ": Unmatched [] in regexp\n";
7104             }
7105 0 0       0 if ($char[$i] eq ']') {
7106 0         0 my $right = $i;
7107              
7108             # [^...]
7109 0 0       0 if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
7110 0         0 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);
  0         0  
7111             }
7112             else {
7113 0         0 splice @char, $left, $right-$left+1, Ekoi8r::charlist_not_qr(@char[$left+1..$right-1], $modifier);
7114             }
7115              
7116 0         0 $i = $left;
7117 0         0 last;
7118             }
7119             }
7120             }
7121              
7122             # rewrite character class or escape character
7123             elsif (my $char = character_class($char[$i],$modifier)) {
7124 1         3 $char[$i] = $char;
7125             }
7126              
7127             # P.794 29.2.161. split
7128             # in Chapter 29: Functions
7129             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
7130              
7131             # P.951 split
7132             # in Chapter 27: Functions
7133             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
7134              
7135             # said "The //m modifier is assumed when you split on the pattern /^/",
7136             # but perl5.008 is not so. Therefore, this software adds //m.
7137             # (and so on)
7138              
7139             # split(m/^/) --> split(m/^/m)
7140             elsif (($char[$i] eq '^') and ($modifier !~ /m/oxms)) {
7141 7         36 $modifier .= 'm';
7142             }
7143              
7144             # /i modifier
7145             elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Ekoi8r::uc($char[$i]) ne Ekoi8r::fc($char[$i]))) {
7146 0 0       0 if (CORE::length(Ekoi8r::fc($char[$i])) == 1) {
7147 0         0 $char[$i] = '[' . Ekoi8r::uc($char[$i]) . Ekoi8r::fc($char[$i]) . ']';
7148             }
7149             else {
7150 0         0 $char[$i] = '(?:' . Ekoi8r::uc($char[$i]) . '|' . Ekoi8r::fc($char[$i]) . ')';
7151             }
7152             }
7153              
7154             # \u \l \U \L \F \Q \E
7155             elsif ($char[$i] =~ /\A ([<>]) \z/oxms) {
7156 0 0       0 if ($right_e < $left_e) {
7157 0         0 $char[$i] = '\\' . $char[$i];
7158             }
7159             }
7160             elsif ($char[$i] eq '\u') {
7161 0         0 $char[$i] = '@{[Ekoi8r::ucfirst qq<';
7162 0         0 $left_e++;
7163             }
7164             elsif ($char[$i] eq '\l') {
7165 0         0 $char[$i] = '@{[Ekoi8r::lcfirst qq<';
7166 0         0 $left_e++;
7167             }
7168             elsif ($char[$i] eq '\U') {
7169 0         0 $char[$i] = '@{[Ekoi8r::uc qq<';
7170 0         0 $left_e++;
7171             }
7172             elsif ($char[$i] eq '\L') {
7173 0         0 $char[$i] = '@{[Ekoi8r::lc qq<';
7174 0         0 $left_e++;
7175             }
7176             elsif ($char[$i] eq '\F') {
7177 0         0 $char[$i] = '@{[Ekoi8r::fc qq<';
7178 0         0 $left_e++;
7179             }
7180             elsif ($char[$i] eq '\Q') {
7181 0         0 $char[$i] = '@{[CORE::quotemeta qq<';
7182 0         0 $left_e++;
7183             }
7184             elsif ($char[$i] eq '\E') {
7185 0 0       0 if ($right_e < $left_e) {
7186 0         0 $char[$i] = '>]}';
7187 0         0 $right_e++;
7188             }
7189             else {
7190 0         0 $char[$i] = '';
7191             }
7192             }
7193             elsif ($char[$i] eq '\Q') {
7194 0         0 while (1) {
7195 0 0       0 if (++$i > $#char) {
7196 0         0 last;
7197             }
7198 0 0       0 if ($char[$i] eq '\E') {
7199 0         0 last;
7200             }
7201             }
7202             }
7203             elsif ($char[$i] eq '\E') {
7204             }
7205              
7206             # $0 --> $0
7207             elsif ($char[$i] =~ /\A \$ 0 \z/oxms) {
7208 0 0       0 if ($ignorecase) {
7209 0         0 $char[$i] = '@{[Ekoi8r::ignorecase(' . $char[$i] . ')]}';
7210             }
7211             }
7212             elsif ($char[$i] =~ /\A \$ \{ (?>\s*) 0 (?>\s*) \} \z/oxms) {
7213 0 0       0 if ($ignorecase) {
7214 0         0 $char[$i] = '@{[Ekoi8r::ignorecase(' . $char[$i] . ')]}';
7215             }
7216             }
7217              
7218             # $$ --> $$
7219             elsif ($char[$i] =~ /\A \$\$ \z/oxms) {
7220             }
7221              
7222             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
7223             # $1, $2, $3 --> $1, $2, $3 otherwise
7224             elsif ($char[$i] =~ /\A \$ ((?>[1-9][0-9]*)) \z/oxms) {
7225 0         0 $char[$i] = e_capture($1);
7226 0 0       0 if ($ignorecase) {
7227 0         0 $char[$i] = '@{[Ekoi8r::ignorecase(' . $char[$i] . ')]}';
7228             }
7229             }
7230             elsif ($char[$i] =~ /\A \$ \{ (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} \z/oxms) {
7231 0         0 $char[$i] = e_capture($1);
7232 0 0       0 if ($ignorecase) {
7233 0         0 $char[$i] = '@{[Ekoi8r::ignorecase(' . $char[$i] . ')]}';
7234             }
7235             }
7236              
7237             # $$foo[ ... ] --> $ $foo->[ ... ]
7238             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \[ (?:$qq_bracket)*? \] ) \z/oxms) {
7239 0         0 $char[$i] = e_capture($1.'->'.$2);
7240 0 0       0 if ($ignorecase) {
7241 0         0 $char[$i] = '@{[Ekoi8r::ignorecase(' . $char[$i] . ')]}';
7242             }
7243             }
7244              
7245             # $$foo{ ... } --> $ $foo->{ ... }
7246             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \{ (?:$qq_brace)*? \} ) \z/oxms) {
7247 0         0 $char[$i] = e_capture($1.'->'.$2);
7248 0 0       0 if ($ignorecase) {
7249 0         0 $char[$i] = '@{[Ekoi8r::ignorecase(' . $char[$i] . ')]}';
7250             }
7251             }
7252              
7253             # $$foo
7254             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) \z/oxms) {
7255 0         0 $char[$i] = e_capture($1);
7256 0 0       0 if ($ignorecase) {
7257 0         0 $char[$i] = '@{[Ekoi8r::ignorecase(' . $char[$i] . ')]}';
7258             }
7259             }
7260              
7261             # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Ekoi8r::PREMATCH()
7262             elsif ($char[$i] =~ /\A ( \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} ) \z/oxmsgc) {
7263 12 50       25 if ($ignorecase) {
7264 0         0 $char[$i] = '@{[Ekoi8r::ignorecase(Ekoi8r::PREMATCH())]}';
7265             }
7266             else {
7267 12         87 $char[$i] = '@{[Ekoi8r::PREMATCH()]}';
7268             }
7269             }
7270              
7271             # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Ekoi8r::MATCH()
7272             elsif ($char[$i] =~ /\A ( \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} ) \z/oxmsgc) {
7273 12 50       21 if ($ignorecase) {
7274 0         0 $char[$i] = '@{[Ekoi8r::ignorecase(Ekoi8r::MATCH())]}';
7275             }
7276             else {
7277 12         77 $char[$i] = '@{[Ekoi8r::MATCH()]}';
7278             }
7279             }
7280              
7281             # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Ekoi8r::POSTMATCH()
7282             elsif ($char[$i] =~ /\A ( \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} ) \z/oxmsgc) {
7283 9 50       20 if ($ignorecase) {
7284 0         0 $char[$i] = '@{[Ekoi8r::ignorecase(Ekoi8r::POSTMATCH())]}';
7285             }
7286             else {
7287 9         74 $char[$i] = '@{[Ekoi8r::POSTMATCH()]}';
7288             }
7289             }
7290              
7291             # ${ foo }
7292             elsif ($char[$i] =~ /\A \$ (?>\s*) \{ ((?> \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* )) \} \z/oxms) {
7293 0 0       0 if ($ignorecase) {
7294 0         0 $char[$i] = '@{[Ekoi8r::ignorecase(' . $1 . ')]}';
7295             }
7296             }
7297              
7298             # ${ ... }
7299             elsif ($char[$i] =~ /\A \$ (?>\s*) \{ ( .+ ) \} \z/oxms) {
7300 0         0 $char[$i] = e_capture($1);
7301 0 0       0 if ($ignorecase) {
7302 0         0 $char[$i] = '@{[Ekoi8r::ignorecase(' . $char[$i] . ')]}';
7303             }
7304             }
7305              
7306             # $scalar or @array
7307             elsif ($char[$i] =~ /\A [\$\@].+ /oxms) {
7308 3         6 $char[$i] = e_string($char[$i]);
7309 3 50       20 if ($ignorecase) {
7310 0         0 $char[$i] = '@{[Ekoi8r::ignorecase(' . $char[$i] . ')]}';
7311             }
7312             }
7313              
7314             # quote character before ? + * {
7315             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
7316 1 50       10 if ($char[$i-1] =~ /\A (?:[\x00-\xFF]|\\[0-7]{2,3}|\\x[0-9-A-Fa-f]{1,2}) \z/oxms) {
7317             }
7318             else {
7319 0         0 $char[$i-1] = '(?:' . $char[$i-1] . ')';
7320             }
7321             }
7322             }
7323              
7324             # make regexp string
7325 74         108 $modifier =~ tr/i//d;
7326 74 50       174 if ($left_e > $right_e) {
7327 0         0 return join '', 'Ekoi8r::split', $ope, $delimiter, @char, '>]}' x ($left_e - $right_e), $end_delimiter, $modifier;
7328             }
7329 74         745 return join '', 'Ekoi8r::split', $ope, $delimiter, @char, $end_delimiter, $modifier;
7330             }
7331              
7332             #
7333             # escape regexp of split qr''
7334             #
7335             sub e_split_q {
7336 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
7337 0   0       $modifier ||= '';
7338              
7339 0           $modifier =~ tr/p//d;
7340 0 0         if ($modifier =~ /([adlu])/oxms) {
7341 0           my $line = 0;
7342 0           for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
7343 0 0         if ($filename ne __FILE__) {
7344 0           $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
7345 0           last;
7346             }
7347             }
7348 0           die qq{Unsupported modifier "$1" used at line $line.\n};
7349             }
7350              
7351 0           $slash = 'div';
7352              
7353             # /b /B modifier
7354 0 0         if ($modifier =~ tr/bB//d) {
7355 0           return join '', 'split', $ope, $delimiter, $string, $end_delimiter, $modifier;
7356             }
7357              
7358 0 0         my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
7359              
7360             # split regexp
7361 0           my @char = $string =~ /\G((?>
7362             [^\\\[] |
7363             [\x00-\xFF] |
7364             \[\^ |
7365             \[\: (?>[a-z]+) \:\] |
7366             \[\:\^ (?>[a-z]+) \:\] |
7367             \\ (?:$q_char) |
7368             (?:$q_char)
7369             ))/oxmsg;
7370              
7371             # unescape character
7372 0           for (my $i=0; $i <= $#char; $i++) {
7373 0 0 0       if (0) {
    0 0        
    0 0        
    0 0        
    0          
    0          
7374             }
7375              
7376             # open character class [...]
7377 0           elsif ($char[$i] eq '[') {
7378 0           my $left = $i;
7379 0 0         if ($char[$i+1] eq ']') {
7380 0           $i++;
7381             }
7382 0           while (1) {
7383 0 0         if (++$i > $#char) {
7384 0           die __FILE__, ": Unmatched [] in regexp\n";
7385             }
7386 0 0         if ($char[$i] eq ']') {
7387 0           my $right = $i;
7388              
7389             # [...]
7390 0           splice @char, $left, $right-$left+1, Ekoi8r::charlist_qr(@char[$left+1..$right-1], $modifier);
7391              
7392 0           $i = $left;
7393 0           last;
7394             }
7395             }
7396             }
7397              
7398             # open character class [^...]
7399             elsif ($char[$i] eq '[^') {
7400 0           my $left = $i;
7401 0 0         if ($char[$i+1] eq ']') {
7402 0           $i++;
7403             }
7404 0           while (1) {
7405 0 0         if (++$i > $#char) {
7406 0           die __FILE__, ": Unmatched [] in regexp\n";
7407             }
7408 0 0         if ($char[$i] eq ']') {
7409 0           my $right = $i;
7410              
7411             # [^...]
7412 0           splice @char, $left, $right-$left+1, Ekoi8r::charlist_not_qr(@char[$left+1..$right-1], $modifier);
7413              
7414 0           $i = $left;
7415 0           last;
7416             }
7417             }
7418             }
7419              
7420             # rewrite character class or escape character
7421             elsif (my $char = character_class($char[$i],$modifier)) {
7422 0           $char[$i] = $char;
7423             }
7424              
7425             # split(m/^/) --> split(m/^/m)
7426             elsif (($char[$i] eq '^') and ($modifier !~ /m/oxms)) {
7427 0           $modifier .= 'm';
7428             }
7429              
7430             # /i modifier
7431             elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Ekoi8r::uc($char[$i]) ne Ekoi8r::fc($char[$i]))) {
7432 0 0         if (CORE::length(Ekoi8r::fc($char[$i])) == 1) {
7433 0           $char[$i] = '[' . Ekoi8r::uc($char[$i]) . Ekoi8r::fc($char[$i]) . ']';
7434             }
7435             else {
7436 0           $char[$i] = '(?:' . Ekoi8r::uc($char[$i]) . '|' . Ekoi8r::fc($char[$i]) . ')';
7437             }
7438             }
7439              
7440             # quote character before ? + * {
7441             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
7442 0 0         if ($char[$i-1] =~ /\A [\x00-\xFF] \z/oxms) {
7443             }
7444             else {
7445 0           $char[$i-1] = '(?:' . $char[$i-1] . ')';
7446             }
7447             }
7448             }
7449              
7450 0           $modifier =~ tr/i//d;
7451 0           return join '', 'Ekoi8r::split', $ope, $delimiter, @char, $end_delimiter, $modifier;
7452             }
7453              
7454             #
7455             # instead of Carp::carp
7456             #
7457             sub carp {
7458 0     0 0   my($package,$filename,$line) = caller(1);
7459 0           print STDERR "@_ at $filename line $line.\n";
7460             }
7461              
7462             #
7463             # instead of Carp::croak
7464             #
7465             sub croak {
7466 0     0 0   my($package,$filename,$line) = caller(1);
7467 0           print STDERR "@_ at $filename line $line.\n";
7468 0           die "\n";
7469             }
7470              
7471             #
7472             # instead of Carp::cluck
7473             #
7474             sub cluck {
7475 0     0 0   my $i = 0;
7476 0           my @cluck = ();
7477 0           while (my($package,$filename,$line,$subroutine) = caller($i)) {
7478 0           push @cluck, "[$i] $filename($line) $package::$subroutine\n";
7479 0           $i++;
7480             }
7481 0           print STDERR CORE::reverse @cluck;
7482 0           print STDERR "\n";
7483 0           carp @_;
7484             }
7485              
7486             #
7487             # instead of Carp::confess
7488             #
7489             sub confess {
7490 0     0 0   my $i = 0;
7491 0           my @confess = ();
7492 0           while (my($package,$filename,$line,$subroutine) = caller($i)) {
7493 0           push @confess, "[$i] $filename($line) $package::$subroutine\n";
7494 0           $i++;
7495             }
7496 0           print STDERR CORE::reverse @confess;
7497 0           print STDERR "\n";
7498 0           croak @_;
7499             }
7500              
7501             1;
7502              
7503             __END__