File Coverage

Char/Elatin1.pm
Criterion Covered Total %
statement 83 3062 2.7
branch 4 2670 0.1
condition 1 373 0.2
subroutine 36 125 28.8
pod 7 74 9.4
total 131 6304 2.0


line stmt bran cond sub pod time code
1             #
2             # This file is *** FOR CPAN USE ONLY ***.
3             #
4             package Char::Elatin1;
5             ######################################################################
6             #
7             # Char::Elatin1 - Run-time routines for Char/Latin1.pm
8             #
9             # http://search.cpan.org/dist/Char-Latin1/
10             #
11             # Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015 INABA Hitoshi
12             ######################################################################
13              
14 197     197   4490 use 5.00503; # Galapagos Consensus 1998 for primetools
  197         640  
  197         11316  
15             # use 5.008001; # Lancaster Consensus 2013 for toolchains
16              
17             # 12.3. Delaying use Until Runtime
18             # in Chapter 12. Packages, Libraries, and Modules
19             # of ISBN 0-596-00313-7 Perl Cookbook, 2nd Edition.
20             # (and so on)
21              
22 197     197   14230 BEGIN { CORE::eval q{ use vars qw($VERSION) } }
  197     197   1403  
  197         347  
  197         44721  
23             $VERSION = sprintf '%d.%02d', q$Revision: 1.02 $ =~ /(\d+)/xmsg;
24              
25             BEGIN {
26 197 50   197   1394 if ($^X =~ / jperl /oxmsi) {
27 0         0 die __FILE__, ": needs perl(not jperl) 5.00503 or later. (\$^X==$^X)";
28             }
29 197         290 if (CORE::ord('A') == 193) {
30             die __FILE__, ": is not US-ASCII script (may be EBCDIC or EBCDIK script).";
31             }
32 197         31619 if (CORE::ord('A') != 0x41) {
33             die __FILE__, ": is not US-ASCII script (must be US-ASCII script).";
34             }
35             }
36              
37             BEGIN {
38              
39             # instead of utf8.pm
40 197     197   12982 CORE::eval q{
  197     197   1213  
  197     64   340  
  197         30830  
  64         12723  
  71         13715  
  75         13477  
  72         11679  
  53         9635  
  59         10997  
41             no warnings qw(redefine);
42             *utf8::upgrade = sub { CORE::length $_[0] };
43             *utf8::downgrade = sub { 1 };
44             *utf8::encode = sub { };
45             *utf8::decode = sub { 1 };
46             *utf8::is_utf8 = sub { };
47             *utf8::valid = sub { 1 };
48             };
49 197 50       134414 if ($@) {
50 0         0 *utf8::upgrade = sub { CORE::length $_[0] };
  0         0  
51 0         0 *utf8::downgrade = sub { 1 };
  0         0  
52 0         0 *utf8::encode = sub { };
  0         0  
53 0         0 *utf8::decode = sub { 1 };
  0         0  
54 0         0 *utf8::is_utf8 = sub { };
  0         0  
55 0         0 *utf8::valid = sub { 1 };
  0         0  
56             }
57             }
58              
59             # instead of Symbol.pm
60             BEGIN {
61 197     197   501 my $genpkg = "Symbol::";
62 197         10900 my $genseq = 0;
63              
64             sub gensym () {
65 0     0 0 0 my $name = "GEN" . $genseq++;
66              
67             # here, no strict qw(refs); if strict.pm exists
68              
69 0         0 my $ref = \*{$genpkg . $name};
  0         0  
70 0         0 delete $$genpkg{$name};
71 0         0 return $ref;
72             }
73              
74             sub qualify ($;$) {
75 0     0 0 0 my ($name) = @_;
76 0 0 0     0 if (!ref($name) && (Char::Elatin1::index($name, '::') == -1) && (Char::Elatin1::index($name, "'") == -1)) {
      0        
77 0         0 my $pkg;
78 0         0 my %global = map {$_ => 1} qw(ARGV ARGVOUT ENV INC SIG STDERR STDIN STDOUT DATA);
  0         0  
79              
80             # Global names: special character, "^xyz", or other.
81 0 0 0     0 if ($name =~ /^(([^a-z])|(\^[a-z_]+))\z/i || $global{$name}) {
82             # RGS 2001-11-05 : translate leading ^X to control-char
83 0         0 $name =~ s/^\^([a-z_])/'qq(\c'.$1.')'/eei;
  0         0  
84 0         0 $pkg = "main";
85             }
86             else {
87 0 0       0 $pkg = (@_ > 1) ? $_[1] : caller;
88             }
89 0         0 $name = $pkg . "::" . $name;
90             }
91 0         0 return $name;
92             }
93              
94             sub qualify_to_ref ($;$) {
95              
96             # here, no strict qw(refs); if strict.pm exists
97              
98 0 0   0 0 0 return \*{ qualify $_[0], @_ > 1 ? $_[1] : caller };
  0         0  
99             }
100             }
101              
102             # Column: local $@
103             # in Chapter 9. Osaete okitai Perl no kiso
104             # of ISBN 10: 4798119172 | ISBN 13: 978-4798119175 MODAN Perl NYUMON
105             # (and so on)
106              
107             # use strict; if strict.pm exists
108             BEGIN {
109 197 50   197   490 if (CORE::eval { local $@; CORE::require strict }) {
  197         377  
  197         2039  
110 197         30287 strict::->import;
111             }
112             }
113              
114             # P.714 29.2.39. flock
115             # in Chapter 29: Functions
116             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
117              
118             # P.863 flock
119             # in Chapter 27: Functions
120             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
121              
122             sub LOCK_SH() {1}
123             sub LOCK_EX() {2}
124             sub LOCK_UN() {8}
125             sub LOCK_NB() {4}
126              
127             # instead of Carp.pm
128             sub carp;
129             sub croak;
130             sub cluck;
131             sub confess;
132              
133             # 6.18. Matching Multiple-Byte Characters
134             # in Chapter 6. Pattern Matching
135             # of ISBN 978-1-56592-243-3 Perl Perl Cookbook.
136             # (and so on)
137              
138             # regexp of character
139 197     197   14245 BEGIN { CORE::eval q{ use vars qw($your_char) } } $your_char = q{[\x00-\xFF]};
  197     197   1180  
  197         331  
  197         13379  
140 197     197   12387 BEGIN { CORE::eval q{ use vars qw($qq_char ) } } $qq_char = qr/\\c[\x40-\x5F]|\\?(?:$your_char)/oxms;
  197     197   1249  
  197         320  
  197         14150  
141 197     197   11823 BEGIN { CORE::eval q{ use vars qw($q_char ) } } $q_char = qr/$your_char/oxms;
  197     197   1103  
  197         320  
  197         16687  
142              
143             #
144             # Latin-1 character range per length
145             #
146             my %range_tr = ();
147              
148             #
149             # alias of encoding name
150             #
151 197     197   12236 BEGIN { CORE::eval q{ use vars qw($encoding_alias) } }
  197     197   1268  
  197         346  
  197         416903  
152              
153             #
154             # Latin-1 case conversion
155             #
156             my %lc = ();
157             @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)} =
158             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);
159             my %uc = ();
160             @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)} =
161             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);
162             my %fc = ();
163             @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)} =
164             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);
165              
166             if (0) {
167             }
168              
169             elsif (__PACKAGE__ =~ / \b Elatin1 \z/oxms) {
170             %range_tr = (
171             1 => [ [0x00..0xFF],
172             ],
173             );
174             $encoding_alias = qr/ \b (?: iso[-_ ]?8859-1 | iec[- ]?8859-1 | latin-?1 ) \b /oxmsi;
175              
176             %lc = (%lc,
177             "\xC0" => "\xE0", # LATIN LETTER A WITH GRAVE
178             "\xC1" => "\xE1", # LATIN LETTER A WITH ACUTE
179             "\xC2" => "\xE2", # LATIN LETTER A WITH CIRCUMFLEX
180             "\xC3" => "\xE3", # LATIN LETTER A WITH TILDE
181             "\xC4" => "\xE4", # LATIN LETTER A WITH DIAERESIS
182             "\xC5" => "\xE5", # LATIN LETTER A WITH RING ABOVE
183             "\xC6" => "\xE6", # LATIN LETTER AE
184             "\xC7" => "\xE7", # LATIN LETTER C WITH CEDILLA
185             "\xC8" => "\xE8", # LATIN LETTER E WITH GRAVE
186             "\xC9" => "\xE9", # LATIN LETTER E WITH ACUTE
187             "\xCA" => "\xEA", # LATIN LETTER E WITH CIRCUMFLEX
188             "\xCB" => "\xEB", # LATIN LETTER E WITH DIAERESIS
189             "\xCC" => "\xEC", # LATIN LETTER I WITH GRAVE
190             "\xCD" => "\xED", # LATIN LETTER I WITH ACUTE
191             "\xCE" => "\xEE", # LATIN LETTER I WITH CIRCUMFLEX
192             "\xCF" => "\xEF", # LATIN LETTER I WITH DIAERESIS
193             "\xD0" => "\xF0", # LATIN LETTER ETH (Icelandic)
194             "\xD1" => "\xF1", # LATIN LETTER N WITH TILDE
195             "\xD2" => "\xF2", # LATIN LETTER O WITH GRAVE
196             "\xD3" => "\xF3", # LATIN LETTER O WITH ACUTE
197             "\xD4" => "\xF4", # LATIN LETTER O WITH CIRCUMFLEX
198             "\xD5" => "\xF5", # LATIN LETTER O WITH TILDE
199             "\xD6" => "\xF6", # LATIN LETTER O WITH DIAERESIS
200             "\xD8" => "\xF8", # LATIN LETTER O WITH STROKE
201             "\xD9" => "\xF9", # LATIN LETTER U WITH GRAVE
202             "\xDA" => "\xFA", # LATIN LETTER U WITH ACUTE
203             "\xDB" => "\xFB", # LATIN LETTER U WITH CIRCUMFLEX
204             "\xDC" => "\xFC", # LATIN LETTER U WITH DIAERESIS
205             "\xDD" => "\xFD", # LATIN LETTER Y WITH ACUTE
206             "\xDE" => "\xFE", # LATIN LETTER THORN (Icelandic)
207             );
208              
209             %uc = (%uc,
210             "\xE0" => "\xC0", # LATIN LETTER A WITH GRAVE
211             "\xE1" => "\xC1", # LATIN LETTER A WITH ACUTE
212             "\xE2" => "\xC2", # LATIN LETTER A WITH CIRCUMFLEX
213             "\xE3" => "\xC3", # LATIN LETTER A WITH TILDE
214             "\xE4" => "\xC4", # LATIN LETTER A WITH DIAERESIS
215             "\xE5" => "\xC5", # LATIN LETTER A WITH RING ABOVE
216             "\xE6" => "\xC6", # LATIN LETTER AE
217             "\xE7" => "\xC7", # LATIN LETTER C WITH CEDILLA
218             "\xE8" => "\xC8", # LATIN LETTER E WITH GRAVE
219             "\xE9" => "\xC9", # LATIN LETTER E WITH ACUTE
220             "\xEA" => "\xCA", # LATIN LETTER E WITH CIRCUMFLEX
221             "\xEB" => "\xCB", # LATIN LETTER E WITH DIAERESIS
222             "\xEC" => "\xCC", # LATIN LETTER I WITH GRAVE
223             "\xED" => "\xCD", # LATIN LETTER I WITH ACUTE
224             "\xEE" => "\xCE", # LATIN LETTER I WITH CIRCUMFLEX
225             "\xEF" => "\xCF", # LATIN LETTER I WITH DIAERESIS
226             "\xF0" => "\xD0", # LATIN LETTER ETH (Icelandic)
227             "\xF1" => "\xD1", # LATIN LETTER N WITH TILDE
228             "\xF2" => "\xD2", # LATIN LETTER O WITH GRAVE
229             "\xF3" => "\xD3", # LATIN LETTER O WITH ACUTE
230             "\xF4" => "\xD4", # LATIN LETTER O WITH CIRCUMFLEX
231             "\xF5" => "\xD5", # LATIN LETTER O WITH TILDE
232             "\xF6" => "\xD6", # LATIN LETTER O WITH DIAERESIS
233             "\xF8" => "\xD8", # LATIN LETTER O WITH STROKE
234             "\xF9" => "\xD9", # LATIN LETTER U WITH GRAVE
235             "\xFA" => "\xDA", # LATIN LETTER U WITH ACUTE
236             "\xFB" => "\xDB", # LATIN LETTER U WITH CIRCUMFLEX
237             "\xFC" => "\xDC", # LATIN LETTER U WITH DIAERESIS
238             "\xFD" => "\xDD", # LATIN LETTER Y WITH ACUTE
239             "\xFE" => "\xDE", # LATIN LETTER THORN (Icelandic)
240             );
241              
242             %fc = (%fc,
243             "\xC0" => "\xE0", # LATIN CAPITAL LETTER A WITH GRAVE --> LATIN SMALL LETTER A WITH GRAVE
244             "\xC1" => "\xE1", # LATIN CAPITAL LETTER A WITH ACUTE --> LATIN SMALL LETTER A WITH ACUTE
245             "\xC2" => "\xE2", # LATIN CAPITAL LETTER A WITH CIRCUMFLEX --> LATIN SMALL LETTER A WITH CIRCUMFLEX
246             "\xC3" => "\xE3", # LATIN CAPITAL LETTER A WITH TILDE --> LATIN SMALL LETTER A WITH TILDE
247             "\xC4" => "\xE4", # LATIN CAPITAL LETTER A WITH DIAERESIS --> LATIN SMALL LETTER A WITH DIAERESIS
248             "\xC5" => "\xE5", # LATIN CAPITAL LETTER A WITH RING ABOVE --> LATIN SMALL LETTER A WITH RING ABOVE
249             "\xC6" => "\xE6", # LATIN CAPITAL LETTER AE --> LATIN SMALL LETTER AE
250             "\xC7" => "\xE7", # LATIN CAPITAL LETTER C WITH CEDILLA --> LATIN SMALL LETTER C WITH CEDILLA
251             "\xC8" => "\xE8", # LATIN CAPITAL LETTER E WITH GRAVE --> LATIN SMALL LETTER E WITH GRAVE
252             "\xC9" => "\xE9", # LATIN CAPITAL LETTER E WITH ACUTE --> LATIN SMALL LETTER E WITH ACUTE
253             "\xCA" => "\xEA", # LATIN CAPITAL LETTER E WITH CIRCUMFLEX --> LATIN SMALL LETTER E WITH CIRCUMFLEX
254             "\xCB" => "\xEB", # LATIN CAPITAL LETTER E WITH DIAERESIS --> LATIN SMALL LETTER E WITH DIAERESIS
255             "\xCC" => "\xEC", # LATIN CAPITAL LETTER I WITH GRAVE --> LATIN SMALL LETTER I WITH GRAVE
256             "\xCD" => "\xED", # LATIN CAPITAL LETTER I WITH ACUTE --> LATIN SMALL LETTER I WITH ACUTE
257             "\xCE" => "\xEE", # LATIN CAPITAL LETTER I WITH CIRCUMFLEX --> LATIN SMALL LETTER I WITH CIRCUMFLEX
258             "\xCF" => "\xEF", # LATIN CAPITAL LETTER I WITH DIAERESIS --> LATIN SMALL LETTER I WITH DIAERESIS
259             "\xD0" => "\xF0", # LATIN CAPITAL LETTER ETH --> LATIN SMALL LETTER ETH
260             "\xD1" => "\xF1", # LATIN CAPITAL LETTER N WITH TILDE --> LATIN SMALL LETTER N WITH TILDE
261             "\xD2" => "\xF2", # LATIN CAPITAL LETTER O WITH GRAVE --> LATIN SMALL LETTER O WITH GRAVE
262             "\xD3" => "\xF3", # LATIN CAPITAL LETTER O WITH ACUTE --> LATIN SMALL LETTER O WITH ACUTE
263             "\xD4" => "\xF4", # LATIN CAPITAL LETTER O WITH CIRCUMFLEX --> LATIN SMALL LETTER O WITH CIRCUMFLEX
264             "\xD5" => "\xF5", # LATIN CAPITAL LETTER O WITH TILDE --> LATIN SMALL LETTER O WITH TILDE
265             "\xD6" => "\xF6", # LATIN CAPITAL LETTER O WITH DIAERESIS --> LATIN SMALL LETTER O WITH DIAERESIS
266             "\xD8" => "\xF8", # LATIN CAPITAL LETTER O WITH STROKE --> LATIN SMALL LETTER O WITH STROKE
267             "\xD9" => "\xF9", # LATIN CAPITAL LETTER U WITH GRAVE --> LATIN SMALL LETTER U WITH GRAVE
268             "\xDA" => "\xFA", # LATIN CAPITAL LETTER U WITH ACUTE --> LATIN SMALL LETTER U WITH ACUTE
269             "\xDB" => "\xFB", # LATIN CAPITAL LETTER U WITH CIRCUMFLEX --> LATIN SMALL LETTER U WITH CIRCUMFLEX
270             "\xDC" => "\xFC", # LATIN CAPITAL LETTER U WITH DIAERESIS --> LATIN SMALL LETTER U WITH DIAERESIS
271             "\xDD" => "\xFD", # LATIN CAPITAL LETTER Y WITH ACUTE --> LATIN SMALL LETTER Y WITH ACUTE
272             "\xDE" => "\xFE", # LATIN CAPITAL LETTER THORN --> LATIN SMALL LETTER THORN
273             "\xDF" => "\x73\x73", # LATIN SMALL LETTER SHARP S --> LATIN SMALL LETTER S, LATIN SMALL LETTER S
274             );
275             }
276              
277             else {
278             croak "Don't know my package name '@{[__PACKAGE__]}'";
279             }
280              
281             #
282             # @ARGV wildcard globbing
283             #
284             sub import {
285              
286 0 0   0   0 if ($^O =~ /\A (?: MSWin32 | NetWare | symbian | dos ) \z/oxms) {
287 0         0 my @argv = ();
288 0         0 for (@ARGV) {
289              
290             # has space
291 0 0       0 if (/\A (?:$q_char)*? [ ] /oxms) {
    0          
292 0 0       0 if (my @glob = Char::Elatin1::glob(qq{"$_"})) {
293 0         0 push @argv, @glob;
294             }
295             else {
296 0         0 push @argv, $_;
297             }
298             }
299              
300             # has wildcard metachar
301             elsif (/\A (?:$q_char)*? [*?] /oxms) {
302 0 0       0 if (my @glob = Char::Elatin1::glob($_)) {
303 0         0 push @argv, @glob;
304             }
305             else {
306 0         0 push @argv, $_;
307             }
308             }
309              
310             # no wildcard globbing
311             else {
312 0         0 push @argv, $_;
313             }
314             }
315 0         0 @ARGV = @argv;
316             }
317             }
318              
319             # P.230 Care with Prototypes
320             # in Chapter 6: Subroutines
321             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
322             #
323             # If you aren't careful, you can get yourself into trouble with prototypes.
324             # But if you are careful, you can do a lot of neat things with them. This is
325             # all very powerful, of course, and should only be used in moderation to make
326             # the world a better place.
327              
328             # P.332 Care with Prototypes
329             # in Chapter 7: Subroutines
330             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
331             #
332             # If you aren't careful, you can get yourself into trouble with prototypes.
333             # But if you are careful, you can do a lot of neat things with them. This is
334             # all very powerful, of course, and should only be used in moderation to make
335             # the world a better place.
336              
337             #
338             # Prototypes of subroutines
339             #
340 0     0   0 sub unimport {}
341             sub Char::Elatin1::split(;$$$);
342             sub Char::Elatin1::tr($$$$;$);
343             sub Char::Elatin1::chop(@);
344             sub Char::Elatin1::index($$;$);
345             sub Char::Elatin1::rindex($$;$);
346             sub Char::Elatin1::lcfirst(@);
347             sub Char::Elatin1::lcfirst_();
348             sub Char::Elatin1::lc(@);
349             sub Char::Elatin1::lc_();
350             sub Char::Elatin1::ucfirst(@);
351             sub Char::Elatin1::ucfirst_();
352             sub Char::Elatin1::uc(@);
353             sub Char::Elatin1::uc_();
354             sub Char::Elatin1::fc(@);
355             sub Char::Elatin1::fc_();
356             sub Char::Elatin1::ignorecase;
357             sub Char::Elatin1::classic_character_class;
358             sub Char::Elatin1::capture;
359             sub Char::Elatin1::chr(;$);
360             sub Char::Elatin1::chr_();
361             sub Char::Elatin1::glob($);
362             sub Char::Elatin1::glob_();
363              
364             sub Char::Latin1::ord(;$);
365             sub Char::Latin1::ord_();
366             sub Char::Latin1::reverse(@);
367             sub Char::Latin1::getc(;*@);
368             sub Char::Latin1::length(;$);
369             sub Char::Latin1::substr($$;$$);
370             sub Char::Latin1::index($$;$);
371             sub Char::Latin1::rindex($$;$);
372             sub Char::Latin1::escape(;$);
373              
374             #
375             # Regexp work
376             #
377 197     197   16744 BEGIN { CORE::eval q{ use vars qw(
  197     197   1504  
  197         433  
  197         93450  
378             $Char::Latin1::re_a
379             $Char::Latin1::re_t
380             $Char::Latin1::re_n
381             $Char::Latin1::re_r
382             ) } }
383              
384             #
385             # Character class
386             #
387 197     197   15664 BEGIN { CORE::eval q{ use vars qw(
  197     197   1454  
  197         356  
  197         3408617  
388             $dot
389             $dot_s
390             $eD
391             $eS
392             $eW
393             $eH
394             $eV
395             $eR
396             $eN
397             $not_alnum
398             $not_alpha
399             $not_ascii
400             $not_blank
401             $not_cntrl
402             $not_digit
403             $not_graph
404             $not_lower
405             $not_lower_i
406             $not_print
407             $not_punct
408             $not_space
409             $not_upper
410             $not_upper_i
411             $not_word
412             $not_xdigit
413             $eb
414             $eB
415             ) } }
416              
417             ${Char::Elatin1::dot} = qr{(?:[^\x0A])};
418             ${Char::Elatin1::dot_s} = qr{(?:[\x00-\xFF])};
419             ${Char::Elatin1::eD} = qr{(?:[^0-9])};
420              
421             # Vertical tabs are now whitespace
422             # \s in a regex now matches a vertical tab in all circumstances.
423             # http://search.cpan.org/dist/perl-5.18.0/pod/perldelta.pod#Vertical_tabs_are_now_whitespace
424             # ${Char::Elatin1::eS} = qr{(?:[^\x09\x0A \x0C\x0D\x20])};
425             # ${Char::Elatin1::eS} = qr{(?:[^\x09\x0A\x0B\x0C\x0D\x20])};
426             ${Char::Elatin1::eS} = qr{(?:[^\s])};
427              
428             ${Char::Elatin1::eW} = qr{(?:[^0-9A-Z_a-z])};
429             ${Char::Elatin1::eH} = qr{(?:[^\x09\x20])};
430             ${Char::Elatin1::eV} = qr{(?:[^\x0A\x0B\x0C\x0D])};
431             ${Char::Elatin1::eR} = qr{(?:\x0D\x0A|[\x0A\x0D])};
432             ${Char::Elatin1::eN} = qr{(?:[^\x0A])};
433             ${Char::Elatin1::not_alnum} = qr{(?:[^\x30-\x39\x41-\x5A\x61-\x7A])};
434             ${Char::Elatin1::not_alpha} = qr{(?:[^\x41-\x5A\x61-\x7A])};
435             ${Char::Elatin1::not_ascii} = qr{(?:[^\x00-\x7F])};
436             ${Char::Elatin1::not_blank} = qr{(?:[^\x09\x20])};
437             ${Char::Elatin1::not_cntrl} = qr{(?:[^\x00-\x1F\x7F])};
438             ${Char::Elatin1::not_digit} = qr{(?:[^\x30-\x39])};
439             ${Char::Elatin1::not_graph} = qr{(?:[^\x21-\x7F])};
440             ${Char::Elatin1::not_lower} = qr{(?:[^\x61-\x7A])};
441             ${Char::Elatin1::not_lower_i} = qr{(?:[\x00-\xFF])};
442             ${Char::Elatin1::not_print} = qr{(?:[^\x20-\x7F])};
443             ${Char::Elatin1::not_punct} = qr{(?:[^\x21-\x2F\x3A-\x3F\x40\x5B-\x5F\x60\x7B-\x7E])};
444             ${Char::Elatin1::not_space} = qr{(?:[^\s\x0B])};
445             ${Char::Elatin1::not_upper} = qr{(?:[^\x41-\x5A])};
446             ${Char::Elatin1::not_upper_i} = qr{(?:[\x00-\xFF])};
447             ${Char::Elatin1::not_word} = qr{(?:[^\x30-\x39\x41-\x5A\x5F\x61-\x7A])};
448             ${Char::Elatin1::not_xdigit} = qr{(?:[^\x30-\x39\x41-\x46\x61-\x66])};
449             ${Char::Elatin1::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))};
450             ${Char::Elatin1::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]))};
451              
452             # avoid: Name "Char::Elatin1::foo" used only once: possible typo at here.
453             ${Char::Elatin1::dot} = ${Char::Elatin1::dot};
454             ${Char::Elatin1::dot_s} = ${Char::Elatin1::dot_s};
455             ${Char::Elatin1::eD} = ${Char::Elatin1::eD};
456             ${Char::Elatin1::eS} = ${Char::Elatin1::eS};
457             ${Char::Elatin1::eW} = ${Char::Elatin1::eW};
458             ${Char::Elatin1::eH} = ${Char::Elatin1::eH};
459             ${Char::Elatin1::eV} = ${Char::Elatin1::eV};
460             ${Char::Elatin1::eR} = ${Char::Elatin1::eR};
461             ${Char::Elatin1::eN} = ${Char::Elatin1::eN};
462             ${Char::Elatin1::not_alnum} = ${Char::Elatin1::not_alnum};
463             ${Char::Elatin1::not_alpha} = ${Char::Elatin1::not_alpha};
464             ${Char::Elatin1::not_ascii} = ${Char::Elatin1::not_ascii};
465             ${Char::Elatin1::not_blank} = ${Char::Elatin1::not_blank};
466             ${Char::Elatin1::not_cntrl} = ${Char::Elatin1::not_cntrl};
467             ${Char::Elatin1::not_digit} = ${Char::Elatin1::not_digit};
468             ${Char::Elatin1::not_graph} = ${Char::Elatin1::not_graph};
469             ${Char::Elatin1::not_lower} = ${Char::Elatin1::not_lower};
470             ${Char::Elatin1::not_lower_i} = ${Char::Elatin1::not_lower_i};
471             ${Char::Elatin1::not_print} = ${Char::Elatin1::not_print};
472             ${Char::Elatin1::not_punct} = ${Char::Elatin1::not_punct};
473             ${Char::Elatin1::not_space} = ${Char::Elatin1::not_space};
474             ${Char::Elatin1::not_upper} = ${Char::Elatin1::not_upper};
475             ${Char::Elatin1::not_upper_i} = ${Char::Elatin1::not_upper_i};
476             ${Char::Elatin1::not_word} = ${Char::Elatin1::not_word};
477             ${Char::Elatin1::not_xdigit} = ${Char::Elatin1::not_xdigit};
478             ${Char::Elatin1::eb} = ${Char::Elatin1::eb};
479             ${Char::Elatin1::eB} = ${Char::Elatin1::eB};
480              
481             #
482             # Latin-1 split
483             #
484             sub Char::Elatin1::split(;$$$) {
485              
486             # P.794 29.2.161. split
487             # in Chapter 29: Functions
488             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
489              
490             # P.951 split
491             # in Chapter 27: Functions
492             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
493              
494 0     0 0 0 my $pattern = $_[0];
495 0         0 my $string = $_[1];
496 0         0 my $limit = $_[2];
497              
498             # if $pattern is also omitted or is the literal space, " "
499 0 0       0 if (not defined $pattern) {
500 0         0 $pattern = ' ';
501             }
502              
503             # if $string is omitted, the function splits the $_ string
504 0 0       0 if (not defined $string) {
505 0 0       0 if (defined $_) {
506 0         0 $string = $_;
507             }
508             else {
509 0         0 $string = '';
510             }
511             }
512              
513 0         0 my @split = ();
514              
515             # when string is empty
516 0 0       0 if ($string eq '') {
    0          
517              
518             # resulting list value in list context
519 0 0       0 if (wantarray) {
520 0         0 return @split;
521             }
522              
523             # count of substrings in scalar context
524             else {
525 0 0       0 carp "Use of implicit split to \@_ is deprecated" if $^W;
526 0         0 @_ = @split;
527 0         0 return scalar @_;
528             }
529             }
530              
531             # split's first argument is more consistently interpreted
532             #
533             # After some changes earlier in v5.17, split's behavior has been simplified:
534             # if the PATTERN argument evaluates to a string containing one space, it is
535             # treated the way that a literal string containing one space once was.
536             # http://search.cpan.org/dist/perl-5.18.0/pod/perldelta.pod#split's_first_argument_is_more_consistently_interpreted
537              
538             # if $pattern is also omitted or is the literal space, " ", the function splits
539             # on whitespace, /\s+/, after skipping any leading whitespace
540             # (and so on)
541              
542             elsif ($pattern eq ' ') {
543 0 0       0 if (not defined $limit) {
544 0         0 return CORE::split(' ', $string);
545             }
546             else {
547 0         0 return CORE::split(' ', $string, $limit);
548             }
549             }
550              
551             # if $limit is negative, it is treated as if an arbitrarily large $limit has been specified
552 0 0 0     0 if ((not defined $limit) or ($limit <= 0)) {
    0          
553              
554             # a pattern capable of matching either the null string or something longer than the
555             # null string will split the value of $string into separate characters wherever it
556             # matches the null string between characters
557             # (and so on)
558              
559 0 0       0 if ('' =~ / \A $pattern \z /xms) {
560 0         0 my $last_subexpression_offsets = _last_subexpression_offsets($pattern);
561 0         0 my $limit = scalar(() = $string =~ /($pattern)/oxmsg);
562              
563             # P.1024 Appendix W.10 Multibyte Processing
564             # of ISBN 1-56592-224-7 CJKV Information Processing
565             # (and so on)
566              
567             # the //m modifier is assumed when you split on the pattern /^/
568             # (and so on)
569              
570             # V
571 0   0     0 while ((--$limit > 0) and ($string =~ s/\A((?:$q_char)+?)$pattern//m)) {
572              
573             # if the $pattern contains parentheses, then the substring matched by each pair of parentheses
574             # is included in the resulting list, interspersed with the fields that are ordinarily returned
575             # (and so on)
576              
577 0         0 local $@;
578 0         0 for (my $digit=1; $digit <= ($last_subexpression_offsets + 1); $digit++) {
579 0         0 push @split, CORE::eval('$' . $digit);
580             }
581             }
582             }
583              
584             else {
585 0         0 my $last_subexpression_offsets = _last_subexpression_offsets($pattern);
586              
587             # V
588 0         0 while ($string =~ s/\A((?:$q_char)*?)$pattern//m) {
589 0         0 local $@;
590 0         0 for (my $digit=1; $digit <= ($last_subexpression_offsets + 1); $digit++) {
591 0         0 push @split, CORE::eval('$' . $digit);
592             }
593             }
594             }
595             }
596              
597             elsif ($limit > 0) {
598 0 0       0 if ('' =~ / \A $pattern \z /xms) {
599 0         0 my $last_subexpression_offsets = _last_subexpression_offsets($pattern);
600 0   0     0 while ((--$limit > 0) and (CORE::length($string) > 0)) {
601              
602             # V
603 0 0       0 if ($string =~ s/\A((?:$q_char)+?)$pattern//m) {
604 0         0 local $@;
605 0         0 for (my $digit=1; $digit <= ($last_subexpression_offsets + 1); $digit++) {
606 0         0 push @split, CORE::eval('$' . $digit);
607             }
608             }
609             }
610             }
611             else {
612 0         0 my $last_subexpression_offsets = _last_subexpression_offsets($pattern);
613 0   0     0 while ((--$limit > 0) and (CORE::length($string) > 0)) {
614              
615             # V
616 0 0       0 if ($string =~ s/\A((?:$q_char)*?)$pattern//m) {
617 0         0 local $@;
618 0         0 for (my $digit=1; $digit <= ($last_subexpression_offsets + 1); $digit++) {
619 0         0 push @split, CORE::eval('$' . $digit);
620             }
621             }
622             }
623             }
624             }
625              
626 0 0       0 if (CORE::length($string) > 0) {
627 0         0 push @split, $string;
628             }
629              
630             # if $_[2] (NOT "$limit") is omitted or zero, trailing null fields are stripped from the result
631 0 0 0     0 if ((not defined $_[2]) or ($_[2] == 0)) {
632 0   0     0 while ((scalar(@split) >= 1) and ($split[-1] eq '')) {
633 0         0 pop @split;
634             }
635             }
636              
637             # resulting list value in list context
638 0 0       0 if (wantarray) {
639 0         0 return @split;
640             }
641              
642             # count of substrings in scalar context
643             else {
644 0 0       0 carp "Use of implicit split to \@_ is deprecated" if $^W;
645 0         0 @_ = @split;
646 0         0 return scalar @_;
647             }
648             }
649              
650             #
651             # get last subexpression offsets
652             #
653             sub _last_subexpression_offsets {
654 0     0   0 my $pattern = $_[0];
655              
656             # remove comment
657 0         0 $pattern =~ s/\(\?\# .*? \)//oxmsg;
658              
659 0         0 my $modifier = '';
660 0 0       0 if ($pattern =~ /\(\?\^? ([\-A-Za-z]+) :/oxms) {
661 0         0 $modifier = $1;
662 0         0 $modifier =~ s/-[A-Za-z]*//;
663             }
664              
665             # with /x modifier
666 0         0 my @char = ();
667 0 0       0 if ($modifier =~ /x/oxms) {
668 0         0 @char = $pattern =~ /\G(
669             \\ (?:$q_char) |
670             \# (?:$q_char)*? $ |
671             \[ (?: \\\] | (?:$q_char))+? \] |
672             \(\? |
673             (?:$q_char)
674             )/oxmsg;
675             }
676              
677             # without /x modifier
678             else {
679 0         0 @char = $pattern =~ /\G(
680             \\ (?:$q_char) |
681             \[ (?: \\\] | (?:$q_char))+? \] |
682             \(\? |
683             (?:$q_char)
684             )/oxmsg;
685             }
686              
687 0         0 return scalar grep { $_ eq '(' } @char;
  0         0  
688             }
689              
690             #
691             # Latin-1 transliteration (tr///)
692             #
693             sub Char::Elatin1::tr($$$$;$) {
694              
695 0     0 0 0 my $bind_operator = $_[1];
696 0         0 my $searchlist = $_[2];
697 0         0 my $replacementlist = $_[3];
698 0   0     0 my $modifier = $_[4] || '';
699              
700 0 0       0 if ($modifier =~ /r/oxms) {
701 0 0       0 if ($bind_operator =~ / !~ /oxms) {
702 0         0 croak "Using !~ with tr///r doesn't make sense";
703             }
704             }
705              
706 0         0 my @char = $_[0] =~ /\G ($q_char) /oxmsg;
707 0         0 my @searchlist = _charlist_tr($searchlist);
708 0         0 my @replacementlist = _charlist_tr($replacementlist);
709              
710 0         0 my %tr = ();
711 0         0 for (my $i=0; $i <= $#searchlist; $i++) {
712 0 0       0 if (not exists $tr{$searchlist[$i]}) {
713 0 0 0     0 if (defined $replacementlist[$i] and ($replacementlist[$i] ne '')) {
    0 0        
    0          
714 0         0 $tr{$searchlist[$i]} = $replacementlist[$i];
715             }
716             elsif ($modifier =~ /d/oxms) {
717 0         0 $tr{$searchlist[$i]} = '';
718             }
719             elsif (defined $replacementlist[-1] and ($replacementlist[-1] ne '')) {
720 0         0 $tr{$searchlist[$i]} = $replacementlist[-1];
721             }
722             else {
723 0         0 $tr{$searchlist[$i]} = $searchlist[$i];
724             }
725             }
726             }
727              
728 0         0 my $tr = 0;
729 0         0 my $replaced = '';
730 0 0       0 if ($modifier =~ /c/oxms) {
731 0         0 while (defined(my $char = shift @char)) {
732 0 0       0 if (not exists $tr{$char}) {
733 0 0       0 if (defined $replacementlist[0]) {
734 0         0 $replaced .= $replacementlist[0];
735             }
736 0         0 $tr++;
737 0 0       0 if ($modifier =~ /s/oxms) {
738 0   0     0 while (@char and (not exists $tr{$char[0]})) {
739 0         0 shift @char;
740 0         0 $tr++;
741             }
742             }
743             }
744             else {
745 0         0 $replaced .= $char;
746             }
747             }
748             }
749             else {
750 0         0 while (defined(my $char = shift @char)) {
751 0 0       0 if (exists $tr{$char}) {
752 0         0 $replaced .= $tr{$char};
753 0         0 $tr++;
754 0 0       0 if ($modifier =~ /s/oxms) {
755 0   0     0 while (@char and (exists $tr{$char[0]}) and ($tr{$char[0]} eq $tr{$char})) {
      0        
756 0         0 shift @char;
757 0         0 $tr++;
758             }
759             }
760             }
761             else {
762 0         0 $replaced .= $char;
763             }
764             }
765             }
766              
767 0 0       0 if ($modifier =~ /r/oxms) {
768 0         0 return $replaced;
769             }
770             else {
771 0         0 $_[0] = $replaced;
772 0 0       0 if ($bind_operator =~ / !~ /oxms) {
773 0         0 return not $tr;
774             }
775             else {
776 0         0 return $tr;
777             }
778             }
779             }
780              
781             #
782             # Latin-1 chop
783             #
784             sub Char::Elatin1::chop(@) {
785              
786 0     0 0 0 my $chop;
787 0 0       0 if (@_ == 0) {
788 0         0 my @char = /\G ($q_char) /oxmsg;
789 0         0 $chop = pop @char;
790 0         0 $_ = join '', @char;
791             }
792             else {
793 0         0 for (@_) {
794 0         0 my @char = /\G ($q_char) /oxmsg;
795 0         0 $chop = pop @char;
796 0         0 $_ = join '', @char;
797             }
798             }
799 0         0 return $chop;
800             }
801              
802             #
803             # Latin-1 index by octet
804             #
805             sub Char::Elatin1::index($$;$) {
806              
807 0     0 1 0 my($str,$substr,$position) = @_;
808 0   0     0 $position ||= 0;
809 0         0 my $pos = 0;
810              
811 0         0 while ($pos < CORE::length($str)) {
812 0 0       0 if (CORE::substr($str,$pos,CORE::length($substr)) eq $substr) {
813 0 0       0 if ($pos >= $position) {
814 0         0 return $pos;
815             }
816             }
817 0 0       0 if (CORE::substr($str,$pos) =~ /\A ($q_char) /oxms) {
818 0         0 $pos += CORE::length($1);
819             }
820             else {
821 0         0 $pos += 1;
822             }
823             }
824 0         0 return -1;
825             }
826              
827             #
828             # Latin-1 reverse index
829             #
830             sub Char::Elatin1::rindex($$;$) {
831              
832 0     0 0 0 my($str,$substr,$position) = @_;
833 0   0     0 $position ||= CORE::length($str) - 1;
834 0         0 my $pos = 0;
835 0         0 my $rindex = -1;
836              
837 0   0     0 while (($pos < CORE::length($str)) and ($pos <= $position)) {
838 0 0       0 if (CORE::substr($str,$pos,CORE::length($substr)) eq $substr) {
839 0         0 $rindex = $pos;
840             }
841 0 0       0 if (CORE::substr($str,$pos) =~ /\A ($q_char) /oxms) {
842 0         0 $pos += CORE::length($1);
843             }
844             else {
845 0         0 $pos += 1;
846             }
847             }
848 0         0 return $rindex;
849             }
850              
851             #
852             # Latin-1 lower case first with parameter
853             #
854             sub Char::Elatin1::lcfirst(@) {
855 0 0   0 0 0 if (@_) {
856 0         0 my $s = shift @_;
857 0 0 0     0 if (@_ and wantarray) {
858 0         0 return Char::Elatin1::lc(CORE::substr($s,0,1)) . CORE::substr($s,1), @_;
859             }
860             else {
861 0         0 return Char::Elatin1::lc(CORE::substr($s,0,1)) . CORE::substr($s,1);
862             }
863             }
864             else {
865 0         0 return Char::Elatin1::lc(CORE::substr($_,0,1)) . CORE::substr($_,1);
866             }
867             }
868              
869             #
870             # Latin-1 lower case first without parameter
871             #
872             sub Char::Elatin1::lcfirst_() {
873 0     0 0 0 return Char::Elatin1::lc(CORE::substr($_,0,1)) . CORE::substr($_,1);
874             }
875              
876             #
877             # Latin-1 lower case with parameter
878             #
879             sub Char::Elatin1::lc(@) {
880 0 0   0 0 0 if (@_) {
881 0         0 my $s = shift @_;
882 0 0 0     0 if (@_ and wantarray) {
883 0 0       0 return join('', map {defined($lc{$_}) ? $lc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg)), @_;
  0         0  
884             }
885             else {
886 0 0       0 return join('', map {defined($lc{$_}) ? $lc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg));
  0         0  
887             }
888             }
889             else {
890 0         0 return Char::Elatin1::lc_();
891             }
892             }
893              
894             #
895             # Latin-1 lower case without parameter
896             #
897             sub Char::Elatin1::lc_() {
898 0     0 0 0 my $s = $_;
899 0 0       0 return join '', map {defined($lc{$_}) ? $lc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg);
  0         0  
900             }
901              
902             #
903             # Latin-1 upper case first with parameter
904             #
905             sub Char::Elatin1::ucfirst(@) {
906 0 0   0 0 0 if (@_) {
907 0         0 my $s = shift @_;
908 0 0 0     0 if (@_ and wantarray) {
909 0         0 return Char::Elatin1::uc(CORE::substr($s,0,1)) . CORE::substr($s,1), @_;
910             }
911             else {
912 0         0 return Char::Elatin1::uc(CORE::substr($s,0,1)) . CORE::substr($s,1);
913             }
914             }
915             else {
916 0         0 return Char::Elatin1::uc(CORE::substr($_,0,1)) . CORE::substr($_,1);
917             }
918             }
919              
920             #
921             # Latin-1 upper case first without parameter
922             #
923             sub Char::Elatin1::ucfirst_() {
924 0     0 0 0 return Char::Elatin1::uc(CORE::substr($_,0,1)) . CORE::substr($_,1);
925             }
926              
927             #
928             # Latin-1 upper case with parameter
929             #
930             sub Char::Elatin1::uc(@) {
931 0 0   0 0 0 if (@_) {
932 0         0 my $s = shift @_;
933 0 0 0     0 if (@_ and wantarray) {
934 0 0       0 return join('', map {defined($uc{$_}) ? $uc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg)), @_;
  0         0  
935             }
936             else {
937 0 0       0 return join('', map {defined($uc{$_}) ? $uc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg));
  0         0  
938             }
939             }
940             else {
941 0         0 return Char::Elatin1::uc_();
942             }
943             }
944              
945             #
946             # Latin-1 upper case without parameter
947             #
948             sub Char::Elatin1::uc_() {
949 0     0 0 0 my $s = $_;
950 0 0       0 return join '', map {defined($uc{$_}) ? $uc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg);
  0         0  
951             }
952              
953             #
954             # Latin-1 fold case with parameter
955             #
956             sub Char::Elatin1::fc(@) {
957 0 0   0 0 0 if (@_) {
958 0         0 my $s = shift @_;
959 0 0 0     0 if (@_ and wantarray) {
960 0 0       0 return join('', map {defined($fc{$_}) ? $fc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg)), @_;
  0         0  
961             }
962             else {
963 0 0       0 return join('', map {defined($fc{$_}) ? $fc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg));
  0         0  
964             }
965             }
966             else {
967 0         0 return Char::Elatin1::fc_();
968             }
969             }
970              
971             #
972             # Latin-1 fold case without parameter
973             #
974             sub Char::Elatin1::fc_() {
975 0     0 0 0 my $s = $_;
976 0 0       0 return join '', map {defined($fc{$_}) ? $fc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg);
  0         0  
977             }
978              
979             #
980             # Latin-1 regexp capture
981             #
982             {
983             sub Char::Elatin1::capture {
984 0     0 1 0 return $_[0];
985             }
986             }
987              
988             #
989             # Latin-1 regexp ignore case modifier
990             #
991             sub Char::Elatin1::ignorecase {
992              
993 0     0 0 0 my @string = @_;
994 0         0 my $metachar = qr/[\@\\|[\]{]/oxms;
995              
996             # ignore case of $scalar or @array
997 0         0 for my $string (@string) {
998              
999             # split regexp
1000 0         0 my @char = $string =~ /\G(
1001             \[\^ |
1002             \\? (?:$q_char)
1003             )/oxmsg;
1004              
1005             # unescape character
1006 0         0 for (my $i=0; $i <= $#char; $i++) {
1007 0 0       0 next if not defined $char[$i];
1008              
1009             # open character class [...]
1010 0 0       0 if ($char[$i] eq '[') {
    0          
    0          
    0          
1011 0         0 my $left = $i;
1012              
1013             # [] make die "unmatched [] in regexp ..."
1014              
1015 0 0       0 if ($char[$i+1] eq ']') {
1016 0         0 $i++;
1017             }
1018              
1019 0         0 while (1) {
1020 0 0       0 if (++$i > $#char) {
1021 0         0 croak "Unmatched [] in regexp";
1022             }
1023 0 0       0 if ($char[$i] eq ']') {
1024 0         0 my $right = $i;
1025 0         0 my @charlist = charlist_qr(@char[$left+1..$right-1], 'i');
1026              
1027             # escape character
1028 0         0 for my $char (@charlist) {
1029 0 0       0 if (0) {
1030             }
1031              
1032 0         0 elsif ($char =~ /\A [.|)] \z/oxms) {
1033 0         0 $char = $1 . '\\' . $char;
1034             }
1035             }
1036              
1037             # [...]
1038 0         0 splice @char, $left, $right-$left+1, '(?:' . join('|', @charlist) . ')';
1039              
1040 0         0 $i = $left;
1041 0         0 last;
1042             }
1043             }
1044             }
1045              
1046             # open character class [^...]
1047             elsif ($char[$i] eq '[^') {
1048 0         0 my $left = $i;
1049              
1050             # [^] make die "unmatched [] in regexp ..."
1051              
1052 0 0       0 if ($char[$i+1] eq ']') {
1053 0         0 $i++;
1054             }
1055              
1056 0         0 while (1) {
1057 0 0       0 if (++$i > $#char) {
1058 0         0 croak "Unmatched [] in regexp";
1059             }
1060 0 0       0 if ($char[$i] eq ']') {
1061 0         0 my $right = $i;
1062 0         0 my @charlist = charlist_not_qr(@char[$left+1..$right-1], 'i');
1063              
1064             # escape character
1065 0         0 for my $char (@charlist) {
1066 0 0       0 if (0) {
1067             }
1068              
1069 0         0 elsif ($char =~ /\A [.|)] \z/oxms) {
1070 0         0 $char = '\\' . $char;
1071             }
1072             }
1073              
1074             # [^...]
1075 0         0 splice @char, $left, $right-$left+1, '(?!' . join('|', @charlist) . ")(?:$your_char)";
1076              
1077 0         0 $i = $left;
1078 0         0 last;
1079             }
1080             }
1081             }
1082              
1083             # rewrite classic character class or escape character
1084             elsif (my $char = classic_character_class($char[$i])) {
1085 0         0 $char[$i] = $char;
1086             }
1087              
1088             # with /i modifier
1089             elsif ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) {
1090 0         0 my $uc = Char::Elatin1::uc($char[$i]);
1091 0         0 my $fc = Char::Elatin1::fc($char[$i]);
1092 0 0       0 if ($uc ne $fc) {
1093 0 0       0 if (CORE::length($fc) == 1) {
1094 0         0 $char[$i] = '[' . $uc . $fc . ']';
1095             }
1096             else {
1097 0         0 $char[$i] = '(?:' . $uc . '|' . $fc . ')';
1098             }
1099             }
1100             }
1101             }
1102              
1103             # characterize
1104 0         0 for (my $i=0; $i <= $#char; $i++) {
1105 0 0       0 next if not defined $char[$i];
1106              
1107 0 0       0 if (0) {
1108             }
1109              
1110             # quote character before ? + * {
1111 0 0       0 elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
1112 0 0       0 if ($char[$i-1] !~ /\A [\x00-\xFF] \z/oxms) {
1113 0         0 $char[$i-1] = '(?:' . $char[$i-1] . ')';
1114             }
1115             }
1116             }
1117              
1118 0         0 $string = join '', @char;
1119             }
1120              
1121             # make regexp string
1122 0         0 return @string;
1123             }
1124              
1125             #
1126             # classic character class ( \D \S \W \d \s \w \C \X \H \V \h \v \R \N \b \B )
1127             #
1128             sub Char::Elatin1::classic_character_class {
1129 0     0 0 0 my($char) = @_;
1130              
1131             return {
1132 0   0     0 '\D' => '${Char::Elatin1::eD}',
1133             '\S' => '${Char::Elatin1::eS}',
1134             '\W' => '${Char::Elatin1::eW}',
1135             '\d' => '[0-9]',
1136              
1137             # Before Perl 5.6, \s only matched the five whitespace characters
1138             # tab, newline, form-feed, carriage return, and the space character
1139             # itself, which, taken together, is the character class [\t\n\f\r ].
1140              
1141             # Vertical tabs are now whitespace
1142             # \s in a regex now matches a vertical tab in all circumstances.
1143             # http://search.cpan.org/dist/perl-5.18.0/pod/perldelta.pod#Vertical_tabs_are_now_whitespace
1144             # \t \n \v \f \r space
1145             # '\s' => '[\x09\x0A \x0C\x0D\x20]',
1146             # '\s' => '[\x09\x0A\x0B\x0C\x0D\x20]',
1147             '\s' => '\s',
1148              
1149             '\w' => '[0-9A-Z_a-z]',
1150             '\C' => '[\x00-\xFF]',
1151             '\X' => 'X',
1152              
1153             # \h \v \H \V
1154              
1155             # P.114 Character Class Shortcuts
1156             # in Chapter 7: In the World of Regular Expressions
1157             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
1158              
1159             # P.357 13.2.3 Whitespace
1160             # in Chapter 13: perlrecharclass: Perl Regular Expression Character Classes
1161             # of ISBN-13: 978-1-906966-02-7 The Perl Language Reference Manual (for Perl version 5.12.1)
1162             #
1163             # 0x00009 CHARACTER TABULATION h s
1164             # 0x0000a LINE FEED (LF) vs
1165             # 0x0000b LINE TABULATION v
1166             # 0x0000c FORM FEED (FF) vs
1167             # 0x0000d CARRIAGE RETURN (CR) vs
1168             # 0x00020 SPACE h s
1169              
1170             # P.196 Table 5-9. Alphanumeric regex metasymbols
1171             # in Chapter 5. Pattern Matching
1172             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
1173              
1174             # (and so on)
1175              
1176             '\H' => '${Char::Elatin1::eH}',
1177             '\V' => '${Char::Elatin1::eV}',
1178             '\h' => '[\x09\x20]',
1179             '\v' => '[\x0A\x0B\x0C\x0D]',
1180             '\R' => '${Char::Elatin1::eR}',
1181              
1182             # \N
1183             #
1184             # http://perldoc.perl.org/perlre.html
1185             # Character Classes and other Special Escapes
1186             # Any character but \n (experimental). Not affected by /s modifier
1187              
1188             '\N' => '${Char::Elatin1::eN}',
1189              
1190             # \b \B
1191              
1192             # P.180 Boundaries: The \b and \B Assertions
1193             # in Chapter 5: Pattern Matching
1194             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
1195              
1196             # P.219 Boundaries: The \b and \B Assertions
1197             # in Chapter 5: Pattern Matching
1198             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
1199              
1200             # '\b' => '(?:(?<=\A|\W)(?=\w)|(?<=\w)(?=\W|\z))',
1201             '\b' => '${Char::Elatin1::eb}',
1202              
1203             # '\B' => '(?:(?<=\w)(?=\w)|(?<=\W)(?=\W))',
1204             '\B' => '${Char::Elatin1::eB}',
1205              
1206             }->{$char} || '';
1207             }
1208              
1209             #
1210             # prepare Latin-1 characters per length
1211             #
1212              
1213             # 1 octet characters
1214             my @chars1 = ();
1215             sub chars1 {
1216 0 0   0 0 0 if (@chars1) {
1217 0         0 return @chars1;
1218             }
1219 0 0       0 if (exists $range_tr{1}) {
1220 0         0 my @ranges = @{ $range_tr{1} };
  0         0  
1221 0         0 while (my @range = splice(@ranges,0,1)) {
1222 0         0 for my $oct0 (@{$range[0]}) {
  0         0  
1223 0         0 push @chars1, pack 'C', $oct0;
1224             }
1225             }
1226             }
1227 0         0 return @chars1;
1228             }
1229              
1230             # 2 octets characters
1231             my @chars2 = ();
1232             sub chars2 {
1233 0 0   0 0 0 if (@chars2) {
1234 0         0 return @chars2;
1235             }
1236 0 0       0 if (exists $range_tr{2}) {
1237 0         0 my @ranges = @{ $range_tr{2} };
  0         0  
1238 0         0 while (my @range = splice(@ranges,0,2)) {
1239 0         0 for my $oct0 (@{$range[0]}) {
  0         0  
1240 0         0 for my $oct1 (@{$range[1]}) {
  0         0  
1241 0         0 push @chars2, pack 'CC', $oct0,$oct1;
1242             }
1243             }
1244             }
1245             }
1246 0         0 return @chars2;
1247             }
1248              
1249             # 3 octets characters
1250             my @chars3 = ();
1251             sub chars3 {
1252 0 0   0 0 0 if (@chars3) {
1253 0         0 return @chars3;
1254             }
1255 0 0       0 if (exists $range_tr{3}) {
1256 0         0 my @ranges = @{ $range_tr{3} };
  0         0  
1257 0         0 while (my @range = splice(@ranges,0,3)) {
1258 0         0 for my $oct0 (@{$range[0]}) {
  0         0  
1259 0         0 for my $oct1 (@{$range[1]}) {
  0         0  
1260 0         0 for my $oct2 (@{$range[2]}) {
  0         0  
1261 0         0 push @chars3, pack 'CCC', $oct0,$oct1,$oct2;
1262             }
1263             }
1264             }
1265             }
1266             }
1267 0         0 return @chars3;
1268             }
1269              
1270             # 4 octets characters
1271             my @chars4 = ();
1272             sub chars4 {
1273 0 0   0 0 0 if (@chars4) {
1274 0         0 return @chars4;
1275             }
1276 0 0       0 if (exists $range_tr{4}) {
1277 0         0 my @ranges = @{ $range_tr{4} };
  0         0  
1278 0         0 while (my @range = splice(@ranges,0,4)) {
1279 0         0 for my $oct0 (@{$range[0]}) {
  0         0  
1280 0         0 for my $oct1 (@{$range[1]}) {
  0         0  
1281 0         0 for my $oct2 (@{$range[2]}) {
  0         0  
1282 0         0 for my $oct3 (@{$range[3]}) {
  0         0  
1283 0         0 push @chars4, pack 'CCCC', $oct0,$oct1,$oct2,$oct3;
1284             }
1285             }
1286             }
1287             }
1288             }
1289             }
1290 0         0 return @chars4;
1291             }
1292              
1293             #
1294             # Latin-1 open character list for tr
1295             #
1296             sub _charlist_tr {
1297              
1298 0     0   0 local $_ = shift @_;
1299              
1300             # unescape character
1301 0         0 my @char = ();
1302 0         0 while (not /\G \z/oxmsgc) {
1303 0 0       0 if (/\G (\\0?55|\\x2[Dd]|\\-) /oxmsgc) {
    0          
    0          
    0          
    0          
    0          
    0          
1304 0         0 push @char, '\-';
1305             }
1306             elsif (/\G \\ ([0-7]{2,3}) /oxmsgc) {
1307 0         0 push @char, CORE::chr(oct $1);
1308             }
1309             elsif (/\G \\x ([0-9A-Fa-f]{1,2}) /oxmsgc) {
1310 0         0 push @char, CORE::chr(hex $1);
1311             }
1312             elsif (/\G \\c ([\x40-\x5F]) /oxmsgc) {
1313 0         0 push @char, CORE::chr(CORE::ord($1) & 0x1F);
1314             }
1315             elsif (/\G (\\ [0nrtfbae]) /oxmsgc) {
1316 0         0 push @char, {
1317             '\0' => "\0",
1318             '\n' => "\n",
1319             '\r' => "\r",
1320             '\t' => "\t",
1321             '\f' => "\f",
1322             '\b' => "\x08", # \b means backspace in character class
1323             '\a' => "\a",
1324             '\e' => "\e",
1325             }->{$1};
1326             }
1327             elsif (/\G \\ ($q_char) /oxmsgc) {
1328 0         0 push @char, $1;
1329             }
1330             elsif (/\G ($q_char) /oxmsgc) {
1331 0         0 push @char, $1;
1332             }
1333             }
1334              
1335             # join separated multiple-octet
1336 0         0 @char = join('',@char) =~ /\G (\\-|$q_char) /oxmsg;
1337              
1338             # unescape '-'
1339 0         0 my @i = ();
1340 0         0 for my $i (0 .. $#char) {
1341 0 0       0 if ($char[$i] eq '\-') {
    0          
1342 0         0 $char[$i] = '-';
1343             }
1344             elsif ($char[$i] eq '-') {
1345 0 0 0     0 if ((0 < $i) and ($i < $#char)) {
1346 0         0 push @i, $i;
1347             }
1348             }
1349             }
1350              
1351             # open character list (reverse for splice)
1352 0         0 for my $i (CORE::reverse @i) {
1353 0         0 my @range = ();
1354              
1355             # range error
1356 0 0 0     0 if ((CORE::length($char[$i-1]) > CORE::length($char[$i+1])) or ($char[$i-1] gt $char[$i+1])) {
1357 0         0 croak "Invalid tr/// range \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1358             }
1359              
1360             # range of multiple-octet code
1361 0 0       0 if (CORE::length($char[$i-1]) == 1) {
    0          
    0          
    0          
1362 0 0       0 if (CORE::length($char[$i+1]) == 1) {
    0          
    0          
    0          
1363 0 0       0 push @range, grep {($char[$i-1] le $_) and ($_ le $char[$i+1])} chars1();
  0         0  
1364             }
1365             elsif (CORE::length($char[$i+1]) == 2) {
1366 0         0 push @range, grep {$char[$i-1] le $_} chars1();
  0         0  
1367 0         0 push @range, grep {$_ le $char[$i+1]} chars2();
  0         0  
1368             }
1369             elsif (CORE::length($char[$i+1]) == 3) {
1370 0         0 push @range, grep {$char[$i-1] le $_} chars1();
  0         0  
1371 0         0 push @range, chars2();
1372 0         0 push @range, grep {$_ le $char[$i+1]} chars3();
  0         0  
1373             }
1374             elsif (CORE::length($char[$i+1]) == 4) {
1375 0         0 push @range, grep {$char[$i-1] le $_} chars1();
  0         0  
1376 0         0 push @range, chars2();
1377 0         0 push @range, chars3();
1378 0         0 push @range, grep {$_ le $char[$i+1]} chars4();
  0         0  
1379             }
1380             else {
1381 0         0 croak "Invalid tr/// range (over 4octets) \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1382             }
1383             }
1384             elsif (CORE::length($char[$i-1]) == 2) {
1385 0 0       0 if (CORE::length($char[$i+1]) == 2) {
    0          
    0          
1386 0 0       0 push @range, grep {($char[$i-1] le $_) and ($_ le $char[$i+1])} chars2();
  0         0  
1387             }
1388             elsif (CORE::length($char[$i+1]) == 3) {
1389 0         0 push @range, grep {$char[$i-1] le $_} chars2();
  0         0  
1390 0         0 push @range, grep {$_ le $char[$i+1]} chars3();
  0         0  
1391             }
1392             elsif (CORE::length($char[$i+1]) == 4) {
1393 0         0 push @range, grep {$char[$i-1] le $_} chars2();
  0         0  
1394 0         0 push @range, chars3();
1395 0         0 push @range, grep {$_ le $char[$i+1]} chars4();
  0         0  
1396             }
1397             else {
1398 0         0 croak "Invalid tr/// range (over 4octets) \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1399             }
1400             }
1401             elsif (CORE::length($char[$i-1]) == 3) {
1402 0 0       0 if (CORE::length($char[$i+1]) == 3) {
    0          
1403 0 0       0 push @range, grep {($char[$i-1] le $_) and ($_ le $char[$i+1])} chars3();
  0         0  
1404             }
1405             elsif (CORE::length($char[$i+1]) == 4) {
1406 0         0 push @range, grep {$char[$i-1] le $_} chars3();
  0         0  
1407 0         0 push @range, grep {$_ le $char[$i+1]} chars4();
  0         0  
1408             }
1409             else {
1410 0         0 croak "Invalid tr/// range (over 4octets) \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1411             }
1412             }
1413             elsif (CORE::length($char[$i-1]) == 4) {
1414 0 0       0 if (CORE::length($char[$i+1]) == 4) {
1415 0 0       0 push @range, grep {($char[$i-1] le $_) and ($_ le $char[$i+1])} chars4();
  0         0  
1416             }
1417             else {
1418 0         0 croak "Invalid tr/// range (over 4octets) \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1419             }
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 0         0 splice @char, $i-1, 3, @range;
1426             }
1427              
1428 0         0 return @char;
1429             }
1430              
1431             #
1432             # Latin-1 open character class
1433             #
1434             sub _cc {
1435 0 0   0   0 if (scalar(@_) == 0) {
    0          
    0          
1436 0         0 die __FILE__, ": subroutine cc got no parameter.";
1437             }
1438             elsif (scalar(@_) == 1) {
1439 0         0 return sprintf('\x%02X',$_[0]);
1440             }
1441             elsif (scalar(@_) == 2) {
1442 0 0       0 if ($_[0] > $_[1]) {
    0          
    0          
1443 0         0 die __FILE__, ": subroutine cc got \$_[0] > \$_[1] parameters).";
1444             }
1445             elsif ($_[0] == $_[1]) {
1446 0         0 return sprintf('\x%02X',$_[0]);
1447             }
1448             elsif (($_[0]+1) == $_[1]) {
1449 0         0 return sprintf('[\\x%02X\\x%02X]',$_[0],$_[1]);
1450             }
1451             else {
1452 0         0 return sprintf('[\\x%02X-\\x%02X]',$_[0],$_[1]);
1453             }
1454             }
1455             else {
1456 0         0 die __FILE__, ": subroutine cc got 3 or more parameters (@{[scalar(@_)]} parameters).";
  0         0  
1457             }
1458             }
1459              
1460             #
1461             # Latin-1 octet range
1462             #
1463             sub _octets {
1464 0     0   0 my $length = shift @_;
1465              
1466 0 0       0 if ($length == 1) {
1467 0         0 my($a1) = unpack 'C', $_[0];
1468 0         0 my($z1) = unpack 'C', $_[1];
1469              
1470 0 0       0 if ($a1 > $z1) {
1471 0         0 croak 'Invalid [] range in regexp (CORE::ord(A) > CORE::ord(B)) ' . '\x' . unpack('H*',$a1) . '-\x' . unpack('H*',$z1);
1472             }
1473              
1474 0 0       0 if ($a1 == $z1) {
    0          
1475 0         0 return sprintf('\x%02X',$a1);
1476             }
1477             elsif (($a1+1) == $z1) {
1478 0         0 return sprintf('\x%02X\x%02X',$a1,$z1);
1479             }
1480             else {
1481 0         0 return sprintf('\x%02X-\x%02X',$a1,$z1);
1482             }
1483             }
1484             else {
1485 0         0 die __FILE__, ": subroutine _octets got invalid length ($length).";
1486             }
1487             }
1488              
1489             #
1490             # Latin-1 range regexp
1491             #
1492             sub _range_regexp {
1493 0     0   0 my($length,$first,$last) = @_;
1494              
1495 0         0 my @range_regexp = ();
1496 0 0       0 if (not exists $range_tr{$length}) {
1497 0         0 return @range_regexp;
1498             }
1499              
1500 0         0 my @ranges = @{ $range_tr{$length} };
  0         0  
1501 0         0 while (my @range = splice(@ranges,0,$length)) {
1502 0         0 my $min = '';
1503 0         0 my $max = '';
1504 0         0 for (my $i=0; $i < $length; $i++) {
1505 0         0 $min .= pack 'C', $range[$i][0];
1506 0         0 $max .= pack 'C', $range[$i][-1];
1507             }
1508              
1509             # min___max
1510             # FIRST_____________LAST
1511             # (nothing)
1512              
1513 0 0 0     0 if ($max lt $first) {
    0 0        
    0 0        
    0 0        
    0 0        
    0 0        
    0 0        
1514             }
1515              
1516             # **********
1517             # min_________max
1518             # FIRST_____________LAST
1519             # **********
1520              
1521             elsif (($min le $first) and ($first le $max) and ($max le $last)) {
1522 0         0 push @range_regexp, _octets($length,$first,$max,$min,$max);
1523             }
1524              
1525             # **********************
1526             # min________________max
1527             # FIRST_____________LAST
1528             # **********************
1529              
1530             elsif (($min eq $first) and ($max eq $last)) {
1531 0         0 push @range_regexp, _octets($length,$first,$last,$min,$max);
1532             }
1533              
1534             # *********
1535             # min___max
1536             # FIRST_____________LAST
1537             # *********
1538              
1539             elsif (($first le $min) and ($max le $last)) {
1540 0         0 push @range_regexp, _octets($length,$min,$max,$min,$max);
1541             }
1542              
1543             # **********************
1544             # min__________________________max
1545             # FIRST_____________LAST
1546             # **********************
1547              
1548             elsif (($min le $first) and ($last le $max)) {
1549 0         0 push @range_regexp, _octets($length,$first,$last,$min,$max);
1550             }
1551              
1552             # *********
1553             # min________max
1554             # FIRST_____________LAST
1555             # *********
1556              
1557             elsif (($first le $min) and ($min le $last) and ($last le $max)) {
1558 0         0 push @range_regexp, _octets($length,$min,$last,$min,$max);
1559             }
1560              
1561             # min___max
1562             # FIRST_____________LAST
1563             # (nothing)
1564              
1565             elsif ($last lt $min) {
1566             }
1567              
1568             else {
1569 0         0 die __FILE__, ": subroutine _range_regexp panic.";
1570             }
1571             }
1572              
1573 0         0 return @range_regexp;
1574             }
1575              
1576             #
1577             # Latin-1 open character list for qr and not qr
1578             #
1579             sub _charlist {
1580              
1581 0     0   0 my $modifier = pop @_;
1582 0         0 my @char = @_;
1583              
1584 0 0       0 my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
1585              
1586             # unescape character
1587 0         0 for (my $i=0; $i <= $#char; $i++) {
1588              
1589             # escape - to ...
1590 0 0 0     0 if ($char[$i] eq '-') {
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
1591 0 0 0     0 if ((0 < $i) and ($i < $#char)) {
1592 0         0 $char[$i] = '...';
1593             }
1594             }
1595              
1596             # octal escape sequence
1597             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
1598 0         0 $char[$i] = octchr($1);
1599             }
1600              
1601             # hexadecimal escape sequence
1602             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
1603 0         0 $char[$i] = hexchr($1);
1604             }
1605              
1606             # \N{CHARNAME} --> N\{CHARNAME}
1607             elsif ($char[$i] =~ /\A \\ (N) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
1608 0         0 $char[$i] = $1 . '\\' . $2;
1609             }
1610              
1611             # \p{PROPERTY} --> p\{PROPERTY}
1612             elsif ($char[$i] =~ /\A \\ (p) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
1613 0         0 $char[$i] = $1 . '\\' . $2;
1614             }
1615              
1616             # \P{PROPERTY} --> P\{PROPERTY}
1617             elsif ($char[$i] =~ /\A \\ (P) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
1618 0         0 $char[$i] = $1 . '\\' . $2;
1619             }
1620              
1621             # \p, \P, \X --> p, P, X
1622             elsif ($char[$i] =~ /\A \\ ( [pPX] ) \z/oxms) {
1623 0         0 $char[$i] = $1;
1624             }
1625              
1626             elsif ($char[$i] =~ /\A \\ ([0-7]{2,3}) \z/oxms) {
1627 0         0 $char[$i] = CORE::chr oct $1;
1628             }
1629             elsif ($char[$i] =~ /\A \\x ([0-9A-Fa-f]{1,2}) \z/oxms) {
1630 0         0 $char[$i] = CORE::chr hex $1;
1631             }
1632             elsif ($char[$i] =~ /\A \\c ([\x40-\x5F]) \z/oxms) {
1633 0         0 $char[$i] = CORE::chr(CORE::ord($1) & 0x1F);
1634             }
1635             elsif ($char[$i] =~ /\A (\\ [0nrtfbaedswDSWHVhvR]) \z/oxms) {
1636 0         0 $char[$i] = {
1637             '\0' => "\0",
1638             '\n' => "\n",
1639             '\r' => "\r",
1640             '\t' => "\t",
1641             '\f' => "\f",
1642             '\b' => "\x08", # \b means backspace in character class
1643             '\a' => "\a",
1644             '\e' => "\e",
1645             '\d' => '[0-9]',
1646              
1647             # Vertical tabs are now whitespace
1648             # \s in a regex now matches a vertical tab in all circumstances.
1649             # http://search.cpan.org/dist/perl-5.18.0/pod/perldelta.pod#Vertical_tabs_are_now_whitespace
1650             # \t \n \v \f \r space
1651             # '\s' => '[\x09\x0A \x0C\x0D\x20]',
1652             # '\s' => '[\x09\x0A\x0B\x0C\x0D\x20]',
1653             '\s' => '\s',
1654              
1655             '\w' => '[0-9A-Z_a-z]',
1656             '\D' => '${Char::Elatin1::eD}',
1657             '\S' => '${Char::Elatin1::eS}',
1658             '\W' => '${Char::Elatin1::eW}',
1659              
1660             '\H' => '${Char::Elatin1::eH}',
1661             '\V' => '${Char::Elatin1::eV}',
1662             '\h' => '[\x09\x20]',
1663             '\v' => '[\x0A\x0B\x0C\x0D]',
1664             '\R' => '${Char::Elatin1::eR}',
1665              
1666             }->{$1};
1667             }
1668              
1669             # POSIX-style character classes
1670             elsif ($ignorecase and ($char[$i] =~ /\A ( \[\: \^? (?:lower|upper) :\] ) \z/oxms)) {
1671 0         0 $char[$i] = {
1672              
1673             '[:lower:]' => '[\x41-\x5A\x61-\x7A]',
1674             '[:upper:]' => '[\x41-\x5A\x61-\x7A]',
1675             '[:^lower:]' => '${Char::Elatin1::not_lower_i}',
1676             '[:^upper:]' => '${Char::Elatin1::not_upper_i}',
1677              
1678             }->{$1};
1679             }
1680             elsif ($char[$i] =~ /\A ( \[\: \^? (?:alnum|alpha|ascii|blank|cntrl|digit|graph|lower|print|punct|space|upper|word|xdigit) :\] ) \z/oxms) {
1681 0         0 $char[$i] = {
1682              
1683             '[:alnum:]' => '[\x30-\x39\x41-\x5A\x61-\x7A]',
1684             '[:alpha:]' => '[\x41-\x5A\x61-\x7A]',
1685             '[:ascii:]' => '[\x00-\x7F]',
1686             '[:blank:]' => '[\x09\x20]',
1687             '[:cntrl:]' => '[\x00-\x1F\x7F]',
1688             '[:digit:]' => '[\x30-\x39]',
1689             '[:graph:]' => '[\x21-\x7F]',
1690             '[:lower:]' => '[\x61-\x7A]',
1691             '[:print:]' => '[\x20-\x7F]',
1692             '[:punct:]' => '[\x21-\x2F\x3A-\x3F\x40\x5B-\x5F\x60\x7B-\x7E]',
1693              
1694             # P.174 POSIX-Style Character Classes
1695             # in Chapter 5: Pattern Matching
1696             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
1697              
1698             # P.311 11.2.4 Character Classes and other Special Escapes
1699             # in Chapter 11: perlre: Perl regular expressions
1700             # of ISBN-13: 978-1-906966-02-7 The Perl Language Reference Manual (for Perl version 5.12.1)
1701              
1702             # P.210 POSIX-Style Character Classes
1703             # in Chapter 5: Pattern Matching
1704             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
1705              
1706             '[:space:]' => '[\s\x0B]', # "\s" plus vertical tab ("\cK")
1707              
1708             '[:upper:]' => '[\x41-\x5A]',
1709             '[:word:]' => '[\x30-\x39\x41-\x5A\x5F\x61-\x7A]',
1710             '[:xdigit:]' => '[\x30-\x39\x41-\x46\x61-\x66]',
1711             '[:^alnum:]' => '${Char::Elatin1::not_alnum}',
1712             '[:^alpha:]' => '${Char::Elatin1::not_alpha}',
1713             '[:^ascii:]' => '${Char::Elatin1::not_ascii}',
1714             '[:^blank:]' => '${Char::Elatin1::not_blank}',
1715             '[:^cntrl:]' => '${Char::Elatin1::not_cntrl}',
1716             '[:^digit:]' => '${Char::Elatin1::not_digit}',
1717             '[:^graph:]' => '${Char::Elatin1::not_graph}',
1718             '[:^lower:]' => '${Char::Elatin1::not_lower}',
1719             '[:^print:]' => '${Char::Elatin1::not_print}',
1720             '[:^punct:]' => '${Char::Elatin1::not_punct}',
1721             '[:^space:]' => '${Char::Elatin1::not_space}',
1722             '[:^upper:]' => '${Char::Elatin1::not_upper}',
1723             '[:^word:]' => '${Char::Elatin1::not_word}',
1724             '[:^xdigit:]' => '${Char::Elatin1::not_xdigit}',
1725              
1726             }->{$1};
1727             }
1728             elsif ($char[$i] =~ /\A \\ ($q_char) \z/oxms) {
1729 0         0 $char[$i] = $1;
1730             }
1731             }
1732              
1733             # open character list
1734 0         0 my @singleoctet = ();
1735 0         0 my @multipleoctet = ();
1736 0         0 for (my $i=0; $i <= $#char; ) {
1737              
1738             # escaped -
1739 0 0 0     0 if (defined($char[$i+1]) and ($char[$i+1] eq '...')) {
    0          
    0          
    0          
    0          
    0          
1740 0         0 $i += 1;
1741 0         0 next;
1742             }
1743              
1744             # make range regexp
1745             elsif ($char[$i] eq '...') {
1746              
1747             # range error
1748 0 0       0 if (CORE::length($char[$i-1]) > CORE::length($char[$i+1])) {
    0          
1749 0         0 croak 'Invalid [] range in regexp (length(A) > length(B)) ' . '\x' . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]);
1750             }
1751             elsif (CORE::length($char[$i-1]) == CORE::length($char[$i+1])) {
1752 0 0       0 if ($char[$i-1] gt $char[$i+1]) {
1753 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]);
1754             }
1755             }
1756              
1757             # make range regexp per length
1758 0         0 for my $length (CORE::length($char[$i-1]) .. CORE::length($char[$i+1])) {
1759 0         0 my @regexp = ();
1760              
1761             # is first and last
1762 0 0 0     0 if (($length == CORE::length($char[$i-1])) and ($length == CORE::length($char[$i+1]))) {
    0 0        
    0          
    0          
1763 0         0 push @regexp, _range_regexp($length, $char[$i-1], $char[$i+1]);
1764             }
1765              
1766             # is first
1767             elsif ($length == CORE::length($char[$i-1])) {
1768 0         0 push @regexp, _range_regexp($length, $char[$i-1], "\xFF" x $length);
1769             }
1770              
1771             # is inside in first and last
1772             elsif ((CORE::length($char[$i-1]) < $length) and ($length < CORE::length($char[$i+1]))) {
1773 0         0 push @regexp, _range_regexp($length, "\x00" x $length, "\xFF" x $length);
1774             }
1775              
1776             # is last
1777             elsif ($length == CORE::length($char[$i+1])) {
1778 0         0 push @regexp, _range_regexp($length, "\x00" x $length, $char[$i+1]);
1779             }
1780              
1781             else {
1782 0         0 die __FILE__, ": subroutine make_regexp panic.";
1783             }
1784              
1785 0 0       0 if ($length == 1) {
1786 0         0 push @singleoctet, @regexp;
1787             }
1788             else {
1789 0         0 push @multipleoctet, @regexp;
1790             }
1791             }
1792              
1793 0         0 $i += 2;
1794             }
1795              
1796             # with /i modifier
1797             elsif ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) {
1798 0 0       0 if ($modifier =~ /i/oxms) {
1799 0         0 my $uc = Char::Elatin1::uc($char[$i]);
1800 0         0 my $fc = Char::Elatin1::fc($char[$i]);
1801 0 0       0 if ($uc ne $fc) {
1802 0 0       0 if (CORE::length($fc) == 1) {
1803 0         0 push @singleoctet, $uc, $fc;
1804             }
1805             else {
1806 0         0 push @singleoctet, $uc;
1807 0         0 push @multipleoctet, $fc;
1808             }
1809             }
1810             else {
1811 0         0 push @singleoctet, $char[$i];
1812             }
1813             }
1814             else {
1815 0         0 push @singleoctet, $char[$i];
1816             }
1817 0         0 $i += 1;
1818             }
1819              
1820             # single character of single octet code
1821             elsif ($char[$i] =~ /\A (?: \\h ) \z/oxms) {
1822 0         0 push @singleoctet, "\t", "\x20";
1823 0         0 $i += 1;
1824             }
1825             elsif ($char[$i] =~ /\A (?: \\v ) \z/oxms) {
1826 0         0 push @singleoctet, "\x0A", "\x0B", "\x0C", "\x0D";
1827 0         0 $i += 1;
1828             }
1829             elsif ($char[$i] =~ /\A (?: \\d | \\s | \\w ) \z/oxms) {
1830 0         0 push @singleoctet, $char[$i];
1831 0         0 $i += 1;
1832             }
1833              
1834             # single character of multiple-octet code
1835             else {
1836 0         0 push @multipleoctet, $char[$i];
1837 0         0 $i += 1;
1838             }
1839             }
1840              
1841             # quote metachar
1842 0         0 for (@singleoctet) {
1843 0 0       0 if ($_ eq '...') {
    0          
    0          
    0          
    0          
1844 0         0 $_ = '-';
1845             }
1846             elsif (/\A \n \z/oxms) {
1847 0         0 $_ = '\n';
1848             }
1849             elsif (/\A \r \z/oxms) {
1850 0         0 $_ = '\r';
1851             }
1852             elsif (/\A ([\x00-\x20\x7F-\xFF]) \z/oxms) {
1853 0         0 $_ = sprintf('\x%02X', CORE::ord $1);
1854             }
1855             elsif (/\A [\x00-\xFF] \z/oxms) {
1856 0         0 $_ = quotemeta $_;
1857             }
1858             }
1859              
1860             # return character list
1861 0         0 return \@singleoctet, \@multipleoctet;
1862             }
1863              
1864             #
1865             # Latin-1 octal escape sequence
1866             #
1867             sub octchr {
1868 0     0 0 0 my($octdigit) = @_;
1869              
1870 0         0 my @binary = ();
1871 0         0 for my $octal (split(//,$octdigit)) {
1872 0         0 push @binary, {
1873             '0' => '000',
1874             '1' => '001',
1875             '2' => '010',
1876             '3' => '011',
1877             '4' => '100',
1878             '5' => '101',
1879             '6' => '110',
1880             '7' => '111',
1881             }->{$octal};
1882             }
1883 0         0 my $binary = join '', @binary;
1884              
1885 0         0 my $octchr = {
1886             # 1234567
1887             1 => pack('B*', "0000000$binary"),
1888             2 => pack('B*', "000000$binary"),
1889             3 => pack('B*', "00000$binary"),
1890             4 => pack('B*', "0000$binary"),
1891             5 => pack('B*', "000$binary"),
1892             6 => pack('B*', "00$binary"),
1893             7 => pack('B*', "0$binary"),
1894             0 => pack('B*', "$binary"),
1895              
1896             }->{CORE::length($binary) % 8};
1897              
1898 0         0 return $octchr;
1899             }
1900              
1901             #
1902             # Latin-1 hexadecimal escape sequence
1903             #
1904             sub hexchr {
1905 0     0 0 0 my($hexdigit) = @_;
1906              
1907 0         0 my $hexchr = {
1908             1 => pack('H*', "0$hexdigit"),
1909             0 => pack('H*', "$hexdigit"),
1910              
1911             }->{CORE::length($_[0]) % 2};
1912              
1913 0         0 return $hexchr;
1914             }
1915              
1916             #
1917             # Latin-1 open character list for qr
1918             #
1919             sub charlist_qr {
1920              
1921 0     0 0 0 my $modifier = pop @_;
1922 0         0 my @char = @_;
1923              
1924 0         0 my($singleoctet, $multipleoctet) = _charlist(@char, $modifier);
1925 0         0 my @singleoctet = @$singleoctet;
1926 0         0 my @multipleoctet = @$multipleoctet;
1927              
1928             # return character list
1929 0 0       0 if (scalar(@singleoctet) >= 1) {
1930              
1931             # with /i modifier
1932 0 0       0 if ($modifier =~ m/i/oxms) {
1933 0         0 my %singleoctet_ignorecase = ();
1934 0         0 for (@singleoctet) {
1935 0   0     0 while (s/ \A \\x(..) - \\x(..) //oxms or s/ \A \\x((..)) //oxms) {
1936 0         0 for my $ord (hex($1) .. hex($2)) {
1937 0         0 my $char = CORE::chr($ord);
1938 0         0 my $uc = Char::Elatin1::uc($char);
1939 0         0 my $fc = Char::Elatin1::fc($char);
1940 0 0       0 if ($uc eq $fc) {
1941 0         0 $singleoctet_ignorecase{unpack 'C*', $char} = 1;
1942             }
1943             else {
1944 0 0       0 if (CORE::length($fc) == 1) {
1945 0         0 $singleoctet_ignorecase{unpack 'C*', $uc} = 1;
1946 0         0 $singleoctet_ignorecase{unpack 'C*', $fc} = 1;
1947             }
1948             else {
1949 0         0 $singleoctet_ignorecase{unpack 'C*', $uc} = 1;
1950 0         0 push @multipleoctet, join '', map {sprintf('\x%02X',$_)} unpack 'C*', $fc;
  0         0  
1951             }
1952             }
1953             }
1954             }
1955 0 0       0 if ($_ ne '') {
1956 0         0 $singleoctet_ignorecase{unpack 'C*', $_} = 1;
1957             }
1958             }
1959 0         0 my $i = 0;
1960 0         0 my @singleoctet_ignorecase = ();
1961 0         0 for my $ord (0 .. 255) {
1962 0 0       0 if (exists $singleoctet_ignorecase{$ord}) {
1963 0         0 push @{$singleoctet_ignorecase[$i]}, $ord;
  0         0  
1964             }
1965             else {
1966 0         0 $i++;
1967             }
1968             }
1969 0         0 @singleoctet = ();
1970 0         0 for my $range (@singleoctet_ignorecase) {
1971 0 0       0 if (ref $range) {
1972 0 0       0 if (scalar(@{$range}) == 1) {
  0 0       0  
  0         0  
1973 0         0 push @singleoctet, sprintf('\x%02X', @{$range}[0]);
  0         0  
1974             }
1975             elsif (scalar(@{$range}) == 2) {
1976 0         0 push @singleoctet, sprintf('\x%02X\x%02X', @{$range}[0], @{$range}[-1]);
  0         0  
  0         0  
1977             }
1978             else {
1979 0         0 push @singleoctet, sprintf('\x%02X-\x%02X', @{$range}[0], @{$range}[-1]);
  0         0  
  0         0  
1980             }
1981             }
1982             }
1983             }
1984              
1985 0         0 my $not_anchor = '';
1986              
1987 0         0 push @multipleoctet, join('', $not_anchor, '[', @singleoctet, ']' );
1988             }
1989 0 0       0 if (scalar(@multipleoctet) >= 2) {
1990 0         0 return '(?:' . join('|', @multipleoctet) . ')';
1991             }
1992             else {
1993 0         0 return $multipleoctet[0];
1994             }
1995             }
1996              
1997             #
1998             # Latin-1 open character list for not qr
1999             #
2000             sub charlist_not_qr {
2001              
2002 0     0 0 0 my $modifier = pop @_;
2003 0         0 my @char = @_;
2004              
2005 0         0 my($singleoctet, $multipleoctet) = _charlist(@char, $modifier);
2006 0         0 my @singleoctet = @$singleoctet;
2007 0         0 my @multipleoctet = @$multipleoctet;
2008              
2009             # with /i modifier
2010 0 0       0 if ($modifier =~ m/i/oxms) {
2011 0         0 my %singleoctet_ignorecase = ();
2012 0         0 for (@singleoctet) {
2013 0   0     0 while (s/ \A \\x(..) - \\x(..) //oxms or s/ \A \\x((..)) //oxms) {
2014 0         0 for my $ord (hex($1) .. hex($2)) {
2015 0         0 my $char = CORE::chr($ord);
2016 0         0 my $uc = Char::Elatin1::uc($char);
2017 0         0 my $fc = Char::Elatin1::fc($char);
2018 0 0       0 if ($uc eq $fc) {
2019 0         0 $singleoctet_ignorecase{unpack 'C*', $char} = 1;
2020             }
2021             else {
2022 0 0       0 if (CORE::length($fc) == 1) {
2023 0         0 $singleoctet_ignorecase{unpack 'C*', $uc} = 1;
2024 0         0 $singleoctet_ignorecase{unpack 'C*', $fc} = 1;
2025             }
2026             else {
2027 0         0 $singleoctet_ignorecase{unpack 'C*', $uc} = 1;
2028 0         0 push @multipleoctet, join '', map {sprintf('\x%02X',$_)} unpack 'C*', $fc;
  0         0  
2029             }
2030             }
2031             }
2032             }
2033 0 0       0 if ($_ ne '') {
2034 0         0 $singleoctet_ignorecase{unpack 'C*', $_} = 1;
2035             }
2036             }
2037 0         0 my $i = 0;
2038 0         0 my @singleoctet_ignorecase = ();
2039 0         0 for my $ord (0 .. 255) {
2040 0 0       0 if (exists $singleoctet_ignorecase{$ord}) {
2041 0         0 push @{$singleoctet_ignorecase[$i]}, $ord;
  0         0  
2042             }
2043             else {
2044 0         0 $i++;
2045             }
2046             }
2047 0         0 @singleoctet = ();
2048 0         0 for my $range (@singleoctet_ignorecase) {
2049 0 0       0 if (ref $range) {
2050 0 0       0 if (scalar(@{$range}) == 1) {
  0 0       0  
  0         0  
2051 0         0 push @singleoctet, sprintf('\x%02X', @{$range}[0]);
  0         0  
2052             }
2053             elsif (scalar(@{$range}) == 2) {
2054 0         0 push @singleoctet, sprintf('\x%02X\x%02X', @{$range}[0], @{$range}[-1]);
  0         0  
  0         0  
2055             }
2056             else {
2057 0         0 push @singleoctet, sprintf('\x%02X-\x%02X', @{$range}[0], @{$range}[-1]);
  0         0  
  0         0  
2058             }
2059             }
2060             }
2061             }
2062              
2063             # return character list
2064 0 0       0 if (scalar(@multipleoctet) >= 1) {
2065 0 0       0 if (scalar(@singleoctet) >= 1) {
2066              
2067             # any character other than multiple-octet and single octet character class
2068 0         0 return '(?!' . join('|', @multipleoctet) . ')(?:[^' . join('', @singleoctet) . '])';
2069             }
2070             else {
2071              
2072             # any character other than multiple-octet character class
2073 0         0 return '(?!' . join('|', @multipleoctet) . ")(?:$your_char)";
2074             }
2075             }
2076             else {
2077 0 0       0 if (scalar(@singleoctet) >= 1) {
2078              
2079             # any character other than single octet character class
2080 0         0 return '(?:[^' . join('', @singleoctet) . '])';
2081             }
2082             else {
2083              
2084             # any character
2085 0         0 return "(?:$your_char)";
2086             }
2087             }
2088             }
2089              
2090             #
2091             # open file in read mode
2092             #
2093             sub _open_r {
2094 197     197   628 my(undef,$file) = @_;
2095 197         928 $file =~ s#\A (\s) #./$1#oxms;
2096 197   33     24557 return CORE::eval(q{open($_[0],'<',$_[1])}) ||
2097             open($_[0],"< $file\0");
2098             }
2099              
2100             #
2101             # open file in write mode
2102             #
2103             sub _open_w {
2104 0     0   0 my(undef,$file) = @_;
2105 0         0 $file =~ s#\A (\s) #./$1#oxms;
2106 0   0     0 return CORE::eval(q{open($_[0],'>',$_[1])}) ||
2107             open($_[0],"> $file\0");
2108             }
2109              
2110             #
2111             # open file in append mode
2112             #
2113             sub _open_a {
2114 0     0   0 my(undef,$file) = @_;
2115 0         0 $file =~ s#\A (\s) #./$1#oxms;
2116 0   0     0 return CORE::eval(q{open($_[0],'>>',$_[1])}) ||
2117             open($_[0],">> $file\0");
2118             }
2119              
2120             #
2121             # safe system
2122             #
2123             sub _systemx {
2124              
2125             # P.707 29.2.33. exec
2126             # in Chapter 29: Functions
2127             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
2128             #
2129             # Be aware that in older releases of Perl, exec (and system) did not flush
2130             # your output buffer, so you needed to enable command buffering by setting $|
2131             # on one or more filehandles to avoid lost output in the case of exec, or
2132             # misordererd output in the case of system. This situation was largely remedied
2133             # in the 5.6 release of Perl. (So, 5.005 release not yet.)
2134              
2135             # P.855 exec
2136             # in Chapter 27: Functions
2137             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
2138             #
2139             # In very old release of Perl (before v5.6), exec (and system) did not flush
2140             # your output buffer, so you needed to enable command buffering by setting $|
2141             # on one or more filehandles to avoid lost output with exec or misordered
2142             # output with system.
2143              
2144 197     197   732 $| = 1;
2145              
2146             # P.565 23.1.2. Cleaning Up Your Environment
2147             # in Chapter 23: Security
2148             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
2149              
2150             # P.656 Cleaning Up Your Environment
2151             # in Chapter 20: Security
2152             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
2153              
2154             # local $ENV{'PATH'} = '.';
2155 197         2181 local @ENV{qw(IFS CDPATH ENV BASH_ENV)}; # Make %ENV safer
2156              
2157             # P.707 29.2.33. exec
2158             # in Chapter 29: Functions
2159             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
2160             #
2161             # As we mentioned earlier, exec treats a discrete list of arguments as an
2162             # indication that it should bypass shell processing. However, there is one
2163             # place where you might still get tripped up. The exec call (and system, too)
2164             # will not distinguish between a single scalar argument and an array containing
2165             # only one element.
2166             #
2167             # @args = ("echo surprise"); # just one element in list
2168             # exec @args # still subject to shell escapes
2169             # or die "exec: $!"; # because @args == 1
2170             #
2171             # To avoid this, you can use the PATHNAME syntax, explicitly duplicating the
2172             # first argument as the pathname, which forces the rest of the arguments to be
2173             # interpreted as a list, even if there is only one of them:
2174             #
2175             # exec { $args[0] } @args # safe even with one-argument list
2176             # or die "can't exec @args: $!";
2177              
2178             # P.855 exec
2179             # in Chapter 27: Functions
2180             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
2181             #
2182             # As we mentioned earlier, exec treats a discrete list of arguments as a
2183             # directive to bypass shell processing. However, there is one place where
2184             # you might still get tripped up. The exec call (and system, too) cannot
2185             # distinguish between a single scalar argument and an array containing
2186             # only one element.
2187             #
2188             # @args = ("echo surprise"); # just one element in list
2189             # exec @args # still subject to shell escapes
2190             # || die "exec: $!"; # because @args == 1
2191             #
2192             # To avoid this, use the PATHNAME syntax, explicitly duplicating the first
2193             # argument as the pathname, which forces the rest of the arguments to be
2194             # interpreted as a list, even if there is only one of them:
2195             #
2196             # exec { $args[0] } @args # safe even with one-argument list
2197             # || die "can't exec @args: $!";
2198              
2199 197         418 return CORE::system { $_[0] } @_; # safe even with one-argument list
  197         23763432  
2200             }
2201              
2202             #
2203             # Latin-1 order to character (with parameter)
2204             #
2205             sub Char::Elatin1::chr(;$) {
2206              
2207 0 0   0 0   my $c = @_ ? $_[0] : $_;
2208              
2209 0 0         if ($c == 0x00) {
2210 0           return "\x00";
2211             }
2212             else {
2213 0           my @chr = ();
2214 0           while ($c > 0) {
2215 0           unshift @chr, ($c % 0x100);
2216 0           $c = int($c / 0x100);
2217             }
2218 0           return pack 'C*', @chr;
2219             }
2220             }
2221              
2222             #
2223             # Latin-1 order to character (without parameter)
2224             #
2225             sub Char::Elatin1::chr_() {
2226              
2227 0     0 0   my $c = $_;
2228              
2229 0 0         if ($c == 0x00) {
2230 0           return "\x00";
2231             }
2232             else {
2233 0           my @chr = ();
2234 0           while ($c > 0) {
2235 0           unshift @chr, ($c % 0x100);
2236 0           $c = int($c / 0x100);
2237             }
2238 0           return pack 'C*', @chr;
2239             }
2240             }
2241              
2242             #
2243             # Latin-1 path globbing (with parameter)
2244             #
2245             sub Char::Elatin1::glob($) {
2246              
2247 0 0   0 0   if (wantarray) {
2248 0           my @glob = _DOS_like_glob(@_);
2249 0           for my $glob (@glob) {
2250 0           $glob =~ s{ \A (?:\./)+ }{}oxms;
2251             }
2252 0           return @glob;
2253             }
2254             else {
2255 0           my $glob = _DOS_like_glob(@_);
2256 0           $glob =~ s{ \A (?:\./)+ }{}oxms;
2257 0           return $glob;
2258             }
2259             }
2260              
2261             #
2262             # Latin-1 path globbing (without parameter)
2263             #
2264             sub Char::Elatin1::glob_() {
2265              
2266 0 0   0 0   if (wantarray) {
2267 0           my @glob = _DOS_like_glob();
2268 0           for my $glob (@glob) {
2269 0           $glob =~ s{ \A (?:\./)+ }{}oxms;
2270             }
2271 0           return @glob;
2272             }
2273             else {
2274 0           my $glob = _DOS_like_glob();
2275 0           $glob =~ s{ \A (?:\./)+ }{}oxms;
2276 0           return $glob;
2277             }
2278             }
2279              
2280             #
2281             # Latin-1 path globbing via File::DosGlob 1.10
2282             #
2283             # Often I confuse "_dosglob" and "_doglob".
2284             # So, I renamed "_dosglob" to "_DOS_like_glob".
2285             #
2286             my %iter;
2287             my %entries;
2288             sub _DOS_like_glob {
2289              
2290             # context (keyed by second cxix argument provided by core)
2291 0     0     my($expr,$cxix) = @_;
2292              
2293             # glob without args defaults to $_
2294 0 0         $expr = $_ if not defined $expr;
2295              
2296             # represents the current user's home directory
2297             #
2298             # 7.3. Expanding Tildes in Filenames
2299             # in Chapter 7. File Access
2300             # of ISBN 0-596-00313-7 Perl Cookbook, 2nd Edition.
2301             #
2302             # and File::HomeDir, File::HomeDir::Windows module
2303              
2304             # DOS-like system
2305 0 0         if ($^O =~ /\A (?: MSWin32 | NetWare | symbian | dos ) \z/oxms) {
2306 0           $expr =~ s{ \A ~ (?= [^/\\] ) }
2307 0           { my_home_MSWin32() }oxmse;
2308             }
2309              
2310             # UNIX-like system
2311             else {
2312 0           $expr =~ s{ \A ~ ( (?:[^/])* ) }
2313 0 0 0       { $1 ? (CORE::eval(q{(getpwnam($1))[7]})||my_home()) : my_home() }oxmse;
2314             }
2315              
2316             # assume global context if not provided one
2317 0 0         $cxix = '_G_' if not defined $cxix;
2318 0 0         $iter{$cxix} = 0 if not exists $iter{$cxix};
2319              
2320             # if we're just beginning, do it all first
2321 0 0         if ($iter{$cxix} == 0) {
2322 0           $entries{$cxix} = [ _do_glob(1, _parse_line($expr)) ];
2323             }
2324              
2325             # chuck it all out, quick or slow
2326 0 0         if (wantarray) {
2327 0           delete $iter{$cxix};
2328 0           return @{delete $entries{$cxix}};
  0            
2329             }
2330             else {
2331 0 0         if ($iter{$cxix} = scalar @{$entries{$cxix}}) {
  0            
2332 0           return shift @{$entries{$cxix}};
  0            
2333             }
2334             else {
2335             # return undef for EOL
2336 0           delete $iter{$cxix};
2337 0           delete $entries{$cxix};
2338 0           return undef;
2339             }
2340             }
2341             }
2342              
2343             #
2344             # Latin-1 path globbing subroutine
2345             #
2346             sub _do_glob {
2347              
2348 0     0     my($cond,@expr) = @_;
2349 0           my @glob = ();
2350 0           my $fix_drive_relative_paths = 0;
2351              
2352             OUTER:
2353 0           for my $expr (@expr) {
2354 0 0         next OUTER if not defined $expr;
2355 0 0         next OUTER if $expr eq '';
2356              
2357 0           my @matched = ();
2358 0           my @globdir = ();
2359 0           my $head = '.';
2360 0           my $pathsep = '/';
2361 0           my $tail;
2362              
2363             # if argument is within quotes strip em and do no globbing
2364 0 0         if ($expr =~ /\A " ((?:$q_char)*) " \z/oxms) {
2365 0           $expr = $1;
2366 0 0         if ($cond eq 'd') {
2367 0 0         if (-d $expr) {
2368 0           push @glob, $expr;
2369             }
2370             }
2371             else {
2372 0 0         if (-e $expr) {
2373 0           push @glob, $expr;
2374             }
2375             }
2376 0           next OUTER;
2377             }
2378              
2379             # wildcards with a drive prefix such as h:*.pm must be changed
2380             # to h:./*.pm to expand correctly
2381 0 0         if ($^O =~ /\A (?: MSWin32 | NetWare | symbian | dos ) \z/oxms) {
2382 0 0         if ($expr =~ s# \A ((?:[A-Za-z]:)?) ([^/\\]) #$1./$2#oxms) {
2383 0           $fix_drive_relative_paths = 1;
2384             }
2385             }
2386              
2387 0 0         if (($head, $tail) = _parse_path($expr,$pathsep)) {
2388 0 0         if ($tail eq '') {
2389 0           push @glob, $expr;
2390 0           next OUTER;
2391             }
2392 0 0         if ($head =~ / \A (?:$q_char)*? [*?] /oxms) {
2393 0 0         if (@globdir = _do_glob('d', $head)) {
2394 0           push @glob, _do_glob($cond, map {"$_$pathsep$tail"} @globdir);
  0            
2395 0           next OUTER;
2396             }
2397             }
2398 0 0 0       if ($head eq '' or $head =~ /\A [A-Za-z]: \z/oxms) {
2399 0           $head .= $pathsep;
2400             }
2401 0           $expr = $tail;
2402             }
2403              
2404             # If file component has no wildcards, we can avoid opendir
2405 0 0         if ($expr !~ / \A (?:$q_char)*? [*?] /oxms) {
2406 0 0         if ($head eq '.') {
2407 0           $head = '';
2408             }
2409 0 0 0       if ($head ne '' and ($head =~ / \G ($q_char) /oxmsg)[-1] ne $pathsep) {
2410 0           $head .= $pathsep;
2411             }
2412 0           $head .= $expr;
2413 0 0         if ($cond eq 'd') {
2414 0 0         if (-d $head) {
2415 0           push @glob, $head;
2416             }
2417             }
2418             else {
2419 0 0         if (-e $head) {
2420 0           push @glob, $head;
2421             }
2422             }
2423 0           next OUTER;
2424             }
2425 0 0         opendir(*DIR, $head) or next OUTER;
2426 0           my @leaf = readdir DIR;
2427 0           closedir DIR;
2428              
2429 0 0         if ($head eq '.') {
2430 0           $head = '';
2431             }
2432 0 0 0       if ($head ne '' and ($head =~ / \G ($q_char) /oxmsg)[-1] ne $pathsep) {
2433 0           $head .= $pathsep;
2434             }
2435              
2436 0           my $pattern = '';
2437 0           while ($expr =~ / \G ($q_char) /oxgc) {
2438 0           my $char = $1;
2439              
2440             # 6.9. Matching Shell Globs as Regular Expressions
2441             # in Chapter 6. Pattern Matching
2442             # of ISBN 0-596-00313-7 Perl Cookbook, 2nd Edition.
2443             # (and so on)
2444              
2445 0 0         if ($char eq '*') {
    0          
    0          
2446 0           $pattern .= "(?:$your_char)*",
2447             }
2448             elsif ($char eq '?') {
2449 0           $pattern .= "(?:$your_char)?", # DOS style
2450             # $pattern .= "(?:$your_char)", # UNIX style
2451             }
2452             elsif ((my $fc = Char::Elatin1::fc($char)) ne $char) {
2453 0           $pattern .= $fc;
2454             }
2455             else {
2456 0           $pattern .= quotemeta $char;
2457             }
2458             }
2459 0     0     my $matchsub = sub { Char::Elatin1::fc($_[0]) =~ /\A $pattern \z/xms };
  0            
2460              
2461             # if ($@) {
2462             # print STDERR "$0: $@\n";
2463             # next OUTER;
2464             # }
2465              
2466             INNER:
2467 0           for my $leaf (@leaf) {
2468 0 0 0       if ($leaf eq '.' or $leaf eq '..') {
2469 0           next INNER;
2470             }
2471 0 0 0       if ($cond eq 'd' and not -d "$head$leaf") {
2472 0           next INNER;
2473             }
2474              
2475 0 0         if (&$matchsub($leaf)) {
2476 0           push @matched, "$head$leaf";
2477 0           next INNER;
2478             }
2479              
2480             # [DOS compatibility special case]
2481             # Failed, add a trailing dot and try again, but only...
2482              
2483 0 0 0       if (Char::Elatin1::index($leaf,'.') == -1 and # if name does not have a dot in it *and*
      0        
2484             CORE::length($leaf) <= 8 and # name is shorter than or equal to 8 chars *and*
2485             Char::Elatin1::index($pattern,'\\.') != -1 # pattern has a dot.
2486             ) {
2487 0 0         if (&$matchsub("$leaf.")) {
2488 0           push @matched, "$head$leaf";
2489 0           next INNER;
2490             }
2491             }
2492             }
2493 0 0         if (@matched) {
2494 0           push @glob, @matched;
2495             }
2496             }
2497 0 0         if ($fix_drive_relative_paths) {
2498 0           for my $glob (@glob) {
2499 0           $glob =~ s# \A ([A-Za-z]:) \./ #$1#oxms;
2500             }
2501             }
2502 0           return @glob;
2503             }
2504              
2505             #
2506             # Latin-1 parse line
2507             #
2508             sub _parse_line {
2509              
2510 0     0     my($line) = @_;
2511              
2512 0           $line .= ' ';
2513 0           my @piece = ();
2514 0           while ($line =~ /
2515             " ( (?: [^"] )* ) " \s+ |
2516             ( (?: [^"\s] )* ) \s+
2517             /oxmsg
2518             ) {
2519 0 0         push @piece, defined($1) ? $1 : $2;
2520             }
2521 0           return @piece;
2522             }
2523              
2524             #
2525             # Latin-1 parse path
2526             #
2527             sub _parse_path {
2528              
2529 0     0     my($path,$pathsep) = @_;
2530              
2531 0           $path .= '/';
2532 0           my @subpath = ();
2533 0           while ($path =~ /
2534             ((?: [^\/\\] )+?) [\/\\]
2535             /oxmsg
2536             ) {
2537 0           push @subpath, $1;
2538             }
2539              
2540 0           my $tail = pop @subpath;
2541 0           my $head = join $pathsep, @subpath;
2542 0           return $head, $tail;
2543             }
2544              
2545             #
2546             # via File::HomeDir::Windows 1.00
2547             #
2548             sub my_home_MSWin32 {
2549              
2550             # A lot of unix people and unix-derived tools rely on
2551             # the ability to overload HOME. We will support it too
2552             # so that they can replace raw HOME calls with File::HomeDir.
2553 0 0 0 0 0   if (exists $ENV{'HOME'} and $ENV{'HOME'}) {
    0 0        
    0 0        
      0        
      0        
2554 0           return $ENV{'HOME'};
2555             }
2556              
2557             # Do we have a user profile?
2558             elsif (exists $ENV{'USERPROFILE'} and $ENV{'USERPROFILE'}) {
2559 0           return $ENV{'USERPROFILE'};
2560             }
2561              
2562             # Some Windows use something like $ENV{'HOME'}
2563             elsif (exists $ENV{'HOMEDRIVE'} and exists $ENV{'HOMEPATH'} and $ENV{'HOMEDRIVE'} and $ENV{'HOMEPATH'}) {
2564 0           return join '', $ENV{'HOMEDRIVE'}, $ENV{'HOMEPATH'};
2565             }
2566              
2567 0           return undef;
2568             }
2569              
2570             #
2571             # via File::HomeDir::Unix 1.00
2572             #
2573             sub my_home {
2574 0     0 0   my $home;
2575              
2576 0 0 0       if (exists $ENV{'HOME'} and defined $ENV{'HOME'}) {
    0 0        
2577 0           $home = $ENV{'HOME'};
2578             }
2579              
2580             # This is from the original code, but I'm guessing
2581             # it means "login directory" and exists on some Unixes.
2582             elsif (exists $ENV{'LOGDIR'} and $ENV{'LOGDIR'}) {
2583 0           $home = $ENV{'LOGDIR'};
2584             }
2585              
2586             ### More-desperate methods
2587              
2588             # Light desperation on any (Unixish) platform
2589             else {
2590 0           $home = CORE::eval q{ (getpwuid($<))[7] };
2591             }
2592              
2593             # On Unix in general, a non-existant home means "no home"
2594             # For example, "nobody"-like users might use /nonexistant
2595 0 0 0       if (defined $home and ! -d($home)) {
2596 0           $home = undef;
2597             }
2598 0           return $home;
2599             }
2600              
2601             #
2602             # ${^PREMATCH}, $PREMATCH, $` the string preceding what was matched
2603             #
2604             sub Char::Elatin1::PREMATCH {
2605 0     0 0   return $`;
2606             }
2607              
2608             #
2609             # ${^MATCH}, $MATCH, $& the string that matched
2610             #
2611             sub Char::Elatin1::MATCH {
2612 0     0 0   return $&;
2613             }
2614              
2615             #
2616             # ${^POSTMATCH}, $POSTMATCH, $' the string following what was matched
2617             #
2618             sub Char::Elatin1::POSTMATCH {
2619 0     0 0   return $';
2620             }
2621              
2622             #
2623             # Latin-1 character to order (with parameter)
2624             #
2625             sub Char::Latin1::ord(;$) {
2626              
2627 0 0   0 1   local $_ = shift if @_;
2628              
2629 0 0         if (/\A ($q_char) /oxms) {
2630 0           my @ord = unpack 'C*', $1;
2631 0           my $ord = 0;
2632 0           while (my $o = shift @ord) {
2633 0           $ord = $ord * 0x100 + $o;
2634             }
2635 0           return $ord;
2636             }
2637             else {
2638 0           return CORE::ord $_;
2639             }
2640             }
2641              
2642             #
2643             # Latin-1 character to order (without parameter)
2644             #
2645             sub Char::Latin1::ord_() {
2646              
2647 0 0   0 0   if (/\A ($q_char) /oxms) {
2648 0           my @ord = unpack 'C*', $1;
2649 0           my $ord = 0;
2650 0           while (my $o = shift @ord) {
2651 0           $ord = $ord * 0x100 + $o;
2652             }
2653 0           return $ord;
2654             }
2655             else {
2656 0           return CORE::ord $_;
2657             }
2658             }
2659              
2660             #
2661             # Latin-1 reverse
2662             #
2663             sub Char::Latin1::reverse(@) {
2664              
2665 0 0   0 0   if (wantarray) {
2666 0           return CORE::reverse @_;
2667             }
2668             else {
2669              
2670             # One of us once cornered Larry in an elevator and asked him what
2671             # problem he was solving with this, but he looked as far off into
2672             # the distance as he could in an elevator and said, "It seemed like
2673             # a good idea at the time."
2674              
2675 0           return join '', CORE::reverse(join('',@_) =~ /\G ($q_char) /oxmsg);
2676             }
2677             }
2678              
2679             #
2680             # Latin-1 getc (with parameter, without parameter)
2681             #
2682             sub Char::Latin1::getc(;*@) {
2683              
2684 0     0 0   my($package) = caller;
2685 0 0         my $fh = @_ ? qualify_to_ref(shift,$package) : \*STDIN;
2686 0 0 0       croak 'Too many arguments for Char::Latin1::getc' if @_ and not wantarray;
2687              
2688 0           my @length = sort { $a <=> $b } keys %range_tr;
  0            
2689 0           my $getc = '';
2690 0           for my $length ($length[0] .. $length[-1]) {
2691 0           $getc .= CORE::getc($fh);
2692 0 0         if (exists $range_tr{CORE::length($getc)}) {
2693 0 0         if ($getc =~ /\A ${Char::Elatin1::dot_s} \z/oxms) {
2694 0 0         return wantarray ? ($getc,@_) : $getc;
2695             }
2696             }
2697             }
2698 0 0         return wantarray ? ($getc,@_) : $getc;
2699             }
2700              
2701             #
2702             # Latin-1 length by character
2703             #
2704             sub Char::Latin1::length(;$) {
2705              
2706 0 0   0 1   local $_ = shift if @_;
2707              
2708 0           local @_ = /\G ($q_char) /oxmsg;
2709 0           return scalar @_;
2710             }
2711              
2712             #
2713             # Latin-1 substr by character
2714             #
2715             BEGIN {
2716              
2717             # P.232 The lvalue Attribute
2718             # in Chapter 6: Subroutines
2719             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
2720              
2721             # P.336 The lvalue Attribute
2722             # in Chapter 7: Subroutines
2723             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
2724              
2725             # P.144 8.4 Lvalue subroutines
2726             # in Chapter 8: perlsub: Perl subroutines
2727             # of ISBN-13: 978-1-906966-02-7 The Perl Language Reference Manual (for Perl version 5.12.1)
2728              
2729 197 50 0 197 1 164080 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            
2730             # vv----------------*******
2731             sub Char::Latin1::substr($$;$$) %s {
2732              
2733             my @char = $_[0] =~ /\G ($q_char) /oxmsg;
2734              
2735             # If the substring is beyond either end of the string, substr() returns the undefined
2736             # value and produces a warning. When used as an lvalue, specifying a substring that
2737             # is entirely outside the string raises an exception.
2738             # http://perldoc.perl.org/functions/substr.html
2739              
2740             # A return with no argument returns the scalar value undef in scalar context,
2741             # an empty list () in list context, and (naturally) nothing at all in void
2742             # context.
2743              
2744             my $offset = $_[1];
2745             if (($offset > scalar(@char)) or ($offset < (-1 * scalar(@char)))) {
2746             return;
2747             }
2748              
2749             # substr($string,$offset,$length,$replacement)
2750             if (@_ == 4) {
2751             my(undef,undef,$length,$replacement) = @_;
2752             my $substr = join '', splice(@char, $offset, $length, $replacement);
2753             $_[0] = join '', @char;
2754              
2755             # return $substr; this doesn't work, don't say "return"
2756             $substr;
2757             }
2758              
2759             # substr($string,$offset,$length)
2760             elsif (@_ == 3) {
2761             my(undef,undef,$length) = @_;
2762             my $octet_offset = 0;
2763             my $octet_length = 0;
2764             if ($offset == 0) {
2765             $octet_offset = 0;
2766             }
2767             elsif ($offset > 0) {
2768             $octet_offset = CORE::length(join '', @char[0..$offset-1]);
2769             }
2770             else {
2771             $octet_offset = -1 * CORE::length(join '', @char[$#char+$offset+1..$#char]);
2772             }
2773             if ($length == 0) {
2774             $octet_length = 0;
2775             }
2776             elsif ($length > 0) {
2777             $octet_length = CORE::length(join '', @char[$offset..$offset+$length-1]);
2778             }
2779             else {
2780             $octet_length = -1 * CORE::length(join '', @char[$#char+$length+1..$#char]);
2781             }
2782             CORE::substr($_[0], $octet_offset, $octet_length);
2783             }
2784              
2785             # substr($string,$offset)
2786             else {
2787             my $octet_offset = 0;
2788             if ($offset == 0) {
2789             $octet_offset = 0;
2790             }
2791             elsif ($offset > 0) {
2792             $octet_offset = CORE::length(join '', @char[0..$offset-1]);
2793             }
2794             else {
2795             $octet_offset = -1 * CORE::length(join '', @char[$#char+$offset+1..$#char]);
2796             }
2797             CORE::substr($_[0], $octet_offset);
2798             }
2799             }
2800             END
2801             }
2802              
2803             #
2804             # Latin-1 index by character
2805             #
2806             sub Char::Latin1::index($$;$) {
2807              
2808 0     0 1   my $index;
2809 0 0         if (@_ == 3) {
2810 0           $index = Char::Elatin1::index($_[0], $_[1], CORE::length(Char::Latin1::substr($_[0], 0, $_[2])));
2811             }
2812             else {
2813 0           $index = Char::Elatin1::index($_[0], $_[1]);
2814             }
2815              
2816 0 0         if ($index == -1) {
2817 0           return -1;
2818             }
2819             else {
2820 0           return Char::Latin1::length(CORE::substr $_[0], 0, $index);
2821             }
2822             }
2823              
2824             #
2825             # Latin-1 rindex by character
2826             #
2827             sub Char::Latin1::rindex($$;$) {
2828              
2829 0     0 1   my $rindex;
2830 0 0         if (@_ == 3) {
2831 0           $rindex = Char::Elatin1::rindex($_[0], $_[1], CORE::length(Char::Latin1::substr($_[0], 0, $_[2])));
2832             }
2833             else {
2834 0           $rindex = Char::Elatin1::rindex($_[0], $_[1]);
2835             }
2836              
2837 0 0         if ($rindex == -1) {
2838 0           return -1;
2839             }
2840             else {
2841 0           return Char::Latin1::length(CORE::substr $_[0], 0, $rindex);
2842             }
2843             }
2844              
2845             # when 'm//', '/' means regexp match 'm//' and '?' means regexp match '??'
2846             # when 'div', '/' means division operator and '?' means conditional operator (condition ? then : else)
2847 197     197   20110 BEGIN { CORE::eval q{ use vars qw($slash) } } $slash = 'm//';
  197     197   2077  
  197         542  
  197         17841  
2848              
2849             # ord() to ord() or Char::Latin1::ord()
2850 197     197   14076 BEGIN { CORE::eval q{ use vars qw($function_ord) } } $function_ord = 'ord';
  197     197   1202  
  197         449  
  197         14011  
2851              
2852             # ord to ord or Char::Latin1::ord_
2853 197     197   12290 BEGIN { CORE::eval q{ use vars qw($function_ord_) } } $function_ord_ = 'ord';
  197     197   1150  
  197         389  
  197         12638  
2854              
2855             # reverse to reverse or Char::Latin1::reverse
2856 197     197   11756 BEGIN { CORE::eval q{ use vars qw($function_reverse) } } $function_reverse = 'reverse';
  197     197   1320  
  197         402  
  197         13100  
2857              
2858             # getc to getc or Char::Latin1::getc
2859 197     197   16314 BEGIN { CORE::eval q{ use vars qw($function_getc) } } $function_getc = 'getc';
  197     197   1119  
  197         369  
  197         14256  
2860              
2861             # P.1023 Appendix W.9 Multibyte Anchoring
2862             # of ISBN 1-56592-224-7 CJKV Information Processing
2863              
2864             my $anchor = '';
2865              
2866 197     197   12495 BEGIN { CORE::eval q{ use vars qw($nest) } }
  197     197   1227  
  197         670  
  197         12762433  
2867              
2868             # regexp of nested parens in qqXX
2869              
2870             # P.340 Matching Nested Constructs with Embedded Code
2871             # in Chapter 7: Perl
2872             # of ISBN 0-596-00289-0 Mastering Regular Expressions, Second edition
2873              
2874             my $qq_paren = qr{(?{local $nest=0}) (?>(?:
2875             \\c[\x40-\x5F] |
2876             \\ [\x00-\xFF] |
2877             [^()] |
2878             \( (?{$nest++}) |
2879             \) (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!))
2880             }xms;
2881             my $qq_brace = qr{(?{local $nest=0}) (?>(?:
2882             \\c[\x40-\x5F] |
2883             \\ [\x00-\xFF] |
2884             [^{}] |
2885             \{ (?{$nest++}) |
2886             \} (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!))
2887             }xms;
2888             my $qq_bracket = qr{(?{local $nest=0}) (?>(?:
2889             \\c[\x40-\x5F] |
2890             \\ [\x00-\xFF] |
2891             [^[\]] |
2892             \[ (?{$nest++}) |
2893             \] (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!))
2894             }xms;
2895             my $qq_angle = qr{(?{local $nest=0}) (?>(?:
2896             \\c[\x40-\x5F] |
2897             \\ [\x00-\xFF] |
2898             [^<>] |
2899             \< (?{$nest++}) |
2900             \> (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!))
2901             }xms;
2902             my $qq_scalar = qr{(?: \{ (?:$qq_brace)*? \} |
2903             (?: ::)? (?:
2904             [a-zA-Z_][a-zA-Z_0-9]*
2905             (?: ::[a-zA-Z_][a-zA-Z_0-9]* )* (?: \[ (?: \$\[ | \$\] | $qq_char )*? \] | \{ (?:$qq_brace)*? \} )*
2906             (?: (?: -> )? (?: [\$\@\%\&\*]\* | \$\#\* | [\@\%]? \[ (?: \$\[ | \$\] | $qq_char )*? \] | [\@\%\*]? \{ (?:$qq_brace)*? \} ) )*
2907             ))
2908             }xms;
2909             my $qq_variable = qr{(?: \{ (?:$qq_brace)*? \} |
2910             (?: ::)? (?:
2911             [0-9]+ |
2912             [^a-zA-Z_0-9\[\]] |
2913             ^[A-Z] |
2914             [a-zA-Z_][a-zA-Z_0-9]*
2915             (?: ::[a-zA-Z_][a-zA-Z_0-9]* )* (?: \[ (?: \$\[ | \$\] | $qq_char )*? \] | \{ (?:$qq_brace)*? \} )*
2916             (?: (?: -> )? (?: [\$\@\%\&\*]\* | \$\#\* | [\@\%]? \[ (?: \$\[ | \$\] | $qq_char )*? \] | [\@\%\*]? \{ (?:$qq_brace)*? \} ) )*
2917             ))
2918             }xms;
2919             my $qq_substr = qr{(?: Char::Latin1::substr | CORE::substr | substr ) \( $qq_paren \)
2920             }xms;
2921              
2922             # regexp of nested parens in qXX
2923             my $q_paren = qr{(?{local $nest=0}) (?>(?:
2924             [^()] |
2925             \( (?{$nest++}) |
2926             \) (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!))
2927             }xms;
2928             my $q_brace = qr{(?{local $nest=0}) (?>(?:
2929             [^{}] |
2930             \{ (?{$nest++}) |
2931             \} (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!))
2932             }xms;
2933             my $q_bracket = qr{(?{local $nest=0}) (?>(?:
2934             [^[\]] |
2935             \[ (?{$nest++}) |
2936             \] (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!))
2937             }xms;
2938             my $q_angle = qr{(?{local $nest=0}) (?>(?:
2939             [^<>] |
2940             \< (?{$nest++}) |
2941             \> (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!))
2942             }xms;
2943              
2944             my $matched = '';
2945             my $s_matched = '';
2946              
2947             my $tr_variable = ''; # variable of tr///
2948             my $sub_variable = ''; # variable of s///
2949             my $bind_operator = ''; # =~ or !~
2950              
2951             my @heredoc = (); # here document
2952             my @heredoc_delimiter = ();
2953             my $here_script = ''; # here script
2954              
2955             #
2956             # escape Latin-1 script
2957             #
2958             sub Char::Latin1::escape(;$) {
2959 0 0   0 0   local($_) = $_[0] if @_;
2960              
2961             # P.359 The Study Function
2962             # in Chapter 7: Perl
2963             # of ISBN 0-596-00289-0 Mastering Regular Expressions, Second edition
2964              
2965 0           study $_; # Yes, I studied study yesterday.
2966              
2967             # while all script
2968              
2969             # 6.14. Matching from Where the Last Pattern Left Off
2970             # in Chapter 6. Pattern Matching
2971             # of ISBN 0-596-00313-7 Perl Cookbook, 2nd Edition.
2972             # (and so on)
2973              
2974             # one member of Tag-team
2975             #
2976             # P.128 Start of match (or end of previous match): \G
2977             # P.130 Advanced Use of \G with Perl
2978             # in Chapter 3: Overview of Regular Expression Features and Flavors
2979             # P.255 Use leading anchors
2980             # P.256 Expose ^ and \G at the front expressions
2981             # in Chapter 6: Crafting an Efficient Expression
2982             # P.315 "Tag-team" matching with /gc
2983             # in Chapter 7: Perl
2984             # of ISBN 0-596-00289-0 Mastering Regular Expressions, Second edition
2985              
2986 0           my $e_script = '';
2987 0           while (not /\G \z/oxgc) { # member
2988 0           $e_script .= Char::Latin1::escape_token();
2989             }
2990              
2991 0           return $e_script;
2992             }
2993              
2994             #
2995             # escape Latin-1 token of script
2996             #
2997             sub Char::Latin1::escape_token {
2998              
2999             # \n output here document
3000              
3001 0     0 0   my $ignore_modules = join('|', qw(
3002             utf8
3003             bytes
3004             charnames
3005             I18N::Japanese
3006             I18N::Collate
3007             I18N::JExt
3008             File::DosGlob
3009             Wild
3010             Wildcard
3011             Japanese
3012             ));
3013              
3014             # another member of Tag-team
3015             #
3016             # P.315 "Tag-team" matching with /gc
3017             # in Chapter 7: Perl
3018             # of ISBN 0-596-00289-0 Mastering Regular Expressions, Second edition
3019              
3020 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          
3021 0           my $heredoc = '';
3022 0 0         if (scalar(@heredoc_delimiter) >= 1) {
3023 0           $slash = 'm//';
3024              
3025 0           $heredoc = join '', @heredoc;
3026 0           @heredoc = ();
3027              
3028             # skip here document
3029 0           for my $heredoc_delimiter (@heredoc_delimiter) {
3030 0           /\G .*? \n $heredoc_delimiter \n/xmsgc;
3031             }
3032 0           @heredoc_delimiter = ();
3033              
3034 0           $here_script = '';
3035             }
3036 0           return "\n" . $heredoc;
3037             }
3038              
3039             # ignore space, comment
3040 0           elsif (/\G (\s+|\#.*) /oxgc) { return $1; }
3041              
3042             # if (, elsif (, unless (, while (, until (, given (, and when (
3043              
3044             # given, when
3045              
3046             # P.225 The given Statement
3047             # in Chapter 15: Smart Matching and given-when
3048             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
3049              
3050             # P.133 The given Statement
3051             # in Chapter 4: Statements and Declarations
3052             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
3053              
3054             elsif (/\G ( (?: if | elsif | unless | while | until | given | when ) \s* \( ) /oxgc) {
3055 0           $slash = 'm//';
3056 0           return $1;
3057             }
3058              
3059             # scalar variable ($scalar = ...) =~ tr///;
3060             # scalar variable ($scalar = ...) =~ s///;
3061              
3062             # state
3063              
3064             # P.68 Persistent, Private Variables
3065             # in Chapter 4: Subroutines
3066             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
3067              
3068             # P.160 Persistent Lexically Scoped Variables: state
3069             # in Chapter 4: Statements and Declarations
3070             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
3071              
3072             # (and so on)
3073              
3074             elsif (/\G ( \( \s* (?: local \b | my \b | our \b | state \b )? \s* \$ $qq_scalar ) /oxgc) {
3075 0           my $e_string = e_string($1);
3076              
3077 0 0         if (/\G ( \s* = $qq_paren \) ) ( \s* (?: =~ | !~ ) \s* ) (?= (?: tr | y ) \b ) /oxgc) {
    0          
3078 0           $tr_variable = $e_string . e_string($1);
3079 0           $bind_operator = $2;
3080 0           $slash = 'm//';
3081 0           return '';
3082             }
3083             elsif (/\G ( \s* = $qq_paren \) ) ( \s* (?: =~ | !~ ) \s* ) (?= s \b ) /oxgc) {
3084 0           $sub_variable = $e_string . e_string($1);
3085 0           $bind_operator = $2;
3086 0           $slash = 'm//';
3087 0           return '';
3088             }
3089             else {
3090 0           $slash = 'div';
3091 0           return $e_string;
3092             }
3093             }
3094              
3095             # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Char::Elatin1::PREMATCH()
3096             elsif (/\G ( \$` | \$\{`\} | \$ \s* PREMATCH \b | \$ \s* \{ \s* PREMATCH \s* \} | \$ \s* \{\^PREMATCH\} ) /oxmsgc) {
3097 0           $slash = 'div';
3098 0           return q{Char::Elatin1::PREMATCH()};
3099             }
3100              
3101             # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Char::Elatin1::MATCH()
3102             elsif (/\G ( \$& | \$\{&\} | \$ \s* MATCH \b | \$ \s* \{ \s* MATCH \s* \} | \$ \s* \{\^MATCH\} ) /oxmsgc) {
3103 0           $slash = 'div';
3104 0           return q{Char::Elatin1::MATCH()};
3105             }
3106              
3107             # $', ${'} --> $', ${'}
3108             elsif (/\G ( \$' | \$\{'\} ) /oxmsgc) {
3109 0           $slash = 'div';
3110 0           return $1;
3111             }
3112              
3113             # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Char::Elatin1::POSTMATCH()
3114             elsif (/\G ( \$ \s* POSTMATCH \b | \$ \s* \{ \s* POSTMATCH \s* \} | \$ \s* \{\^POSTMATCH\} ) /oxmsgc) {
3115 0           $slash = 'div';
3116 0           return q{Char::Elatin1::POSTMATCH()};
3117             }
3118              
3119             # scalar variable $scalar =~ tr///;
3120             # scalar variable $scalar =~ s///;
3121             # substr() =~ tr///;
3122             # substr() =~ s///;
3123             elsif (/\G ( \$ $qq_scalar | $qq_substr ) /oxgc) {
3124 0           my $scalar = e_string($1);
3125              
3126 0 0         if (/\G ( \s* (?: =~ | !~ ) \s* ) (?= (?: tr | y ) \b ) /oxgc) {
    0          
3127 0           $tr_variable = $scalar;
3128 0           $bind_operator = $1;
3129 0           $slash = 'm//';
3130 0           return '';
3131             }
3132             elsif (/\G ( \s* (?: =~ | !~ ) \s* ) (?= s \b ) /oxgc) {
3133 0           $sub_variable = $scalar;
3134 0           $bind_operator = $1;
3135 0           $slash = 'm//';
3136 0           return '';
3137             }
3138             else {
3139 0           $slash = 'div';
3140 0           return $scalar;
3141             }
3142             }
3143              
3144             # end of statement
3145             elsif (/\G ( [,;] ) /oxgc) {
3146 0           $slash = 'm//';
3147              
3148             # clear tr/// variable
3149 0           $tr_variable = '';
3150              
3151             # clear s/// variable
3152 0           $sub_variable = '';
3153              
3154 0           $bind_operator = '';
3155              
3156 0           return $1;
3157             }
3158              
3159             # bareword
3160             elsif (/\G ( \{ \s* (?: tr | index | rindex | reverse ) \s* \} ) /oxmsgc) {
3161 0           return $1;
3162             }
3163              
3164             # $0 --> $0
3165             elsif (/\G ( \$ 0 ) /oxmsgc) {
3166 0           $slash = 'div';
3167 0           return $1;
3168             }
3169             elsif (/\G ( \$ \{ \s* 0 \s* \} ) /oxmsgc) {
3170 0           $slash = 'div';
3171 0           return $1;
3172             }
3173              
3174             # $$ --> $$
3175             elsif (/\G ( \$ \$ ) (?![\w\{]) /oxmsgc) {
3176 0           $slash = 'div';
3177 0           return $1;
3178             }
3179              
3180             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
3181             # $1, $2, $3 --> $1, $2, $3 otherwise
3182             elsif (/\G \$ ([1-9][0-9]*) /oxmsgc) {
3183 0           $slash = 'div';
3184 0           return e_capture($1);
3185             }
3186             elsif (/\G \$ \{ \s* ([1-9][0-9]*) \s* \} /oxmsgc) {
3187 0           $slash = 'div';
3188 0           return e_capture($1);
3189             }
3190              
3191             # $$foo[ ... ] --> $ $foo->[ ... ]
3192             elsif (/\G \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) ( \[ .+? \] ) /oxmsgc) {
3193 0           $slash = 'div';
3194 0           return e_capture($1.'->'.$2);
3195             }
3196              
3197             # $$foo{ ... } --> $ $foo->{ ... }
3198             elsif (/\G \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) ( \{ .+? \} ) /oxmsgc) {
3199 0           $slash = 'div';
3200 0           return e_capture($1.'->'.$2);
3201             }
3202              
3203             # $$foo
3204             elsif (/\G \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) /oxmsgc) {
3205 0           $slash = 'div';
3206 0           return e_capture($1);
3207             }
3208              
3209             # ${ foo }
3210             elsif (/\G \$ \s* \{ ( \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* ) \} /oxmsgc) {
3211 0           $slash = 'div';
3212 0           return '${' . $1 . '}';
3213             }
3214              
3215             # ${ ... }
3216             elsif (/\G \$ \s* \{ \s* ( $qq_brace ) \s* \} /oxmsgc) {
3217 0           $slash = 'div';
3218 0           return e_capture($1);
3219             }
3220              
3221             # variable or function
3222             # $ @ % & * $ #
3223             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) {
3224 0           $slash = 'div';
3225 0           return $1;
3226             }
3227             # $ $ $ $ $ $ $ $ $ $ $ $ $ $
3228             # $ @ # \ ' " / ? ( ) [ ] < >
3229             elsif (/\G ( \$[\$\@\#\\\'\"\/\?\(\)\[\]\<\>] ) /oxmsgc) {
3230 0           $slash = 'div';
3231 0           return $1;
3232             }
3233              
3234             # while ()
3235             elsif (/\G \b (while \s* \( \s* <[\$]?[A-Za-z_][A-Za-z_0-9]*> \s* \)) \b /oxgc) {
3236 0           return $1;
3237             }
3238              
3239             # while () --- glob
3240              
3241             # avoid "Error: Runtime exception" of perl version 5.005_03
3242              
3243             elsif (/\G \b while \s* \( \s* < ((?:[^>\0\a\e\f\n\r\t])+?) > \s* \) \b /oxgc) {
3244 0           return 'while ($_ = Char::Elatin1::glob("' . $1 . '"))';
3245             }
3246              
3247             # while (glob)
3248             elsif (/\G \b while \s* \( \s* glob \s* \) /oxgc) {
3249 0           return 'while ($_ = Char::Elatin1::glob_)';
3250             }
3251              
3252             # while (glob(WILDCARD))
3253             elsif (/\G \b while \s* \( \s* glob \b /oxgc) {
3254 0           return 'while ($_ = Char::Elatin1::glob';
3255             }
3256              
3257             # doit if, doit unless, doit while, doit until, doit for, doit when
3258 0           elsif (/\G \b ( if | unless | while | until | for | when ) \b /oxgc) { $slash = 'm//'; return $1; }
  0            
3259              
3260             # subroutines of package Char::Elatin1
3261 0           elsif (/\G \b (CORE:: | ->[ ]* (?: atan2 | [a-z]{2,})) \b /oxgc) { $slash = 'm//'; return $1; }
  0            
3262 0           elsif (/\G \b Char::Latin1::eval (?= \s* \{ ) /oxgc) { $slash = 'm//'; return 'eval'; }
  0            
3263 0           elsif (/\G \b Char::Latin1::eval \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'eval Char::Latin1::escape'; }
  0            
3264 0           elsif (/\G \b bytes::substr \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'substr'; }
  0            
3265 0           elsif (/\G \b chop \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'Char::Elatin1::chop'; }
  0            
3266 0           elsif (/\G \b bytes::index \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'index'; }
  0            
3267 0           elsif (/\G \b Char::Latin1::index \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'Char::Latin1::index'; }
  0            
3268 0           elsif (/\G \b index \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'Char::Elatin1::index'; }
  0            
3269 0           elsif (/\G \b bytes::rindex \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'rindex'; }
  0            
3270 0           elsif (/\G \b Char::Latin1::rindex \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'Char::Latin1::rindex'; }
  0            
3271 0           elsif (/\G \b rindex \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'Char::Elatin1::rindex'; }
  0            
3272 0           elsif (/\G \b lc (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Char::Elatin1::lc'; }
  0            
3273 0           elsif (/\G \b lcfirst (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Char::Elatin1::lcfirst'; }
  0            
3274 0           elsif (/\G \b uc (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Char::Elatin1::uc'; }
  0            
3275 0           elsif (/\G \b ucfirst (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Char::Elatin1::ucfirst'; }
  0            
3276 0           elsif (/\G \b fc (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Char::Elatin1::fc'; }
  0            
3277              
3278             # "-s '' ..." means file test "-s 'filename' ..." (not means "- s/// ...")
3279 0           elsif (/\G -s \s+ \s* (\") ((?:$qq_char)+?) (\") /oxgc) { $slash = 'm//'; return '-s ' . e_qq('', $1,$3,$2); }
  0            
3280 0           elsif (/\G -s \s+ qq \s* (\#) ((?:$qq_char)+?) (\#) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0            
3281 0           elsif (/\G -s \s+ qq \s* (\() ((?:$qq_paren)+?) (\)) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0            
3282 0           elsif (/\G -s \s+ qq \s* (\{) ((?:$qq_brace)+?) (\}) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0            
3283 0           elsif (/\G -s \s+ qq \s* (\[) ((?:$qq_bracket)+?) (\]) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0            
3284 0           elsif (/\G -s \s+ qq \s* (\<) ((?:$qq_angle)+?) (\>) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0            
3285 0           elsif (/\G -s \s+ qq \s* (\S) ((?:$qq_char)+?) (\1) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0            
3286              
3287 0           elsif (/\G -s \s+ \s* (\') ((?:\\\'|\\\\|$q_char)+?) (\') /oxgc) { $slash = 'm//'; return '-s ' . e_q ('', $1,$3,$2); }
  0            
3288 0           elsif (/\G -s \s+ q \s* (\#) ((?:\\\#|\\\\|$q_char)+?) (\#) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0            
3289 0           elsif (/\G -s \s+ q \s* (\() ((?:\\\)|\\\\|$q_paren)+?) (\)) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0            
3290 0           elsif (/\G -s \s+ q \s* (\{) ((?:\\\}|\\\\|$q_brace)+?) (\}) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0            
3291 0           elsif (/\G -s \s+ q \s* (\[) ((?:\\\]|\\\\|$q_bracket)+?) (\]) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0            
3292 0           elsif (/\G -s \s+ q \s* (\<) ((?:\\\>|\\\\|$q_angle)+?) (\>) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0            
3293 0           elsif (/\G -s \s+ q \s* (\S) ((?:\\\1|\\\\|$q_char)+?) (\1) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0            
3294              
3295             elsif (/\G -s \s* (\$ \w+(?: ::\w+)* (?: (?: ->)? (?: [\$\@\%\&\*]\* | \$\#\* | \( (?:$qq_paren)*? \) | [\@\%\*]? \{ (?:$qq_brace)+? \} | [\@\%]? \[ (?:$qq_bracket)+? \] ) )*) /oxgc)
3296 0           { $slash = 'm//'; return "-s $1"; }
  0            
3297 0           elsif (/\G -s \s* \( ((?:$qq_paren)*?) \) /oxgc) { $slash = 'm//'; return "-s ($1)"; }
  0            
3298 0           elsif (/\G -s (?= \s+ [a-z]+) /oxgc) { $slash = 'm//'; return '-s'; }
  0            
3299 0           elsif (/\G -s \s+ (\w+) /oxgc) { $slash = 'm//'; return "-s $1"; }
  0            
3300              
3301 0           elsif (/\G \b bytes::length (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'length'; }
  0            
3302 0           elsif (/\G \b bytes::chr (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'chr'; }
  0            
3303 0           elsif (/\G \b chr (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Char::Elatin1::chr'; }
  0            
3304 0           elsif (/\G \b bytes::ord (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $slash = 'div'; return 'ord'; }
  0            
3305 0           elsif (/\G \b ord (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $slash = 'div'; return $function_ord; }
  0            
3306 0           elsif (/\G \b glob (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Char::Elatin1::glob'; }
  0            
3307 0           elsif (/\G \b lc \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'Char::Elatin1::lc_'; }
  0            
3308 0           elsif (/\G \b lcfirst \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'Char::Elatin1::lcfirst_'; }
  0            
3309 0           elsif (/\G \b uc \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'Char::Elatin1::uc_'; }
  0            
3310 0           elsif (/\G \b ucfirst \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'Char::Elatin1::ucfirst_'; }
  0            
3311 0           elsif (/\G \b fc \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'Char::Elatin1::fc_'; }
  0            
3312 0           elsif (/\G -s \b (?! \s* => ) /oxgc) { $slash = 'm//'; return '-s '; }
  0            
3313              
3314 0           elsif (/\G \b bytes::length \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'length'; }
  0            
3315 0           elsif (/\G \b bytes::chr \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'chr'; }
  0            
3316 0           elsif (/\G \b chr \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'Char::Elatin1::chr_'; }
  0            
3317 0           elsif (/\G \b bytes::ord \b (?! \s* => ) /oxgc) { $slash = 'div'; return 'ord'; }
  0            
3318 0           elsif (/\G \b ord \b (?! \s* => ) /oxgc) { $slash = 'div'; return $function_ord_; }
  0            
3319 0           elsif (/\G \b glob \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'Char::Elatin1::glob_'; }
  0            
3320 0           elsif (/\G \b reverse \b (?! \s* => ) /oxgc) { $slash = 'm//'; return $function_reverse; }
  0            
3321 0           elsif (/\G \b getc \b (?! \s* => ) /oxgc) { $slash = 'm//'; return $function_getc; }
  0            
3322             # split
3323             elsif (/\G \b (split) \b (?! \s* => ) /oxgc) {
3324 0           $slash = 'm//';
3325              
3326 0           my $e = '';
3327 0           while (/\G ( \s+ | \( | \#.* ) /oxgc) {
3328 0           $e .= $1;
3329             }
3330              
3331             # end of split
3332 0 0         if (/\G (?= [,;\)\}\]] ) /oxgc) { return 'Char::Elatin1::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          
3333              
3334             # split scalar value
3335 0           elsif (/\G ( [\$\@\&\*] $qq_scalar ) /oxgc) { return 'Char::Elatin1::split' . $e . e_string($1); }
3336              
3337             # split literal space
3338 0           elsif (/\G \b qq (\#) [ ] (\#) /oxgc) { return 'Char::Elatin1::split' . $e . qq {qq$1 $2}; }
3339 0           elsif (/\G \b qq (\s*) (\() [ ] (\)) /oxgc) { return 'Char::Elatin1::split' . $e . qq{$1qq$2 $3}; }
3340 0           elsif (/\G \b qq (\s*) (\{) [ ] (\}) /oxgc) { return 'Char::Elatin1::split' . $e . qq{$1qq$2 $3}; }
3341 0           elsif (/\G \b qq (\s*) (\[) [ ] (\]) /oxgc) { return 'Char::Elatin1::split' . $e . qq{$1qq$2 $3}; }
3342 0           elsif (/\G \b qq (\s*) (\<) [ ] (\>) /oxgc) { return 'Char::Elatin1::split' . $e . qq{$1qq$2 $3}; }
3343 0           elsif (/\G \b qq (\s*) (\S) [ ] (\2) /oxgc) { return 'Char::Elatin1::split' . $e . qq{$1qq$2 $3}; }
3344 0           elsif (/\G \b q (\#) [ ] (\#) /oxgc) { return 'Char::Elatin1::split' . $e . qq {q$1 $2}; }
3345 0           elsif (/\G \b q (\s*) (\() [ ] (\)) /oxgc) { return 'Char::Elatin1::split' . $e . qq {$1q$2 $3}; }
3346 0           elsif (/\G \b q (\s*) (\{) [ ] (\}) /oxgc) { return 'Char::Elatin1::split' . $e . qq {$1q$2 $3}; }
3347 0           elsif (/\G \b q (\s*) (\[) [ ] (\]) /oxgc) { return 'Char::Elatin1::split' . $e . qq {$1q$2 $3}; }
3348 0           elsif (/\G \b q (\s*) (\<) [ ] (\>) /oxgc) { return 'Char::Elatin1::split' . $e . qq {$1q$2 $3}; }
3349 0           elsif (/\G \b q (\s*) (\S) [ ] (\2) /oxgc) { return 'Char::Elatin1::split' . $e . qq {$1q$2 $3}; }
3350 0           elsif (/\G ' [ ] ' /oxgc) { return 'Char::Elatin1::split' . $e . qq {' '}; }
3351 0           elsif (/\G " [ ] " /oxgc) { return 'Char::Elatin1::split' . $e . qq {" "}; }
3352              
3353             # split qq//
3354             elsif (/\G \b (qq) \b /oxgc) {
3355 0 0         if (/\G (\#) ((?:$qq_char)*?) (\#) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq# # --> qr # #
  0            
3356             else {
3357 0           while (not /\G \z/oxgc) {
3358 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
3359 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq ( ) --> qr ( )
3360 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq { } --> qr { }
3361 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq [ ] --> qr [ ]
3362 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq < > --> qr < >
3363 0           elsif (/\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) /oxgc) { return e_split($e.'qr','{','}',$2,''); } # qq | | --> qr { }
3364 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq * * --> qr * *
3365             }
3366 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3367             }
3368             }
3369              
3370             # split qr//
3371             elsif (/\G \b (qr) \b /oxgc) {
3372 0 0         if (/\G (\#) ((?:$qq_char)*?) (\#) ([imosxpadlubB]*) /oxgc) { return e_split ($e.'qr',$1,$3,$2,$4); } # qr# #
  0            
3373             else {
3374 0           while (not /\G \z/oxgc) {
3375 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
3376 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([imosxpadlubB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # qr ( )
3377 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([imosxpadlubB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # qr { }
3378 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([imosxpadlubB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # qr [ ]
3379 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([imosxpadlubB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # qr < >
3380 0           elsif (/\G (\') ((?:$qq_char)*?) (\') ([imosxpadlubB]*) /oxgc) { return e_split_q($e.'qr',$1, $3, $2,$4); } # qr ' '
3381 0           elsif (/\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ([imosxpadlubB]*) /oxgc) { return e_split ($e.'qr','{','}',$2,$4); } # qr | | --> qr { }
3382 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([imosxpadlubB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # qr * *
3383             }
3384 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3385             }
3386             }
3387              
3388             # split q//
3389             elsif (/\G \b (q) \b /oxgc) {
3390 0 0         if (/\G (\#) ((?:\\\#|\\\\|$q_char)*?) (\#) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q# # --> qr # #
  0            
3391             else {
3392 0           while (not /\G \z/oxgc) {
3393 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
3394 0           elsif (/\G (\() ((?:\\\\|\\\)|\\\(|$q_paren)*?) (\)) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q ( ) --> qr ( )
3395 0           elsif (/\G (\{) ((?:\\\\|\\\}|\\\{|$q_brace)*?) (\}) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q { } --> qr { }
3396 0           elsif (/\G (\[) ((?:\\\\|\\\]|\\\[|$q_bracket)*?) (\]) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q [ ] --> qr [ ]
3397 0           elsif (/\G (\<) ((?:\\\\|\\\>|\\\<|$q_angle)*?) (\>) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q < > --> qr < >
3398 0           elsif (/\G ([*\-:?\\^|]) ((?:$q_char)*?) (\1) /oxgc) { return e_split_q($e.'qr','{','}',$2,''); } # q | | --> qr { }
3399 0           elsif (/\G (\S) ((?:\\\\|\\\1| $q_char)*?) (\1) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q * * --> qr * *
3400             }
3401 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3402             }
3403             }
3404              
3405             # split m//
3406             elsif (/\G \b (m) \b /oxgc) {
3407 0 0         if (/\G (\#) ((?:$qq_char)*?) (\#) ([cgimosxpadlubB]*) /oxgc) { return e_split ($e.'qr',$1,$3,$2,$4); } # m# # --> qr # #
  0            
3408             else {
3409 0           while (not /\G \z/oxgc) {
3410 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
3411 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cgimosxpadlubB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # m ( ) --> qr ( )
3412 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cgimosxpadlubB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # m { } --> qr { }
3413 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cgimosxpadlubB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # m [ ] --> qr [ ]
3414 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cgimosxpadlubB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # m < > --> qr < >
3415 0           elsif (/\G (\') ((?:$qq_char)*?) (\') ([cgimosxpadlubB]*) /oxgc) { return e_split_q($e.'qr',$1, $3, $2,$4); } # m ' ' --> qr ' '
3416 0           elsif (/\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ([cgimosxpadlubB]*) /oxgc) { return e_split ($e.'qr','{','}',$2,$4); } # m | | --> qr { }
3417 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cgimosxpadlubB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # m * * --> qr * *
3418             }
3419 0           die __FILE__, ": Search pattern not terminated";
3420             }
3421             }
3422              
3423             # split ''
3424             elsif (/\G (\') /oxgc) {
3425 0           my $q_string = '';
3426 0           while (not /\G \z/oxgc) {
3427 0 0         if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0          
    0          
    0          
3428 0           elsif (/\G (\\\') /oxgc) { $q_string .= $1; } # splitqr'' --> split qr''
3429 0           elsif (/\G \' /oxgc) { return e_split_q($e.q{ qr},"'","'",$q_string,''); } # ' ' --> qr ' '
3430 0           elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3431             }
3432 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3433             }
3434              
3435             # split ""
3436             elsif (/\G (\") /oxgc) {
3437 0           my $qq_string = '';
3438 0           while (not /\G \z/oxgc) {
3439 0 0         if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0          
    0          
    0          
3440 0           elsif (/\G (\\\") /oxgc) { $qq_string .= $1; } # splitqr"" --> split qr""
3441 0           elsif (/\G \" /oxgc) { return e_split($e.q{ qr},'"','"',$qq_string,''); } # " " --> qr " "
3442 0           elsif (/\G ($q_char) /oxgc) { $qq_string .= $1; }
3443             }
3444 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3445             }
3446              
3447             # split //
3448             elsif (/\G (\/) /oxgc) {
3449 0           my $regexp = '';
3450 0           while (not /\G \z/oxgc) {
3451 0 0         if (/\G (\\\\) /oxgc) { $regexp .= $1; }
  0 0          
    0          
    0          
3452 0           elsif (/\G (\\\/) /oxgc) { $regexp .= $1; } # splitqr// --> split qr//
3453 0           elsif (/\G \/ ([cgimosxpadlubB]*) /oxgc) { return e_split($e.q{ qr}, '/','/',$regexp,$1); } # / / --> qr / /
3454 0           elsif (/\G ($q_char) /oxgc) { $regexp .= $1; }
3455             }
3456 0           die __FILE__, ": Search pattern not terminated";
3457             }
3458             }
3459              
3460             # tr/// or y///
3461              
3462             # about [cdsrbB]* (/B modifier)
3463             #
3464             # P.559 appendix C
3465             # of ISBN 4-89052-384-7 Programming perl
3466             # (Japanese title is: Perl puroguramingu)
3467              
3468             elsif (/\G \b ( tr | y ) \b /oxgc) {
3469 0           my $ope = $1;
3470              
3471             # $1 $2 $3 $4 $5 $6
3472 0 0         if (/\G (\#) ((?:$qq_char)*?) (\#) ((?:$qq_char)*?) (\#) ([cdsrbB]*) /oxgc) { # tr# # #
3473 0           my @tr = ($tr_variable,$2);
3474 0           return e_tr(@tr,'',$4,$6);
3475             }
3476             else {
3477 0           my $e = '';
3478 0           while (not /\G \z/oxgc) {
3479 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3480             elsif (/\G (\() ((?:$qq_paren)*?) (\)) /oxgc) {
3481 0           my @tr = ($tr_variable,$2);
3482 0           while (not /\G \z/oxgc) {
3483 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3484 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr ( ) ( )
3485 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr ( ) { }
3486 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr ( ) [ ]
3487 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr ( ) < >
3488 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr ( ) * *
3489             }
3490 0           die __FILE__, ": Transliteration replacement not terminated";
3491             }
3492             elsif (/\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) {
3493 0           my @tr = ($tr_variable,$2);
3494 0           while (not /\G \z/oxgc) {
3495 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3496 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr { } ( )
3497 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr { } { }
3498 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr { } [ ]
3499 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr { } < >
3500 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr { } * *
3501             }
3502 0           die __FILE__, ": Transliteration replacement not terminated";
3503             }
3504             elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) {
3505 0           my @tr = ($tr_variable,$2);
3506 0           while (not /\G \z/oxgc) {
3507 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3508 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr [ ] ( )
3509 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr [ ] { }
3510 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr [ ] [ ]
3511 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr [ ] < >
3512 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr [ ] * *
3513             }
3514 0           die __FILE__, ": Transliteration replacement not terminated";
3515             }
3516             elsif (/\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) {
3517 0           my @tr = ($tr_variable,$2);
3518 0           while (not /\G \z/oxgc) {
3519 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3520 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr < > ( )
3521 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr < > { }
3522 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr < > [ ]
3523 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr < > < >
3524 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr < > * *
3525             }
3526 0           die __FILE__, ": Transliteration replacement not terminated";
3527             }
3528             # $1 $2 $3 $4 $5 $6
3529             elsif (/\G (\S) ((?:$qq_char)*?) (\1) ((?:$qq_char)*?) (\1) ([cdsrbB]*) /oxgc) { # tr * * *
3530 0           my @tr = ($tr_variable,$2);
3531 0           return e_tr(@tr,'',$4,$6);
3532             }
3533             }
3534 0           die __FILE__, ": Transliteration pattern not terminated";
3535             }
3536             }
3537              
3538             # qq//
3539             elsif (/\G \b (qq) \b /oxgc) {
3540 0           my $ope = $1;
3541              
3542             # if (/\G (\#) ((?:$qq_char)*?) (\#) /oxgc) { return e_qq($ope,$1,$3,$2); } # qq# #
3543 0 0         if (/\G (\#) /oxgc) { # qq# #
3544 0           my $qq_string = '';
3545 0           while (not /\G \z/oxgc) {
3546 0 0         if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0          
    0          
    0          
3547 0           elsif (/\G (\\\#) /oxgc) { $qq_string .= $1; }
3548 0           elsif (/\G (\#) /oxgc) { return e_qq($ope,'#','#',$qq_string); }
3549 0           elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3550             }
3551 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3552             }
3553              
3554             else {
3555 0           my $e = '';
3556 0           while (not /\G \z/oxgc) {
3557 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3558              
3559             # elsif (/\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qq ( )
3560             elsif (/\G (\() /oxgc) { # qq ( )
3561 0           my $qq_string = '';
3562 0           local $nest = 1;
3563 0           while (not /\G \z/oxgc) {
3564 0 0         if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0          
    0          
    0          
    0          
3565 0           elsif (/\G (\\\)) /oxgc) { $qq_string .= $1; }
3566 0           elsif (/\G (\() /oxgc) { $qq_string .= $1; $nest++; }
  0            
3567             elsif (/\G (\)) /oxgc) {
3568 0 0         if (--$nest == 0) { return $e . e_qq($ope,'(',')',$qq_string); }
  0            
3569 0           else { $qq_string .= $1; }
3570             }
3571 0           elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3572             }
3573 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3574             }
3575              
3576             # elsif (/\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qq { }
3577             elsif (/\G (\{) /oxgc) { # qq { }
3578 0           my $qq_string = '';
3579 0           local $nest = 1;
3580 0           while (not /\G \z/oxgc) {
3581 0 0         if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0          
    0          
    0          
    0          
3582 0           elsif (/\G (\\\}) /oxgc) { $qq_string .= $1; }
3583 0           elsif (/\G (\{) /oxgc) { $qq_string .= $1; $nest++; }
  0            
3584             elsif (/\G (\}) /oxgc) {
3585 0 0         if (--$nest == 0) { return $e . e_qq($ope,'{','}',$qq_string); }
  0            
3586 0           else { $qq_string .= $1; }
3587             }
3588 0           elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3589             }
3590 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3591             }
3592              
3593             # elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qq [ ]
3594             elsif (/\G (\[) /oxgc) { # qq [ ]
3595 0           my $qq_string = '';
3596 0           local $nest = 1;
3597 0           while (not /\G \z/oxgc) {
3598 0 0         if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0          
    0          
    0          
    0          
3599 0           elsif (/\G (\\\]) /oxgc) { $qq_string .= $1; }
3600 0           elsif (/\G (\[) /oxgc) { $qq_string .= $1; $nest++; }
  0            
3601             elsif (/\G (\]) /oxgc) {
3602 0 0         if (--$nest == 0) { return $e . e_qq($ope,'[',']',$qq_string); }
  0            
3603 0           else { $qq_string .= $1; }
3604             }
3605 0           elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3606             }
3607 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3608             }
3609              
3610             # elsif (/\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qq < >
3611             elsif (/\G (\<) /oxgc) { # qq < >
3612 0           my $qq_string = '';
3613 0           local $nest = 1;
3614 0           while (not /\G \z/oxgc) {
3615 0 0         if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0          
    0          
    0          
    0          
3616 0           elsif (/\G (\\\>) /oxgc) { $qq_string .= $1; }
3617 0           elsif (/\G (\<) /oxgc) { $qq_string .= $1; $nest++; }
  0            
3618             elsif (/\G (\>) /oxgc) {
3619 0 0         if (--$nest == 0) { return $e . e_qq($ope,'<','>',$qq_string); }
  0            
3620 0           else { $qq_string .= $1; }
3621             }
3622 0           elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3623             }
3624 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3625             }
3626              
3627             # elsif (/\G (\S) ((?:$qq_char)*?) (\1) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qq * *
3628             elsif (/\G (\S) /oxgc) { # qq * *
3629 0           my $delimiter = $1;
3630 0           my $qq_string = '';
3631 0           while (not /\G \z/oxgc) {
3632 0 0         if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0          
    0          
    0          
3633 0           elsif (/\G (\\\Q$delimiter\E) /oxgc) { $qq_string .= $1; }
3634 0           elsif (/\G (\Q$delimiter\E) /oxgc) { return $e . e_qq($ope,$delimiter,$delimiter,$qq_string); }
3635 0           elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3636             }
3637 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3638             }
3639             }
3640 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3641             }
3642             }
3643              
3644             # qr//
3645             elsif (/\G \b (qr) \b /oxgc) {
3646 0           my $ope = $1;
3647 0 0         if (/\G (\#) ((?:$qq_char)*?) (\#) ([imosxpadlubB]*) /oxgc) { # qr# # #
3648 0           return e_qr($ope,$1,$3,$2,$4);
3649             }
3650             else {
3651 0           my $e = '';
3652 0           while (not /\G \z/oxgc) {
3653 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
3654 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([imosxpadlubB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # qr ( )
3655 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([imosxpadlubB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # qr { }
3656 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([imosxpadlubB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # qr [ ]
3657 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([imosxpadlubB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # qr < >
3658 0           elsif (/\G (\') ((?:$qq_char)*?) (\') ([imosxpadlubB]*) /oxgc) { return $e . e_qr_q($ope,$1, $3, $2,$4); } # qr ' '
3659 0           elsif (/\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ([imosxpadlubB]*) /oxgc) { return $e . e_qr ($ope,'{','}',$2,$4); } # qr | | --> qr { }
3660 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([imosxpadlubB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # qr * *
3661             }
3662 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3663             }
3664             }
3665              
3666             # qw//
3667             elsif (/\G \b (qw) \b /oxgc) {
3668 0           my $ope = $1;
3669 0 0         if (/\G (\#) (.*?) (\#) /oxmsgc) { # qw# #
3670 0           return e_qw($ope,$1,$3,$2);
3671             }
3672             else {
3673 0           my $e = '';
3674 0           while (not /\G \z/oxgc) {
3675 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
3676              
3677 0           elsif (/\G (\() ([^(]*?) (\)) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw ( )
3678 0           elsif (/\G (\() ((?:$q_paren)*?) (\)) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw ( )
3679              
3680 0           elsif (/\G (\{) ([^{]*?) (\}) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw { }
3681 0           elsif (/\G (\{) ((?:$q_brace)*?) (\}) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw { }
3682              
3683 0           elsif (/\G (\[) ([^[]*?) (\]) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw [ ]
3684 0           elsif (/\G (\[) ((?:$q_bracket)*?) (\]) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw [ ]
3685              
3686 0           elsif (/\G (\<) ([^<]*?) (\>) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw < >
3687 0           elsif (/\G (\<) ((?:$q_angle)*?) (\>) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw < >
3688              
3689 0           elsif (/\G ([\x21-\x3F]) (.*?) (\1) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw * *
3690 0           elsif (/\G (\S) ((?:$q_char)*?) (\1) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw * *
3691             }
3692 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3693             }
3694             }
3695              
3696             # qx//
3697             elsif (/\G \b (qx) \b /oxgc) {
3698 0           my $ope = $1;
3699 0 0         if (/\G (\#) ((?:$qq_char)*?) (\#) /oxgc) { # qx# #
3700 0           return e_qq($ope,$1,$3,$2);
3701             }
3702             else {
3703 0           my $e = '';
3704 0           while (not /\G \z/oxgc) {
3705 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
3706 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qx ( )
3707 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qx { }
3708 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qx [ ]
3709 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qx < >
3710 0           elsif (/\G (\') ((?:$qq_char)*?) (\') /oxgc) { return $e . e_q ($ope,$1,$3,$2); } # qx ' '
3711 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qx * *
3712             }
3713 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3714             }
3715             }
3716              
3717             # q//
3718             elsif (/\G \b (q) \b /oxgc) {
3719 0           my $ope = $1;
3720              
3721             # if (/\G (\#) ((?:\\\#|\\\\|$q_char)*?) (\#) /oxgc) { return e_q($ope,$1,$3,$2); } # q# #
3722              
3723             # avoid "Error: Runtime exception" of perl version 5.005_03
3724             # (and so on)
3725              
3726 0 0         if (/\G (\#) /oxgc) { # q# #
3727 0           my $q_string = '';
3728 0           while (not /\G \z/oxgc) {
3729 0 0         if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0          
    0          
    0          
3730 0           elsif (/\G (\\\#) /oxgc) { $q_string .= $1; }
3731 0           elsif (/\G (\#) /oxgc) { return e_q($ope,'#','#',$q_string); }
3732 0           elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3733             }
3734 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3735             }
3736              
3737             else {
3738 0           my $e = '';
3739 0           while (not /\G \z/oxgc) {
3740 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3741              
3742             # elsif (/\G (\() ((?:\\\)|\\\\|$q_paren)*?) (\)) /oxgc) { return $e . e_q($ope,$1,$3,$2); } # q ( )
3743             elsif (/\G (\() /oxgc) { # q ( )
3744 0           my $q_string = '';
3745 0           local $nest = 1;
3746 0           while (not /\G \z/oxgc) {
3747 0 0         if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3748 0           elsif (/\G (\\\)) /oxgc) { $q_string .= $1; }
3749 0           elsif (/\G (\\\() /oxgc) { $q_string .= $1; }
3750 0           elsif (/\G (\() /oxgc) { $q_string .= $1; $nest++; }
  0            
3751             elsif (/\G (\)) /oxgc) {
3752 0 0         if (--$nest == 0) { return $e . e_q($ope,'(',')',$q_string); }
  0            
3753 0           else { $q_string .= $1; }
3754             }
3755 0           elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3756             }
3757 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3758             }
3759              
3760             # elsif (/\G (\{) ((?:\\\}|\\\\|$q_brace)*?) (\}) /oxgc) { return $e . e_q($ope,$1,$3,$2); } # q { }
3761             elsif (/\G (\{) /oxgc) { # q { }
3762 0           my $q_string = '';
3763 0           local $nest = 1;
3764 0           while (not /\G \z/oxgc) {
3765 0 0         if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3766 0           elsif (/\G (\\\}) /oxgc) { $q_string .= $1; }
3767 0           elsif (/\G (\\\{) /oxgc) { $q_string .= $1; }
3768 0           elsif (/\G (\{) /oxgc) { $q_string .= $1; $nest++; }
  0            
3769             elsif (/\G (\}) /oxgc) {
3770 0 0         if (--$nest == 0) { return $e . e_q($ope,'{','}',$q_string); }
  0            
3771 0           else { $q_string .= $1; }
3772             }
3773 0           elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3774             }
3775 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3776             }
3777              
3778             # elsif (/\G (\[) ((?:\\\]|\\\\|$q_bracket)*?) (\]) /oxgc) { return $e . e_q($ope,$1,$3,$2); } # q [ ]
3779             elsif (/\G (\[) /oxgc) { # q [ ]
3780 0           my $q_string = '';
3781 0           local $nest = 1;
3782 0           while (not /\G \z/oxgc) {
3783 0 0         if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3784 0           elsif (/\G (\\\]) /oxgc) { $q_string .= $1; }
3785 0           elsif (/\G (\\\[) /oxgc) { $q_string .= $1; }
3786 0           elsif (/\G (\[) /oxgc) { $q_string .= $1; $nest++; }
  0            
3787             elsif (/\G (\]) /oxgc) {
3788 0 0         if (--$nest == 0) { return $e . e_q($ope,'[',']',$q_string); }
  0            
3789 0           else { $q_string .= $1; }
3790             }
3791 0           elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3792             }
3793 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3794             }
3795              
3796             # elsif (/\G (\<) ((?:\\\>|\\\\|$q_angle)*?) (\>) /oxgc) { return $e . e_q($ope,$1,$3,$2); } # q < >
3797             elsif (/\G (\<) /oxgc) { # q < >
3798 0           my $q_string = '';
3799 0           local $nest = 1;
3800 0           while (not /\G \z/oxgc) {
3801 0 0         if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3802 0           elsif (/\G (\\\>) /oxgc) { $q_string .= $1; }
3803 0           elsif (/\G (\\\<) /oxgc) { $q_string .= $1; }
3804 0           elsif (/\G (\<) /oxgc) { $q_string .= $1; $nest++; }
  0            
3805             elsif (/\G (\>) /oxgc) {
3806 0 0         if (--$nest == 0) { return $e . e_q($ope,'<','>',$q_string); }
  0            
3807 0           else { $q_string .= $1; }
3808             }
3809 0           elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3810             }
3811 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3812             }
3813              
3814             # elsif (/\G (\S) ((?:\\\1|\\\\|$q_char)*?) (\1) /oxgc) { return $e . e_q($ope,$1,$3,$2); } # q * *
3815             elsif (/\G (\S) /oxgc) { # q * *
3816 0           my $delimiter = $1;
3817 0           my $q_string = '';
3818 0           while (not /\G \z/oxgc) {
3819 0 0         if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0          
    0          
    0          
3820 0           elsif (/\G (\\\Q$delimiter\E) /oxgc) { $q_string .= $1; }
3821 0           elsif (/\G (\Q$delimiter\E) /oxgc) { return $e . e_q($ope,$delimiter,$delimiter,$q_string); }
3822 0           elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3823             }
3824 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3825             }
3826             }
3827 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3828             }
3829             }
3830              
3831             # m//
3832             elsif (/\G \b (m) \b /oxgc) {
3833 0           my $ope = $1;
3834 0 0         if (/\G (\#) ((?:$qq_char)*?) (\#) ([cgimosxpadlubB]*) /oxgc) { # m# #
3835 0           return e_qr($ope,$1,$3,$2,$4);
3836             }
3837             else {
3838 0           my $e = '';
3839 0           while (not /\G \z/oxgc) {
3840 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
3841 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cgimosxpadlubB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m ( )
3842 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cgimosxpadlubB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m { }
3843 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cgimosxpadlubB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m [ ]
3844 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cgimosxpadlubB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m < >
3845 0           elsif (/\G (\?) ((?:$qq_char)*?) (\?) ([cgimosxpadlubB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m ? ?
3846 0           elsif (/\G (\') ((?:$qq_char)*?) (\') ([cgimosxpadlubB]*) /oxgc) { return $e . e_qr_q($ope,$1, $3, $2,$4); } # m ' '
3847 0           elsif (/\G ([*\-:\\^|]) ((?:$qq_char)*?) (\1) ([cgimosxpadlubB]*) /oxgc) { return $e . e_qr ($ope,'{','}',$2,$4); } # m | | --> m { }
3848 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cgimosxpadlubB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m * *
3849             }
3850 0           die __FILE__, ": Search pattern not terminated";
3851             }
3852             }
3853              
3854             # s///
3855              
3856             # about [cegimosxpradlubB]* (/cg modifier)
3857             #
3858             # P.67 Pattern-Matching Operators
3859             # of ISBN 0-596-00241-6 Perl in a Nutshell, Second Edition.
3860              
3861             elsif (/\G \b (s) \b /oxgc) {
3862 0           my $ope = $1;
3863              
3864             # $1 $2 $3 $4 $5 $6
3865 0 0         if (/\G (\#) ((?:$qq_char)*?) (\#) ((?:$qq_char)*?) (\#) ([cegimosxpradlubB]*) /oxgc) { # s# # #
3866 0           return e_sub($sub_variable,$1,$2,$3,$3,$4,$5,$6);
3867             }
3868             else {
3869 0           my $e = '';
3870 0           while (not /\G \z/oxgc) {
3871 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
3872             elsif (/\G (\() ((?:$qq_paren)*?) (\)) /oxgc) {
3873 0           my @s = ($1,$2,$3);
3874 0           while (not /\G \z/oxgc) {
3875 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
3876             # $1 $2 $3 $4
3877 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3878 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3879 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3880 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3881 0           elsif (/\G (\') ((?:$qq_char)*?) (\') ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3882 0           elsif (/\G (\$) ((?:$qq_char)*?) (\$) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3883 0           elsif (/\G (\:) ((?:$qq_char)*?) (\:) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3884 0           elsif (/\G (\@) ((?:$qq_char)*?) (\@) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3885 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3886             }
3887 0           die __FILE__, ": Substitution replacement not terminated";
3888             }
3889             elsif (/\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) {
3890 0           my @s = ($1,$2,$3);
3891 0           while (not /\G \z/oxgc) {
3892 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
3893             # $1 $2 $3 $4
3894 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3895 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3896 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3897 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3898 0           elsif (/\G (\') ((?:$qq_char)*?) (\') ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3899 0           elsif (/\G (\$) ((?:$qq_char)*?) (\$) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3900 0           elsif (/\G (\:) ((?:$qq_char)*?) (\:) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3901 0           elsif (/\G (\@) ((?:$qq_char)*?) (\@) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3902 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3903             }
3904 0           die __FILE__, ": Substitution replacement not terminated";
3905             }
3906             elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) {
3907 0           my @s = ($1,$2,$3);
3908 0           while (not /\G \z/oxgc) {
3909 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
3910             # $1 $2 $3 $4
3911 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3912 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3913 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3914 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3915 0           elsif (/\G (\') ((?:$qq_char)*?) (\') ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3916 0           elsif (/\G (\$) ((?:$qq_char)*?) (\$) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3917 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3918             }
3919 0           die __FILE__, ": Substitution replacement not terminated";
3920             }
3921             elsif (/\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) {
3922 0           my @s = ($1,$2,$3);
3923 0           while (not /\G \z/oxgc) {
3924 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
3925             # $1 $2 $3 $4
3926 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3927 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3928 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3929 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3930 0           elsif (/\G (\') ((?:$qq_char)*?) (\') ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3931 0           elsif (/\G (\$) ((?:$qq_char)*?) (\$) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3932 0           elsif (/\G (\:) ((?:$qq_char)*?) (\:) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3933 0           elsif (/\G (\@) ((?:$qq_char)*?) (\@) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3934 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3935             }
3936 0           die __FILE__, ": Substitution replacement not terminated";
3937             }
3938             # $1 $2 $3 $4 $5 $6
3939             elsif (/\G (\') ((?:$qq_char)*?) (\') ((?:$qq_char)*?) (\') ([cegimosxpradlubB]*) /oxgc) {
3940 0           return e_sub($sub_variable,$1,$2,$3,$3,$4,$5,$6);
3941             }
3942             # $1 $2 $3 $4 $5 $6
3943             elsif (/\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ((?:$qq_char)*?) (\1) ([cegimosxpradlubB]*) /oxgc) {
3944 0           return e_sub($sub_variable,'{',$2,'}','{',$4,'}',$6); # s | | | --> s { } { }
3945             }
3946             # $1 $2 $3 $4 $5 $6
3947             elsif (/\G (\$) ((?:$qq_char)*?) (\1) ((?:$qq_char)*?) (\1) ([cegimosxpradlubB]*) /oxgc) {
3948 0           return e_sub($sub_variable,$1,$2,$3,$3,$4,$5,$6);
3949             }
3950             # $1 $2 $3 $4 $5 $6
3951             elsif (/\G (\S) ((?:$qq_char)*?) (\1) ((?:$qq_char)*?) (\1) ([cegimosxpradlubB]*) /oxgc) {
3952 0           return e_sub($sub_variable,$1,$2,$3,$3,$4,$5,$6);
3953             }
3954             }
3955 0           die __FILE__, ": Substitution pattern not terminated";
3956             }
3957             }
3958              
3959             # require ignore module
3960 0           elsif (/\G \b require (\s+ (?:$ignore_modules) .*? ;) ([ \t]* [#\n]) /oxmsgc) { return "# require$1$2"; }
3961 0           elsif (/\G \b require (\s+ (?:$ignore_modules) .*? ;) ([ \t]* [^#]) /oxmsgc) { return "# require$1\n$2"; }
3962 0           elsif (/\G \b require (\s+ (?:$ignore_modules)) \b /oxmsgc) { return "# require$1"; }
3963              
3964             # use strict; --> use strict; no strict qw(refs);
3965 0           elsif (/\G \b use (\s+ strict .*? ;) ([ \t]* [#\n]) /oxmsgc) { return "use$1 no strict qw(refs);$2"; }
3966 0           elsif (/\G \b use (\s+ strict .*? ;) ([ \t]* [^#]) /oxmsgc) { return "use$1 no strict qw(refs);\n$2"; }
3967 0           elsif (/\G \b use (\s+ strict) \b /oxmsgc) { return "use$1; no strict qw(refs)"; }
3968              
3969             # use 5.12.0; --> use 5.12.0; no strict qw(refs);
3970             elsif (/\G \b use \s+ (([1-9][0-9_]*)(?:\.([0-9_]+))*) \s* ; /oxmsgc) {
3971 0 0 0       if (($2 >= 6) or (($2 == 5) and ($3 ge '012'))) {
      0        
3972 0           return "use $1; no strict qw(refs);";
3973             }
3974             else {
3975 0           return "use $1;";
3976             }
3977             }
3978             elsif (/\G \b use \s+ (v([0-9][0-9_]*)(?:\.([0-9_]+))*) \s* ; /oxmsgc) {
3979 0 0 0       if (($2 >= 6) or (($2 == 5) and ($3 >= 12))) {
      0        
3980 0           return "use $1; no strict qw(refs);";
3981             }
3982             else {
3983 0           return "use $1;";
3984             }
3985             }
3986              
3987             # ignore use module
3988 0           elsif (/\G \b use (\s+ (?:$ignore_modules) .*? ;) ([ \t]* [#\n]) /oxmsgc) { return "# use$1$2"; }
3989 0           elsif (/\G \b use (\s+ (?:$ignore_modules) .*? ;) ([ \t]* [^#]) /oxmsgc) { return "# use$1\n$2"; }
3990 0           elsif (/\G \b use (\s+ (?:$ignore_modules)) \b /oxmsgc) { return "# use$1"; }
3991              
3992             # ignore no module
3993 0           elsif (/\G \b no (\s+ (?:$ignore_modules) .*? ;) ([ \t]* [#\n]) /oxmsgc) { return "# no$1$2"; }
3994 0           elsif (/\G \b no (\s+ (?:$ignore_modules) .*? ;) ([ \t]* [^#]) /oxmsgc) { return "# no$1\n$2"; }
3995 0           elsif (/\G \b no (\s+ (?:$ignore_modules)) \b /oxmsgc) { return "# no$1"; }
3996              
3997             # use else
3998 0           elsif (/\G \b use \b /oxmsgc) { return "use"; }
3999              
4000             # use else
4001 0           elsif (/\G \b no \b /oxmsgc) { return "no"; }
4002              
4003             # ''
4004             elsif (/\G (?
4005 0           my $q_string = '';
4006 0           while (not /\G \z/oxgc) {
4007 0 0         if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0          
    0          
    0          
4008 0           elsif (/\G (\\\') /oxgc) { $q_string .= $1; }
4009 0           elsif (/\G \' /oxgc) { return e_q('', "'","'",$q_string); }
4010 0           elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
4011             }
4012 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
4013             }
4014              
4015             # ""
4016             elsif (/\G (\") /oxgc) {
4017 0           my $qq_string = '';
4018 0           while (not /\G \z/oxgc) {
4019 0 0         if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0          
    0          
    0          
4020 0           elsif (/\G (\\\") /oxgc) { $qq_string .= $1; }
4021 0           elsif (/\G \" /oxgc) { return e_qq('', '"','"',$qq_string); }
4022 0           elsif (/\G ($q_char) /oxgc) { $qq_string .= $1; }
4023             }
4024 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
4025             }
4026              
4027             # ``
4028             elsif (/\G (\`) /oxgc) {
4029 0           my $qx_string = '';
4030 0           while (not /\G \z/oxgc) {
4031 0 0         if (/\G (\\\\) /oxgc) { $qx_string .= $1; }
  0 0          
    0          
    0          
4032 0           elsif (/\G (\\\`) /oxgc) { $qx_string .= $1; }
4033 0           elsif (/\G \` /oxgc) { return e_qq('', '`','`',$qx_string); }
4034 0           elsif (/\G ($q_char) /oxgc) { $qx_string .= $1; }
4035             }
4036 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
4037             }
4038              
4039             # // --- not divide operator (num / num), not defined-or
4040             elsif (($slash eq 'm//') and /\G (\/) /oxgc) {
4041 0           my $regexp = '';
4042 0           while (not /\G \z/oxgc) {
4043 0 0         if (/\G (\\\\) /oxgc) { $regexp .= $1; }
  0 0          
    0          
    0          
4044 0           elsif (/\G (\\\/) /oxgc) { $regexp .= $1; }
4045 0           elsif (/\G \/ ([cgimosxpadlubB]*) /oxgc) { return e_qr('', '/','/',$regexp,$1); }
4046 0           elsif (/\G ($q_char) /oxgc) { $regexp .= $1; }
4047             }
4048 0           die __FILE__, ": Search pattern not terminated";
4049             }
4050              
4051             # ?? --- not conditional operator (condition ? then : else)
4052             elsif (($slash eq 'm//') and /\G (\?) /oxgc) {
4053 0           my $regexp = '';
4054 0           while (not /\G \z/oxgc) {
4055 0 0         if (/\G (\\\\) /oxgc) { $regexp .= $1; }
  0 0          
    0          
    0          
4056 0           elsif (/\G (\\\?) /oxgc) { $regexp .= $1; }
4057 0           elsif (/\G \? ([cgimosxpadlubB]*) /oxgc) { return e_qr('m','?','?',$regexp,$1); }
4058 0           elsif (/\G ($q_char) /oxgc) { $regexp .= $1; }
4059             }
4060 0           die __FILE__, ": Search pattern not terminated";
4061             }
4062              
4063             # << (bit shift) --- not here document
4064 0           elsif (/\G ( << \s* ) (?= [0-9\$\@\&] ) /oxgc) { $slash = 'm//'; return $1; }
  0            
4065              
4066             # <<'HEREDOC'
4067             elsif (/\G ( << '([a-zA-Z_0-9]*)' ) /oxgc) {
4068 0           $slash = 'm//';
4069 0           my $here_quote = $1;
4070 0           my $delimiter = $2;
4071              
4072             # get here document
4073 0 0         if ($here_script eq '') {
4074 0           $here_script = CORE::substr $_, pos $_;
4075 0           $here_script =~ s/.*?\n//oxm;
4076             }
4077 0 0         if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4078 0           push @heredoc, $1 . qq{\n$delimiter\n};
4079 0           push @heredoc_delimiter, $delimiter;
4080             }
4081             else {
4082 0           die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF";
4083             }
4084 0           return $here_quote;
4085             }
4086              
4087             # <<\HEREDOC
4088              
4089             # P.66 2.6.6. "Here" Documents
4090             # in Chapter 2: Bits and Pieces
4091             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
4092              
4093             # P.73 "Here" Documents
4094             # in Chapter 2: Bits and Pieces
4095             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
4096              
4097             elsif (/\G ( << \\([a-zA-Z_0-9]+) ) /oxgc) {
4098 0           $slash = 'm//';
4099 0           my $here_quote = $1;
4100 0           my $delimiter = $2;
4101              
4102             # get here document
4103 0 0         if ($here_script eq '') {
4104 0           $here_script = CORE::substr $_, pos $_;
4105 0           $here_script =~ s/.*?\n//oxm;
4106             }
4107 0 0         if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4108 0           push @heredoc, $1 . qq{\n$delimiter\n};
4109 0           push @heredoc_delimiter, $delimiter;
4110             }
4111             else {
4112 0           die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF";
4113             }
4114 0           return $here_quote;
4115             }
4116              
4117             # <<"HEREDOC"
4118             elsif (/\G ( << "([a-zA-Z_0-9]*)" ) /oxgc) {
4119 0           $slash = 'm//';
4120 0           my $here_quote = $1;
4121 0           my $delimiter = $2;
4122              
4123             # get here document
4124 0 0         if ($here_script eq '') {
4125 0           $here_script = CORE::substr $_, pos $_;
4126 0           $here_script =~ s/.*?\n//oxm;
4127             }
4128 0 0         if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4129 0           push @heredoc, e_heredoc($1) . qq{\n$delimiter\n};
4130 0           push @heredoc_delimiter, $delimiter;
4131             }
4132             else {
4133 0           die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF";
4134             }
4135 0           return $here_quote;
4136             }
4137              
4138             # <
4139             elsif (/\G ( << ([a-zA-Z_0-9]+) ) /oxgc) {
4140 0           $slash = 'm//';
4141 0           my $here_quote = $1;
4142 0           my $delimiter = $2;
4143              
4144             # get here document
4145 0 0         if ($here_script eq '') {
4146 0           $here_script = CORE::substr $_, pos $_;
4147 0           $here_script =~ s/.*?\n//oxm;
4148             }
4149 0 0         if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4150 0           push @heredoc, e_heredoc($1) . qq{\n$delimiter\n};
4151 0           push @heredoc_delimiter, $delimiter;
4152             }
4153             else {
4154 0           die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF";
4155             }
4156 0           return $here_quote;
4157             }
4158              
4159             # <<`HEREDOC`
4160             elsif (/\G ( << `([a-zA-Z_0-9]*)` ) /oxgc) {
4161 0           $slash = 'm//';
4162 0           my $here_quote = $1;
4163 0           my $delimiter = $2;
4164              
4165             # get here document
4166 0 0         if ($here_script eq '') {
4167 0           $here_script = CORE::substr $_, pos $_;
4168 0           $here_script =~ s/.*?\n//oxm;
4169             }
4170 0 0         if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4171 0           push @heredoc, e_heredoc($1) . qq{\n$delimiter\n};
4172 0           push @heredoc_delimiter, $delimiter;
4173             }
4174             else {
4175 0           die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF";
4176             }
4177 0           return $here_quote;
4178             }
4179              
4180             # <<= <=> <= < operator
4181             elsif (/\G ( <<= | <=> | <= | < ) (?= \s* [A-Za-z_0-9'"`\$\@\&\*\(\+\-] )/oxgc) {
4182 0           return $1;
4183             }
4184              
4185             #
4186             elsif (/\G (<[\$]?[A-Za-z_][A-Za-z_0-9]*>) /oxgc) {
4187 0           return $1;
4188             }
4189              
4190             # --- glob
4191              
4192             # avoid "Error: Runtime exception" of perl version 5.005_03
4193              
4194             elsif (/\G < ((?:[^>\0\a\e\f\n\r\t])+?) > /oxgc) {
4195 0           return 'Char::Elatin1::glob("' . $1 . '")';
4196             }
4197              
4198             # __DATA__
4199 0           elsif (/\G ^ ( __DATA__ \n .*) \z /oxmsgc) { return $1; }
4200              
4201             # __END__
4202 0           elsif (/\G ^ ( __END__ \n .*) \z /oxmsgc) { return $1; }
4203              
4204             # \cD Control-D
4205              
4206             # P.68 2.6.8. Other Literal Tokens
4207             # in Chapter 2: Bits and Pieces
4208             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
4209              
4210             # P.76 Other Literal Tokens
4211             # in Chapter 2: Bits and Pieces
4212             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
4213              
4214 0           elsif (/\G ( \cD .*) \z /oxmsgc) { return $1; }
4215              
4216             # \cZ Control-Z
4217 0           elsif (/\G ( \cZ .*) \z /oxmsgc) { return $1; }
4218              
4219             # any operator before div
4220             elsif (/\G (
4221             -- | \+\+ |
4222             [\)\}\]]
4223              
4224 0           ) /oxgc) { $slash = 'div'; return $1; }
  0            
4225              
4226             # yada-yada or triple-dot operator
4227             elsif (/\G (
4228             \.\.\.
4229              
4230 0           ) /oxgc) { $slash = 'm//'; return q{die('Unimplemented')}; }
  0            
4231              
4232             # any operator before m//
4233              
4234             # //, //= (defined-or)
4235              
4236             # P.164 Logical Operators
4237             # in Chapter 10: More Control Structures
4238             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
4239              
4240             # P.119 C-Style Logical (Short-Circuit) Operators
4241             # in Chapter 3: Unary and Binary Operators
4242             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
4243              
4244             # (and so on)
4245              
4246             # ~~
4247              
4248             # P.221 The Smart Match Operator
4249             # in Chapter 15: Smart Matching and given-when
4250             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
4251              
4252             # P.112 Smartmatch Operator
4253             # in Chapter 3: Unary and Binary Operators
4254             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
4255              
4256             # (and so on)
4257              
4258             elsif (/\G (
4259              
4260             !~~ | !~ | != | ! |
4261             %= | % |
4262             &&= | && | &= | & |
4263             -= | -> | - |
4264             :\s*= |
4265             : |
4266             <<= | <=> | <= | < |
4267             == | => | =~ | = |
4268             >>= | >> | >= | > |
4269             \*\*= | \*\* | \*= | \* |
4270             \+= | \+ |
4271             \.\. | \.= | \. |
4272             \/\/= | \/\/ |
4273             \/= | \/ |
4274             \? |
4275             \\ |
4276             \^= | \^ |
4277             \b x= |
4278             \|\|= | \|\| | \|= | \| |
4279             ~~ | ~ |
4280             \b(?: and | cmp | eq | ge | gt | le | lt | ne | not | or | xor | x )\b |
4281             \b(?: print )\b |
4282              
4283             [,;\(\{\[]
4284              
4285 0           ) /oxgc) { $slash = 'm//'; return $1; }
  0            
4286              
4287             # other any character
4288 0           elsif (/\G ($q_char) /oxgc) { $slash = 'div'; return $1; }
  0            
4289              
4290             # system error
4291             else {
4292 0           die __FILE__, ": Oops, this shouldn't happen!";
4293             }
4294             }
4295              
4296             # escape Latin-1 string
4297             sub e_string {
4298 0     0 0   my($string) = @_;
4299 0           my $e_string = '';
4300              
4301 0           local $slash = 'm//';
4302              
4303             # P.1024 Appendix W.10 Multibyte Processing
4304             # of ISBN 1-56592-224-7 CJKV Information Processing
4305             # (and so on)
4306              
4307 0           my @char = $string =~ / \G (\\?(?:$q_char)) /oxmsg;
4308              
4309             # without { ... }
4310 0 0 0       if (not (grep(/\A \{ \z/xms, @char) and grep(/\A \} \z/xms, @char))) {
4311 0 0         if ($string !~ /<
4312 0           return $string;
4313             }
4314             }
4315              
4316             E_STRING_LOOP:
4317 0           while ($string !~ /\G \z/oxgc) {
4318 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          
4319             }
4320              
4321             # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> @{[Char::Elatin1::PREMATCH()]}
4322 0           elsif ($string =~ /\G ( \$` | \$\{`\} | \$ \s* PREMATCH \b | \$ \s* \{ \s* PREMATCH \s* \} | \$ \s* \{\^PREMATCH\} ) /oxmsgc) {
4323 0           $e_string .= q{Char::Elatin1::PREMATCH()};
4324 0           $slash = 'div';
4325             }
4326              
4327             # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> @{[Char::Elatin1::MATCH()]}
4328             elsif ($string =~ /\G ( \$& | \$\{&\} | \$ \s* MATCH \b | \$ \s* \{ \s* MATCH \s* \} | \$ \s* \{\^MATCH\} ) /oxmsgc) {
4329 0           $e_string .= q{Char::Elatin1::MATCH()};
4330 0           $slash = 'div';
4331             }
4332              
4333             # $', ${'} --> $', ${'}
4334             elsif ($string =~ /\G ( \$' | \$\{'\} ) /oxmsgc) {
4335 0           $e_string .= $1;
4336 0           $slash = 'div';
4337             }
4338              
4339             # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> @{[Char::Elatin1::POSTMATCH()]}
4340             elsif ($string =~ /\G ( \$ \s* POSTMATCH \b | \$ \s* \{ \s* POSTMATCH \s* \} | \$ \s* \{\^POSTMATCH\} ) /oxmsgc) {
4341 0           $e_string .= q{Char::Elatin1::POSTMATCH()};
4342 0           $slash = 'div';
4343             }
4344              
4345             # bareword
4346             elsif ($string =~ /\G ( \{ \s* (?: tr | index | rindex | reverse ) \s* \} ) /oxmsgc) {
4347 0           $e_string .= $1;
4348 0           $slash = 'div';
4349             }
4350              
4351             # $0 --> $0
4352             elsif ($string =~ /\G ( \$ 0 ) /oxmsgc) {
4353 0           $e_string .= $1;
4354 0           $slash = 'div';
4355             }
4356             elsif ($string =~ /\G ( \$ \{ \s* 0 \s* \} ) /oxmsgc) {
4357 0           $e_string .= $1;
4358 0           $slash = 'div';
4359             }
4360              
4361             # $$ --> $$
4362             elsif ($string =~ /\G ( \$ \$ ) (?![\w\{]) /oxmsgc) {
4363 0           $e_string .= $1;
4364 0           $slash = 'div';
4365             }
4366              
4367             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
4368             # $1, $2, $3 --> $1, $2, $3 otherwise
4369             elsif ($string =~ /\G \$ ([1-9][0-9]*) /oxmsgc) {
4370 0           $e_string .= e_capture($1);
4371 0           $slash = 'div';
4372             }
4373             elsif ($string =~ /\G \$ \{ \s* ([1-9][0-9]*) \s* \} /oxmsgc) {
4374 0           $e_string .= e_capture($1);
4375 0           $slash = 'div';
4376             }
4377              
4378             # $$foo[ ... ] --> $ $foo->[ ... ]
4379             elsif ($string =~ /\G \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) ( \[ .+? \] ) /oxmsgc) {
4380 0           $e_string .= e_capture($1.'->'.$2);
4381 0           $slash = 'div';
4382             }
4383              
4384             # $$foo{ ... } --> $ $foo->{ ... }
4385             elsif ($string =~ /\G \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) ( \{ .+? \} ) /oxmsgc) {
4386 0           $e_string .= e_capture($1.'->'.$2);
4387 0           $slash = 'div';
4388             }
4389              
4390             # $$foo
4391             elsif ($string =~ /\G \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) /oxmsgc) {
4392 0           $e_string .= e_capture($1);
4393 0           $slash = 'div';
4394             }
4395              
4396             # ${ foo }
4397             elsif ($string =~ /\G \$ \s* \{ ( \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* ) \} /oxmsgc) {
4398 0           $e_string .= '${' . $1 . '}';
4399 0           $slash = 'div';
4400             }
4401              
4402             # ${ ... }
4403             elsif ($string =~ /\G \$ \s* \{ \s* ( $qq_brace ) \s* \} /oxmsgc) {
4404 0           $e_string .= e_capture($1);
4405 0           $slash = 'div';
4406             }
4407              
4408             # variable or function
4409             # $ @ % & * $ #
4410             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) {
4411 0           $e_string .= $1;
4412 0           $slash = 'div';
4413             }
4414             # $ $ $ $ $ $ $ $ $ $ $ $ $ $
4415             # $ @ # \ ' " / ? ( ) [ ] < >
4416             elsif ($string =~ /\G ( \$[\$\@\#\\\'\"\/\?\(\)\[\]\<\>] ) /oxmsgc) {
4417 0           $e_string .= $1;
4418 0           $slash = 'div';
4419             }
4420              
4421             # subroutines of package Char::Elatin1
4422 0           elsif ($string =~ /\G \b (CORE:: | ->[ ]* (?: atan2 | [a-z]{2,})) \b /oxgc) { $e_string .= $1; $slash = 'm//'; }
  0            
4423 0           elsif ($string =~ /\G \b Char::Latin1::eval (?= \s* \{ ) /oxgc) { $e_string .= 'eval'; $slash = 'm//'; }
  0            
4424 0           elsif ($string =~ /\G \b Char::Latin1::eval \b /oxgc) { $e_string .= 'eval Char::Latin1::escape'; $slash = 'm//'; }
  0            
4425 0           elsif ($string =~ /\G \b bytes::substr \b /oxgc) { $e_string .= 'substr'; $slash = 'm//'; }
  0            
4426 0           elsif ($string =~ /\G \b chop \b /oxgc) { $e_string .= 'Char::Elatin1::chop'; $slash = 'm//'; }
  0            
4427 0           elsif ($string =~ /\G \b bytes::index \b /oxgc) { $e_string .= 'index'; $slash = 'm//'; }
  0            
4428 0           elsif ($string =~ /\G \b Char::Latin1::index \b /oxgc) { $e_string .= 'Char::Latin1::index'; $slash = 'm//'; }
  0            
4429 0           elsif ($string =~ /\G \b index \b /oxgc) { $e_string .= 'Char::Elatin1::index'; $slash = 'm//'; }
  0            
4430 0           elsif ($string =~ /\G \b bytes::rindex \b /oxgc) { $e_string .= 'rindex'; $slash = 'm//'; }
  0            
4431 0           elsif ($string =~ /\G \b Char::Latin1::rindex \b /oxgc) { $e_string .= 'Char::Latin1::rindex'; $slash = 'm//'; }
  0            
4432 0           elsif ($string =~ /\G \b rindex \b /oxgc) { $e_string .= 'Char::Elatin1::rindex'; $slash = 'm//'; }
  0            
4433 0           elsif ($string =~ /\G \b lc (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Char::Elatin1::lc'; $slash = 'm//'; }
  0            
4434 0           elsif ($string =~ /\G \b lcfirst (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Char::Elatin1::lcfirst'; $slash = 'm//'; }
  0            
4435 0           elsif ($string =~ /\G \b uc (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Char::Elatin1::uc'; $slash = 'm//'; }
  0            
4436 0           elsif ($string =~ /\G \b ucfirst (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Char::Elatin1::ucfirst'; $slash = 'm//'; }
  0            
4437 0           elsif ($string =~ /\G \b fc (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Char::Elatin1::fc'; $slash = 'm//'; }
  0            
4438              
4439             # "-s '' ..." means file test "-s 'filename' ..." (not means "- s/// ...")
4440 0           elsif ($string =~ /\G -s \s+ \s* (\") ((?:$qq_char)+?) (\") /oxgc) { $e_string .= '-s ' . e_qq('', $1,$3,$2); $slash = 'm//'; }
  0            
4441 0           elsif ($string =~ /\G -s \s+ qq \s* (\#) ((?:$qq_char)+?) (\#) /oxgc) { $e_string .= '-s ' . e_qq('qq',$1,$3,$2); $slash = 'm//'; }
  0            
4442 0           elsif ($string =~ /\G -s \s+ qq \s* (\() ((?:$qq_paren)+?) (\)) /oxgc) { $e_string .= '-s ' . e_qq('qq',$1,$3,$2); $slash = 'm//'; }
  0            
4443 0           elsif ($string =~ /\G -s \s+ qq \s* (\{) ((?:$qq_brace)+?) (\}) /oxgc) { $e_string .= '-s ' . e_qq('qq',$1,$3,$2); $slash = 'm//'; }
  0            
4444 0           elsif ($string =~ /\G -s \s+ qq \s* (\[) ((?:$qq_bracket)+?) (\]) /oxgc) { $e_string .= '-s ' . e_qq('qq',$1,$3,$2); $slash = 'm//'; }
  0            
4445 0           elsif ($string =~ /\G -s \s+ qq \s* (\<) ((?:$qq_angle)+?) (\>) /oxgc) { $e_string .= '-s ' . e_qq('qq',$1,$3,$2); $slash = 'm//'; }
  0            
4446 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            
4447              
4448 0           elsif ($string =~ /\G -s \s+ \s* (\') ((?:\\\'|\\\\|$q_char)+?) (\') /oxgc) { $e_string .= '-s ' . e_q ('', $1,$3,$2); $slash = 'm//'; }
  0            
4449 0           elsif ($string =~ /\G -s \s+ q \s* (\#) ((?:\\\#|\\\\|$q_char)+?) (\#) /oxgc) { $e_string .= '-s ' . e_q ('q', $1,$3,$2); $slash = 'm//'; }
  0            
4450 0           elsif ($string =~ /\G -s \s+ q \s* (\() ((?:\\\)|\\\\|$q_paren)+?) (\)) /oxgc) { $e_string .= '-s ' . e_q ('q', $1,$3,$2); $slash = 'm//'; }
  0            
4451 0           elsif ($string =~ /\G -s \s+ q \s* (\{) ((?:\\\}|\\\\|$q_brace)+?) (\}) /oxgc) { $e_string .= '-s ' . e_q ('q', $1,$3,$2); $slash = 'm//'; }
  0            
4452 0           elsif ($string =~ /\G -s \s+ q \s* (\[) ((?:\\\]|\\\\|$q_bracket)+?) (\]) /oxgc) { $e_string .= '-s ' . e_q ('q', $1,$3,$2); $slash = 'm//'; }
  0            
4453 0           elsif ($string =~ /\G -s \s+ q \s* (\<) ((?:\\\>|\\\\|$q_angle)+?) (\>) /oxgc) { $e_string .= '-s ' . e_q ('q', $1,$3,$2); $slash = 'm//'; }
  0            
4454 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            
4455              
4456             elsif ($string =~ /\G -s \s* (\$ \w+(?: ::\w+)* (?: (?: ->)? (?: [\$\@\%\&\*]\* | \$\#\* | \( (?:$qq_paren)*? \) | [\@\%\*]? \{ (?:$qq_brace)+? \} | [\@\%]? \[ (?:$qq_bracket)+? \] ) )*) /oxgc)
4457 0           { $e_string .= "-s $1"; $slash = 'm//'; }
  0            
4458 0           elsif ($string =~ /\G -s \s* \( ((?:$qq_paren)*?) \) /oxgc) { $e_string .= "-s ($1)"; $slash = 'm//'; }
  0            
4459 0           elsif ($string =~ /\G -s (?= \s+ [a-z]+) /oxgc) { $e_string .= '-s'; $slash = 'm//'; }
  0            
4460 0           elsif ($string =~ /\G -s \s+ (\w+) /oxgc) { $e_string .= "-s $1"; $slash = 'm//'; }
  0            
4461              
4462 0           elsif ($string =~ /\G \b bytes::length (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'length'; $slash = 'm//'; }
  0            
4463 0           elsif ($string =~ /\G \b bytes::chr (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'chr'; $slash = 'm//'; }
  0            
4464 0           elsif ($string =~ /\G \b chr (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Char::Elatin1::chr'; $slash = 'm//'; }
  0            
4465 0           elsif ($string =~ /\G \b bytes::ord (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'ord'; $slash = 'div'; }
  0            
4466 0           elsif ($string =~ /\G \b ord (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $e_string .= $function_ord; $slash = 'div'; }
  0            
4467 0           elsif ($string =~ /\G \b glob (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Char::Elatin1::glob'; $slash = 'm//'; }
  0            
4468 0           elsif ($string =~ /\G \b lc \b /oxgc) { $e_string .= 'Char::Elatin1::lc_'; $slash = 'm//'; }
  0            
4469 0           elsif ($string =~ /\G \b lcfirst \b /oxgc) { $e_string .= 'Char::Elatin1::lcfirst_'; $slash = 'm//'; }
  0            
4470 0           elsif ($string =~ /\G \b uc \b /oxgc) { $e_string .= 'Char::Elatin1::uc_'; $slash = 'm//'; }
  0            
4471 0           elsif ($string =~ /\G \b ucfirst \b /oxgc) { $e_string .= 'Char::Elatin1::ucfirst_'; $slash = 'm//'; }
  0            
4472 0           elsif ($string =~ /\G \b fc \b /oxgc) { $e_string .= 'Char::Elatin1::fc_'; $slash = 'm//'; }
  0            
4473 0           elsif ($string =~ /\G -s \b /oxgc) { $e_string .= '-s '; $slash = 'm//'; }
  0            
4474              
4475 0           elsif ($string =~ /\G \b bytes::length \b /oxgc) { $e_string .= 'length'; $slash = 'm//'; }
  0            
4476 0           elsif ($string =~ /\G \b bytes::chr \b /oxgc) { $e_string .= 'chr'; $slash = 'm//'; }
  0            
4477 0           elsif ($string =~ /\G \b chr \b /oxgc) { $e_string .= 'Char::Elatin1::chr_'; $slash = 'm//'; }
  0            
4478 0           elsif ($string =~ /\G \b bytes::ord \b /oxgc) { $e_string .= 'ord'; $slash = 'div'; }
  0            
4479 0           elsif ($string =~ /\G \b ord \b /oxgc) { $e_string .= $function_ord_; $slash = 'div'; }
  0            
4480 0           elsif ($string =~ /\G \b glob \b /oxgc) { $e_string .= 'Char::Elatin1::glob_'; $slash = 'm//'; }
  0            
4481 0           elsif ($string =~ /\G \b reverse \b /oxgc) { $e_string .= $function_reverse; $slash = 'm//'; }
  0            
4482 0           elsif ($string =~ /\G \b getc \b /oxgc) { $e_string .= $function_getc; $slash = 'm//'; }
  0            
4483             # split
4484             elsif ($string =~ /\G \b (split) \b (?! \s* => ) /oxgc) {
4485 0           $slash = 'm//';
4486              
4487 0           my $e = '';
4488 0           while ($string =~ /\G ( \s+ | \( | \#.* ) /oxgc) {
4489 0           $e .= $1;
4490             }
4491              
4492             # end of split
4493 0 0         if ($string =~ /\G (?= [,;\)\}\]] ) /oxgc) { return 'Char::Elatin1::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          
4494              
4495             # split scalar value
4496 0           elsif ($string =~ /\G ( [\$\@\&\*] $qq_scalar ) /oxgc) { $e_string .= 'Char::Elatin1::split' . $e . e_string($1); next E_STRING_LOOP; }
  0            
4497              
4498             # split literal space
4499 0           elsif ($string =~ /\G \b qq (\#) [ ] (\#) /oxgc) { $e_string .= 'Char::Elatin1::split' . $e . qq {qq$1 $2}; next E_STRING_LOOP; }
  0            
4500 0           elsif ($string =~ /\G \b qq (\s*) (\() [ ] (\)) /oxgc) { $e_string .= 'Char::Elatin1::split' . $e . qq{$1qq$2 $3}; next E_STRING_LOOP; }
  0            
4501 0           elsif ($string =~ /\G \b qq (\s*) (\{) [ ] (\}) /oxgc) { $e_string .= 'Char::Elatin1::split' . $e . qq{$1qq$2 $3}; next E_STRING_LOOP; }
  0            
4502 0           elsif ($string =~ /\G \b qq (\s*) (\[) [ ] (\]) /oxgc) { $e_string .= 'Char::Elatin1::split' . $e . qq{$1qq$2 $3}; next E_STRING_LOOP; }
  0            
4503 0           elsif ($string =~ /\G \b qq (\s*) (\<) [ ] (\>) /oxgc) { $e_string .= 'Char::Elatin1::split' . $e . qq{$1qq$2 $3}; next E_STRING_LOOP; }
  0            
4504 0           elsif ($string =~ /\G \b qq (\s*) (\S) [ ] (\2) /oxgc) { $e_string .= 'Char::Elatin1::split' . $e . qq{$1qq$2 $3}; next E_STRING_LOOP; }
  0            
4505 0           elsif ($string =~ /\G \b q (\#) [ ] (\#) /oxgc) { $e_string .= 'Char::Elatin1::split' . $e . qq {q$1 $2}; next E_STRING_LOOP; }
  0            
4506 0           elsif ($string =~ /\G \b q (\s*) (\() [ ] (\)) /oxgc) { $e_string .= 'Char::Elatin1::split' . $e . qq {$1q$2 $3}; next E_STRING_LOOP; }
  0            
4507 0           elsif ($string =~ /\G \b q (\s*) (\{) [ ] (\}) /oxgc) { $e_string .= 'Char::Elatin1::split' . $e . qq {$1q$2 $3}; next E_STRING_LOOP; }
  0            
4508 0           elsif ($string =~ /\G \b q (\s*) (\[) [ ] (\]) /oxgc) { $e_string .= 'Char::Elatin1::split' . $e . qq {$1q$2 $3}; next E_STRING_LOOP; }
  0            
4509 0           elsif ($string =~ /\G \b q (\s*) (\<) [ ] (\>) /oxgc) { $e_string .= 'Char::Elatin1::split' . $e . qq {$1q$2 $3}; next E_STRING_LOOP; }
  0            
4510 0           elsif ($string =~ /\G \b q (\s*) (\S) [ ] (\2) /oxgc) { $e_string .= 'Char::Elatin1::split' . $e . qq {$1q$2 $3}; next E_STRING_LOOP; }
  0            
4511 0           elsif ($string =~ /\G ' [ ] ' /oxgc) { $e_string .= 'Char::Elatin1::split' . $e . qq {' '}; next E_STRING_LOOP; }
  0            
4512 0           elsif ($string =~ /\G " [ ] " /oxgc) { $e_string .= 'Char::Elatin1::split' . $e . qq {" "}; next E_STRING_LOOP; }
  0            
4513              
4514             # split qq//
4515             elsif ($string =~ /\G \b (qq) \b /oxgc) {
4516 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            
4517             else {
4518 0           while ($string !~ /\G \z/oxgc) {
4519 0 0         if ($string =~ /\G (\s+|\#.*) /oxgc) { $e_string .= $e . $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
4520 0           elsif ($string =~ /\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { $e_string .= e_split($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # qq ( ) --> qr ( )
  0            
4521 0           elsif ($string =~ /\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { $e_string .= e_split($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # qq { } --> qr { }
  0            
4522 0           elsif ($string =~ /\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { $e_string .= e_split($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # qq [ ] --> qr [ ]
  0            
4523 0           elsif ($string =~ /\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { $e_string .= e_split($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # qq < > --> qr < >
  0            
4524 0           elsif ($string =~ /\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) /oxgc) { $e_string .= e_split($e.'qr','{','}',$2,''); next E_STRING_LOOP; } # qq | | --> qr { }
  0            
4525 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            
4526             }
4527 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
4528             }
4529             }
4530              
4531             # split qr//
4532             elsif ($string =~ /\G \b (qr) \b /oxgc) {
4533 0 0         if ($string =~ /\G (\#) ((?:$qq_char)*?) (\#) ([imosxpadlubB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1,$3,$2,$4); next E_STRING_LOOP; } # qr# #
  0            
  0            
4534             else {
4535 0           while ($string !~ /\G \z/oxgc) {
4536 0 0         if ($string =~ /\G (\s+|\#.*) /oxgc) { $e_string .= $e . $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
4537 0           elsif ($string =~ /\G (\() ((?:$qq_paren)*?) (\)) ([imosxpadlubB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # qr ( )
  0            
4538 0           elsif ($string =~ /\G (\{) ((?:$qq_brace)*?) (\}) ([imosxpadlubB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # qr { }
  0            
4539 0           elsif ($string =~ /\G (\[) ((?:$qq_bracket)*?) (\]) ([imosxpadlubB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # qr [ ]
  0            
4540 0           elsif ($string =~ /\G (\<) ((?:$qq_angle)*?) (\>) ([imosxpadlubB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # qr < >
  0            
4541 0           elsif ($string =~ /\G (\') ((?:$qq_char)*?) (\') ([imosxpadlubB]*) /oxgc) { $e_string .= e_split_q($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # qr ' '
  0            
4542 0           elsif ($string =~ /\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ([imosxpadlubB]*) /oxgc) { $e_string .= e_split ($e.'qr','{','}',$2,$4); next E_STRING_LOOP; } # qr | | --> qr { }
  0            
4543 0           elsif ($string =~ /\G (\S) ((?:$qq_char)*?) (\1) ([imosxpadlubB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # qr * *
  0            
4544             }
4545 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
4546             }
4547             }
4548              
4549             # split q//
4550             elsif ($string =~ /\G \b (q) \b /oxgc) {
4551 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            
4552             else {
4553 0           while ($string !~ /\G \z/oxgc) {
4554 0 0         if ($string =~ /\G (\s+|\#.*) /oxgc) { $e_string .= $e . $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
4555 0           elsif ($string =~ /\G (\() ((?:\\\\|\\\)|\\\(|$q_paren)*?) (\)) /oxgc) { $e_string .= e_split_q($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # q ( ) --> qr ( )
  0            
4556 0           elsif ($string =~ /\G (\{) ((?:\\\\|\\\}|\\\{|$q_brace)*?) (\}) /oxgc) { $e_string .= e_split_q($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # q { } --> qr { }
  0            
4557 0           elsif ($string =~ /\G (\[) ((?:\\\\|\\\]|\\\[|$q_bracket)*?) (\]) /oxgc) { $e_string .= e_split_q($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # q [ ] --> qr [ ]
  0            
4558 0           elsif ($string =~ /\G (\<) ((?:\\\\|\\\>|\\\<|$q_angle)*?) (\>) /oxgc) { $e_string .= e_split_q($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # q < > --> qr < >
  0            
4559 0           elsif ($string =~ /\G ([*\-:?\\^|]) ((?:$q_char)*?) (\1) /oxgc) { $e_string .= e_split_q($e.'qr','{','}',$2,''); next E_STRING_LOOP; } # q | | --> qr { }
  0            
4560 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            
4561             }
4562 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
4563             }
4564             }
4565              
4566             # split m//
4567             elsif ($string =~ /\G \b (m) \b /oxgc) {
4568 0 0         if ($string =~ /\G (\#) ((?:$qq_char)*?) (\#) ([cgimosxpadlubB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1,$3,$2,$4); next E_STRING_LOOP; } # m# # --> qr # #
  0            
  0            
4569             else {
4570 0           while ($string !~ /\G \z/oxgc) {
4571 0 0         if ($string =~ /\G (\s+|\#.*) /oxgc) { $e_string .= $e . $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
4572 0           elsif ($string =~ /\G (\() ((?:$qq_paren)*?) (\)) ([cgimosxpadlubB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # m ( ) --> qr ( )
  0            
4573 0           elsif ($string =~ /\G (\{) ((?:$qq_brace)*?) (\}) ([cgimosxpadlubB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # m { } --> qr { }
  0            
4574 0           elsif ($string =~ /\G (\[) ((?:$qq_bracket)*?) (\]) ([cgimosxpadlubB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # m [ ] --> qr [ ]
  0            
4575 0           elsif ($string =~ /\G (\<) ((?:$qq_angle)*?) (\>) ([cgimosxpadlubB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # m < > --> qr < >
  0            
4576 0           elsif ($string =~ /\G (\') ((?:$qq_char)*?) (\') ([cgimosxpadlubB]*) /oxgc) { $e_string .= e_split_q($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # m ' ' --> qr ' '
  0            
4577 0           elsif ($string =~ /\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ([cgimosxpadlubB]*) /oxgc) { $e_string .= e_split ($e.'qr','{','}',$2,$4); next E_STRING_LOOP; } # m | | --> qr { }
  0            
4578 0           elsif ($string =~ /\G (\S) ((?:$qq_char)*?) (\1) ([cgimosxpadlubB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # m * * --> qr * *
  0            
4579             }
4580 0           die __FILE__, ": Search pattern not terminated";
4581             }
4582             }
4583              
4584             # split ''
4585             elsif ($string =~ /\G (\') /oxgc) {
4586 0           my $q_string = '';
4587 0           while ($string !~ /\G \z/oxgc) {
4588 0 0         if ($string =~ /\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0          
    0          
    0          
4589 0           elsif ($string =~ /\G (\\\') /oxgc) { $q_string .= $1; } # splitqr'' --> split qr''
4590 0           elsif ($string =~ /\G \' /oxgc) { $e_string .= e_split_q($e.q{ qr},"'","'",$q_string,''); next E_STRING_LOOP; } # ' ' --> qr ' '
  0            
4591 0           elsif ($string =~ /\G ($q_char) /oxgc) { $q_string .= $1; }
4592             }
4593 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
4594             }
4595              
4596             # split ""
4597             elsif ($string =~ /\G (\") /oxgc) {
4598 0           my $qq_string = '';
4599 0           while ($string !~ /\G \z/oxgc) {
4600 0 0         if ($string =~ /\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0          
    0          
    0          
4601 0           elsif ($string =~ /\G (\\\") /oxgc) { $qq_string .= $1; } # splitqr"" --> split qr""
4602 0           elsif ($string =~ /\G \" /oxgc) { $e_string .= e_split($e.q{ qr},'"','"',$qq_string,''); next E_STRING_LOOP; } # " " --> qr " "
  0            
4603 0           elsif ($string =~ /\G ($q_char) /oxgc) { $qq_string .= $1; }
4604             }
4605 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
4606             }
4607              
4608             # split //
4609             elsif ($string =~ /\G (\/) /oxgc) {
4610 0           my $regexp = '';
4611 0           while ($string !~ /\G \z/oxgc) {
4612 0 0         if ($string =~ /\G (\\\\) /oxgc) { $regexp .= $1; }
  0 0          
    0          
    0          
4613 0           elsif ($string =~ /\G (\\\/) /oxgc) { $regexp .= $1; } # splitqr// --> split qr//
4614 0           elsif ($string =~ /\G \/ ([cgimosxpadlubB]*) /oxgc) { $e_string .= e_split($e.q{ qr}, '/','/',$regexp,$1); next E_STRING_LOOP; } # / / --> qr / /
  0            
4615 0           elsif ($string =~ /\G ($q_char) /oxgc) { $regexp .= $1; }
4616             }
4617 0           die __FILE__, ": Search pattern not terminated";
4618             }
4619             }
4620              
4621             # qq//
4622             elsif ($string =~ /\G \b (qq) \b /oxgc) {
4623 0           my $ope = $1;
4624 0 0         if ($string =~ /\G (\#) ((?:$qq_char)*?) (\#) /oxgc) { # qq# #
4625 0           $e_string .= e_qq($ope,$1,$3,$2);
4626             }
4627             else {
4628 0           my $e = '';
4629 0           while ($string !~ /\G \z/oxgc) {
4630 0 0         if ($string =~ /\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
4631 0           elsif ($string =~ /\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qq ( )
  0            
4632 0           elsif ($string =~ /\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qq { }
  0            
4633 0           elsif ($string =~ /\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qq [ ]
  0            
4634 0           elsif ($string =~ /\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qq < >
  0            
4635 0           elsif ($string =~ /\G (\S) ((?:$qq_char)*?) (\1) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qq * *
  0            
4636             }
4637 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
4638             }
4639             }
4640              
4641             # qx//
4642             elsif ($string =~ /\G \b (qx) \b /oxgc) {
4643 0           my $ope = $1;
4644 0 0         if ($string =~ /\G (\#) ((?:$qq_char)*?) (\#) /oxgc) { # qx# #
4645 0           $e_string .= e_qq($ope,$1,$3,$2);
4646             }
4647             else {
4648 0           my $e = '';
4649 0           while ($string !~ /\G \z/oxgc) {
4650 0 0         if ($string =~ /\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
4651 0           elsif ($string =~ /\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qx ( )
  0            
4652 0           elsif ($string =~ /\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qx { }
  0            
4653 0           elsif ($string =~ /\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qx [ ]
  0            
4654 0           elsif ($string =~ /\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qx < >
  0            
4655 0           elsif ($string =~ /\G (\') ((?:$qq_char)*?) (\') /oxgc) { $e_string .= $e . e_q ($ope,$1,$3,$2); next E_STRING_LOOP; } # qx ' '
  0            
4656 0           elsif ($string =~ /\G (\S) ((?:$qq_char)*?) (\1) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qx * *
  0            
4657             }
4658 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
4659             }
4660             }
4661              
4662             # q//
4663             elsif ($string =~ /\G \b (q) \b /oxgc) {
4664 0           my $ope = $1;
4665 0 0         if ($string =~ /\G (\#) ((?:\\\#|\\\\|$q_char)*?) (\#) /oxgc) { # q# #
4666 0           $e_string .= e_q($ope,$1,$3,$2);
4667             }
4668             else {
4669 0           my $e = '';
4670 0           while ($string !~ /\G \z/oxgc) {
4671 0 0         if ($string =~ /\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
4672 0           elsif ($string =~ /\G (\() ((?:\\\\|\\\)|\\\(|$q_paren)*?) (\)) /oxgc) { $e_string .= $e . e_q($ope,$1,$3,$2); next E_STRING_LOOP; } # q ( )
  0            
4673 0           elsif ($string =~ /\G (\{) ((?:\\\\|\\\}|\\\{|$q_brace)*?) (\}) /oxgc) { $e_string .= $e . e_q($ope,$1,$3,$2); next E_STRING_LOOP; } # q { }
  0            
4674 0           elsif ($string =~ /\G (\[) ((?:\\\\|\\\]|\\\[|$q_bracket)*?) (\]) /oxgc) { $e_string .= $e . e_q($ope,$1,$3,$2); next E_STRING_LOOP; } # q [ ]
  0            
4675 0           elsif ($string =~ /\G (\<) ((?:\\\\|\\\>|\\\<|$q_angle)*?) (\>) /oxgc) { $e_string .= $e . e_q($ope,$1,$3,$2); next E_STRING_LOOP; } # q < >
  0            
4676 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            
4677             }
4678 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
4679             }
4680             }
4681              
4682             # ''
4683 0           elsif ($string =~ /\G (?
4684              
4685             # ""
4686 0           elsif ($string =~ /\G (\") ((?:$qq_char)*?) (\") /oxgc) { $e_string .= e_qq('',$1,$3,$2); }
4687              
4688             # ``
4689 0           elsif ($string =~ /\G (\`) ((?:$qq_char)*?) (\`) /oxgc) { $e_string .= e_qq('',$1,$3,$2); }
4690              
4691             # <<= <=> <= < operator
4692             elsif ($string =~ /\G ( <<= | <=> | <= | < ) (?= \s* [A-Za-z_0-9'"`\$\@\&\*\(\+\-] )/oxgc)
4693 0           { $e_string .= $1; }
4694              
4695             #
4696 0           elsif ($string =~ /\G (<[\$]?[A-Za-z_][A-Za-z_0-9]*>) /oxgc) { $e_string .= $1; }
4697              
4698             # --- glob
4699             elsif ($string =~ /\G < ((?:$q_char)+?) > /oxgc) {
4700 0           $e_string .= 'Char::Elatin1::glob("' . $1 . '")';
4701             }
4702              
4703             # << (bit shift) --- not here document
4704 0           elsif ($string =~ /\G ( << \s* ) (?= [0-9\$\@\&] ) /oxgc) { $slash = 'm//'; $e_string .= $1; }
  0            
4705              
4706             # <<'HEREDOC'
4707             elsif ($string =~ /\G ( << '([a-zA-Z_0-9]*)' ) /oxgc) {
4708 0           $slash = 'm//';
4709 0           my $here_quote = $1;
4710 0           my $delimiter = $2;
4711              
4712             # get here document
4713 0 0         if ($here_script eq '') {
4714 0           $here_script = CORE::substr $_, pos $_;
4715 0           $here_script =~ s/.*?\n//oxm;
4716             }
4717 0 0         if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4718 0           push @heredoc, $1 . qq{\n$delimiter\n};
4719 0           push @heredoc_delimiter, $delimiter;
4720             }
4721             else {
4722 0           die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF";
4723             }
4724 0           $e_string .= $here_quote;
4725             }
4726              
4727             # <<\HEREDOC
4728             elsif ($string =~ /\G ( << \\([a-zA-Z_0-9]+) ) /oxgc) {
4729 0           $slash = 'm//';
4730 0           my $here_quote = $1;
4731 0           my $delimiter = $2;
4732              
4733             # get here document
4734 0 0         if ($here_script eq '') {
4735 0           $here_script = CORE::substr $_, pos $_;
4736 0           $here_script =~ s/.*?\n//oxm;
4737             }
4738 0 0         if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4739 0           push @heredoc, $1 . qq{\n$delimiter\n};
4740 0           push @heredoc_delimiter, $delimiter;
4741             }
4742             else {
4743 0           die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF";
4744             }
4745 0           $e_string .= $here_quote;
4746             }
4747              
4748             # <<"HEREDOC"
4749             elsif ($string =~ /\G ( << "([a-zA-Z_0-9]*)" ) /oxgc) {
4750 0           $slash = 'm//';
4751 0           my $here_quote = $1;
4752 0           my $delimiter = $2;
4753              
4754             # get here document
4755 0 0         if ($here_script eq '') {
4756 0           $here_script = CORE::substr $_, pos $_;
4757 0           $here_script =~ s/.*?\n//oxm;
4758             }
4759 0 0         if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4760 0           push @heredoc, e_heredoc($1) . qq{\n$delimiter\n};
4761 0           push @heredoc_delimiter, $delimiter;
4762             }
4763             else {
4764 0           die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF";
4765             }
4766 0           $e_string .= $here_quote;
4767             }
4768              
4769             # <
4770             elsif ($string =~ /\G ( << ([a-zA-Z_0-9]+) ) /oxgc) {
4771 0           $slash = 'm//';
4772 0           my $here_quote = $1;
4773 0           my $delimiter = $2;
4774              
4775             # get here document
4776 0 0         if ($here_script eq '') {
4777 0           $here_script = CORE::substr $_, pos $_;
4778 0           $here_script =~ s/.*?\n//oxm;
4779             }
4780 0 0         if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4781 0           push @heredoc, e_heredoc($1) . qq{\n$delimiter\n};
4782 0           push @heredoc_delimiter, $delimiter;
4783             }
4784             else {
4785 0           die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF";
4786             }
4787 0           $e_string .= $here_quote;
4788             }
4789              
4790             # <<`HEREDOC`
4791             elsif ($string =~ /\G ( << `([a-zA-Z_0-9]*)` ) /oxgc) {
4792 0           $slash = 'm//';
4793 0           my $here_quote = $1;
4794 0           my $delimiter = $2;
4795              
4796             # get here document
4797 0 0         if ($here_script eq '') {
4798 0           $here_script = CORE::substr $_, pos $_;
4799 0           $here_script =~ s/.*?\n//oxm;
4800             }
4801 0 0         if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4802 0           push @heredoc, e_heredoc($1) . qq{\n$delimiter\n};
4803 0           push @heredoc_delimiter, $delimiter;
4804             }
4805             else {
4806 0           die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF";
4807             }
4808 0           $e_string .= $here_quote;
4809             }
4810              
4811             # any operator before div
4812             elsif ($string =~ /\G (
4813             -- | \+\+ |
4814             [\)\}\]]
4815              
4816 0           ) /oxgc) { $slash = 'div'; $e_string .= $1; }
  0            
4817              
4818             # yada-yada or triple-dot operator
4819             elsif ($string =~ /\G (
4820             \.\.\.
4821              
4822 0           ) /oxgc) { $slash = 'm//'; $e_string .= q{die('Unimplemented')}; }
  0            
4823              
4824             # any operator before m//
4825             elsif ($string =~ /\G (
4826              
4827             !~~ | !~ | != | ! |
4828             %= | % |
4829             &&= | && | &= | & |
4830             -= | -> | - |
4831             :\s*= |
4832             : |
4833             <<= | <=> | <= | < |
4834             == | => | =~ | = |
4835             >>= | >> | >= | > |
4836             \*\*= | \*\* | \*= | \* |
4837             \+= | \+ |
4838             \.\. | \.= | \. |
4839             \/\/= | \/\/ |
4840             \/= | \/ |
4841             \? |
4842             \\ |
4843             \^= | \^ |
4844             \b x= |
4845             \|\|= | \|\| | \|= | \| |
4846             ~~ | ~ |
4847             \b(?: and | cmp | eq | ge | gt | le | lt | ne | not | or | xor | x )\b |
4848             \b(?: print )\b |
4849              
4850             [,;\(\{\[]
4851              
4852 0           ) /oxgc) { $slash = 'm//'; $e_string .= $1; }
  0            
4853              
4854             # other any character
4855 0           elsif ($string =~ /\G ($q_char) /oxgc) { $e_string .= $1; }
4856              
4857             # system error
4858             else {
4859 0           die __FILE__, ": Oops, this shouldn't happen!";
4860             }
4861             }
4862              
4863 0           return $e_string;
4864             }
4865              
4866             #
4867             # character class
4868             #
4869             sub character_class {
4870 0     0 0   my($char,$modifier) = @_;
4871              
4872 0 0         if ($char eq '.') {
4873 0 0         if ($modifier =~ /s/) {
4874 0           return '${Char::Elatin1::dot_s}';
4875             }
4876             else {
4877 0           return '${Char::Elatin1::dot}';
4878             }
4879             }
4880             else {
4881 0           return Char::Elatin1::classic_character_class($char);
4882             }
4883             }
4884              
4885             #
4886             # escape capture ($1, $2, $3, ...)
4887             #
4888             sub e_capture {
4889              
4890 0     0 0   return join '', '${', $_[0], '}';
4891             }
4892              
4893             #
4894             # escape transliteration (tr/// or y///)
4895             #
4896             sub e_tr {
4897 0     0 0   my($variable,$charclass,$e,$charclass2,$modifier) = @_;
4898 0           my $e_tr = '';
4899 0   0       $modifier ||= '';
4900              
4901 0           $slash = 'div';
4902              
4903             # quote character class 1
4904 0           $charclass = q_tr($charclass);
4905              
4906             # quote character class 2
4907 0           $charclass2 = q_tr($charclass2);
4908              
4909             # /b /B modifier
4910 0 0         if ($modifier =~ tr/bB//d) {
4911 0 0         if ($variable eq '') {
4912 0           $e_tr = qq{tr$charclass$e$charclass2$modifier};
4913             }
4914             else {
4915 0           $e_tr = qq{$variable${bind_operator}tr$charclass$e$charclass2$modifier};
4916             }
4917             }
4918             else {
4919 0 0         if ($variable eq '') {
4920 0           $e_tr = qq{Char::Elatin1::tr(\$_,' =~ ',$charclass,$e$charclass2,'$modifier')};
4921             }
4922             else {
4923 0           $e_tr = qq{Char::Elatin1::tr($variable,'$bind_operator',$charclass,$e$charclass2,'$modifier')};
4924             }
4925             }
4926              
4927             # clear tr/// variable
4928 0           $tr_variable = '';
4929 0           $bind_operator = '';
4930              
4931 0           return $e_tr;
4932             }
4933              
4934             #
4935             # quote for escape transliteration (tr/// or y///)
4936             #
4937             sub q_tr {
4938 0     0 0   my($charclass) = @_;
4939              
4940             # quote character class
4941 0 0         if ($charclass !~ /'/oxms) {
    0          
    0          
    0          
    0          
    0          
4942 0           return e_q('', "'", "'", $charclass); # --> q' '
4943             }
4944             elsif ($charclass !~ /\//oxms) {
4945 0           return e_q('q', '/', '/', $charclass); # --> q/ /
4946             }
4947             elsif ($charclass !~ /\#/oxms) {
4948 0           return e_q('q', '#', '#', $charclass); # --> q# #
4949             }
4950             elsif ($charclass !~ /[\<\>]/oxms) {
4951 0           return e_q('q', '<', '>', $charclass); # --> q< >
4952             }
4953             elsif ($charclass !~ /[\(\)]/oxms) {
4954 0           return e_q('q', '(', ')', $charclass); # --> q( )
4955             }
4956             elsif ($charclass !~ /[\{\}]/oxms) {
4957 0           return e_q('q', '{', '}', $charclass); # --> q{ }
4958             }
4959             else {
4960 0           for my $char (qw( ! " $ % & * + . : = ? @ ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
4961 0 0         if ($charclass !~ /\Q$char\E/xms) {
4962 0           return e_q('q', $char, $char, $charclass);
4963             }
4964             }
4965             }
4966              
4967 0           return e_q('q', '{', '}', $charclass);
4968             }
4969              
4970             #
4971             # escape q string (q//, '')
4972             #
4973             sub e_q {
4974 0     0 0   my($ope,$delimiter,$end_delimiter,$string) = @_;
4975              
4976 0           $slash = 'div';
4977              
4978 0           return join '', $ope, $delimiter, $string, $end_delimiter;
4979             }
4980              
4981             #
4982             # escape qq string (qq//, "", qx//, ``)
4983             #
4984             sub e_qq {
4985 0     0 0   my($ope,$delimiter,$end_delimiter,$string) = @_;
4986              
4987 0           $slash = 'div';
4988              
4989 0           my $left_e = 0;
4990 0           my $right_e = 0;
4991 0           my @char = $string =~ /\G(
4992             \\o\{ [0-7]+ \} |
4993             \\x\{ [0-9A-Fa-f]+ \} |
4994             \\N\{ [^0-9\}][^\}]* \} |
4995             \$` | \$\{`\} | \$ \s* PREMATCH | \$ \s* \{ \s* PREMATCH \s* \} | \$ \s* \{\^PREMATCH\} |
4996             \$& | \$\{&\} | \$ \s* MATCH | \$ \s* \{ \s* MATCH \s* \} | \$ \s* \{\^MATCH\} |
4997             \$ \s* POSTMATCH | \$ \s* \{ \s* POSTMATCH \s* \} | \$ \s* \{\^POSTMATCH\} |
4998             \$ \s* \d+ |
4999             \$ \s* \{ \s* \d+ \s* \} |
5000             \$ \$ (?![\w\{]) |
5001             \$ \s* \$ \s* $qq_variable |
5002             \\?(?:$q_char)
5003             )/oxmsg;
5004              
5005 0           for (my $i=0; $i <= $#char; $i++) {
5006              
5007             # "\L\u" --> "\u\L"
5008 0 0 0       if (($char[$i] eq '\L') and ($char[$i+1] eq '\u')) {
    0 0        
    0          
    0          
    0          
5009 0           @char[$i,$i+1] = @char[$i+1,$i];
5010             }
5011              
5012             # "\U\l" --> "\l\U"
5013             elsif (($char[$i] eq '\U') and ($char[$i+1] eq '\l')) {
5014 0           @char[$i,$i+1] = @char[$i+1,$i];
5015             }
5016              
5017             # octal escape sequence
5018             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
5019 0           $char[$i] = Char::Elatin1::octchr($1);
5020             }
5021              
5022             # hexadecimal escape sequence
5023             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
5024 0           $char[$i] = Char::Elatin1::hexchr($1);
5025             }
5026              
5027             # \N{CHARNAME} --> N{CHARNAME}
5028             elsif ($char[$i] =~ /\A \\ ( N\{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
5029 0           $char[$i] = $1;
5030             }
5031              
5032 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          
5033             }
5034              
5035             # \F
5036             #
5037             # P.69 Table 2-6. Translation escapes
5038             # in Chapter 2: Bits and Pieces
5039             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
5040             # (and so on)
5041              
5042             # \u \l \U \L \F \Q \E
5043 0           elsif ($char[$i] =~ /\A ([<>]) \z/oxms) {
5044 0 0         if ($right_e < $left_e) {
5045 0           $char[$i] = '\\' . $char[$i];
5046             }
5047             }
5048             elsif ($char[$i] eq '\u') {
5049              
5050             # "STRING @{[ LIST EXPR ]} MORE STRING"
5051              
5052             # P.257 Other Tricks You Can Do with Hard References
5053             # in Chapter 8: References
5054             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
5055              
5056             # P.353 Other Tricks You Can Do with Hard References
5057             # in Chapter 8: References
5058             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
5059              
5060             # (and so on)
5061              
5062 0           $char[$i] = '@{[Char::Elatin1::ucfirst qq<';
5063 0           $left_e++;
5064             }
5065             elsif ($char[$i] eq '\l') {
5066 0           $char[$i] = '@{[Char::Elatin1::lcfirst qq<';
5067 0           $left_e++;
5068             }
5069             elsif ($char[$i] eq '\U') {
5070 0           $char[$i] = '@{[Char::Elatin1::uc qq<';
5071 0           $left_e++;
5072             }
5073             elsif ($char[$i] eq '\L') {
5074 0           $char[$i] = '@{[Char::Elatin1::lc qq<';
5075 0           $left_e++;
5076             }
5077             elsif ($char[$i] eq '\F') {
5078 0           $char[$i] = '@{[Char::Elatin1::fc qq<';
5079 0           $left_e++;
5080             }
5081             elsif ($char[$i] eq '\Q') {
5082 0           $char[$i] = '@{[CORE::quotemeta qq<';
5083 0           $left_e++;
5084             }
5085             elsif ($char[$i] eq '\E') {
5086 0 0         if ($right_e < $left_e) {
5087 0           $char[$i] = '>]}';
5088 0           $right_e++;
5089             }
5090             else {
5091 0           $char[$i] = '';
5092             }
5093             }
5094             elsif ($char[$i] eq '\Q') {
5095 0           while (1) {
5096 0 0         if (++$i > $#char) {
5097 0           last;
5098             }
5099 0 0         if ($char[$i] eq '\E') {
5100 0           last;
5101             }
5102             }
5103             }
5104             elsif ($char[$i] eq '\E') {
5105             }
5106              
5107             # $0 --> $0
5108             elsif ($char[$i] =~ /\A \$ 0 \z/oxms) {
5109             }
5110             elsif ($char[$i] =~ /\A \$ \{ \s* 0 \s* \} \z/oxms) {
5111             }
5112              
5113             # $$ --> $$
5114             elsif ($char[$i] =~ /\A \$\$ \z/oxms) {
5115             }
5116              
5117             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
5118             # $1, $2, $3 --> $1, $2, $3 otherwise
5119             elsif ($char[$i] =~ /\A \$ ([1-9][0-9]*) \z/oxms) {
5120 0           $char[$i] = e_capture($1);
5121             }
5122             elsif ($char[$i] =~ /\A \$ \{ \s* ([1-9][0-9]*) \s* \} \z/oxms) {
5123 0           $char[$i] = e_capture($1);
5124             }
5125              
5126             # $$foo[ ... ] --> $ $foo->[ ... ]
5127             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) ( \[ (?:$qq_bracket)*? \] ) \z/oxms) {
5128 0           $char[$i] = e_capture($1.'->'.$2);
5129             }
5130              
5131             # $$foo{ ... } --> $ $foo->{ ... }
5132             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) ( \{ (?:$qq_brace)*? \} ) \z/oxms) {
5133 0           $char[$i] = e_capture($1.'->'.$2);
5134             }
5135              
5136             # $$foo
5137             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) \z/oxms) {
5138 0           $char[$i] = e_capture($1);
5139             }
5140              
5141             # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Char::Elatin1::PREMATCH()
5142             elsif ($char[$i] =~ /\A ( \$` | \$\{`\} | \$ \s* PREMATCH | \$ \s* \{ \s* PREMATCH \s* \} | \$ \s* \{\^PREMATCH\} ) \z/oxmsgc) {
5143 0           $char[$i] = '@{[Char::Elatin1::PREMATCH()]}';
5144             }
5145              
5146             # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Char::Elatin1::MATCH()
5147             elsif ($char[$i] =~ /\A ( \$& | \$\{&\} | \$ \s* MATCH | \$ \s* \{ \s* MATCH \s* \} | \$ \s* \{\^MATCH\} ) \z/oxmsgc) {
5148 0           $char[$i] = '@{[Char::Elatin1::MATCH()]}';
5149             }
5150              
5151             # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Char::Elatin1::POSTMATCH()
5152             elsif ($char[$i] =~ /\A ( \$ \s* POSTMATCH | \$ \s* \{ \s* POSTMATCH \s* \} | \$ \s* \{\^POSTMATCH\} ) \z/oxmsgc) {
5153 0           $char[$i] = '@{[Char::Elatin1::POSTMATCH()]}';
5154             }
5155              
5156             # ${ foo } --> ${ foo }
5157             elsif ($char[$i] =~ /\A \$ \s* \{ \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* \} \z/oxms) {
5158             }
5159              
5160             # ${ ... }
5161             elsif ($char[$i] =~ /\A \$ \s* \{ \s* ( .+ ) \s* \} \z/oxms) {
5162 0           $char[$i] = e_capture($1);
5163             }
5164             }
5165              
5166             # return string
5167 0 0         if ($left_e > $right_e) {
5168 0           return join '', $ope, $delimiter, @char, '>]}' x ($left_e - $right_e), $end_delimiter;
5169             }
5170 0           return join '', $ope, $delimiter, @char, $end_delimiter;
5171             }
5172              
5173             #
5174             # escape qw string (qw//)
5175             #
5176             sub e_qw {
5177 0     0 0   my($ope,$delimiter,$end_delimiter,$string) = @_;
5178              
5179 0           $slash = 'div';
5180              
5181             # choice again delimiter
5182 0           my %octet = map {$_ => 1} ($string =~ /\G ([\x00-\xFF]) /oxmsg);
  0            
5183 0 0         if (not $octet{$end_delimiter}) {
    0          
    0          
    0          
    0          
5184 0           return join '', $ope, $delimiter, $string, $end_delimiter;
5185             }
5186             elsif (not $octet{')'}) {
5187 0           return join '', $ope, '(', $string, ')';
5188             }
5189             elsif (not $octet{'}'}) {
5190 0           return join '', $ope, '{', $string, '}';
5191             }
5192             elsif (not $octet{']'}) {
5193 0           return join '', $ope, '[', $string, ']';
5194             }
5195             elsif (not $octet{'>'}) {
5196 0           return join '', $ope, '<', $string, '>';
5197             }
5198             else {
5199 0           for my $char (qw( ! " $ % & * + - . / : = ? @ ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
5200 0 0         if (not $octet{$char}) {
5201 0           return join '', $ope, $char, $string, $char;
5202             }
5203             }
5204             }
5205              
5206             # qw/AAA BBB C'CC/ --> ('AAA', 'BBB', 'C\'CC')
5207 0           my @string = CORE::split(/\s+/, $string);
5208 0           for my $string (@string) {
5209 0           my @octet = $string =~ /\G ([\x00-\xFF]) /oxmsg;
5210 0           for my $octet (@octet) {
5211 0 0         if ($octet =~ /\A (['\\]) \z/oxms) {
5212 0           $octet = '\\' . $1;
5213             }
5214             }
5215 0           $string = join '', @octet;
5216             }
5217 0           return join '', '(', (join ', ', map { "'$_'" } @string), ')';
  0            
5218             }
5219              
5220             #
5221             # escape here document (<<"HEREDOC", <
5222             #
5223             sub e_heredoc {
5224 0     0 0   my($string) = @_;
5225              
5226 0           $slash = 'm//';
5227              
5228 0           my $metachar = qr/[\@\\|]/oxms; # '|' is for <<`HEREDOC`
5229              
5230 0           my $left_e = 0;
5231 0           my $right_e = 0;
5232 0           my @char = $string =~ /\G(
5233             \\o\{ [0-7]+ \} |
5234             \\x\{ [0-9A-Fa-f]+ \} |
5235             \\N\{ [^0-9\}][^\}]* \} |
5236             \$` | \$\{`\} | \$ \s* PREMATCH | \$ \s* \{ \s* PREMATCH \s* \} | \$ \s* \{\^PREMATCH\} |
5237             \$& | \$\{&\} | \$ \s* MATCH | \$ \s* \{ \s* MATCH \s* \} | \$ \s* \{\^MATCH\} |
5238             \$ \s* POSTMATCH | \$ \s* \{ \s* POSTMATCH \s* \} | \$ \s* \{\^POSTMATCH\} |
5239             \$ \s* \d+ |
5240             \$ \s* \{ \s* \d+ \s* \} |
5241             \$ \$ (?![\w\{]) |
5242             \$ \s* \$ \s* $qq_variable |
5243             \\?(?:$q_char)
5244             )/oxmsg;
5245              
5246 0           for (my $i=0; $i <= $#char; $i++) {
5247              
5248             # "\L\u" --> "\u\L"
5249 0 0 0       if (($char[$i] eq '\L') and ($char[$i+1] eq '\u')) {
    0 0        
    0          
    0          
    0          
5250 0           @char[$i,$i+1] = @char[$i+1,$i];
5251             }
5252              
5253             # "\U\l" --> "\l\U"
5254             elsif (($char[$i] eq '\U') and ($char[$i+1] eq '\l')) {
5255 0           @char[$i,$i+1] = @char[$i+1,$i];
5256             }
5257              
5258             # octal escape sequence
5259             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
5260 0           $char[$i] = Char::Elatin1::octchr($1);
5261             }
5262              
5263             # hexadecimal escape sequence
5264             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
5265 0           $char[$i] = Char::Elatin1::hexchr($1);
5266             }
5267              
5268             # \N{CHARNAME} --> N{CHARNAME}
5269             elsif ($char[$i] =~ /\A \\ ( N\{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
5270 0           $char[$i] = $1;
5271             }
5272              
5273 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          
5274             }
5275              
5276             # \u \l \U \L \F \Q \E
5277 0           elsif ($char[$i] =~ /\A ([<>]) \z/oxms) {
5278 0 0         if ($right_e < $left_e) {
5279 0           $char[$i] = '\\' . $char[$i];
5280             }
5281             }
5282             elsif ($char[$i] eq '\u') {
5283 0           $char[$i] = '@{[Char::Elatin1::ucfirst qq<';
5284 0           $left_e++;
5285             }
5286             elsif ($char[$i] eq '\l') {
5287 0           $char[$i] = '@{[Char::Elatin1::lcfirst qq<';
5288 0           $left_e++;
5289             }
5290             elsif ($char[$i] eq '\U') {
5291 0           $char[$i] = '@{[Char::Elatin1::uc qq<';
5292 0           $left_e++;
5293             }
5294             elsif ($char[$i] eq '\L') {
5295 0           $char[$i] = '@{[Char::Elatin1::lc qq<';
5296 0           $left_e++;
5297             }
5298             elsif ($char[$i] eq '\F') {
5299 0           $char[$i] = '@{[Char::Elatin1::fc qq<';
5300 0           $left_e++;
5301             }
5302             elsif ($char[$i] eq '\Q') {
5303 0           $char[$i] = '@{[CORE::quotemeta qq<';
5304 0           $left_e++;
5305             }
5306             elsif ($char[$i] eq '\E') {
5307 0 0         if ($right_e < $left_e) {
5308 0           $char[$i] = '>]}';
5309 0           $right_e++;
5310             }
5311             else {
5312 0           $char[$i] = '';
5313             }
5314             }
5315             elsif ($char[$i] eq '\Q') {
5316 0           while (1) {
5317 0 0         if (++$i > $#char) {
5318 0           last;
5319             }
5320 0 0         if ($char[$i] eq '\E') {
5321 0           last;
5322             }
5323             }
5324             }
5325             elsif ($char[$i] eq '\E') {
5326             }
5327              
5328             # $0 --> $0
5329             elsif ($char[$i] =~ /\A \$ 0 \z/oxms) {
5330             }
5331             elsif ($char[$i] =~ /\A \$ \{ \s* 0 \s* \} \z/oxms) {
5332             }
5333              
5334             # $$ --> $$
5335             elsif ($char[$i] =~ /\A \$\$ \z/oxms) {
5336             }
5337              
5338             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
5339             # $1, $2, $3 --> $1, $2, $3 otherwise
5340             elsif ($char[$i] =~ /\A \$ ([1-9][0-9]*) \z/oxms) {
5341 0           $char[$i] = e_capture($1);
5342             }
5343             elsif ($char[$i] =~ /\A \$ \{ \s* ([1-9][0-9]*) \s* \} \z/oxms) {
5344 0           $char[$i] = e_capture($1);
5345             }
5346              
5347             # $$foo[ ... ] --> $ $foo->[ ... ]
5348             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) ( \[ (?:$qq_bracket)*? \] ) \z/oxms) {
5349 0           $char[$i] = e_capture($1.'->'.$2);
5350             }
5351              
5352             # $$foo{ ... } --> $ $foo->{ ... }
5353             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) ( \{ (?:$qq_brace)*? \} ) \z/oxms) {
5354 0           $char[$i] = e_capture($1.'->'.$2);
5355             }
5356              
5357             # $$foo
5358             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) \z/oxms) {
5359 0           $char[$i] = e_capture($1);
5360             }
5361              
5362             # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Char::Elatin1::PREMATCH()
5363             elsif ($char[$i] =~ /\A ( \$` | \$\{`\} | \$ \s* PREMATCH | \$ \s* \{ \s* PREMATCH \s* \} | \$ \s* \{\^PREMATCH\} ) \z/oxmsgc) {
5364 0           $char[$i] = '@{[Char::Elatin1::PREMATCH()]}';
5365             }
5366              
5367             # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Char::Elatin1::MATCH()
5368             elsif ($char[$i] =~ /\A ( \$& | \$\{&\} | \$ \s* MATCH | \$ \s* \{ \s* MATCH \s* \} | \$ \s* \{\^MATCH\} ) \z/oxmsgc) {
5369 0           $char[$i] = '@{[Char::Elatin1::MATCH()]}';
5370             }
5371              
5372             # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Char::Elatin1::POSTMATCH()
5373             elsif ($char[$i] =~ /\A ( \$ \s* POSTMATCH | \$ \s* \{ \s* POSTMATCH \s* \} | \$ \s* \{\^POSTMATCH\} ) \z/oxmsgc) {
5374 0           $char[$i] = '@{[Char::Elatin1::POSTMATCH()]}';
5375             }
5376              
5377             # ${ foo } --> ${ foo }
5378             elsif ($char[$i] =~ /\A \$ \s* \{ \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* \} \z/oxms) {
5379             }
5380              
5381             # ${ ... }
5382             elsif ($char[$i] =~ /\A \$ \s* \{ \s* ( .+ ) \s* \} \z/oxms) {
5383 0           $char[$i] = e_capture($1);
5384             }
5385             }
5386              
5387             # return string
5388 0 0         if ($left_e > $right_e) {
5389 0           return join '', @char, '>]}' x ($left_e - $right_e);
5390             }
5391 0           return join '', @char;
5392             }
5393              
5394             #
5395             # escape regexp (m//, qr//)
5396             #
5397             sub e_qr {
5398 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
5399 0   0       $modifier ||= '';
5400              
5401 0           $modifier =~ tr/p//d;
5402 0 0         if ($modifier =~ /([adlu])/oxms) {
5403 0           my $line = 0;
5404 0           for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
5405 0 0         if ($filename ne __FILE__) {
5406 0           $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
5407 0           last;
5408             }
5409             }
5410 0           die qq{Unsupported modifier "$1" used at line $line.\n};
5411             }
5412              
5413 0           $slash = 'div';
5414              
5415             # literal null string pattern
5416 0 0         if ($string eq '') {
    0          
5417 0           $modifier =~ tr/bB//d;
5418 0           $modifier =~ tr/i//d;
5419 0           return join '', $ope, $delimiter, $end_delimiter, $modifier;
5420             }
5421              
5422             # /b /B modifier
5423             elsif ($modifier =~ tr/bB//d) {
5424              
5425             # choice again delimiter
5426 0 0         if ($delimiter =~ / [\@:] /oxms) {
5427 0           my @char = $string =~ /\G([\x00-\xFF])/oxmsg;
5428 0           my %octet = map {$_ => 1} @char;
  0            
5429 0 0         if (not $octet{')'}) {
    0          
    0          
    0          
5430 0           $delimiter = '(';
5431 0           $end_delimiter = ')';
5432             }
5433             elsif (not $octet{'}'}) {
5434 0           $delimiter = '{';
5435 0           $end_delimiter = '}';
5436             }
5437             elsif (not $octet{']'}) {
5438 0           $delimiter = '[';
5439 0           $end_delimiter = ']';
5440             }
5441             elsif (not $octet{'>'}) {
5442 0           $delimiter = '<';
5443 0           $end_delimiter = '>';
5444             }
5445             else {
5446 0           for my $char (qw( ! " $ % & * + - . / = ? ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
5447 0 0         if (not $octet{$char}) {
5448 0           $delimiter = $char;
5449 0           $end_delimiter = $char;
5450 0           last;
5451             }
5452             }
5453             }
5454             }
5455              
5456 0 0 0       if (($ope =~ /\A m? \z/oxms) and ($delimiter eq '?')) {
5457 0           return join '', $ope, $delimiter, $string, $matched, $end_delimiter, $modifier;
5458             }
5459             else {
5460 0           return join '', $ope, $delimiter, '(?:', $string, ')', $matched, $end_delimiter, $modifier;
5461             }
5462             }
5463              
5464 0 0         my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
5465 0           my $metachar = qr/[\@\\|[\]{^]/oxms;
5466              
5467             # split regexp
5468 0           my @char = $string =~ /\G(
5469             \\o\{ [0-7]+ \} |
5470             \\ [0-7]{2,3} |
5471             \\x\{ [0-9A-Fa-f]+ \} |
5472             \\x [0-9A-Fa-f]{1,2} |
5473             \\c [\x40-\x5F] |
5474             \\N\{ [^0-9\}][^\}]* \} |
5475             \\p\{ [^0-9\}][^\}]* \} |
5476             \\P\{ [^0-9\}][^\}]* \} |
5477             \\ (?:$q_char) |
5478             \$` | \$\{`\} | \$ \s* PREMATCH | \$ \s* \{ \s* PREMATCH \s* \} | \$ \s* \{\^PREMATCH\} |
5479             \$& | \$\{&\} | \$ \s* MATCH | \$ \s* \{ \s* MATCH \s* \} | \$ \s* \{\^MATCH\} |
5480             \$ \s* POSTMATCH | \$ \s* \{ \s* POSTMATCH \s* \} | \$ \s* \{\^POSTMATCH\} |
5481             [\$\@] $qq_variable |
5482             \$ \s* \d+ |
5483             \$ \s* \{ \s* \d+ \s* \} |
5484             \$ \$ (?![\w\{]) |
5485             \$ \s* \$ \s* $qq_variable |
5486             \[\:\^ (?:alnum|alpha|ascii|blank|cntrl|digit|graph|lower|print|punct|space|upper|word|xdigit) :\] |
5487             \[\: (?:alnum|alpha|ascii|blank|cntrl|digit|graph|lower|print|punct|space|upper|word|xdigit) :\] |
5488             \[\^ |
5489             \(\? |
5490             (?:$q_char)
5491             )/oxmsg;
5492              
5493             # choice again delimiter
5494 0 0         if ($delimiter =~ / [\@:] /oxms) {
5495 0           my %octet = map {$_ => 1} @char;
  0            
5496 0 0         if (not $octet{')'}) {
    0          
    0          
    0          
5497 0           $delimiter = '(';
5498 0           $end_delimiter = ')';
5499             }
5500             elsif (not $octet{'}'}) {
5501 0           $delimiter = '{';
5502 0           $end_delimiter = '}';
5503             }
5504             elsif (not $octet{']'}) {
5505 0           $delimiter = '[';
5506 0           $end_delimiter = ']';
5507             }
5508             elsif (not $octet{'>'}) {
5509 0           $delimiter = '<';
5510 0           $end_delimiter = '>';
5511             }
5512             else {
5513 0           for my $char (qw( ! " $ % & * + - . / = ? ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
5514 0 0         if (not $octet{$char}) {
5515 0           $delimiter = $char;
5516 0           $end_delimiter = $char;
5517 0           last;
5518             }
5519             }
5520             }
5521             }
5522              
5523 0           my $left_e = 0;
5524 0           my $right_e = 0;
5525 0           for (my $i=0; $i <= $#char; $i++) {
5526              
5527             # "\L\u" --> "\u\L"
5528 0 0 0       if (($char[$i] eq '\L') and ($char[$i+1] eq '\u')) {
    0 0        
    0          
    0          
    0          
    0          
    0          
    0          
5529 0           @char[$i,$i+1] = @char[$i+1,$i];
5530             }
5531              
5532             # "\U\l" --> "\l\U"
5533             elsif (($char[$i] eq '\U') and ($char[$i+1] eq '\l')) {
5534 0           @char[$i,$i+1] = @char[$i+1,$i];
5535             }
5536              
5537             # octal escape sequence
5538             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
5539 0           $char[$i] = Char::Elatin1::octchr($1);
5540             }
5541              
5542             # hexadecimal escape sequence
5543             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
5544 0           $char[$i] = Char::Elatin1::hexchr($1);
5545             }
5546              
5547             # \N{CHARNAME} --> N\{CHARNAME}
5548             elsif ($char[$i] =~ /\A \\ (N) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
5549 0           $char[$i] = $1 . '\\' . $2;
5550             }
5551              
5552             # \p{PROPERTY} --> p\{PROPERTY}
5553             elsif ($char[$i] =~ /\A \\ (p) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
5554 0           $char[$i] = $1 . '\\' . $2;
5555             }
5556              
5557             # \P{PROPERTY} --> P\{PROPERTY}
5558             elsif ($char[$i] =~ /\A \\ (P) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
5559 0           $char[$i] = $1 . '\\' . $2;
5560             }
5561              
5562             # \p, \P, \X --> p, P, X
5563             elsif ($char[$i] =~ /\A \\ ( [pPX] ) \z/oxms) {
5564 0           $char[$i] = $1;
5565             }
5566              
5567 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          
5568             }
5569              
5570             # join separated multiple-octet
5571 0           elsif ($char[$i] =~ /\A (?: \\ [0-7]{2,3} | \\x [0-9A-Fa-f]{1,2}) \z/oxms) {
5572 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        
5573 0           $char[$i] .= join '', splice @char, $i+1, 3;
5574             }
5575             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)) {
5576 0           $char[$i] .= join '', splice @char, $i+1, 2;
5577             }
5578             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)) {
5579 0           $char[$i] .= join '', splice @char, $i+1, 1;
5580             }
5581             }
5582              
5583             # open character class [...]
5584             elsif ($char[$i] eq '[') {
5585 0           my $left = $i;
5586              
5587             # [] make die "Unmatched [] in regexp ..."
5588             # (and so on)
5589              
5590 0 0         if ($char[$i+1] eq ']') {
5591 0           $i++;
5592             }
5593              
5594 0           while (1) {
5595 0 0         if (++$i > $#char) {
5596 0           die __FILE__, ": Unmatched [] in regexp";
5597             }
5598 0 0         if ($char[$i] eq ']') {
5599 0           my $right = $i;
5600              
5601             # [...]
5602 0 0         if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
5603 0           splice @char, $left, $right-$left+1, sprintf(q{@{[Char::Elatin1::charlist_qr(%s,'%s')]}}, join(',', map {qq_stuff($delimiter,$end_delimiter,$_)} @char[$left+1..$right-1]), $modifier);
  0            
5604             }
5605             else {
5606 0           splice @char, $left, $right-$left+1, Char::Elatin1::charlist_qr(@char[$left+1..$right-1], $modifier);
5607             }
5608              
5609 0           $i = $left;
5610 0           last;
5611             }
5612             }
5613             }
5614              
5615             # open character class [^...]
5616             elsif ($char[$i] eq '[^') {
5617 0           my $left = $i;
5618              
5619             # [^] make die "Unmatched [] in regexp ..."
5620             # (and so on)
5621              
5622 0 0         if ($char[$i+1] eq ']') {
5623 0           $i++;
5624             }
5625              
5626 0           while (1) {
5627 0 0         if (++$i > $#char) {
5628 0           die __FILE__, ": Unmatched [] in regexp";
5629             }
5630 0 0         if ($char[$i] eq ']') {
5631 0           my $right = $i;
5632              
5633             # [^...]
5634 0 0         if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
5635 0           splice @char, $left, $right-$left+1, sprintf(q{@{[Char::Elatin1::charlist_not_qr(%s,'%s')]}}, join(',', map {qq_stuff($delimiter,$end_delimiter,$_)} @char[$left+1..$right-1]), $modifier);
  0            
5636             }
5637             else {
5638 0           splice @char, $left, $right-$left+1, Char::Elatin1::charlist_not_qr(@char[$left+1..$right-1], $modifier);
5639             }
5640              
5641 0           $i = $left;
5642 0           last;
5643             }
5644             }
5645             }
5646              
5647             # rewrite character class or escape character
5648             elsif (my $char = character_class($char[$i],$modifier)) {
5649 0           $char[$i] = $char;
5650             }
5651              
5652             # /i modifier
5653             elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Char::Elatin1::uc($char[$i]) ne Char::Elatin1::fc($char[$i]))) {
5654 0 0         if (CORE::length(Char::Elatin1::fc($char[$i])) == 1) {
5655 0           $char[$i] = '[' . Char::Elatin1::uc($char[$i]) . Char::Elatin1::fc($char[$i]) . ']';
5656             }
5657             else {
5658 0           $char[$i] = '(?:' . Char::Elatin1::uc($char[$i]) . '|' . Char::Elatin1::fc($char[$i]) . ')';
5659             }
5660             }
5661              
5662             # \u \l \U \L \F \Q \E
5663             elsif ($char[$i] =~ /\A [<>] \z/oxms) {
5664 0 0         if ($right_e < $left_e) {
5665 0           $char[$i] = '\\' . $char[$i];
5666             }
5667             }
5668             elsif ($char[$i] eq '\u') {
5669 0           $char[$i] = '@{[Char::Elatin1::ucfirst qq<';
5670 0           $left_e++;
5671             }
5672             elsif ($char[$i] eq '\l') {
5673 0           $char[$i] = '@{[Char::Elatin1::lcfirst qq<';
5674 0           $left_e++;
5675             }
5676             elsif ($char[$i] eq '\U') {
5677 0           $char[$i] = '@{[Char::Elatin1::uc qq<';
5678 0           $left_e++;
5679             }
5680             elsif ($char[$i] eq '\L') {
5681 0           $char[$i] = '@{[Char::Elatin1::lc qq<';
5682 0           $left_e++;
5683             }
5684             elsif ($char[$i] eq '\F') {
5685 0           $char[$i] = '@{[Char::Elatin1::fc qq<';
5686 0           $left_e++;
5687             }
5688             elsif ($char[$i] eq '\Q') {
5689 0           $char[$i] = '@{[CORE::quotemeta qq<';
5690 0           $left_e++;
5691             }
5692             elsif ($char[$i] eq '\E') {
5693 0 0         if ($right_e < $left_e) {
5694 0           $char[$i] = '>]}';
5695 0           $right_e++;
5696             }
5697             else {
5698 0           $char[$i] = '';
5699             }
5700             }
5701             elsif ($char[$i] eq '\Q') {
5702 0           while (1) {
5703 0 0         if (++$i > $#char) {
5704 0           last;
5705             }
5706 0 0         if ($char[$i] eq '\E') {
5707 0           last;
5708             }
5709             }
5710             }
5711             elsif ($char[$i] eq '\E') {
5712             }
5713              
5714             # $0 --> $0
5715             elsif ($char[$i] =~ /\A \$ 0 \z/oxms) {
5716 0 0         if ($ignorecase) {
5717 0           $char[$i] = '@{[Char::Elatin1::ignorecase(' . $char[$i] . ')]}';
5718             }
5719             }
5720             elsif ($char[$i] =~ /\A \$ \{ \s* 0 \s* \} \z/oxms) {
5721 0 0         if ($ignorecase) {
5722 0           $char[$i] = '@{[Char::Elatin1::ignorecase(' . $char[$i] . ')]}';
5723             }
5724             }
5725              
5726             # $$ --> $$
5727             elsif ($char[$i] =~ /\A \$\$ \z/oxms) {
5728             }
5729              
5730             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
5731             # $1, $2, $3 --> $1, $2, $3 otherwise
5732             elsif ($char[$i] =~ /\A \$ ([1-9][0-9]*) \z/oxms) {
5733 0           $char[$i] = e_capture($1);
5734 0 0         if ($ignorecase) {
5735 0           $char[$i] = '@{[Char::Elatin1::ignorecase(' . $char[$i] . ')]}';
5736             }
5737             }
5738             elsif ($char[$i] =~ /\A \$ \{ \s* ([1-9][0-9]*) \s* \} \z/oxms) {
5739 0           $char[$i] = e_capture($1);
5740 0 0         if ($ignorecase) {
5741 0           $char[$i] = '@{[Char::Elatin1::ignorecase(' . $char[$i] . ')]}';
5742             }
5743             }
5744              
5745             # $$foo[ ... ] --> $ $foo->[ ... ]
5746             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) ( \[ (?:$qq_bracket)*? \] ) \z/oxms) {
5747 0           $char[$i] = e_capture($1.'->'.$2);
5748 0 0         if ($ignorecase) {
5749 0           $char[$i] = '@{[Char::Elatin1::ignorecase(' . $char[$i] . ')]}';
5750             }
5751             }
5752              
5753             # $$foo{ ... } --> $ $foo->{ ... }
5754             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) ( \{ (?:$qq_brace)*? \} ) \z/oxms) {
5755 0           $char[$i] = e_capture($1.'->'.$2);
5756 0 0         if ($ignorecase) {
5757 0           $char[$i] = '@{[Char::Elatin1::ignorecase(' . $char[$i] . ')]}';
5758             }
5759             }
5760              
5761             # $$foo
5762             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) \z/oxms) {
5763 0           $char[$i] = e_capture($1);
5764 0 0         if ($ignorecase) {
5765 0           $char[$i] = '@{[Char::Elatin1::ignorecase(' . $char[$i] . ')]}';
5766             }
5767             }
5768              
5769             # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Char::Elatin1::PREMATCH()
5770             elsif ($char[$i] =~ /\A ( \$` | \$\{`\} | \$ \s* PREMATCH | \$ \s* \{ \s* PREMATCH \s* \} | \$ \s* \{\^PREMATCH\} ) \z/oxmsgc) {
5771 0 0         if ($ignorecase) {
5772 0           $char[$i] = '@{[Char::Elatin1::ignorecase(Char::Elatin1::PREMATCH())]}';
5773             }
5774             else {
5775 0           $char[$i] = '@{[Char::Elatin1::PREMATCH()]}';
5776             }
5777             }
5778              
5779             # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Char::Elatin1::MATCH()
5780             elsif ($char[$i] =~ /\A ( \$& | \$\{&\} | \$ \s* MATCH | \$ \s* \{ \s* MATCH \s* \} | \$ \s* \{\^MATCH\} ) \z/oxmsgc) {
5781 0 0         if ($ignorecase) {
5782 0           $char[$i] = '@{[Char::Elatin1::ignorecase(Char::Elatin1::MATCH())]}';
5783             }
5784             else {
5785 0           $char[$i] = '@{[Char::Elatin1::MATCH()]}';
5786             }
5787             }
5788              
5789             # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Char::Elatin1::POSTMATCH()
5790             elsif ($char[$i] =~ /\A ( \$ \s* POSTMATCH | \$ \s* \{ \s* POSTMATCH \s* \} | \$ \s* \{\^POSTMATCH\} ) \z/oxmsgc) {
5791 0 0         if ($ignorecase) {
5792 0           $char[$i] = '@{[Char::Elatin1::ignorecase(Char::Elatin1::POSTMATCH())]}';
5793             }
5794             else {
5795 0           $char[$i] = '@{[Char::Elatin1::POSTMATCH()]}';
5796             }
5797             }
5798              
5799             # ${ foo }
5800             elsif ($char[$i] =~ /\A \$ \s* \{ ( \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* ) \} \z/oxms) {
5801 0 0         if ($ignorecase) {
5802 0           $char[$i] = '@{[Char::Elatin1::ignorecase(' . $char[$i] . ')]}';
5803             }
5804             }
5805              
5806             # ${ ... }
5807             elsif ($char[$i] =~ /\A \$ \s* \{ \s* ( .+ ) \s* \} \z/oxms) {
5808 0           $char[$i] = e_capture($1);
5809 0 0         if ($ignorecase) {
5810 0           $char[$i] = '@{[Char::Elatin1::ignorecase(' . $char[$i] . ')]}';
5811             }
5812             }
5813              
5814             # $scalar or @array
5815             elsif ($char[$i] =~ /\A [\$\@].+ /oxms) {
5816 0           $char[$i] = e_string($char[$i]);
5817 0 0         if ($ignorecase) {
5818 0           $char[$i] = '@{[Char::Elatin1::ignorecase(' . $char[$i] . ')]}';
5819             }
5820             }
5821              
5822             # quote character before ? + * {
5823             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
5824 0 0 0       if ($char[$i-1] =~ /\A (?:\\[0-7]{2,3}|\\x[0-9-A-Fa-f]{1,2}) \z/oxms) {
    0          
5825             }
5826             elsif (($ope =~ /\A m? \z/oxms) and ($delimiter eq '?')) {
5827 0           my $char = $char[$i-1];
5828 0 0         if ($char[$i] eq '{') {
5829 0           die __FILE__, qq{: "MULTIBYTE{n}" should be "(MULTIBYTE){n}" in m?? (and shift \$1,\$2,\$3,...) ($char){n}};
5830             }
5831             else {
5832 0           die __FILE__, qq{: "MULTIBYTE$char[$i]" should be "(MULTIBYTE)$char[$i]" in m?? (and shift \$1,\$2,\$3,...) ($char)$char[$i]};
5833             }
5834             }
5835             else {
5836 0           $char[$i-1] = '(?:' . $char[$i-1] . ')';
5837             }
5838             }
5839             }
5840              
5841             # make regexp string
5842 0           $modifier =~ tr/i//d;
5843 0 0         if ($left_e > $right_e) {
5844 0 0 0       if (($ope =~ /\A m? \z/oxms) and ($delimiter eq '?')) {
5845 0           return join '', $ope, $delimiter, $anchor, @char, '>]}' x ($left_e - $right_e), $matched, $end_delimiter, $modifier;
5846             }
5847             else {
5848 0           return join '', $ope, $delimiter, $anchor, '(?:', @char, '>]}' x ($left_e - $right_e), ')', $matched, $end_delimiter, $modifier;
5849             }
5850             }
5851 0 0 0       if (($ope =~ /\A m? \z/oxms) and ($delimiter eq '?')) {
5852 0           return join '', $ope, $delimiter, $anchor, @char, $matched, $end_delimiter, $modifier;
5853             }
5854             else {
5855 0           return join '', $ope, $delimiter, $anchor, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
5856             }
5857             }
5858              
5859             #
5860             # double quote stuff
5861             #
5862             sub qq_stuff {
5863 0     0 0   my($delimiter,$end_delimiter,$stuff) = @_;
5864              
5865             # scalar variable or array variable
5866 0 0         if ($stuff =~ /\A [\$\@] /oxms) {
5867 0           return $stuff;
5868             }
5869              
5870             # quote by delimiter
5871 0           my %octet = map {$_ => 1} ($stuff =~ /\G ([\x00-\xFF]) /oxmsg);
  0            
5872 0           for my $char (qw( ! " $ % & * + - . / : = ? @ ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
5873 0 0         next if $char eq $delimiter;
5874 0 0         next if $char eq $end_delimiter;
5875 0 0         if (not $octet{$char}) {
5876 0           return join '', 'qq', $char, $stuff, $char;
5877             }
5878             }
5879 0           return join '', 'qq', '<', $stuff, '>';
5880             }
5881              
5882             #
5883             # escape regexp (m'', qr'', and m''b, qr''b)
5884             #
5885             sub e_qr_q {
5886 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
5887 0   0       $modifier ||= '';
5888              
5889 0           $modifier =~ tr/p//d;
5890 0 0         if ($modifier =~ /([adlu])/oxms) {
5891 0           my $line = 0;
5892 0           for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
5893 0 0         if ($filename ne __FILE__) {
5894 0           $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
5895 0           last;
5896             }
5897             }
5898 0           die qq{Unsupported modifier "$1" used at line $line.\n};
5899             }
5900              
5901 0           $slash = 'div';
5902              
5903             # literal null string pattern
5904 0 0         if ($string eq '') {
    0          
5905 0           $modifier =~ tr/bB//d;
5906 0           $modifier =~ tr/i//d;
5907 0           return join '', $ope, $delimiter, $end_delimiter, $modifier;
5908             }
5909              
5910             # with /b /B modifier
5911             elsif ($modifier =~ tr/bB//d) {
5912 0           return e_qr_qb($ope,$delimiter,$end_delimiter,$string,$modifier);
5913             }
5914              
5915             # without /b /B modifier
5916             else {
5917 0           return e_qr_qt($ope,$delimiter,$end_delimiter,$string,$modifier);
5918             }
5919             }
5920              
5921             #
5922             # escape regexp (m'', qr'')
5923             #
5924             sub e_qr_qt {
5925 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
5926              
5927 0 0         my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
5928              
5929             # split regexp
5930 0           my @char = $string =~ /\G(
5931             \[\:\^ [a-z]+ \:\] |
5932             \[\: [a-z]+ \:\] |
5933             \[\^ |
5934             [\$\@\/\\] |
5935             \\? (?:$q_char)
5936             )/oxmsg;
5937              
5938             # unescape character
5939 0           for (my $i=0; $i <= $#char; $i++) {
5940 0 0 0       if (0) {
    0 0        
    0 0        
    0          
    0          
    0          
5941             }
5942              
5943             # open character class [...]
5944 0           elsif ($char[$i] eq '[') {
5945 0           my $left = $i;
5946 0 0         if ($char[$i+1] eq ']') {
5947 0           $i++;
5948             }
5949 0           while (1) {
5950 0 0         if (++$i > $#char) {
5951 0           die __FILE__, ": Unmatched [] in regexp";
5952             }
5953 0 0         if ($char[$i] eq ']') {
5954 0           my $right = $i;
5955              
5956             # [...]
5957 0           splice @char, $left, $right-$left+1, Char::Elatin1::charlist_qr(@char[$left+1..$right-1], $modifier);
5958              
5959 0           $i = $left;
5960 0           last;
5961             }
5962             }
5963             }
5964              
5965             # open character class [^...]
5966             elsif ($char[$i] eq '[^') {
5967 0           my $left = $i;
5968 0 0         if ($char[$i+1] eq ']') {
5969 0           $i++;
5970             }
5971 0           while (1) {
5972 0 0         if (++$i > $#char) {
5973 0           die __FILE__, ": Unmatched [] in regexp";
5974             }
5975 0 0         if ($char[$i] eq ']') {
5976 0           my $right = $i;
5977              
5978             # [^...]
5979 0           splice @char, $left, $right-$left+1, Char::Elatin1::charlist_not_qr(@char[$left+1..$right-1], $modifier);
5980              
5981 0           $i = $left;
5982 0           last;
5983             }
5984             }
5985             }
5986              
5987             # escape $ @ / and \
5988             elsif ($char[$i] =~ /\A [\$\@\/\\] \z/oxms) {
5989 0           $char[$i] = '\\' . $char[$i];
5990             }
5991              
5992             # rewrite character class or escape character
5993             elsif (my $char = character_class($char[$i],$modifier)) {
5994 0           $char[$i] = $char;
5995             }
5996              
5997             # /i modifier
5998             elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Char::Elatin1::uc($char[$i]) ne Char::Elatin1::fc($char[$i]))) {
5999 0 0         if (CORE::length(Char::Elatin1::fc($char[$i])) == 1) {
6000 0           $char[$i] = '[' . Char::Elatin1::uc($char[$i]) . Char::Elatin1::fc($char[$i]) . ']';
6001             }
6002             else {
6003 0           $char[$i] = '(?:' . Char::Elatin1::uc($char[$i]) . '|' . Char::Elatin1::fc($char[$i]) . ')';
6004             }
6005             }
6006              
6007             # quote character before ? + * {
6008             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
6009 0 0         if ($char[$i-1] =~ /\A [\x00-\xFF] \z/oxms) {
6010             }
6011             else {
6012 0           $char[$i-1] = '(?:' . $char[$i-1] . ')';
6013             }
6014             }
6015             }
6016              
6017 0           $delimiter = '/';
6018 0           $end_delimiter = '/';
6019              
6020 0           $modifier =~ tr/i//d;
6021 0           return join '', $ope, $delimiter, $anchor, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
6022             }
6023              
6024             #
6025             # escape regexp (m''b, qr''b)
6026             #
6027             sub e_qr_qb {
6028 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6029              
6030             # split regexp
6031 0           my @char = $string =~ /\G(
6032             \\\\ |
6033             [\$\@\/\\] |
6034             [\x00-\xFF]
6035             )/oxmsg;
6036              
6037             # unescape character
6038 0           for (my $i=0; $i <= $#char; $i++) {
6039 0 0         if (0) {
    0          
6040             }
6041              
6042             # remain \\
6043 0           elsif ($char[$i] eq '\\\\') {
6044             }
6045              
6046             # escape $ @ / and \
6047             elsif ($char[$i] =~ /\A [\$\@\/\\] \z/oxms) {
6048 0           $char[$i] = '\\' . $char[$i];
6049             }
6050             }
6051              
6052 0           $delimiter = '/';
6053 0           $end_delimiter = '/';
6054 0           return join '', $ope, $delimiter, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
6055             }
6056              
6057             #
6058             # escape regexp (s/here//)
6059             #
6060             sub e_s1 {
6061 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6062 0   0       $modifier ||= '';
6063              
6064 0           $modifier =~ tr/p//d;
6065 0 0         if ($modifier =~ /([adlu])/oxms) {
6066 0           my $line = 0;
6067 0           for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
6068 0 0         if ($filename ne __FILE__) {
6069 0           $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
6070 0           last;
6071             }
6072             }
6073 0           die qq{Unsupported modifier "$1" used at line $line.\n};
6074             }
6075              
6076 0           $slash = 'div';
6077              
6078             # literal null string pattern
6079 0 0         if ($string eq '') {
    0          
6080 0           $modifier =~ tr/bB//d;
6081 0           $modifier =~ tr/i//d;
6082 0           return join '', $ope, $delimiter, $end_delimiter, $modifier;
6083             }
6084              
6085             # /b /B modifier
6086             elsif ($modifier =~ tr/bB//d) {
6087              
6088             # choice again delimiter
6089 0 0         if ($delimiter =~ / [\@:] /oxms) {
6090 0           my @char = $string =~ /\G([\x00-\xFF])/oxmsg;
6091 0           my %octet = map {$_ => 1} @char;
  0            
6092 0 0         if (not $octet{')'}) {
    0          
    0          
    0          
6093 0           $delimiter = '(';
6094 0           $end_delimiter = ')';
6095             }
6096             elsif (not $octet{'}'}) {
6097 0           $delimiter = '{';
6098 0           $end_delimiter = '}';
6099             }
6100             elsif (not $octet{']'}) {
6101 0           $delimiter = '[';
6102 0           $end_delimiter = ']';
6103             }
6104             elsif (not $octet{'>'}) {
6105 0           $delimiter = '<';
6106 0           $end_delimiter = '>';
6107             }
6108             else {
6109 0           for my $char (qw( ! " $ % & * + - . / = ? ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
6110 0 0         if (not $octet{$char}) {
6111 0           $delimiter = $char;
6112 0           $end_delimiter = $char;
6113 0           last;
6114             }
6115             }
6116             }
6117             }
6118              
6119 0           my $prematch = '';
6120 0           return join '', $ope, $delimiter, $prematch, '(?:', $string, ')', $matched, $end_delimiter, $modifier;
6121             }
6122              
6123 0 0         my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
6124 0           my $metachar = qr/[\@\\|[\]{^]/oxms;
6125              
6126             # split regexp
6127 0           my @char = $string =~ /\G(
6128             \\g \s* \{ \s* - \s* [1-9][0-9]* \s* \} |
6129             \\g \s* \{ \s* [1-9][0-9]* \s* \} |
6130             \\g \s* [1-9][0-9]* |
6131             \\o\{ [0-7]+ \} |
6132             \\ [1-9][0-9]* |
6133             \\ [0-7]{2,3} |
6134             \\x\{ [0-9A-Fa-f]+ \} |
6135             \\x [0-9A-Fa-f]{1,2} |
6136             \\c [\x40-\x5F] |
6137             \\N\{ [^0-9\}][^\}]* \} |
6138             \\p\{ [^0-9\}][^\}]* \} |
6139             \\P\{ [^0-9\}][^\}]* \} |
6140             \\ (?:$q_char) |
6141             \$` | \$\{`\} | \$ \s* PREMATCH | \$ \s* \{ \s* PREMATCH \s* \} | \$ \s* \{\^PREMATCH\} |
6142             \$& | \$\{&\} | \$ \s* MATCH | \$ \s* \{ \s* MATCH \s* \} | \$ \s* \{\^MATCH\} |
6143             \$ \s* POSTMATCH | \$ \s* \{ \s* POSTMATCH \s* \} | \$ \s* \{\^POSTMATCH\} |
6144             [\$\@] $qq_variable |
6145             \$ \s* \d+ |
6146             \$ \s* \{ \s* \d+ \s* \} |
6147             \$ \$ (?![\w\{]) |
6148             \$ \s* \$ \s* $qq_variable |
6149             \[\:\^ (?:alnum|alpha|ascii|blank|cntrl|digit|graph|lower|print|punct|space|upper|word|xdigit) :\] |
6150             \[\: (?:alnum|alpha|ascii|blank|cntrl|digit|graph|lower|print|punct|space|upper|word|xdigit) :\] |
6151             \[\^ |
6152             \(\? |
6153             (?:$q_char)
6154             )/oxmsg;
6155              
6156             # choice again delimiter
6157 0 0         if ($delimiter =~ / [\@:] /oxms) {
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             # count '('
6187 0           my $parens = grep { $_ eq '(' } @char;
  0            
6188              
6189 0           my $left_e = 0;
6190 0           my $right_e = 0;
6191 0           for (my $i=0; $i <= $#char; $i++) {
6192              
6193             # "\L\u" --> "\u\L"
6194 0 0 0       if (($char[$i] eq '\L') and ($char[$i+1] eq '\u')) {
    0 0        
    0          
    0          
    0          
    0          
    0          
    0          
6195 0           @char[$i,$i+1] = @char[$i+1,$i];
6196             }
6197              
6198             # "\U\l" --> "\l\U"
6199             elsif (($char[$i] eq '\U') and ($char[$i+1] eq '\l')) {
6200 0           @char[$i,$i+1] = @char[$i+1,$i];
6201             }
6202              
6203             # octal escape sequence
6204             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
6205 0           $char[$i] = Char::Elatin1::octchr($1);
6206             }
6207              
6208             # hexadecimal escape sequence
6209             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
6210 0           $char[$i] = Char::Elatin1::hexchr($1);
6211             }
6212              
6213             # \N{CHARNAME} --> N\{CHARNAME}
6214             elsif ($char[$i] =~ /\A \\ (N) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
6215 0           $char[$i] = $1 . '\\' . $2;
6216             }
6217              
6218             # \p{PROPERTY} --> p\{PROPERTY}
6219             elsif ($char[$i] =~ /\A \\ (p) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
6220 0           $char[$i] = $1 . '\\' . $2;
6221             }
6222              
6223             # \P{PROPERTY} --> P\{PROPERTY}
6224             elsif ($char[$i] =~ /\A \\ (P) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
6225 0           $char[$i] = $1 . '\\' . $2;
6226             }
6227              
6228             # \p, \P, \X --> p, P, X
6229             elsif ($char[$i] =~ /\A \\ ( [pPX] ) \z/oxms) {
6230 0           $char[$i] = $1;
6231             }
6232              
6233 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          
6234             }
6235              
6236             # join separated multiple-octet
6237 0           elsif ($char[$i] =~ /\A (?: \\ [0-7]{2,3} | \\x [0-9A-Fa-f]{1,2}) \z/oxms) {
6238 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        
6239 0           $char[$i] .= join '', splice @char, $i+1, 3;
6240             }
6241             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)) {
6242 0           $char[$i] .= join '', splice @char, $i+1, 2;
6243             }
6244             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)) {
6245 0           $char[$i] .= join '', splice @char, $i+1, 1;
6246             }
6247             }
6248              
6249             # open character class [...]
6250             elsif ($char[$i] eq '[') {
6251 0           my $left = $i;
6252 0 0         if ($char[$i+1] eq ']') {
6253 0           $i++;
6254             }
6255 0           while (1) {
6256 0 0         if (++$i > $#char) {
6257 0           die __FILE__, ": Unmatched [] in regexp";
6258             }
6259 0 0         if ($char[$i] eq ']') {
6260 0           my $right = $i;
6261              
6262             # [...]
6263 0 0         if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
6264 0           splice @char, $left, $right-$left+1, sprintf(q{@{[Char::Elatin1::charlist_qr(%s,'%s')]}}, join(',', map {qq_stuff($delimiter,$end_delimiter,$_)} @char[$left+1..$right-1]), $modifier);
  0            
6265             }
6266             else {
6267 0           splice @char, $left, $right-$left+1, Char::Elatin1::charlist_qr(@char[$left+1..$right-1], $modifier);
6268             }
6269              
6270 0           $i = $left;
6271 0           last;
6272             }
6273             }
6274             }
6275              
6276             # open character class [^...]
6277             elsif ($char[$i] eq '[^') {
6278 0           my $left = $i;
6279 0 0         if ($char[$i+1] eq ']') {
6280 0           $i++;
6281             }
6282 0           while (1) {
6283 0 0         if (++$i > $#char) {
6284 0           die __FILE__, ": Unmatched [] in regexp";
6285             }
6286 0 0         if ($char[$i] eq ']') {
6287 0           my $right = $i;
6288              
6289             # [^...]
6290 0 0         if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
6291 0           splice @char, $left, $right-$left+1, sprintf(q{@{[Char::Elatin1::charlist_not_qr(%s,'%s')]}}, join(',', map {qq_stuff($delimiter,$end_delimiter,$_)} @char[$left+1..$right-1]), $modifier);
  0            
6292             }
6293             else {
6294 0           splice @char, $left, $right-$left+1, Char::Elatin1::charlist_not_qr(@char[$left+1..$right-1], $modifier);
6295             }
6296              
6297 0           $i = $left;
6298 0           last;
6299             }
6300             }
6301             }
6302              
6303             # rewrite character class or escape character
6304             elsif (my $char = character_class($char[$i],$modifier)) {
6305 0           $char[$i] = $char;
6306             }
6307              
6308             # /i modifier
6309             elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Char::Elatin1::uc($char[$i]) ne Char::Elatin1::fc($char[$i]))) {
6310 0 0         if (CORE::length(Char::Elatin1::fc($char[$i])) == 1) {
6311 0           $char[$i] = '[' . Char::Elatin1::uc($char[$i]) . Char::Elatin1::fc($char[$i]) . ']';
6312             }
6313             else {
6314 0           $char[$i] = '(?:' . Char::Elatin1::uc($char[$i]) . '|' . Char::Elatin1::fc($char[$i]) . ')';
6315             }
6316             }
6317              
6318             # \u \l \U \L \F \Q \E
6319             elsif ($char[$i] =~ /\A [<>] \z/oxms) {
6320 0 0         if ($right_e < $left_e) {
6321 0           $char[$i] = '\\' . $char[$i];
6322             }
6323             }
6324             elsif ($char[$i] eq '\u') {
6325 0           $char[$i] = '@{[Char::Elatin1::ucfirst qq<';
6326 0           $left_e++;
6327             }
6328             elsif ($char[$i] eq '\l') {
6329 0           $char[$i] = '@{[Char::Elatin1::lcfirst qq<';
6330 0           $left_e++;
6331             }
6332             elsif ($char[$i] eq '\U') {
6333 0           $char[$i] = '@{[Char::Elatin1::uc qq<';
6334 0           $left_e++;
6335             }
6336             elsif ($char[$i] eq '\L') {
6337 0           $char[$i] = '@{[Char::Elatin1::lc qq<';
6338 0           $left_e++;
6339             }
6340             elsif ($char[$i] eq '\F') {
6341 0           $char[$i] = '@{[Char::Elatin1::fc qq<';
6342 0           $left_e++;
6343             }
6344             elsif ($char[$i] eq '\Q') {
6345 0           $char[$i] = '@{[CORE::quotemeta qq<';
6346 0           $left_e++;
6347             }
6348             elsif ($char[$i] eq '\E') {
6349 0 0         if ($right_e < $left_e) {
6350 0           $char[$i] = '>]}';
6351 0           $right_e++;
6352             }
6353             else {
6354 0           $char[$i] = '';
6355             }
6356             }
6357             elsif ($char[$i] eq '\Q') {
6358 0           while (1) {
6359 0 0         if (++$i > $#char) {
6360 0           last;
6361             }
6362 0 0         if ($char[$i] eq '\E') {
6363 0           last;
6364             }
6365             }
6366             }
6367             elsif ($char[$i] eq '\E') {
6368             }
6369              
6370             # \0 --> \0
6371             elsif ($char[$i] =~ /\A \\ \s* 0 \z/oxms) {
6372             }
6373              
6374             # \g{N}, \g{-N}
6375              
6376             # P.108 Using Simple Patterns
6377             # in Chapter 7: In the World of Regular Expressions
6378             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
6379              
6380             # P.221 Capturing
6381             # in Chapter 5: Pattern Matching
6382             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
6383              
6384             # \g{-1}, \g{-2}, \g{-3} --> \g{-1}, \g{-2}, \g{-3}
6385             elsif ($char[$i] =~ /\A \\g \s* \{ \s* - \s* ([1-9][0-9]*) \s* \} \z/oxms) {
6386             }
6387              
6388             # \g{1}, \g{2}, \g{3} --> \g{2}, \g{3}, \g{4} (only when multibyte anchoring is enable)
6389             elsif ($char[$i] =~ /\A \\g \s* \{ \s* ([1-9][0-9]*) \s* \} \z/oxms) {
6390             }
6391              
6392             # \g1, \g2, \g3 --> \g2, \g3, \g4 (only when multibyte anchoring is enable)
6393             elsif ($char[$i] =~ /\A \\g \s* ([1-9][0-9]*) \z/oxms) {
6394             }
6395              
6396             # \1, \2, \3 --> \2, \3, \4 (only when multibyte anchoring is enable)
6397             elsif ($char[$i] =~ /\A \\ \s* ([1-9][0-9]*) \z/oxms) {
6398             }
6399              
6400             # $0 --> $0
6401             elsif ($char[$i] =~ /\A \$ 0 \z/oxms) {
6402 0 0         if ($ignorecase) {
6403 0           $char[$i] = '@{[Char::Elatin1::ignorecase(' . $char[$i] . ')]}';
6404             }
6405             }
6406             elsif ($char[$i] =~ /\A \$ \{ \s* 0 \s* \} \z/oxms) {
6407 0 0         if ($ignorecase) {
6408 0           $char[$i] = '@{[Char::Elatin1::ignorecase(' . $char[$i] . ')]}';
6409             }
6410             }
6411              
6412             # $$ --> $$
6413             elsif ($char[$i] =~ /\A \$\$ \z/oxms) {
6414             }
6415              
6416             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
6417             # $1, $2, $3 --> $1, $2, $3 otherwise
6418             elsif ($char[$i] =~ /\A \$ ([1-9][0-9]*) \z/oxms) {
6419 0           $char[$i] = e_capture($1);
6420 0 0         if ($ignorecase) {
6421 0           $char[$i] = '@{[Char::Elatin1::ignorecase(' . $char[$i] . ')]}';
6422             }
6423             }
6424             elsif ($char[$i] =~ /\A \$ \{ \s* ([1-9][0-9]*) \s* \} \z/oxms) {
6425 0           $char[$i] = e_capture($1);
6426 0 0         if ($ignorecase) {
6427 0           $char[$i] = '@{[Char::Elatin1::ignorecase(' . $char[$i] . ')]}';
6428             }
6429             }
6430              
6431             # $$foo[ ... ] --> $ $foo->[ ... ]
6432             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) ( \[ (?:$qq_bracket)*? \] ) \z/oxms) {
6433 0           $char[$i] = e_capture($1.'->'.$2);
6434 0 0         if ($ignorecase) {
6435 0           $char[$i] = '@{[Char::Elatin1::ignorecase(' . $char[$i] . ')]}';
6436             }
6437             }
6438              
6439             # $$foo{ ... } --> $ $foo->{ ... }
6440             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) ( \{ (?:$qq_brace)*? \} ) \z/oxms) {
6441 0           $char[$i] = e_capture($1.'->'.$2);
6442 0 0         if ($ignorecase) {
6443 0           $char[$i] = '@{[Char::Elatin1::ignorecase(' . $char[$i] . ')]}';
6444             }
6445             }
6446              
6447             # $$foo
6448             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) \z/oxms) {
6449 0           $char[$i] = e_capture($1);
6450 0 0         if ($ignorecase) {
6451 0           $char[$i] = '@{[Char::Elatin1::ignorecase(' . $char[$i] . ')]}';
6452             }
6453             }
6454              
6455             # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Char::Elatin1::PREMATCH()
6456             elsif ($char[$i] =~ /\A ( \$` | \$\{`\} | \$ \s* PREMATCH | \$ \s* \{ \s* PREMATCH \s* \} | \$ \s* \{\^PREMATCH\} ) \z/oxmsgc) {
6457 0 0         if ($ignorecase) {
6458 0           $char[$i] = '@{[Char::Elatin1::ignorecase(Char::Elatin1::PREMATCH())]}';
6459             }
6460             else {
6461 0           $char[$i] = '@{[Char::Elatin1::PREMATCH()]}';
6462             }
6463             }
6464              
6465             # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Char::Elatin1::MATCH()
6466             elsif ($char[$i] =~ /\A ( \$& | \$\{&\} | \$ \s* MATCH | \$ \s* \{ \s* MATCH \s* \} | \$ \s* \{\^MATCH\} ) \z/oxmsgc) {
6467 0 0         if ($ignorecase) {
6468 0           $char[$i] = '@{[Char::Elatin1::ignorecase(Char::Elatin1::MATCH())]}';
6469             }
6470             else {
6471 0           $char[$i] = '@{[Char::Elatin1::MATCH()]}';
6472             }
6473             }
6474              
6475             # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Char::Elatin1::POSTMATCH()
6476             elsif ($char[$i] =~ /\A ( \$ \s* POSTMATCH | \$ \s* \{ \s* POSTMATCH \s* \} | \$ \s* \{\^POSTMATCH\} ) \z/oxmsgc) {
6477 0 0         if ($ignorecase) {
6478 0           $char[$i] = '@{[Char::Elatin1::ignorecase(Char::Elatin1::POSTMATCH())]}';
6479             }
6480             else {
6481 0           $char[$i] = '@{[Char::Elatin1::POSTMATCH()]}';
6482             }
6483             }
6484              
6485             # ${ foo }
6486             elsif ($char[$i] =~ /\A \$ \s* \{ ( \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* ) \} \z/oxms) {
6487 0 0         if ($ignorecase) {
6488 0           $char[$i] = '@{[Char::Elatin1::ignorecase(' . $char[$i] . ')]}';
6489             }
6490             }
6491              
6492             # ${ ... }
6493             elsif ($char[$i] =~ /\A \$ \s* \{ \s* ( .+ ) \s* \} \z/oxms) {
6494 0           $char[$i] = e_capture($1);
6495 0 0         if ($ignorecase) {
6496 0           $char[$i] = '@{[Char::Elatin1::ignorecase(' . $char[$i] . ')]}';
6497             }
6498             }
6499              
6500             # $scalar or @array
6501             elsif ($char[$i] =~ /\A [\$\@].+ /oxms) {
6502 0           $char[$i] = e_string($char[$i]);
6503 0 0         if ($ignorecase) {
6504 0           $char[$i] = '@{[Char::Elatin1::ignorecase(' . $char[$i] . ')]}';
6505             }
6506             }
6507              
6508             # quote character before ? + * {
6509             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
6510 0 0         if ($char[$i-1] =~ /\A (?:\\[0-7]{2,3}|\\x[0-9-A-Fa-f]{1,2}) \z/oxms) {
6511             }
6512             else {
6513 0           $char[$i-1] = '(?:' . $char[$i-1] . ')';
6514             }
6515             }
6516             }
6517              
6518             # make regexp string
6519 0           my $prematch = '';
6520 0           $modifier =~ tr/i//d;
6521 0 0         if ($left_e > $right_e) {
6522 0           return join '', $ope, $delimiter, $prematch, '(?:', @char, '>]}' x ($left_e - $right_e), ')', $matched, $end_delimiter, $modifier;
6523             }
6524 0           return join '', $ope, $delimiter, $prematch, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
6525             }
6526              
6527             #
6528             # escape regexp (s'here'' or s'here''b)
6529             #
6530             sub e_s1_q {
6531 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6532 0   0       $modifier ||= '';
6533              
6534 0           $modifier =~ tr/p//d;
6535 0 0         if ($modifier =~ /([adlu])/oxms) {
6536 0           my $line = 0;
6537 0           for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
6538 0 0         if ($filename ne __FILE__) {
6539 0           $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
6540 0           last;
6541             }
6542             }
6543 0           die qq{Unsupported modifier "$1" used at line $line.\n};
6544             }
6545              
6546 0           $slash = 'div';
6547              
6548             # literal null string pattern
6549 0 0         if ($string eq '') {
    0          
6550 0           $modifier =~ tr/bB//d;
6551 0           $modifier =~ tr/i//d;
6552 0           return join '', $ope, $delimiter, $end_delimiter, $modifier;
6553             }
6554              
6555             # with /b /B modifier
6556             elsif ($modifier =~ tr/bB//d) {
6557 0           return e_s1_qb($ope,$delimiter,$end_delimiter,$string,$modifier);
6558             }
6559              
6560             # without /b /B modifier
6561             else {
6562 0           return e_s1_qt($ope,$delimiter,$end_delimiter,$string,$modifier);
6563             }
6564             }
6565              
6566             #
6567             # escape regexp (s'here'')
6568             #
6569             sub e_s1_qt {
6570 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6571              
6572 0 0         my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
6573              
6574             # split regexp
6575 0           my @char = $string =~ /\G(
6576             \[\:\^ [a-z]+ \:\] |
6577             \[\: [a-z]+ \:\] |
6578             \[\^ |
6579             [\$\@\/\\] |
6580             \\? (?:$q_char)
6581             )/oxmsg;
6582              
6583             # unescape character
6584 0           for (my $i=0; $i <= $#char; $i++) {
6585 0 0 0       if (0) {
    0 0        
    0 0        
    0          
    0          
    0          
6586             }
6587              
6588             # open character class [...]
6589 0           elsif ($char[$i] eq '[') {
6590 0           my $left = $i;
6591 0 0         if ($char[$i+1] eq ']') {
6592 0           $i++;
6593             }
6594 0           while (1) {
6595 0 0         if (++$i > $#char) {
6596 0           die __FILE__, ": Unmatched [] in regexp";
6597             }
6598 0 0         if ($char[$i] eq ']') {
6599 0           my $right = $i;
6600              
6601             # [...]
6602 0           splice @char, $left, $right-$left+1, Char::Elatin1::charlist_qr(@char[$left+1..$right-1], $modifier);
6603              
6604 0           $i = $left;
6605 0           last;
6606             }
6607             }
6608             }
6609              
6610             # open character class [^...]
6611             elsif ($char[$i] eq '[^') {
6612 0           my $left = $i;
6613 0 0         if ($char[$i+1] eq ']') {
6614 0           $i++;
6615             }
6616 0           while (1) {
6617 0 0         if (++$i > $#char) {
6618 0           die __FILE__, ": Unmatched [] in regexp";
6619             }
6620 0 0         if ($char[$i] eq ']') {
6621 0           my $right = $i;
6622              
6623             # [^...]
6624 0           splice @char, $left, $right-$left+1, Char::Elatin1::charlist_not_qr(@char[$left+1..$right-1], $modifier);
6625              
6626 0           $i = $left;
6627 0           last;
6628             }
6629             }
6630             }
6631              
6632             # escape $ @ / and \
6633             elsif ($char[$i] =~ /\A [\$\@\/\\] \z/oxms) {
6634 0           $char[$i] = '\\' . $char[$i];
6635             }
6636              
6637             # rewrite character class or escape character
6638             elsif (my $char = character_class($char[$i],$modifier)) {
6639 0           $char[$i] = $char;
6640             }
6641              
6642             # /i modifier
6643             elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Char::Elatin1::uc($char[$i]) ne Char::Elatin1::fc($char[$i]))) {
6644 0 0         if (CORE::length(Char::Elatin1::fc($char[$i])) == 1) {
6645 0           $char[$i] = '[' . Char::Elatin1::uc($char[$i]) . Char::Elatin1::fc($char[$i]) . ']';
6646             }
6647             else {
6648 0           $char[$i] = '(?:' . Char::Elatin1::uc($char[$i]) . '|' . Char::Elatin1::fc($char[$i]) . ')';
6649             }
6650             }
6651              
6652             # quote character before ? + * {
6653             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
6654 0 0         if ($char[$i-1] =~ /\A [\x00-\xFF] \z/oxms) {
6655             }
6656             else {
6657 0           $char[$i-1] = '(?:' . $char[$i-1] . ')';
6658             }
6659             }
6660             }
6661              
6662 0           $modifier =~ tr/i//d;
6663 0           $delimiter = '/';
6664 0           $end_delimiter = '/';
6665 0           my $prematch = '';
6666 0           return join '', $ope, $delimiter, $prematch, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
6667             }
6668              
6669             #
6670             # escape regexp (s'here''b)
6671             #
6672             sub e_s1_qb {
6673 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6674              
6675             # split regexp
6676 0           my @char = $string =~ /\G(
6677             \\\\ |
6678             [\$\@\/\\] |
6679             [\x00-\xFF]
6680             )/oxmsg;
6681              
6682             # unescape character
6683 0           for (my $i=0; $i <= $#char; $i++) {
6684 0 0         if (0) {
    0          
6685             }
6686              
6687             # remain \\
6688 0           elsif ($char[$i] eq '\\\\') {
6689             }
6690              
6691             # escape $ @ / and \
6692             elsif ($char[$i] =~ /\A [\$\@\/\\] \z/oxms) {
6693 0           $char[$i] = '\\' . $char[$i];
6694             }
6695             }
6696              
6697 0           $delimiter = '/';
6698 0           $end_delimiter = '/';
6699 0           my $prematch = '';
6700 0           return join '', $ope, $delimiter, $prematch, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
6701             }
6702              
6703             #
6704             # escape regexp (s''here')
6705             #
6706             sub e_s2_q {
6707 0     0 0   my($ope,$delimiter,$end_delimiter,$string) = @_;
6708              
6709 0           $slash = 'div';
6710              
6711 0           my @char = $string =~ / \G (\\\\|[\$\@\/\\]|$q_char) /oxmsg;
6712 0           for (my $i=0; $i <= $#char; $i++) {
6713 0 0         if (0) {
    0          
6714             }
6715              
6716             # not escape \\
6717 0           elsif ($char[$i] =~ /\A \\\\ \z/oxms) {
6718             }
6719              
6720             # escape $ @ / and \
6721             elsif ($char[$i] =~ /\A [\$\@\/\\] \z/oxms) {
6722 0           $char[$i] = '\\' . $char[$i];
6723             }
6724             }
6725              
6726 0           return join '', $ope, $delimiter, @char, $end_delimiter;
6727             }
6728              
6729             #
6730             # escape regexp (s/here/and here/modifier)
6731             #
6732             sub e_sub {
6733 0     0 0   my($variable,$delimiter1,$pattern,$end_delimiter1,$delimiter2,$replacement,$end_delimiter2,$modifier) = @_;
6734 0   0       $modifier ||= '';
6735              
6736 0           $modifier =~ tr/p//d;
6737 0 0         if ($modifier =~ /([adlu])/oxms) {
6738 0           my $line = 0;
6739 0           for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
6740 0 0         if ($filename ne __FILE__) {
6741 0           $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
6742 0           last;
6743             }
6744             }
6745 0           die qq{Unsupported modifier "$1" used at line $line.\n};
6746             }
6747              
6748 0 0         if ($variable eq '') {
6749 0           $variable = '$_';
6750 0           $bind_operator = ' =~ ';
6751             }
6752              
6753 0           $slash = 'div';
6754              
6755             # P.128 Start of match (or end of previous match): \G
6756             # P.130 Advanced Use of \G with Perl
6757             # in Chapter 3: Overview of Regular Expression Features and Flavors
6758             # P.312 Iterative Matching: Scalar Context, with /g
6759             # in Chapter 7: Perl
6760             # of ISBN 0-596-00289-0 Mastering Regular Expressions, Second edition
6761              
6762             # P.181 Where You Left Off: The \G Assertion
6763             # in Chapter 5: Pattern Matching
6764             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
6765              
6766             # P.220 Where You Left Off: The \G Assertion
6767             # in Chapter 5: Pattern Matching
6768             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
6769              
6770 0           my $e_modifier = $modifier =~ tr/e//d;
6771 0           my $r_modifier = $modifier =~ tr/r//d;
6772              
6773 0           my $my = '';
6774 0 0         if ($variable =~ s/\A \( \s* ( (?: local \b | my \b | our \b | state \b )? .+ ) \) \z/$1/oxms) {
6775 0           $my = $variable;
6776 0           $variable =~ s/ (?: local \b | my \b | our \b | state \b ) \s* //oxms;
6777 0           $variable =~ s/ = .+ \z//oxms;
6778             }
6779              
6780 0           (my $variable_basename = $variable) =~ s/ [\[\{].* \z//oxms;
6781 0           $variable_basename =~ s/ \s+ \z//oxms;
6782              
6783             # quote replacement string
6784 0           my $e_replacement = '';
6785 0 0         if ($e_modifier >= 1) {
6786 0           $e_replacement = e_qq('', '', '', $replacement);
6787 0           $e_modifier--;
6788             }
6789             else {
6790 0 0         if ($delimiter2 eq "'") {
6791 0           $e_replacement = e_s2_q('qq', '/', '/', $replacement);
6792             }
6793             else {
6794 0           $e_replacement = e_qq ('qq', $delimiter2, $end_delimiter2, $replacement);
6795             }
6796             }
6797              
6798 0           my $sub = '';
6799              
6800             # with /r
6801 0 0         if ($r_modifier) {
6802 0 0         if (0) {
6803             }
6804              
6805             # s///gr without multibyte anchoring
6806 0           elsif ($modifier =~ /g/oxms) {
6807 0 0         $sub = sprintf(
6808             # 1 2 3 4 5
6809             q,
6810              
6811             $variable, # 1
6812             ($delimiter1 eq "'") ? # 2
6813             e_s1_q('m', $delimiter1, $end_delimiter1, $pattern, $modifier) : # :
6814             e_s1 ('m', $delimiter1, $end_delimiter1, $pattern, $modifier), # :
6815             $s_matched, # 3
6816             $e_replacement, # 4
6817             '$Char::Latin1::re_r=CORE::eval $Char::Latin1::re_r; ' x $e_modifier, # 5
6818             );
6819             }
6820              
6821             # s///r
6822             else {
6823              
6824 0           my $prematch = q{$`};
6825              
6826 0 0         $sub = sprintf(
6827             # 1 2 3 4 5 6 7
6828             q<(%s =~ %s) ? CORE::eval{%s local $^W=0; local $Char::Latin1::re_r=%s; %s"%s$Char::Latin1::re_r$'" } : %s>,
6829              
6830             $variable, # 1
6831             ($delimiter1 eq "'") ? # 2
6832             e_s1_q('m', $delimiter1, $end_delimiter1, $pattern, $modifier) : # :
6833             e_s1 ('m', $delimiter1, $end_delimiter1, $pattern, $modifier), # :
6834             $s_matched, # 3
6835             $e_replacement, # 4
6836             '$Char::Latin1::re_r=CORE::eval $Char::Latin1::re_r; ' x $e_modifier, # 5
6837             $prematch, # 6
6838             $variable, # 7
6839             );
6840             }
6841              
6842             # $var !~ s///r doesn't make sense
6843 0 0         if ($bind_operator =~ / !~ /oxms) {
6844 0           $sub = q{die("$0: Using !~ with s///r doesn't make sense"), } . $sub;
6845             }
6846             }
6847              
6848             # without /r
6849             else {
6850 0 0         if (0) {
6851             }
6852              
6853             # s///g without multibyte anchoring
6854 0           elsif ($modifier =~ /g/oxms) {
6855 0 0         $sub = sprintf(
    0          
6856             # 1 2 3 4 5 6 7 8
6857             q,
6858              
6859             $variable, # 1
6860             ($delimiter1 eq "'") ? # 2
6861             e_s1_q('m', $delimiter1, $end_delimiter1, $pattern, $modifier) : # :
6862             e_s1 ('m', $delimiter1, $end_delimiter1, $pattern, $modifier), # :
6863             $s_matched, # 3
6864             $e_replacement, # 4
6865             '$Char::Latin1::re_r=CORE::eval $Char::Latin1::re_r; ' x $e_modifier, # 5
6866             $variable, # 6
6867             $variable, # 7
6868             ($bind_operator =~ / !~ /oxms) ? '!' : '', # 8
6869             );
6870             }
6871              
6872             # s///
6873             else {
6874              
6875 0           my $prematch = q{$`};
6876              
6877 0 0         $sub = sprintf(
    0          
6878              
6879             ($bind_operator =~ / =~ /oxms) ?
6880              
6881             # 1 2 3 4 5 6 7 8
6882             q<(%s%s%s) ? CORE::eval{%s local $^W=0; local $Char::Latin1::re_r=%s; %s%s="%s$Char::Latin1::re_r$'"; 1 } : undef> :
6883              
6884             # 1 2 3 4 5 6 7 8
6885             q<(%s%s%s) ? 1 : CORE::eval{%s local $^W=0; local $Char::Latin1::re_r=%s; %s%s="%s$Char::Latin1::re_r$'"; undef }>,
6886              
6887             $variable, # 1
6888             $bind_operator, # 2
6889             ($delimiter1 eq "'") ? # 3
6890             e_s1_q('m', $delimiter1, $end_delimiter1, $pattern, $modifier) : # :
6891             e_s1 ('m', $delimiter1, $end_delimiter1, $pattern, $modifier), # :
6892             $s_matched, # 4
6893             $e_replacement, # 5
6894             '$Char::Latin1::re_r=CORE::eval $Char::Latin1::re_r; ' x $e_modifier, # 6
6895             $variable, # 7
6896             $prematch, # 8
6897             );
6898             }
6899             }
6900              
6901             # (my $foo = $bar) =~ s/// --> (my $foo = $bar, CORE::eval { ... })[1]
6902 0 0         if ($my ne '') {
6903 0           $sub = "($my, $sub)[1]";
6904             }
6905              
6906             # clear s/// variable
6907 0           $sub_variable = '';
6908 0           $bind_operator = '';
6909              
6910 0           return $sub;
6911             }
6912              
6913             #
6914             # escape regexp of split qr//
6915             #
6916             sub e_split {
6917 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6918 0   0       $modifier ||= '';
6919              
6920 0           $modifier =~ tr/p//d;
6921 0 0         if ($modifier =~ /([adlu])/oxms) {
6922 0           my $line = 0;
6923 0           for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
6924 0 0         if ($filename ne __FILE__) {
6925 0           $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
6926 0           last;
6927             }
6928             }
6929 0           die qq{Unsupported modifier "$1" used at line $line.\n};
6930             }
6931              
6932 0           $slash = 'div';
6933              
6934             # /b /B modifier
6935 0 0         if ($modifier =~ tr/bB//d) {
6936 0           return join '', 'split', $ope, $delimiter, $string, $end_delimiter, $modifier;
6937             }
6938              
6939 0 0         my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
6940 0           my $metachar = qr/[\@\\|[\]{^]/oxms;
6941              
6942             # split regexp
6943 0           my @char = $string =~ /\G(
6944             \\o\{ [0-7]+ \} |
6945             \\ [0-7]{2,3} |
6946             \\x\{ [0-9A-Fa-f]+ \} |
6947             \\x [0-9A-Fa-f]{1,2} |
6948             \\c [\x40-\x5F] |
6949             \\N\{ [^0-9\}][^\}]* \} |
6950             \\p\{ [^0-9\}][^\}]* \} |
6951             \\P\{ [^0-9\}][^\}]* \} |
6952             \\ (?:$q_char) |
6953             \$` | \$\{`\} | \$ \s* PREMATCH | \$ \s* \{ \s* PREMATCH \s* \} | \$ \s* \{\^PREMATCH\} |
6954             \$& | \$\{&\} | \$ \s* MATCH | \$ \s* \{ \s* MATCH \s* \} | \$ \s* \{\^MATCH\} |
6955             \$ \s* POSTMATCH | \$ \s* \{ \s* POSTMATCH \s* \} | \$ \s* \{\^POSTMATCH\} |
6956             [\$\@] $qq_variable |
6957             \$ \s* \d+ |
6958             \$ \s* \{ \s* \d+ \s* \} |
6959             \$ \$ (?![\w\{]) |
6960             \$ \s* \$ \s* $qq_variable |
6961             \[\:\^ (?:alnum|alpha|ascii|blank|cntrl|digit|graph|lower|print|punct|space|upper|word|xdigit) :\] |
6962             \[\: (?:alnum|alpha|ascii|blank|cntrl|digit|graph|lower|print|punct|space|upper|word|xdigit) :\] |
6963             \[\^ |
6964             \(\? |
6965             (?:$q_char)
6966             )/oxmsg;
6967              
6968 0           my $left_e = 0;
6969 0           my $right_e = 0;
6970 0           for (my $i=0; $i <= $#char; $i++) {
6971              
6972             # "\L\u" --> "\u\L"
6973 0 0 0       if (($char[$i] eq '\L') and ($char[$i+1] eq '\u')) {
    0 0        
    0          
    0          
    0          
    0          
    0          
    0          
6974 0           @char[$i,$i+1] = @char[$i+1,$i];
6975             }
6976              
6977             # "\U\l" --> "\l\U"
6978             elsif (($char[$i] eq '\U') and ($char[$i+1] eq '\l')) {
6979 0           @char[$i,$i+1] = @char[$i+1,$i];
6980             }
6981              
6982             # octal escape sequence
6983             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
6984 0           $char[$i] = Char::Elatin1::octchr($1);
6985             }
6986              
6987             # hexadecimal escape sequence
6988             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
6989 0           $char[$i] = Char::Elatin1::hexchr($1);
6990             }
6991              
6992             # \N{CHARNAME} --> N\{CHARNAME}
6993             elsif ($char[$i] =~ /\A \\ (N) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
6994 0           $char[$i] = $1 . '\\' . $2;
6995             }
6996              
6997             # \p{PROPERTY} --> p\{PROPERTY}
6998             elsif ($char[$i] =~ /\A \\ (p) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
6999 0           $char[$i] = $1 . '\\' . $2;
7000             }
7001              
7002             # \P{PROPERTY} --> P\{PROPERTY}
7003             elsif ($char[$i] =~ /\A \\ (P) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
7004 0           $char[$i] = $1 . '\\' . $2;
7005             }
7006              
7007             # \p, \P, \X --> p, P, X
7008             elsif ($char[$i] =~ /\A \\ ( [pPX] ) \z/oxms) {
7009 0           $char[$i] = $1;
7010             }
7011              
7012 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          
7013             }
7014              
7015             # join separated multiple-octet
7016 0           elsif ($char[$i] =~ /\A (?: \\ [0-7]{2,3} | \\x [0-9A-Fa-f]{1,2}) \z/oxms) {
7017 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        
7018 0           $char[$i] .= join '', splice @char, $i+1, 3;
7019             }
7020             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)) {
7021 0           $char[$i] .= join '', splice @char, $i+1, 2;
7022             }
7023             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)) {
7024 0           $char[$i] .= join '', splice @char, $i+1, 1;
7025             }
7026             }
7027              
7028             # open character class [...]
7029             elsif ($char[$i] eq '[') {
7030 0           my $left = $i;
7031 0 0         if ($char[$i+1] eq ']') {
7032 0           $i++;
7033             }
7034 0           while (1) {
7035 0 0         if (++$i > $#char) {
7036 0           die __FILE__, ": Unmatched [] in regexp";
7037             }
7038 0 0         if ($char[$i] eq ']') {
7039 0           my $right = $i;
7040              
7041             # [...]
7042 0 0         if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
7043 0           splice @char, $left, $right-$left+1, sprintf(q{@{[Char::Elatin1::charlist_qr(%s,'%s')]}}, join(',', map {qq_stuff($delimiter,$end_delimiter,$_)} @char[$left+1..$right-1]), $modifier);
  0            
7044             }
7045             else {
7046 0           splice @char, $left, $right-$left+1, Char::Elatin1::charlist_qr(@char[$left+1..$right-1], $modifier);
7047             }
7048              
7049 0           $i = $left;
7050 0           last;
7051             }
7052             }
7053             }
7054              
7055             # open character class [^...]
7056             elsif ($char[$i] eq '[^') {
7057 0           my $left = $i;
7058 0 0         if ($char[$i+1] eq ']') {
7059 0           $i++;
7060             }
7061 0           while (1) {
7062 0 0         if (++$i > $#char) {
7063 0           die __FILE__, ": Unmatched [] in regexp";
7064             }
7065 0 0         if ($char[$i] eq ']') {
7066 0           my $right = $i;
7067              
7068             # [^...]
7069 0 0         if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
7070 0           splice @char, $left, $right-$left+1, sprintf(q{@{[Char::Elatin1::charlist_not_qr(%s,'%s')]}}, join(',', map {qq_stuff($delimiter,$end_delimiter,$_)} @char[$left+1..$right-1]), $modifier);
  0            
7071             }
7072             else {
7073 0           splice @char, $left, $right-$left+1, Char::Elatin1::charlist_not_qr(@char[$left+1..$right-1], $modifier);
7074             }
7075              
7076 0           $i = $left;
7077 0           last;
7078             }
7079             }
7080             }
7081              
7082             # rewrite character class or escape character
7083             elsif (my $char = character_class($char[$i],$modifier)) {
7084 0           $char[$i] = $char;
7085             }
7086              
7087             # P.794 29.2.161. split
7088             # in Chapter 29: Functions
7089             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
7090              
7091             # P.951 split
7092             # in Chapter 27: Functions
7093             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
7094              
7095             # said "The //m modifier is assumed when you split on the pattern /^/",
7096             # but perl5.008 is not so. Therefore, this software adds //m.
7097             # (and so on)
7098              
7099             # split(m/^/) --> split(m/^/m)
7100             elsif (($char[$i] eq '^') and ($modifier !~ /m/oxms)) {
7101 0           $modifier .= 'm';
7102             }
7103              
7104             # /i modifier
7105             elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Char::Elatin1::uc($char[$i]) ne Char::Elatin1::fc($char[$i]))) {
7106 0 0         if (CORE::length(Char::Elatin1::fc($char[$i])) == 1) {
7107 0           $char[$i] = '[' . Char::Elatin1::uc($char[$i]) . Char::Elatin1::fc($char[$i]) . ']';
7108             }
7109             else {
7110 0           $char[$i] = '(?:' . Char::Elatin1::uc($char[$i]) . '|' . Char::Elatin1::fc($char[$i]) . ')';
7111             }
7112             }
7113              
7114             # \u \l \U \L \F \Q \E
7115             elsif ($char[$i] =~ /\A ([<>]) \z/oxms) {
7116 0 0         if ($right_e < $left_e) {
7117 0           $char[$i] = '\\' . $char[$i];
7118             }
7119             }
7120             elsif ($char[$i] eq '\u') {
7121 0           $char[$i] = '@{[Char::Elatin1::ucfirst qq<';
7122 0           $left_e++;
7123             }
7124             elsif ($char[$i] eq '\l') {
7125 0           $char[$i] = '@{[Char::Elatin1::lcfirst qq<';
7126 0           $left_e++;
7127             }
7128             elsif ($char[$i] eq '\U') {
7129 0           $char[$i] = '@{[Char::Elatin1::uc qq<';
7130 0           $left_e++;
7131             }
7132             elsif ($char[$i] eq '\L') {
7133 0           $char[$i] = '@{[Char::Elatin1::lc qq<';
7134 0           $left_e++;
7135             }
7136             elsif ($char[$i] eq '\F') {
7137 0           $char[$i] = '@{[Char::Elatin1::fc qq<';
7138 0           $left_e++;
7139             }
7140             elsif ($char[$i] eq '\Q') {
7141 0           $char[$i] = '@{[CORE::quotemeta qq<';
7142 0           $left_e++;
7143             }
7144             elsif ($char[$i] eq '\E') {
7145 0 0         if ($right_e < $left_e) {
7146 0           $char[$i] = '>]}';
7147 0           $right_e++;
7148             }
7149             else {
7150 0           $char[$i] = '';
7151             }
7152             }
7153             elsif ($char[$i] eq '\Q') {
7154 0           while (1) {
7155 0 0         if (++$i > $#char) {
7156 0           last;
7157             }
7158 0 0         if ($char[$i] eq '\E') {
7159 0           last;
7160             }
7161             }
7162             }
7163             elsif ($char[$i] eq '\E') {
7164             }
7165              
7166             # $0 --> $0
7167             elsif ($char[$i] =~ /\A \$ 0 \z/oxms) {
7168 0 0         if ($ignorecase) {
7169 0           $char[$i] = '@{[Char::Elatin1::ignorecase(' . $char[$i] . ')]}';
7170             }
7171             }
7172             elsif ($char[$i] =~ /\A \$ \{ \s* 0 \s* \} \z/oxms) {
7173 0 0         if ($ignorecase) {
7174 0           $char[$i] = '@{[Char::Elatin1::ignorecase(' . $char[$i] . ')]}';
7175             }
7176             }
7177              
7178             # $$ --> $$
7179             elsif ($char[$i] =~ /\A \$\$ \z/oxms) {
7180             }
7181              
7182             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
7183             # $1, $2, $3 --> $1, $2, $3 otherwise
7184             elsif ($char[$i] =~ /\A \$ ([1-9][0-9]*) \z/oxms) {
7185 0           $char[$i] = e_capture($1);
7186 0 0         if ($ignorecase) {
7187 0           $char[$i] = '@{[Char::Elatin1::ignorecase(' . $char[$i] . ')]}';
7188             }
7189             }
7190             elsif ($char[$i] =~ /\A \$ \{ \s* ([1-9][0-9]*) \s* \} \z/oxms) {
7191 0           $char[$i] = e_capture($1);
7192 0 0         if ($ignorecase) {
7193 0           $char[$i] = '@{[Char::Elatin1::ignorecase(' . $char[$i] . ')]}';
7194             }
7195             }
7196              
7197             # $$foo[ ... ] --> $ $foo->[ ... ]
7198             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) ( \[ (?:$qq_bracket)*? \] ) \z/oxms) {
7199 0           $char[$i] = e_capture($1.'->'.$2);
7200 0 0         if ($ignorecase) {
7201 0           $char[$i] = '@{[Char::Elatin1::ignorecase(' . $char[$i] . ')]}';
7202             }
7203             }
7204              
7205             # $$foo{ ... } --> $ $foo->{ ... }
7206             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) ( \{ (?:$qq_brace)*? \} ) \z/oxms) {
7207 0           $char[$i] = e_capture($1.'->'.$2);
7208 0 0         if ($ignorecase) {
7209 0           $char[$i] = '@{[Char::Elatin1::ignorecase(' . $char[$i] . ')]}';
7210             }
7211             }
7212              
7213             # $$foo
7214             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) \z/oxms) {
7215 0           $char[$i] = e_capture($1);
7216 0 0         if ($ignorecase) {
7217 0           $char[$i] = '@{[Char::Elatin1::ignorecase(' . $char[$i] . ')]}';
7218             }
7219             }
7220              
7221             # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Char::Elatin1::PREMATCH()
7222             elsif ($char[$i] =~ /\A ( \$` | \$\{`\} | \$ \s* PREMATCH | \$ \s* \{ \s* PREMATCH \s* \} | \$ \s* \{\^PREMATCH\} ) \z/oxmsgc) {
7223 0 0         if ($ignorecase) {
7224 0           $char[$i] = '@{[Char::Elatin1::ignorecase(Char::Elatin1::PREMATCH())]}';
7225             }
7226             else {
7227 0           $char[$i] = '@{[Char::Elatin1::PREMATCH()]}';
7228             }
7229             }
7230              
7231             # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Char::Elatin1::MATCH()
7232             elsif ($char[$i] =~ /\A ( \$& | \$\{&\} | \$ \s* MATCH | \$ \s* \{ \s* MATCH \s* \} | \$ \s* \{\^MATCH\} ) \z/oxmsgc) {
7233 0 0         if ($ignorecase) {
7234 0           $char[$i] = '@{[Char::Elatin1::ignorecase(Char::Elatin1::MATCH())]}';
7235             }
7236             else {
7237 0           $char[$i] = '@{[Char::Elatin1::MATCH()]}';
7238             }
7239             }
7240              
7241             # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Char::Elatin1::POSTMATCH()
7242             elsif ($char[$i] =~ /\A ( \$ \s* POSTMATCH | \$ \s* \{ \s* POSTMATCH \s* \} | \$ \s* \{\^POSTMATCH\} ) \z/oxmsgc) {
7243 0 0         if ($ignorecase) {
7244 0           $char[$i] = '@{[Char::Elatin1::ignorecase(Char::Elatin1::POSTMATCH())]}';
7245             }
7246             else {
7247 0           $char[$i] = '@{[Char::Elatin1::POSTMATCH()]}';
7248             }
7249             }
7250              
7251             # ${ foo }
7252             elsif ($char[$i] =~ /\A \$ \s* \{ ( \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* ) \} \z/oxms) {
7253 0 0         if ($ignorecase) {
7254 0           $char[$i] = '@{[Char::Elatin1::ignorecase(' . $1 . ')]}';
7255             }
7256             }
7257              
7258             # ${ ... }
7259             elsif ($char[$i] =~ /\A \$ \s* \{ \s* ( .+ ) \s* \} \z/oxms) {
7260 0           $char[$i] = e_capture($1);
7261 0 0         if ($ignorecase) {
7262 0           $char[$i] = '@{[Char::Elatin1::ignorecase(' . $char[$i] . ')]}';
7263             }
7264             }
7265              
7266             # $scalar or @array
7267             elsif ($char[$i] =~ /\A [\$\@].+ /oxms) {
7268 0           $char[$i] = e_string($char[$i]);
7269 0 0         if ($ignorecase) {
7270 0           $char[$i] = '@{[Char::Elatin1::ignorecase(' . $char[$i] . ')]}';
7271             }
7272             }
7273              
7274             # quote character before ? + * {
7275             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
7276 0 0         if ($char[$i-1] =~ /\A (?:\\[0-7]{2,3}|\\x[0-9-A-Fa-f]{1,2}) \z/oxms) {
7277             }
7278             else {
7279 0           $char[$i-1] = '(?:' . $char[$i-1] . ')';
7280             }
7281             }
7282             }
7283              
7284             # make regexp string
7285 0           $modifier =~ tr/i//d;
7286 0 0         if ($left_e > $right_e) {
7287 0           return join '', 'Char::Elatin1::split', $ope, $delimiter, @char, '>]}' x ($left_e - $right_e), $end_delimiter, $modifier;
7288             }
7289 0           return join '', 'Char::Elatin1::split', $ope, $delimiter, @char, $end_delimiter, $modifier;
7290             }
7291              
7292             #
7293             # escape regexp of split qr''
7294             #
7295             sub e_split_q {
7296 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
7297 0   0       $modifier ||= '';
7298              
7299 0           $modifier =~ tr/p//d;
7300 0 0         if ($modifier =~ /([adlu])/oxms) {
7301 0           my $line = 0;
7302 0           for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
7303 0 0         if ($filename ne __FILE__) {
7304 0           $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
7305 0           last;
7306             }
7307             }
7308 0           die qq{Unsupported modifier "$1" used at line $line.\n};
7309             }
7310              
7311 0           $slash = 'div';
7312              
7313             # /b /B modifier
7314 0 0         if ($modifier =~ tr/bB//d) {
7315 0           return join '', 'split', $ope, $delimiter, $string, $end_delimiter, $modifier;
7316             }
7317              
7318 0 0         my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
7319              
7320             # split regexp
7321 0           my @char = $string =~ /\G(
7322             \[\:\^ [a-z]+ \:\] |
7323             \[\: [a-z]+ \:\] |
7324             \[\^ |
7325             \\? (?:$q_char)
7326             )/oxmsg;
7327              
7328             # unescape character
7329 0           for (my $i=0; $i <= $#char; $i++) {
7330 0 0 0       if (0) {
    0 0        
    0 0        
    0 0        
    0          
    0          
7331             }
7332              
7333             # open character class [...]
7334 0           elsif ($char[$i] eq '[') {
7335 0           my $left = $i;
7336 0 0         if ($char[$i+1] eq ']') {
7337 0           $i++;
7338             }
7339 0           while (1) {
7340 0 0         if (++$i > $#char) {
7341 0           die __FILE__, ": Unmatched [] in regexp";
7342             }
7343 0 0         if ($char[$i] eq ']') {
7344 0           my $right = $i;
7345              
7346             # [...]
7347 0           splice @char, $left, $right-$left+1, Char::Elatin1::charlist_qr(@char[$left+1..$right-1], $modifier);
7348              
7349 0           $i = $left;
7350 0           last;
7351             }
7352             }
7353             }
7354              
7355             # open character class [^...]
7356             elsif ($char[$i] eq '[^') {
7357 0           my $left = $i;
7358 0 0         if ($char[$i+1] eq ']') {
7359 0           $i++;
7360             }
7361 0           while (1) {
7362 0 0         if (++$i > $#char) {
7363 0           die __FILE__, ": Unmatched [] in regexp";
7364             }
7365 0 0         if ($char[$i] eq ']') {
7366 0           my $right = $i;
7367              
7368             # [^...]
7369 0           splice @char, $left, $right-$left+1, Char::Elatin1::charlist_not_qr(@char[$left+1..$right-1], $modifier);
7370              
7371 0           $i = $left;
7372 0           last;
7373             }
7374             }
7375             }
7376              
7377             # rewrite character class or escape character
7378             elsif (my $char = character_class($char[$i],$modifier)) {
7379 0           $char[$i] = $char;
7380             }
7381              
7382             # split(m/^/) --> split(m/^/m)
7383             elsif (($char[$i] eq '^') and ($modifier !~ /m/oxms)) {
7384 0           $modifier .= 'm';
7385             }
7386              
7387             # /i modifier
7388             elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Char::Elatin1::uc($char[$i]) ne Char::Elatin1::fc($char[$i]))) {
7389 0 0         if (CORE::length(Char::Elatin1::fc($char[$i])) == 1) {
7390 0           $char[$i] = '[' . Char::Elatin1::uc($char[$i]) . Char::Elatin1::fc($char[$i]) . ']';
7391             }
7392             else {
7393 0           $char[$i] = '(?:' . Char::Elatin1::uc($char[$i]) . '|' . Char::Elatin1::fc($char[$i]) . ')';
7394             }
7395             }
7396              
7397             # quote character before ? + * {
7398             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
7399 0 0         if ($char[$i-1] =~ /\A [\x00-\xFF] \z/oxms) {
7400             }
7401             else {
7402 0           $char[$i-1] = '(?:' . $char[$i-1] . ')';
7403             }
7404             }
7405             }
7406              
7407 0           $modifier =~ tr/i//d;
7408 0           return join '', 'Char::Elatin1::split', $ope, $delimiter, @char, $end_delimiter, $modifier;
7409             }
7410              
7411             #
7412             # instead of Carp::carp
7413             #
7414             sub carp {
7415 0     0 0   my($package,$filename,$line) = caller(1);
7416 0           print STDERR "@_ at $filename line $line.\n";
7417             }
7418              
7419             #
7420             # instead of Carp::croak
7421             #
7422             sub croak {
7423 0     0 0   my($package,$filename,$line) = caller(1);
7424 0           print STDERR "@_ at $filename line $line.\n";
7425 0           die "\n";
7426             }
7427              
7428             #
7429             # instead of Carp::cluck
7430             #
7431             sub cluck {
7432 0     0 0   my $i = 0;
7433 0           my @cluck = ();
7434 0           while (my($package,$filename,$line,$subroutine) = caller($i)) {
7435 0           push @cluck, "[$i] $filename($line) $package::$subroutine\n";
7436 0           $i++;
7437             }
7438 0           print STDERR CORE::reverse @cluck;
7439 0           print STDERR "\n";
7440 0           carp @_;
7441             }
7442              
7443             #
7444             # instead of Carp::confess
7445             #
7446             sub confess {
7447 0     0 0   my $i = 0;
7448 0           my @confess = ();
7449 0           while (my($package,$filename,$line,$subroutine) = caller($i)) {
7450 0           push @confess, "[$i] $filename($line) $package::$subroutine\n";
7451 0           $i++;
7452             }
7453 0           print STDERR CORE::reverse @confess;
7454 0           print STDERR "\n";
7455 0           croak @_;
7456             }
7457              
7458             1;
7459              
7460             __END__