File Coverage

blib/lib/Ekoi8u.pm
Criterion Covered Total %
statement 83 3085 2.6
branch 4 2674 0.1
condition 1 373 0.2
subroutine 36 125 28.8
pod 7 74 9.4
total 131 6331 2.0


line stmt bran cond sub pod time code
1             package Ekoi8u;
2             ######################################################################
3             #
4             # Ekoi8u - Run-time routines for KOI8U.pm
5             #
6             # http://search.cpan.org/dist/Char-KOI8U/
7             #
8             # Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015 INABA Hitoshi
9             ######################################################################
10              
11 200     200   5319 use 5.00503; # Galapagos Consensus 1998 for primetools
  200         841  
  200         14504  
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   31613 BEGIN { CORE::eval q{ use vars qw($VERSION) } }
  200     200   7892  
  200         386  
  200         40752  
27             $VERSION = '1.05';
28             $VERSION = CORE::eval $VERSION;
29              
30             BEGIN {
31 200 50   200   1744 if ($^X =~ / jperl /oxmsi) {
32 0         0 die __FILE__, ": needs perl(not jperl) 5.00503 or later. (\$^X==$^X)\n";
33             }
34 200         503 if (CORE::ord('A') == 193) {
35             die __FILE__, ": is not US-ASCII script (may be EBCDIC or EBCDIK script).\n";
36             }
37 200         35749 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   15973 CORE::eval q{
  200     200   1347  
  200     69   366  
  200         46151  
  69         13434  
  60         12425  
  78         27097  
  72         14623  
  60         12705  
  61         12368  
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       145752 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 { };
  0         0  
58 0         0 *utf8::decode = sub { 1 };
  0         0  
59 0         0 *utf8::is_utf8 = sub { };
  0         0  
60 0         0 *utf8::valid = sub { 1 };
  0         0  
61             }
62             }
63              
64             # instead of Symbol.pm
65             BEGIN {
66 200     200   638 my $genpkg = "Symbol::";
67 200         10479 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) && (Ekoi8u::index($name, '::') == -1) && (Ekoi8u::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   440 if (CORE::eval { local $@; CORE::require strict }) {
  200         370  
  200         2641  
115 200         32675 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   21585 BEGIN { CORE::eval q{ use vars qw($your_char) } } $your_char = q{[\x00-\xFF]};
  200     200   1280  
  200         345  
  200         14887  
145 200     200   14481 BEGIN { CORE::eval q{ use vars qw($qq_char ) } } $qq_char = qr/\\c[\x40-\x5F]|\\?(?:$your_char)/oxms;
  200     200   1324  
  200         334  
  200         15425  
146 200     200   16351 BEGIN { CORE::eval q{ use vars qw($q_char ) } } $q_char = qr/$your_char/oxms;
  200     200   1340  
  200         349  
  200         20037  
147              
148             #
149             # KOI8-U character range per length
150             #
151             my %range_tr = ();
152              
153             #
154             # alias of encoding name
155             #
156 200     200   16666 BEGIN { CORE::eval q{ use vars qw($encoding_alias) } }
  200     200   1802  
  200         746  
  200         486631  
157              
158             #
159             # KOI8-U 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 Ekoi8u \z/oxms) {
175             %range_tr = (
176             1 => [ [0x00..0xFF],
177             ],
178             );
179             $encoding_alias = qr/ \b (?: koi8-?u ) \b /oxmsi;
180              
181             %lc = (%lc,
182             "\xB3" => "\xA3", # CYRILLIC LETTER IO
183             "\xB4" => "\xA4", # CYRILLIC LETTER UKRAINIAN IE
184             "\xB6" => "\xA6", # CYRILLIC LETTER BYELORUSSIAN-UKRAINIAN I
185             "\xB7" => "\xA7", # CYRILLIC LETTER YI (UKRAINIAN)
186             "\xBD" => "\xAD", # CYRILLIC LETTER GHE WITH UPTURN
187             "\xE0" => "\xC0", # CYRILLIC LETTER YU
188             "\xE1" => "\xC1", # CYRILLIC LETTER A
189             "\xE2" => "\xC2", # CYRILLIC LETTER BE
190             "\xE3" => "\xC3", # CYRILLIC LETTER TSE
191             "\xE4" => "\xC4", # CYRILLIC LETTER DE
192             "\xE5" => "\xC5", # CYRILLIC LETTER IE
193             "\xE6" => "\xC6", # CYRILLIC LETTER EF
194             "\xE7" => "\xC7", # CYRILLIC LETTER GHE
195             "\xE8" => "\xC8", # CYRILLIC LETTER KHA
196             "\xE9" => "\xC9", # CYRILLIC LETTER I
197             "\xEA" => "\xCA", # CYRILLIC LETTER SHORT I
198             "\xEB" => "\xCB", # CYRILLIC LETTER KA
199             "\xEC" => "\xCC", # CYRILLIC LETTER EL
200             "\xED" => "\xCD", # CYRILLIC LETTER EM
201             "\xEE" => "\xCE", # CYRILLIC LETTER EN
202             "\xEF" => "\xCF", # CYRILLIC LETTER O
203             "\xF0" => "\xD0", # CYRILLIC LETTER PE
204             "\xF1" => "\xD1", # CYRILLIC LETTER YA
205             "\xF2" => "\xD2", # CYRILLIC LETTER ER
206             "\xF3" => "\xD3", # CYRILLIC LETTER ES
207             "\xF4" => "\xD4", # CYRILLIC LETTER TE
208             "\xF5" => "\xD5", # CYRILLIC LETTER U
209             "\xF6" => "\xD6", # CYRILLIC LETTER ZHE
210             "\xF7" => "\xD7", # CYRILLIC LETTER VE
211             "\xF8" => "\xD8", # CYRILLIC LETTER SOFT SIGN
212             "\xF9" => "\xD9", # CYRILLIC LETTER YERU
213             "\xFA" => "\xDA", # CYRILLIC LETTER ZE
214             "\xFB" => "\xDB", # CYRILLIC LETTER SHA
215             "\xFC" => "\xDC", # CYRILLIC LETTER E
216             "\xFD" => "\xDD", # CYRILLIC LETTER SHCHA
217             "\xFE" => "\xDE", # CYRILLIC LETTER CHE
218             "\xFF" => "\xDF", # CYRILLIC LETTER HARD SIGN
219             );
220              
221             %uc = (%uc,
222             "\xA3" => "\xB3", # CYRILLIC LETTER IO
223             "\xA4" => "\xB4", # CYRILLIC LETTER UKRAINIAN IE
224             "\xA6" => "\xB6", # CYRILLIC LETTER BYELORUSSIAN-UKRAINIAN I
225             "\xA7" => "\xB7", # CYRILLIC LETTER YI (UKRAINIAN)
226             "\xAD" => "\xBD", # CYRILLIC LETTER GHE WITH UPTURN
227             "\xC0" => "\xE0", # CYRILLIC LETTER YU
228             "\xC1" => "\xE1", # CYRILLIC LETTER A
229             "\xC2" => "\xE2", # CYRILLIC LETTER BE
230             "\xC3" => "\xE3", # CYRILLIC LETTER TSE
231             "\xC4" => "\xE4", # CYRILLIC LETTER DE
232             "\xC5" => "\xE5", # CYRILLIC LETTER IE
233             "\xC6" => "\xE6", # CYRILLIC LETTER EF
234             "\xC7" => "\xE7", # CYRILLIC LETTER GHE
235             "\xC8" => "\xE8", # CYRILLIC LETTER KHA
236             "\xC9" => "\xE9", # CYRILLIC LETTER I
237             "\xCA" => "\xEA", # CYRILLIC LETTER SHORT I
238             "\xCB" => "\xEB", # CYRILLIC LETTER KA
239             "\xCC" => "\xEC", # CYRILLIC LETTER EL
240             "\xCD" => "\xED", # CYRILLIC LETTER EM
241             "\xCE" => "\xEE", # CYRILLIC LETTER EN
242             "\xCF" => "\xEF", # CYRILLIC LETTER O
243             "\xD0" => "\xF0", # CYRILLIC LETTER PE
244             "\xD1" => "\xF1", # CYRILLIC LETTER YA
245             "\xD2" => "\xF2", # CYRILLIC LETTER ER
246             "\xD3" => "\xF3", # CYRILLIC LETTER ES
247             "\xD4" => "\xF4", # CYRILLIC LETTER TE
248             "\xD5" => "\xF5", # CYRILLIC LETTER U
249             "\xD6" => "\xF6", # CYRILLIC LETTER ZHE
250             "\xD7" => "\xF7", # CYRILLIC LETTER VE
251             "\xD8" => "\xF8", # CYRILLIC LETTER SOFT SIGN
252             "\xD9" => "\xF9", # CYRILLIC LETTER YERU
253             "\xDA" => "\xFA", # CYRILLIC LETTER ZE
254             "\xDB" => "\xFB", # CYRILLIC LETTER SHA
255             "\xDC" => "\xFC", # CYRILLIC LETTER E
256             "\xDD" => "\xFD", # CYRILLIC LETTER SHCHA
257             "\xDE" => "\xFE", # CYRILLIC LETTER CHE
258             "\xDF" => "\xFF", # CYRILLIC LETTER HARD SIGN
259             );
260              
261             %fc = (%fc,
262             "\xB3" => "\xA3", # CYRILLIC CAPITAL LETTER IO --> CYRILLIC SMALL LETTER IO
263             "\xB4" => "\xA4", # CYRILLIC CAPITAL LETTER UKRAINIAN IE --> CYRILLIC SMALL LETTER UKRAINIAN IE
264             "\xB6" => "\xA6", # CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I --> CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I
265             "\xB7" => "\xA7", # CYRILLIC CAPITAL LETTER YI --> CYRILLIC SMALL LETTER YI
266             "\xBD" => "\xAD", # CYRILLIC CAPITAL LETTER GHE WITH UPTURN --> CYRILLIC SMALL LETTER GHE WITH UPTURN
267             "\xE0" => "\xC0", # CYRILLIC CAPITAL LETTER YU --> CYRILLIC SMALL LETTER YU
268             "\xE1" => "\xC1", # CYRILLIC CAPITAL LETTER A --> CYRILLIC SMALL LETTER A
269             "\xE2" => "\xC2", # CYRILLIC CAPITAL LETTER BE --> CYRILLIC SMALL LETTER BE
270             "\xE3" => "\xC3", # CYRILLIC CAPITAL LETTER TSE --> CYRILLIC SMALL LETTER TSE
271             "\xE4" => "\xC4", # CYRILLIC CAPITAL LETTER DE --> CYRILLIC SMALL LETTER DE
272             "\xE5" => "\xC5", # CYRILLIC CAPITAL LETTER IE --> CYRILLIC SMALL LETTER IE
273             "\xE6" => "\xC6", # CYRILLIC CAPITAL LETTER EF --> CYRILLIC SMALL LETTER EF
274             "\xE7" => "\xC7", # CYRILLIC CAPITAL LETTER GHE --> CYRILLIC SMALL LETTER GHE
275             "\xE8" => "\xC8", # CYRILLIC CAPITAL LETTER HA --> CYRILLIC SMALL LETTER HA
276             "\xE9" => "\xC9", # CYRILLIC CAPITAL LETTER I --> CYRILLIC SMALL LETTER I
277             "\xEA" => "\xCA", # CYRILLIC CAPITAL LETTER SHORT I --> CYRILLIC SMALL LETTER SHORT I
278             "\xEB" => "\xCB", # CYRILLIC CAPITAL LETTER KA --> CYRILLIC SMALL LETTER KA
279             "\xEC" => "\xCC", # CYRILLIC CAPITAL LETTER EL --> CYRILLIC SMALL LETTER EL
280             "\xED" => "\xCD", # CYRILLIC CAPITAL LETTER EM --> CYRILLIC SMALL LETTER EM
281             "\xEE" => "\xCE", # CYRILLIC CAPITAL LETTER EN --> CYRILLIC SMALL LETTER EN
282             "\xEF" => "\xCF", # CYRILLIC CAPITAL LETTER O --> CYRILLIC SMALL LETTER O
283             "\xF0" => "\xD0", # CYRILLIC CAPITAL LETTER PE --> CYRILLIC SMALL LETTER PE
284             "\xF1" => "\xD1", # CYRILLIC CAPITAL LETTER YA --> CYRILLIC SMALL LETTER YA
285             "\xF2" => "\xD2", # CYRILLIC CAPITAL LETTER ER --> CYRILLIC SMALL LETTER ER
286             "\xF3" => "\xD3", # CYRILLIC CAPITAL LETTER ES --> CYRILLIC SMALL LETTER ES
287             "\xF4" => "\xD4", # CYRILLIC CAPITAL LETTER TE --> CYRILLIC SMALL LETTER TE
288             "\xF5" => "\xD5", # CYRILLIC CAPITAL LETTER U --> CYRILLIC SMALL LETTER U
289             "\xF6" => "\xD6", # CYRILLIC CAPITAL LETTER ZHE --> CYRILLIC SMALL LETTER ZHE
290             "\xF7" => "\xD7", # CYRILLIC CAPITAL LETTER VE --> CYRILLIC SMALL LETTER VE
291             "\xF8" => "\xD8", # CYRILLIC CAPITAL LETTER SOFT SIGN --> CYRILLIC SMALL LETTER SOFT SIGN
292             "\xF9" => "\xD9", # CYRILLIC CAPITAL LETTER YERU --> CYRILLIC SMALL LETTER YERU
293             "\xFA" => "\xDA", # CYRILLIC CAPITAL LETTER ZE --> CYRILLIC SMALL LETTER ZE
294             "\xFB" => "\xDB", # CYRILLIC CAPITAL LETTER SHA --> CYRILLIC SMALL LETTER SHA
295             "\xFC" => "\xDC", # CYRILLIC CAPITAL LETTER E --> CYRILLIC SMALL LETTER E
296             "\xFD" => "\xDD", # CYRILLIC CAPITAL LETTER SHCHA --> CYRILLIC SMALL LETTER SHCHA
297             "\xFE" => "\xDE", # CYRILLIC CAPITAL LETTER CHE --> CYRILLIC SMALL LETTER CHE
298             "\xFF" => "\xDF", # CYRILLIC CAPITAL LETTER HARD SIGN --> CYRILLIC SMALL LETTER HARD SIGN
299             );
300             }
301              
302             else {
303             croak "Don't know my package name '@{[__PACKAGE__]}'";
304             }
305              
306             #
307             # @ARGV wildcard globbing
308             #
309             sub import {
310              
311 0 0   0   0 if ($^O =~ /\A (?: MSWin32 | NetWare | symbian | dos ) \z/oxms) {
312 0         0 my @argv = ();
313 0         0 for (@ARGV) {
314              
315             # has space
316 0 0       0 if (/\A (?:$q_char)*? [ ] /oxms) {
    0          
317 0 0       0 if (my @glob = Ekoi8u::glob(qq{"$_"})) {
318 0         0 push @argv, @glob;
319             }
320             else {
321 0         0 push @argv, $_;
322             }
323             }
324              
325             # has wildcard metachar
326             elsif (/\A (?:$q_char)*? [*?] /oxms) {
327 0 0       0 if (my @glob = Ekoi8u::glob($_)) {
328 0         0 push @argv, @glob;
329             }
330             else {
331 0         0 push @argv, $_;
332             }
333             }
334              
335             # no wildcard globbing
336             else {
337 0         0 push @argv, $_;
338             }
339             }
340 0         0 @ARGV = @argv;
341             }
342              
343 0         0 *Char::ord = \&KOI8U::ord;
344 0         0 *Char::ord_ = \&KOI8U::ord_;
345 0         0 *Char::reverse = \&KOI8U::reverse;
346 0         0 *Char::getc = \&KOI8U::getc;
347 0         0 *Char::length = \&KOI8U::length;
348 0         0 *Char::substr = \&KOI8U::substr;
349 0         0 *Char::index = \&KOI8U::index;
350 0         0 *Char::rindex = \&KOI8U::rindex;
351 0         0 *Char::eval = \&KOI8U::eval;
352 0         0 *Char::escape = \&KOI8U::escape;
353 0         0 *Char::escape_token = \&KOI8U::escape_token;
354 0         0 *Char::escape_script = \&KOI8U::escape_script;
355             }
356              
357             # P.230 Care with Prototypes
358             # in Chapter 6: Subroutines
359             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
360             #
361             # If you aren't careful, you can get yourself into trouble with prototypes.
362             # But if you are careful, you can do a lot of neat things with them. This is
363             # all very powerful, of course, and should only be used in moderation to make
364             # the world a better place.
365              
366             # P.332 Care with Prototypes
367             # in Chapter 7: Subroutines
368             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
369             #
370             # If you aren't careful, you can get yourself into trouble with prototypes.
371             # But if you are careful, you can do a lot of neat things with them. This is
372             # all very powerful, of course, and should only be used in moderation to make
373             # the world a better place.
374              
375             #
376             # Prototypes of subroutines
377             #
378 0     0   0 sub unimport {}
379             sub Ekoi8u::split(;$$$);
380             sub Ekoi8u::tr($$$$;$);
381             sub Ekoi8u::chop(@);
382             sub Ekoi8u::index($$;$);
383             sub Ekoi8u::rindex($$;$);
384             sub Ekoi8u::lcfirst(@);
385             sub Ekoi8u::lcfirst_();
386             sub Ekoi8u::lc(@);
387             sub Ekoi8u::lc_();
388             sub Ekoi8u::ucfirst(@);
389             sub Ekoi8u::ucfirst_();
390             sub Ekoi8u::uc(@);
391             sub Ekoi8u::uc_();
392             sub Ekoi8u::fc(@);
393             sub Ekoi8u::fc_();
394             sub Ekoi8u::ignorecase;
395             sub Ekoi8u::classic_character_class;
396             sub Ekoi8u::capture;
397             sub Ekoi8u::chr(;$);
398             sub Ekoi8u::chr_();
399             sub Ekoi8u::glob($);
400             sub Ekoi8u::glob_();
401              
402             sub KOI8U::ord(;$);
403             sub KOI8U::ord_();
404             sub KOI8U::reverse(@);
405             sub KOI8U::getc(;*@);
406             sub KOI8U::length(;$);
407             sub KOI8U::substr($$;$$);
408             sub KOI8U::index($$;$);
409             sub KOI8U::rindex($$;$);
410             sub KOI8U::escape(;$);
411              
412             #
413             # Regexp work
414             #
415 200     200   17579 BEGIN { CORE::eval q{ use vars qw(
  200     200   1968  
  200         548  
  200         109361  
416             $KOI8U::re_a
417             $KOI8U::re_t
418             $KOI8U::re_n
419             $KOI8U::re_r
420             ) } }
421              
422             #
423             # Character class
424             #
425 200     200   18349 BEGIN { CORE::eval q{ use vars qw(
  200     200   1281  
  200         381  
  200         3594918  
426             $dot
427             $dot_s
428             $eD
429             $eS
430             $eW
431             $eH
432             $eV
433             $eR
434             $eN
435             $not_alnum
436             $not_alpha
437             $not_ascii
438             $not_blank
439             $not_cntrl
440             $not_digit
441             $not_graph
442             $not_lower
443             $not_lower_i
444             $not_print
445             $not_punct
446             $not_space
447             $not_upper
448             $not_upper_i
449             $not_word
450             $not_xdigit
451             $eb
452             $eB
453             ) } }
454              
455             ${Ekoi8u::dot} = qr{(?>[^\x0A])};
456             ${Ekoi8u::dot_s} = qr{(?>[\x00-\xFF])};
457             ${Ekoi8u::eD} = qr{(?>[^0-9])};
458              
459             # Vertical tabs are now whitespace
460             # \s in a regex now matches a vertical tab in all circumstances.
461             # http://search.cpan.org/dist/perl-5.18.0/pod/perldelta.pod#Vertical_tabs_are_now_whitespace
462             # ${Ekoi8u::eS} = qr{(?>[^\x09\x0A \x0C\x0D\x20])};
463             # ${Ekoi8u::eS} = qr{(?>[^\x09\x0A\x0B\x0C\x0D\x20])};
464             ${Ekoi8u::eS} = qr{(?>[^\s])};
465              
466             ${Ekoi8u::eW} = qr{(?>[^0-9A-Z_a-z])};
467             ${Ekoi8u::eH} = qr{(?>[^\x09\x20])};
468             ${Ekoi8u::eV} = qr{(?>[^\x0A\x0B\x0C\x0D])};
469             ${Ekoi8u::eR} = qr{(?>\x0D\x0A|[\x0A\x0D])};
470             ${Ekoi8u::eN} = qr{(?>[^\x0A])};
471             ${Ekoi8u::not_alnum} = qr{(?>[^\x30-\x39\x41-\x5A\x61-\x7A])};
472             ${Ekoi8u::not_alpha} = qr{(?>[^\x41-\x5A\x61-\x7A])};
473             ${Ekoi8u::not_ascii} = qr{(?>[^\x00-\x7F])};
474             ${Ekoi8u::not_blank} = qr{(?>[^\x09\x20])};
475             ${Ekoi8u::not_cntrl} = qr{(?>[^\x00-\x1F\x7F])};
476             ${Ekoi8u::not_digit} = qr{(?>[^\x30-\x39])};
477             ${Ekoi8u::not_graph} = qr{(?>[^\x21-\x7F])};
478             ${Ekoi8u::not_lower} = qr{(?>[^\x61-\x7A])};
479             ${Ekoi8u::not_lower_i} = qr{(?>[^\x41-\x5A\x61-\x7A])}; # Perl 5.16 compatible
480             # ${Ekoi8u::not_lower_i} = qr{(?>[\x00-\xFF])}; # older Perl compatible
481             ${Ekoi8u::not_print} = qr{(?>[^\x20-\x7F])};
482             ${Ekoi8u::not_punct} = qr{(?>[^\x21-\x2F\x3A-\x3F\x40\x5B-\x5F\x60\x7B-\x7E])};
483             ${Ekoi8u::not_space} = qr{(?>[^\s\x0B])};
484             ${Ekoi8u::not_upper} = qr{(?>[^\x41-\x5A])};
485             ${Ekoi8u::not_upper_i} = qr{(?>[^\x41-\x5A\x61-\x7A])}; # Perl 5.16 compatible
486             # ${Ekoi8u::not_upper_i} = qr{(?>[\x00-\xFF])}; # older Perl compatible
487             ${Ekoi8u::not_word} = qr{(?>[^\x30-\x39\x41-\x5A\x5F\x61-\x7A])};
488             ${Ekoi8u::not_xdigit} = qr{(?>[^\x30-\x39\x41-\x46\x61-\x66])};
489             ${Ekoi8u::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))};
490             ${Ekoi8u::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]))};
491              
492             # avoid: Name "Ekoi8u::foo" used only once: possible typo at here.
493             ${Ekoi8u::dot} = ${Ekoi8u::dot};
494             ${Ekoi8u::dot_s} = ${Ekoi8u::dot_s};
495             ${Ekoi8u::eD} = ${Ekoi8u::eD};
496             ${Ekoi8u::eS} = ${Ekoi8u::eS};
497             ${Ekoi8u::eW} = ${Ekoi8u::eW};
498             ${Ekoi8u::eH} = ${Ekoi8u::eH};
499             ${Ekoi8u::eV} = ${Ekoi8u::eV};
500             ${Ekoi8u::eR} = ${Ekoi8u::eR};
501             ${Ekoi8u::eN} = ${Ekoi8u::eN};
502             ${Ekoi8u::not_alnum} = ${Ekoi8u::not_alnum};
503             ${Ekoi8u::not_alpha} = ${Ekoi8u::not_alpha};
504             ${Ekoi8u::not_ascii} = ${Ekoi8u::not_ascii};
505             ${Ekoi8u::not_blank} = ${Ekoi8u::not_blank};
506             ${Ekoi8u::not_cntrl} = ${Ekoi8u::not_cntrl};
507             ${Ekoi8u::not_digit} = ${Ekoi8u::not_digit};
508             ${Ekoi8u::not_graph} = ${Ekoi8u::not_graph};
509             ${Ekoi8u::not_lower} = ${Ekoi8u::not_lower};
510             ${Ekoi8u::not_lower_i} = ${Ekoi8u::not_lower_i};
511             ${Ekoi8u::not_print} = ${Ekoi8u::not_print};
512             ${Ekoi8u::not_punct} = ${Ekoi8u::not_punct};
513             ${Ekoi8u::not_space} = ${Ekoi8u::not_space};
514             ${Ekoi8u::not_upper} = ${Ekoi8u::not_upper};
515             ${Ekoi8u::not_upper_i} = ${Ekoi8u::not_upper_i};
516             ${Ekoi8u::not_word} = ${Ekoi8u::not_word};
517             ${Ekoi8u::not_xdigit} = ${Ekoi8u::not_xdigit};
518             ${Ekoi8u::eb} = ${Ekoi8u::eb};
519             ${Ekoi8u::eB} = ${Ekoi8u::eB};
520              
521             #
522             # KOI8-U split
523             #
524             sub Ekoi8u::split(;$$$) {
525              
526             # P.794 29.2.161. split
527             # in Chapter 29: Functions
528             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
529              
530             # P.951 split
531             # in Chapter 27: Functions
532             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
533              
534 0     0 0 0 my $pattern = $_[0];
535 0         0 my $string = $_[1];
536 0         0 my $limit = $_[2];
537              
538             # if $pattern is also omitted or is the literal space, " "
539 0 0       0 if (not defined $pattern) {
540 0         0 $pattern = ' ';
541             }
542              
543             # if $string is omitted, the function splits the $_ string
544 0 0       0 if (not defined $string) {
545 0 0       0 if (defined $_) {
546 0         0 $string = $_;
547             }
548             else {
549 0         0 $string = '';
550             }
551             }
552              
553 0         0 my @split = ();
554              
555             # when string is empty
556 0 0       0 if ($string eq '') {
    0          
557              
558             # resulting list value in list context
559 0 0       0 if (wantarray) {
560 0         0 return @split;
561             }
562              
563             # count of substrings in scalar context
564             else {
565 0 0       0 carp "Use of implicit split to \@_ is deprecated" if $^W;
566 0         0 @_ = @split;
567 0         0 return scalar @_;
568             }
569             }
570              
571             # split's first argument is more consistently interpreted
572             #
573             # After some changes earlier in v5.17, split's behavior has been simplified:
574             # if the PATTERN argument evaluates to a string containing one space, it is
575             # treated the way that a literal string containing one space once was.
576             # http://search.cpan.org/dist/perl-5.18.0/pod/perldelta.pod#split's_first_argument_is_more_consistently_interpreted
577              
578             # if $pattern is also omitted or is the literal space, " ", the function splits
579             # on whitespace, /\s+/, after skipping any leading whitespace
580             # (and so on)
581              
582             elsif ($pattern eq ' ') {
583 0 0       0 if (not defined $limit) {
584 0         0 return CORE::split(' ', $string);
585             }
586             else {
587 0         0 return CORE::split(' ', $string, $limit);
588             }
589             }
590              
591             # if $limit is negative, it is treated as if an arbitrarily large $limit has been specified
592 0 0 0     0 if ((not defined $limit) or ($limit <= 0)) {
    0          
593              
594             # a pattern capable of matching either the null string or something longer than the
595             # null string will split the value of $string into separate characters wherever it
596             # matches the null string between characters
597             # (and so on)
598              
599 0 0       0 if ('' =~ / \A $pattern \z /xms) {
600 0         0 my $last_subexpression_offsets = _last_subexpression_offsets($pattern);
601 0         0 my $limit = scalar(() = $string =~ /($pattern)/oxmsg);
602              
603             # P.1024 Appendix W.10 Multibyte Processing
604             # of ISBN 1-56592-224-7 CJKV Information Processing
605             # (and so on)
606              
607             # the //m modifier is assumed when you split on the pattern /^/
608             # (and so on)
609              
610             # V
611 0   0     0 while ((--$limit > 0) and ($string =~ s/\A((?:$q_char)+?)$pattern//m)) {
612              
613             # if the $pattern contains parentheses, then the substring matched by each pair of parentheses
614             # is included in the resulting list, interspersed with the fields that are ordinarily returned
615             # (and so on)
616              
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             else {
625 0         0 my $last_subexpression_offsets = _last_subexpression_offsets($pattern);
626              
627             # V
628 0         0 while ($string =~ s/\A((?:$q_char)*?)$pattern//m) {
629 0         0 local $@;
630 0         0 for (my $digit=1; $digit <= ($last_subexpression_offsets + 1); $digit++) {
631 0         0 push @split, CORE::eval('$' . $digit);
632             }
633             }
634             }
635             }
636              
637             elsif ($limit > 0) {
638 0 0       0 if ('' =~ / \A $pattern \z /xms) {
639 0         0 my $last_subexpression_offsets = _last_subexpression_offsets($pattern);
640 0   0     0 while ((--$limit > 0) and (CORE::length($string) > 0)) {
641              
642             # V
643 0 0       0 if ($string =~ s/\A((?:$q_char)+?)$pattern//m) {
644 0         0 local $@;
645 0         0 for (my $digit=1; $digit <= ($last_subexpression_offsets + 1); $digit++) {
646 0         0 push @split, CORE::eval('$' . $digit);
647             }
648             }
649             }
650             }
651             else {
652 0         0 my $last_subexpression_offsets = _last_subexpression_offsets($pattern);
653 0   0     0 while ((--$limit > 0) and (CORE::length($string) > 0)) {
654              
655             # V
656 0 0       0 if ($string =~ s/\A((?:$q_char)*?)$pattern//m) {
657 0         0 local $@;
658 0         0 for (my $digit=1; $digit <= ($last_subexpression_offsets + 1); $digit++) {
659 0         0 push @split, CORE::eval('$' . $digit);
660             }
661             }
662             }
663             }
664             }
665              
666 0 0       0 if (CORE::length($string) > 0) {
667 0         0 push @split, $string;
668             }
669              
670             # if $_[2] (NOT "$limit") is omitted or zero, trailing null fields are stripped from the result
671 0 0 0     0 if ((not defined $_[2]) or ($_[2] == 0)) {
672 0   0     0 while ((scalar(@split) >= 1) and ($split[-1] eq '')) {
673 0         0 pop @split;
674             }
675             }
676              
677             # resulting list value in list context
678 0 0       0 if (wantarray) {
679 0         0 return @split;
680             }
681              
682             # count of substrings in scalar context
683             else {
684 0 0       0 carp "Use of implicit split to \@_ is deprecated" if $^W;
685 0         0 @_ = @split;
686 0         0 return scalar @_;
687             }
688             }
689              
690             #
691             # get last subexpression offsets
692             #
693             sub _last_subexpression_offsets {
694 0     0   0 my $pattern = $_[0];
695              
696             # remove comment
697 0         0 $pattern =~ s/\(\?\# .*? \)//oxmsg;
698              
699 0         0 my $modifier = '';
700 0 0       0 if ($pattern =~ /\(\?\^? ([\-A-Za-z]+) :/oxms) {
701 0         0 $modifier = $1;
702 0         0 $modifier =~ s/-[A-Za-z]*//;
703             }
704              
705             # with /x modifier
706 0         0 my @char = ();
707 0 0       0 if ($modifier =~ /x/oxms) {
708 0         0 @char = $pattern =~ /\G((?>
709             [^\\\#\[\(] |
710             \\ $q_char |
711             \# (?>[^\n]*) $ |
712             \[ (?>(?:[^\\\]]|\\\\|\\\]|$q_char)+) \] |
713             \(\? |
714             $q_char
715             ))/oxmsg;
716             }
717              
718             # without /x modifier
719             else {
720 0         0 @char = $pattern =~ /\G((?>
721             [^\\\[\(] |
722             \\ $q_char |
723             \[ (?>(?:[^\\\]]|\\\\|\\\]|$q_char)+) \] |
724             \(\? |
725             $q_char
726             ))/oxmsg;
727             }
728              
729 0         0 return scalar grep { $_ eq '(' } @char;
  0         0  
730             }
731              
732             #
733             # KOI8-U transliteration (tr///)
734             #
735             sub Ekoi8u::tr($$$$;$) {
736              
737 0     0 0 0 my $bind_operator = $_[1];
738 0         0 my $searchlist = $_[2];
739 0         0 my $replacementlist = $_[3];
740 0   0     0 my $modifier = $_[4] || '';
741              
742 0 0       0 if ($modifier =~ /r/oxms) {
743 0 0       0 if ($bind_operator =~ / !~ /oxms) {
744 0         0 croak "Using !~ with tr///r doesn't make sense";
745             }
746             }
747              
748 0         0 my @char = $_[0] =~ /\G (?>$q_char) /oxmsg;
749 0         0 my @searchlist = _charlist_tr($searchlist);
750 0         0 my @replacementlist = _charlist_tr($replacementlist);
751              
752 0         0 my %tr = ();
753 0         0 for (my $i=0; $i <= $#searchlist; $i++) {
754 0 0       0 if (not exists $tr{$searchlist[$i]}) {
755 0 0 0     0 if (defined $replacementlist[$i] and ($replacementlist[$i] ne '')) {
    0 0        
    0          
756 0         0 $tr{$searchlist[$i]} = $replacementlist[$i];
757             }
758             elsif ($modifier =~ /d/oxms) {
759 0         0 $tr{$searchlist[$i]} = '';
760             }
761             elsif (defined $replacementlist[-1] and ($replacementlist[-1] ne '')) {
762 0         0 $tr{$searchlist[$i]} = $replacementlist[-1];
763             }
764             else {
765 0         0 $tr{$searchlist[$i]} = $searchlist[$i];
766             }
767             }
768             }
769              
770 0         0 my $tr = 0;
771 0         0 my $replaced = '';
772 0 0       0 if ($modifier =~ /c/oxms) {
773 0         0 while (defined(my $char = shift @char)) {
774 0 0       0 if (not exists $tr{$char}) {
775 0 0       0 if (defined $replacementlist[0]) {
776 0         0 $replaced .= $replacementlist[0];
777             }
778 0         0 $tr++;
779 0 0       0 if ($modifier =~ /s/oxms) {
780 0   0     0 while (@char and (not exists $tr{$char[0]})) {
781 0         0 shift @char;
782 0         0 $tr++;
783             }
784             }
785             }
786             else {
787 0         0 $replaced .= $char;
788             }
789             }
790             }
791             else {
792 0         0 while (defined(my $char = shift @char)) {
793 0 0       0 if (exists $tr{$char}) {
794 0         0 $replaced .= $tr{$char};
795 0         0 $tr++;
796 0 0       0 if ($modifier =~ /s/oxms) {
797 0   0     0 while (@char and (exists $tr{$char[0]}) and ($tr{$char[0]} eq $tr{$char})) {
      0        
798 0         0 shift @char;
799 0         0 $tr++;
800             }
801             }
802             }
803             else {
804 0         0 $replaced .= $char;
805             }
806             }
807             }
808              
809 0 0       0 if ($modifier =~ /r/oxms) {
810 0         0 return $replaced;
811             }
812             else {
813 0         0 $_[0] = $replaced;
814 0 0       0 if ($bind_operator =~ / !~ /oxms) {
815 0         0 return not $tr;
816             }
817             else {
818 0         0 return $tr;
819             }
820             }
821             }
822              
823             #
824             # KOI8-U chop
825             #
826             sub Ekoi8u::chop(@) {
827              
828 0     0 0 0 my $chop;
829 0 0       0 if (@_ == 0) {
830 0         0 my @char = /\G (?>$q_char) /oxmsg;
831 0         0 $chop = pop @char;
832 0         0 $_ = join '', @char;
833             }
834             else {
835 0         0 for (@_) {
836 0         0 my @char = /\G (?>$q_char) /oxmsg;
837 0         0 $chop = pop @char;
838 0         0 $_ = join '', @char;
839             }
840             }
841 0         0 return $chop;
842             }
843              
844             #
845             # KOI8-U index by octet
846             #
847             sub Ekoi8u::index($$;$) {
848              
849 0     0 1 0 my($str,$substr,$position) = @_;
850 0   0     0 $position ||= 0;
851 0         0 my $pos = 0;
852              
853 0         0 while ($pos < CORE::length($str)) {
854 0 0       0 if (CORE::substr($str,$pos,CORE::length($substr)) eq $substr) {
855 0 0       0 if ($pos >= $position) {
856 0         0 return $pos;
857             }
858             }
859 0 0       0 if (CORE::substr($str,$pos) =~ /\A ($q_char) /oxms) {
860 0         0 $pos += CORE::length($1);
861             }
862             else {
863 0         0 $pos += 1;
864             }
865             }
866 0         0 return -1;
867             }
868              
869             #
870             # KOI8-U reverse index
871             #
872             sub Ekoi8u::rindex($$;$) {
873              
874 0     0 0 0 my($str,$substr,$position) = @_;
875 0   0     0 $position ||= CORE::length($str) - 1;
876 0         0 my $pos = 0;
877 0         0 my $rindex = -1;
878              
879 0   0     0 while (($pos < CORE::length($str)) and ($pos <= $position)) {
880 0 0       0 if (CORE::substr($str,$pos,CORE::length($substr)) eq $substr) {
881 0         0 $rindex = $pos;
882             }
883 0 0       0 if (CORE::substr($str,$pos) =~ /\A ($q_char) /oxms) {
884 0         0 $pos += CORE::length($1);
885             }
886             else {
887 0         0 $pos += 1;
888             }
889             }
890 0         0 return $rindex;
891             }
892              
893             #
894             # KOI8-U lower case first with parameter
895             #
896             sub Ekoi8u::lcfirst(@) {
897 0 0   0 0 0 if (@_) {
898 0         0 my $s = shift @_;
899 0 0 0     0 if (@_ and wantarray) {
900 0         0 return Ekoi8u::lc(CORE::substr($s,0,1)) . CORE::substr($s,1), @_;
901             }
902             else {
903 0         0 return Ekoi8u::lc(CORE::substr($s,0,1)) . CORE::substr($s,1);
904             }
905             }
906             else {
907 0         0 return Ekoi8u::lc(CORE::substr($_,0,1)) . CORE::substr($_,1);
908             }
909             }
910              
911             #
912             # KOI8-U lower case first without parameter
913             #
914             sub Ekoi8u::lcfirst_() {
915 0     0 0 0 return Ekoi8u::lc(CORE::substr($_,0,1)) . CORE::substr($_,1);
916             }
917              
918             #
919             # KOI8-U lower case with parameter
920             #
921             sub Ekoi8u::lc(@) {
922 0 0   0 0 0 if (@_) {
923 0         0 my $s = shift @_;
924 0 0 0     0 if (@_ and wantarray) {
925 0 0       0 return join('', map {defined($lc{$_}) ? $lc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg)), @_;
  0         0  
926             }
927             else {
928 0 0       0 return join('', map {defined($lc{$_}) ? $lc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg));
  0         0  
929             }
930             }
931             else {
932 0         0 return Ekoi8u::lc_();
933             }
934             }
935              
936             #
937             # KOI8-U lower case without parameter
938             #
939             sub Ekoi8u::lc_() {
940 0     0 0 0 my $s = $_;
941 0 0       0 return join '', map {defined($lc{$_}) ? $lc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg);
  0         0  
942             }
943              
944             #
945             # KOI8-U upper case first with parameter
946             #
947             sub Ekoi8u::ucfirst(@) {
948 0 0   0 0 0 if (@_) {
949 0         0 my $s = shift @_;
950 0 0 0     0 if (@_ and wantarray) {
951 0         0 return Ekoi8u::uc(CORE::substr($s,0,1)) . CORE::substr($s,1), @_;
952             }
953             else {
954 0         0 return Ekoi8u::uc(CORE::substr($s,0,1)) . CORE::substr($s,1);
955             }
956             }
957             else {
958 0         0 return Ekoi8u::uc(CORE::substr($_,0,1)) . CORE::substr($_,1);
959             }
960             }
961              
962             #
963             # KOI8-U upper case first without parameter
964             #
965             sub Ekoi8u::ucfirst_() {
966 0     0 0 0 return Ekoi8u::uc(CORE::substr($_,0,1)) . CORE::substr($_,1);
967             }
968              
969             #
970             # KOI8-U upper case with parameter
971             #
972             sub Ekoi8u::uc(@) {
973 0 0   0 0 0 if (@_) {
974 0         0 my $s = shift @_;
975 0 0 0     0 if (@_ and wantarray) {
976 0 0       0 return join('', map {defined($uc{$_}) ? $uc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg)), @_;
  0         0  
977             }
978             else {
979 0 0       0 return join('', map {defined($uc{$_}) ? $uc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg));
  0         0  
980             }
981             }
982             else {
983 0         0 return Ekoi8u::uc_();
984             }
985             }
986              
987             #
988             # KOI8-U upper case without parameter
989             #
990             sub Ekoi8u::uc_() {
991 0     0 0 0 my $s = $_;
992 0 0       0 return join '', map {defined($uc{$_}) ? $uc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg);
  0         0  
993             }
994              
995             #
996             # KOI8-U fold case with parameter
997             #
998             sub Ekoi8u::fc(@) {
999 0 0   0 0 0 if (@_) {
1000 0         0 my $s = shift @_;
1001 0 0 0     0 if (@_ and wantarray) {
1002 0 0       0 return join('', map {defined($fc{$_}) ? $fc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg)), @_;
  0         0  
1003             }
1004             else {
1005 0 0       0 return join('', map {defined($fc{$_}) ? $fc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg));
  0         0  
1006             }
1007             }
1008             else {
1009 0         0 return Ekoi8u::fc_();
1010             }
1011             }
1012              
1013             #
1014             # KOI8-U fold case without parameter
1015             #
1016             sub Ekoi8u::fc_() {
1017 0     0 0 0 my $s = $_;
1018 0 0       0 return join '', map {defined($fc{$_}) ? $fc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg);
  0         0  
1019             }
1020              
1021             #
1022             # KOI8-U regexp capture
1023             #
1024             {
1025             sub Ekoi8u::capture {
1026 0     0 1 0 return $_[0];
1027             }
1028             }
1029              
1030             #
1031             # KOI8-U regexp ignore case modifier
1032             #
1033             sub Ekoi8u::ignorecase {
1034              
1035 0     0 0 0 my @string = @_;
1036 0         0 my $metachar = qr/[\@\\|[\]{]/oxms;
1037              
1038             # ignore case of $scalar or @array
1039 0         0 for my $string (@string) {
1040              
1041             # split regexp
1042 0         0 my @char = $string =~ /\G (?>\[\^|\\$q_char|$q_char) /oxmsg;
1043              
1044             # unescape character
1045 0         0 for (my $i=0; $i <= $#char; $i++) {
1046 0 0       0 next if not defined $char[$i];
1047              
1048             # open character class [...]
1049 0 0       0 if ($char[$i] eq '[') {
    0          
    0          
    0          
1050 0         0 my $left = $i;
1051              
1052             # [] make die "unmatched [] in regexp ...\n"
1053              
1054 0 0       0 if ($char[$i+1] eq ']') {
1055 0         0 $i++;
1056             }
1057              
1058 0         0 while (1) {
1059 0 0       0 if (++$i > $#char) {
1060 0         0 croak "Unmatched [] in regexp";
1061             }
1062 0 0       0 if ($char[$i] eq ']') {
1063 0         0 my $right = $i;
1064 0         0 my @charlist = charlist_qr(@char[$left+1..$right-1], 'i');
1065              
1066             # escape character
1067 0         0 for my $char (@charlist) {
1068 0 0       0 if (0) {
1069             }
1070              
1071 0         0 elsif ($char =~ /\A [.|)] \z/oxms) {
1072 0         0 $char = '\\' . $char;
1073             }
1074             }
1075              
1076             # [...]
1077 0         0 splice @char, $left, $right-$left+1, '(?:' . join('|', @charlist) . ')';
1078              
1079 0         0 $i = $left;
1080 0         0 last;
1081             }
1082             }
1083             }
1084              
1085             # open character class [^...]
1086             elsif ($char[$i] eq '[^') {
1087 0         0 my $left = $i;
1088              
1089             # [^] make die "unmatched [] in regexp ...\n"
1090              
1091 0 0       0 if ($char[$i+1] eq ']') {
1092 0         0 $i++;
1093             }
1094              
1095 0         0 while (1) {
1096 0 0       0 if (++$i > $#char) {
1097 0         0 croak "Unmatched [] in regexp";
1098             }
1099 0 0       0 if ($char[$i] eq ']') {
1100 0         0 my $right = $i;
1101 0         0 my @charlist = charlist_not_qr(@char[$left+1..$right-1], 'i');
1102              
1103             # escape character
1104 0         0 for my $char (@charlist) {
1105 0 0       0 if (0) {
1106             }
1107              
1108 0         0 elsif ($char =~ /\A [.|)] \z/oxms) {
1109 0         0 $char = '\\' . $char;
1110             }
1111             }
1112              
1113             # [^...]
1114 0         0 splice @char, $left, $right-$left+1, '(?!' . join('|', @charlist) . ")(?:$your_char)";
1115              
1116 0         0 $i = $left;
1117 0         0 last;
1118             }
1119             }
1120             }
1121              
1122             # rewrite classic character class or escape character
1123             elsif (my $char = classic_character_class($char[$i])) {
1124 0         0 $char[$i] = $char;
1125             }
1126              
1127             # with /i modifier
1128             elsif ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) {
1129 0         0 my $uc = Ekoi8u::uc($char[$i]);
1130 0         0 my $fc = Ekoi8u::fc($char[$i]);
1131 0 0       0 if ($uc ne $fc) {
1132 0 0       0 if (CORE::length($fc) == 1) {
1133 0         0 $char[$i] = '[' . $uc . $fc . ']';
1134             }
1135             else {
1136 0         0 $char[$i] = '(?:' . $uc . '|' . $fc . ')';
1137             }
1138             }
1139             }
1140             }
1141              
1142             # characterize
1143 0         0 for (my $i=0; $i <= $#char; $i++) {
1144 0 0       0 next if not defined $char[$i];
1145              
1146 0 0       0 if (0) {
1147             }
1148              
1149             # quote character before ? + * {
1150 0 0       0 elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
1151 0 0       0 if ($char[$i-1] !~ /\A [\x00-\xFF] \z/oxms) {
1152 0         0 $char[$i-1] = '(?:' . $char[$i-1] . ')';
1153             }
1154             }
1155             }
1156              
1157 0         0 $string = join '', @char;
1158             }
1159              
1160             # make regexp string
1161 0         0 return @string;
1162             }
1163              
1164             #
1165             # classic character class ( \D \S \W \d \s \w \C \X \H \V \h \v \R \N \b \B )
1166             #
1167             sub Ekoi8u::classic_character_class {
1168 0     0 0 0 my($char) = @_;
1169              
1170             return {
1171 0   0     0 '\D' => '${Ekoi8u::eD}',
1172             '\S' => '${Ekoi8u::eS}',
1173             '\W' => '${Ekoi8u::eW}',
1174             '\d' => '[0-9]',
1175              
1176             # Before Perl 5.6, \s only matched the five whitespace characters
1177             # tab, newline, form-feed, carriage return, and the space character
1178             # itself, which, taken together, is the character class [\t\n\f\r ].
1179              
1180             # Vertical tabs are now whitespace
1181             # \s in a regex now matches a vertical tab in all circumstances.
1182             # http://search.cpan.org/dist/perl-5.18.0/pod/perldelta.pod#Vertical_tabs_are_now_whitespace
1183             # \t \n \v \f \r space
1184             # '\s' => '[\x09\x0A \x0C\x0D\x20]',
1185             # '\s' => '[\x09\x0A\x0B\x0C\x0D\x20]',
1186             '\s' => '\s',
1187              
1188             '\w' => '[0-9A-Z_a-z]',
1189             '\C' => '[\x00-\xFF]',
1190             '\X' => 'X',
1191              
1192             # \h \v \H \V
1193              
1194             # P.114 Character Class Shortcuts
1195             # in Chapter 7: In the World of Regular Expressions
1196             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
1197              
1198             # P.357 13.2.3 Whitespace
1199             # in Chapter 13: perlrecharclass: Perl Regular Expression Character Classes
1200             # of ISBN-13: 978-1-906966-02-7 The Perl Language Reference Manual (for Perl version 5.12.1)
1201             #
1202             # 0x00009 CHARACTER TABULATION h s
1203             # 0x0000a LINE FEED (LF) vs
1204             # 0x0000b LINE TABULATION v
1205             # 0x0000c FORM FEED (FF) vs
1206             # 0x0000d CARRIAGE RETURN (CR) vs
1207             # 0x00020 SPACE h s
1208              
1209             # P.196 Table 5-9. Alphanumeric regex metasymbols
1210             # in Chapter 5. Pattern Matching
1211             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
1212              
1213             # (and so on)
1214              
1215             '\H' => '${Ekoi8u::eH}',
1216             '\V' => '${Ekoi8u::eV}',
1217             '\h' => '[\x09\x20]',
1218             '\v' => '[\x0A\x0B\x0C\x0D]',
1219             '\R' => '${Ekoi8u::eR}',
1220              
1221             # \N
1222             #
1223             # http://perldoc.perl.org/perlre.html
1224             # Character Classes and other Special Escapes
1225             # Any character but \n (experimental). Not affected by /s modifier
1226              
1227             '\N' => '${Ekoi8u::eN}',
1228              
1229             # \b \B
1230              
1231             # P.180 Boundaries: The \b and \B Assertions
1232             # in Chapter 5: Pattern Matching
1233             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
1234              
1235             # P.219 Boundaries: The \b and \B Assertions
1236             # in Chapter 5: Pattern Matching
1237             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
1238              
1239             # \b really means (?:(?<=\w)(?!\w)|(?
1240             # or (?:(?<=\A|\W)(?=\w)|(?<=\w)(?=\W|\z))
1241             '\b' => '${Ekoi8u::eb}',
1242              
1243             # \B really means (?:(?<=\w)(?=\w)|(?
1244             # or (?:(?<=\w)(?=\w)|(?<=\W)(?=\W))
1245             '\B' => '${Ekoi8u::eB}',
1246              
1247             }->{$char} || '';
1248             }
1249              
1250             #
1251             # prepare KOI8-U characters per length
1252             #
1253              
1254             # 1 octet characters
1255             my @chars1 = ();
1256             sub chars1 {
1257 0 0   0 0 0 if (@chars1) {
1258 0         0 return @chars1;
1259             }
1260 0 0       0 if (exists $range_tr{1}) {
1261 0         0 my @ranges = @{ $range_tr{1} };
  0         0  
1262 0         0 while (my @range = splice(@ranges,0,1)) {
1263 0         0 for my $oct0 (@{$range[0]}) {
  0         0  
1264 0         0 push @chars1, pack 'C', $oct0;
1265             }
1266             }
1267             }
1268 0         0 return @chars1;
1269             }
1270              
1271             # 2 octets characters
1272             my @chars2 = ();
1273             sub chars2 {
1274 0 0   0 0 0 if (@chars2) {
1275 0         0 return @chars2;
1276             }
1277 0 0       0 if (exists $range_tr{2}) {
1278 0         0 my @ranges = @{ $range_tr{2} };
  0         0  
1279 0         0 while (my @range = splice(@ranges,0,2)) {
1280 0         0 for my $oct0 (@{$range[0]}) {
  0         0  
1281 0         0 for my $oct1 (@{$range[1]}) {
  0         0  
1282 0         0 push @chars2, pack 'CC', $oct0,$oct1;
1283             }
1284             }
1285             }
1286             }
1287 0         0 return @chars2;
1288             }
1289              
1290             # 3 octets characters
1291             my @chars3 = ();
1292             sub chars3 {
1293 0 0   0 0 0 if (@chars3) {
1294 0         0 return @chars3;
1295             }
1296 0 0       0 if (exists $range_tr{3}) {
1297 0         0 my @ranges = @{ $range_tr{3} };
  0         0  
1298 0         0 while (my @range = splice(@ranges,0,3)) {
1299 0         0 for my $oct0 (@{$range[0]}) {
  0         0  
1300 0         0 for my $oct1 (@{$range[1]}) {
  0         0  
1301 0         0 for my $oct2 (@{$range[2]}) {
  0         0  
1302 0         0 push @chars3, pack 'CCC', $oct0,$oct1,$oct2;
1303             }
1304             }
1305             }
1306             }
1307             }
1308 0         0 return @chars3;
1309             }
1310              
1311             # 4 octets characters
1312             my @chars4 = ();
1313             sub chars4 {
1314 0 0   0 0 0 if (@chars4) {
1315 0         0 return @chars4;
1316             }
1317 0 0       0 if (exists $range_tr{4}) {
1318 0         0 my @ranges = @{ $range_tr{4} };
  0         0  
1319 0         0 while (my @range = splice(@ranges,0,4)) {
1320 0         0 for my $oct0 (@{$range[0]}) {
  0         0  
1321 0         0 for my $oct1 (@{$range[1]}) {
  0         0  
1322 0         0 for my $oct2 (@{$range[2]}) {
  0         0  
1323 0         0 for my $oct3 (@{$range[3]}) {
  0         0  
1324 0         0 push @chars4, pack 'CCCC', $oct0,$oct1,$oct2,$oct3;
1325             }
1326             }
1327             }
1328             }
1329             }
1330             }
1331 0         0 return @chars4;
1332             }
1333              
1334             #
1335             # KOI8-U open character list for tr
1336             #
1337             sub _charlist_tr {
1338              
1339 0     0   0 local $_ = shift @_;
1340              
1341             # unescape character
1342 0         0 my @char = ();
1343 0         0 while (not /\G \z/oxmsgc) {
1344 0 0       0 if (/\G (\\0?55|\\x2[Dd]|\\-) /oxmsgc) {
    0          
    0          
    0          
    0          
    0          
    0          
1345 0         0 push @char, '\-';
1346             }
1347             elsif (/\G \\ ([0-7]{2,3}) /oxmsgc) {
1348 0         0 push @char, CORE::chr(oct $1);
1349             }
1350             elsif (/\G \\x ([0-9A-Fa-f]{1,2}) /oxmsgc) {
1351 0         0 push @char, CORE::chr(hex $1);
1352             }
1353             elsif (/\G \\c ([\x40-\x5F]) /oxmsgc) {
1354 0         0 push @char, CORE::chr(CORE::ord($1) & 0x1F);
1355             }
1356             elsif (/\G (\\ [0nrtfbae]) /oxmsgc) {
1357 0         0 push @char, {
1358             '\0' => "\0",
1359             '\n' => "\n",
1360             '\r' => "\r",
1361             '\t' => "\t",
1362             '\f' => "\f",
1363             '\b' => "\x08", # \b means backspace in character class
1364             '\a' => "\a",
1365             '\e' => "\e",
1366             }->{$1};
1367             }
1368             elsif (/\G \\ ($q_char) /oxmsgc) {
1369 0         0 push @char, $1;
1370             }
1371             elsif (/\G ($q_char) /oxmsgc) {
1372 0         0 push @char, $1;
1373             }
1374             }
1375              
1376             # join separated multiple-octet
1377 0         0 @char = join('',@char) =~ /\G (?>\\-|$q_char) /oxmsg;
1378              
1379             # unescape '-'
1380 0         0 my @i = ();
1381 0         0 for my $i (0 .. $#char) {
1382 0 0       0 if ($char[$i] eq '\-') {
    0          
1383 0         0 $char[$i] = '-';
1384             }
1385             elsif ($char[$i] eq '-') {
1386 0 0 0     0 if ((0 < $i) and ($i < $#char)) {
1387 0         0 push @i, $i;
1388             }
1389             }
1390             }
1391              
1392             # open character list (reverse for splice)
1393 0         0 for my $i (CORE::reverse @i) {
1394 0         0 my @range = ();
1395              
1396             # range error
1397 0 0 0     0 if ((CORE::length($char[$i-1]) > CORE::length($char[$i+1])) or ($char[$i-1] gt $char[$i+1])) {
1398 0         0 croak "Invalid tr/// range \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1399             }
1400              
1401             # range of multiple-octet code
1402 0 0       0 if (CORE::length($char[$i-1]) == 1) {
    0          
    0          
    0          
1403 0 0       0 if (CORE::length($char[$i+1]) == 1) {
    0          
    0          
    0          
1404 0 0       0 push @range, grep {($char[$i-1] le $_) and ($_ le $char[$i+1])} chars1();
  0         0  
1405             }
1406             elsif (CORE::length($char[$i+1]) == 2) {
1407 0         0 push @range, grep {$char[$i-1] le $_} chars1();
  0         0  
1408 0         0 push @range, grep {$_ le $char[$i+1]} chars2();
  0         0  
1409             }
1410             elsif (CORE::length($char[$i+1]) == 3) {
1411 0         0 push @range, grep {$char[$i-1] le $_} chars1();
  0         0  
1412 0         0 push @range, chars2();
1413 0         0 push @range, grep {$_ le $char[$i+1]} chars3();
  0         0  
1414             }
1415             elsif (CORE::length($char[$i+1]) == 4) {
1416 0         0 push @range, grep {$char[$i-1] le $_} chars1();
  0         0  
1417 0         0 push @range, chars2();
1418 0         0 push @range, chars3();
1419 0         0 push @range, grep {$_ le $char[$i+1]} chars4();
  0         0  
1420             }
1421             else {
1422 0         0 croak "Invalid tr/// range (over 4octets) \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1423             }
1424             }
1425             elsif (CORE::length($char[$i-1]) == 2) {
1426 0 0       0 if (CORE::length($char[$i+1]) == 2) {
    0          
    0          
1427 0 0       0 push @range, grep {($char[$i-1] le $_) and ($_ le $char[$i+1])} chars2();
  0         0  
1428             }
1429             elsif (CORE::length($char[$i+1]) == 3) {
1430 0         0 push @range, grep {$char[$i-1] le $_} chars2();
  0         0  
1431 0         0 push @range, grep {$_ le $char[$i+1]} chars3();
  0         0  
1432             }
1433             elsif (CORE::length($char[$i+1]) == 4) {
1434 0         0 push @range, grep {$char[$i-1] le $_} chars2();
  0         0  
1435 0         0 push @range, chars3();
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]) == 3) {
1443 0 0       0 if (CORE::length($char[$i+1]) == 3) {
    0          
1444 0 0       0 push @range, grep {($char[$i-1] le $_) and ($_ le $char[$i+1])} chars3();
  0         0  
1445             }
1446             elsif (CORE::length($char[$i+1]) == 4) {
1447 0         0 push @range, grep {$char[$i-1] le $_} chars3();
  0         0  
1448 0         0 push @range, grep {$_ le $char[$i+1]} chars4();
  0         0  
1449             }
1450             else {
1451 0         0 croak "Invalid tr/// range (over 4octets) \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1452             }
1453             }
1454             elsif (CORE::length($char[$i-1]) == 4) {
1455 0 0       0 if (CORE::length($char[$i+1]) == 4) {
1456 0 0       0 push @range, grep {($char[$i-1] le $_) and ($_ le $char[$i+1])} chars4();
  0         0  
1457             }
1458             else {
1459 0         0 croak "Invalid tr/// range (over 4octets) \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1460             }
1461             }
1462             else {
1463 0         0 croak "Invalid tr/// range (over 4octets) \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1464             }
1465              
1466 0         0 splice @char, $i-1, 3, @range;
1467             }
1468              
1469 0         0 return @char;
1470             }
1471              
1472             #
1473             # KOI8-U open character class
1474             #
1475             sub _cc {
1476 0 0   0   0 if (scalar(@_) == 0) {
    0          
    0          
1477 0         0 die __FILE__, ": subroutine cc got no parameter.\n";
1478             }
1479             elsif (scalar(@_) == 1) {
1480 0         0 return sprintf('\x%02X',$_[0]);
1481             }
1482             elsif (scalar(@_) == 2) {
1483 0 0       0 if ($_[0] > $_[1]) {
    0          
    0          
1484 0         0 die __FILE__, ": subroutine cc got \$_[0] > \$_[1] parameters).\n";
1485             }
1486             elsif ($_[0] == $_[1]) {
1487 0         0 return sprintf('\x%02X',$_[0]);
1488             }
1489             elsif (($_[0]+1) == $_[1]) {
1490 0         0 return sprintf('[\\x%02X\\x%02X]',$_[0],$_[1]);
1491             }
1492             else {
1493 0         0 return sprintf('[\\x%02X-\\x%02X]',$_[0],$_[1]);
1494             }
1495             }
1496             else {
1497 0         0 die __FILE__, ": subroutine cc got 3 or more parameters (@{[scalar(@_)]} parameters).\n";
  0         0  
1498             }
1499             }
1500              
1501             #
1502             # KOI8-U octet range
1503             #
1504             sub _octets {
1505 0     0   0 my $length = shift @_;
1506              
1507 0 0       0 if ($length == 1) {
1508 0         0 my($a1) = unpack 'C', $_[0];
1509 0         0 my($z1) = unpack 'C', $_[1];
1510              
1511 0 0       0 if ($a1 > $z1) {
1512 0         0 croak 'Invalid [] range in regexp (CORE::ord(A) > CORE::ord(B)) ' . '\x' . unpack('H*',$a1) . '-\x' . unpack('H*',$z1);
1513             }
1514              
1515 0 0       0 if ($a1 == $z1) {
    0          
1516 0         0 return sprintf('\x%02X',$a1);
1517             }
1518             elsif (($a1+1) == $z1) {
1519 0         0 return sprintf('\x%02X\x%02X',$a1,$z1);
1520             }
1521             else {
1522 0         0 return sprintf('\x%02X-\x%02X',$a1,$z1);
1523             }
1524             }
1525             else {
1526 0         0 die __FILE__, ": subroutine _octets got invalid length ($length).\n";
1527             }
1528             }
1529              
1530             #
1531             # KOI8-U range regexp
1532             #
1533             sub _range_regexp {
1534 0     0   0 my($length,$first,$last) = @_;
1535              
1536 0         0 my @range_regexp = ();
1537 0 0       0 if (not exists $range_tr{$length}) {
1538 0         0 return @range_regexp;
1539             }
1540              
1541 0         0 my @ranges = @{ $range_tr{$length} };
  0         0  
1542 0         0 while (my @range = splice(@ranges,0,$length)) {
1543 0         0 my $min = '';
1544 0         0 my $max = '';
1545 0         0 for (my $i=0; $i < $length; $i++) {
1546 0         0 $min .= pack 'C', $range[$i][0];
1547 0         0 $max .= pack 'C', $range[$i][-1];
1548             }
1549              
1550             # min___max
1551             # FIRST_____________LAST
1552             # (nothing)
1553              
1554 0 0 0     0 if ($max lt $first) {
    0 0        
    0 0        
    0 0        
    0 0        
    0 0        
    0 0        
1555             }
1556              
1557             # **********
1558             # min_________max
1559             # FIRST_____________LAST
1560             # **********
1561              
1562             elsif (($min le $first) and ($first le $max) and ($max le $last)) {
1563 0         0 push @range_regexp, _octets($length,$first,$max,$min,$max);
1564             }
1565              
1566             # **********************
1567             # min________________max
1568             # FIRST_____________LAST
1569             # **********************
1570              
1571             elsif (($min eq $first) and ($max eq $last)) {
1572 0         0 push @range_regexp, _octets($length,$first,$last,$min,$max);
1573             }
1574              
1575             # *********
1576             # min___max
1577             # FIRST_____________LAST
1578             # *********
1579              
1580             elsif (($first le $min) and ($max le $last)) {
1581 0         0 push @range_regexp, _octets($length,$min,$max,$min,$max);
1582             }
1583              
1584             # **********************
1585             # min__________________________max
1586             # FIRST_____________LAST
1587             # **********************
1588              
1589             elsif (($min le $first) and ($last le $max)) {
1590 0         0 push @range_regexp, _octets($length,$first,$last,$min,$max);
1591             }
1592              
1593             # *********
1594             # min________max
1595             # FIRST_____________LAST
1596             # *********
1597              
1598             elsif (($first le $min) and ($min le $last) and ($last le $max)) {
1599 0         0 push @range_regexp, _octets($length,$min,$last,$min,$max);
1600             }
1601              
1602             # min___max
1603             # FIRST_____________LAST
1604             # (nothing)
1605              
1606             elsif ($last lt $min) {
1607             }
1608              
1609             else {
1610 0         0 die __FILE__, ": subroutine _range_regexp panic.\n";
1611             }
1612             }
1613              
1614 0         0 return @range_regexp;
1615             }
1616              
1617             #
1618             # KOI8-U open character list for qr and not qr
1619             #
1620             sub _charlist {
1621              
1622 0     0   0 my $modifier = pop @_;
1623 0         0 my @char = @_;
1624              
1625 0 0       0 my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
1626              
1627             # unescape character
1628 0         0 for (my $i=0; $i <= $#char; $i++) {
1629              
1630             # escape - to ...
1631 0 0 0     0 if ($char[$i] eq '-') {
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
1632 0 0 0     0 if ((0 < $i) and ($i < $#char)) {
1633 0         0 $char[$i] = '...';
1634             }
1635             }
1636              
1637             # octal escape sequence
1638             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
1639 0         0 $char[$i] = octchr($1);
1640             }
1641              
1642             # hexadecimal escape sequence
1643             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
1644 0         0 $char[$i] = hexchr($1);
1645             }
1646              
1647             # \b{...} --> b\{...}
1648             # \B{...} --> B\{...}
1649             # \N{CHARNAME} --> N\{CHARNAME}
1650             # \p{PROPERTY} --> p\{PROPERTY}
1651             # \P{PROPERTY} --> P\{PROPERTY}
1652             elsif ($char[$i] =~ /\A \\ ([bBNpP]) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
1653 0         0 $char[$i] = $1 . '\\' . $2;
1654             }
1655              
1656             # \p, \P, \X --> p, P, X
1657             elsif ($char[$i] =~ /\A \\ ( [pPX] ) \z/oxms) {
1658 0         0 $char[$i] = $1;
1659             }
1660              
1661             elsif ($char[$i] =~ /\A \\ ([0-7]{2,3}) \z/oxms) {
1662 0         0 $char[$i] = CORE::chr oct $1;
1663             }
1664             elsif ($char[$i] =~ /\A \\x ([0-9A-Fa-f]{1,2}) \z/oxms) {
1665 0         0 $char[$i] = CORE::chr hex $1;
1666             }
1667             elsif ($char[$i] =~ /\A \\c ([\x40-\x5F]) \z/oxms) {
1668 0         0 $char[$i] = CORE::chr(CORE::ord($1) & 0x1F);
1669             }
1670             elsif ($char[$i] =~ /\A (\\ [0nrtfbaedswDSWHVhvR]) \z/oxms) {
1671 0         0 $char[$i] = {
1672             '\0' => "\0",
1673             '\n' => "\n",
1674             '\r' => "\r",
1675             '\t' => "\t",
1676             '\f' => "\f",
1677             '\b' => "\x08", # \b means backspace in character class
1678             '\a' => "\a",
1679             '\e' => "\e",
1680             '\d' => '[0-9]',
1681              
1682             # Vertical tabs are now whitespace
1683             # \s in a regex now matches a vertical tab in all circumstances.
1684             # http://search.cpan.org/dist/perl-5.18.0/pod/perldelta.pod#Vertical_tabs_are_now_whitespace
1685             # \t \n \v \f \r space
1686             # '\s' => '[\x09\x0A \x0C\x0D\x20]',
1687             # '\s' => '[\x09\x0A\x0B\x0C\x0D\x20]',
1688             '\s' => '\s',
1689              
1690             '\w' => '[0-9A-Z_a-z]',
1691             '\D' => '${Ekoi8u::eD}',
1692             '\S' => '${Ekoi8u::eS}',
1693             '\W' => '${Ekoi8u::eW}',
1694              
1695             '\H' => '${Ekoi8u::eH}',
1696             '\V' => '${Ekoi8u::eV}',
1697             '\h' => '[\x09\x20]',
1698             '\v' => '[\x0A\x0B\x0C\x0D]',
1699             '\R' => '${Ekoi8u::eR}',
1700              
1701             }->{$1};
1702             }
1703              
1704             # POSIX-style character classes
1705             elsif ($ignorecase and ($char[$i] =~ /\A ( \[\: \^? (?:lower|upper) :\] ) \z/oxms)) {
1706 0         0 $char[$i] = {
1707              
1708             '[:lower:]' => '[\x41-\x5A\x61-\x7A]',
1709             '[:upper:]' => '[\x41-\x5A\x61-\x7A]',
1710             '[:^lower:]' => '${Ekoi8u::not_lower_i}',
1711             '[:^upper:]' => '${Ekoi8u::not_upper_i}',
1712              
1713             }->{$1};
1714             }
1715             elsif ($char[$i] =~ /\A ( \[\: \^? (?:alnum|alpha|ascii|blank|cntrl|digit|graph|lower|print|punct|space|upper|word|xdigit) :\] ) \z/oxms) {
1716 0         0 $char[$i] = {
1717              
1718             '[:alnum:]' => '[\x30-\x39\x41-\x5A\x61-\x7A]',
1719             '[:alpha:]' => '[\x41-\x5A\x61-\x7A]',
1720             '[:ascii:]' => '[\x00-\x7F]',
1721             '[:blank:]' => '[\x09\x20]',
1722             '[:cntrl:]' => '[\x00-\x1F\x7F]',
1723             '[:digit:]' => '[\x30-\x39]',
1724             '[:graph:]' => '[\x21-\x7F]',
1725             '[:lower:]' => '[\x61-\x7A]',
1726             '[:print:]' => '[\x20-\x7F]',
1727             '[:punct:]' => '[\x21-\x2F\x3A-\x3F\x40\x5B-\x5F\x60\x7B-\x7E]',
1728              
1729             # P.174 POSIX-Style Character Classes
1730             # in Chapter 5: Pattern Matching
1731             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
1732              
1733             # P.311 11.2.4 Character Classes and other Special Escapes
1734             # in Chapter 11: perlre: Perl regular expressions
1735             # of ISBN-13: 978-1-906966-02-7 The Perl Language Reference Manual (for Perl version 5.12.1)
1736              
1737             # P.210 POSIX-Style Character Classes
1738             # in Chapter 5: Pattern Matching
1739             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
1740              
1741             '[:space:]' => '[\s\x0B]', # "\s" plus vertical tab ("\cK")
1742              
1743             '[:upper:]' => '[\x41-\x5A]',
1744             '[:word:]' => '[\x30-\x39\x41-\x5A\x5F\x61-\x7A]',
1745             '[:xdigit:]' => '[\x30-\x39\x41-\x46\x61-\x66]',
1746             '[:^alnum:]' => '${Ekoi8u::not_alnum}',
1747             '[:^alpha:]' => '${Ekoi8u::not_alpha}',
1748             '[:^ascii:]' => '${Ekoi8u::not_ascii}',
1749             '[:^blank:]' => '${Ekoi8u::not_blank}',
1750             '[:^cntrl:]' => '${Ekoi8u::not_cntrl}',
1751             '[:^digit:]' => '${Ekoi8u::not_digit}',
1752             '[:^graph:]' => '${Ekoi8u::not_graph}',
1753             '[:^lower:]' => '${Ekoi8u::not_lower}',
1754             '[:^print:]' => '${Ekoi8u::not_print}',
1755             '[:^punct:]' => '${Ekoi8u::not_punct}',
1756             '[:^space:]' => '${Ekoi8u::not_space}',
1757             '[:^upper:]' => '${Ekoi8u::not_upper}',
1758             '[:^word:]' => '${Ekoi8u::not_word}',
1759             '[:^xdigit:]' => '${Ekoi8u::not_xdigit}',
1760              
1761             }->{$1};
1762             }
1763             elsif ($char[$i] =~ /\A \\ ($q_char) \z/oxms) {
1764 0         0 $char[$i] = $1;
1765             }
1766             }
1767              
1768             # open character list
1769 0         0 my @singleoctet = ();
1770 0         0 my @multipleoctet = ();
1771 0         0 for (my $i=0; $i <= $#char; ) {
1772              
1773             # escaped -
1774 0 0 0     0 if (defined($char[$i+1]) and ($char[$i+1] eq '...')) {
    0          
    0          
    0          
    0          
    0          
1775 0         0 $i += 1;
1776 0         0 next;
1777             }
1778              
1779             # make range regexp
1780             elsif ($char[$i] eq '...') {
1781              
1782             # range error
1783 0 0       0 if (CORE::length($char[$i-1]) > CORE::length($char[$i+1])) {
    0          
1784 0         0 croak 'Invalid [] range in regexp (length(A) > length(B)) ' . '\x' . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]);
1785             }
1786             elsif (CORE::length($char[$i-1]) == CORE::length($char[$i+1])) {
1787 0 0       0 if ($char[$i-1] gt $char[$i+1]) {
1788 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]);
1789             }
1790             }
1791              
1792             # make range regexp per length
1793 0         0 for my $length (CORE::length($char[$i-1]) .. CORE::length($char[$i+1])) {
1794 0         0 my @regexp = ();
1795              
1796             # is first and last
1797 0 0 0     0 if (($length == CORE::length($char[$i-1])) and ($length == CORE::length($char[$i+1]))) {
    0 0        
    0          
    0          
1798 0         0 push @regexp, _range_regexp($length, $char[$i-1], $char[$i+1]);
1799             }
1800              
1801             # is first
1802             elsif ($length == CORE::length($char[$i-1])) {
1803 0         0 push @regexp, _range_regexp($length, $char[$i-1], "\xFF" x $length);
1804             }
1805              
1806             # is inside in first and last
1807             elsif ((CORE::length($char[$i-1]) < $length) and ($length < CORE::length($char[$i+1]))) {
1808 0         0 push @regexp, _range_regexp($length, "\x00" x $length, "\xFF" x $length);
1809             }
1810              
1811             # is last
1812             elsif ($length == CORE::length($char[$i+1])) {
1813 0         0 push @regexp, _range_regexp($length, "\x00" x $length, $char[$i+1]);
1814             }
1815              
1816             else {
1817 0         0 die __FILE__, ": subroutine make_regexp panic.\n";
1818             }
1819              
1820 0 0       0 if ($length == 1) {
1821 0         0 push @singleoctet, @regexp;
1822             }
1823             else {
1824 0         0 push @multipleoctet, @regexp;
1825             }
1826             }
1827              
1828 0         0 $i += 2;
1829             }
1830              
1831             # with /i modifier
1832             elsif ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) {
1833 0 0       0 if ($modifier =~ /i/oxms) {
1834 0         0 my $uc = Ekoi8u::uc($char[$i]);
1835 0         0 my $fc = Ekoi8u::fc($char[$i]);
1836 0 0       0 if ($uc ne $fc) {
1837 0 0       0 if (CORE::length($fc) == 1) {
1838 0         0 push @singleoctet, $uc, $fc;
1839             }
1840             else {
1841 0         0 push @singleoctet, $uc;
1842 0         0 push @multipleoctet, $fc;
1843             }
1844             }
1845             else {
1846 0         0 push @singleoctet, $char[$i];
1847             }
1848             }
1849             else {
1850 0         0 push @singleoctet, $char[$i];
1851             }
1852 0         0 $i += 1;
1853             }
1854              
1855             # single character of single octet code
1856             elsif ($char[$i] =~ /\A (?: \\h ) \z/oxms) {
1857 0         0 push @singleoctet, "\t", "\x20";
1858 0         0 $i += 1;
1859             }
1860             elsif ($char[$i] =~ /\A (?: \\v ) \z/oxms) {
1861 0         0 push @singleoctet, "\x0A", "\x0B", "\x0C", "\x0D";
1862 0         0 $i += 1;
1863             }
1864             elsif ($char[$i] =~ /\A (?: \\d | \\s | \\w ) \z/oxms) {
1865 0         0 push @singleoctet, $char[$i];
1866 0         0 $i += 1;
1867             }
1868              
1869             # single character of multiple-octet code
1870             else {
1871 0         0 push @multipleoctet, $char[$i];
1872 0         0 $i += 1;
1873             }
1874             }
1875              
1876             # quote metachar
1877 0         0 for (@singleoctet) {
1878 0 0       0 if ($_ eq '...') {
    0          
    0          
    0          
    0          
1879 0         0 $_ = '-';
1880             }
1881             elsif (/\A \n \z/oxms) {
1882 0         0 $_ = '\n';
1883             }
1884             elsif (/\A \r \z/oxms) {
1885 0         0 $_ = '\r';
1886             }
1887             elsif (/\A ([\x00-\x20\x7F-\xFF]) \z/oxms) {
1888 0         0 $_ = sprintf('\x%02X', CORE::ord $1);
1889             }
1890             elsif (/\A [\x00-\xFF] \z/oxms) {
1891 0         0 $_ = quotemeta $_;
1892             }
1893             }
1894              
1895             # return character list
1896 0         0 return \@singleoctet, \@multipleoctet;
1897             }
1898              
1899             #
1900             # KOI8-U octal escape sequence
1901             #
1902             sub octchr {
1903 0     0 0 0 my($octdigit) = @_;
1904              
1905 0         0 my @binary = ();
1906 0         0 for my $octal (split(//,$octdigit)) {
1907 0         0 push @binary, {
1908             '0' => '000',
1909             '1' => '001',
1910             '2' => '010',
1911             '3' => '011',
1912             '4' => '100',
1913             '5' => '101',
1914             '6' => '110',
1915             '7' => '111',
1916             }->{$octal};
1917             }
1918 0         0 my $binary = join '', @binary;
1919              
1920 0         0 my $octchr = {
1921             # 1234567
1922             1 => pack('B*', "0000000$binary"),
1923             2 => pack('B*', "000000$binary"),
1924             3 => pack('B*', "00000$binary"),
1925             4 => pack('B*', "0000$binary"),
1926             5 => pack('B*', "000$binary"),
1927             6 => pack('B*', "00$binary"),
1928             7 => pack('B*', "0$binary"),
1929             0 => pack('B*', "$binary"),
1930              
1931             }->{CORE::length($binary) % 8};
1932              
1933 0         0 return $octchr;
1934             }
1935              
1936             #
1937             # KOI8-U hexadecimal escape sequence
1938             #
1939             sub hexchr {
1940 0     0 0 0 my($hexdigit) = @_;
1941              
1942 0         0 my $hexchr = {
1943             1 => pack('H*', "0$hexdigit"),
1944             0 => pack('H*', "$hexdigit"),
1945              
1946             }->{CORE::length($_[0]) % 2};
1947              
1948 0         0 return $hexchr;
1949             }
1950              
1951             #
1952             # KOI8-U open character list for qr
1953             #
1954             sub charlist_qr {
1955              
1956 0     0 0 0 my $modifier = pop @_;
1957 0         0 my @char = @_;
1958              
1959 0         0 my($singleoctet, $multipleoctet) = _charlist(@char, $modifier);
1960 0         0 my @singleoctet = @$singleoctet;
1961 0         0 my @multipleoctet = @$multipleoctet;
1962              
1963             # return character list
1964 0 0       0 if (scalar(@singleoctet) >= 1) {
1965              
1966             # with /i modifier
1967 0 0       0 if ($modifier =~ m/i/oxms) {
1968 0         0 my %singleoctet_ignorecase = ();
1969 0         0 for (@singleoctet) {
1970 0   0     0 while (s/ \A \\x(..) - \\x(..) //oxms or s/ \A \\x((..)) //oxms) {
1971 0         0 for my $ord (hex($1) .. hex($2)) {
1972 0         0 my $char = CORE::chr($ord);
1973 0         0 my $uc = Ekoi8u::uc($char);
1974 0         0 my $fc = Ekoi8u::fc($char);
1975 0 0       0 if ($uc eq $fc) {
1976 0         0 $singleoctet_ignorecase{unpack 'C*', $char} = 1;
1977             }
1978             else {
1979 0 0       0 if (CORE::length($fc) == 1) {
1980 0         0 $singleoctet_ignorecase{unpack 'C*', $uc} = 1;
1981 0         0 $singleoctet_ignorecase{unpack 'C*', $fc} = 1;
1982             }
1983             else {
1984 0         0 $singleoctet_ignorecase{unpack 'C*', $uc} = 1;
1985 0         0 push @multipleoctet, join '', map {sprintf('\x%02X',$_)} unpack 'C*', $fc;
  0         0  
1986             }
1987             }
1988             }
1989             }
1990 0 0       0 if ($_ ne '') {
1991 0         0 $singleoctet_ignorecase{unpack 'C*', $_} = 1;
1992             }
1993             }
1994 0         0 my $i = 0;
1995 0         0 my @singleoctet_ignorecase = ();
1996 0         0 for my $ord (0 .. 255) {
1997 0 0       0 if (exists $singleoctet_ignorecase{$ord}) {
1998 0         0 push @{$singleoctet_ignorecase[$i]}, $ord;
  0         0  
1999             }
2000             else {
2001 0         0 $i++;
2002             }
2003             }
2004 0         0 @singleoctet = ();
2005 0         0 for my $range (@singleoctet_ignorecase) {
2006 0 0       0 if (ref $range) {
2007 0 0       0 if (scalar(@{$range}) == 1) {
  0 0       0  
  0         0  
2008 0         0 push @singleoctet, sprintf('\x%02X', @{$range}[0]);
  0         0  
2009             }
2010             elsif (scalar(@{$range}) == 2) {
2011 0         0 push @singleoctet, sprintf('\x%02X\x%02X', @{$range}[0], @{$range}[-1]);
  0         0  
  0         0  
2012             }
2013             else {
2014 0         0 push @singleoctet, sprintf('\x%02X-\x%02X', @{$range}[0], @{$range}[-1]);
  0         0  
  0         0  
2015             }
2016             }
2017             }
2018             }
2019              
2020 0         0 my $not_anchor = '';
2021              
2022 0         0 push @multipleoctet, join('', $not_anchor, '[', @singleoctet, ']' );
2023             }
2024 0 0       0 if (scalar(@multipleoctet) >= 2) {
2025 0         0 return '(?:' . join('|', @multipleoctet) . ')';
2026             }
2027             else {
2028 0         0 return $multipleoctet[0];
2029             }
2030             }
2031              
2032             #
2033             # KOI8-U open character list for not qr
2034             #
2035             sub charlist_not_qr {
2036              
2037 0     0 0 0 my $modifier = pop @_;
2038 0         0 my @char = @_;
2039              
2040 0         0 my($singleoctet, $multipleoctet) = _charlist(@char, $modifier);
2041 0         0 my @singleoctet = @$singleoctet;
2042 0         0 my @multipleoctet = @$multipleoctet;
2043              
2044             # with /i modifier
2045 0 0       0 if ($modifier =~ m/i/oxms) {
2046 0         0 my %singleoctet_ignorecase = ();
2047 0         0 for (@singleoctet) {
2048 0   0     0 while (s/ \A \\x(..) - \\x(..) //oxms or s/ \A \\x((..)) //oxms) {
2049 0         0 for my $ord (hex($1) .. hex($2)) {
2050 0         0 my $char = CORE::chr($ord);
2051 0         0 my $uc = Ekoi8u::uc($char);
2052 0         0 my $fc = Ekoi8u::fc($char);
2053 0 0       0 if ($uc eq $fc) {
2054 0         0 $singleoctet_ignorecase{unpack 'C*', $char} = 1;
2055             }
2056             else {
2057 0 0       0 if (CORE::length($fc) == 1) {
2058 0         0 $singleoctet_ignorecase{unpack 'C*', $uc} = 1;
2059 0         0 $singleoctet_ignorecase{unpack 'C*', $fc} = 1;
2060             }
2061             else {
2062 0         0 $singleoctet_ignorecase{unpack 'C*', $uc} = 1;
2063 0         0 push @multipleoctet, join '', map {sprintf('\x%02X',$_)} unpack 'C*', $fc;
  0         0  
2064             }
2065             }
2066             }
2067             }
2068 0 0       0 if ($_ ne '') {
2069 0         0 $singleoctet_ignorecase{unpack 'C*', $_} = 1;
2070             }
2071             }
2072 0         0 my $i = 0;
2073 0         0 my @singleoctet_ignorecase = ();
2074 0         0 for my $ord (0 .. 255) {
2075 0 0       0 if (exists $singleoctet_ignorecase{$ord}) {
2076 0         0 push @{$singleoctet_ignorecase[$i]}, $ord;
  0         0  
2077             }
2078             else {
2079 0         0 $i++;
2080             }
2081             }
2082 0         0 @singleoctet = ();
2083 0         0 for my $range (@singleoctet_ignorecase) {
2084 0 0       0 if (ref $range) {
2085 0 0       0 if (scalar(@{$range}) == 1) {
  0 0       0  
  0         0  
2086 0         0 push @singleoctet, sprintf('\x%02X', @{$range}[0]);
  0         0  
2087             }
2088             elsif (scalar(@{$range}) == 2) {
2089 0         0 push @singleoctet, sprintf('\x%02X\x%02X', @{$range}[0], @{$range}[-1]);
  0         0  
  0         0  
2090             }
2091             else {
2092 0         0 push @singleoctet, sprintf('\x%02X-\x%02X', @{$range}[0], @{$range}[-1]);
  0         0  
  0         0  
2093             }
2094             }
2095             }
2096             }
2097              
2098             # return character list
2099 0 0       0 if (scalar(@multipleoctet) >= 1) {
2100 0 0       0 if (scalar(@singleoctet) >= 1) {
2101              
2102             # any character other than multiple-octet and single octet character class
2103 0         0 return '(?!' . join('|', @multipleoctet) . ')(?:[^' . join('', @singleoctet) . '])';
2104             }
2105             else {
2106              
2107             # any character other than multiple-octet character class
2108 0         0 return '(?!' . join('|', @multipleoctet) . ")(?:$your_char)";
2109             }
2110             }
2111             else {
2112 0 0       0 if (scalar(@singleoctet) >= 1) {
2113              
2114             # any character other than single octet character class
2115 0         0 return '(?:[^' . join('', @singleoctet) . '])';
2116             }
2117             else {
2118              
2119             # any character
2120 0         0 return "(?:$your_char)";
2121             }
2122             }
2123             }
2124              
2125             #
2126             # open file in read mode
2127             #
2128             sub _open_r {
2129 200     200   685 my(undef,$file) = @_;
2130 200         848 $file =~ s#\A (\s) #./$1#oxms;
2131 200   33     18207 return CORE::eval(q{open($_[0],'<',$_[1])}) ||
2132             open($_[0],"< $file\0");
2133             }
2134              
2135             #
2136             # open file in write mode
2137             #
2138             sub _open_w {
2139 0     0   0 my(undef,$file) = @_;
2140 0         0 $file =~ s#\A (\s) #./$1#oxms;
2141 0   0     0 return CORE::eval(q{open($_[0],'>',$_[1])}) ||
2142             open($_[0],"> $file\0");
2143             }
2144              
2145             #
2146             # open file in append mode
2147             #
2148             sub _open_a {
2149 0     0   0 my(undef,$file) = @_;
2150 0         0 $file =~ s#\A (\s) #./$1#oxms;
2151 0   0     0 return CORE::eval(q{open($_[0],'>>',$_[1])}) ||
2152             open($_[0],">> $file\0");
2153             }
2154              
2155             #
2156             # safe system
2157             #
2158             sub _systemx {
2159              
2160             # P.707 29.2.33. exec
2161             # in Chapter 29: Functions
2162             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
2163             #
2164             # Be aware that in older releases of Perl, exec (and system) did not flush
2165             # your output buffer, so you needed to enable command buffering by setting $|
2166             # on one or more filehandles to avoid lost output in the case of exec, or
2167             # misordererd output in the case of system. This situation was largely remedied
2168             # in the 5.6 release of Perl. (So, 5.005 release not yet.)
2169              
2170             # P.855 exec
2171             # in Chapter 27: Functions
2172             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
2173             #
2174             # In very old release of Perl (before v5.6), exec (and system) did not flush
2175             # your output buffer, so you needed to enable command buffering by setting $|
2176             # on one or more filehandles to avoid lost output with exec or misordered
2177             # output with system.
2178              
2179 200     200   796 $| = 1;
2180              
2181             # P.565 23.1.2. Cleaning Up Your Environment
2182             # in Chapter 23: Security
2183             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
2184              
2185             # P.656 Cleaning Up Your Environment
2186             # in Chapter 20: Security
2187             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
2188              
2189             # local $ENV{'PATH'} = '.';
2190 200         2332 local @ENV{qw(IFS CDPATH ENV BASH_ENV)}; # Make %ENV safer
2191              
2192             # P.707 29.2.33. exec
2193             # in Chapter 29: Functions
2194             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
2195             #
2196             # As we mentioned earlier, exec treats a discrete list of arguments as an
2197             # indication that it should bypass shell processing. However, there is one
2198             # place where you might still get tripped up. The exec call (and system, too)
2199             # will not distinguish between a single scalar argument and an array containing
2200             # only one element.
2201             #
2202             # @args = ("echo surprise"); # just one element in list
2203             # exec @args # still subject to shell escapes
2204             # or die "exec: $!"; # because @args == 1
2205             #
2206             # To avoid this, you can use the PATHNAME syntax, explicitly duplicating the
2207             # first argument as the pathname, which forces the rest of the arguments to be
2208             # interpreted as a list, even if there is only one of them:
2209             #
2210             # exec { $args[0] } @args # safe even with one-argument list
2211             # or die "can't exec @args: $!";
2212              
2213             # P.855 exec
2214             # in Chapter 27: Functions
2215             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
2216             #
2217             # As we mentioned earlier, exec treats a discrete list of arguments as a
2218             # directive to bypass shell processing. However, there is one place where
2219             # you might still get tripped up. The exec call (and system, too) cannot
2220             # distinguish between a single scalar argument and an array containing
2221             # only one element.
2222             #
2223             # @args = ("echo surprise"); # just one element in list
2224             # exec @args # still subject to shell escapes
2225             # || die "exec: $!"; # because @args == 1
2226             #
2227             # To avoid this, use the PATHNAME syntax, explicitly duplicating the first
2228             # argument as the pathname, which forces the rest of the arguments to be
2229             # interpreted as a list, even if there is only one of them:
2230             #
2231             # exec { $args[0] } @args # safe even with one-argument list
2232             # || die "can't exec @args: $!";
2233              
2234 200         442 return CORE::system { $_[0] } @_; # safe even with one-argument list
  200         25593970  
2235             }
2236              
2237             #
2238             # KOI8-U order to character (with parameter)
2239             #
2240             sub Ekoi8u::chr(;$) {
2241              
2242 0 0   0 0   my $c = @_ ? $_[0] : $_;
2243              
2244 0 0         if ($c == 0x00) {
2245 0           return "\x00";
2246             }
2247             else {
2248 0           my @chr = ();
2249 0           while ($c > 0) {
2250 0           unshift @chr, ($c % 0x100);
2251 0           $c = int($c / 0x100);
2252             }
2253 0           return pack 'C*', @chr;
2254             }
2255             }
2256              
2257             #
2258             # KOI8-U order to character (without parameter)
2259             #
2260             sub Ekoi8u::chr_() {
2261              
2262 0     0 0   my $c = $_;
2263              
2264 0 0         if ($c == 0x00) {
2265 0           return "\x00";
2266             }
2267             else {
2268 0           my @chr = ();
2269 0           while ($c > 0) {
2270 0           unshift @chr, ($c % 0x100);
2271 0           $c = int($c / 0x100);
2272             }
2273 0           return pack 'C*', @chr;
2274             }
2275             }
2276              
2277             #
2278             # KOI8-U path globbing (with parameter)
2279             #
2280             sub Ekoi8u::glob($) {
2281              
2282 0 0   0 0   if (wantarray) {
2283 0           my @glob = _DOS_like_glob(@_);
2284 0           for my $glob (@glob) {
2285 0           $glob =~ s{ \A (?:\./)+ }{}oxms;
2286             }
2287 0           return @glob;
2288             }
2289             else {
2290 0           my $glob = _DOS_like_glob(@_);
2291 0           $glob =~ s{ \A (?:\./)+ }{}oxms;
2292 0           return $glob;
2293             }
2294             }
2295              
2296             #
2297             # KOI8-U path globbing (without parameter)
2298             #
2299             sub Ekoi8u::glob_() {
2300              
2301 0 0   0 0   if (wantarray) {
2302 0           my @glob = _DOS_like_glob();
2303 0           for my $glob (@glob) {
2304 0           $glob =~ s{ \A (?:\./)+ }{}oxms;
2305             }
2306 0           return @glob;
2307             }
2308             else {
2309 0           my $glob = _DOS_like_glob();
2310 0           $glob =~ s{ \A (?:\./)+ }{}oxms;
2311 0           return $glob;
2312             }
2313             }
2314              
2315             #
2316             # KOI8-U path globbing via File::DosGlob 1.10
2317             #
2318             # Often I confuse "_dosglob" and "_doglob".
2319             # So, I renamed "_dosglob" to "_DOS_like_glob".
2320             #
2321             my %iter;
2322             my %entries;
2323             sub _DOS_like_glob {
2324              
2325             # context (keyed by second cxix argument provided by core)
2326 0     0     my($expr,$cxix) = @_;
2327              
2328             # glob without args defaults to $_
2329 0 0         $expr = $_ if not defined $expr;
2330              
2331             # represents the current user's home directory
2332             #
2333             # 7.3. Expanding Tildes in Filenames
2334             # in Chapter 7. File Access
2335             # of ISBN 0-596-00313-7 Perl Cookbook, 2nd Edition.
2336             #
2337             # and File::HomeDir, File::HomeDir::Windows module
2338              
2339             # DOS-like system
2340 0 0         if ($^O =~ /\A (?: MSWin32 | NetWare | symbian | dos ) \z/oxms) {
2341 0           $expr =~ s{ \A ~ (?= [^/\\] ) }
2342 0           { my_home_MSWin32() }oxmse;
2343             }
2344              
2345             # UNIX-like system
2346             else {
2347 0           $expr =~ s{ \A ~ ( (?:[^/])* ) }
2348 0 0 0       { $1 ? (CORE::eval(q{(getpwnam($1))[7]})||my_home()) : my_home() }oxmse;
2349             }
2350              
2351             # assume global context if not provided one
2352 0 0         $cxix = '_G_' if not defined $cxix;
2353 0 0         $iter{$cxix} = 0 if not exists $iter{$cxix};
2354              
2355             # if we're just beginning, do it all first
2356 0 0         if ($iter{$cxix} == 0) {
2357 0           $entries{$cxix} = [ _do_glob(1, _parse_line($expr)) ];
2358             }
2359              
2360             # chuck it all out, quick or slow
2361 0 0         if (wantarray) {
2362 0           delete $iter{$cxix};
2363 0           return @{delete $entries{$cxix}};
  0            
2364             }
2365             else {
2366 0 0         if ($iter{$cxix} = scalar @{$entries{$cxix}}) {
  0            
2367 0           return shift @{$entries{$cxix}};
  0            
2368             }
2369             else {
2370             # return undef for EOL
2371 0           delete $iter{$cxix};
2372 0           delete $entries{$cxix};
2373 0           return undef;
2374             }
2375             }
2376             }
2377              
2378             #
2379             # KOI8-U path globbing subroutine
2380             #
2381             sub _do_glob {
2382              
2383 0     0     my($cond,@expr) = @_;
2384 0           my @glob = ();
2385 0           my $fix_drive_relative_paths = 0;
2386              
2387             OUTER:
2388 0           for my $expr (@expr) {
2389 0 0         next OUTER if not defined $expr;
2390 0 0         next OUTER if $expr eq '';
2391              
2392 0           my @matched = ();
2393 0           my @globdir = ();
2394 0           my $head = '.';
2395 0           my $pathsep = '/';
2396 0           my $tail;
2397              
2398             # if argument is within quotes strip em and do no globbing
2399 0 0         if ($expr =~ /\A " ((?:$q_char)*?) " \z/oxms) {
2400 0           $expr = $1;
2401 0 0         if ($cond eq 'd') {
2402 0 0         if (-d $expr) {
2403 0           push @glob, $expr;
2404             }
2405             }
2406             else {
2407 0 0         if (-e $expr) {
2408 0           push @glob, $expr;
2409             }
2410             }
2411 0           next OUTER;
2412             }
2413              
2414             # wildcards with a drive prefix such as h:*.pm must be changed
2415             # to h:./*.pm to expand correctly
2416 0 0         if ($^O =~ /\A (?: MSWin32 | NetWare | symbian | dos ) \z/oxms) {
2417 0 0         if ($expr =~ s# \A ((?:[A-Za-z]:)?) ([^/\\]) #$1./$2#oxms) {
2418 0           $fix_drive_relative_paths = 1;
2419             }
2420             }
2421              
2422 0 0         if (($head, $tail) = _parse_path($expr,$pathsep)) {
2423 0 0         if ($tail eq '') {
2424 0           push @glob, $expr;
2425 0           next OUTER;
2426             }
2427 0 0         if ($head =~ / \A (?:$q_char)*? [*?] /oxms) {
2428 0 0         if (@globdir = _do_glob('d', $head)) {
2429 0           push @glob, _do_glob($cond, map {"$_$pathsep$tail"} @globdir);
  0            
2430 0           next OUTER;
2431             }
2432             }
2433 0 0 0       if ($head eq '' or $head =~ /\A [A-Za-z]: \z/oxms) {
2434 0           $head .= $pathsep;
2435             }
2436 0           $expr = $tail;
2437             }
2438              
2439             # If file component has no wildcards, we can avoid opendir
2440 0 0         if ($expr !~ / \A (?:$q_char)*? [*?] /oxms) {
2441 0 0         if ($head eq '.') {
2442 0           $head = '';
2443             }
2444 0 0 0       if ($head ne '' and ($head =~ / \G ($q_char) /oxmsg)[-1] ne $pathsep) {
2445 0           $head .= $pathsep;
2446             }
2447 0           $head .= $expr;
2448 0 0         if ($cond eq 'd') {
2449 0 0         if (-d $head) {
2450 0           push @glob, $head;
2451             }
2452             }
2453             else {
2454 0 0         if (-e $head) {
2455 0           push @glob, $head;
2456             }
2457             }
2458 0           next OUTER;
2459             }
2460 0 0         opendir(*DIR, $head) or next OUTER;
2461 0           my @leaf = readdir DIR;
2462 0           closedir DIR;
2463              
2464 0 0         if ($head eq '.') {
2465 0           $head = '';
2466             }
2467 0 0 0       if ($head ne '' and ($head =~ / \G ($q_char) /oxmsg)[-1] ne $pathsep) {
2468 0           $head .= $pathsep;
2469             }
2470              
2471 0           my $pattern = '';
2472 0           while ($expr =~ / \G ($q_char) /oxgc) {
2473 0           my $char = $1;
2474              
2475             # 6.9. Matching Shell Globs as Regular Expressions
2476             # in Chapter 6. Pattern Matching
2477             # of ISBN 0-596-00313-7 Perl Cookbook, 2nd Edition.
2478             # (and so on)
2479              
2480 0 0         if ($char eq '*') {
    0          
    0          
2481 0           $pattern .= "(?:$your_char)*",
2482             }
2483             elsif ($char eq '?') {
2484 0           $pattern .= "(?:$your_char)?", # DOS style
2485             # $pattern .= "(?:$your_char)", # UNIX style
2486             }
2487             elsif ((my $fc = Ekoi8u::fc($char)) ne $char) {
2488 0           $pattern .= $fc;
2489             }
2490             else {
2491 0           $pattern .= quotemeta $char;
2492             }
2493             }
2494 0     0     my $matchsub = sub { Ekoi8u::fc($_[0]) =~ /\A $pattern \z/xms };
  0            
2495              
2496             # if ($@) {
2497             # print STDERR "$0: $@\n";
2498             # next OUTER;
2499             # }
2500              
2501             INNER:
2502 0           for my $leaf (@leaf) {
2503 0 0 0       if ($leaf eq '.' or $leaf eq '..') {
2504 0           next INNER;
2505             }
2506 0 0 0       if ($cond eq 'd' and not -d "$head$leaf") {
2507 0           next INNER;
2508             }
2509              
2510 0 0         if (&$matchsub($leaf)) {
2511 0           push @matched, "$head$leaf";
2512 0           next INNER;
2513             }
2514              
2515             # [DOS compatibility special case]
2516             # Failed, add a trailing dot and try again, but only...
2517              
2518 0 0 0       if (Ekoi8u::index($leaf,'.') == -1 and # if name does not have a dot in it *and*
      0        
2519             CORE::length($leaf) <= 8 and # name is shorter than or equal to 8 chars *and*
2520             Ekoi8u::index($pattern,'\\.') != -1 # pattern has a dot.
2521             ) {
2522 0 0         if (&$matchsub("$leaf.")) {
2523 0           push @matched, "$head$leaf";
2524 0           next INNER;
2525             }
2526             }
2527             }
2528 0 0         if (@matched) {
2529 0           push @glob, @matched;
2530             }
2531             }
2532 0 0         if ($fix_drive_relative_paths) {
2533 0           for my $glob (@glob) {
2534 0           $glob =~ s# \A ([A-Za-z]:) \./ #$1#oxms;
2535             }
2536             }
2537 0           return @glob;
2538             }
2539              
2540             #
2541             # KOI8-U parse line
2542             #
2543             sub _parse_line {
2544              
2545 0     0     my($line) = @_;
2546              
2547 0           $line .= ' ';
2548 0           my @piece = ();
2549 0           while ($line =~ /
2550             " ( (?>(?: [^"] )* ) ) " (?>\s+) |
2551             ( (?>(?: [^"\s] )* ) ) (?>\s+)
2552             /oxmsg
2553             ) {
2554 0 0         push @piece, defined($1) ? $1 : $2;
2555             }
2556 0           return @piece;
2557             }
2558              
2559             #
2560             # KOI8-U parse path
2561             #
2562             sub _parse_path {
2563              
2564 0     0     my($path,$pathsep) = @_;
2565              
2566 0           $path .= '/';
2567 0           my @subpath = ();
2568 0           while ($path =~ /
2569             ((?: [^\/\\] )+?) [\/\\]
2570             /oxmsg
2571             ) {
2572 0           push @subpath, $1;
2573             }
2574              
2575 0           my $tail = pop @subpath;
2576 0           my $head = join $pathsep, @subpath;
2577 0           return $head, $tail;
2578             }
2579              
2580             #
2581             # via File::HomeDir::Windows 1.00
2582             #
2583             sub my_home_MSWin32 {
2584              
2585             # A lot of unix people and unix-derived tools rely on
2586             # the ability to overload HOME. We will support it too
2587             # so that they can replace raw HOME calls with File::HomeDir.
2588 0 0 0 0 0   if (exists $ENV{'HOME'} and $ENV{'HOME'}) {
    0 0        
    0 0        
      0        
      0        
2589 0           return $ENV{'HOME'};
2590             }
2591              
2592             # Do we have a user profile?
2593             elsif (exists $ENV{'USERPROFILE'} and $ENV{'USERPROFILE'}) {
2594 0           return $ENV{'USERPROFILE'};
2595             }
2596              
2597             # Some Windows use something like $ENV{'HOME'}
2598             elsif (exists $ENV{'HOMEDRIVE'} and exists $ENV{'HOMEPATH'} and $ENV{'HOMEDRIVE'} and $ENV{'HOMEPATH'}) {
2599 0           return join '', $ENV{'HOMEDRIVE'}, $ENV{'HOMEPATH'};
2600             }
2601              
2602 0           return undef;
2603             }
2604              
2605             #
2606             # via File::HomeDir::Unix 1.00
2607             #
2608             sub my_home {
2609 0     0 0   my $home;
2610              
2611 0 0 0       if (exists $ENV{'HOME'} and defined $ENV{'HOME'}) {
    0 0        
2612 0           $home = $ENV{'HOME'};
2613             }
2614              
2615             # This is from the original code, but I'm guessing
2616             # it means "login directory" and exists on some Unixes.
2617             elsif (exists $ENV{'LOGDIR'} and $ENV{'LOGDIR'}) {
2618 0           $home = $ENV{'LOGDIR'};
2619             }
2620              
2621             ### More-desperate methods
2622              
2623             # Light desperation on any (Unixish) platform
2624             else {
2625 0           $home = CORE::eval q{ (getpwuid($<))[7] };
2626             }
2627              
2628             # On Unix in general, a non-existant home means "no home"
2629             # For example, "nobody"-like users might use /nonexistant
2630 0 0 0       if (defined $home and ! -d($home)) {
2631 0           $home = undef;
2632             }
2633 0           return $home;
2634             }
2635              
2636             #
2637             # ${^PREMATCH}, $PREMATCH, $` the string preceding what was matched
2638             #
2639             sub Ekoi8u::PREMATCH {
2640 0     0 0   return $`;
2641             }
2642              
2643             #
2644             # ${^MATCH}, $MATCH, $& the string that matched
2645             #
2646             sub Ekoi8u::MATCH {
2647 0     0 0   return $&;
2648             }
2649              
2650             #
2651             # ${^POSTMATCH}, $POSTMATCH, $' the string following what was matched
2652             #
2653             sub Ekoi8u::POSTMATCH {
2654 0     0 0   return $';
2655             }
2656              
2657             #
2658             # KOI8-U character to order (with parameter)
2659             #
2660             sub KOI8U::ord(;$) {
2661              
2662 0 0   0 1   local $_ = shift if @_;
2663              
2664 0 0         if (/\A ($q_char) /oxms) {
2665 0           my @ord = unpack 'C*', $1;
2666 0           my $ord = 0;
2667 0           while (my $o = shift @ord) {
2668 0           $ord = $ord * 0x100 + $o;
2669             }
2670 0           return $ord;
2671             }
2672             else {
2673 0           return CORE::ord $_;
2674             }
2675             }
2676              
2677             #
2678             # KOI8-U character to order (without parameter)
2679             #
2680             sub KOI8U::ord_() {
2681              
2682 0 0   0 0   if (/\A ($q_char) /oxms) {
2683 0           my @ord = unpack 'C*', $1;
2684 0           my $ord = 0;
2685 0           while (my $o = shift @ord) {
2686 0           $ord = $ord * 0x100 + $o;
2687             }
2688 0           return $ord;
2689             }
2690             else {
2691 0           return CORE::ord $_;
2692             }
2693             }
2694              
2695             #
2696             # KOI8-U reverse
2697             #
2698             sub KOI8U::reverse(@) {
2699              
2700 0 0   0 0   if (wantarray) {
2701 0           return CORE::reverse @_;
2702             }
2703             else {
2704              
2705             # One of us once cornered Larry in an elevator and asked him what
2706             # problem he was solving with this, but he looked as far off into
2707             # the distance as he could in an elevator and said, "It seemed like
2708             # a good idea at the time."
2709              
2710 0           return join '', CORE::reverse(join('',@_) =~ /\G ($q_char) /oxmsg);
2711             }
2712             }
2713              
2714             #
2715             # KOI8-U getc (with parameter, without parameter)
2716             #
2717             sub KOI8U::getc(;*@) {
2718              
2719 0     0 0   my($package) = caller;
2720 0 0         my $fh = @_ ? qualify_to_ref(shift,$package) : \*STDIN;
2721 0 0 0       croak 'Too many arguments for KOI8U::getc' if @_ and not wantarray;
2722              
2723 0           my @length = sort { $a <=> $b } keys %range_tr;
  0            
2724 0           my $getc = '';
2725 0           for my $length ($length[0] .. $length[-1]) {
2726 0           $getc .= CORE::getc($fh);
2727 0 0         if (exists $range_tr{CORE::length($getc)}) {
2728 0 0         if ($getc =~ /\A ${Ekoi8u::dot_s} \z/oxms) {
2729 0 0         return wantarray ? ($getc,@_) : $getc;
2730             }
2731             }
2732             }
2733 0 0         return wantarray ? ($getc,@_) : $getc;
2734             }
2735              
2736             #
2737             # KOI8-U length by character
2738             #
2739             sub KOI8U::length(;$) {
2740              
2741 0 0   0 1   local $_ = shift if @_;
2742              
2743 0           local @_ = /\G ($q_char) /oxmsg;
2744 0           return scalar @_;
2745             }
2746              
2747             #
2748             # KOI8-U substr by character
2749             #
2750             BEGIN {
2751              
2752             # P.232 The lvalue Attribute
2753             # in Chapter 6: Subroutines
2754             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
2755              
2756             # P.336 The lvalue Attribute
2757             # in Chapter 7: Subroutines
2758             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
2759              
2760             # P.144 8.4 Lvalue subroutines
2761             # in Chapter 8: perlsub: Perl subroutines
2762             # of ISBN-13: 978-1-906966-02-7 The Perl Language Reference Manual (for Perl version 5.12.1)
2763              
2764 200 50 0 200 1 163725 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            
2765             # vv----------------------*******
2766             sub KOI8U::substr($$;$$) %s {
2767              
2768             my @char = $_[0] =~ /\G (?>$q_char) /oxmsg;
2769              
2770             # If the substring is beyond either end of the string, substr() returns the undefined
2771             # value and produces a warning. When used as an lvalue, specifying a substring that
2772             # is entirely outside the string raises an exception.
2773             # http://perldoc.perl.org/functions/substr.html
2774              
2775             # A return with no argument returns the scalar value undef in scalar context,
2776             # an empty list () in list context, and (naturally) nothing at all in void
2777             # context.
2778              
2779             my $offset = $_[1];
2780             if (($offset > scalar(@char)) or ($offset < (-1 * scalar(@char)))) {
2781             return;
2782             }
2783              
2784             # substr($string,$offset,$length,$replacement)
2785             if (@_ == 4) {
2786             my(undef,undef,$length,$replacement) = @_;
2787             my $substr = join '', splice(@char, $offset, $length, $replacement);
2788             $_[0] = join '', @char;
2789              
2790             # return $substr; this doesn't work, don't say "return"
2791             $substr;
2792             }
2793              
2794             # substr($string,$offset,$length)
2795             elsif (@_ == 3) {
2796             my(undef,undef,$length) = @_;
2797             my $octet_offset = 0;
2798             my $octet_length = 0;
2799             if ($offset == 0) {
2800             $octet_offset = 0;
2801             }
2802             elsif ($offset > 0) {
2803             $octet_offset = CORE::length(join '', @char[0..$offset-1]);
2804             }
2805             else {
2806             $octet_offset = -1 * CORE::length(join '', @char[$#char+$offset+1..$#char]);
2807             }
2808             if ($length == 0) {
2809             $octet_length = 0;
2810             }
2811             elsif ($length > 0) {
2812             $octet_length = CORE::length(join '', @char[$offset..$offset+$length-1]);
2813             }
2814             else {
2815             $octet_length = -1 * CORE::length(join '', @char[$#char+$length+1..$#char]);
2816             }
2817             CORE::substr($_[0], $octet_offset, $octet_length);
2818             }
2819              
2820             # substr($string,$offset)
2821             else {
2822             my $octet_offset = 0;
2823             if ($offset == 0) {
2824             $octet_offset = 0;
2825             }
2826             elsif ($offset > 0) {
2827             $octet_offset = CORE::length(join '', @char[0..$offset-1]);
2828             }
2829             else {
2830             $octet_offset = -1 * CORE::length(join '', @char[$#char+$offset+1..$#char]);
2831             }
2832             CORE::substr($_[0], $octet_offset);
2833             }
2834             }
2835             END
2836             }
2837              
2838             #
2839             # KOI8-U index by character
2840             #
2841             sub KOI8U::index($$;$) {
2842              
2843 0     0 1   my $index;
2844 0 0         if (@_ == 3) {
2845 0           $index = Ekoi8u::index($_[0], $_[1], CORE::length(KOI8U::substr($_[0], 0, $_[2])));
2846             }
2847             else {
2848 0           $index = Ekoi8u::index($_[0], $_[1]);
2849             }
2850              
2851 0 0         if ($index == -1) {
2852 0           return -1;
2853             }
2854             else {
2855 0           return KOI8U::length(CORE::substr $_[0], 0, $index);
2856             }
2857             }
2858              
2859             #
2860             # KOI8-U rindex by character
2861             #
2862             sub KOI8U::rindex($$;$) {
2863              
2864 0     0 1   my $rindex;
2865 0 0         if (@_ == 3) {
2866 0           $rindex = Ekoi8u::rindex($_[0], $_[1], CORE::length(KOI8U::substr($_[0], 0, $_[2])));
2867             }
2868             else {
2869 0           $rindex = Ekoi8u::rindex($_[0], $_[1]);
2870             }
2871              
2872 0 0         if ($rindex == -1) {
2873 0           return -1;
2874             }
2875             else {
2876 0           return KOI8U::length(CORE::substr $_[0], 0, $rindex);
2877             }
2878             }
2879              
2880             # when 'm//', '/' means regexp match 'm//' and '?' means regexp match '??'
2881             # when 'div', '/' means division operator and '?' means conditional operator (condition ? then : else)
2882 200     200   21435 BEGIN { CORE::eval q{ use vars qw($slash) } } $slash = 'm//';
  200     200   2407  
  200         446  
  200         18004  
2883              
2884             # ord() to ord() or KOI8U::ord()
2885 200     200   14959 BEGIN { CORE::eval q{ use vars qw($function_ord) } } $function_ord = 'ord';
  200     200   1457  
  200         448  
  200         13613  
2886              
2887             # ord to ord or KOI8U::ord_
2888 200     200   15367 BEGIN { CORE::eval q{ use vars qw($function_ord_) } } $function_ord_ = 'ord';
  200     200   1534  
  200         404  
  200         13368  
2889              
2890             # reverse to reverse or KOI8U::reverse
2891 200     200   15875 BEGIN { CORE::eval q{ use vars qw($function_reverse) } } $function_reverse = 'reverse';
  200     200   1270  
  200         432  
  200         14336  
2892              
2893             # getc to getc or KOI8U::getc
2894 200     200   14914 BEGIN { CORE::eval q{ use vars qw($function_getc) } } $function_getc = 'getc';
  200     200   1283  
  200         386  
  200         19953  
2895              
2896             # P.1023 Appendix W.9 Multibyte Anchoring
2897             # of ISBN 1-56592-224-7 CJKV Information Processing
2898              
2899             my $anchor = '';
2900              
2901 200     200   13985 BEGIN { CORE::eval q{ use vars qw($nest) } }
  200     200   1221  
  200         415  
  200         13326410  
2902              
2903             # regexp of nested parens in qqXX
2904              
2905             # P.340 Matching Nested Constructs with Embedded Code
2906             # in Chapter 7: Perl
2907             # of ISBN 0-596-00289-0 Mastering Regular Expressions, Second edition
2908              
2909             my $qq_paren = qr{(?{local $nest=0}) (?>(?:
2910             [^\\()] |
2911             \( (?{$nest++}) |
2912             \) (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!)) |
2913             \\ [^c] |
2914             \\c[\x40-\x5F] |
2915             [\x00-\xFF]
2916             }xms;
2917              
2918             my $qq_brace = qr{(?{local $nest=0}) (?>(?:
2919             [^\\{}] |
2920             \{ (?{$nest++}) |
2921             \} (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!)) |
2922             \\ [^c] |
2923             \\c[\x40-\x5F] |
2924             [\x00-\xFF]
2925             }xms;
2926              
2927             my $qq_bracket = qr{(?{local $nest=0}) (?>(?:
2928             [^\\\[\]] |
2929             \[ (?{$nest++}) |
2930             \] (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!)) |
2931             \\ [^c] |
2932             \\c[\x40-\x5F] |
2933             [\x00-\xFF]
2934             }xms;
2935              
2936             my $qq_angle = qr{(?{local $nest=0}) (?>(?:
2937             [^\\<>] |
2938             \< (?{$nest++}) |
2939             \> (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!)) |
2940             \\ [^c] |
2941             \\c[\x40-\x5F] |
2942             [\x00-\xFF]
2943             }xms;
2944              
2945             my $qq_scalar = qr{(?: \{ (?:$qq_brace)*? \} |
2946             (?: ::)? (?:
2947             (?> [a-zA-Z_][a-zA-Z_0-9]* (?: ::[a-zA-Z_][a-zA-Z_0-9]*)* )
2948             (?>(?: \[ (?: \$\[ | \$\] | $qq_char )*? \] | \{ (?:$qq_brace)*? \} )*)
2949             (?>(?: (?: -> )? (?: [\$\@\%\&\*]\* | \$\#\* | [\@\%]? \[ (?: \$\[ | \$\] | $qq_char )*? \] | [\@\%\*]? \{ (?:$qq_brace)*? \} ) )*)
2950             ))
2951             }xms;
2952              
2953             my $qq_variable = qr{(?: \{ (?:$qq_brace)*? \} |
2954             (?: ::)? (?:
2955             (?>[0-9]+) |
2956             [^a-zA-Z_0-9\[\]] |
2957             ^[A-Z] |
2958             (?> [a-zA-Z_][a-zA-Z_0-9]* (?: ::[a-zA-Z_][a-zA-Z_0-9]*)* )
2959             (?>(?: \[ (?: \$\[ | \$\] | $qq_char )*? \] | \{ (?:$qq_brace)*? \} )*)
2960             (?>(?: (?: -> )? (?: [\$\@\%\&\*]\* | \$\#\* | [\@\%]? \[ (?: \$\[ | \$\] | $qq_char )*? \] | [\@\%\*]? \{ (?:$qq_brace)*? \} ) )*)
2961             ))
2962             }xms;
2963              
2964             my $qq_substr = qr{(?> Char::substr | KOI8U::substr | CORE::substr | substr ) (?>\s*) \( $qq_paren \)
2965             }xms;
2966              
2967             # regexp of nested parens in qXX
2968             my $q_paren = qr{(?{local $nest=0}) (?>(?:
2969             [^()] |
2970             \( (?{$nest++}) |
2971             \) (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!)) |
2972             [\x00-\xFF]
2973             }xms;
2974              
2975             my $q_brace = qr{(?{local $nest=0}) (?>(?:
2976             [^\{\}] |
2977             \{ (?{$nest++}) |
2978             \} (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!)) |
2979             [\x00-\xFF]
2980             }xms;
2981              
2982             my $q_bracket = qr{(?{local $nest=0}) (?>(?:
2983             [^\[\]] |
2984             \[ (?{$nest++}) |
2985             \] (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!)) |
2986             [\x00-\xFF]
2987             }xms;
2988              
2989             my $q_angle = qr{(?{local $nest=0}) (?>(?:
2990             [^<>] |
2991             \< (?{$nest++}) |
2992             \> (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!)) |
2993             [\x00-\xFF]
2994             }xms;
2995              
2996             my $matched = '';
2997             my $s_matched = '';
2998              
2999             my $tr_variable = ''; # variable of tr///
3000             my $sub_variable = ''; # variable of s///
3001             my $bind_operator = ''; # =~ or !~
3002              
3003             my @heredoc = (); # here document
3004             my @heredoc_delimiter = ();
3005             my $here_script = ''; # here script
3006              
3007             #
3008             # escape KOI8-U script
3009             #
3010             sub KOI8U::escape(;$) {
3011 0 0   0 0   local($_) = $_[0] if @_;
3012              
3013             # P.359 The Study Function
3014             # in Chapter 7: Perl
3015             # of ISBN 0-596-00289-0 Mastering Regular Expressions, Second edition
3016              
3017 0           study $_; # Yes, I studied study yesterday.
3018              
3019             # while all script
3020              
3021             # 6.14. Matching from Where the Last Pattern Left Off
3022             # in Chapter 6. Pattern Matching
3023             # of ISBN 0-596-00313-7 Perl Cookbook, 2nd Edition.
3024             # (and so on)
3025              
3026             # one member of Tag-team
3027             #
3028             # P.128 Start of match (or end of previous match): \G
3029             # P.130 Advanced Use of \G with Perl
3030             # in Chapter 3: Overview of Regular Expression Features and Flavors
3031             # P.255 Use leading anchors
3032             # P.256 Expose ^ and \G at the front expressions
3033             # in Chapter 6: Crafting an Efficient Expression
3034             # P.315 "Tag-team" matching with /gc
3035             # in Chapter 7: Perl
3036             # of ISBN 0-596-00289-0 Mastering Regular Expressions, Second edition
3037              
3038 0           my $e_script = '';
3039 0           while (not /\G \z/oxgc) { # member
3040 0           $e_script .= KOI8U::escape_token();
3041             }
3042              
3043 0           return $e_script;
3044             }
3045              
3046             #
3047             # escape KOI8-U token of script
3048             #
3049             sub KOI8U::escape_token {
3050              
3051             # \n output here document
3052              
3053 0     0 0   my $ignore_modules = join('|', qw(
3054             utf8
3055             bytes
3056             charnames
3057             I18N::Japanese
3058             I18N::Collate
3059             I18N::JExt
3060             File::DosGlob
3061             Wild
3062             Wildcard
3063             Japanese
3064             ));
3065              
3066             # another member of Tag-team
3067             #
3068             # P.315 "Tag-team" matching with /gc
3069             # in Chapter 7: Perl
3070             # of ISBN 0-596-00289-0 Mastering Regular Expressions, Second edition
3071              
3072 0 0 0       if (/\G ( \n ) /oxgc) { # another member (and so on)
    0 0        
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    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          
3073 0           my $heredoc = '';
3074 0 0         if (scalar(@heredoc_delimiter) >= 1) {
3075 0           $slash = 'm//';
3076              
3077 0           $heredoc = join '', @heredoc;
3078 0           @heredoc = ();
3079              
3080             # skip here document
3081 0           for my $heredoc_delimiter (@heredoc_delimiter) {
3082 0           /\G .*? \n $heredoc_delimiter \n/xmsgc;
3083             }
3084 0           @heredoc_delimiter = ();
3085              
3086 0           $here_script = '';
3087             }
3088 0           return "\n" . $heredoc;
3089             }
3090              
3091             # ignore space, comment
3092 0           elsif (/\G ((?>\s+)|\#.*) /oxgc) { return $1; }
3093              
3094             # if (, elsif (, unless (, while (, until (, given (, and when (
3095              
3096             # given, when
3097              
3098             # P.225 The given Statement
3099             # in Chapter 15: Smart Matching and given-when
3100             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
3101              
3102             # P.133 The given Statement
3103             # in Chapter 4: Statements and Declarations
3104             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
3105              
3106             elsif (/\G ( (?: if | elsif | unless | while | until | given | when ) (?>\s*) \( ) /oxgc) {
3107 0           $slash = 'm//';
3108 0           return $1;
3109             }
3110              
3111             # scalar variable ($scalar = ...) =~ tr///;
3112             # scalar variable ($scalar = ...) =~ s///;
3113              
3114             # state
3115              
3116             # P.68 Persistent, Private Variables
3117             # in Chapter 4: Subroutines
3118             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
3119              
3120             # P.160 Persistent Lexically Scoped Variables: state
3121             # in Chapter 4: Statements and Declarations
3122             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
3123              
3124             # (and so on)
3125              
3126             elsif (/\G ( \( (?>\s*) (?: local \b | my \b | our \b | state \b )? (?>\s*) \$ $qq_scalar ) /oxgc) {
3127 0           my $e_string = e_string($1);
3128              
3129 0 0         if (/\G ( (?>\s*) = $qq_paren \) ) ( (?>\s*) (?: =~ | !~ ) (?>\s*) ) (?= (?: tr | y ) \b ) /oxgc) {
    0          
3130 0           $tr_variable = $e_string . e_string($1);
3131 0           $bind_operator = $2;
3132 0           $slash = 'm//';
3133 0           return '';
3134             }
3135             elsif (/\G ( (?>\s*) = $qq_paren \) ) ( (?>\s*) (?: =~ | !~ ) (?>\s*) ) (?= s \b ) /oxgc) {
3136 0           $sub_variable = $e_string . e_string($1);
3137 0           $bind_operator = $2;
3138 0           $slash = 'm//';
3139 0           return '';
3140             }
3141             else {
3142 0           $slash = 'div';
3143 0           return $e_string;
3144             }
3145             }
3146              
3147             # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Ekoi8u::PREMATCH()
3148             elsif (/\G ( \$` | \$\{`\} | \$ (?>\s*) PREMATCH \b | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} ) /oxmsgc) {
3149 0           $slash = 'div';
3150 0           return q{Ekoi8u::PREMATCH()};
3151             }
3152              
3153             # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Ekoi8u::MATCH()
3154             elsif (/\G ( \$& | \$\{&\} | \$ (?>\s*) MATCH \b | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} ) /oxmsgc) {
3155 0           $slash = 'div';
3156 0           return q{Ekoi8u::MATCH()};
3157             }
3158              
3159             # $', ${'} --> $', ${'}
3160             elsif (/\G ( \$' | \$\{'\} ) /oxmsgc) {
3161 0           $slash = 'div';
3162 0           return $1;
3163             }
3164              
3165             # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Ekoi8u::POSTMATCH()
3166             elsif (/\G ( \$ (?>\s*) POSTMATCH \b | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} ) /oxmsgc) {
3167 0           $slash = 'div';
3168 0           return q{Ekoi8u::POSTMATCH()};
3169             }
3170              
3171             # scalar variable $scalar =~ tr///;
3172             # scalar variable $scalar =~ s///;
3173             # substr() =~ tr///;
3174             # substr() =~ s///;
3175             elsif (/\G ( \$ $qq_scalar | $qq_substr ) /oxgc) {
3176 0           my $scalar = e_string($1);
3177              
3178 0 0         if (/\G ( (?>\s*) (?: =~ | !~ ) (?>\s*) ) (?= (?: tr | y ) \b ) /oxgc) {
    0          
3179 0           $tr_variable = $scalar;
3180 0           $bind_operator = $1;
3181 0           $slash = 'm//';
3182 0           return '';
3183             }
3184             elsif (/\G ( (?>\s*) (?: =~ | !~ ) (?>\s*) ) (?= s \b ) /oxgc) {
3185 0           $sub_variable = $scalar;
3186 0           $bind_operator = $1;
3187 0           $slash = 'm//';
3188 0           return '';
3189             }
3190             else {
3191 0           $slash = 'div';
3192 0           return $scalar;
3193             }
3194             }
3195              
3196             # end of statement
3197             elsif (/\G ( [,;] ) /oxgc) {
3198 0           $slash = 'm//';
3199              
3200             # clear tr/// variable
3201 0           $tr_variable = '';
3202              
3203             # clear s/// variable
3204 0           $sub_variable = '';
3205              
3206 0           $bind_operator = '';
3207              
3208 0           return $1;
3209             }
3210              
3211             # bareword
3212             elsif (/\G ( \{ (?>\s*) (?: tr | index | rindex | reverse ) (?>\s*) \} ) /oxmsgc) {
3213 0           return $1;
3214             }
3215              
3216             # $0 --> $0
3217             elsif (/\G ( \$ 0 ) /oxmsgc) {
3218 0           $slash = 'div';
3219 0           return $1;
3220             }
3221             elsif (/\G ( \$ \{ (?>\s*) 0 (?>\s*) \} ) /oxmsgc) {
3222 0           $slash = 'div';
3223 0           return $1;
3224             }
3225              
3226             # $$ --> $$
3227             elsif (/\G ( \$ \$ ) (?![\w\{]) /oxmsgc) {
3228 0           $slash = 'div';
3229 0           return $1;
3230             }
3231              
3232             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
3233             # $1, $2, $3 --> $1, $2, $3 otherwise
3234             elsif (/\G \$ ((?>[1-9][0-9]*)) /oxmsgc) {
3235 0           $slash = 'div';
3236 0           return e_capture($1);
3237             }
3238             elsif (/\G \$ \{ (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} /oxmsgc) {
3239 0           $slash = 'div';
3240 0           return e_capture($1);
3241             }
3242              
3243             # $$foo[ ... ] --> $ $foo->[ ... ]
3244             elsif (/\G \$ ( \$ (?> [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \[ .+? \] ) /oxmsgc) {
3245 0           $slash = 'div';
3246 0           return e_capture($1.'->'.$2);
3247             }
3248              
3249             # $$foo{ ... } --> $ $foo->{ ... }
3250             elsif (/\G \$ ( \$ (?> [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \{ .+? \} ) /oxmsgc) {
3251 0           $slash = 'div';
3252 0           return e_capture($1.'->'.$2);
3253             }
3254              
3255             # $$foo
3256             elsif (/\G \$ ( \$ (?> [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) /oxmsgc) {
3257 0           $slash = 'div';
3258 0           return e_capture($1);
3259             }
3260              
3261             # ${ foo }
3262             elsif (/\G \$ (?>\s*) \{ ( (?>\s*) (?> [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) (?>\s*) ) \} /oxmsgc) {
3263 0           $slash = 'div';
3264 0           return '${' . $1 . '}';
3265             }
3266              
3267             # ${ ... }
3268             elsif (/\G \$ (?>\s*) \{ (?>\s*) ( $qq_brace ) (?>\s*) \} /oxmsgc) {
3269 0           $slash = 'div';
3270 0           return e_capture($1);
3271             }
3272              
3273             # variable or function
3274             # $ @ % & * $ #
3275             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) {
3276 0           $slash = 'div';
3277 0           return $1;
3278             }
3279             # $ $ $ $ $ $ $ $ $ $ $ $ $ $
3280             # $ @ # \ ' " / ? ( ) [ ] < >
3281             elsif (/\G ( \$[\$\@\#\\\'\"\/\?\(\)\[\]\<\>] ) /oxmsgc) {
3282 0           $slash = 'div';
3283 0           return $1;
3284             }
3285              
3286             # while ()
3287             elsif (/\G \b (while (?>\s*) \( (?>\s*) <[\$]?[A-Za-z_][A-Za-z_0-9]*> (?>\s*) \)) \b /oxgc) {
3288 0           return $1;
3289             }
3290              
3291             # while () --- glob
3292              
3293             # avoid "Error: Runtime exception" of perl version 5.005_03
3294              
3295             elsif (/\G \b while (?>\s*) \( (?>\s*) < ((?:[^>\0\a\e\f\n\r\t])+?) > (?>\s*) \) \b /oxgc) {
3296 0           return 'while ($_ = Ekoi8u::glob("' . $1 . '"))';
3297             }
3298              
3299             # while (glob)
3300             elsif (/\G \b while (?>\s*) \( (?>\s*) glob (?>\s*) \) /oxgc) {
3301 0           return 'while ($_ = Ekoi8u::glob_)';
3302             }
3303              
3304             # while (glob(WILDCARD))
3305             elsif (/\G \b while (?>\s*) \( (?>\s*) glob \b /oxgc) {
3306 0           return 'while ($_ = Ekoi8u::glob';
3307             }
3308              
3309             # doit if, doit unless, doit while, doit until, doit for, doit when
3310 0           elsif (/\G \b ( if | unless | while | until | for | when ) \b /oxgc) { $slash = 'm//'; return $1; }
  0            
3311              
3312             # subroutines of package Ekoi8u
3313 0           elsif (/\G \b (CORE:: | ->(>?\s*) (?: atan2 | [a-z]{2,})) \b /oxgc) { $slash = 'm//'; return $1; }
  0            
3314 0           elsif (/\G \b Char::eval (?= (?>\s*) \{ ) /oxgc) { $slash = 'm//'; return 'eval'; }
  0            
3315 0           elsif (/\G \b KOI8U::eval (?= (?>\s*) \{ ) /oxgc) { $slash = 'm//'; return 'eval'; }
  0            
3316 0           elsif (/\G \b Char::eval \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'eval Char::escape'; }
  0            
3317 0           elsif (/\G \b KOI8U::eval \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'eval KOI8U::escape'; }
  0            
3318 0           elsif (/\G \b bytes::substr \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'substr'; }
  0            
3319 0           elsif (/\G \b chop \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Ekoi8u::chop'; }
  0            
3320 0           elsif (/\G \b bytes::index \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'index'; }
  0            
3321 0           elsif (/\G \b Char::index \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Char::index'; }
  0            
3322 0           elsif (/\G \b KOI8U::index \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'KOI8U::index'; }
  0            
3323 0           elsif (/\G \b index \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Ekoi8u::index'; }
  0            
3324 0           elsif (/\G \b bytes::rindex \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'rindex'; }
  0            
3325 0           elsif (/\G \b Char::rindex \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Char::rindex'; }
  0            
3326 0           elsif (/\G \b KOI8U::rindex \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'KOI8U::rindex'; }
  0            
3327 0           elsif (/\G \b rindex \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Ekoi8u::rindex'; }
  0            
3328 0           elsif (/\G \b lc (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Ekoi8u::lc'; }
  0            
3329 0           elsif (/\G \b lcfirst (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Ekoi8u::lcfirst'; }
  0            
3330 0           elsif (/\G \b uc (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Ekoi8u::uc'; }
  0            
3331 0           elsif (/\G \b ucfirst (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Ekoi8u::ucfirst'; }
  0            
3332 0           elsif (/\G \b fc (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Ekoi8u::fc'; }
  0            
3333              
3334             # "-s '' ..." means file test "-s 'filename' ..." (not means "- s/// ...")
3335 0           elsif (/\G -s (?>\s*) (\") ((?:$qq_char)+?) (\") /oxgc) { $slash = 'm//'; return '-s ' . e_qq('', $1,$3,$2); }
  0            
3336 0           elsif (/\G -s (?>\s+) qq (?>\s*) (\#) ((?:$qq_char)+?) (\#) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0            
3337 0           elsif (/\G -s (?>\s+) qq (?>\s*) (\() ((?:$qq_paren)+?) (\)) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0            
3338 0           elsif (/\G -s (?>\s+) qq (?>\s*) (\{) ((?:$qq_brace)+?) (\}) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0            
3339 0           elsif (/\G -s (?>\s+) qq (?>\s*) (\[) ((?:$qq_bracket)+?) (\]) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0            
3340 0           elsif (/\G -s (?>\s+) qq (?>\s*) (\<) ((?:$qq_angle)+?) (\>) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0            
3341 0           elsif (/\G -s (?>\s+) qq (?>\s*) (\S) ((?:$qq_char)+?) (\1) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0            
3342              
3343 0           elsif (/\G -s (?>\s*) (\') ((?:\\\'|\\\\|$q_char)+?) (\') /oxgc) { $slash = 'm//'; return '-s ' . e_q ('', $1,$3,$2); }
  0            
3344 0           elsif (/\G -s (?>\s+) q (?>\s*) (\#) ((?:\\\#|\\\\|$q_char)+?) (\#) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0            
3345 0           elsif (/\G -s (?>\s+) q (?>\s*) (\() ((?:\\\)|\\\\|$q_paren)+?) (\)) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0            
3346 0           elsif (/\G -s (?>\s+) q (?>\s*) (\{) ((?:\\\}|\\\\|$q_brace)+?) (\}) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0            
3347 0           elsif (/\G -s (?>\s+) q (?>\s*) (\[) ((?:\\\]|\\\\|$q_bracket)+?) (\]) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0            
3348 0           elsif (/\G -s (?>\s+) q (?>\s*) (\<) ((?:\\\>|\\\\|$q_angle)+?) (\>) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0            
3349 0           elsif (/\G -s (?>\s+) q (?>\s*) (\S) ((?:\\\1|\\\\|$q_char)+?) (\1) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0            
3350              
3351             elsif (/\G -s (?>\s*) (\$ (?> \w+ (?: ::\w+)* ) (?: (?: ->)? (?: [\$\@\%\&\*]\* | \$\#\* | \( (?:$qq_paren)*? \) | [\@\%\*]? \{ (?:$qq_brace)+? \} | [\@\%]? \[ (?:$qq_bracket)+? \] ) )*) /oxgc)
3352 0           { $slash = 'm//'; return "-s $1"; }
  0            
3353 0           elsif (/\G -s (?>\s*) \( ((?:$qq_paren)*?) \) /oxgc) { $slash = 'm//'; return "-s ($1)"; }
  0            
3354 0           elsif (/\G -s (?= (?>\s+) [a-z]+) /oxgc) { $slash = 'm//'; return '-s'; }
  0            
3355 0           elsif (/\G -s (?>\s+) ((?>\w+)) /oxgc) { $slash = 'm//'; return "-s $1"; }
  0            
3356              
3357 0           elsif (/\G \b bytes::length (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'length'; }
  0            
3358 0           elsif (/\G \b bytes::chr (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'chr'; }
  0            
3359 0           elsif (/\G \b chr (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Ekoi8u::chr'; }
  0            
3360 0           elsif (/\G \b bytes::ord (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'div'; return 'ord'; }
  0            
3361 0           elsif (/\G \b ord (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'div'; return $function_ord; }
  0            
3362 0           elsif (/\G \b glob (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Ekoi8u::glob'; }
  0            
3363 0           elsif (/\G \b lc \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Ekoi8u::lc_'; }
  0            
3364 0           elsif (/\G \b lcfirst \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Ekoi8u::lcfirst_'; }
  0            
3365 0           elsif (/\G \b uc \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Ekoi8u::uc_'; }
  0            
3366 0           elsif (/\G \b ucfirst \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Ekoi8u::ucfirst_'; }
  0            
3367 0           elsif (/\G \b fc \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Ekoi8u::fc_'; }
  0            
3368 0           elsif (/\G -s \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return '-s '; }
  0            
3369              
3370 0           elsif (/\G \b bytes::length \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'length'; }
  0            
3371 0           elsif (/\G \b bytes::chr \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'chr'; }
  0            
3372 0           elsif (/\G \b chr \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Ekoi8u::chr_'; }
  0            
3373 0           elsif (/\G \b bytes::ord \b (?! (?>\s*) => ) /oxgc) { $slash = 'div'; return 'ord'; }
  0            
3374 0           elsif (/\G \b ord \b (?! (?>\s*) => ) /oxgc) { $slash = 'div'; return $function_ord_; }
  0            
3375 0           elsif (/\G \b glob \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Ekoi8u::glob_'; }
  0            
3376 0           elsif (/\G \b reverse \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return $function_reverse; }
  0            
3377 0           elsif (/\G \b getc \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return $function_getc; }
  0            
3378             # split
3379             elsif (/\G \b (split) \b (?! (?>\s*) => ) /oxgc) {
3380 0           $slash = 'm//';
3381              
3382 0           my $e = '';
3383 0           while (/\G ( (?>\s+) | \( | \#.* ) /oxgc) {
3384 0           $e .= $1;
3385             }
3386              
3387             # end of split
3388 0 0         if (/\G (?= [,;\)\}\]] ) /oxgc) { return 'Ekoi8u::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          
3389              
3390             # split scalar value
3391 0           elsif (/\G ( [\$\@\&\*] $qq_scalar ) /oxgc) { return 'Ekoi8u::split' . $e . e_string($1); }
3392              
3393             # split literal space
3394 0           elsif (/\G \b qq (\#) [ ] (\#) /oxgc) { return 'Ekoi8u::split' . $e . qq {qq$1 $2}; }
3395 0           elsif (/\G \b qq ((?>\s*)) (\() [ ] (\)) /oxgc) { return 'Ekoi8u::split' . $e . qq{$1qq$2 $3}; }
3396 0           elsif (/\G \b qq ((?>\s*)) (\{) [ ] (\}) /oxgc) { return 'Ekoi8u::split' . $e . qq{$1qq$2 $3}; }
3397 0           elsif (/\G \b qq ((?>\s*)) (\[) [ ] (\]) /oxgc) { return 'Ekoi8u::split' . $e . qq{$1qq$2 $3}; }
3398 0           elsif (/\G \b qq ((?>\s*)) (\<) [ ] (\>) /oxgc) { return 'Ekoi8u::split' . $e . qq{$1qq$2 $3}; }
3399 0           elsif (/\G \b qq ((?>\s*)) (\S) [ ] (\2) /oxgc) { return 'Ekoi8u::split' . $e . qq{$1qq$2 $3}; }
3400 0           elsif (/\G \b q (\#) [ ] (\#) /oxgc) { return 'Ekoi8u::split' . $e . qq {q$1 $2}; }
3401 0           elsif (/\G \b q ((?>\s*)) (\() [ ] (\)) /oxgc) { return 'Ekoi8u::split' . $e . qq {$1q$2 $3}; }
3402 0           elsif (/\G \b q ((?>\s*)) (\{) [ ] (\}) /oxgc) { return 'Ekoi8u::split' . $e . qq {$1q$2 $3}; }
3403 0           elsif (/\G \b q ((?>\s*)) (\[) [ ] (\]) /oxgc) { return 'Ekoi8u::split' . $e . qq {$1q$2 $3}; }
3404 0           elsif (/\G \b q ((?>\s*)) (\<) [ ] (\>) /oxgc) { return 'Ekoi8u::split' . $e . qq {$1q$2 $3}; }
3405 0           elsif (/\G \b q ((?>\s*)) (\S) [ ] (\2) /oxgc) { return 'Ekoi8u::split' . $e . qq {$1q$2 $3}; }
3406 0           elsif (/\G ' [ ] ' /oxgc) { return 'Ekoi8u::split' . $e . qq {' '}; }
3407 0           elsif (/\G " [ ] " /oxgc) { return 'Ekoi8u::split' . $e . qq {" "}; }
3408              
3409             # split qq//
3410             elsif (/\G \b (qq) \b /oxgc) {
3411 0 0         if (/\G (\#) ((?:$qq_char)*?) (\#) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq# # --> qr # #
  0            
3412             else {
3413 0           while (not /\G \z/oxgc) {
3414 0 0         if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
3415 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq ( ) --> qr ( )
3416 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq { } --> qr { }
3417 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq [ ] --> qr [ ]
3418 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq < > --> qr < >
3419 0           elsif (/\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) /oxgc) { return e_split($e.'qr','{','}',$2,''); } # qq | | --> qr { }
3420 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq * * --> qr * *
3421             }
3422 0           die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3423             }
3424             }
3425              
3426             # split qr//
3427             elsif (/\G \b (qr) \b /oxgc) {
3428 0 0         if (/\G (\#) ((?:$qq_char)*?) (\#) ([imosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1,$3,$2,$4); } # qr# #
  0            
3429             else {
3430 0           while (not /\G \z/oxgc) {
3431 0 0         if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
3432 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([imosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # qr ( )
3433 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([imosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # qr { }
3434 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([imosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # qr [ ]
3435 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([imosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # qr < >
3436 0           elsif (/\G (\') ((?:$qq_char)*?) (\') ([imosxpadlunbB]*) /oxgc) { return e_split_q($e.'qr',$1, $3, $2,$4); } # qr ' '
3437 0           elsif (/\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ([imosxpadlunbB]*) /oxgc) { return e_split ($e.'qr','{','}',$2,$4); } # qr | | --> qr { }
3438 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([imosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # qr * *
3439             }
3440 0           die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3441             }
3442             }
3443              
3444             # split q//
3445             elsif (/\G \b (q) \b /oxgc) {
3446 0 0         if (/\G (\#) ((?:\\\#|\\\\|$q_char)*?) (\#) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q# # --> qr # #
  0            
3447             else {
3448 0           while (not /\G \z/oxgc) {
3449 0 0         if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
3450 0           elsif (/\G (\() ((?:\\\\|\\\)|\\\(|$q_paren)*?) (\)) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q ( ) --> qr ( )
3451 0           elsif (/\G (\{) ((?:\\\\|\\\}|\\\{|$q_brace)*?) (\}) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q { } --> qr { }
3452 0           elsif (/\G (\[) ((?:\\\\|\\\]|\\\[|$q_bracket)*?) (\]) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q [ ] --> qr [ ]
3453 0           elsif (/\G (\<) ((?:\\\\|\\\>|\\\<|$q_angle)*?) (\>) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q < > --> qr < >
3454 0           elsif (/\G ([*\-:?\\^|]) ((?:$q_char)*?) (\1) /oxgc) { return e_split_q($e.'qr','{','}',$2,''); } # q | | --> qr { }
3455 0           elsif (/\G (\S) ((?:\\\\|\\\1| $q_char)*?) (\1) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q * * --> qr * *
3456             }
3457 0           die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3458             }
3459             }
3460              
3461             # split m//
3462             elsif (/\G \b (m) \b /oxgc) {
3463 0 0         if (/\G (\#) ((?:$qq_char)*?) (\#) ([cgimosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1,$3,$2,$4); } # m# # --> qr # #
  0            
3464             else {
3465 0           while (not /\G \z/oxgc) {
3466 0 0         if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
3467 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cgimosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # m ( ) --> qr ( )
3468 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cgimosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # m { } --> qr { }
3469 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cgimosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # m [ ] --> qr [ ]
3470 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cgimosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # m < > --> qr < >
3471 0           elsif (/\G (\') ((?:$qq_char)*?) (\') ([cgimosxpadlunbB]*) /oxgc) { return e_split_q($e.'qr',$1, $3, $2,$4); } # m ' ' --> qr ' '
3472 0           elsif (/\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ([cgimosxpadlunbB]*) /oxgc) { return e_split ($e.'qr','{','}',$2,$4); } # m | | --> qr { }
3473 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cgimosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # m * * --> qr * *
3474             }
3475 0           die __FILE__, ": Search pattern not terminated\n";
3476             }
3477             }
3478              
3479             # split ''
3480             elsif (/\G (\') /oxgc) {
3481 0           my $q_string = '';
3482 0           while (not /\G \z/oxgc) {
3483 0 0         if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0          
    0          
    0          
3484 0           elsif (/\G (\\\') /oxgc) { $q_string .= $1; } # splitqr'' --> split qr''
3485 0           elsif (/\G \' /oxgc) { return e_split_q($e.q{ qr},"'","'",$q_string,''); } # ' ' --> qr ' '
3486 0           elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3487             }
3488 0           die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3489             }
3490              
3491             # split ""
3492             elsif (/\G (\") /oxgc) {
3493 0           my $qq_string = '';
3494 0           while (not /\G \z/oxgc) {
3495 0 0         if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0          
    0          
    0          
3496 0           elsif (/\G (\\\") /oxgc) { $qq_string .= $1; } # splitqr"" --> split qr""
3497 0           elsif (/\G \" /oxgc) { return e_split($e.q{ qr},'"','"',$qq_string,''); } # " " --> qr " "
3498 0           elsif (/\G ($q_char) /oxgc) { $qq_string .= $1; }
3499             }
3500 0           die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3501             }
3502              
3503             # split //
3504             elsif (/\G (\/) /oxgc) {
3505 0           my $regexp = '';
3506 0           while (not /\G \z/oxgc) {
3507 0 0         if (/\G (\\\\) /oxgc) { $regexp .= $1; }
  0 0          
    0          
    0          
3508 0           elsif (/\G (\\\/) /oxgc) { $regexp .= $1; } # splitqr// --> split qr//
3509 0           elsif (/\G \/ ([cgimosxpadlunbB]*) /oxgc) { return e_split($e.q{ qr}, '/','/',$regexp,$1); } # / / --> qr / /
3510 0           elsif (/\G ($q_char) /oxgc) { $regexp .= $1; }
3511             }
3512 0           die __FILE__, ": Search pattern not terminated\n";
3513             }
3514             }
3515              
3516             # tr/// or y///
3517              
3518             # about [cdsrbB]* (/B modifier)
3519             #
3520             # P.559 appendix C
3521             # of ISBN 4-89052-384-7 Programming perl
3522             # (Japanese title is: Perl puroguramingu)
3523              
3524             elsif (/\G \b ( tr | y ) \b /oxgc) {
3525 0           my $ope = $1;
3526              
3527             # $1 $2 $3 $4 $5 $6
3528 0 0         if (/\G (\#) ((?:$qq_char)*?) (\#) ((?:$qq_char)*?) (\#) ([cdsrbB]*) /oxgc) { # tr# # #
3529 0           my @tr = ($tr_variable,$2);
3530 0           return e_tr(@tr,'',$4,$6);
3531             }
3532             else {
3533 0           my $e = '';
3534 0           while (not /\G \z/oxgc) {
3535 0 0         if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3536             elsif (/\G (\() ((?:$qq_paren)*?) (\)) /oxgc) {
3537 0           my @tr = ($tr_variable,$2);
3538 0           while (not /\G \z/oxgc) {
3539 0 0         if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3540 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr ( ) ( )
3541 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr ( ) { }
3542 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr ( ) [ ]
3543 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr ( ) < >
3544 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr ( ) * *
3545             }
3546 0           die __FILE__, ": Transliteration replacement not terminated\n";
3547             }
3548             elsif (/\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) {
3549 0           my @tr = ($tr_variable,$2);
3550 0           while (not /\G \z/oxgc) {
3551 0 0         if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3552 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr { } ( )
3553 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr { } { }
3554 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr { } [ ]
3555 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr { } < >
3556 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr { } * *
3557             }
3558 0           die __FILE__, ": Transliteration replacement not terminated\n";
3559             }
3560             elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) {
3561 0           my @tr = ($tr_variable,$2);
3562 0           while (not /\G \z/oxgc) {
3563 0 0         if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3564 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr [ ] ( )
3565 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr [ ] { }
3566 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr [ ] [ ]
3567 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr [ ] < >
3568 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr [ ] * *
3569             }
3570 0           die __FILE__, ": Transliteration replacement not terminated\n";
3571             }
3572             elsif (/\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) {
3573 0           my @tr = ($tr_variable,$2);
3574 0           while (not /\G \z/oxgc) {
3575 0 0         if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3576 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr < > ( )
3577 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr < > { }
3578 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr < > [ ]
3579 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr < > < >
3580 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr < > * *
3581             }
3582 0           die __FILE__, ": Transliteration replacement not terminated\n";
3583             }
3584             # $1 $2 $3 $4 $5 $6
3585             elsif (/\G (\S) ((?:$qq_char)*?) (\1) ((?:$qq_char)*?) (\1) ([cdsrbB]*) /oxgc) { # tr * * *
3586 0           my @tr = ($tr_variable,$2);
3587 0           return e_tr(@tr,'',$4,$6);
3588             }
3589             }
3590 0           die __FILE__, ": Transliteration pattern not terminated\n";
3591             }
3592             }
3593              
3594             # qq//
3595             elsif (/\G \b (qq) \b /oxgc) {
3596 0           my $ope = $1;
3597              
3598             # if (/\G (\#) ((?:$qq_char)*?) (\#) /oxgc) { return e_qq($ope,$1,$3,$2); } # qq# #
3599 0 0         if (/\G (\#) /oxgc) { # qq# #
3600 0           my $qq_string = '';
3601 0           while (not /\G \z/oxgc) {
3602 0 0         if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0          
    0          
    0          
3603 0           elsif (/\G (\\\#) /oxgc) { $qq_string .= $1; }
3604 0           elsif (/\G (\#) /oxgc) { return e_qq($ope,'#','#',$qq_string); }
3605 0           elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3606             }
3607 0           die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3608             }
3609              
3610             else {
3611 0           my $e = '';
3612 0           while (not /\G \z/oxgc) {
3613 0 0         if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3614              
3615             # elsif (/\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qq ( )
3616             elsif (/\G (\() /oxgc) { # qq ( )
3617 0           my $qq_string = '';
3618 0           local $nest = 1;
3619 0           while (not /\G \z/oxgc) {
3620 0 0         if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0          
    0          
    0          
    0          
3621 0           elsif (/\G (\\\)) /oxgc) { $qq_string .= $1; }
3622 0           elsif (/\G (\() /oxgc) { $qq_string .= $1; $nest++; }
  0            
3623             elsif (/\G (\)) /oxgc) {
3624 0 0         if (--$nest == 0) { return $e . e_qq($ope,'(',')',$qq_string); }
  0            
3625 0           else { $qq_string .= $1; }
3626             }
3627 0           elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3628             }
3629 0           die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3630             }
3631              
3632             # elsif (/\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qq { }
3633             elsif (/\G (\{) /oxgc) { # qq { }
3634 0           my $qq_string = '';
3635 0           local $nest = 1;
3636 0           while (not /\G \z/oxgc) {
3637 0 0         if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0          
    0          
    0          
    0          
3638 0           elsif (/\G (\\\}) /oxgc) { $qq_string .= $1; }
3639 0           elsif (/\G (\{) /oxgc) { $qq_string .= $1; $nest++; }
  0            
3640             elsif (/\G (\}) /oxgc) {
3641 0 0         if (--$nest == 0) { return $e . e_qq($ope,'{','}',$qq_string); }
  0            
3642 0           else { $qq_string .= $1; }
3643             }
3644 0           elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3645             }
3646 0           die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3647             }
3648              
3649             # elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qq [ ]
3650             elsif (/\G (\[) /oxgc) { # qq [ ]
3651 0           my $qq_string = '';
3652 0           local $nest = 1;
3653 0           while (not /\G \z/oxgc) {
3654 0 0         if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0          
    0          
    0          
    0          
3655 0           elsif (/\G (\\\]) /oxgc) { $qq_string .= $1; }
3656 0           elsif (/\G (\[) /oxgc) { $qq_string .= $1; $nest++; }
  0            
3657             elsif (/\G (\]) /oxgc) {
3658 0 0         if (--$nest == 0) { return $e . e_qq($ope,'[',']',$qq_string); }
  0            
3659 0           else { $qq_string .= $1; }
3660             }
3661 0           elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3662             }
3663 0           die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3664             }
3665              
3666             # elsif (/\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qq < >
3667             elsif (/\G (\<) /oxgc) { # qq < >
3668 0           my $qq_string = '';
3669 0           local $nest = 1;
3670 0           while (not /\G \z/oxgc) {
3671 0 0         if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0          
    0          
    0          
    0          
3672 0           elsif (/\G (\\\>) /oxgc) { $qq_string .= $1; }
3673 0           elsif (/\G (\<) /oxgc) { $qq_string .= $1; $nest++; }
  0            
3674             elsif (/\G (\>) /oxgc) {
3675 0 0         if (--$nest == 0) { return $e . e_qq($ope,'<','>',$qq_string); }
  0            
3676 0           else { $qq_string .= $1; }
3677             }
3678 0           elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3679             }
3680 0           die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3681             }
3682              
3683             # elsif (/\G (\S) ((?:$qq_char)*?) (\1) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qq * *
3684             elsif (/\G (\S) /oxgc) { # qq * *
3685 0           my $delimiter = $1;
3686 0           my $qq_string = '';
3687 0           while (not /\G \z/oxgc) {
3688 0 0         if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0          
    0          
    0          
3689 0           elsif (/\G (\\\Q$delimiter\E) /oxgc) { $qq_string .= $1; }
3690 0           elsif (/\G (\Q$delimiter\E) /oxgc) { return $e . e_qq($ope,$delimiter,$delimiter,$qq_string); }
3691 0           elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3692             }
3693 0           die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3694             }
3695             }
3696 0           die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3697             }
3698             }
3699              
3700             # qr//
3701             elsif (/\G \b (qr) \b /oxgc) {
3702 0           my $ope = $1;
3703 0 0         if (/\G (\#) ((?:$qq_char)*?) (\#) ([imosxpadlunbB]*) /oxgc) { # qr# # #
3704 0           return e_qr($ope,$1,$3,$2,$4);
3705             }
3706             else {
3707 0           my $e = '';
3708 0           while (not /\G \z/oxgc) {
3709 0 0         if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
3710 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([imosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # qr ( )
3711 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([imosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # qr { }
3712 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([imosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # qr [ ]
3713 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([imosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # qr < >
3714 0           elsif (/\G (\') ((?:$qq_char)*?) (\') ([imosxpadlunbB]*) /oxgc) { return $e . e_qr_q($ope,$1, $3, $2,$4); } # qr ' '
3715 0           elsif (/\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ([imosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,'{','}',$2,$4); } # qr | | --> qr { }
3716 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([imosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # qr * *
3717             }
3718 0           die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3719             }
3720             }
3721              
3722             # qw//
3723             elsif (/\G \b (qw) \b /oxgc) {
3724 0           my $ope = $1;
3725 0 0         if (/\G (\#) (.*?) (\#) /oxmsgc) { # qw# #
3726 0           return e_qw($ope,$1,$3,$2);
3727             }
3728             else {
3729 0           my $e = '';
3730 0           while (not /\G \z/oxgc) {
3731 0 0         if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
3732              
3733 0           elsif (/\G (\() ([^(]*?) (\)) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw ( )
3734 0           elsif (/\G (\() ((?:$q_paren)*?) (\)) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw ( )
3735              
3736 0           elsif (/\G (\{) ([^{]*?) (\}) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw { }
3737 0           elsif (/\G (\{) ((?:$q_brace)*?) (\}) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw { }
3738              
3739 0           elsif (/\G (\[) ([^[]*?) (\]) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw [ ]
3740 0           elsif (/\G (\[) ((?:$q_bracket)*?) (\]) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw [ ]
3741              
3742 0           elsif (/\G (\<) ([^<]*?) (\>) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw < >
3743 0           elsif (/\G (\<) ((?:$q_angle)*?) (\>) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw < >
3744              
3745 0           elsif (/\G ([\x21-\x3F]) (.*?) (\1) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw * *
3746 0           elsif (/\G (\S) ((?:$q_char)*?) (\1) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw * *
3747             }
3748 0           die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3749             }
3750             }
3751              
3752             # qx//
3753             elsif (/\G \b (qx) \b /oxgc) {
3754 0           my $ope = $1;
3755 0 0         if (/\G (\#) ((?:$qq_char)*?) (\#) /oxgc) { # qx# #
3756 0           return e_qq($ope,$1,$3,$2);
3757             }
3758             else {
3759 0           my $e = '';
3760 0           while (not /\G \z/oxgc) {
3761 0 0         if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
3762 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qx ( )
3763 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qx { }
3764 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qx [ ]
3765 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qx < >
3766 0           elsif (/\G (\') ((?:$qq_char)*?) (\') /oxgc) { return $e . e_q ($ope,$1,$3,$2); } # qx ' '
3767 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qx * *
3768             }
3769 0           die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3770             }
3771             }
3772              
3773             # q//
3774             elsif (/\G \b (q) \b /oxgc) {
3775 0           my $ope = $1;
3776              
3777             # if (/\G (\#) ((?:\\\#|\\\\|$q_char)*?) (\#) /oxgc) { return e_q($ope,$1,$3,$2); } # q# #
3778              
3779             # avoid "Error: Runtime exception" of perl version 5.005_03
3780             # (and so on)
3781              
3782 0 0         if (/\G (\#) /oxgc) { # q# #
3783 0           my $q_string = '';
3784 0           while (not /\G \z/oxgc) {
3785 0 0         if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0          
    0          
    0          
3786 0           elsif (/\G (\\\#) /oxgc) { $q_string .= $1; }
3787 0           elsif (/\G (\#) /oxgc) { return e_q($ope,'#','#',$q_string); }
3788 0           elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3789             }
3790 0           die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3791             }
3792              
3793             else {
3794 0           my $e = '';
3795 0           while (not /\G \z/oxgc) {
3796 0 0         if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3797              
3798             # elsif (/\G (\() ((?:\\\)|\\\\|$q_paren)*?) (\)) /oxgc) { return $e . e_q($ope,$1,$3,$2); } # q ( )
3799             elsif (/\G (\() /oxgc) { # q ( )
3800 0           my $q_string = '';
3801 0           local $nest = 1;
3802 0           while (not /\G \z/oxgc) {
3803 0 0         if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3804 0           elsif (/\G (\\\)) /oxgc) { $q_string .= $1; }
3805 0           elsif (/\G (\\\() /oxgc) { $q_string .= $1; }
3806 0           elsif (/\G (\() /oxgc) { $q_string .= $1; $nest++; }
  0            
3807             elsif (/\G (\)) /oxgc) {
3808 0 0         if (--$nest == 0) { return $e . e_q($ope,'(',')',$q_string); }
  0            
3809 0           else { $q_string .= $1; }
3810             }
3811 0           elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3812             }
3813 0           die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3814             }
3815              
3816             # elsif (/\G (\{) ((?:\\\}|\\\\|$q_brace)*?) (\}) /oxgc) { return $e . e_q($ope,$1,$3,$2); } # q { }
3817             elsif (/\G (\{) /oxgc) { # q { }
3818 0           my $q_string = '';
3819 0           local $nest = 1;
3820 0           while (not /\G \z/oxgc) {
3821 0 0         if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3822 0           elsif (/\G (\\\}) /oxgc) { $q_string .= $1; }
3823 0           elsif (/\G (\\\{) /oxgc) { $q_string .= $1; }
3824 0           elsif (/\G (\{) /oxgc) { $q_string .= $1; $nest++; }
  0            
3825             elsif (/\G (\}) /oxgc) {
3826 0 0         if (--$nest == 0) { return $e . e_q($ope,'{','}',$q_string); }
  0            
3827 0           else { $q_string .= $1; }
3828             }
3829 0           elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3830             }
3831 0           die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3832             }
3833              
3834             # elsif (/\G (\[) ((?:\\\]|\\\\|$q_bracket)*?) (\]) /oxgc) { return $e . e_q($ope,$1,$3,$2); } # q [ ]
3835             elsif (/\G (\[) /oxgc) { # q [ ]
3836 0           my $q_string = '';
3837 0           local $nest = 1;
3838 0           while (not /\G \z/oxgc) {
3839 0 0         if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3840 0           elsif (/\G (\\\]) /oxgc) { $q_string .= $1; }
3841 0           elsif (/\G (\\\[) /oxgc) { $q_string .= $1; }
3842 0           elsif (/\G (\[) /oxgc) { $q_string .= $1; $nest++; }
  0            
3843             elsif (/\G (\]) /oxgc) {
3844 0 0         if (--$nest == 0) { return $e . e_q($ope,'[',']',$q_string); }
  0            
3845 0           else { $q_string .= $1; }
3846             }
3847 0           elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3848             }
3849 0           die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3850             }
3851              
3852             # elsif (/\G (\<) ((?:\\\>|\\\\|$q_angle)*?) (\>) /oxgc) { return $e . e_q($ope,$1,$3,$2); } # q < >
3853             elsif (/\G (\<) /oxgc) { # q < >
3854 0           my $q_string = '';
3855 0           local $nest = 1;
3856 0           while (not /\G \z/oxgc) {
3857 0 0         if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3858 0           elsif (/\G (\\\>) /oxgc) { $q_string .= $1; }
3859 0           elsif (/\G (\\\<) /oxgc) { $q_string .= $1; }
3860 0           elsif (/\G (\<) /oxgc) { $q_string .= $1; $nest++; }
  0            
3861             elsif (/\G (\>) /oxgc) {
3862 0 0         if (--$nest == 0) { return $e . e_q($ope,'<','>',$q_string); }
  0            
3863 0           else { $q_string .= $1; }
3864             }
3865 0           elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3866             }
3867 0           die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3868             }
3869              
3870             # elsif (/\G (\S) ((?:\\\1|\\\\|$q_char)*?) (\1) /oxgc) { return $e . e_q($ope,$1,$3,$2); } # q * *
3871             elsif (/\G (\S) /oxgc) { # q * *
3872 0           my $delimiter = $1;
3873 0           my $q_string = '';
3874 0           while (not /\G \z/oxgc) {
3875 0 0         if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0          
    0          
    0          
3876 0           elsif (/\G (\\\Q$delimiter\E) /oxgc) { $q_string .= $1; }
3877 0           elsif (/\G (\Q$delimiter\E) /oxgc) { return $e . e_q($ope,$delimiter,$delimiter,$q_string); }
3878 0           elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3879             }
3880 0           die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3881             }
3882             }
3883 0           die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3884             }
3885             }
3886              
3887             # m//
3888             elsif (/\G \b (m) \b /oxgc) {
3889 0           my $ope = $1;
3890 0 0         if (/\G (\#) ((?:$qq_char)*?) (\#) ([cgimosxpadlunbB]*) /oxgc) { # m# #
3891 0           return e_qr($ope,$1,$3,$2,$4);
3892             }
3893             else {
3894 0           my $e = '';
3895 0           while (not /\G \z/oxgc) {
3896 0 0         if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
3897 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cgimosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m ( )
3898 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cgimosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m { }
3899 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cgimosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m [ ]
3900 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cgimosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m < >
3901 0           elsif (/\G (\?) ((?:$qq_char)*?) (\?) ([cgimosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m ? ?
3902 0           elsif (/\G (\') ((?:$qq_char)*?) (\') ([cgimosxpadlunbB]*) /oxgc) { return $e . e_qr_q($ope,$1, $3, $2,$4); } # m ' '
3903 0           elsif (/\G ([*\-:\\^|]) ((?:$qq_char)*?) (\1) ([cgimosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,'{','}',$2,$4); } # m | | --> m { }
3904 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cgimosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m * *
3905             }
3906 0           die __FILE__, ": Search pattern not terminated\n";
3907             }
3908             }
3909              
3910             # s///
3911              
3912             # about [cegimosxpradlunbB]* (/cg modifier)
3913             #
3914             # P.67 Pattern-Matching Operators
3915             # of ISBN 0-596-00241-6 Perl in a Nutshell, Second Edition.
3916              
3917             elsif (/\G \b (s) \b /oxgc) {
3918 0           my $ope = $1;
3919              
3920             # $1 $2 $3 $4 $5 $6
3921 0 0         if (/\G (\#) ((?:$qq_char)*?) (\#) ((?:$qq_char)*?) (\#) ([cegimosxpradlunbB]*) /oxgc) { # s# # #
3922 0           return e_sub($sub_variable,$1,$2,$3,$3,$4,$5,$6);
3923             }
3924             else {
3925 0           my $e = '';
3926 0           while (not /\G \z/oxgc) {
3927 0 0         if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
3928             elsif (/\G (\() ((?:$qq_paren)*?) (\)) /oxgc) {
3929 0           my @s = ($1,$2,$3);
3930 0           while (not /\G \z/oxgc) {
3931 0 0         if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
3932             # $1 $2 $3 $4
3933 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3934 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3935 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3936 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3937 0           elsif (/\G (\') ((?:$qq_char)*?) (\') ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3938 0           elsif (/\G (\$) ((?:$qq_char)*?) (\$) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3939 0           elsif (/\G (\:) ((?:$qq_char)*?) (\:) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3940 0           elsif (/\G (\@) ((?:$qq_char)*?) (\@) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3941 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3942             }
3943 0           die __FILE__, ": Substitution replacement not terminated\n";
3944             }
3945             elsif (/\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) {
3946 0           my @s = ($1,$2,$3);
3947 0           while (not /\G \z/oxgc) {
3948 0 0         if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
3949             # $1 $2 $3 $4
3950 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3951 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3952 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3953 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3954 0           elsif (/\G (\') ((?:$qq_char)*?) (\') ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3955 0           elsif (/\G (\$) ((?:$qq_char)*?) (\$) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3956 0           elsif (/\G (\:) ((?:$qq_char)*?) (\:) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3957 0           elsif (/\G (\@) ((?:$qq_char)*?) (\@) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3958 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3959             }
3960 0           die __FILE__, ": Substitution replacement not terminated\n";
3961             }
3962             elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) {
3963 0           my @s = ($1,$2,$3);
3964 0           while (not /\G \z/oxgc) {
3965 0 0         if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
3966             # $1 $2 $3 $4
3967 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3968 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3969 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3970 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3971 0           elsif (/\G (\') ((?:$qq_char)*?) (\') ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3972 0           elsif (/\G (\$) ((?:$qq_char)*?) (\$) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3973 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3974             }
3975 0           die __FILE__, ": Substitution replacement not terminated\n";
3976             }
3977             elsif (/\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) {
3978 0           my @s = ($1,$2,$3);
3979 0           while (not /\G \z/oxgc) {
3980 0 0         if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
3981             # $1 $2 $3 $4
3982 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3983 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3984 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3985 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3986 0           elsif (/\G (\') ((?:$qq_char)*?) (\') ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3987 0           elsif (/\G (\$) ((?:$qq_char)*?) (\$) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3988 0           elsif (/\G (\:) ((?:$qq_char)*?) (\:) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3989 0           elsif (/\G (\@) ((?:$qq_char)*?) (\@) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3990 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3991             }
3992 0           die __FILE__, ": Substitution replacement not terminated\n";
3993             }
3994             # $1 $2 $3 $4 $5 $6
3995             elsif (/\G (\') ((?:$qq_char)*?) (\') ((?:$qq_char)*?) (\') ([cegimosxpradlunbB]*) /oxgc) {
3996 0           return e_sub($sub_variable,$1,$2,$3,$3,$4,$5,$6);
3997             }
3998             # $1 $2 $3 $4 $5 $6
3999             elsif (/\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ((?:$qq_char)*?) (\1) ([cegimosxpradlunbB]*) /oxgc) {
4000 0           return e_sub($sub_variable,'{',$2,'}','{',$4,'}',$6); # s | | | --> s { } { }
4001             }
4002             # $1 $2 $3 $4 $5 $6
4003             elsif (/\G (\$) ((?:$qq_char)*?) (\1) ((?:$qq_char)*?) (\1) ([cegimosxpradlunbB]*) /oxgc) {
4004 0           return e_sub($sub_variable,$1,$2,$3,$3,$4,$5,$6);
4005             }
4006             # $1 $2 $3 $4 $5 $6
4007             elsif (/\G (\S) ((?:$qq_char)*?) (\1) ((?:$qq_char)*?) (\1) ([cegimosxpradlunbB]*) /oxgc) {
4008 0           return e_sub($sub_variable,$1,$2,$3,$3,$4,$5,$6);
4009             }
4010             }
4011 0           die __FILE__, ": Substitution pattern not terminated\n";
4012             }
4013             }
4014              
4015             # require ignore module
4016 0           elsif (/\G \b require ((?>\s+) (?:$ignore_modules) .*? ;) ([ \t]* [#\n]) /oxmsgc) { return "# require$1$2"; }
4017 0           elsif (/\G \b require ((?>\s+) (?:$ignore_modules) .*? ;) ([ \t]* [^#]) /oxmsgc) { return "# require$1\n$2"; }
4018 0           elsif (/\G \b require ((?>\s+) (?:$ignore_modules)) \b /oxmsgc) { return "# require$1"; }
4019              
4020             # use strict; --> use strict; no strict qw(refs);
4021 0           elsif (/\G \b use ((?>\s+) strict .*? ;) ([ \t]* [#\n]) /oxmsgc) { return "use$1 no strict qw(refs);$2"; }
4022 0           elsif (/\G \b use ((?>\s+) strict .*? ;) ([ \t]* [^#]) /oxmsgc) { return "use$1 no strict qw(refs);\n$2"; }
4023 0           elsif (/\G \b use ((?>\s+) strict) \b /oxmsgc) { return "use$1; no strict qw(refs)"; }
4024              
4025             # use 5.12.0; --> use 5.12.0; no strict qw(refs);
4026             elsif (/\G \b use (?>\s+) ((?>([1-9][0-9_]*)(?:\.([0-9_]+))*)) (?>\s*) ; /oxmsgc) {
4027 0 0 0       if (($2 >= 6) or (($2 == 5) and ($3 ge '012'))) {
      0        
4028 0           return "use $1; no strict qw(refs);";
4029             }
4030             else {
4031 0           return "use $1;";
4032             }
4033             }
4034             elsif (/\G \b use (?>\s+) ((?>v([0-9][0-9_]*)(?:\.([0-9_]+))*)) (?>\s*) ; /oxmsgc) {
4035 0 0 0       if (($2 >= 6) or (($2 == 5) and ($3 >= 12))) {
      0        
4036 0           return "use $1; no strict qw(refs);";
4037             }
4038             else {
4039 0           return "use $1;";
4040             }
4041             }
4042              
4043             # ignore use module
4044 0           elsif (/\G \b use ((?>\s+) (?:$ignore_modules) .*? ;) ([ \t]* [#\n]) /oxmsgc) { return "# use$1$2"; }
4045 0           elsif (/\G \b use ((?>\s+) (?:$ignore_modules) .*? ;) ([ \t]* [^#]) /oxmsgc) { return "# use$1\n$2"; }
4046 0           elsif (/\G \b use ((?>\s+) (?:$ignore_modules)) \b /oxmsgc) { return "# use$1"; }
4047              
4048             # ignore no module
4049 0           elsif (/\G \b no ((?>\s+) (?:$ignore_modules) .*? ;) ([ \t]* [#\n]) /oxmsgc) { return "# no$1$2"; }
4050 0           elsif (/\G \b no ((?>\s+) (?:$ignore_modules) .*? ;) ([ \t]* [^#]) /oxmsgc) { return "# no$1\n$2"; }
4051 0           elsif (/\G \b no ((?>\s+) (?:$ignore_modules)) \b /oxmsgc) { return "# no$1"; }
4052              
4053             # use else
4054 0           elsif (/\G \b use \b /oxmsgc) { return "use"; }
4055              
4056             # use else
4057 0           elsif (/\G \b no \b /oxmsgc) { return "no"; }
4058              
4059             # ''
4060             elsif (/\G (?
4061 0           my $q_string = '';
4062 0           while (not /\G \z/oxgc) {
4063 0 0         if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0          
    0          
    0          
4064 0           elsif (/\G (\\\') /oxgc) { $q_string .= $1; }
4065 0           elsif (/\G \' /oxgc) { return e_q('', "'","'",$q_string); }
4066 0           elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
4067             }
4068 0           die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4069             }
4070              
4071             # ""
4072             elsif (/\G (\") /oxgc) {
4073 0           my $qq_string = '';
4074 0           while (not /\G \z/oxgc) {
4075 0 0         if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0          
    0          
    0          
4076 0           elsif (/\G (\\\") /oxgc) { $qq_string .= $1; }
4077 0           elsif (/\G \" /oxgc) { return e_qq('', '"','"',$qq_string); }
4078 0           elsif (/\G ($q_char) /oxgc) { $qq_string .= $1; }
4079             }
4080 0           die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4081             }
4082              
4083             # ``
4084             elsif (/\G (\`) /oxgc) {
4085 0           my $qx_string = '';
4086 0           while (not /\G \z/oxgc) {
4087 0 0         if (/\G (\\\\) /oxgc) { $qx_string .= $1; }
  0 0          
    0          
    0          
4088 0           elsif (/\G (\\\`) /oxgc) { $qx_string .= $1; }
4089 0           elsif (/\G \` /oxgc) { return e_qq('', '`','`',$qx_string); }
4090 0           elsif (/\G ($q_char) /oxgc) { $qx_string .= $1; }
4091             }
4092 0           die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4093             }
4094              
4095             # // --- not divide operator (num / num), not defined-or
4096             elsif (($slash eq 'm//') and /\G (\/) /oxgc) {
4097 0           my $regexp = '';
4098 0           while (not /\G \z/oxgc) {
4099 0 0         if (/\G (\\\\) /oxgc) { $regexp .= $1; }
  0 0          
    0          
    0          
4100 0           elsif (/\G (\\\/) /oxgc) { $regexp .= $1; }
4101 0           elsif (/\G \/ ([cgimosxpadlunbB]*) /oxgc) { return e_qr('', '/','/',$regexp,$1); }
4102 0           elsif (/\G ($q_char) /oxgc) { $regexp .= $1; }
4103             }
4104 0           die __FILE__, ": Search pattern not terminated\n";
4105             }
4106              
4107             # ?? --- not conditional operator (condition ? then : else)
4108             elsif (($slash eq 'm//') and /\G (\?) /oxgc) {
4109 0           my $regexp = '';
4110 0           while (not /\G \z/oxgc) {
4111 0 0         if (/\G (\\\\) /oxgc) { $regexp .= $1; }
  0 0          
    0          
    0          
4112 0           elsif (/\G (\\\?) /oxgc) { $regexp .= $1; }
4113 0           elsif (/\G \? ([cgimosxpadlunbB]*) /oxgc) { return e_qr('m','?','?',$regexp,$1); }
4114 0           elsif (/\G ($q_char) /oxgc) { $regexp .= $1; }
4115             }
4116 0           die __FILE__, ": Search pattern not terminated\n";
4117             }
4118              
4119             # <<>> (a safer ARGV)
4120 0           elsif (/\G ( <<>> ) /oxgc) { $slash = 'm//'; return $1; }
  0            
4121              
4122             # << (bit shift) --- not here document
4123 0           elsif (/\G ( << (?>\s*) ) (?= [0-9\$\@\&] ) /oxgc) { $slash = 'm//'; return $1; }
  0            
4124              
4125             # <<'HEREDOC'
4126             elsif (/\G ( << '([a-zA-Z_0-9]*)' ) /oxgc) {
4127 0           $slash = 'm//';
4128 0           my $here_quote = $1;
4129 0           my $delimiter = $2;
4130              
4131             # get here document
4132 0 0         if ($here_script eq '') {
4133 0           $here_script = CORE::substr $_, pos $_;
4134 0           $here_script =~ s/.*?\n//oxm;
4135             }
4136 0 0         if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4137 0           push @heredoc, $1 . qq{\n$delimiter\n};
4138 0           push @heredoc_delimiter, $delimiter;
4139             }
4140             else {
4141 0           die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4142             }
4143 0           return $here_quote;
4144             }
4145              
4146             # <<\HEREDOC
4147              
4148             # P.66 2.6.6. "Here" Documents
4149             # in Chapter 2: Bits and Pieces
4150             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
4151              
4152             # P.73 "Here" Documents
4153             # in Chapter 2: Bits and Pieces
4154             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
4155              
4156             elsif (/\G ( << \\([a-zA-Z_0-9]+) ) /oxgc) {
4157 0           $slash = 'm//';
4158 0           my $here_quote = $1;
4159 0           my $delimiter = $2;
4160              
4161             # get here document
4162 0 0         if ($here_script eq '') {
4163 0           $here_script = CORE::substr $_, pos $_;
4164 0           $here_script =~ s/.*?\n//oxm;
4165             }
4166 0 0         if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4167 0           push @heredoc, $1 . qq{\n$delimiter\n};
4168 0           push @heredoc_delimiter, $delimiter;
4169             }
4170             else {
4171 0           die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4172             }
4173 0           return $here_quote;
4174             }
4175              
4176             # <<"HEREDOC"
4177             elsif (/\G ( << "([a-zA-Z_0-9]*)" ) /oxgc) {
4178 0           $slash = 'm//';
4179 0           my $here_quote = $1;
4180 0           my $delimiter = $2;
4181              
4182             # get here document
4183 0 0         if ($here_script eq '') {
4184 0           $here_script = CORE::substr $_, pos $_;
4185 0           $here_script =~ s/.*?\n//oxm;
4186             }
4187 0 0         if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4188 0           push @heredoc, e_heredoc($1) . qq{\n$delimiter\n};
4189 0           push @heredoc_delimiter, $delimiter;
4190             }
4191             else {
4192 0           die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4193             }
4194 0           return $here_quote;
4195             }
4196              
4197             # <
4198             elsif (/\G ( << ([a-zA-Z_0-9]+) ) /oxgc) {
4199 0           $slash = 'm//';
4200 0           my $here_quote = $1;
4201 0           my $delimiter = $2;
4202              
4203             # get here document
4204 0 0         if ($here_script eq '') {
4205 0           $here_script = CORE::substr $_, pos $_;
4206 0           $here_script =~ s/.*?\n//oxm;
4207             }
4208 0 0         if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4209 0           push @heredoc, e_heredoc($1) . qq{\n$delimiter\n};
4210 0           push @heredoc_delimiter, $delimiter;
4211             }
4212             else {
4213 0           die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4214             }
4215 0           return $here_quote;
4216             }
4217              
4218             # <<`HEREDOC`
4219             elsif (/\G ( << `([a-zA-Z_0-9]*)` ) /oxgc) {
4220 0           $slash = 'm//';
4221 0           my $here_quote = $1;
4222 0           my $delimiter = $2;
4223              
4224             # get here document
4225 0 0         if ($here_script eq '') {
4226 0           $here_script = CORE::substr $_, pos $_;
4227 0           $here_script =~ s/.*?\n//oxm;
4228             }
4229 0 0         if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4230 0           push @heredoc, e_heredoc($1) . qq{\n$delimiter\n};
4231 0           push @heredoc_delimiter, $delimiter;
4232             }
4233             else {
4234 0           die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4235             }
4236 0           return $here_quote;
4237             }
4238              
4239             # <<= <=> <= < operator
4240             elsif (/\G ( <<= | <=> | <= | < ) (?= (?>\s*) [A-Za-z_0-9'"`\$\@\&\*\(\+\-] )/oxgc) {
4241 0           return $1;
4242             }
4243              
4244             #
4245             elsif (/\G (<[\$]?[A-Za-z_][A-Za-z_0-9]*>) /oxgc) {
4246 0           return $1;
4247             }
4248              
4249             # --- glob
4250              
4251             # avoid "Error: Runtime exception" of perl version 5.005_03
4252              
4253             elsif (/\G < ((?:[^>\0\a\e\f\n\r\t])+?) > /oxgc) {
4254 0           return 'Ekoi8u::glob("' . $1 . '")';
4255             }
4256              
4257             # __DATA__
4258 0           elsif (/\G ^ ( __DATA__ \n .*) \z /oxmsgc) { return $1; }
4259              
4260             # __END__
4261 0           elsif (/\G ^ ( __END__ \n .*) \z /oxmsgc) { return $1; }
4262              
4263             # \cD Control-D
4264              
4265             # P.68 2.6.8. Other Literal Tokens
4266             # in Chapter 2: Bits and Pieces
4267             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
4268              
4269             # P.76 Other Literal Tokens
4270             # in Chapter 2: Bits and Pieces
4271             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
4272              
4273 0           elsif (/\G ( \cD .*) \z /oxmsgc) { return $1; }
4274              
4275             # \cZ Control-Z
4276 0           elsif (/\G ( \cZ .*) \z /oxmsgc) { return $1; }
4277              
4278             # any operator before div
4279             elsif (/\G (
4280             -- | \+\+ |
4281             [\)\}\]]
4282              
4283 0           ) /oxgc) { $slash = 'div'; return $1; }
  0            
4284              
4285             # yada-yada or triple-dot operator
4286             elsif (/\G (
4287             \.\.\.
4288              
4289 0           ) /oxgc) { $slash = 'm//'; return q{die('Unimplemented')}; }
  0            
4290              
4291             # any operator before m//
4292              
4293             # //, //= (defined-or)
4294              
4295             # P.164 Logical Operators
4296             # in Chapter 10: More Control Structures
4297             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
4298              
4299             # P.119 C-Style Logical (Short-Circuit) Operators
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             # ~~
4306              
4307             # P.221 The Smart Match Operator
4308             # in Chapter 15: Smart Matching and given-when
4309             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
4310              
4311             # P.112 Smartmatch Operator
4312             # in Chapter 3: Unary and Binary Operators
4313             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
4314              
4315             # (and so on)
4316              
4317             elsif (/\G ((?>
4318              
4319             !~~ | !~ | != | ! |
4320             %= | % |
4321             &&= | && | &= | &\.= | &\. | & |
4322             -= | -> | - |
4323             :(?>\s*)= |
4324             : |
4325             <<>> |
4326             <<= | <=> | <= | < |
4327             == | => | =~ | = |
4328             >>= | >> | >= | > |
4329             \*\*= | \*\* | \*= | \* |
4330             \+= | \+ |
4331             \.\. | \.= | \. |
4332             \/\/= | \/\/ |
4333             \/= | \/ |
4334             \? |
4335             \\ |
4336             \^= | \^\.= | \^\. | \^ |
4337             \b x= |
4338             \|\|= | \|\| | \|= | \|\.= | \|\. | \| |
4339             ~~ | ~\. | ~ |
4340             \b(?: and | cmp | eq | ge | gt | le | lt | ne | not | or | xor | x )\b |
4341             \b(?: print )\b |
4342              
4343             [,;\(\{\[]
4344              
4345 0           )) /oxgc) { $slash = 'm//'; return $1; }
  0            
4346              
4347             # other any character
4348 0           elsif (/\G ($q_char) /oxgc) { $slash = 'div'; return $1; }
  0            
4349              
4350             # system error
4351             else {
4352 0           die __FILE__, ": Oops, this shouldn't happen!\n";
4353             }
4354             }
4355              
4356             # escape KOI8-U string
4357             sub e_string {
4358 0     0 0   my($string) = @_;
4359 0           my $e_string = '';
4360              
4361 0           local $slash = 'm//';
4362              
4363             # P.1024 Appendix W.10 Multibyte Processing
4364             # of ISBN 1-56592-224-7 CJKV Information Processing
4365             # (and so on)
4366              
4367 0           my @char = $string =~ / \G (?>[^\\]|\\$q_char|$q_char) /oxmsg;
4368              
4369             # without { ... }
4370 0 0 0       if (not (grep(/\A \{ \z/xms, @char) and grep(/\A \} \z/xms, @char))) {
4371 0 0         if ($string !~ /<
4372 0           return $string;
4373             }
4374             }
4375              
4376             E_STRING_LOOP:
4377 0           while ($string !~ /\G \z/oxgc) {
4378 0 0         if (0) {
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
4379             }
4380              
4381             # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> @{[Ekoi8u::PREMATCH()]}
4382 0           elsif ($string =~ /\G ( \$` | \$\{`\} | \$ (?>\s*) PREMATCH \b | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} ) /oxmsgc) {
4383 0           $e_string .= q{Ekoi8u::PREMATCH()};
4384 0           $slash = 'div';
4385             }
4386              
4387             # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> @{[Ekoi8u::MATCH()]}
4388             elsif ($string =~ /\G ( \$& | \$\{&\} | \$ (?>\s*) MATCH \b | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} ) /oxmsgc) {
4389 0           $e_string .= q{Ekoi8u::MATCH()};
4390 0           $slash = 'div';
4391             }
4392              
4393             # $', ${'} --> $', ${'}
4394             elsif ($string =~ /\G ( \$' | \$\{'\} ) /oxmsgc) {
4395 0           $e_string .= $1;
4396 0           $slash = 'div';
4397             }
4398              
4399             # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> @{[Ekoi8u::POSTMATCH()]}
4400             elsif ($string =~ /\G ( \$ (?>\s*) POSTMATCH \b | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} ) /oxmsgc) {
4401 0           $e_string .= q{Ekoi8u::POSTMATCH()};
4402 0           $slash = 'div';
4403             }
4404              
4405             # bareword
4406             elsif ($string =~ /\G ( \{ (?>\s*) (?: tr | index | rindex | reverse ) (?>\s*) \} ) /oxmsgc) {
4407 0           $e_string .= $1;
4408 0           $slash = 'div';
4409             }
4410              
4411             # $0 --> $0
4412             elsif ($string =~ /\G ( \$ 0 ) /oxmsgc) {
4413 0           $e_string .= $1;
4414 0           $slash = 'div';
4415             }
4416             elsif ($string =~ /\G ( \$ \{ (?>\s*) 0 (?>\s*) \} ) /oxmsgc) {
4417 0           $e_string .= $1;
4418 0           $slash = 'div';
4419             }
4420              
4421             # $$ --> $$
4422             elsif ($string =~ /\G ( \$ \$ ) (?![\w\{]) /oxmsgc) {
4423 0           $e_string .= $1;
4424 0           $slash = 'div';
4425             }
4426              
4427             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
4428             # $1, $2, $3 --> $1, $2, $3 otherwise
4429             elsif ($string =~ /\G \$ ((?>[1-9][0-9]*)) /oxmsgc) {
4430 0           $e_string .= e_capture($1);
4431 0           $slash = 'div';
4432             }
4433             elsif ($string =~ /\G \$ \{ (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} /oxmsgc) {
4434 0           $e_string .= e_capture($1);
4435 0           $slash = 'div';
4436             }
4437              
4438             # $$foo[ ... ] --> $ $foo->[ ... ]
4439             elsif ($string =~ /\G \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \[ .+? \] ) /oxmsgc) {
4440 0           $e_string .= e_capture($1.'->'.$2);
4441 0           $slash = 'div';
4442             }
4443              
4444             # $$foo{ ... } --> $ $foo->{ ... }
4445             elsif ($string =~ /\G \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \{ .+? \} ) /oxmsgc) {
4446 0           $e_string .= e_capture($1.'->'.$2);
4447 0           $slash = 'div';
4448             }
4449              
4450             # $$foo
4451             elsif ($string =~ /\G \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) /oxmsgc) {
4452 0           $e_string .= e_capture($1);
4453 0           $slash = 'div';
4454             }
4455              
4456             # ${ foo }
4457             elsif ($string =~ /\G \$ (?>\s*) \{ ((?> \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* )) \} /oxmsgc) {
4458 0           $e_string .= '${' . $1 . '}';
4459 0           $slash = 'div';
4460             }
4461              
4462             # ${ ... }
4463             elsif ($string =~ /\G \$ (?>\s*) \{ (?>\s*) ( $qq_brace ) (?>\s*) \} /oxmsgc) {
4464 0           $e_string .= e_capture($1);
4465 0           $slash = 'div';
4466             }
4467              
4468             # variable or function
4469             # $ @ % & * $ #
4470             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) {
4471 0           $e_string .= $1;
4472 0           $slash = 'div';
4473             }
4474             # $ $ $ $ $ $ $ $ $ $ $ $ $ $
4475             # $ @ # \ ' " / ? ( ) [ ] < >
4476             elsif ($string =~ /\G ( \$[\$\@\#\\\'\"\/\?\(\)\[\]\<\>] ) /oxmsgc) {
4477 0           $e_string .= $1;
4478 0           $slash = 'div';
4479             }
4480              
4481             # subroutines of package Ekoi8u
4482 0           elsif ($string =~ /\G \b (CORE:: | ->(>?\s*) (?: atan2 | [a-z]{2,})) \b /oxgc) { $e_string .= $1; $slash = 'm//'; }
  0            
4483 0           elsif ($string =~ /\G \b Char::eval (?= (?>\s*) \{ ) /oxgc) { $e_string .= 'eval'; $slash = 'm//'; }
  0            
4484 0           elsif ($string =~ /\G \b KOI8U::eval (?= (?>\s*) \{ ) /oxgc) { $e_string .= 'eval'; $slash = 'm//'; }
  0            
4485 0           elsif ($string =~ /\G \b Char::eval \b /oxgc) { $e_string .= 'eval Char::escape'; $slash = 'm//'; }
  0            
4486 0           elsif ($string =~ /\G \b KOI8U::eval \b /oxgc) { $e_string .= 'eval KOI8U::escape'; $slash = 'm//'; }
  0            
4487 0           elsif ($string =~ /\G \b bytes::substr \b /oxgc) { $e_string .= 'substr'; $slash = 'm//'; }
  0            
4488 0           elsif ($string =~ /\G \b chop \b /oxgc) { $e_string .= 'Ekoi8u::chop'; $slash = 'm//'; }
  0            
4489 0           elsif ($string =~ /\G \b bytes::index \b /oxgc) { $e_string .= 'index'; $slash = 'm//'; }
  0            
4490 0           elsif ($string =~ /\G \b Char::index \b /oxgc) { $e_string .= 'Char::index'; $slash = 'm//'; }
  0            
4491 0           elsif ($string =~ /\G \b KOI8U::index \b /oxgc) { $e_string .= 'KOI8U::index'; $slash = 'm//'; }
  0            
4492 0           elsif ($string =~ /\G \b index \b /oxgc) { $e_string .= 'Ekoi8u::index'; $slash = 'm//'; }
  0            
4493 0           elsif ($string =~ /\G \b bytes::rindex \b /oxgc) { $e_string .= 'rindex'; $slash = 'm//'; }
  0            
4494 0           elsif ($string =~ /\G \b Char::rindex \b /oxgc) { $e_string .= 'Char::rindex'; $slash = 'm//'; }
  0            
4495 0           elsif ($string =~ /\G \b KOI8U::rindex \b /oxgc) { $e_string .= 'KOI8U::rindex'; $slash = 'm//'; }
  0            
4496 0           elsif ($string =~ /\G \b rindex \b /oxgc) { $e_string .= 'Ekoi8u::rindex'; $slash = 'm//'; }
  0            
4497 0           elsif ($string =~ /\G \b lc (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Ekoi8u::lc'; $slash = 'm//'; }
  0            
4498 0           elsif ($string =~ /\G \b lcfirst (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Ekoi8u::lcfirst'; $slash = 'm//'; }
  0            
4499 0           elsif ($string =~ /\G \b uc (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Ekoi8u::uc'; $slash = 'm//'; }
  0            
4500 0           elsif ($string =~ /\G \b ucfirst (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Ekoi8u::ucfirst'; $slash = 'm//'; }
  0            
4501 0           elsif ($string =~ /\G \b fc (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Ekoi8u::fc'; $slash = 'm//'; }
  0            
4502              
4503             # "-s '' ..." means file test "-s 'filename' ..." (not means "- s/// ...")
4504 0           elsif ($string =~ /\G -s (?>\s*) (\") ((?:$qq_char)+?) (\") /oxgc) { $e_string .= '-s ' . e_qq('', $1,$3,$2); $slash = 'm//'; }
  0            
4505 0           elsif ($string =~ /\G -s (?>\s+) qq (?>\s*) (\#) ((?:$qq_char)+?) (\#) /oxgc) { $e_string .= '-s ' . e_qq('qq',$1,$3,$2); $slash = 'm//'; }
  0            
4506 0           elsif ($string =~ /\G -s (?>\s+) qq (?>\s*) (\() ((?:$qq_paren)+?) (\)) /oxgc) { $e_string .= '-s ' . e_qq('qq',$1,$3,$2); $slash = 'm//'; }
  0            
4507 0           elsif ($string =~ /\G -s (?>\s+) qq (?>\s*) (\{) ((?:$qq_brace)+?) (\}) /oxgc) { $e_string .= '-s ' . e_qq('qq',$1,$3,$2); $slash = 'm//'; }
  0            
4508 0           elsif ($string =~ /\G -s (?>\s+) qq (?>\s*) (\[) ((?:$qq_bracket)+?) (\]) /oxgc) { $e_string .= '-s ' . e_qq('qq',$1,$3,$2); $slash = 'm//'; }
  0            
4509 0           elsif ($string =~ /\G -s (?>\s+) qq (?>\s*) (\<) ((?:$qq_angle)+?) (\>) /oxgc) { $e_string .= '-s ' . e_qq('qq',$1,$3,$2); $slash = 'm//'; }
  0            
4510 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            
4511              
4512 0           elsif ($string =~ /\G -s (?>\s*) (\') ((?:\\\'|\\\\|$q_char)+?) (\') /oxgc) { $e_string .= '-s ' . e_q ('', $1,$3,$2); $slash = 'm//'; }
  0            
4513 0           elsif ($string =~ /\G -s (?>\s+) q (?>\s*) (\#) ((?:\\\#|\\\\|$q_char)+?) (\#) /oxgc) { $e_string .= '-s ' . e_q ('q', $1,$3,$2); $slash = 'm//'; }
  0            
4514 0           elsif ($string =~ /\G -s (?>\s+) q (?>\s*) (\() ((?:\\\)|\\\\|$q_paren)+?) (\)) /oxgc) { $e_string .= '-s ' . e_q ('q', $1,$3,$2); $slash = 'm//'; }
  0            
4515 0           elsif ($string =~ /\G -s (?>\s+) q (?>\s*) (\{) ((?:\\\}|\\\\|$q_brace)+?) (\}) /oxgc) { $e_string .= '-s ' . e_q ('q', $1,$3,$2); $slash = 'm//'; }
  0            
4516 0           elsif ($string =~ /\G -s (?>\s+) q (?>\s*) (\[) ((?:\\\]|\\\\|$q_bracket)+?) (\]) /oxgc) { $e_string .= '-s ' . e_q ('q', $1,$3,$2); $slash = 'm//'; }
  0            
4517 0           elsif ($string =~ /\G -s (?>\s+) q (?>\s*) (\<) ((?:\\\>|\\\\|$q_angle)+?) (\>) /oxgc) { $e_string .= '-s ' . e_q ('q', $1,$3,$2); $slash = 'm//'; }
  0            
4518 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            
4519              
4520             elsif ($string =~ /\G -s (?>\s*) (\$ (?> \w+ (?: ::\w+)*) (?: (?: ->)? (?: [\$\@\%\&\*]\* | \$\#\* | \( (?:$qq_paren)*? \) | [\@\%\*]? \{ (?:$qq_brace)+? \} | [\@\%]? \[ (?:$qq_bracket)+? \] ))*) /oxgc)
4521 0           { $e_string .= "-s $1"; $slash = 'm//'; }
  0            
4522 0           elsif ($string =~ /\G -s (?>\s*) \( ((?:$qq_paren)*?) \) /oxgc) { $e_string .= "-s ($1)"; $slash = 'm//'; }
  0            
4523 0           elsif ($string =~ /\G -s (?= (?>\s+) [a-z]+) /oxgc) { $e_string .= '-s'; $slash = 'm//'; }
  0            
4524 0           elsif ($string =~ /\G -s (?>\s+) ((?>\w+)) /oxgc) { $e_string .= "-s $1"; $slash = 'm//'; }
  0            
4525              
4526 0           elsif ($string =~ /\G \b bytes::length (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'length'; $slash = 'm//'; }
  0            
4527 0           elsif ($string =~ /\G \b bytes::chr (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'chr'; $slash = 'm//'; }
  0            
4528 0           elsif ($string =~ /\G \b chr (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Ekoi8u::chr'; $slash = 'm//'; }
  0            
4529 0           elsif ($string =~ /\G \b bytes::ord (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'ord'; $slash = 'div'; }
  0            
4530 0           elsif ($string =~ /\G \b ord (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $e_string .= $function_ord; $slash = 'div'; }
  0            
4531 0           elsif ($string =~ /\G \b glob (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Ekoi8u::glob'; $slash = 'm//'; }
  0            
4532 0           elsif ($string =~ /\G \b lc \b /oxgc) { $e_string .= 'Ekoi8u::lc_'; $slash = 'm//'; }
  0            
4533 0           elsif ($string =~ /\G \b lcfirst \b /oxgc) { $e_string .= 'Ekoi8u::lcfirst_'; $slash = 'm//'; }
  0            
4534 0           elsif ($string =~ /\G \b uc \b /oxgc) { $e_string .= 'Ekoi8u::uc_'; $slash = 'm//'; }
  0            
4535 0           elsif ($string =~ /\G \b ucfirst \b /oxgc) { $e_string .= 'Ekoi8u::ucfirst_'; $slash = 'm//'; }
  0            
4536 0           elsif ($string =~ /\G \b fc \b /oxgc) { $e_string .= 'Ekoi8u::fc_'; $slash = 'm//'; }
  0            
4537 0           elsif ($string =~ /\G -s \b /oxgc) { $e_string .= '-s '; $slash = 'm//'; }
  0            
4538              
4539 0           elsif ($string =~ /\G \b bytes::length \b /oxgc) { $e_string .= 'length'; $slash = 'm//'; }
  0            
4540 0           elsif ($string =~ /\G \b bytes::chr \b /oxgc) { $e_string .= 'chr'; $slash = 'm//'; }
  0            
4541 0           elsif ($string =~ /\G \b chr \b /oxgc) { $e_string .= 'Ekoi8u::chr_'; $slash = 'm//'; }
  0            
4542 0           elsif ($string =~ /\G \b bytes::ord \b /oxgc) { $e_string .= 'ord'; $slash = 'div'; }
  0            
4543 0           elsif ($string =~ /\G \b ord \b /oxgc) { $e_string .= $function_ord_; $slash = 'div'; }
  0            
4544 0           elsif ($string =~ /\G \b glob \b /oxgc) { $e_string .= 'Ekoi8u::glob_'; $slash = 'm//'; }
  0            
4545 0           elsif ($string =~ /\G \b reverse \b /oxgc) { $e_string .= $function_reverse; $slash = 'm//'; }
  0            
4546 0           elsif ($string =~ /\G \b getc \b /oxgc) { $e_string .= $function_getc; $slash = 'm//'; }
  0            
4547             # split
4548             elsif ($string =~ /\G \b (split) \b (?! (?>\s*) => ) /oxgc) {
4549 0           $slash = 'm//';
4550              
4551 0           my $e = '';
4552 0           while ($string =~ /\G ( (?>\s+) | \( | \#.* ) /oxgc) {
4553 0           $e .= $1;
4554             }
4555              
4556             # end of split
4557 0 0         if ($string =~ /\G (?= [,;\)\}\]] ) /oxgc) { return 'Ekoi8u::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          
4558              
4559             # split scalar value
4560 0           elsif ($string =~ /\G ( [\$\@\&\*] $qq_scalar ) /oxgc) { $e_string .= 'Ekoi8u::split' . $e . e_string($1); next E_STRING_LOOP; }
  0            
4561              
4562             # split literal space
4563 0           elsif ($string =~ /\G \b qq (\#) [ ] (\#) /oxgc) { $e_string .= 'Ekoi8u::split' . $e . qq {qq$1 $2}; next E_STRING_LOOP; }
  0            
4564 0           elsif ($string =~ /\G \b qq ((?>\s*)) (\() [ ] (\)) /oxgc) { $e_string .= 'Ekoi8u::split' . $e . qq{$1qq$2 $3}; next E_STRING_LOOP; }
  0            
4565 0           elsif ($string =~ /\G \b qq ((?>\s*)) (\{) [ ] (\}) /oxgc) { $e_string .= 'Ekoi8u::split' . $e . qq{$1qq$2 $3}; next E_STRING_LOOP; }
  0            
4566 0           elsif ($string =~ /\G \b qq ((?>\s*)) (\[) [ ] (\]) /oxgc) { $e_string .= 'Ekoi8u::split' . $e . qq{$1qq$2 $3}; next E_STRING_LOOP; }
  0            
4567 0           elsif ($string =~ /\G \b qq ((?>\s*)) (\<) [ ] (\>) /oxgc) { $e_string .= 'Ekoi8u::split' . $e . qq{$1qq$2 $3}; next E_STRING_LOOP; }
  0            
4568 0           elsif ($string =~ /\G \b qq ((?>\s*)) (\S) [ ] (\2) /oxgc) { $e_string .= 'Ekoi8u::split' . $e . qq{$1qq$2 $3}; next E_STRING_LOOP; }
  0            
4569 0           elsif ($string =~ /\G \b q (\#) [ ] (\#) /oxgc) { $e_string .= 'Ekoi8u::split' . $e . qq {q$1 $2}; next E_STRING_LOOP; }
  0            
4570 0           elsif ($string =~ /\G \b q ((?>\s*)) (\() [ ] (\)) /oxgc) { $e_string .= 'Ekoi8u::split' . $e . qq {$1q$2 $3}; next E_STRING_LOOP; }
  0            
4571 0           elsif ($string =~ /\G \b q ((?>\s*)) (\{) [ ] (\}) /oxgc) { $e_string .= 'Ekoi8u::split' . $e . qq {$1q$2 $3}; next E_STRING_LOOP; }
  0            
4572 0           elsif ($string =~ /\G \b q ((?>\s*)) (\[) [ ] (\]) /oxgc) { $e_string .= 'Ekoi8u::split' . $e . qq {$1q$2 $3}; next E_STRING_LOOP; }
  0            
4573 0           elsif ($string =~ /\G \b q ((?>\s*)) (\<) [ ] (\>) /oxgc) { $e_string .= 'Ekoi8u::split' . $e . qq {$1q$2 $3}; next E_STRING_LOOP; }
  0            
4574 0           elsif ($string =~ /\G \b q ((?>\s*)) (\S) [ ] (\2) /oxgc) { $e_string .= 'Ekoi8u::split' . $e . qq {$1q$2 $3}; next E_STRING_LOOP; }
  0            
4575 0           elsif ($string =~ /\G ' [ ] ' /oxgc) { $e_string .= 'Ekoi8u::split' . $e . qq {' '}; next E_STRING_LOOP; }
  0            
4576 0           elsif ($string =~ /\G " [ ] " /oxgc) { $e_string .= 'Ekoi8u::split' . $e . qq {" "}; next E_STRING_LOOP; }
  0            
4577              
4578             # split qq//
4579             elsif ($string =~ /\G \b (qq) \b /oxgc) {
4580 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            
4581             else {
4582 0           while ($string !~ /\G \z/oxgc) {
4583 0 0         if ($string =~ /\G ((?>\s+)|\#.*) /oxgc) { $e_string .= $e . $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
4584 0           elsif ($string =~ /\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { $e_string .= e_split($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # qq ( ) --> qr ( )
  0            
4585 0           elsif ($string =~ /\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { $e_string .= e_split($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # qq { } --> qr { }
  0            
4586 0           elsif ($string =~ /\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { $e_string .= e_split($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # qq [ ] --> qr [ ]
  0            
4587 0           elsif ($string =~ /\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { $e_string .= e_split($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # qq < > --> qr < >
  0            
4588 0           elsif ($string =~ /\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) /oxgc) { $e_string .= e_split($e.'qr','{','}',$2,''); next E_STRING_LOOP; } # qq | | --> qr { }
  0            
4589 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            
4590             }
4591 0           die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4592             }
4593             }
4594              
4595             # split qr//
4596             elsif ($string =~ /\G \b (qr) \b /oxgc) {
4597 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            
4598             else {
4599 0           while ($string !~ /\G \z/oxgc) {
4600 0 0         if ($string =~ /\G ((?>\s+)|\#.*) /oxgc) { $e_string .= $e . $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
4601 0           elsif ($string =~ /\G (\() ((?:$qq_paren)*?) (\)) ([imosxpadlunbB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # qr ( )
  0            
4602 0           elsif ($string =~ /\G (\{) ((?:$qq_brace)*?) (\}) ([imosxpadlunbB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # qr { }
  0            
4603 0           elsif ($string =~ /\G (\[) ((?:$qq_bracket)*?) (\]) ([imosxpadlunbB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # qr [ ]
  0            
4604 0           elsif ($string =~ /\G (\<) ((?:$qq_angle)*?) (\>) ([imosxpadlunbB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # qr < >
  0            
4605 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            
4606 0           elsif ($string =~ /\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ([imosxpadlunbB]*) /oxgc) { $e_string .= e_split ($e.'qr','{','}',$2,$4); next E_STRING_LOOP; } # qr | | --> qr { }
  0            
4607 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            
4608             }
4609 0           die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4610             }
4611             }
4612              
4613             # split q//
4614             elsif ($string =~ /\G \b (q) \b /oxgc) {
4615 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            
4616             else {
4617 0           while ($string !~ /\G \z/oxgc) {
4618 0 0         if ($string =~ /\G ((?>\s+)|\#.*) /oxgc) { $e_string .= $e . $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
4619 0           elsif ($string =~ /\G (\() ((?:\\\\|\\\)|\\\(|$q_paren)*?) (\)) /oxgc) { $e_string .= e_split_q($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # q ( ) --> qr ( )
  0            
4620 0           elsif ($string =~ /\G (\{) ((?:\\\\|\\\}|\\\{|$q_brace)*?) (\}) /oxgc) { $e_string .= e_split_q($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # q { } --> qr { }
  0            
4621 0           elsif ($string =~ /\G (\[) ((?:\\\\|\\\]|\\\[|$q_bracket)*?) (\]) /oxgc) { $e_string .= e_split_q($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # q [ ] --> qr [ ]
  0            
4622 0           elsif ($string =~ /\G (\<) ((?:\\\\|\\\>|\\\<|$q_angle)*?) (\>) /oxgc) { $e_string .= e_split_q($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # q < > --> qr < >
  0            
4623 0           elsif ($string =~ /\G ([*\-:?\\^|]) ((?:$q_char)*?) (\1) /oxgc) { $e_string .= e_split_q($e.'qr','{','}',$2,''); next E_STRING_LOOP; } # q | | --> qr { }
  0            
4624 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            
4625             }
4626 0           die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4627             }
4628             }
4629              
4630             # split m//
4631             elsif ($string =~ /\G \b (m) \b /oxgc) {
4632 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            
4633             else {
4634 0           while ($string !~ /\G \z/oxgc) {
4635 0 0         if ($string =~ /\G ((?>\s+)|\#.*) /oxgc) { $e_string .= $e . $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
4636 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            
4637 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            
4638 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            
4639 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            
4640 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            
4641 0           elsif ($string =~ /\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ([cgimosxpadlunbB]*) /oxgc) { $e_string .= e_split ($e.'qr','{','}',$2,$4); next E_STRING_LOOP; } # m | | --> qr { }
  0            
4642 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            
4643             }
4644 0           die __FILE__, ": Search pattern not terminated\n";
4645             }
4646             }
4647              
4648             # split ''
4649             elsif ($string =~ /\G (\') /oxgc) {
4650 0           my $q_string = '';
4651 0           while ($string !~ /\G \z/oxgc) {
4652 0 0         if ($string =~ /\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0          
    0          
    0          
4653 0           elsif ($string =~ /\G (\\\') /oxgc) { $q_string .= $1; } # splitqr'' --> split qr''
4654 0           elsif ($string =~ /\G \' /oxgc) { $e_string .= e_split_q($e.q{ qr},"'","'",$q_string,''); next E_STRING_LOOP; } # ' ' --> qr ' '
  0            
4655 0           elsif ($string =~ /\G ($q_char) /oxgc) { $q_string .= $1; }
4656             }
4657 0           die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4658             }
4659              
4660             # split ""
4661             elsif ($string =~ /\G (\") /oxgc) {
4662 0           my $qq_string = '';
4663 0           while ($string !~ /\G \z/oxgc) {
4664 0 0         if ($string =~ /\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0          
    0          
    0          
4665 0           elsif ($string =~ /\G (\\\") /oxgc) { $qq_string .= $1; } # splitqr"" --> split qr""
4666 0           elsif ($string =~ /\G \" /oxgc) { $e_string .= e_split($e.q{ qr},'"','"',$qq_string,''); next E_STRING_LOOP; } # " " --> qr " "
  0            
4667 0           elsif ($string =~ /\G ($q_char) /oxgc) { $qq_string .= $1; }
4668             }
4669 0           die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4670             }
4671              
4672             # split //
4673             elsif ($string =~ /\G (\/) /oxgc) {
4674 0           my $regexp = '';
4675 0           while ($string !~ /\G \z/oxgc) {
4676 0 0         if ($string =~ /\G (\\\\) /oxgc) { $regexp .= $1; }
  0 0          
    0          
    0          
4677 0           elsif ($string =~ /\G (\\\/) /oxgc) { $regexp .= $1; } # splitqr// --> split qr//
4678 0           elsif ($string =~ /\G \/ ([cgimosxpadlunbB]*) /oxgc) { $e_string .= e_split($e.q{ qr}, '/','/',$regexp,$1); next E_STRING_LOOP; } # / / --> qr / /
  0            
4679 0           elsif ($string =~ /\G ($q_char) /oxgc) { $regexp .= $1; }
4680             }
4681 0           die __FILE__, ": Search pattern not terminated\n";
4682             }
4683             }
4684              
4685             # qq//
4686             elsif ($string =~ /\G \b (qq) \b /oxgc) {
4687 0           my $ope = $1;
4688 0 0         if ($string =~ /\G (\#) ((?:$qq_char)*?) (\#) /oxgc) { # qq# #
4689 0           $e_string .= e_qq($ope,$1,$3,$2);
4690             }
4691             else {
4692 0           my $e = '';
4693 0           while ($string !~ /\G \z/oxgc) {
4694 0 0         if ($string =~ /\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
4695 0           elsif ($string =~ /\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qq ( )
  0            
4696 0           elsif ($string =~ /\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qq { }
  0            
4697 0           elsif ($string =~ /\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qq [ ]
  0            
4698 0           elsif ($string =~ /\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qq < >
  0            
4699 0           elsif ($string =~ /\G (\S) ((?:$qq_char)*?) (\1) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qq * *
  0            
4700             }
4701 0           die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4702             }
4703             }
4704              
4705             # qx//
4706             elsif ($string =~ /\G \b (qx) \b /oxgc) {
4707 0           my $ope = $1;
4708 0 0         if ($string =~ /\G (\#) ((?:$qq_char)*?) (\#) /oxgc) { # qx# #
4709 0           $e_string .= e_qq($ope,$1,$3,$2);
4710             }
4711             else {
4712 0           my $e = '';
4713 0           while ($string !~ /\G \z/oxgc) {
4714 0 0         if ($string =~ /\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
4715 0           elsif ($string =~ /\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qx ( )
  0            
4716 0           elsif ($string =~ /\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qx { }
  0            
4717 0           elsif ($string =~ /\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qx [ ]
  0            
4718 0           elsif ($string =~ /\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qx < >
  0            
4719 0           elsif ($string =~ /\G (\') ((?:$qq_char)*?) (\') /oxgc) { $e_string .= $e . e_q ($ope,$1,$3,$2); next E_STRING_LOOP; } # qx ' '
  0            
4720 0           elsif ($string =~ /\G (\S) ((?:$qq_char)*?) (\1) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qx * *
  0            
4721             }
4722 0           die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4723             }
4724             }
4725              
4726             # q//
4727             elsif ($string =~ /\G \b (q) \b /oxgc) {
4728 0           my $ope = $1;
4729 0 0         if ($string =~ /\G (\#) ((?:\\\#|\\\\|$q_char)*?) (\#) /oxgc) { # q# #
4730 0           $e_string .= e_q($ope,$1,$3,$2);
4731             }
4732             else {
4733 0           my $e = '';
4734 0           while ($string !~ /\G \z/oxgc) {
4735 0 0         if ($string =~ /\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
4736 0           elsif ($string =~ /\G (\() ((?:\\\\|\\\)|\\\(|$q_paren)*?) (\)) /oxgc) { $e_string .= $e . e_q($ope,$1,$3,$2); next E_STRING_LOOP; } # q ( )
  0            
4737 0           elsif ($string =~ /\G (\{) ((?:\\\\|\\\}|\\\{|$q_brace)*?) (\}) /oxgc) { $e_string .= $e . e_q($ope,$1,$3,$2); next E_STRING_LOOP; } # q { }
  0            
4738 0           elsif ($string =~ /\G (\[) ((?:\\\\|\\\]|\\\[|$q_bracket)*?) (\]) /oxgc) { $e_string .= $e . e_q($ope,$1,$3,$2); next E_STRING_LOOP; } # q [ ]
  0            
4739 0           elsif ($string =~ /\G (\<) ((?:\\\\|\\\>|\\\<|$q_angle)*?) (\>) /oxgc) { $e_string .= $e . e_q($ope,$1,$3,$2); next E_STRING_LOOP; } # q < >
  0            
4740 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            
4741             }
4742 0           die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4743             }
4744             }
4745              
4746             # ''
4747 0           elsif ($string =~ /\G (?
4748              
4749             # ""
4750 0           elsif ($string =~ /\G (\") ((?:$qq_char)*?) (\") /oxgc) { $e_string .= e_qq('',$1,$3,$2); }
4751              
4752             # ``
4753 0           elsif ($string =~ /\G (\`) ((?:$qq_char)*?) (\`) /oxgc) { $e_string .= e_qq('',$1,$3,$2); }
4754              
4755             # <<>> (a safer ARGV)
4756 0           elsif ($string =~ /\G ( <<>> ) /oxgc) { $e_string .= $1; }
4757              
4758             # <<= <=> <= < operator
4759 0           elsif ($string =~ /\G ( <<= | <=> | <= | < ) (?= (?>\s*) [A-Za-z_0-9'"`\$\@\&\*\(\+\-] )/oxgc) { $e_string .= $1; }
4760              
4761             #
4762 0           elsif ($string =~ /\G (<[\$]?[A-Za-z_][A-Za-z_0-9]*>) /oxgc) { $e_string .= $1; }
4763              
4764             # --- glob
4765             elsif ($string =~ /\G < ((?:$q_char)+?) > /oxgc) {
4766 0           $e_string .= 'Ekoi8u::glob("' . $1 . '")';
4767             }
4768              
4769             # << (bit shift) --- not here document
4770 0           elsif ($string =~ /\G ( << (?>\s*) ) (?= [0-9\$\@\&] ) /oxgc) { $slash = 'm//'; $e_string .= $1; }
  0            
4771              
4772             # <<'HEREDOC'
4773             elsif ($string =~ /\G ( << '([a-zA-Z_0-9]*)' ) /oxgc) {
4774 0           $slash = 'm//';
4775 0           my $here_quote = $1;
4776 0           my $delimiter = $2;
4777              
4778             # get here document
4779 0 0         if ($here_script eq '') {
4780 0           $here_script = CORE::substr $_, pos $_;
4781 0           $here_script =~ s/.*?\n//oxm;
4782             }
4783 0 0         if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4784 0           push @heredoc, $1 . qq{\n$delimiter\n};
4785 0           push @heredoc_delimiter, $delimiter;
4786             }
4787             else {
4788 0           die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4789             }
4790 0           $e_string .= $here_quote;
4791             }
4792              
4793             # <<\HEREDOC
4794             elsif ($string =~ /\G ( << \\([a-zA-Z_0-9]+) ) /oxgc) {
4795 0           $slash = 'm//';
4796 0           my $here_quote = $1;
4797 0           my $delimiter = $2;
4798              
4799             # get here document
4800 0 0         if ($here_script eq '') {
4801 0           $here_script = CORE::substr $_, pos $_;
4802 0           $here_script =~ s/.*?\n//oxm;
4803             }
4804 0 0         if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4805 0           push @heredoc, $1 . qq{\n$delimiter\n};
4806 0           push @heredoc_delimiter, $delimiter;
4807             }
4808             else {
4809 0           die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4810             }
4811 0           $e_string .= $here_quote;
4812             }
4813              
4814             # <<"HEREDOC"
4815             elsif ($string =~ /\G ( << "([a-zA-Z_0-9]*)" ) /oxgc) {
4816 0           $slash = 'm//';
4817 0           my $here_quote = $1;
4818 0           my $delimiter = $2;
4819              
4820             # get here document
4821 0 0         if ($here_script eq '') {
4822 0           $here_script = CORE::substr $_, pos $_;
4823 0           $here_script =~ s/.*?\n//oxm;
4824             }
4825 0 0         if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4826 0           push @heredoc, e_heredoc($1) . qq{\n$delimiter\n};
4827 0           push @heredoc_delimiter, $delimiter;
4828             }
4829             else {
4830 0           die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4831             }
4832 0           $e_string .= $here_quote;
4833             }
4834              
4835             # <
4836             elsif ($string =~ /\G ( << ([a-zA-Z_0-9]+) ) /oxgc) {
4837 0           $slash = 'm//';
4838 0           my $here_quote = $1;
4839 0           my $delimiter = $2;
4840              
4841             # get here document
4842 0 0         if ($here_script eq '') {
4843 0           $here_script = CORE::substr $_, pos $_;
4844 0           $here_script =~ s/.*?\n//oxm;
4845             }
4846 0 0         if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4847 0           push @heredoc, e_heredoc($1) . qq{\n$delimiter\n};
4848 0           push @heredoc_delimiter, $delimiter;
4849             }
4850             else {
4851 0           die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4852             }
4853 0           $e_string .= $here_quote;
4854             }
4855              
4856             # <<`HEREDOC`
4857             elsif ($string =~ /\G ( << `([a-zA-Z_0-9]*)` ) /oxgc) {
4858 0           $slash = 'm//';
4859 0           my $here_quote = $1;
4860 0           my $delimiter = $2;
4861              
4862             # get here document
4863 0 0         if ($here_script eq '') {
4864 0           $here_script = CORE::substr $_, pos $_;
4865 0           $here_script =~ s/.*?\n//oxm;
4866             }
4867 0 0         if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4868 0           push @heredoc, e_heredoc($1) . qq{\n$delimiter\n};
4869 0           push @heredoc_delimiter, $delimiter;
4870             }
4871             else {
4872 0           die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4873             }
4874 0           $e_string .= $here_quote;
4875             }
4876              
4877             # any operator before div
4878             elsif ($string =~ /\G (
4879             -- | \+\+ |
4880             [\)\}\]]
4881              
4882 0           ) /oxgc) { $slash = 'div'; $e_string .= $1; }
  0            
4883              
4884             # yada-yada or triple-dot operator
4885             elsif ($string =~ /\G (
4886             \.\.\.
4887              
4888 0           ) /oxgc) { $slash = 'm//'; $e_string .= q{die('Unimplemented')}; }
  0            
4889              
4890             # any operator before m//
4891             elsif ($string =~ /\G ((?>
4892              
4893             !~~ | !~ | != | ! |
4894             %= | % |
4895             &&= | && | &= | &\.= | &\. | & |
4896             -= | -> | - |
4897             :(?>\s*)= |
4898             : |
4899             <<>> |
4900             <<= | <=> | <= | < |
4901             == | => | =~ | = |
4902             >>= | >> | >= | > |
4903             \*\*= | \*\* | \*= | \* |
4904             \+= | \+ |
4905             \.\. | \.= | \. |
4906             \/\/= | \/\/ |
4907             \/= | \/ |
4908             \? |
4909             \\ |
4910             \^= | \^\.= | \^\. | \^ |
4911             \b x= |
4912             \|\|= | \|\| | \|= | \|\.= | \|\. | \| |
4913             ~~ | ~\. | ~ |
4914             \b(?: and | cmp | eq | ge | gt | le | lt | ne | not | or | xor | x )\b |
4915             \b(?: print )\b |
4916              
4917             [,;\(\{\[]
4918              
4919 0           )) /oxgc) { $slash = 'm//'; $e_string .= $1; }
  0            
4920              
4921             # other any character
4922 0           elsif ($string =~ /\G ($q_char) /oxgc) { $e_string .= $1; }
4923              
4924             # system error
4925             else {
4926 0           die __FILE__, ": Oops, this shouldn't happen!\n";
4927             }
4928             }
4929              
4930 0           return $e_string;
4931             }
4932              
4933             #
4934             # character class
4935             #
4936             sub character_class {
4937 0     0 0   my($char,$modifier) = @_;
4938              
4939 0 0         if ($char eq '.') {
4940 0 0         if ($modifier =~ /s/) {
4941 0           return '${Ekoi8u::dot_s}';
4942             }
4943             else {
4944 0           return '${Ekoi8u::dot}';
4945             }
4946             }
4947             else {
4948 0           return Ekoi8u::classic_character_class($char);
4949             }
4950             }
4951              
4952             #
4953             # escape capture ($1, $2, $3, ...)
4954             #
4955             sub e_capture {
4956              
4957 0     0 0   return join '', '${', $_[0], '}';
4958             }
4959              
4960             #
4961             # escape transliteration (tr/// or y///)
4962             #
4963             sub e_tr {
4964 0     0 0   my($variable,$charclass,$e,$charclass2,$modifier) = @_;
4965 0           my $e_tr = '';
4966 0   0       $modifier ||= '';
4967              
4968 0           $slash = 'div';
4969              
4970             # quote character class 1
4971 0           $charclass = q_tr($charclass);
4972              
4973             # quote character class 2
4974 0           $charclass2 = q_tr($charclass2);
4975              
4976             # /b /B modifier
4977 0 0         if ($modifier =~ tr/bB//d) {
4978 0 0         if ($variable eq '') {
4979 0           $e_tr = qq{tr$charclass$e$charclass2$modifier};
4980             }
4981             else {
4982 0           $e_tr = qq{$variable${bind_operator}tr$charclass$e$charclass2$modifier};
4983             }
4984             }
4985             else {
4986 0 0         if ($variable eq '') {
4987 0           $e_tr = qq{Ekoi8u::tr(\$_,' =~ ',$charclass,$e$charclass2,'$modifier')};
4988             }
4989             else {
4990 0           $e_tr = qq{Ekoi8u::tr($variable,'$bind_operator',$charclass,$e$charclass2,'$modifier')};
4991             }
4992             }
4993              
4994             # clear tr/// variable
4995 0           $tr_variable = '';
4996 0           $bind_operator = '';
4997              
4998 0           return $e_tr;
4999             }
5000              
5001             #
5002             # quote for escape transliteration (tr/// or y///)
5003             #
5004             sub q_tr {
5005 0     0 0   my($charclass) = @_;
5006              
5007             # quote character class
5008 0 0         if ($charclass !~ /'/oxms) {
    0          
    0          
    0          
    0          
    0          
5009 0           return e_q('', "'", "'", $charclass); # --> q' '
5010             }
5011             elsif ($charclass !~ /\//oxms) {
5012 0           return e_q('q', '/', '/', $charclass); # --> q/ /
5013             }
5014             elsif ($charclass !~ /\#/oxms) {
5015 0           return e_q('q', '#', '#', $charclass); # --> q# #
5016             }
5017             elsif ($charclass !~ /[\<\>]/oxms) {
5018 0           return e_q('q', '<', '>', $charclass); # --> q< >
5019             }
5020             elsif ($charclass !~ /[\(\)]/oxms) {
5021 0           return e_q('q', '(', ')', $charclass); # --> q( )
5022             }
5023             elsif ($charclass !~ /[\{\}]/oxms) {
5024 0           return e_q('q', '{', '}', $charclass); # --> q{ }
5025             }
5026             else {
5027 0           for my $char (qw( ! " $ % & * + . : = ? @ ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
5028 0 0         if ($charclass !~ /\Q$char\E/xms) {
5029 0           return e_q('q', $char, $char, $charclass);
5030             }
5031             }
5032             }
5033              
5034 0           return e_q('q', '{', '}', $charclass);
5035             }
5036              
5037             #
5038             # escape q string (q//, '')
5039             #
5040             sub e_q {
5041 0     0 0   my($ope,$delimiter,$end_delimiter,$string) = @_;
5042              
5043 0           $slash = 'div';
5044              
5045 0           return join '', $ope, $delimiter, $string, $end_delimiter;
5046             }
5047              
5048             #
5049             # escape qq string (qq//, "", qx//, ``)
5050             #
5051             sub e_qq {
5052 0     0 0   my($ope,$delimiter,$end_delimiter,$string) = @_;
5053              
5054 0           $slash = 'div';
5055              
5056 0           my $left_e = 0;
5057 0           my $right_e = 0;
5058              
5059             # split regexp
5060 0           my @char = $string =~ /\G((?>
5061             [^\\\$] |
5062             \\x\{ (?>[0-9A-Fa-f]+) \} |
5063             \\o\{ (?>[0-7]+) \} |
5064             \\N\{ (?>[^0-9\}][^\}]*) \} |
5065             \\ $q_char |
5066             \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} |
5067             \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} |
5068             \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} |
5069             \$ (?>\s* [0-9]+) |
5070             \$ (?>\s*) \{ (?>\s* [0-9]+ \s*) \} |
5071             \$ \$ (?![\w\{]) |
5072             \$ (?>\s*) \$ (?>\s*) $qq_variable |
5073             $q_char
5074             ))/oxmsg;
5075              
5076 0           for (my $i=0; $i <= $#char; $i++) {
5077              
5078             # "\L\u" --> "\u\L"
5079 0 0 0       if (($char[$i] eq '\L') and ($char[$i+1] eq '\u')) {
    0 0        
    0          
    0          
    0          
5080 0           @char[$i,$i+1] = @char[$i+1,$i];
5081             }
5082              
5083             # "\U\l" --> "\l\U"
5084             elsif (($char[$i] eq '\U') and ($char[$i+1] eq '\l')) {
5085 0           @char[$i,$i+1] = @char[$i+1,$i];
5086             }
5087              
5088             # octal escape sequence
5089             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
5090 0           $char[$i] = Ekoi8u::octchr($1);
5091             }
5092              
5093             # hexadecimal escape sequence
5094             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
5095 0           $char[$i] = Ekoi8u::hexchr($1);
5096             }
5097              
5098             # \N{CHARNAME} --> N{CHARNAME}
5099             elsif ($char[$i] =~ /\A \\ ( N\{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
5100 0           $char[$i] = $1;
5101             }
5102              
5103 0 0         if (0) {
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
5104             }
5105              
5106             # \F
5107             #
5108             # P.69 Table 2-6. Translation escapes
5109             # in Chapter 2: Bits and Pieces
5110             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
5111             # (and so on)
5112              
5113             # \u \l \U \L \F \Q \E
5114 0           elsif ($char[$i] =~ /\A ([<>]) \z/oxms) {
5115 0 0         if ($right_e < $left_e) {
5116 0           $char[$i] = '\\' . $char[$i];
5117             }
5118             }
5119             elsif ($char[$i] eq '\u') {
5120              
5121             # "STRING @{[ LIST EXPR ]} MORE STRING"
5122              
5123             # P.257 Other Tricks You Can Do with Hard References
5124             # in Chapter 8: References
5125             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
5126              
5127             # P.353 Other Tricks You Can Do with Hard References
5128             # in Chapter 8: References
5129             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
5130              
5131             # (and so on)
5132              
5133 0           $char[$i] = '@{[Ekoi8u::ucfirst qq<';
5134 0           $left_e++;
5135             }
5136             elsif ($char[$i] eq '\l') {
5137 0           $char[$i] = '@{[Ekoi8u::lcfirst qq<';
5138 0           $left_e++;
5139             }
5140             elsif ($char[$i] eq '\U') {
5141 0           $char[$i] = '@{[Ekoi8u::uc qq<';
5142 0           $left_e++;
5143             }
5144             elsif ($char[$i] eq '\L') {
5145 0           $char[$i] = '@{[Ekoi8u::lc qq<';
5146 0           $left_e++;
5147             }
5148             elsif ($char[$i] eq '\F') {
5149 0           $char[$i] = '@{[Ekoi8u::fc qq<';
5150 0           $left_e++;
5151             }
5152             elsif ($char[$i] eq '\Q') {
5153 0           $char[$i] = '@{[CORE::quotemeta qq<';
5154 0           $left_e++;
5155             }
5156             elsif ($char[$i] eq '\E') {
5157 0 0         if ($right_e < $left_e) {
5158 0           $char[$i] = '>]}';
5159 0           $right_e++;
5160             }
5161             else {
5162 0           $char[$i] = '';
5163             }
5164             }
5165             elsif ($char[$i] eq '\Q') {
5166 0           while (1) {
5167 0 0         if (++$i > $#char) {
5168 0           last;
5169             }
5170 0 0         if ($char[$i] eq '\E') {
5171 0           last;
5172             }
5173             }
5174             }
5175             elsif ($char[$i] eq '\E') {
5176             }
5177              
5178             # $0 --> $0
5179             elsif ($char[$i] =~ /\A \$ 0 \z/oxms) {
5180             }
5181             elsif ($char[$i] =~ /\A \$ \{ (?>\s*) 0 (?>\s*) \} \z/oxms) {
5182             }
5183              
5184             # $$ --> $$
5185             elsif ($char[$i] =~ /\A \$\$ \z/oxms) {
5186             }
5187              
5188             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
5189             # $1, $2, $3 --> $1, $2, $3 otherwise
5190             elsif ($char[$i] =~ /\A \$ ((?>[1-9][0-9]*)) \z/oxms) {
5191 0           $char[$i] = e_capture($1);
5192             }
5193             elsif ($char[$i] =~ /\A \$ \{ (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} \z/oxms) {
5194 0           $char[$i] = e_capture($1);
5195             }
5196              
5197             # $$foo[ ... ] --> $ $foo->[ ... ]
5198             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \[ (?:$qq_bracket)*? \] ) \z/oxms) {
5199 0           $char[$i] = e_capture($1.'->'.$2);
5200             }
5201              
5202             # $$foo{ ... } --> $ $foo->{ ... }
5203             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \{ (?:$qq_brace)*? \} ) \z/oxms) {
5204 0           $char[$i] = e_capture($1.'->'.$2);
5205             }
5206              
5207             # $$foo
5208             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) \z/oxms) {
5209 0           $char[$i] = e_capture($1);
5210             }
5211              
5212             # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Ekoi8u::PREMATCH()
5213             elsif ($char[$i] =~ /\A ( \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} ) \z/oxmsgc) {
5214 0           $char[$i] = '@{[Ekoi8u::PREMATCH()]}';
5215             }
5216              
5217             # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Ekoi8u::MATCH()
5218             elsif ($char[$i] =~ /\A ( \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} ) \z/oxmsgc) {
5219 0           $char[$i] = '@{[Ekoi8u::MATCH()]}';
5220             }
5221              
5222             # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Ekoi8u::POSTMATCH()
5223             elsif ($char[$i] =~ /\A ( \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} ) \z/oxmsgc) {
5224 0           $char[$i] = '@{[Ekoi8u::POSTMATCH()]}';
5225             }
5226              
5227             # ${ foo } --> ${ foo }
5228             elsif ($char[$i] =~ /\A \$ (?>\s*) \{ (?> \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* ) \} \z/oxms) {
5229             }
5230              
5231             # ${ ... }
5232             elsif ($char[$i] =~ /\A \$ (?>\s*) \{ ( .+ ) \} \z/oxms) {
5233 0           $char[$i] = e_capture($1);
5234             }
5235             }
5236              
5237             # return string
5238 0 0         if ($left_e > $right_e) {
5239 0           return join '', $ope, $delimiter, @char, '>]}' x ($left_e - $right_e), $end_delimiter;
5240             }
5241 0           return join '', $ope, $delimiter, @char, $end_delimiter;
5242             }
5243              
5244             #
5245             # escape qw string (qw//)
5246             #
5247             sub e_qw {
5248 0     0 0   my($ope,$delimiter,$end_delimiter,$string) = @_;
5249              
5250 0           $slash = 'div';
5251              
5252             # choice again delimiter
5253 0           my %octet = map {$_ => 1} ($string =~ /\G ([\x00-\xFF]) /oxmsg);
  0            
5254 0 0         if (not $octet{$end_delimiter}) {
    0          
    0          
    0          
    0          
5255 0           return join '', $ope, $delimiter, $string, $end_delimiter;
5256             }
5257             elsif (not $octet{')'}) {
5258 0           return join '', $ope, '(', $string, ')';
5259             }
5260             elsif (not $octet{'}'}) {
5261 0           return join '', $ope, '{', $string, '}';
5262             }
5263             elsif (not $octet{']'}) {
5264 0           return join '', $ope, '[', $string, ']';
5265             }
5266             elsif (not $octet{'>'}) {
5267 0           return join '', $ope, '<', $string, '>';
5268             }
5269             else {
5270 0           for my $char (qw( ! " $ % & * + - . / : = ? @ ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
5271 0 0         if (not $octet{$char}) {
5272 0           return join '', $ope, $char, $string, $char;
5273             }
5274             }
5275             }
5276              
5277             # qw/AAA BBB C'CC/ --> ('AAA', 'BBB', 'C\'CC')
5278 0           my @string = CORE::split(/\s+/, $string);
5279 0           for my $string (@string) {
5280 0           my @octet = $string =~ /\G ([\x00-\xFF]) /oxmsg;
5281 0           for my $octet (@octet) {
5282 0 0         if ($octet =~ /\A (['\\]) \z/oxms) {
5283 0           $octet = '\\' . $1;
5284             }
5285             }
5286 0           $string = join '', @octet;
5287             }
5288 0           return join '', '(', (join ', ', map { "'$_'" } @string), ')';
  0            
5289             }
5290              
5291             #
5292             # escape here document (<<"HEREDOC", <
5293             #
5294             sub e_heredoc {
5295 0     0 0   my($string) = @_;
5296              
5297 0           $slash = 'm//';
5298              
5299 0           my $metachar = qr/[\@\\|]/oxms; # '|' is for <<`HEREDOC`
5300              
5301 0           my $left_e = 0;
5302 0           my $right_e = 0;
5303              
5304             # split regexp
5305 0           my @char = $string =~ /\G((?>
5306             [^\\\$] |
5307             \\x\{ (?>[0-9A-Fa-f]+) \} |
5308             \\o\{ (?>[0-7]+) \} |
5309             \\N\{ (?>[^0-9\}][^\}]*) \} |
5310             \\ $q_char |
5311             \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} |
5312             \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} |
5313             \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} |
5314             \$ (?>\s* [0-9]+) |
5315             \$ (?>\s*) \{ (?>\s* [0-9]+ \s*) \} |
5316             \$ \$ (?![\w\{]) |
5317             \$ (?>\s*) \$ (?>\s*) $qq_variable |
5318             $q_char
5319             ))/oxmsg;
5320              
5321 0           for (my $i=0; $i <= $#char; $i++) {
5322              
5323             # "\L\u" --> "\u\L"
5324 0 0 0       if (($char[$i] eq '\L') and ($char[$i+1] eq '\u')) {
    0 0        
    0          
    0          
    0          
5325 0           @char[$i,$i+1] = @char[$i+1,$i];
5326             }
5327              
5328             # "\U\l" --> "\l\U"
5329             elsif (($char[$i] eq '\U') and ($char[$i+1] eq '\l')) {
5330 0           @char[$i,$i+1] = @char[$i+1,$i];
5331             }
5332              
5333             # octal escape sequence
5334             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
5335 0           $char[$i] = Ekoi8u::octchr($1);
5336             }
5337              
5338             # hexadecimal escape sequence
5339             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
5340 0           $char[$i] = Ekoi8u::hexchr($1);
5341             }
5342              
5343             # \N{CHARNAME} --> N{CHARNAME}
5344             elsif ($char[$i] =~ /\A \\ ( N\{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
5345 0           $char[$i] = $1;
5346             }
5347              
5348 0 0         if (0) {
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
5349             }
5350              
5351             # \u \l \U \L \F \Q \E
5352 0           elsif ($char[$i] =~ /\A ([<>]) \z/oxms) {
5353 0 0         if ($right_e < $left_e) {
5354 0           $char[$i] = '\\' . $char[$i];
5355             }
5356             }
5357             elsif ($char[$i] eq '\u') {
5358 0           $char[$i] = '@{[Ekoi8u::ucfirst qq<';
5359 0           $left_e++;
5360             }
5361             elsif ($char[$i] eq '\l') {
5362 0           $char[$i] = '@{[Ekoi8u::lcfirst qq<';
5363 0           $left_e++;
5364             }
5365             elsif ($char[$i] eq '\U') {
5366 0           $char[$i] = '@{[Ekoi8u::uc qq<';
5367 0           $left_e++;
5368             }
5369             elsif ($char[$i] eq '\L') {
5370 0           $char[$i] = '@{[Ekoi8u::lc qq<';
5371 0           $left_e++;
5372             }
5373             elsif ($char[$i] eq '\F') {
5374 0           $char[$i] = '@{[Ekoi8u::fc qq<';
5375 0           $left_e++;
5376             }
5377             elsif ($char[$i] eq '\Q') {
5378 0           $char[$i] = '@{[CORE::quotemeta qq<';
5379 0           $left_e++;
5380             }
5381             elsif ($char[$i] eq '\E') {
5382 0 0         if ($right_e < $left_e) {
5383 0           $char[$i] = '>]}';
5384 0           $right_e++;
5385             }
5386             else {
5387 0           $char[$i] = '';
5388             }
5389             }
5390             elsif ($char[$i] eq '\Q') {
5391 0           while (1) {
5392 0 0         if (++$i > $#char) {
5393 0           last;
5394             }
5395 0 0         if ($char[$i] eq '\E') {
5396 0           last;
5397             }
5398             }
5399             }
5400             elsif ($char[$i] eq '\E') {
5401             }
5402              
5403             # $0 --> $0
5404             elsif ($char[$i] =~ /\A \$ 0 \z/oxms) {
5405             }
5406             elsif ($char[$i] =~ /\A \$ \{ (?>\s*) 0 (?>\s*) \} \z/oxms) {
5407             }
5408              
5409             # $$ --> $$
5410             elsif ($char[$i] =~ /\A \$\$ \z/oxms) {
5411             }
5412              
5413             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
5414             # $1, $2, $3 --> $1, $2, $3 otherwise
5415             elsif ($char[$i] =~ /\A \$ ((?>[1-9][0-9]*)) \z/oxms) {
5416 0           $char[$i] = e_capture($1);
5417             }
5418             elsif ($char[$i] =~ /\A \$ \{ (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} \z/oxms) {
5419 0           $char[$i] = e_capture($1);
5420             }
5421              
5422             # $$foo[ ... ] --> $ $foo->[ ... ]
5423             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \[ (?:$qq_bracket)*? \] ) \z/oxms) {
5424 0           $char[$i] = e_capture($1.'->'.$2);
5425             }
5426              
5427             # $$foo{ ... } --> $ $foo->{ ... }
5428             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \{ (?:$qq_brace)*? \} ) \z/oxms) {
5429 0           $char[$i] = e_capture($1.'->'.$2);
5430             }
5431              
5432             # $$foo
5433             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) \z/oxms) {
5434 0           $char[$i] = e_capture($1);
5435             }
5436              
5437             # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Ekoi8u::PREMATCH()
5438             elsif ($char[$i] =~ /\A ( \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} ) \z/oxmsgc) {
5439 0           $char[$i] = '@{[Ekoi8u::PREMATCH()]}';
5440             }
5441              
5442             # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Ekoi8u::MATCH()
5443             elsif ($char[$i] =~ /\A ( \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} ) \z/oxmsgc) {
5444 0           $char[$i] = '@{[Ekoi8u::MATCH()]}';
5445             }
5446              
5447             # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Ekoi8u::POSTMATCH()
5448             elsif ($char[$i] =~ /\A ( \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} ) \z/oxmsgc) {
5449 0           $char[$i] = '@{[Ekoi8u::POSTMATCH()]}';
5450             }
5451              
5452             # ${ foo } --> ${ foo }
5453             elsif ($char[$i] =~ /\A \$ (?>\s*) \{ (?> \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* ) \} \z/oxms) {
5454             }
5455              
5456             # ${ ... }
5457             elsif ($char[$i] =~ /\A \$ (?>\s*) \{ ( .+ ) \} \z/oxms) {
5458 0           $char[$i] = e_capture($1);
5459             }
5460             }
5461              
5462             # return string
5463 0 0         if ($left_e > $right_e) {
5464 0           return join '', @char, '>]}' x ($left_e - $right_e);
5465             }
5466 0           return join '', @char;
5467             }
5468              
5469             #
5470             # escape regexp (m//, qr//)
5471             #
5472             sub e_qr {
5473 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
5474 0   0       $modifier ||= '';
5475              
5476 0           $modifier =~ tr/p//d;
5477 0 0         if ($modifier =~ /([adlu])/oxms) {
5478 0           my $line = 0;
5479 0           for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
5480 0 0         if ($filename ne __FILE__) {
5481 0           $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
5482 0           last;
5483             }
5484             }
5485 0           die qq{Unsupported modifier "$1" used at line $line.\n};
5486             }
5487              
5488 0           $slash = 'div';
5489              
5490             # literal null string pattern
5491 0 0         if ($string eq '') {
    0          
5492 0           $modifier =~ tr/bB//d;
5493 0           $modifier =~ tr/i//d;
5494 0           return join '', $ope, $delimiter, $end_delimiter, $modifier;
5495             }
5496              
5497             # /b /B modifier
5498             elsif ($modifier =~ tr/bB//d) {
5499              
5500             # choice again delimiter
5501 0 0         if ($delimiter =~ / [\@:] /oxms) {
5502 0           my @char = $string =~ /\G ([\x00-\xFF]) /oxmsg;
5503 0           my %octet = map {$_ => 1} @char;
  0            
5504 0 0         if (not $octet{')'}) {
    0          
    0          
    0          
5505 0           $delimiter = '(';
5506 0           $end_delimiter = ')';
5507             }
5508             elsif (not $octet{'}'}) {
5509 0           $delimiter = '{';
5510 0           $end_delimiter = '}';
5511             }
5512             elsif (not $octet{']'}) {
5513 0           $delimiter = '[';
5514 0           $end_delimiter = ']';
5515             }
5516             elsif (not $octet{'>'}) {
5517 0           $delimiter = '<';
5518 0           $end_delimiter = '>';
5519             }
5520             else {
5521 0           for my $char (qw( ! " $ % & * + - . / = ? ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
5522 0 0         if (not $octet{$char}) {
5523 0           $delimiter = $char;
5524 0           $end_delimiter = $char;
5525 0           last;
5526             }
5527             }
5528             }
5529             }
5530              
5531 0 0 0       if (($ope =~ /\A m? \z/oxms) and ($delimiter eq '?')) {
5532 0           return join '', $ope, $delimiter, $string, $matched, $end_delimiter, $modifier;
5533             }
5534             else {
5535 0           return join '', $ope, $delimiter, '(?:', $string, ')', $matched, $end_delimiter, $modifier;
5536             }
5537             }
5538              
5539 0 0         my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
5540 0           my $metachar = qr/[\@\\|[\]{^]/oxms;
5541              
5542             # split regexp
5543 0           my @char = $string =~ /\G((?>
5544             [^\\\$\@\[\(] |
5545             \\x (?>[0-9A-Fa-f]{1,2}) |
5546             \\ (?>[0-7]{2,3}) |
5547             \\c [\x40-\x5F] |
5548             \\x\{ (?>[0-9A-Fa-f]+) \} |
5549             \\o\{ (?>[0-7]+) \} |
5550             \\[bBNpP]\{ (?>[^0-9\}][^\}]*) \} |
5551             \\ $q_char |
5552             \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} |
5553             \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} |
5554             \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} |
5555             [\$\@] $qq_variable |
5556             \$ (?>\s* [0-9]+) |
5557             \$ (?>\s*) \{ (?>\s* [0-9]+ \s*) \} |
5558             \$ \$ (?![\w\{]) |
5559             \$ (?>\s*) \$ (?>\s*) $qq_variable |
5560             \[\^ |
5561             \[\: (?>[a-z]+) :\] |
5562             \[\:\^ (?>[a-z]+) :\] |
5563             \(\? |
5564             $q_char
5565             ))/oxmsg;
5566              
5567             # choice again delimiter
5568 0 0         if ($delimiter =~ / [\@:] /oxms) {
5569 0           my %octet = map {$_ => 1} @char;
  0            
5570 0 0         if (not $octet{')'}) {
    0          
    0          
    0          
5571 0           $delimiter = '(';
5572 0           $end_delimiter = ')';
5573             }
5574             elsif (not $octet{'}'}) {
5575 0           $delimiter = '{';
5576 0           $end_delimiter = '}';
5577             }
5578             elsif (not $octet{']'}) {
5579 0           $delimiter = '[';
5580 0           $end_delimiter = ']';
5581             }
5582             elsif (not $octet{'>'}) {
5583 0           $delimiter = '<';
5584 0           $end_delimiter = '>';
5585             }
5586             else {
5587 0           for my $char (qw( ! " $ % & * + - . / = ? ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
5588 0 0         if (not $octet{$char}) {
5589 0           $delimiter = $char;
5590 0           $end_delimiter = $char;
5591 0           last;
5592             }
5593             }
5594             }
5595             }
5596              
5597 0           my $left_e = 0;
5598 0           my $right_e = 0;
5599 0           for (my $i=0; $i <= $#char; $i++) {
5600              
5601             # "\L\u" --> "\u\L"
5602 0 0 0       if (($char[$i] eq '\L') and ($char[$i+1] eq '\u')) {
    0 0        
    0          
    0          
    0          
    0          
5603 0           @char[$i,$i+1] = @char[$i+1,$i];
5604             }
5605              
5606             # "\U\l" --> "\l\U"
5607             elsif (($char[$i] eq '\U') and ($char[$i+1] eq '\l')) {
5608 0           @char[$i,$i+1] = @char[$i+1,$i];
5609             }
5610              
5611             # octal escape sequence
5612             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
5613 0           $char[$i] = Ekoi8u::octchr($1);
5614             }
5615              
5616             # hexadecimal escape sequence
5617             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
5618 0           $char[$i] = Ekoi8u::hexchr($1);
5619             }
5620              
5621             # \b{...} --> b\{...}
5622             # \B{...} --> B\{...}
5623             # \N{CHARNAME} --> N\{CHARNAME}
5624             # \p{PROPERTY} --> p\{PROPERTY}
5625             # \P{PROPERTY} --> P\{PROPERTY}
5626             elsif ($char[$i] =~ /\A \\ ([bBNpP]) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
5627 0           $char[$i] = $1 . '\\' . $2;
5628             }
5629              
5630             # \p, \P, \X --> p, P, X
5631             elsif ($char[$i] =~ /\A \\ ( [pPX] ) \z/oxms) {
5632 0           $char[$i] = $1;
5633             }
5634              
5635 0 0 0       if (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          
5636             }
5637              
5638             # join separated multiple-octet
5639 0           elsif ($char[$i] =~ /\A (?: \\ [0-7]{2,3} | \\x [0-9A-Fa-f]{1,2}) \z/oxms) {
5640 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        
5641 0           $char[$i] .= join '', splice @char, $i+1, 3;
5642             }
5643             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)) {
5644 0           $char[$i] .= join '', splice @char, $i+1, 2;
5645             }
5646             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)) {
5647 0           $char[$i] .= join '', splice @char, $i+1, 1;
5648             }
5649             }
5650              
5651             # open character class [...]
5652             elsif ($char[$i] eq '[') {
5653 0           my $left = $i;
5654              
5655             # [] make die "Unmatched [] in regexp ...\n"
5656             # (and so on)
5657              
5658 0 0         if ($char[$i+1] eq ']') {
5659 0           $i++;
5660             }
5661              
5662 0           while (1) {
5663 0 0         if (++$i > $#char) {
5664 0           die __FILE__, ": Unmatched [] in regexp\n";
5665             }
5666 0 0         if ($char[$i] eq ']') {
5667 0           my $right = $i;
5668              
5669             # [...]
5670 0 0         if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
5671 0           splice @char, $left, $right-$left+1, sprintf(q{@{[Ekoi8u::charlist_qr(%s,'%s')]}}, join(',', map {qq_stuff($delimiter,$end_delimiter,$_)} @char[$left+1..$right-1]), $modifier);
  0            
5672             }
5673             else {
5674 0           splice @char, $left, $right-$left+1, Ekoi8u::charlist_qr(@char[$left+1..$right-1], $modifier);
5675             }
5676              
5677 0           $i = $left;
5678 0           last;
5679             }
5680             }
5681             }
5682              
5683             # open character class [^...]
5684             elsif ($char[$i] eq '[^') {
5685 0           my $left = $i;
5686              
5687             # [^] make die "Unmatched [] in regexp ...\n"
5688             # (and so on)
5689              
5690 0 0         if ($char[$i+1] eq ']') {
5691 0           $i++;
5692             }
5693              
5694 0           while (1) {
5695 0 0         if (++$i > $#char) {
5696 0           die __FILE__, ": Unmatched [] in regexp\n";
5697             }
5698 0 0         if ($char[$i] eq ']') {
5699 0           my $right = $i;
5700              
5701             # [^...]
5702 0 0         if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
5703 0           splice @char, $left, $right-$left+1, sprintf(q{@{[Ekoi8u::charlist_not_qr(%s,'%s')]}}, join(',', map {qq_stuff($delimiter,$end_delimiter,$_)} @char[$left+1..$right-1]), $modifier);
  0            
5704             }
5705             else {
5706 0           splice @char, $left, $right-$left+1, Ekoi8u::charlist_not_qr(@char[$left+1..$right-1], $modifier);
5707             }
5708              
5709 0           $i = $left;
5710 0           last;
5711             }
5712             }
5713             }
5714              
5715             # rewrite character class or escape character
5716             elsif (my $char = character_class($char[$i],$modifier)) {
5717 0           $char[$i] = $char;
5718             }
5719              
5720             # /i modifier
5721             elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Ekoi8u::uc($char[$i]) ne Ekoi8u::fc($char[$i]))) {
5722 0 0         if (CORE::length(Ekoi8u::fc($char[$i])) == 1) {
5723 0           $char[$i] = '[' . Ekoi8u::uc($char[$i]) . Ekoi8u::fc($char[$i]) . ']';
5724             }
5725             else {
5726 0           $char[$i] = '(?:' . Ekoi8u::uc($char[$i]) . '|' . Ekoi8u::fc($char[$i]) . ')';
5727             }
5728             }
5729              
5730             # \u \l \U \L \F \Q \E
5731             elsif ($char[$i] =~ /\A [<>] \z/oxms) {
5732 0 0         if ($right_e < $left_e) {
5733 0           $char[$i] = '\\' . $char[$i];
5734             }
5735             }
5736             elsif ($char[$i] eq '\u') {
5737 0           $char[$i] = '@{[Ekoi8u::ucfirst qq<';
5738 0           $left_e++;
5739             }
5740             elsif ($char[$i] eq '\l') {
5741 0           $char[$i] = '@{[Ekoi8u::lcfirst qq<';
5742 0           $left_e++;
5743             }
5744             elsif ($char[$i] eq '\U') {
5745 0           $char[$i] = '@{[Ekoi8u::uc qq<';
5746 0           $left_e++;
5747             }
5748             elsif ($char[$i] eq '\L') {
5749 0           $char[$i] = '@{[Ekoi8u::lc qq<';
5750 0           $left_e++;
5751             }
5752             elsif ($char[$i] eq '\F') {
5753 0           $char[$i] = '@{[Ekoi8u::fc qq<';
5754 0           $left_e++;
5755             }
5756             elsif ($char[$i] eq '\Q') {
5757 0           $char[$i] = '@{[CORE::quotemeta qq<';
5758 0           $left_e++;
5759             }
5760             elsif ($char[$i] eq '\E') {
5761 0 0         if ($right_e < $left_e) {
5762 0           $char[$i] = '>]}';
5763 0           $right_e++;
5764             }
5765             else {
5766 0           $char[$i] = '';
5767             }
5768             }
5769             elsif ($char[$i] eq '\Q') {
5770 0           while (1) {
5771 0 0         if (++$i > $#char) {
5772 0           last;
5773             }
5774 0 0         if ($char[$i] eq '\E') {
5775 0           last;
5776             }
5777             }
5778             }
5779             elsif ($char[$i] eq '\E') {
5780             }
5781              
5782             # $0 --> $0
5783             elsif ($char[$i] =~ /\A \$ 0 \z/oxms) {
5784 0 0         if ($ignorecase) {
5785 0           $char[$i] = '@{[Ekoi8u::ignorecase(' . $char[$i] . ')]}';
5786             }
5787             }
5788             elsif ($char[$i] =~ /\A \$ \{ (?>\s*) 0 (?>\s*) \} \z/oxms) {
5789 0 0         if ($ignorecase) {
5790 0           $char[$i] = '@{[Ekoi8u::ignorecase(' . $char[$i] . ')]}';
5791             }
5792             }
5793              
5794             # $$ --> $$
5795             elsif ($char[$i] =~ /\A \$\$ \z/oxms) {
5796             }
5797              
5798             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
5799             # $1, $2, $3 --> $1, $2, $3 otherwise
5800             elsif ($char[$i] =~ /\A \$ ((?>[1-9][0-9]*)) \z/oxms) {
5801 0           $char[$i] = e_capture($1);
5802 0 0         if ($ignorecase) {
5803 0           $char[$i] = '@{[Ekoi8u::ignorecase(' . $char[$i] . ')]}';
5804             }
5805             }
5806             elsif ($char[$i] =~ /\A \$ \{ (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} \z/oxms) {
5807 0           $char[$i] = e_capture($1);
5808 0 0         if ($ignorecase) {
5809 0           $char[$i] = '@{[Ekoi8u::ignorecase(' . $char[$i] . ')]}';
5810             }
5811             }
5812              
5813             # $$foo[ ... ] --> $ $foo->[ ... ]
5814             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \[ (?:$qq_bracket)*? \] ) \z/oxms) {
5815 0           $char[$i] = e_capture($1.'->'.$2);
5816 0 0         if ($ignorecase) {
5817 0           $char[$i] = '@{[Ekoi8u::ignorecase(' . $char[$i] . ')]}';
5818             }
5819             }
5820              
5821             # $$foo{ ... } --> $ $foo->{ ... }
5822             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \{ (?:$qq_brace)*? \} ) \z/oxms) {
5823 0           $char[$i] = e_capture($1.'->'.$2);
5824 0 0         if ($ignorecase) {
5825 0           $char[$i] = '@{[Ekoi8u::ignorecase(' . $char[$i] . ')]}';
5826             }
5827             }
5828              
5829             # $$foo
5830             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) \z/oxms) {
5831 0           $char[$i] = e_capture($1);
5832 0 0         if ($ignorecase) {
5833 0           $char[$i] = '@{[Ekoi8u::ignorecase(' . $char[$i] . ')]}';
5834             }
5835             }
5836              
5837             # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Ekoi8u::PREMATCH()
5838             elsif ($char[$i] =~ /\A ( \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} ) \z/oxmsgc) {
5839 0 0         if ($ignorecase) {
5840 0           $char[$i] = '@{[Ekoi8u::ignorecase(Ekoi8u::PREMATCH())]}';
5841             }
5842             else {
5843 0           $char[$i] = '@{[Ekoi8u::PREMATCH()]}';
5844             }
5845             }
5846              
5847             # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Ekoi8u::MATCH()
5848             elsif ($char[$i] =~ /\A ( \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} ) \z/oxmsgc) {
5849 0 0         if ($ignorecase) {
5850 0           $char[$i] = '@{[Ekoi8u::ignorecase(Ekoi8u::MATCH())]}';
5851             }
5852             else {
5853 0           $char[$i] = '@{[Ekoi8u::MATCH()]}';
5854             }
5855             }
5856              
5857             # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Ekoi8u::POSTMATCH()
5858             elsif ($char[$i] =~ /\A ( \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} ) \z/oxmsgc) {
5859 0 0         if ($ignorecase) {
5860 0           $char[$i] = '@{[Ekoi8u::ignorecase(Ekoi8u::POSTMATCH())]}';
5861             }
5862             else {
5863 0           $char[$i] = '@{[Ekoi8u::POSTMATCH()]}';
5864             }
5865             }
5866              
5867             # ${ foo }
5868             elsif ($char[$i] =~ /\A \$ (?>\s*) \{ ((?> \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* )) \} \z/oxms) {
5869 0 0         if ($ignorecase) {
5870 0           $char[$i] = '@{[Ekoi8u::ignorecase(' . $char[$i] . ')]}';
5871             }
5872             }
5873              
5874             # ${ ... }
5875             elsif ($char[$i] =~ /\A \$ (?>\s*) \{ ( .+ ) \} \z/oxms) {
5876 0           $char[$i] = e_capture($1);
5877 0 0         if ($ignorecase) {
5878 0           $char[$i] = '@{[Ekoi8u::ignorecase(' . $char[$i] . ')]}';
5879             }
5880             }
5881              
5882             # $scalar or @array
5883             elsif ($char[$i] =~ /\A [\$\@].+ /oxms) {
5884 0           $char[$i] = e_string($char[$i]);
5885 0 0         if ($ignorecase) {
5886 0           $char[$i] = '@{[Ekoi8u::ignorecase(' . $char[$i] . ')]}';
5887             }
5888             }
5889              
5890             # quote character before ? + * {
5891             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
5892 0 0 0       if ($char[$i-1] =~ /\A (?:[\x00-\xFF]|\\[0-7]{2,3}|\\x[0-9-A-Fa-f]{1,2}) \z/oxms) {
    0          
5893             }
5894             elsif (($ope =~ /\A m? \z/oxms) and ($delimiter eq '?')) {
5895 0           my $char = $char[$i-1];
5896 0 0         if ($char[$i] eq '{') {
5897 0           die __FILE__, qq{: "MULTIBYTE{n}" should be "(MULTIBYTE){n}" in m?? (and shift \$1,\$2,\$3,...) ($char){n}\n};
5898             }
5899             else {
5900 0           die __FILE__, qq{: "MULTIBYTE$char[$i]" should be "(MULTIBYTE)$char[$i]" in m?? (and shift \$1,\$2,\$3,...) ($char)$char[$i]\n};
5901             }
5902             }
5903             else {
5904 0           $char[$i-1] = '(?:' . $char[$i-1] . ')';
5905             }
5906             }
5907             }
5908              
5909             # make regexp string
5910 0           $modifier =~ tr/i//d;
5911 0 0         if ($left_e > $right_e) {
5912 0 0 0       if (($ope =~ /\A m? \z/oxms) and ($delimiter eq '?')) {
5913 0           return join '', $ope, $delimiter, $anchor, @char, '>]}' x ($left_e - $right_e), $matched, $end_delimiter, $modifier;
5914             }
5915             else {
5916 0           return join '', $ope, $delimiter, $anchor, '(?:', @char, '>]}' x ($left_e - $right_e), ')', $matched, $end_delimiter, $modifier;
5917             }
5918             }
5919 0 0 0       if (($ope =~ /\A m? \z/oxms) and ($delimiter eq '?')) {
5920 0           return join '', $ope, $delimiter, $anchor, @char, $matched, $end_delimiter, $modifier;
5921             }
5922             else {
5923 0           return join '', $ope, $delimiter, $anchor, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
5924             }
5925             }
5926              
5927             #
5928             # double quote stuff
5929             #
5930             sub qq_stuff {
5931 0     0 0   my($delimiter,$end_delimiter,$stuff) = @_;
5932              
5933             # scalar variable or array variable
5934 0 0         if ($stuff =~ /\A [\$\@] /oxms) {
5935 0           return $stuff;
5936             }
5937              
5938             # quote by delimiter
5939 0           my %octet = map {$_ => 1} ($stuff =~ /\G ([\x00-\xFF]) /oxmsg);
  0            
5940 0           for my $char (qw( ! " $ % & * + - . / : = ? @ ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
5941 0 0         next if $char eq $delimiter;
5942 0 0         next if $char eq $end_delimiter;
5943 0 0         if (not $octet{$char}) {
5944 0           return join '', 'qq', $char, $stuff, $char;
5945             }
5946             }
5947 0           return join '', 'qq', '<', $stuff, '>';
5948             }
5949              
5950             #
5951             # escape regexp (m'', qr'', and m''b, qr''b)
5952             #
5953             sub e_qr_q {
5954 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
5955 0   0       $modifier ||= '';
5956              
5957 0           $modifier =~ tr/p//d;
5958 0 0         if ($modifier =~ /([adlu])/oxms) {
5959 0           my $line = 0;
5960 0           for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
5961 0 0         if ($filename ne __FILE__) {
5962 0           $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
5963 0           last;
5964             }
5965             }
5966 0           die qq{Unsupported modifier "$1" used at line $line.\n};
5967             }
5968              
5969 0           $slash = 'div';
5970              
5971             # literal null string pattern
5972 0 0         if ($string eq '') {
    0          
5973 0           $modifier =~ tr/bB//d;
5974 0           $modifier =~ tr/i//d;
5975 0           return join '', $ope, $delimiter, $end_delimiter, $modifier;
5976             }
5977              
5978             # with /b /B modifier
5979             elsif ($modifier =~ tr/bB//d) {
5980 0           return e_qr_qb($ope,$delimiter,$end_delimiter,$string,$modifier);
5981             }
5982              
5983             # without /b /B modifier
5984             else {
5985 0           return e_qr_qt($ope,$delimiter,$end_delimiter,$string,$modifier);
5986             }
5987             }
5988              
5989             #
5990             # escape regexp (m'', qr'')
5991             #
5992             sub e_qr_qt {
5993 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
5994              
5995 0 0         my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
5996              
5997             # split regexp
5998 0           my @char = $string =~ /\G((?>
5999             [^\\\[\$\@\/] |
6000             [\x00-\xFF] |
6001             \[\^ |
6002             \[\: (?>[a-z]+) \:\] |
6003             \[\:\^ (?>[a-z]+) \:\] |
6004             [\$\@\/] |
6005             \\ (?:$q_char) |
6006             (?:$q_char)
6007             ))/oxmsg;
6008              
6009             # unescape character
6010 0           for (my $i=0; $i <= $#char; $i++) {
6011 0 0 0       if (0) {
    0 0        
    0 0        
    0          
    0          
    0          
6012             }
6013              
6014             # open character class [...]
6015 0           elsif ($char[$i] eq '[') {
6016 0           my $left = $i;
6017 0 0         if ($char[$i+1] eq ']') {
6018 0           $i++;
6019             }
6020 0           while (1) {
6021 0 0         if (++$i > $#char) {
6022 0           die __FILE__, ": Unmatched [] in regexp\n";
6023             }
6024 0 0         if ($char[$i] eq ']') {
6025 0           my $right = $i;
6026              
6027             # [...]
6028 0           splice @char, $left, $right-$left+1, Ekoi8u::charlist_qr(@char[$left+1..$right-1], $modifier);
6029              
6030 0           $i = $left;
6031 0           last;
6032             }
6033             }
6034             }
6035              
6036             # open character class [^...]
6037             elsif ($char[$i] eq '[^') {
6038 0           my $left = $i;
6039 0 0         if ($char[$i+1] eq ']') {
6040 0           $i++;
6041             }
6042 0           while (1) {
6043 0 0         if (++$i > $#char) {
6044 0           die __FILE__, ": Unmatched [] in regexp\n";
6045             }
6046 0 0         if ($char[$i] eq ']') {
6047 0           my $right = $i;
6048              
6049             # [^...]
6050 0           splice @char, $left, $right-$left+1, Ekoi8u::charlist_not_qr(@char[$left+1..$right-1], $modifier);
6051              
6052 0           $i = $left;
6053 0           last;
6054             }
6055             }
6056             }
6057              
6058             # escape $ @ / and \
6059             elsif ($char[$i] =~ /\A [\$\@\/\\] \z/oxms) {
6060 0           $char[$i] = '\\' . $char[$i];
6061             }
6062              
6063             # rewrite character class or escape character
6064             elsif (my $char = character_class($char[$i],$modifier)) {
6065 0           $char[$i] = $char;
6066             }
6067              
6068             # /i modifier
6069             elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Ekoi8u::uc($char[$i]) ne Ekoi8u::fc($char[$i]))) {
6070 0 0         if (CORE::length(Ekoi8u::fc($char[$i])) == 1) {
6071 0           $char[$i] = '[' . Ekoi8u::uc($char[$i]) . Ekoi8u::fc($char[$i]) . ']';
6072             }
6073             else {
6074 0           $char[$i] = '(?:' . Ekoi8u::uc($char[$i]) . '|' . Ekoi8u::fc($char[$i]) . ')';
6075             }
6076             }
6077              
6078             # quote character before ? + * {
6079             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
6080 0 0         if ($char[$i-1] =~ /\A [\x00-\xFF] \z/oxms) {
6081             }
6082             else {
6083 0           $char[$i-1] = '(?:' . $char[$i-1] . ')';
6084             }
6085             }
6086             }
6087              
6088 0           $delimiter = '/';
6089 0           $end_delimiter = '/';
6090              
6091 0           $modifier =~ tr/i//d;
6092 0           return join '', $ope, $delimiter, $anchor, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
6093             }
6094              
6095             #
6096             # escape regexp (m''b, qr''b)
6097             #
6098             sub e_qr_qb {
6099 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6100              
6101             # split regexp
6102 0           my @char = $string =~ /\G ((?>[^\\]|\\\\)) /oxmsg;
6103              
6104             # unescape character
6105 0           for (my $i=0; $i <= $#char; $i++) {
6106 0 0         if (0) {
    0          
6107             }
6108              
6109             # remain \\
6110 0           elsif ($char[$i] eq '\\\\') {
6111             }
6112              
6113             # escape $ @ / and \
6114             elsif ($char[$i] =~ /\A [\$\@\/\\] \z/oxms) {
6115 0           $char[$i] = '\\' . $char[$i];
6116             }
6117             }
6118              
6119 0           $delimiter = '/';
6120 0           $end_delimiter = '/';
6121 0           return join '', $ope, $delimiter, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
6122             }
6123              
6124             #
6125             # escape regexp (s/here//)
6126             #
6127             sub e_s1 {
6128 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6129 0   0       $modifier ||= '';
6130              
6131 0           $modifier =~ tr/p//d;
6132 0 0         if ($modifier =~ /([adlu])/oxms) {
6133 0           my $line = 0;
6134 0           for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
6135 0 0         if ($filename ne __FILE__) {
6136 0           $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
6137 0           last;
6138             }
6139             }
6140 0           die qq{Unsupported modifier "$1" used at line $line.\n};
6141             }
6142              
6143 0           $slash = 'div';
6144              
6145             # literal null string pattern
6146 0 0         if ($string eq '') {
    0          
6147 0           $modifier =~ tr/bB//d;
6148 0           $modifier =~ tr/i//d;
6149 0           return join '', $ope, $delimiter, $end_delimiter, $modifier;
6150             }
6151              
6152             # /b /B modifier
6153             elsif ($modifier =~ tr/bB//d) {
6154              
6155             # choice again delimiter
6156 0 0         if ($delimiter =~ / [\@:] /oxms) {
6157 0           my @char = $string =~ /\G ([\x00-\xFF]) /oxmsg;
6158 0           my %octet = map {$_ => 1} @char;
  0            
6159 0 0         if (not $octet{')'}) {
    0          
    0          
    0          
6160 0           $delimiter = '(';
6161 0           $end_delimiter = ')';
6162             }
6163             elsif (not $octet{'}'}) {
6164 0           $delimiter = '{';
6165 0           $end_delimiter = '}';
6166             }
6167             elsif (not $octet{']'}) {
6168 0           $delimiter = '[';
6169 0           $end_delimiter = ']';
6170             }
6171             elsif (not $octet{'>'}) {
6172 0           $delimiter = '<';
6173 0           $end_delimiter = '>';
6174             }
6175             else {
6176 0           for my $char (qw( ! " $ % & * + - . / = ? ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
6177 0 0         if (not $octet{$char}) {
6178 0           $delimiter = $char;
6179 0           $end_delimiter = $char;
6180 0           last;
6181             }
6182             }
6183             }
6184             }
6185              
6186 0           my $prematch = '';
6187 0           return join '', $ope, $delimiter, $prematch, '(?:', $string, ')', $matched, $end_delimiter, $modifier;
6188             }
6189              
6190 0 0         my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
6191 0           my $metachar = qr/[\@\\|[\]{^]/oxms;
6192              
6193             # split regexp
6194 0           my @char = $string =~ /\G((?>
6195             [^\\\$\@\[\(] |
6196             \\ (?>[1-9][0-9]*) |
6197             \\g (?>\s*) (?>[1-9][0-9]*) |
6198             \\g (?>\s*) \{ (?>\s*) (?>[1-9][0-9]*) (?>\s*) \} |
6199             \\g (?>\s*) \{ (?>\s*) - (?>\s*) (?>[1-9][0-9]*) (?>\s*) \} |
6200             \\x (?>[0-9A-Fa-f]{1,2}) |
6201             \\ (?>[0-7]{2,3}) |
6202             \\c [\x40-\x5F] |
6203             \\x\{ (?>[0-9A-Fa-f]+) \} |
6204             \\o\{ (?>[0-7]+) \} |
6205             \\[bBNpP]\{ (?>[^0-9\}][^\}]*) \} |
6206             \\ $q_char |
6207             \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} |
6208             \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} |
6209             \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} |
6210             [\$\@] $qq_variable |
6211             \$ (?>\s* [0-9]+) |
6212             \$ (?>\s*) \{ (?>\s* [0-9]+ \s*) \} |
6213             \$ \$ (?![\w\{]) |
6214             \$ (?>\s*) \$ (?>\s*) $qq_variable |
6215             \[\^ |
6216             \[\: (?>[a-z]+) :\] |
6217             \[\:\^ (?>[a-z]+) :\] |
6218             \(\? |
6219             $q_char
6220             ))/oxmsg;
6221              
6222             # choice again delimiter
6223 0 0         if ($delimiter =~ / [\@:] /oxms) {
6224 0           my %octet = map {$_ => 1} @char;
  0            
6225 0 0         if (not $octet{')'}) {
    0          
    0          
    0          
6226 0           $delimiter = '(';
6227 0           $end_delimiter = ')';
6228             }
6229             elsif (not $octet{'}'}) {
6230 0           $delimiter = '{';
6231 0           $end_delimiter = '}';
6232             }
6233             elsif (not $octet{']'}) {
6234 0           $delimiter = '[';
6235 0           $end_delimiter = ']';
6236             }
6237             elsif (not $octet{'>'}) {
6238 0           $delimiter = '<';
6239 0           $end_delimiter = '>';
6240             }
6241             else {
6242 0           for my $char (qw( ! " $ % & * + - . / = ? ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
6243 0 0         if (not $octet{$char}) {
6244 0           $delimiter = $char;
6245 0           $end_delimiter = $char;
6246 0           last;
6247             }
6248             }
6249             }
6250             }
6251              
6252             # count '('
6253 0           my $parens = grep { $_ eq '(' } @char;
  0            
6254              
6255 0           my $left_e = 0;
6256 0           my $right_e = 0;
6257 0           for (my $i=0; $i <= $#char; $i++) {
6258              
6259             # "\L\u" --> "\u\L"
6260 0 0 0       if (($char[$i] eq '\L') and ($char[$i+1] eq '\u')) {
    0 0        
    0          
    0          
    0          
    0          
6261 0           @char[$i,$i+1] = @char[$i+1,$i];
6262             }
6263              
6264             # "\U\l" --> "\l\U"
6265             elsif (($char[$i] eq '\U') and ($char[$i+1] eq '\l')) {
6266 0           @char[$i,$i+1] = @char[$i+1,$i];
6267             }
6268              
6269             # octal escape sequence
6270             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
6271 0           $char[$i] = Ekoi8u::octchr($1);
6272             }
6273              
6274             # hexadecimal escape sequence
6275             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
6276 0           $char[$i] = Ekoi8u::hexchr($1);
6277             }
6278              
6279             # \b{...} --> b\{...}
6280             # \B{...} --> B\{...}
6281             # \N{CHARNAME} --> N\{CHARNAME}
6282             # \p{PROPERTY} --> p\{PROPERTY}
6283             # \P{PROPERTY} --> P\{PROPERTY}
6284             elsif ($char[$i] =~ /\A \\ ([bBNpP]) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
6285 0           $char[$i] = $1 . '\\' . $2;
6286             }
6287              
6288             # \p, \P, \X --> p, P, X
6289             elsif ($char[$i] =~ /\A \\ ( [pPX] ) \z/oxms) {
6290 0           $char[$i] = $1;
6291             }
6292              
6293 0 0 0       if (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          
6294             }
6295              
6296             # join separated multiple-octet
6297 0           elsif ($char[$i] =~ /\A (?: \\ [0-7]{2,3} | \\x [0-9A-Fa-f]{1,2}) \z/oxms) {
6298 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        
6299 0           $char[$i] .= join '', splice @char, $i+1, 3;
6300             }
6301             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)) {
6302 0           $char[$i] .= join '', splice @char, $i+1, 2;
6303             }
6304             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)) {
6305 0           $char[$i] .= join '', splice @char, $i+1, 1;
6306             }
6307             }
6308              
6309             # open character class [...]
6310             elsif ($char[$i] eq '[') {
6311 0           my $left = $i;
6312 0 0         if ($char[$i+1] eq ']') {
6313 0           $i++;
6314             }
6315 0           while (1) {
6316 0 0         if (++$i > $#char) {
6317 0           die __FILE__, ": Unmatched [] in regexp\n";
6318             }
6319 0 0         if ($char[$i] eq ']') {
6320 0           my $right = $i;
6321              
6322             # [...]
6323 0 0         if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
6324 0           splice @char, $left, $right-$left+1, sprintf(q{@{[Ekoi8u::charlist_qr(%s,'%s')]}}, join(',', map {qq_stuff($delimiter,$end_delimiter,$_)} @char[$left+1..$right-1]), $modifier);
  0            
6325             }
6326             else {
6327 0           splice @char, $left, $right-$left+1, Ekoi8u::charlist_qr(@char[$left+1..$right-1], $modifier);
6328             }
6329              
6330 0           $i = $left;
6331 0           last;
6332             }
6333             }
6334             }
6335              
6336             # open character class [^...]
6337             elsif ($char[$i] eq '[^') {
6338 0           my $left = $i;
6339 0 0         if ($char[$i+1] eq ']') {
6340 0           $i++;
6341             }
6342 0           while (1) {
6343 0 0         if (++$i > $#char) {
6344 0           die __FILE__, ": Unmatched [] in regexp\n";
6345             }
6346 0 0         if ($char[$i] eq ']') {
6347 0           my $right = $i;
6348              
6349             # [^...]
6350 0 0         if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
6351 0           splice @char, $left, $right-$left+1, sprintf(q{@{[Ekoi8u::charlist_not_qr(%s,'%s')]}}, join(',', map {qq_stuff($delimiter,$end_delimiter,$_)} @char[$left+1..$right-1]), $modifier);
  0            
6352             }
6353             else {
6354 0           splice @char, $left, $right-$left+1, Ekoi8u::charlist_not_qr(@char[$left+1..$right-1], $modifier);
6355             }
6356              
6357 0           $i = $left;
6358 0           last;
6359             }
6360             }
6361             }
6362              
6363             # rewrite character class or escape character
6364             elsif (my $char = character_class($char[$i],$modifier)) {
6365 0           $char[$i] = $char;
6366             }
6367              
6368             # /i modifier
6369             elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Ekoi8u::uc($char[$i]) ne Ekoi8u::fc($char[$i]))) {
6370 0 0         if (CORE::length(Ekoi8u::fc($char[$i])) == 1) {
6371 0           $char[$i] = '[' . Ekoi8u::uc($char[$i]) . Ekoi8u::fc($char[$i]) . ']';
6372             }
6373             else {
6374 0           $char[$i] = '(?:' . Ekoi8u::uc($char[$i]) . '|' . Ekoi8u::fc($char[$i]) . ')';
6375             }
6376             }
6377              
6378             # \u \l \U \L \F \Q \E
6379             elsif ($char[$i] =~ /\A [<>] \z/oxms) {
6380 0 0         if ($right_e < $left_e) {
6381 0           $char[$i] = '\\' . $char[$i];
6382             }
6383             }
6384             elsif ($char[$i] eq '\u') {
6385 0           $char[$i] = '@{[Ekoi8u::ucfirst qq<';
6386 0           $left_e++;
6387             }
6388             elsif ($char[$i] eq '\l') {
6389 0           $char[$i] = '@{[Ekoi8u::lcfirst qq<';
6390 0           $left_e++;
6391             }
6392             elsif ($char[$i] eq '\U') {
6393 0           $char[$i] = '@{[Ekoi8u::uc qq<';
6394 0           $left_e++;
6395             }
6396             elsif ($char[$i] eq '\L') {
6397 0           $char[$i] = '@{[Ekoi8u::lc qq<';
6398 0           $left_e++;
6399             }
6400             elsif ($char[$i] eq '\F') {
6401 0           $char[$i] = '@{[Ekoi8u::fc qq<';
6402 0           $left_e++;
6403             }
6404             elsif ($char[$i] eq '\Q') {
6405 0           $char[$i] = '@{[CORE::quotemeta qq<';
6406 0           $left_e++;
6407             }
6408             elsif ($char[$i] eq '\E') {
6409 0 0         if ($right_e < $left_e) {
6410 0           $char[$i] = '>]}';
6411 0           $right_e++;
6412             }
6413             else {
6414 0           $char[$i] = '';
6415             }
6416             }
6417             elsif ($char[$i] eq '\Q') {
6418 0           while (1) {
6419 0 0         if (++$i > $#char) {
6420 0           last;
6421             }
6422 0 0         if ($char[$i] eq '\E') {
6423 0           last;
6424             }
6425             }
6426             }
6427             elsif ($char[$i] eq '\E') {
6428             }
6429              
6430             # \0 --> \0
6431             elsif ($char[$i] =~ /\A \\ (?>\s*) 0 \z/oxms) {
6432             }
6433              
6434             # \g{N}, \g{-N}
6435              
6436             # P.108 Using Simple Patterns
6437             # in Chapter 7: In the World of Regular Expressions
6438             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
6439              
6440             # P.221 Capturing
6441             # in Chapter 5: Pattern Matching
6442             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
6443              
6444             # \g{-1}, \g{-2}, \g{-3} --> \g{-1}, \g{-2}, \g{-3}
6445             elsif ($char[$i] =~ /\A \\g (?>\s*) \{ (?>\s*) - (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} \z/oxms) {
6446             }
6447              
6448             # \g{1}, \g{2}, \g{3} --> \g{2}, \g{3}, \g{4} (only when multibyte anchoring is enable)
6449             elsif ($char[$i] =~ /\A \\g (?>\s*) \{ (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} \z/oxms) {
6450             }
6451              
6452             # \g1, \g2, \g3 --> \g2, \g3, \g4 (only when multibyte anchoring is enable)
6453             elsif ($char[$i] =~ /\A \\g (?>\s*) ((?>[1-9][0-9]*)) \z/oxms) {
6454             }
6455              
6456             # \1, \2, \3 --> \2, \3, \4 (only when multibyte anchoring is enable)
6457             elsif ($char[$i] =~ /\A \\ (?>\s*) ((?>[1-9][0-9]*)) \z/oxms) {
6458             }
6459              
6460             # $0 --> $0
6461             elsif ($char[$i] =~ /\A \$ 0 \z/oxms) {
6462 0 0         if ($ignorecase) {
6463 0           $char[$i] = '@{[Ekoi8u::ignorecase(' . $char[$i] . ')]}';
6464             }
6465             }
6466             elsif ($char[$i] =~ /\A \$ \{ (?>\s*) 0 (?>\s*) \} \z/oxms) {
6467 0 0         if ($ignorecase) {
6468 0           $char[$i] = '@{[Ekoi8u::ignorecase(' . $char[$i] . ')]}';
6469             }
6470             }
6471              
6472             # $$ --> $$
6473             elsif ($char[$i] =~ /\A \$\$ \z/oxms) {
6474             }
6475              
6476             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
6477             # $1, $2, $3 --> $1, $2, $3 otherwise
6478             elsif ($char[$i] =~ /\A \$ ((?>[1-9][0-9]*)) \z/oxms) {
6479 0           $char[$i] = e_capture($1);
6480 0 0         if ($ignorecase) {
6481 0           $char[$i] = '@{[Ekoi8u::ignorecase(' . $char[$i] . ')]}';
6482             }
6483             }
6484             elsif ($char[$i] =~ /\A \$ \{ (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} \z/oxms) {
6485 0           $char[$i] = e_capture($1);
6486 0 0         if ($ignorecase) {
6487 0           $char[$i] = '@{[Ekoi8u::ignorecase(' . $char[$i] . ')]}';
6488             }
6489             }
6490              
6491             # $$foo[ ... ] --> $ $foo->[ ... ]
6492             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \[ (?:$qq_bracket)*? \] ) \z/oxms) {
6493 0           $char[$i] = e_capture($1.'->'.$2);
6494 0 0         if ($ignorecase) {
6495 0           $char[$i] = '@{[Ekoi8u::ignorecase(' . $char[$i] . ')]}';
6496             }
6497             }
6498              
6499             # $$foo{ ... } --> $ $foo->{ ... }
6500             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \{ (?:$qq_brace)*? \} ) \z/oxms) {
6501 0           $char[$i] = e_capture($1.'->'.$2);
6502 0 0         if ($ignorecase) {
6503 0           $char[$i] = '@{[Ekoi8u::ignorecase(' . $char[$i] . ')]}';
6504             }
6505             }
6506              
6507             # $$foo
6508             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) \z/oxms) {
6509 0           $char[$i] = e_capture($1);
6510 0 0         if ($ignorecase) {
6511 0           $char[$i] = '@{[Ekoi8u::ignorecase(' . $char[$i] . ')]}';
6512             }
6513             }
6514              
6515             # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Ekoi8u::PREMATCH()
6516             elsif ($char[$i] =~ /\A ( \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} ) \z/oxmsgc) {
6517 0 0         if ($ignorecase) {
6518 0           $char[$i] = '@{[Ekoi8u::ignorecase(Ekoi8u::PREMATCH())]}';
6519             }
6520             else {
6521 0           $char[$i] = '@{[Ekoi8u::PREMATCH()]}';
6522             }
6523             }
6524              
6525             # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Ekoi8u::MATCH()
6526             elsif ($char[$i] =~ /\A ( \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} ) \z/oxmsgc) {
6527 0 0         if ($ignorecase) {
6528 0           $char[$i] = '@{[Ekoi8u::ignorecase(Ekoi8u::MATCH())]}';
6529             }
6530             else {
6531 0           $char[$i] = '@{[Ekoi8u::MATCH()]}';
6532             }
6533             }
6534              
6535             # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Ekoi8u::POSTMATCH()
6536             elsif ($char[$i] =~ /\A ( \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} ) \z/oxmsgc) {
6537 0 0         if ($ignorecase) {
6538 0           $char[$i] = '@{[Ekoi8u::ignorecase(Ekoi8u::POSTMATCH())]}';
6539             }
6540             else {
6541 0           $char[$i] = '@{[Ekoi8u::POSTMATCH()]}';
6542             }
6543             }
6544              
6545             # ${ foo }
6546             elsif ($char[$i] =~ /\A \$ (?>\s*) \{ ((?> \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* )) \} \z/oxms) {
6547 0 0         if ($ignorecase) {
6548 0           $char[$i] = '@{[Ekoi8u::ignorecase(' . $char[$i] . ')]}';
6549             }
6550             }
6551              
6552             # ${ ... }
6553             elsif ($char[$i] =~ /\A \$ (?>\s*) \{ ( .+ ) \} \z/oxms) {
6554 0           $char[$i] = e_capture($1);
6555 0 0         if ($ignorecase) {
6556 0           $char[$i] = '@{[Ekoi8u::ignorecase(' . $char[$i] . ')]}';
6557             }
6558             }
6559              
6560             # $scalar or @array
6561             elsif ($char[$i] =~ /\A [\$\@].+ /oxms) {
6562 0           $char[$i] = e_string($char[$i]);
6563 0 0         if ($ignorecase) {
6564 0           $char[$i] = '@{[Ekoi8u::ignorecase(' . $char[$i] . ')]}';
6565             }
6566             }
6567              
6568             # quote character before ? + * {
6569             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
6570 0 0         if ($char[$i-1] =~ /\A (?:[\x00-\xFF]|\\[0-7]{2,3}|\\x[0-9-A-Fa-f]{1,2}) \z/oxms) {
6571             }
6572             else {
6573 0           $char[$i-1] = '(?:' . $char[$i-1] . ')';
6574             }
6575             }
6576             }
6577              
6578             # make regexp string
6579 0           my $prematch = '';
6580 0           $modifier =~ tr/i//d;
6581 0 0         if ($left_e > $right_e) {
6582 0           return join '', $ope, $delimiter, $prematch, '(?:', @char, '>]}' x ($left_e - $right_e), ')', $matched, $end_delimiter, $modifier;
6583             }
6584 0           return join '', $ope, $delimiter, $prematch, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
6585             }
6586              
6587             #
6588             # escape regexp (s'here'' or s'here''b)
6589             #
6590             sub e_s1_q {
6591 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6592 0   0       $modifier ||= '';
6593              
6594 0           $modifier =~ tr/p//d;
6595 0 0         if ($modifier =~ /([adlu])/oxms) {
6596 0           my $line = 0;
6597 0           for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
6598 0 0         if ($filename ne __FILE__) {
6599 0           $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
6600 0           last;
6601             }
6602             }
6603 0           die qq{Unsupported modifier "$1" used at line $line.\n};
6604             }
6605              
6606 0           $slash = 'div';
6607              
6608             # literal null string pattern
6609 0 0         if ($string eq '') {
    0          
6610 0           $modifier =~ tr/bB//d;
6611 0           $modifier =~ tr/i//d;
6612 0           return join '', $ope, $delimiter, $end_delimiter, $modifier;
6613             }
6614              
6615             # with /b /B modifier
6616             elsif ($modifier =~ tr/bB//d) {
6617 0           return e_s1_qb($ope,$delimiter,$end_delimiter,$string,$modifier);
6618             }
6619              
6620             # without /b /B modifier
6621             else {
6622 0           return e_s1_qt($ope,$delimiter,$end_delimiter,$string,$modifier);
6623             }
6624             }
6625              
6626             #
6627             # escape regexp (s'here'')
6628             #
6629             sub e_s1_qt {
6630 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6631              
6632 0 0         my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
6633              
6634             # split regexp
6635 0           my @char = $string =~ /\G((?>
6636             [^\\\[\$\@\/] |
6637             [\x00-\xFF] |
6638             \[\^ |
6639             \[\: (?>[a-z]+) \:\] |
6640             \[\:\^ (?>[a-z]+) \:\] |
6641             [\$\@\/] |
6642             \\ (?:$q_char) |
6643             (?:$q_char)
6644             ))/oxmsg;
6645              
6646             # unescape character
6647 0           for (my $i=0; $i <= $#char; $i++) {
6648 0 0 0       if (0) {
    0 0        
    0 0        
    0          
    0          
    0          
6649             }
6650              
6651             # open character class [...]
6652 0           elsif ($char[$i] eq '[') {
6653 0           my $left = $i;
6654 0 0         if ($char[$i+1] eq ']') {
6655 0           $i++;
6656             }
6657 0           while (1) {
6658 0 0         if (++$i > $#char) {
6659 0           die __FILE__, ": Unmatched [] in regexp\n";
6660             }
6661 0 0         if ($char[$i] eq ']') {
6662 0           my $right = $i;
6663              
6664             # [...]
6665 0           splice @char, $left, $right-$left+1, Ekoi8u::charlist_qr(@char[$left+1..$right-1], $modifier);
6666              
6667 0           $i = $left;
6668 0           last;
6669             }
6670             }
6671             }
6672              
6673             # open character class [^...]
6674             elsif ($char[$i] eq '[^') {
6675 0           my $left = $i;
6676 0 0         if ($char[$i+1] eq ']') {
6677 0           $i++;
6678             }
6679 0           while (1) {
6680 0 0         if (++$i > $#char) {
6681 0           die __FILE__, ": Unmatched [] in regexp\n";
6682             }
6683 0 0         if ($char[$i] eq ']') {
6684 0           my $right = $i;
6685              
6686             # [^...]
6687 0           splice @char, $left, $right-$left+1, Ekoi8u::charlist_not_qr(@char[$left+1..$right-1], $modifier);
6688              
6689 0           $i = $left;
6690 0           last;
6691             }
6692             }
6693             }
6694              
6695             # escape $ @ / and \
6696             elsif ($char[$i] =~ /\A [\$\@\/\\] \z/oxms) {
6697 0           $char[$i] = '\\' . $char[$i];
6698             }
6699              
6700             # rewrite character class or escape character
6701             elsif (my $char = character_class($char[$i],$modifier)) {
6702 0           $char[$i] = $char;
6703             }
6704              
6705             # /i modifier
6706             elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Ekoi8u::uc($char[$i]) ne Ekoi8u::fc($char[$i]))) {
6707 0 0         if (CORE::length(Ekoi8u::fc($char[$i])) == 1) {
6708 0           $char[$i] = '[' . Ekoi8u::uc($char[$i]) . Ekoi8u::fc($char[$i]) . ']';
6709             }
6710             else {
6711 0           $char[$i] = '(?:' . Ekoi8u::uc($char[$i]) . '|' . Ekoi8u::fc($char[$i]) . ')';
6712             }
6713             }
6714              
6715             # quote character before ? + * {
6716             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
6717 0 0         if ($char[$i-1] =~ /\A [\x00-\xFF] \z/oxms) {
6718             }
6719             else {
6720 0           $char[$i-1] = '(?:' . $char[$i-1] . ')';
6721             }
6722             }
6723             }
6724              
6725 0           $modifier =~ tr/i//d;
6726 0           $delimiter = '/';
6727 0           $end_delimiter = '/';
6728 0           my $prematch = '';
6729 0           return join '', $ope, $delimiter, $prematch, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
6730             }
6731              
6732             #
6733             # escape regexp (s'here''b)
6734             #
6735             sub e_s1_qb {
6736 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6737              
6738             # split regexp
6739 0           my @char = $string =~ /\G (?>[^\\]|\\\\) /oxmsg;
6740              
6741             # unescape character
6742 0           for (my $i=0; $i <= $#char; $i++) {
6743 0 0         if (0) {
    0          
6744             }
6745              
6746             # remain \\
6747 0           elsif ($char[$i] eq '\\\\') {
6748             }
6749              
6750             # escape $ @ / and \
6751             elsif ($char[$i] =~ /\A [\$\@\/\\] \z/oxms) {
6752 0           $char[$i] = '\\' . $char[$i];
6753             }
6754             }
6755              
6756 0           $delimiter = '/';
6757 0           $end_delimiter = '/';
6758 0           my $prematch = '';
6759 0           return join '', $ope, $delimiter, $prematch, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
6760             }
6761              
6762             #
6763             # escape regexp (s''here')
6764             #
6765             sub e_s2_q {
6766 0     0 0   my($ope,$delimiter,$end_delimiter,$string) = @_;
6767              
6768 0           $slash = 'div';
6769              
6770 0           my @char = $string =~ / \G (?>[^\\]|\\\\|$q_char) /oxmsg;
6771 0           for (my $i=0; $i <= $#char; $i++) {
6772 0 0         if (0) {
    0          
6773             }
6774              
6775             # not escape \\
6776 0           elsif ($char[$i] =~ /\A \\\\ \z/oxms) {
6777             }
6778              
6779             # escape $ @ / and \
6780             elsif ($char[$i] =~ /\A [\$\@\/\\] \z/oxms) {
6781 0           $char[$i] = '\\' . $char[$i];
6782             }
6783             }
6784              
6785 0           return join '', $ope, $delimiter, @char, $end_delimiter;
6786             }
6787              
6788             #
6789             # escape regexp (s/here/and here/modifier)
6790             #
6791             sub e_sub {
6792 0     0 0   my($variable,$delimiter1,$pattern,$end_delimiter1,$delimiter2,$replacement,$end_delimiter2,$modifier) = @_;
6793 0   0       $modifier ||= '';
6794              
6795 0           $modifier =~ tr/p//d;
6796 0 0         if ($modifier =~ /([adlu])/oxms) {
6797 0           my $line = 0;
6798 0           for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
6799 0 0         if ($filename ne __FILE__) {
6800 0           $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
6801 0           last;
6802             }
6803             }
6804 0           die qq{Unsupported modifier "$1" used at line $line.\n};
6805             }
6806              
6807 0 0         if ($variable eq '') {
6808 0           $variable = '$_';
6809 0           $bind_operator = ' =~ ';
6810             }
6811              
6812 0           $slash = 'div';
6813              
6814             # P.128 Start of match (or end of previous match): \G
6815             # P.130 Advanced Use of \G with Perl
6816             # in Chapter 3: Overview of Regular Expression Features and Flavors
6817             # P.312 Iterative Matching: Scalar Context, with /g
6818             # in Chapter 7: Perl
6819             # of ISBN 0-596-00289-0 Mastering Regular Expressions, Second edition
6820              
6821             # P.181 Where You Left Off: The \G Assertion
6822             # in Chapter 5: Pattern Matching
6823             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
6824              
6825             # P.220 Where You Left Off: The \G Assertion
6826             # in Chapter 5: Pattern Matching
6827             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
6828              
6829 0           my $e_modifier = $modifier =~ tr/e//d;
6830 0           my $r_modifier = $modifier =~ tr/r//d;
6831              
6832 0           my $my = '';
6833 0 0         if ($variable =~ s/\A \( (?>\s*) ( (?>(?: local \b | my \b | our \b | state \b )?) .+ ) \) \z/$1/oxms) {
6834 0           $my = $variable;
6835 0           $variable =~ s/ (?: local \b | my \b | our \b | state \b ) (?>\s*) //oxms;
6836 0           $variable =~ s/ = .+ \z//oxms;
6837             }
6838              
6839 0           (my $variable_basename = $variable) =~ s/ [\[\{].* \z//oxms;
6840 0           $variable_basename =~ s/ \s+ \z//oxms;
6841              
6842             # quote replacement string
6843 0           my $e_replacement = '';
6844 0 0         if ($e_modifier >= 1) {
6845 0           $e_replacement = e_qq('', '', '', $replacement);
6846 0           $e_modifier--;
6847             }
6848             else {
6849 0 0         if ($delimiter2 eq "'") {
6850 0           $e_replacement = e_s2_q('qq', '/', '/', $replacement);
6851             }
6852             else {
6853 0           $e_replacement = e_qq ('qq', $delimiter2, $end_delimiter2, $replacement);
6854             }
6855             }
6856              
6857 0           my $sub = '';
6858              
6859             # with /r
6860 0 0         if ($r_modifier) {
6861 0 0         if (0) {
6862             }
6863              
6864             # s///gr without multibyte anchoring
6865 0           elsif ($modifier =~ /g/oxms) {
6866 0 0         $sub = sprintf(
6867             # 1 2 3 4 5
6868             q,
6869              
6870             $variable, # 1
6871             ($delimiter1 eq "'") ? # 2
6872             e_s1_q('m', $delimiter1, $end_delimiter1, $pattern, $modifier) : # :
6873             e_s1 ('m', $delimiter1, $end_delimiter1, $pattern, $modifier), # :
6874             $s_matched, # 3
6875             $e_replacement, # 4
6876             '$KOI8U::re_r=CORE::eval $KOI8U::re_r; ' x $e_modifier, # 5
6877             );
6878             }
6879              
6880             # s///r
6881             else {
6882              
6883 0           my $prematch = q{$`};
6884              
6885 0 0         $sub = sprintf(
6886             # 1 2 3 4 5 6 7
6887             q<(%s =~ %s) ? CORE::eval{%s local $^W=0; local $KOI8U::re_r=%s; %s"%s$KOI8U::re_r$'" } : %s>,
6888              
6889             $variable, # 1
6890             ($delimiter1 eq "'") ? # 2
6891             e_s1_q('m', $delimiter1, $end_delimiter1, $pattern, $modifier) : # :
6892             e_s1 ('m', $delimiter1, $end_delimiter1, $pattern, $modifier), # :
6893             $s_matched, # 3
6894             $e_replacement, # 4
6895             '$KOI8U::re_r=CORE::eval $KOI8U::re_r; ' x $e_modifier, # 5
6896             $prematch, # 6
6897             $variable, # 7
6898             );
6899             }
6900              
6901             # $var !~ s///r doesn't make sense
6902 0 0         if ($bind_operator =~ / !~ /oxms) {
6903 0           $sub = q{die("$0: Using !~ with s///r doesn't make sense"), } . $sub;
6904             }
6905             }
6906              
6907             # without /r
6908             else {
6909 0 0         if (0) {
6910             }
6911              
6912             # s///g without multibyte anchoring
6913 0           elsif ($modifier =~ /g/oxms) {
6914 0 0         $sub = sprintf(
    0          
6915             # 1 2 3 4 5 6 7 8
6916             q,
6917              
6918             $variable, # 1
6919             ($delimiter1 eq "'") ? # 2
6920             e_s1_q('m', $delimiter1, $end_delimiter1, $pattern, $modifier) : # :
6921             e_s1 ('m', $delimiter1, $end_delimiter1, $pattern, $modifier), # :
6922             $s_matched, # 3
6923             $e_replacement, # 4
6924             '$KOI8U::re_r=CORE::eval $KOI8U::re_r; ' x $e_modifier, # 5
6925             $variable, # 6
6926             $variable, # 7
6927             ($bind_operator =~ / !~ /oxms) ? '!' : '', # 8
6928             );
6929             }
6930              
6931             # s///
6932             else {
6933              
6934 0           my $prematch = q{$`};
6935              
6936 0 0         $sub = sprintf(
    0          
6937              
6938             ($bind_operator =~ / =~ /oxms) ?
6939              
6940             # 1 2 3 4 5 6 7 8
6941             q<(%s%s%s) ? CORE::eval{%s local $^W=0; local $KOI8U::re_r=%s; %s%s="%s$KOI8U::re_r$'"; 1 } : undef> :
6942              
6943             # 1 2 3 4 5 6 7 8
6944             q<(%s%s%s) ? 1 : CORE::eval{%s local $^W=0; local $KOI8U::re_r=%s; %s%s="%s$KOI8U::re_r$'"; undef }>,
6945              
6946             $variable, # 1
6947             $bind_operator, # 2
6948             ($delimiter1 eq "'") ? # 3
6949             e_s1_q('m', $delimiter1, $end_delimiter1, $pattern, $modifier) : # :
6950             e_s1 ('m', $delimiter1, $end_delimiter1, $pattern, $modifier), # :
6951             $s_matched, # 4
6952             $e_replacement, # 5
6953             '$KOI8U::re_r=CORE::eval $KOI8U::re_r; ' x $e_modifier, # 6
6954             $variable, # 7
6955             $prematch, # 8
6956             );
6957             }
6958             }
6959              
6960             # (my $foo = $bar) =~ s/// --> (my $foo = $bar, CORE::eval { ... })[1]
6961 0 0         if ($my ne '') {
6962 0           $sub = "($my, $sub)[1]";
6963             }
6964              
6965             # clear s/// variable
6966 0           $sub_variable = '';
6967 0           $bind_operator = '';
6968              
6969 0           return $sub;
6970             }
6971              
6972             #
6973             # escape regexp of split qr//
6974             #
6975             sub e_split {
6976 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6977 0   0       $modifier ||= '';
6978              
6979 0           $modifier =~ tr/p//d;
6980 0 0         if ($modifier =~ /([adlu])/oxms) {
6981 0           my $line = 0;
6982 0           for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
6983 0 0         if ($filename ne __FILE__) {
6984 0           $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
6985 0           last;
6986             }
6987             }
6988 0           die qq{Unsupported modifier "$1" used at line $line.\n};
6989             }
6990              
6991 0           $slash = 'div';
6992              
6993             # /b /B modifier
6994 0 0         if ($modifier =~ tr/bB//d) {
6995 0           return join '', 'split', $ope, $delimiter, $string, $end_delimiter, $modifier;
6996             }
6997              
6998 0 0         my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
6999 0           my $metachar = qr/[\@\\|[\]{^]/oxms;
7000              
7001             # split regexp
7002 0           my @char = $string =~ /\G((?>
7003             [^\\\$\@\[\(] |
7004             \\x (?>[0-9A-Fa-f]{1,2}) |
7005             \\ (?>[0-7]{2,3}) |
7006             \\c [\x40-\x5F] |
7007             \\x\{ (?>[0-9A-Fa-f]+) \} |
7008             \\o\{ (?>[0-7]+) \} |
7009             \\[bBNpP]\{ (?>[^0-9\}][^\}]*) \} |
7010             \\ $q_char |
7011             \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} |
7012             \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} |
7013             \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} |
7014             [\$\@] $qq_variable |
7015             \$ (?>\s* [0-9]+) |
7016             \$ (?>\s*) \{ (?>\s* [0-9]+ \s*) \} |
7017             \$ \$ (?![\w\{]) |
7018             \$ (?>\s*) \$ (?>\s*) $qq_variable |
7019             \[\^ |
7020             \[\: (?>[a-z]+) :\] |
7021             \[\:\^ (?>[a-z]+) :\] |
7022             \(\? |
7023             $q_char
7024             ))/oxmsg;
7025              
7026 0           my $left_e = 0;
7027 0           my $right_e = 0;
7028 0           for (my $i=0; $i <= $#char; $i++) {
7029              
7030             # "\L\u" --> "\u\L"
7031 0 0 0       if (($char[$i] eq '\L') and ($char[$i+1] eq '\u')) {
    0 0        
    0          
    0          
    0          
    0          
7032 0           @char[$i,$i+1] = @char[$i+1,$i];
7033             }
7034              
7035             # "\U\l" --> "\l\U"
7036             elsif (($char[$i] eq '\U') and ($char[$i+1] eq '\l')) {
7037 0           @char[$i,$i+1] = @char[$i+1,$i];
7038             }
7039              
7040             # octal escape sequence
7041             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
7042 0           $char[$i] = Ekoi8u::octchr($1);
7043             }
7044              
7045             # hexadecimal escape sequence
7046             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
7047 0           $char[$i] = Ekoi8u::hexchr($1);
7048             }
7049              
7050             # \b{...} --> b\{...}
7051             # \B{...} --> B\{...}
7052             # \N{CHARNAME} --> N\{CHARNAME}
7053             # \p{PROPERTY} --> p\{PROPERTY}
7054             # \P{PROPERTY} --> P\{PROPERTY}
7055             elsif ($char[$i] =~ /\A \\ ([bBNpP]) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
7056 0           $char[$i] = $1 . '\\' . $2;
7057             }
7058              
7059             # \p, \P, \X --> p, P, X
7060             elsif ($char[$i] =~ /\A \\ ( [pPX] ) \z/oxms) {
7061 0           $char[$i] = $1;
7062             }
7063              
7064 0 0 0       if (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          
7065             }
7066              
7067             # join separated multiple-octet
7068 0           elsif ($char[$i] =~ /\A (?: \\ [0-7]{2,3} | \\x [0-9A-Fa-f]{1,2}) \z/oxms) {
7069 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        
7070 0           $char[$i] .= join '', splice @char, $i+1, 3;
7071             }
7072             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)) {
7073 0           $char[$i] .= join '', splice @char, $i+1, 2;
7074             }
7075             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)) {
7076 0           $char[$i] .= join '', splice @char, $i+1, 1;
7077             }
7078             }
7079              
7080             # open character class [...]
7081             elsif ($char[$i] eq '[') {
7082 0           my $left = $i;
7083 0 0         if ($char[$i+1] eq ']') {
7084 0           $i++;
7085             }
7086 0           while (1) {
7087 0 0         if (++$i > $#char) {
7088 0           die __FILE__, ": Unmatched [] in regexp\n";
7089             }
7090 0 0         if ($char[$i] eq ']') {
7091 0           my $right = $i;
7092              
7093             # [...]
7094 0 0         if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
7095 0           splice @char, $left, $right-$left+1, sprintf(q{@{[Ekoi8u::charlist_qr(%s,'%s')]}}, join(',', map {qq_stuff($delimiter,$end_delimiter,$_)} @char[$left+1..$right-1]), $modifier);
  0            
7096             }
7097             else {
7098 0           splice @char, $left, $right-$left+1, Ekoi8u::charlist_qr(@char[$left+1..$right-1], $modifier);
7099             }
7100              
7101 0           $i = $left;
7102 0           last;
7103             }
7104             }
7105             }
7106              
7107             # open character class [^...]
7108             elsif ($char[$i] eq '[^') {
7109 0           my $left = $i;
7110 0 0         if ($char[$i+1] eq ']') {
7111 0           $i++;
7112             }
7113 0           while (1) {
7114 0 0         if (++$i > $#char) {
7115 0           die __FILE__, ": Unmatched [] in regexp\n";
7116             }
7117 0 0         if ($char[$i] eq ']') {
7118 0           my $right = $i;
7119              
7120             # [^...]
7121 0 0         if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
7122 0           splice @char, $left, $right-$left+1, sprintf(q{@{[Ekoi8u::charlist_not_qr(%s,'%s')]}}, join(',', map {qq_stuff($delimiter,$end_delimiter,$_)} @char[$left+1..$right-1]), $modifier);
  0            
7123             }
7124             else {
7125 0           splice @char, $left, $right-$left+1, Ekoi8u::charlist_not_qr(@char[$left+1..$right-1], $modifier);
7126             }
7127              
7128 0           $i = $left;
7129 0           last;
7130             }
7131             }
7132             }
7133              
7134             # rewrite character class or escape character
7135             elsif (my $char = character_class($char[$i],$modifier)) {
7136 0           $char[$i] = $char;
7137             }
7138              
7139             # P.794 29.2.161. split
7140             # in Chapter 29: Functions
7141             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
7142              
7143             # P.951 split
7144             # in Chapter 27: Functions
7145             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
7146              
7147             # said "The //m modifier is assumed when you split on the pattern /^/",
7148             # but perl5.008 is not so. Therefore, this software adds //m.
7149             # (and so on)
7150              
7151             # split(m/^/) --> split(m/^/m)
7152             elsif (($char[$i] eq '^') and ($modifier !~ /m/oxms)) {
7153 0           $modifier .= 'm';
7154             }
7155              
7156             # /i modifier
7157             elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Ekoi8u::uc($char[$i]) ne Ekoi8u::fc($char[$i]))) {
7158 0 0         if (CORE::length(Ekoi8u::fc($char[$i])) == 1) {
7159 0           $char[$i] = '[' . Ekoi8u::uc($char[$i]) . Ekoi8u::fc($char[$i]) . ']';
7160             }
7161             else {
7162 0           $char[$i] = '(?:' . Ekoi8u::uc($char[$i]) . '|' . Ekoi8u::fc($char[$i]) . ')';
7163             }
7164             }
7165              
7166             # \u \l \U \L \F \Q \E
7167             elsif ($char[$i] =~ /\A ([<>]) \z/oxms) {
7168 0 0         if ($right_e < $left_e) {
7169 0           $char[$i] = '\\' . $char[$i];
7170             }
7171             }
7172             elsif ($char[$i] eq '\u') {
7173 0           $char[$i] = '@{[Ekoi8u::ucfirst qq<';
7174 0           $left_e++;
7175             }
7176             elsif ($char[$i] eq '\l') {
7177 0           $char[$i] = '@{[Ekoi8u::lcfirst qq<';
7178 0           $left_e++;
7179             }
7180             elsif ($char[$i] eq '\U') {
7181 0           $char[$i] = '@{[Ekoi8u::uc qq<';
7182 0           $left_e++;
7183             }
7184             elsif ($char[$i] eq '\L') {
7185 0           $char[$i] = '@{[Ekoi8u::lc qq<';
7186 0           $left_e++;
7187             }
7188             elsif ($char[$i] eq '\F') {
7189 0           $char[$i] = '@{[Ekoi8u::fc qq<';
7190 0           $left_e++;
7191             }
7192             elsif ($char[$i] eq '\Q') {
7193 0           $char[$i] = '@{[CORE::quotemeta qq<';
7194 0           $left_e++;
7195             }
7196             elsif ($char[$i] eq '\E') {
7197 0 0         if ($right_e < $left_e) {
7198 0           $char[$i] = '>]}';
7199 0           $right_e++;
7200             }
7201             else {
7202 0           $char[$i] = '';
7203             }
7204             }
7205             elsif ($char[$i] eq '\Q') {
7206 0           while (1) {
7207 0 0         if (++$i > $#char) {
7208 0           last;
7209             }
7210 0 0         if ($char[$i] eq '\E') {
7211 0           last;
7212             }
7213             }
7214             }
7215             elsif ($char[$i] eq '\E') {
7216             }
7217              
7218             # $0 --> $0
7219             elsif ($char[$i] =~ /\A \$ 0 \z/oxms) {
7220 0 0         if ($ignorecase) {
7221 0           $char[$i] = '@{[Ekoi8u::ignorecase(' . $char[$i] . ')]}';
7222             }
7223             }
7224             elsif ($char[$i] =~ /\A \$ \{ (?>\s*) 0 (?>\s*) \} \z/oxms) {
7225 0 0         if ($ignorecase) {
7226 0           $char[$i] = '@{[Ekoi8u::ignorecase(' . $char[$i] . ')]}';
7227             }
7228             }
7229              
7230             # $$ --> $$
7231             elsif ($char[$i] =~ /\A \$\$ \z/oxms) {
7232             }
7233              
7234             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
7235             # $1, $2, $3 --> $1, $2, $3 otherwise
7236             elsif ($char[$i] =~ /\A \$ ((?>[1-9][0-9]*)) \z/oxms) {
7237 0           $char[$i] = e_capture($1);
7238 0 0         if ($ignorecase) {
7239 0           $char[$i] = '@{[Ekoi8u::ignorecase(' . $char[$i] . ')]}';
7240             }
7241             }
7242             elsif ($char[$i] =~ /\A \$ \{ (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} \z/oxms) {
7243 0           $char[$i] = e_capture($1);
7244 0 0         if ($ignorecase) {
7245 0           $char[$i] = '@{[Ekoi8u::ignorecase(' . $char[$i] . ')]}';
7246             }
7247             }
7248              
7249             # $$foo[ ... ] --> $ $foo->[ ... ]
7250             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \[ (?:$qq_bracket)*? \] ) \z/oxms) {
7251 0           $char[$i] = e_capture($1.'->'.$2);
7252 0 0         if ($ignorecase) {
7253 0           $char[$i] = '@{[Ekoi8u::ignorecase(' . $char[$i] . ')]}';
7254             }
7255             }
7256              
7257             # $$foo{ ... } --> $ $foo->{ ... }
7258             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \{ (?:$qq_brace)*? \} ) \z/oxms) {
7259 0           $char[$i] = e_capture($1.'->'.$2);
7260 0 0         if ($ignorecase) {
7261 0           $char[$i] = '@{[Ekoi8u::ignorecase(' . $char[$i] . ')]}';
7262             }
7263             }
7264              
7265             # $$foo
7266             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) \z/oxms) {
7267 0           $char[$i] = e_capture($1);
7268 0 0         if ($ignorecase) {
7269 0           $char[$i] = '@{[Ekoi8u::ignorecase(' . $char[$i] . ')]}';
7270             }
7271             }
7272              
7273             # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Ekoi8u::PREMATCH()
7274             elsif ($char[$i] =~ /\A ( \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} ) \z/oxmsgc) {
7275 0 0         if ($ignorecase) {
7276 0           $char[$i] = '@{[Ekoi8u::ignorecase(Ekoi8u::PREMATCH())]}';
7277             }
7278             else {
7279 0           $char[$i] = '@{[Ekoi8u::PREMATCH()]}';
7280             }
7281             }
7282              
7283             # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Ekoi8u::MATCH()
7284             elsif ($char[$i] =~ /\A ( \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} ) \z/oxmsgc) {
7285 0 0         if ($ignorecase) {
7286 0           $char[$i] = '@{[Ekoi8u::ignorecase(Ekoi8u::MATCH())]}';
7287             }
7288             else {
7289 0           $char[$i] = '@{[Ekoi8u::MATCH()]}';
7290             }
7291             }
7292              
7293             # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Ekoi8u::POSTMATCH()
7294             elsif ($char[$i] =~ /\A ( \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} ) \z/oxmsgc) {
7295 0 0         if ($ignorecase) {
7296 0           $char[$i] = '@{[Ekoi8u::ignorecase(Ekoi8u::POSTMATCH())]}';
7297             }
7298             else {
7299 0           $char[$i] = '@{[Ekoi8u::POSTMATCH()]}';
7300             }
7301             }
7302              
7303             # ${ foo }
7304             elsif ($char[$i] =~ /\A \$ (?>\s*) \{ ((?> \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* )) \} \z/oxms) {
7305 0 0         if ($ignorecase) {
7306 0           $char[$i] = '@{[Ekoi8u::ignorecase(' . $1 . ')]}';
7307             }
7308             }
7309              
7310             # ${ ... }
7311             elsif ($char[$i] =~ /\A \$ (?>\s*) \{ ( .+ ) \} \z/oxms) {
7312 0           $char[$i] = e_capture($1);
7313 0 0         if ($ignorecase) {
7314 0           $char[$i] = '@{[Ekoi8u::ignorecase(' . $char[$i] . ')]}';
7315             }
7316             }
7317              
7318             # $scalar or @array
7319             elsif ($char[$i] =~ /\A [\$\@].+ /oxms) {
7320 0           $char[$i] = e_string($char[$i]);
7321 0 0         if ($ignorecase) {
7322 0           $char[$i] = '@{[Ekoi8u::ignorecase(' . $char[$i] . ')]}';
7323             }
7324             }
7325              
7326             # quote character before ? + * {
7327             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
7328 0 0         if ($char[$i-1] =~ /\A (?:[\x00-\xFF]|\\[0-7]{2,3}|\\x[0-9-A-Fa-f]{1,2}) \z/oxms) {
7329             }
7330             else {
7331 0           $char[$i-1] = '(?:' . $char[$i-1] . ')';
7332             }
7333             }
7334             }
7335              
7336             # make regexp string
7337 0           $modifier =~ tr/i//d;
7338 0 0         if ($left_e > $right_e) {
7339 0           return join '', 'Ekoi8u::split', $ope, $delimiter, @char, '>]}' x ($left_e - $right_e), $end_delimiter, $modifier;
7340             }
7341 0           return join '', 'Ekoi8u::split', $ope, $delimiter, @char, $end_delimiter, $modifier;
7342             }
7343              
7344             #
7345             # escape regexp of split qr''
7346             #
7347             sub e_split_q {
7348 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
7349 0   0       $modifier ||= '';
7350              
7351 0           $modifier =~ tr/p//d;
7352 0 0         if ($modifier =~ /([adlu])/oxms) {
7353 0           my $line = 0;
7354 0           for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
7355 0 0         if ($filename ne __FILE__) {
7356 0           $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
7357 0           last;
7358             }
7359             }
7360 0           die qq{Unsupported modifier "$1" used at line $line.\n};
7361             }
7362              
7363 0           $slash = 'div';
7364              
7365             # /b /B modifier
7366 0 0         if ($modifier =~ tr/bB//d) {
7367 0           return join '', 'split', $ope, $delimiter, $string, $end_delimiter, $modifier;
7368             }
7369              
7370 0 0         my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
7371              
7372             # split regexp
7373 0           my @char = $string =~ /\G((?>
7374             [^\\\[] |
7375             [\x00-\xFF] |
7376             \[\^ |
7377             \[\: (?>[a-z]+) \:\] |
7378             \[\:\^ (?>[a-z]+) \:\] |
7379             \\ (?:$q_char) |
7380             (?:$q_char)
7381             ))/oxmsg;
7382              
7383             # unescape character
7384 0           for (my $i=0; $i <= $#char; $i++) {
7385 0 0 0       if (0) {
    0 0        
    0 0        
    0 0        
    0          
    0          
7386             }
7387              
7388             # open character class [...]
7389 0           elsif ($char[$i] eq '[') {
7390 0           my $left = $i;
7391 0 0         if ($char[$i+1] eq ']') {
7392 0           $i++;
7393             }
7394 0           while (1) {
7395 0 0         if (++$i > $#char) {
7396 0           die __FILE__, ": Unmatched [] in regexp\n";
7397             }
7398 0 0         if ($char[$i] eq ']') {
7399 0           my $right = $i;
7400              
7401             # [...]
7402 0           splice @char, $left, $right-$left+1, Ekoi8u::charlist_qr(@char[$left+1..$right-1], $modifier);
7403              
7404 0           $i = $left;
7405 0           last;
7406             }
7407             }
7408             }
7409              
7410             # open character class [^...]
7411             elsif ($char[$i] eq '[^') {
7412 0           my $left = $i;
7413 0 0         if ($char[$i+1] eq ']') {
7414 0           $i++;
7415             }
7416 0           while (1) {
7417 0 0         if (++$i > $#char) {
7418 0           die __FILE__, ": Unmatched [] in regexp\n";
7419             }
7420 0 0         if ($char[$i] eq ']') {
7421 0           my $right = $i;
7422              
7423             # [^...]
7424 0           splice @char, $left, $right-$left+1, Ekoi8u::charlist_not_qr(@char[$left+1..$right-1], $modifier);
7425              
7426 0           $i = $left;
7427 0           last;
7428             }
7429             }
7430             }
7431              
7432             # rewrite character class or escape character
7433             elsif (my $char = character_class($char[$i],$modifier)) {
7434 0           $char[$i] = $char;
7435             }
7436              
7437             # split(m/^/) --> split(m/^/m)
7438             elsif (($char[$i] eq '^') and ($modifier !~ /m/oxms)) {
7439 0           $modifier .= 'm';
7440             }
7441              
7442             # /i modifier
7443             elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Ekoi8u::uc($char[$i]) ne Ekoi8u::fc($char[$i]))) {
7444 0 0         if (CORE::length(Ekoi8u::fc($char[$i])) == 1) {
7445 0           $char[$i] = '[' . Ekoi8u::uc($char[$i]) . Ekoi8u::fc($char[$i]) . ']';
7446             }
7447             else {
7448 0           $char[$i] = '(?:' . Ekoi8u::uc($char[$i]) . '|' . Ekoi8u::fc($char[$i]) . ')';
7449             }
7450             }
7451              
7452             # quote character before ? + * {
7453             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
7454 0 0         if ($char[$i-1] =~ /\A [\x00-\xFF] \z/oxms) {
7455             }
7456             else {
7457 0           $char[$i-1] = '(?:' . $char[$i-1] . ')';
7458             }
7459             }
7460             }
7461              
7462 0           $modifier =~ tr/i//d;
7463 0           return join '', 'Ekoi8u::split', $ope, $delimiter, @char, $end_delimiter, $modifier;
7464             }
7465              
7466             #
7467             # instead of Carp::carp
7468             #
7469             sub carp {
7470 0     0 0   my($package,$filename,$line) = caller(1);
7471 0           print STDERR "@_ at $filename line $line.\n";
7472             }
7473              
7474             #
7475             # instead of Carp::croak
7476             #
7477             sub croak {
7478 0     0 0   my($package,$filename,$line) = caller(1);
7479 0           print STDERR "@_ at $filename line $line.\n";
7480 0           die "\n";
7481             }
7482              
7483             #
7484             # instead of Carp::cluck
7485             #
7486             sub cluck {
7487 0     0 0   my $i = 0;
7488 0           my @cluck = ();
7489 0           while (my($package,$filename,$line,$subroutine) = caller($i)) {
7490 0           push @cluck, "[$i] $filename($line) $package::$subroutine\n";
7491 0           $i++;
7492             }
7493 0           print STDERR CORE::reverse @cluck;
7494 0           print STDERR "\n";
7495 0           carp @_;
7496             }
7497              
7498             #
7499             # instead of Carp::confess
7500             #
7501             sub confess {
7502 0     0 0   my $i = 0;
7503 0           my @confess = ();
7504 0           while (my($package,$filename,$line,$subroutine) = caller($i)) {
7505 0           push @confess, "[$i] $filename($line) $package::$subroutine\n";
7506 0           $i++;
7507             }
7508 0           print STDERR CORE::reverse @confess;
7509 0           print STDERR "\n";
7510 0           croak @_;
7511             }
7512              
7513             1;
7514              
7515             __END__