File Coverage

Char/Elatin4.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::Elatin4;
5             ######################################################################
6             #
7             # Char::Elatin4 - Run-time routines for Char/Latin4.pm
8             #
9             # http://search.cpan.org/dist/Char-Latin4/
10             #
11             # Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015 INABA Hitoshi
12             ######################################################################
13              
14 197     197   5315 use 5.00503; # Galapagos Consensus 1998 for primetools
  197         878  
  197         12132  
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   14321 BEGIN { CORE::eval q{ use vars qw($VERSION) } }
  197     197   1158  
  197         442  
  197         43285  
23             $VERSION = sprintf '%d.%02d', q$Revision: 1.02 $ =~ /(\d+)/xmsg;
24              
25             BEGIN {
26 197 50   197   1299 if ($^X =~ / jperl /oxmsi) {
27 0         0 die __FILE__, ": needs perl(not jperl) 5.00503 or later. (\$^X==$^X)";
28             }
29 197         550 if (CORE::ord('A') == 193) {
30             die __FILE__, ": is not US-ASCII script (may be EBCDIC or EBCDIK script).";
31             }
32 197         32883 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   14334 CORE::eval q{
  197     197   1209  
  197     64   340  
  197         31958  
  64         10921  
  69         13132  
  72         13058  
  52         8512  
  60         10053  
  77         13107  
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       157082 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   532 my $genpkg = "Symbol::";
62 197         10526 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::Elatin4::index($name, '::') == -1) && (Char::Elatin4::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   458 if (CORE::eval { local $@; CORE::require strict }) {
  197         383  
  197         2207  
110 197         28737 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   13027 BEGIN { CORE::eval q{ use vars qw($your_char) } } $your_char = q{[\x00-\xFF]};
  197     197   1180  
  197         731  
  197         13318  
140 197     197   11378 BEGIN { CORE::eval q{ use vars qw($qq_char ) } } $qq_char = qr/\\c[\x40-\x5F]|\\?(?:$your_char)/oxms;
  197     197   1224  
  197         337  
  197         16340  
141 197     197   12068 BEGIN { CORE::eval q{ use vars qw($q_char ) } } $q_char = qr/$your_char/oxms;
  197     197   1429  
  197         335  
  197         15272  
142              
143             #
144             # Latin-4 character range per length
145             #
146             my %range_tr = ();
147              
148             #
149             # alias of encoding name
150             #
151 197     197   14548 BEGIN { CORE::eval q{ use vars qw($encoding_alias) } }
  197     197   1223  
  197         331  
  197         459459  
152              
153             #
154             # Latin-4 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 Elatin4 \z/oxms) {
170             %range_tr = (
171             1 => [ [0x00..0xFF],
172             ],
173             );
174             $encoding_alias = qr/ \b (?: iso[-_ ]?8859-4 | iec[- ]?8859-4 | latin-?4 ) \b /oxmsi;
175              
176             %lc = (%lc,
177             "\xA1" => "\xB1", # LATIN LETTER A WITH OGONEK
178             "\xA3" => "\xB3", # LATIN LETTER R WITH CEDILLA
179             "\xA5" => "\xB5", # LATIN LETTER I WITH TILDE
180             "\xA6" => "\xB6", # LATIN LETTER L WITH CEDILLA
181             "\xA9" => "\xB9", # LATIN LETTER S WITH CARON
182             "\xAA" => "\xBA", # LATIN LETTER E WITH MACRON
183             "\xAB" => "\xBB", # LATIN LETTER G WITH CEDILLA
184             "\xAC" => "\xBC", # LATIN LETTER T WITH STROKE
185             "\xAE" => "\xBE", # LATIN LETTER Z WITH CARON
186             "\xBD" => "\xBF", # LATIN LETTER ENG
187             "\xC0" => "\xE0", # LATIN LETTER A WITH MACRON
188             "\xC1" => "\xE1", # LATIN LETTER A WITH ACUTE
189             "\xC2" => "\xE2", # LATIN LETTER A WITH CIRCUMFLEX
190             "\xC3" => "\xE3", # LATIN LETTER A WITH TILDE
191             "\xC4" => "\xE4", # LATIN LETTER A WITH DIAERESIS
192             "\xC5" => "\xE5", # LATIN LETTER A WITH RING ABOVE
193             "\xC6" => "\xE6", # LATIN LETTER AE
194             "\xC7" => "\xE7", # LATIN LETTER I WITH OGONEK
195             "\xC8" => "\xE8", # LATIN LETTER C WITH CARON
196             "\xC9" => "\xE9", # LATIN LETTER E WITH ACUTE
197             "\xCA" => "\xEA", # LATIN LETTER E WITH OGONEK
198             "\xCB" => "\xEB", # LATIN LETTER E WITH DIAERESIS
199             "\xCC" => "\xEC", # LATIN LETTER E WITH DOT ABOVE
200             "\xCD" => "\xED", # LATIN LETTER I WITH ACUTE
201             "\xCE" => "\xEE", # LATIN LETTER I WITH CIRCUMFLEX
202             "\xCF" => "\xEF", # LATIN LETTER I WITH MACRON
203             "\xD0" => "\xF0", # LATIN LETTER D WITH STROKE
204             "\xD1" => "\xF1", # LATIN LETTER N WITH CEDILLA
205             "\xD2" => "\xF2", # LATIN LETTER O WITH MACRON
206             "\xD3" => "\xF3", # LATIN LETTER K WITH CEDILLA
207             "\xD4" => "\xF4", # LATIN LETTER O WITH CIRCUMFLEX
208             "\xD5" => "\xF5", # LATIN LETTER O WITH TILDE
209             "\xD6" => "\xF6", # LATIN LETTER O WITH DIAERESIS
210             "\xD8" => "\xF8", # LATIN LETTER O WITH STROKE
211             "\xD9" => "\xF9", # LATIN LETTER U WITH OGONEK
212             "\xDA" => "\xFA", # LATIN LETTER U WITH ACUTE
213             "\xDB" => "\xFB", # LATIN LETTER U WITH CIRCUMFLEX
214             "\xDC" => "\xFC", # LATIN LETTER U WITH DIAERESIS
215             "\xDD" => "\xFD", # LATIN LETTER U WITH TILDE
216             "\xDE" => "\xFE", # LATIN LETTER U WITH MACRON
217             );
218              
219             %uc = (%uc,
220             "\xB1" => "\xA1", # LATIN LETTER A WITH OGONEK
221             "\xB3" => "\xA3", # LATIN LETTER R WITH CEDILLA
222             "\xB5" => "\xA5", # LATIN LETTER I WITH TILDE
223             "\xB6" => "\xA6", # LATIN LETTER L WITH CEDILLA
224             "\xB9" => "\xA9", # LATIN LETTER S WITH CARON
225             "\xBA" => "\xAA", # LATIN LETTER E WITH MACRON
226             "\xBB" => "\xAB", # LATIN LETTER G WITH CEDILLA
227             "\xBC" => "\xAC", # LATIN LETTER T WITH STROKE
228             "\xBE" => "\xAE", # LATIN LETTER Z WITH CARON
229             "\xBF" => "\xBD", # LATIN LETTER ENG
230             "\xE0" => "\xC0", # LATIN LETTER A WITH MACRON
231             "\xE1" => "\xC1", # LATIN LETTER A WITH ACUTE
232             "\xE2" => "\xC2", # LATIN LETTER A WITH CIRCUMFLEX
233             "\xE3" => "\xC3", # LATIN LETTER A WITH TILDE
234             "\xE4" => "\xC4", # LATIN LETTER A WITH DIAERESIS
235             "\xE5" => "\xC5", # LATIN LETTER A WITH RING ABOVE
236             "\xE6" => "\xC6", # LATIN LETTER AE
237             "\xE7" => "\xC7", # LATIN LETTER I WITH OGONEK
238             "\xE8" => "\xC8", # LATIN LETTER C WITH CARON
239             "\xE9" => "\xC9", # LATIN LETTER E WITH ACUTE
240             "\xEA" => "\xCA", # LATIN LETTER E WITH OGONEK
241             "\xEB" => "\xCB", # LATIN LETTER E WITH DIAERESIS
242             "\xEC" => "\xCC", # LATIN LETTER E WITH DOT ABOVE
243             "\xED" => "\xCD", # LATIN LETTER I WITH ACUTE
244             "\xEE" => "\xCE", # LATIN LETTER I WITH CIRCUMFLEX
245             "\xEF" => "\xCF", # LATIN LETTER I WITH MACRON
246             "\xF0" => "\xD0", # LATIN LETTER D WITH STROKE
247             "\xF1" => "\xD1", # LATIN LETTER N WITH CEDILLA
248             "\xF2" => "\xD2", # LATIN LETTER O WITH MACRON
249             "\xF3" => "\xD3", # LATIN LETTER K WITH CEDILLA
250             "\xF4" => "\xD4", # LATIN LETTER O WITH CIRCUMFLEX
251             "\xF5" => "\xD5", # LATIN LETTER O WITH TILDE
252             "\xF6" => "\xD6", # LATIN LETTER O WITH DIAERESIS
253             "\xF8" => "\xD8", # LATIN LETTER O WITH STROKE
254             "\xF9" => "\xD9", # LATIN LETTER U WITH OGONEK
255             "\xFA" => "\xDA", # LATIN LETTER U WITH ACUTE
256             "\xFB" => "\xDB", # LATIN LETTER U WITH CIRCUMFLEX
257             "\xFC" => "\xDC", # LATIN LETTER U WITH DIAERESIS
258             "\xFD" => "\xDD", # LATIN LETTER U WITH TILDE
259             "\xFE" => "\xDE", # LATIN LETTER U WITH MACRON
260             );
261              
262             %fc = (%fc,
263             "\xA1" => "\xB1", # LATIN CAPITAL LETTER A WITH OGONEK --> LATIN SMALL LETTER A WITH OGONEK
264             "\xA3" => "\xB3", # LATIN CAPITAL LETTER R WITH CEDILLA --> LATIN SMALL LETTER R WITH CEDILLA
265             "\xA5" => "\xB5", # LATIN CAPITAL LETTER I WITH TILDE --> LATIN SMALL LETTER I WITH TILDE
266             "\xA6" => "\xB6", # LATIN CAPITAL LETTER L WITH CEDILLA --> LATIN SMALL LETTER L WITH CEDILLA
267             "\xA9" => "\xB9", # LATIN CAPITAL LETTER S WITH CARON --> LATIN SMALL LETTER S WITH CARON
268             "\xAA" => "\xBA", # LATIN CAPITAL LETTER E WITH MACRON --> LATIN SMALL LETTER E WITH MACRON
269             "\xAB" => "\xBB", # LATIN CAPITAL LETTER G WITH CEDILLA --> LATIN SMALL LETTER G WITH CEDILLA
270             "\xAC" => "\xBC", # LATIN CAPITAL LETTER T WITH STROKE --> LATIN SMALL LETTER T WITH STROKE
271             "\xAE" => "\xBE", # LATIN CAPITAL LETTER Z WITH CARON --> LATIN SMALL LETTER Z WITH CARON
272             "\xBD" => "\xBF", # LATIN CAPITAL LETTER ENG --> LATIN SMALL LETTER ENG
273             "\xC0" => "\xE0", # LATIN CAPITAL LETTER A WITH MACRON --> LATIN SMALL LETTER A WITH MACRON
274             "\xC1" => "\xE1", # LATIN CAPITAL LETTER A WITH ACUTE --> LATIN SMALL LETTER A WITH ACUTE
275             "\xC2" => "\xE2", # LATIN CAPITAL LETTER A WITH CIRCUMFLEX --> LATIN SMALL LETTER A WITH CIRCUMFLEX
276             "\xC3" => "\xE3", # LATIN CAPITAL LETTER A WITH TILDE --> LATIN SMALL LETTER A WITH TILDE
277             "\xC4" => "\xE4", # LATIN CAPITAL LETTER A WITH DIAERESIS --> LATIN SMALL LETTER A WITH DIAERESIS
278             "\xC5" => "\xE5", # LATIN CAPITAL LETTER A WITH RING ABOVE --> LATIN SMALL LETTER A WITH RING ABOVE
279             "\xC6" => "\xE6", # LATIN CAPITAL LETTER AE --> LATIN SMALL LETTER AE
280             "\xC7" => "\xE7", # LATIN CAPITAL LETTER I WITH OGONEK --> LATIN SMALL LETTER I WITH OGONEK
281             "\xC8" => "\xE8", # LATIN CAPITAL LETTER C WITH CARON --> LATIN SMALL LETTER C WITH CARON
282             "\xC9" => "\xE9", # LATIN CAPITAL LETTER E WITH ACUTE --> LATIN SMALL LETTER E WITH ACUTE
283             "\xCA" => "\xEA", # LATIN CAPITAL LETTER E WITH OGONEK --> LATIN SMALL LETTER E WITH OGONEK
284             "\xCB" => "\xEB", # LATIN CAPITAL LETTER E WITH DIAERESIS --> LATIN SMALL LETTER E WITH DIAERESIS
285             "\xCC" => "\xEC", # LATIN CAPITAL LETTER E WITH DOT ABOVE --> LATIN SMALL LETTER E WITH DOT ABOVE
286             "\xCD" => "\xED", # LATIN CAPITAL LETTER I WITH ACUTE --> LATIN SMALL LETTER I WITH ACUTE
287             "\xCE" => "\xEE", # LATIN CAPITAL LETTER I WITH CIRCUMFLEX --> LATIN SMALL LETTER I WITH CIRCUMFLEX
288             "\xCF" => "\xEF", # LATIN CAPITAL LETTER I WITH MACRON --> LATIN SMALL LETTER I WITH MACRON
289             "\xD0" => "\xF0", # LATIN CAPITAL LETTER D WITH STROKE --> LATIN SMALL LETTER D WITH STROKE
290             "\xD1" => "\xF1", # LATIN CAPITAL LETTER N WITH CEDILLA --> LATIN SMALL LETTER N WITH CEDILLA
291             "\xD2" => "\xF2", # LATIN CAPITAL LETTER O WITH MACRON --> LATIN SMALL LETTER O WITH MACRON
292             "\xD3" => "\xF3", # LATIN CAPITAL LETTER K WITH CEDILLA --> LATIN SMALL LETTER K WITH CEDILLA
293             "\xD4" => "\xF4", # LATIN CAPITAL LETTER O WITH CIRCUMFLEX --> LATIN SMALL LETTER O WITH CIRCUMFLEX
294             "\xD5" => "\xF5", # LATIN CAPITAL LETTER O WITH TILDE --> LATIN SMALL LETTER O WITH TILDE
295             "\xD6" => "\xF6", # LATIN CAPITAL LETTER O WITH DIAERESIS --> LATIN SMALL LETTER O WITH DIAERESIS
296             "\xD8" => "\xF8", # LATIN CAPITAL LETTER O WITH STROKE --> LATIN SMALL LETTER O WITH STROKE
297             "\xD9" => "\xF9", # LATIN CAPITAL LETTER U WITH OGONEK --> LATIN SMALL LETTER U WITH OGONEK
298             "\xDA" => "\xFA", # LATIN CAPITAL LETTER U WITH ACUTE --> LATIN SMALL LETTER U WITH ACUTE
299             "\xDB" => "\xFB", # LATIN CAPITAL LETTER U WITH CIRCUMFLEX --> LATIN SMALL LETTER U WITH CIRCUMFLEX
300             "\xDC" => "\xFC", # LATIN CAPITAL LETTER U WITH DIAERESIS --> LATIN SMALL LETTER U WITH DIAERESIS
301             "\xDD" => "\xFD", # LATIN CAPITAL LETTER U WITH TILDE --> LATIN SMALL LETTER U WITH TILDE
302             "\xDE" => "\xFE", # LATIN CAPITAL LETTER U WITH MACRON --> LATIN SMALL LETTER U WITH MACRON
303             "\xDF" => "\x73\x73", # LATIN SMALL LETTER SHARP S --> LATIN SMALL LETTER S, LATIN SMALL LETTER S
304             );
305             }
306              
307             else {
308             croak "Don't know my package name '@{[__PACKAGE__]}'";
309             }
310              
311             #
312             # @ARGV wildcard globbing
313             #
314             sub import {
315              
316 0 0   0   0 if ($^O =~ /\A (?: MSWin32 | NetWare | symbian | dos ) \z/oxms) {
317 0         0 my @argv = ();
318 0         0 for (@ARGV) {
319              
320             # has space
321 0 0       0 if (/\A (?:$q_char)*? [ ] /oxms) {
    0          
322 0 0       0 if (my @glob = Char::Elatin4::glob(qq{"$_"})) {
323 0         0 push @argv, @glob;
324             }
325             else {
326 0         0 push @argv, $_;
327             }
328             }
329              
330             # has wildcard metachar
331             elsif (/\A (?:$q_char)*? [*?] /oxms) {
332 0 0       0 if (my @glob = Char::Elatin4::glob($_)) {
333 0         0 push @argv, @glob;
334             }
335             else {
336 0         0 push @argv, $_;
337             }
338             }
339              
340             # no wildcard globbing
341             else {
342 0         0 push @argv, $_;
343             }
344             }
345 0         0 @ARGV = @argv;
346             }
347             }
348              
349             # P.230 Care with Prototypes
350             # in Chapter 6: Subroutines
351             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
352             #
353             # If you aren't careful, you can get yourself into trouble with prototypes.
354             # But if you are careful, you can do a lot of neat things with them. This is
355             # all very powerful, of course, and should only be used in moderation to make
356             # the world a better place.
357              
358             # P.332 Care with Prototypes
359             # in Chapter 7: Subroutines
360             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
361             #
362             # If you aren't careful, you can get yourself into trouble with prototypes.
363             # But if you are careful, you can do a lot of neat things with them. This is
364             # all very powerful, of course, and should only be used in moderation to make
365             # the world a better place.
366              
367             #
368             # Prototypes of subroutines
369             #
370 0     0   0 sub unimport {}
371             sub Char::Elatin4::split(;$$$);
372             sub Char::Elatin4::tr($$$$;$);
373             sub Char::Elatin4::chop(@);
374             sub Char::Elatin4::index($$;$);
375             sub Char::Elatin4::rindex($$;$);
376             sub Char::Elatin4::lcfirst(@);
377             sub Char::Elatin4::lcfirst_();
378             sub Char::Elatin4::lc(@);
379             sub Char::Elatin4::lc_();
380             sub Char::Elatin4::ucfirst(@);
381             sub Char::Elatin4::ucfirst_();
382             sub Char::Elatin4::uc(@);
383             sub Char::Elatin4::uc_();
384             sub Char::Elatin4::fc(@);
385             sub Char::Elatin4::fc_();
386             sub Char::Elatin4::ignorecase;
387             sub Char::Elatin4::classic_character_class;
388             sub Char::Elatin4::capture;
389             sub Char::Elatin4::chr(;$);
390             sub Char::Elatin4::chr_();
391             sub Char::Elatin4::glob($);
392             sub Char::Elatin4::glob_();
393              
394             sub Char::Latin4::ord(;$);
395             sub Char::Latin4::ord_();
396             sub Char::Latin4::reverse(@);
397             sub Char::Latin4::getc(;*@);
398             sub Char::Latin4::length(;$);
399             sub Char::Latin4::substr($$;$$);
400             sub Char::Latin4::index($$;$);
401             sub Char::Latin4::rindex($$;$);
402             sub Char::Latin4::escape(;$);
403              
404             #
405             # Regexp work
406             #
407 197     197   16641 BEGIN { CORE::eval q{ use vars qw(
  197     197   1613  
  197         592  
  197         99880  
408             $Char::Latin4::re_a
409             $Char::Latin4::re_t
410             $Char::Latin4::re_n
411             $Char::Latin4::re_r
412             ) } }
413              
414             #
415             # Character class
416             #
417 197     197   15883 BEGIN { CORE::eval q{ use vars qw(
  197     197   3421  
  197         344  
  197         3317995  
418             $dot
419             $dot_s
420             $eD
421             $eS
422             $eW
423             $eH
424             $eV
425             $eR
426             $eN
427             $not_alnum
428             $not_alpha
429             $not_ascii
430             $not_blank
431             $not_cntrl
432             $not_digit
433             $not_graph
434             $not_lower
435             $not_lower_i
436             $not_print
437             $not_punct
438             $not_space
439             $not_upper
440             $not_upper_i
441             $not_word
442             $not_xdigit
443             $eb
444             $eB
445             ) } }
446              
447             ${Char::Elatin4::dot} = qr{(?:[^\x0A])};
448             ${Char::Elatin4::dot_s} = qr{(?:[\x00-\xFF])};
449             ${Char::Elatin4::eD} = qr{(?:[^0-9])};
450              
451             # Vertical tabs are now whitespace
452             # \s in a regex now matches a vertical tab in all circumstances.
453             # http://search.cpan.org/dist/perl-5.18.0/pod/perldelta.pod#Vertical_tabs_are_now_whitespace
454             # ${Char::Elatin4::eS} = qr{(?:[^\x09\x0A \x0C\x0D\x20])};
455             # ${Char::Elatin4::eS} = qr{(?:[^\x09\x0A\x0B\x0C\x0D\x20])};
456             ${Char::Elatin4::eS} = qr{(?:[^\s])};
457              
458             ${Char::Elatin4::eW} = qr{(?:[^0-9A-Z_a-z])};
459             ${Char::Elatin4::eH} = qr{(?:[^\x09\x20])};
460             ${Char::Elatin4::eV} = qr{(?:[^\x0A\x0B\x0C\x0D])};
461             ${Char::Elatin4::eR} = qr{(?:\x0D\x0A|[\x0A\x0D])};
462             ${Char::Elatin4::eN} = qr{(?:[^\x0A])};
463             ${Char::Elatin4::not_alnum} = qr{(?:[^\x30-\x39\x41-\x5A\x61-\x7A])};
464             ${Char::Elatin4::not_alpha} = qr{(?:[^\x41-\x5A\x61-\x7A])};
465             ${Char::Elatin4::not_ascii} = qr{(?:[^\x00-\x7F])};
466             ${Char::Elatin4::not_blank} = qr{(?:[^\x09\x20])};
467             ${Char::Elatin4::not_cntrl} = qr{(?:[^\x00-\x1F\x7F])};
468             ${Char::Elatin4::not_digit} = qr{(?:[^\x30-\x39])};
469             ${Char::Elatin4::not_graph} = qr{(?:[^\x21-\x7F])};
470             ${Char::Elatin4::not_lower} = qr{(?:[^\x61-\x7A])};
471             ${Char::Elatin4::not_lower_i} = qr{(?:[\x00-\xFF])};
472             ${Char::Elatin4::not_print} = qr{(?:[^\x20-\x7F])};
473             ${Char::Elatin4::not_punct} = qr{(?:[^\x21-\x2F\x3A-\x3F\x40\x5B-\x5F\x60\x7B-\x7E])};
474             ${Char::Elatin4::not_space} = qr{(?:[^\s\x0B])};
475             ${Char::Elatin4::not_upper} = qr{(?:[^\x41-\x5A])};
476             ${Char::Elatin4::not_upper_i} = qr{(?:[\x00-\xFF])};
477             ${Char::Elatin4::not_word} = qr{(?:[^\x30-\x39\x41-\x5A\x5F\x61-\x7A])};
478             ${Char::Elatin4::not_xdigit} = qr{(?:[^\x30-\x39\x41-\x46\x61-\x66])};
479             ${Char::Elatin4::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))};
480             ${Char::Elatin4::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]))};
481              
482             # avoid: Name "Char::Elatin4::foo" used only once: possible typo at here.
483             ${Char::Elatin4::dot} = ${Char::Elatin4::dot};
484             ${Char::Elatin4::dot_s} = ${Char::Elatin4::dot_s};
485             ${Char::Elatin4::eD} = ${Char::Elatin4::eD};
486             ${Char::Elatin4::eS} = ${Char::Elatin4::eS};
487             ${Char::Elatin4::eW} = ${Char::Elatin4::eW};
488             ${Char::Elatin4::eH} = ${Char::Elatin4::eH};
489             ${Char::Elatin4::eV} = ${Char::Elatin4::eV};
490             ${Char::Elatin4::eR} = ${Char::Elatin4::eR};
491             ${Char::Elatin4::eN} = ${Char::Elatin4::eN};
492             ${Char::Elatin4::not_alnum} = ${Char::Elatin4::not_alnum};
493             ${Char::Elatin4::not_alpha} = ${Char::Elatin4::not_alpha};
494             ${Char::Elatin4::not_ascii} = ${Char::Elatin4::not_ascii};
495             ${Char::Elatin4::not_blank} = ${Char::Elatin4::not_blank};
496             ${Char::Elatin4::not_cntrl} = ${Char::Elatin4::not_cntrl};
497             ${Char::Elatin4::not_digit} = ${Char::Elatin4::not_digit};
498             ${Char::Elatin4::not_graph} = ${Char::Elatin4::not_graph};
499             ${Char::Elatin4::not_lower} = ${Char::Elatin4::not_lower};
500             ${Char::Elatin4::not_lower_i} = ${Char::Elatin4::not_lower_i};
501             ${Char::Elatin4::not_print} = ${Char::Elatin4::not_print};
502             ${Char::Elatin4::not_punct} = ${Char::Elatin4::not_punct};
503             ${Char::Elatin4::not_space} = ${Char::Elatin4::not_space};
504             ${Char::Elatin4::not_upper} = ${Char::Elatin4::not_upper};
505             ${Char::Elatin4::not_upper_i} = ${Char::Elatin4::not_upper_i};
506             ${Char::Elatin4::not_word} = ${Char::Elatin4::not_word};
507             ${Char::Elatin4::not_xdigit} = ${Char::Elatin4::not_xdigit};
508             ${Char::Elatin4::eb} = ${Char::Elatin4::eb};
509             ${Char::Elatin4::eB} = ${Char::Elatin4::eB};
510              
511             #
512             # Latin-4 split
513             #
514             sub Char::Elatin4::split(;$$$) {
515              
516             # P.794 29.2.161. split
517             # in Chapter 29: Functions
518             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
519              
520             # P.951 split
521             # in Chapter 27: Functions
522             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
523              
524 0     0 0 0 my $pattern = $_[0];
525 0         0 my $string = $_[1];
526 0         0 my $limit = $_[2];
527              
528             # if $pattern is also omitted or is the literal space, " "
529 0 0       0 if (not defined $pattern) {
530 0         0 $pattern = ' ';
531             }
532              
533             # if $string is omitted, the function splits the $_ string
534 0 0       0 if (not defined $string) {
535 0 0       0 if (defined $_) {
536 0         0 $string = $_;
537             }
538             else {
539 0         0 $string = '';
540             }
541             }
542              
543 0         0 my @split = ();
544              
545             # when string is empty
546 0 0       0 if ($string eq '') {
    0          
547              
548             # resulting list value in list context
549 0 0       0 if (wantarray) {
550 0         0 return @split;
551             }
552              
553             # count of substrings in scalar context
554             else {
555 0 0       0 carp "Use of implicit split to \@_ is deprecated" if $^W;
556 0         0 @_ = @split;
557 0         0 return scalar @_;
558             }
559             }
560              
561             # split's first argument is more consistently interpreted
562             #
563             # After some changes earlier in v5.17, split's behavior has been simplified:
564             # if the PATTERN argument evaluates to a string containing one space, it is
565             # treated the way that a literal string containing one space once was.
566             # http://search.cpan.org/dist/perl-5.18.0/pod/perldelta.pod#split's_first_argument_is_more_consistently_interpreted
567              
568             # if $pattern is also omitted or is the literal space, " ", the function splits
569             # on whitespace, /\s+/, after skipping any leading whitespace
570             # (and so on)
571              
572             elsif ($pattern eq ' ') {
573 0 0       0 if (not defined $limit) {
574 0         0 return CORE::split(' ', $string);
575             }
576             else {
577 0         0 return CORE::split(' ', $string, $limit);
578             }
579             }
580              
581             # if $limit is negative, it is treated as if an arbitrarily large $limit has been specified
582 0 0 0     0 if ((not defined $limit) or ($limit <= 0)) {
    0          
583              
584             # a pattern capable of matching either the null string or something longer than the
585             # null string will split the value of $string into separate characters wherever it
586             # matches the null string between characters
587             # (and so on)
588              
589 0 0       0 if ('' =~ / \A $pattern \z /xms) {
590 0         0 my $last_subexpression_offsets = _last_subexpression_offsets($pattern);
591 0         0 my $limit = scalar(() = $string =~ /($pattern)/oxmsg);
592              
593             # P.1024 Appendix W.10 Multibyte Processing
594             # of ISBN 1-56592-224-7 CJKV Information Processing
595             # (and so on)
596              
597             # the //m modifier is assumed when you split on the pattern /^/
598             # (and so on)
599              
600             # V
601 0   0     0 while ((--$limit > 0) and ($string =~ s/\A((?:$q_char)+?)$pattern//m)) {
602              
603             # if the $pattern contains parentheses, then the substring matched by each pair of parentheses
604             # is included in the resulting list, interspersed with the fields that are ordinarily returned
605             # (and so on)
606              
607 0         0 local $@;
608 0         0 for (my $digit=1; $digit <= ($last_subexpression_offsets + 1); $digit++) {
609 0         0 push @split, CORE::eval('$' . $digit);
610             }
611             }
612             }
613              
614             else {
615 0         0 my $last_subexpression_offsets = _last_subexpression_offsets($pattern);
616              
617             # V
618 0         0 while ($string =~ s/\A((?:$q_char)*?)$pattern//m) {
619 0         0 local $@;
620 0         0 for (my $digit=1; $digit <= ($last_subexpression_offsets + 1); $digit++) {
621 0         0 push @split, CORE::eval('$' . $digit);
622             }
623             }
624             }
625             }
626              
627             elsif ($limit > 0) {
628 0 0       0 if ('' =~ / \A $pattern \z /xms) {
629 0         0 my $last_subexpression_offsets = _last_subexpression_offsets($pattern);
630 0   0     0 while ((--$limit > 0) and (CORE::length($string) > 0)) {
631              
632             # V
633 0 0       0 if ($string =~ s/\A((?:$q_char)+?)$pattern//m) {
634 0         0 local $@;
635 0         0 for (my $digit=1; $digit <= ($last_subexpression_offsets + 1); $digit++) {
636 0         0 push @split, CORE::eval('$' . $digit);
637             }
638             }
639             }
640             }
641             else {
642 0         0 my $last_subexpression_offsets = _last_subexpression_offsets($pattern);
643 0   0     0 while ((--$limit > 0) and (CORE::length($string) > 0)) {
644              
645             # V
646 0 0       0 if ($string =~ s/\A((?:$q_char)*?)$pattern//m) {
647 0         0 local $@;
648 0         0 for (my $digit=1; $digit <= ($last_subexpression_offsets + 1); $digit++) {
649 0         0 push @split, CORE::eval('$' . $digit);
650             }
651             }
652             }
653             }
654             }
655              
656 0 0       0 if (CORE::length($string) > 0) {
657 0         0 push @split, $string;
658             }
659              
660             # if $_[2] (NOT "$limit") is omitted or zero, trailing null fields are stripped from the result
661 0 0 0     0 if ((not defined $_[2]) or ($_[2] == 0)) {
662 0   0     0 while ((scalar(@split) >= 1) and ($split[-1] eq '')) {
663 0         0 pop @split;
664             }
665             }
666              
667             # resulting list value in list context
668 0 0       0 if (wantarray) {
669 0         0 return @split;
670             }
671              
672             # count of substrings in scalar context
673             else {
674 0 0       0 carp "Use of implicit split to \@_ is deprecated" if $^W;
675 0         0 @_ = @split;
676 0         0 return scalar @_;
677             }
678             }
679              
680             #
681             # get last subexpression offsets
682             #
683             sub _last_subexpression_offsets {
684 0     0   0 my $pattern = $_[0];
685              
686             # remove comment
687 0         0 $pattern =~ s/\(\?\# .*? \)//oxmsg;
688              
689 0         0 my $modifier = '';
690 0 0       0 if ($pattern =~ /\(\?\^? ([\-A-Za-z]+) :/oxms) {
691 0         0 $modifier = $1;
692 0         0 $modifier =~ s/-[A-Za-z]*//;
693             }
694              
695             # with /x modifier
696 0         0 my @char = ();
697 0 0       0 if ($modifier =~ /x/oxms) {
698 0         0 @char = $pattern =~ /\G(
699             \\ (?:$q_char) |
700             \# (?:$q_char)*? $ |
701             \[ (?: \\\] | (?:$q_char))+? \] |
702             \(\? |
703             (?:$q_char)
704             )/oxmsg;
705             }
706              
707             # without /x modifier
708             else {
709 0         0 @char = $pattern =~ /\G(
710             \\ (?:$q_char) |
711             \[ (?: \\\] | (?:$q_char))+? \] |
712             \(\? |
713             (?:$q_char)
714             )/oxmsg;
715             }
716              
717 0         0 return scalar grep { $_ eq '(' } @char;
  0         0  
718             }
719              
720             #
721             # Latin-4 transliteration (tr///)
722             #
723             sub Char::Elatin4::tr($$$$;$) {
724              
725 0     0 0 0 my $bind_operator = $_[1];
726 0         0 my $searchlist = $_[2];
727 0         0 my $replacementlist = $_[3];
728 0   0     0 my $modifier = $_[4] || '';
729              
730 0 0       0 if ($modifier =~ /r/oxms) {
731 0 0       0 if ($bind_operator =~ / !~ /oxms) {
732 0         0 croak "Using !~ with tr///r doesn't make sense";
733             }
734             }
735              
736 0         0 my @char = $_[0] =~ /\G ($q_char) /oxmsg;
737 0         0 my @searchlist = _charlist_tr($searchlist);
738 0         0 my @replacementlist = _charlist_tr($replacementlist);
739              
740 0         0 my %tr = ();
741 0         0 for (my $i=0; $i <= $#searchlist; $i++) {
742 0 0       0 if (not exists $tr{$searchlist[$i]}) {
743 0 0 0     0 if (defined $replacementlist[$i] and ($replacementlist[$i] ne '')) {
    0 0        
    0          
744 0         0 $tr{$searchlist[$i]} = $replacementlist[$i];
745             }
746             elsif ($modifier =~ /d/oxms) {
747 0         0 $tr{$searchlist[$i]} = '';
748             }
749             elsif (defined $replacementlist[-1] and ($replacementlist[-1] ne '')) {
750 0         0 $tr{$searchlist[$i]} = $replacementlist[-1];
751             }
752             else {
753 0         0 $tr{$searchlist[$i]} = $searchlist[$i];
754             }
755             }
756             }
757              
758 0         0 my $tr = 0;
759 0         0 my $replaced = '';
760 0 0       0 if ($modifier =~ /c/oxms) {
761 0         0 while (defined(my $char = shift @char)) {
762 0 0       0 if (not exists $tr{$char}) {
763 0 0       0 if (defined $replacementlist[0]) {
764 0         0 $replaced .= $replacementlist[0];
765             }
766 0         0 $tr++;
767 0 0       0 if ($modifier =~ /s/oxms) {
768 0   0     0 while (@char and (not exists $tr{$char[0]})) {
769 0         0 shift @char;
770 0         0 $tr++;
771             }
772             }
773             }
774             else {
775 0         0 $replaced .= $char;
776             }
777             }
778             }
779             else {
780 0         0 while (defined(my $char = shift @char)) {
781 0 0       0 if (exists $tr{$char}) {
782 0         0 $replaced .= $tr{$char};
783 0         0 $tr++;
784 0 0       0 if ($modifier =~ /s/oxms) {
785 0   0     0 while (@char and (exists $tr{$char[0]}) and ($tr{$char[0]} eq $tr{$char})) {
      0        
786 0         0 shift @char;
787 0         0 $tr++;
788             }
789             }
790             }
791             else {
792 0         0 $replaced .= $char;
793             }
794             }
795             }
796              
797 0 0       0 if ($modifier =~ /r/oxms) {
798 0         0 return $replaced;
799             }
800             else {
801 0         0 $_[0] = $replaced;
802 0 0       0 if ($bind_operator =~ / !~ /oxms) {
803 0         0 return not $tr;
804             }
805             else {
806 0         0 return $tr;
807             }
808             }
809             }
810              
811             #
812             # Latin-4 chop
813             #
814             sub Char::Elatin4::chop(@) {
815              
816 0     0 0 0 my $chop;
817 0 0       0 if (@_ == 0) {
818 0         0 my @char = /\G ($q_char) /oxmsg;
819 0         0 $chop = pop @char;
820 0         0 $_ = join '', @char;
821             }
822             else {
823 0         0 for (@_) {
824 0         0 my @char = /\G ($q_char) /oxmsg;
825 0         0 $chop = pop @char;
826 0         0 $_ = join '', @char;
827             }
828             }
829 0         0 return $chop;
830             }
831              
832             #
833             # Latin-4 index by octet
834             #
835             sub Char::Elatin4::index($$;$) {
836              
837 0     0 1 0 my($str,$substr,$position) = @_;
838 0   0     0 $position ||= 0;
839 0         0 my $pos = 0;
840              
841 0         0 while ($pos < CORE::length($str)) {
842 0 0       0 if (CORE::substr($str,$pos,CORE::length($substr)) eq $substr) {
843 0 0       0 if ($pos >= $position) {
844 0         0 return $pos;
845             }
846             }
847 0 0       0 if (CORE::substr($str,$pos) =~ /\A ($q_char) /oxms) {
848 0         0 $pos += CORE::length($1);
849             }
850             else {
851 0         0 $pos += 1;
852             }
853             }
854 0         0 return -1;
855             }
856              
857             #
858             # Latin-4 reverse index
859             #
860             sub Char::Elatin4::rindex($$;$) {
861              
862 0     0 0 0 my($str,$substr,$position) = @_;
863 0   0     0 $position ||= CORE::length($str) - 1;
864 0         0 my $pos = 0;
865 0         0 my $rindex = -1;
866              
867 0   0     0 while (($pos < CORE::length($str)) and ($pos <= $position)) {
868 0 0       0 if (CORE::substr($str,$pos,CORE::length($substr)) eq $substr) {
869 0         0 $rindex = $pos;
870             }
871 0 0       0 if (CORE::substr($str,$pos) =~ /\A ($q_char) /oxms) {
872 0         0 $pos += CORE::length($1);
873             }
874             else {
875 0         0 $pos += 1;
876             }
877             }
878 0         0 return $rindex;
879             }
880              
881             #
882             # Latin-4 lower case first with parameter
883             #
884             sub Char::Elatin4::lcfirst(@) {
885 0 0   0 0 0 if (@_) {
886 0         0 my $s = shift @_;
887 0 0 0     0 if (@_ and wantarray) {
888 0         0 return Char::Elatin4::lc(CORE::substr($s,0,1)) . CORE::substr($s,1), @_;
889             }
890             else {
891 0         0 return Char::Elatin4::lc(CORE::substr($s,0,1)) . CORE::substr($s,1);
892             }
893             }
894             else {
895 0         0 return Char::Elatin4::lc(CORE::substr($_,0,1)) . CORE::substr($_,1);
896             }
897             }
898              
899             #
900             # Latin-4 lower case first without parameter
901             #
902             sub Char::Elatin4::lcfirst_() {
903 0     0 0 0 return Char::Elatin4::lc(CORE::substr($_,0,1)) . CORE::substr($_,1);
904             }
905              
906             #
907             # Latin-4 lower case with parameter
908             #
909             sub Char::Elatin4::lc(@) {
910 0 0   0 0 0 if (@_) {
911 0         0 my $s = shift @_;
912 0 0 0     0 if (@_ and wantarray) {
913 0 0       0 return join('', map {defined($lc{$_}) ? $lc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg)), @_;
  0         0  
914             }
915             else {
916 0 0       0 return join('', map {defined($lc{$_}) ? $lc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg));
  0         0  
917             }
918             }
919             else {
920 0         0 return Char::Elatin4::lc_();
921             }
922             }
923              
924             #
925             # Latin-4 lower case without parameter
926             #
927             sub Char::Elatin4::lc_() {
928 0     0 0 0 my $s = $_;
929 0 0       0 return join '', map {defined($lc{$_}) ? $lc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg);
  0         0  
930             }
931              
932             #
933             # Latin-4 upper case first with parameter
934             #
935             sub Char::Elatin4::ucfirst(@) {
936 0 0   0 0 0 if (@_) {
937 0         0 my $s = shift @_;
938 0 0 0     0 if (@_ and wantarray) {
939 0         0 return Char::Elatin4::uc(CORE::substr($s,0,1)) . CORE::substr($s,1), @_;
940             }
941             else {
942 0         0 return Char::Elatin4::uc(CORE::substr($s,0,1)) . CORE::substr($s,1);
943             }
944             }
945             else {
946 0         0 return Char::Elatin4::uc(CORE::substr($_,0,1)) . CORE::substr($_,1);
947             }
948             }
949              
950             #
951             # Latin-4 upper case first without parameter
952             #
953             sub Char::Elatin4::ucfirst_() {
954 0     0 0 0 return Char::Elatin4::uc(CORE::substr($_,0,1)) . CORE::substr($_,1);
955             }
956              
957             #
958             # Latin-4 upper case with parameter
959             #
960             sub Char::Elatin4::uc(@) {
961 0 0   0 0 0 if (@_) {
962 0         0 my $s = shift @_;
963 0 0 0     0 if (@_ and wantarray) {
964 0 0       0 return join('', map {defined($uc{$_}) ? $uc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg)), @_;
  0         0  
965             }
966             else {
967 0 0       0 return join('', map {defined($uc{$_}) ? $uc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg));
  0         0  
968             }
969             }
970             else {
971 0         0 return Char::Elatin4::uc_();
972             }
973             }
974              
975             #
976             # Latin-4 upper case without parameter
977             #
978             sub Char::Elatin4::uc_() {
979 0     0 0 0 my $s = $_;
980 0 0       0 return join '', map {defined($uc{$_}) ? $uc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg);
  0         0  
981             }
982              
983             #
984             # Latin-4 fold case with parameter
985             #
986             sub Char::Elatin4::fc(@) {
987 0 0   0 0 0 if (@_) {
988 0         0 my $s = shift @_;
989 0 0 0     0 if (@_ and wantarray) {
990 0 0       0 return join('', map {defined($fc{$_}) ? $fc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg)), @_;
  0         0  
991             }
992             else {
993 0 0       0 return join('', map {defined($fc{$_}) ? $fc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg));
  0         0  
994             }
995             }
996             else {
997 0         0 return Char::Elatin4::fc_();
998             }
999             }
1000              
1001             #
1002             # Latin-4 fold case without parameter
1003             #
1004             sub Char::Elatin4::fc_() {
1005 0     0 0 0 my $s = $_;
1006 0 0       0 return join '', map {defined($fc{$_}) ? $fc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg);
  0         0  
1007             }
1008              
1009             #
1010             # Latin-4 regexp capture
1011             #
1012             {
1013             sub Char::Elatin4::capture {
1014 0     0 1 0 return $_[0];
1015             }
1016             }
1017              
1018             #
1019             # Latin-4 regexp ignore case modifier
1020             #
1021             sub Char::Elatin4::ignorecase {
1022              
1023 0     0 0 0 my @string = @_;
1024 0         0 my $metachar = qr/[\@\\|[\]{]/oxms;
1025              
1026             # ignore case of $scalar or @array
1027 0         0 for my $string (@string) {
1028              
1029             # split regexp
1030 0         0 my @char = $string =~ /\G(
1031             \[\^ |
1032             \\? (?:$q_char)
1033             )/oxmsg;
1034              
1035             # unescape character
1036 0         0 for (my $i=0; $i <= $#char; $i++) {
1037 0 0       0 next if not defined $char[$i];
1038              
1039             # open character class [...]
1040 0 0       0 if ($char[$i] eq '[') {
    0          
    0          
    0          
1041 0         0 my $left = $i;
1042              
1043             # [] make die "unmatched [] in regexp ..."
1044              
1045 0 0       0 if ($char[$i+1] eq ']') {
1046 0         0 $i++;
1047             }
1048              
1049 0         0 while (1) {
1050 0 0       0 if (++$i > $#char) {
1051 0         0 croak "Unmatched [] in regexp";
1052             }
1053 0 0       0 if ($char[$i] eq ']') {
1054 0         0 my $right = $i;
1055 0         0 my @charlist = charlist_qr(@char[$left+1..$right-1], 'i');
1056              
1057             # escape character
1058 0         0 for my $char (@charlist) {
1059 0 0       0 if (0) {
1060             }
1061              
1062 0         0 elsif ($char =~ /\A [.|)] \z/oxms) {
1063 0         0 $char = $1 . '\\' . $char;
1064             }
1065             }
1066              
1067             # [...]
1068 0         0 splice @char, $left, $right-$left+1, '(?:' . join('|', @charlist) . ')';
1069              
1070 0         0 $i = $left;
1071 0         0 last;
1072             }
1073             }
1074             }
1075              
1076             # open character class [^...]
1077             elsif ($char[$i] eq '[^') {
1078 0         0 my $left = $i;
1079              
1080             # [^] make die "unmatched [] in regexp ..."
1081              
1082 0 0       0 if ($char[$i+1] eq ']') {
1083 0         0 $i++;
1084             }
1085              
1086 0         0 while (1) {
1087 0 0       0 if (++$i > $#char) {
1088 0         0 croak "Unmatched [] in regexp";
1089             }
1090 0 0       0 if ($char[$i] eq ']') {
1091 0         0 my $right = $i;
1092 0         0 my @charlist = charlist_not_qr(@char[$left+1..$right-1], 'i');
1093              
1094             # escape character
1095 0         0 for my $char (@charlist) {
1096 0 0       0 if (0) {
1097             }
1098              
1099 0         0 elsif ($char =~ /\A [.|)] \z/oxms) {
1100 0         0 $char = '\\' . $char;
1101             }
1102             }
1103              
1104             # [^...]
1105 0         0 splice @char, $left, $right-$left+1, '(?!' . join('|', @charlist) . ")(?:$your_char)";
1106              
1107 0         0 $i = $left;
1108 0         0 last;
1109             }
1110             }
1111             }
1112              
1113             # rewrite classic character class or escape character
1114             elsif (my $char = classic_character_class($char[$i])) {
1115 0         0 $char[$i] = $char;
1116             }
1117              
1118             # with /i modifier
1119             elsif ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) {
1120 0         0 my $uc = Char::Elatin4::uc($char[$i]);
1121 0         0 my $fc = Char::Elatin4::fc($char[$i]);
1122 0 0       0 if ($uc ne $fc) {
1123 0 0       0 if (CORE::length($fc) == 1) {
1124 0         0 $char[$i] = '[' . $uc . $fc . ']';
1125             }
1126             else {
1127 0         0 $char[$i] = '(?:' . $uc . '|' . $fc . ')';
1128             }
1129             }
1130             }
1131             }
1132              
1133             # characterize
1134 0         0 for (my $i=0; $i <= $#char; $i++) {
1135 0 0       0 next if not defined $char[$i];
1136              
1137 0 0       0 if (0) {
1138             }
1139              
1140             # quote character before ? + * {
1141 0 0       0 elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
1142 0 0       0 if ($char[$i-1] !~ /\A [\x00-\xFF] \z/oxms) {
1143 0         0 $char[$i-1] = '(?:' . $char[$i-1] . ')';
1144             }
1145             }
1146             }
1147              
1148 0         0 $string = join '', @char;
1149             }
1150              
1151             # make regexp string
1152 0         0 return @string;
1153             }
1154              
1155             #
1156             # classic character class ( \D \S \W \d \s \w \C \X \H \V \h \v \R \N \b \B )
1157             #
1158             sub Char::Elatin4::classic_character_class {
1159 0     0 0 0 my($char) = @_;
1160              
1161             return {
1162 0   0     0 '\D' => '${Char::Elatin4::eD}',
1163             '\S' => '${Char::Elatin4::eS}',
1164             '\W' => '${Char::Elatin4::eW}',
1165             '\d' => '[0-9]',
1166              
1167             # Before Perl 5.6, \s only matched the five whitespace characters
1168             # tab, newline, form-feed, carriage return, and the space character
1169             # itself, which, taken together, is the character class [\t\n\f\r ].
1170              
1171             # Vertical tabs are now whitespace
1172             # \s in a regex now matches a vertical tab in all circumstances.
1173             # http://search.cpan.org/dist/perl-5.18.0/pod/perldelta.pod#Vertical_tabs_are_now_whitespace
1174             # \t \n \v \f \r space
1175             # '\s' => '[\x09\x0A \x0C\x0D\x20]',
1176             # '\s' => '[\x09\x0A\x0B\x0C\x0D\x20]',
1177             '\s' => '\s',
1178              
1179             '\w' => '[0-9A-Z_a-z]',
1180             '\C' => '[\x00-\xFF]',
1181             '\X' => 'X',
1182              
1183             # \h \v \H \V
1184              
1185             # P.114 Character Class Shortcuts
1186             # in Chapter 7: In the World of Regular Expressions
1187             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
1188              
1189             # P.357 13.2.3 Whitespace
1190             # in Chapter 13: perlrecharclass: Perl Regular Expression Character Classes
1191             # of ISBN-13: 978-1-906966-02-7 The Perl Language Reference Manual (for Perl version 5.12.1)
1192             #
1193             # 0x00009 CHARACTER TABULATION h s
1194             # 0x0000a LINE FEED (LF) vs
1195             # 0x0000b LINE TABULATION v
1196             # 0x0000c FORM FEED (FF) vs
1197             # 0x0000d CARRIAGE RETURN (CR) vs
1198             # 0x00020 SPACE h s
1199              
1200             # P.196 Table 5-9. Alphanumeric regex metasymbols
1201             # in Chapter 5. Pattern Matching
1202             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
1203              
1204             # (and so on)
1205              
1206             '\H' => '${Char::Elatin4::eH}',
1207             '\V' => '${Char::Elatin4::eV}',
1208             '\h' => '[\x09\x20]',
1209             '\v' => '[\x0A\x0B\x0C\x0D]',
1210             '\R' => '${Char::Elatin4::eR}',
1211              
1212             # \N
1213             #
1214             # http://perldoc.perl.org/perlre.html
1215             # Character Classes and other Special Escapes
1216             # Any character but \n (experimental). Not affected by /s modifier
1217              
1218             '\N' => '${Char::Elatin4::eN}',
1219              
1220             # \b \B
1221              
1222             # P.180 Boundaries: The \b and \B Assertions
1223             # in Chapter 5: Pattern Matching
1224             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
1225              
1226             # P.219 Boundaries: The \b and \B Assertions
1227             # in Chapter 5: Pattern Matching
1228             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
1229              
1230             # '\b' => '(?:(?<=\A|\W)(?=\w)|(?<=\w)(?=\W|\z))',
1231             '\b' => '${Char::Elatin4::eb}',
1232              
1233             # '\B' => '(?:(?<=\w)(?=\w)|(?<=\W)(?=\W))',
1234             '\B' => '${Char::Elatin4::eB}',
1235              
1236             }->{$char} || '';
1237             }
1238              
1239             #
1240             # prepare Latin-4 characters per length
1241             #
1242              
1243             # 1 octet characters
1244             my @chars1 = ();
1245             sub chars1 {
1246 0 0   0 0 0 if (@chars1) {
1247 0         0 return @chars1;
1248             }
1249 0 0       0 if (exists $range_tr{1}) {
1250 0         0 my @ranges = @{ $range_tr{1} };
  0         0  
1251 0         0 while (my @range = splice(@ranges,0,1)) {
1252 0         0 for my $oct0 (@{$range[0]}) {
  0         0  
1253 0         0 push @chars1, pack 'C', $oct0;
1254             }
1255             }
1256             }
1257 0         0 return @chars1;
1258             }
1259              
1260             # 2 octets characters
1261             my @chars2 = ();
1262             sub chars2 {
1263 0 0   0 0 0 if (@chars2) {
1264 0         0 return @chars2;
1265             }
1266 0 0       0 if (exists $range_tr{2}) {
1267 0         0 my @ranges = @{ $range_tr{2} };
  0         0  
1268 0         0 while (my @range = splice(@ranges,0,2)) {
1269 0         0 for my $oct0 (@{$range[0]}) {
  0         0  
1270 0         0 for my $oct1 (@{$range[1]}) {
  0         0  
1271 0         0 push @chars2, pack 'CC', $oct0,$oct1;
1272             }
1273             }
1274             }
1275             }
1276 0         0 return @chars2;
1277             }
1278              
1279             # 3 octets characters
1280             my @chars3 = ();
1281             sub chars3 {
1282 0 0   0 0 0 if (@chars3) {
1283 0         0 return @chars3;
1284             }
1285 0 0       0 if (exists $range_tr{3}) {
1286 0         0 my @ranges = @{ $range_tr{3} };
  0         0  
1287 0         0 while (my @range = splice(@ranges,0,3)) {
1288 0         0 for my $oct0 (@{$range[0]}) {
  0         0  
1289 0         0 for my $oct1 (@{$range[1]}) {
  0         0  
1290 0         0 for my $oct2 (@{$range[2]}) {
  0         0  
1291 0         0 push @chars3, pack 'CCC', $oct0,$oct1,$oct2;
1292             }
1293             }
1294             }
1295             }
1296             }
1297 0         0 return @chars3;
1298             }
1299              
1300             # 4 octets characters
1301             my @chars4 = ();
1302             sub chars4 {
1303 0 0   0 0 0 if (@chars4) {
1304 0         0 return @chars4;
1305             }
1306 0 0       0 if (exists $range_tr{4}) {
1307 0         0 my @ranges = @{ $range_tr{4} };
  0         0  
1308 0         0 while (my @range = splice(@ranges,0,4)) {
1309 0         0 for my $oct0 (@{$range[0]}) {
  0         0  
1310 0         0 for my $oct1 (@{$range[1]}) {
  0         0  
1311 0         0 for my $oct2 (@{$range[2]}) {
  0         0  
1312 0         0 for my $oct3 (@{$range[3]}) {
  0         0  
1313 0         0 push @chars4, pack 'CCCC', $oct0,$oct1,$oct2,$oct3;
1314             }
1315             }
1316             }
1317             }
1318             }
1319             }
1320 0         0 return @chars4;
1321             }
1322              
1323             #
1324             # Latin-4 open character list for tr
1325             #
1326             sub _charlist_tr {
1327              
1328 0     0   0 local $_ = shift @_;
1329              
1330             # unescape character
1331 0         0 my @char = ();
1332 0         0 while (not /\G \z/oxmsgc) {
1333 0 0       0 if (/\G (\\0?55|\\x2[Dd]|\\-) /oxmsgc) {
    0          
    0          
    0          
    0          
    0          
    0          
1334 0         0 push @char, '\-';
1335             }
1336             elsif (/\G \\ ([0-7]{2,3}) /oxmsgc) {
1337 0         0 push @char, CORE::chr(oct $1);
1338             }
1339             elsif (/\G \\x ([0-9A-Fa-f]{1,2}) /oxmsgc) {
1340 0         0 push @char, CORE::chr(hex $1);
1341             }
1342             elsif (/\G \\c ([\x40-\x5F]) /oxmsgc) {
1343 0         0 push @char, CORE::chr(CORE::ord($1) & 0x1F);
1344             }
1345             elsif (/\G (\\ [0nrtfbae]) /oxmsgc) {
1346 0         0 push @char, {
1347             '\0' => "\0",
1348             '\n' => "\n",
1349             '\r' => "\r",
1350             '\t' => "\t",
1351             '\f' => "\f",
1352             '\b' => "\x08", # \b means backspace in character class
1353             '\a' => "\a",
1354             '\e' => "\e",
1355             }->{$1};
1356             }
1357             elsif (/\G \\ ($q_char) /oxmsgc) {
1358 0         0 push @char, $1;
1359             }
1360             elsif (/\G ($q_char) /oxmsgc) {
1361 0         0 push @char, $1;
1362             }
1363             }
1364              
1365             # join separated multiple-octet
1366 0         0 @char = join('',@char) =~ /\G (\\-|$q_char) /oxmsg;
1367              
1368             # unescape '-'
1369 0         0 my @i = ();
1370 0         0 for my $i (0 .. $#char) {
1371 0 0       0 if ($char[$i] eq '\-') {
    0          
1372 0         0 $char[$i] = '-';
1373             }
1374             elsif ($char[$i] eq '-') {
1375 0 0 0     0 if ((0 < $i) and ($i < $#char)) {
1376 0         0 push @i, $i;
1377             }
1378             }
1379             }
1380              
1381             # open character list (reverse for splice)
1382 0         0 for my $i (CORE::reverse @i) {
1383 0         0 my @range = ();
1384              
1385             # range error
1386 0 0 0     0 if ((CORE::length($char[$i-1]) > CORE::length($char[$i+1])) or ($char[$i-1] gt $char[$i+1])) {
1387 0         0 croak "Invalid tr/// range \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1388             }
1389              
1390             # range of multiple-octet code
1391 0 0       0 if (CORE::length($char[$i-1]) == 1) {
    0          
    0          
    0          
1392 0 0       0 if (CORE::length($char[$i+1]) == 1) {
    0          
    0          
    0          
1393 0 0       0 push @range, grep {($char[$i-1] le $_) and ($_ le $char[$i+1])} chars1();
  0         0  
1394             }
1395             elsif (CORE::length($char[$i+1]) == 2) {
1396 0         0 push @range, grep {$char[$i-1] le $_} chars1();
  0         0  
1397 0         0 push @range, grep {$_ le $char[$i+1]} chars2();
  0         0  
1398             }
1399             elsif (CORE::length($char[$i+1]) == 3) {
1400 0         0 push @range, grep {$char[$i-1] le $_} chars1();
  0         0  
1401 0         0 push @range, chars2();
1402 0         0 push @range, grep {$_ le $char[$i+1]} chars3();
  0         0  
1403             }
1404             elsif (CORE::length($char[$i+1]) == 4) {
1405 0         0 push @range, grep {$char[$i-1] le $_} chars1();
  0         0  
1406 0         0 push @range, chars2();
1407 0         0 push @range, chars3();
1408 0         0 push @range, grep {$_ le $char[$i+1]} chars4();
  0         0  
1409             }
1410             else {
1411 0         0 croak "Invalid tr/// range (over 4octets) \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1412             }
1413             }
1414             elsif (CORE::length($char[$i-1]) == 2) {
1415 0 0       0 if (CORE::length($char[$i+1]) == 2) {
    0          
    0          
1416 0 0       0 push @range, grep {($char[$i-1] le $_) and ($_ le $char[$i+1])} chars2();
  0         0  
1417             }
1418             elsif (CORE::length($char[$i+1]) == 3) {
1419 0         0 push @range, grep {$char[$i-1] le $_} chars2();
  0         0  
1420 0         0 push @range, grep {$_ le $char[$i+1]} chars3();
  0         0  
1421             }
1422             elsif (CORE::length($char[$i+1]) == 4) {
1423 0         0 push @range, grep {$char[$i-1] le $_} chars2();
  0         0  
1424 0         0 push @range, chars3();
1425 0         0 push @range, grep {$_ le $char[$i+1]} chars4();
  0         0  
1426             }
1427             else {
1428 0         0 croak "Invalid tr/// range (over 4octets) \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1429             }
1430             }
1431             elsif (CORE::length($char[$i-1]) == 3) {
1432 0 0       0 if (CORE::length($char[$i+1]) == 3) {
    0          
1433 0 0       0 push @range, grep {($char[$i-1] le $_) and ($_ le $char[$i+1])} chars3();
  0         0  
1434             }
1435             elsif (CORE::length($char[$i+1]) == 4) {
1436 0         0 push @range, grep {$char[$i-1] le $_} chars3();
  0         0  
1437 0         0 push @range, grep {$_ le $char[$i+1]} chars4();
  0         0  
1438             }
1439             else {
1440 0         0 croak "Invalid tr/// range (over 4octets) \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1441             }
1442             }
1443             elsif (CORE::length($char[$i-1]) == 4) {
1444 0 0       0 if (CORE::length($char[$i+1]) == 4) {
1445 0 0       0 push @range, grep {($char[$i-1] le $_) and ($_ le $char[$i+1])} chars4();
  0         0  
1446             }
1447             else {
1448 0         0 croak "Invalid tr/// range (over 4octets) \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1449             }
1450             }
1451             else {
1452 0         0 croak "Invalid tr/// range (over 4octets) \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1453             }
1454              
1455 0         0 splice @char, $i-1, 3, @range;
1456             }
1457              
1458 0         0 return @char;
1459             }
1460              
1461             #
1462             # Latin-4 open character class
1463             #
1464             sub _cc {
1465 0 0   0   0 if (scalar(@_) == 0) {
    0          
    0          
1466 0         0 die __FILE__, ": subroutine cc got no parameter.";
1467             }
1468             elsif (scalar(@_) == 1) {
1469 0         0 return sprintf('\x%02X',$_[0]);
1470             }
1471             elsif (scalar(@_) == 2) {
1472 0 0       0 if ($_[0] > $_[1]) {
    0          
    0          
1473 0         0 die __FILE__, ": subroutine cc got \$_[0] > \$_[1] parameters).";
1474             }
1475             elsif ($_[0] == $_[1]) {
1476 0         0 return sprintf('\x%02X',$_[0]);
1477             }
1478             elsif (($_[0]+1) == $_[1]) {
1479 0         0 return sprintf('[\\x%02X\\x%02X]',$_[0],$_[1]);
1480             }
1481             else {
1482 0         0 return sprintf('[\\x%02X-\\x%02X]',$_[0],$_[1]);
1483             }
1484             }
1485             else {
1486 0         0 die __FILE__, ": subroutine cc got 3 or more parameters (@{[scalar(@_)]} parameters).";
  0         0  
1487             }
1488             }
1489              
1490             #
1491             # Latin-4 octet range
1492             #
1493             sub _octets {
1494 0     0   0 my $length = shift @_;
1495              
1496 0 0       0 if ($length == 1) {
1497 0         0 my($a1) = unpack 'C', $_[0];
1498 0         0 my($z1) = unpack 'C', $_[1];
1499              
1500 0 0       0 if ($a1 > $z1) {
1501 0         0 croak 'Invalid [] range in regexp (CORE::ord(A) > CORE::ord(B)) ' . '\x' . unpack('H*',$a1) . '-\x' . unpack('H*',$z1);
1502             }
1503              
1504 0 0       0 if ($a1 == $z1) {
    0          
1505 0         0 return sprintf('\x%02X',$a1);
1506             }
1507             elsif (($a1+1) == $z1) {
1508 0         0 return sprintf('\x%02X\x%02X',$a1,$z1);
1509             }
1510             else {
1511 0         0 return sprintf('\x%02X-\x%02X',$a1,$z1);
1512             }
1513             }
1514             else {
1515 0         0 die __FILE__, ": subroutine _octets got invalid length ($length).";
1516             }
1517             }
1518              
1519             #
1520             # Latin-4 range regexp
1521             #
1522             sub _range_regexp {
1523 0     0   0 my($length,$first,$last) = @_;
1524              
1525 0         0 my @range_regexp = ();
1526 0 0       0 if (not exists $range_tr{$length}) {
1527 0         0 return @range_regexp;
1528             }
1529              
1530 0         0 my @ranges = @{ $range_tr{$length} };
  0         0  
1531 0         0 while (my @range = splice(@ranges,0,$length)) {
1532 0         0 my $min = '';
1533 0         0 my $max = '';
1534 0         0 for (my $i=0; $i < $length; $i++) {
1535 0         0 $min .= pack 'C', $range[$i][0];
1536 0         0 $max .= pack 'C', $range[$i][-1];
1537             }
1538              
1539             # min___max
1540             # FIRST_____________LAST
1541             # (nothing)
1542              
1543 0 0 0     0 if ($max lt $first) {
    0 0        
    0 0        
    0 0        
    0 0        
    0 0        
    0 0        
1544             }
1545              
1546             # **********
1547             # min_________max
1548             # FIRST_____________LAST
1549             # **********
1550              
1551             elsif (($min le $first) and ($first le $max) and ($max le $last)) {
1552 0         0 push @range_regexp, _octets($length,$first,$max,$min,$max);
1553             }
1554              
1555             # **********************
1556             # min________________max
1557             # FIRST_____________LAST
1558             # **********************
1559              
1560             elsif (($min eq $first) and ($max eq $last)) {
1561 0         0 push @range_regexp, _octets($length,$first,$last,$min,$max);
1562             }
1563              
1564             # *********
1565             # min___max
1566             # FIRST_____________LAST
1567             # *********
1568              
1569             elsif (($first le $min) and ($max le $last)) {
1570 0         0 push @range_regexp, _octets($length,$min,$max,$min,$max);
1571             }
1572              
1573             # **********************
1574             # min__________________________max
1575             # FIRST_____________LAST
1576             # **********************
1577              
1578             elsif (($min le $first) and ($last le $max)) {
1579 0         0 push @range_regexp, _octets($length,$first,$last,$min,$max);
1580             }
1581              
1582             # *********
1583             # min________max
1584             # FIRST_____________LAST
1585             # *********
1586              
1587             elsif (($first le $min) and ($min le $last) and ($last le $max)) {
1588 0         0 push @range_regexp, _octets($length,$min,$last,$min,$max);
1589             }
1590              
1591             # min___max
1592             # FIRST_____________LAST
1593             # (nothing)
1594              
1595             elsif ($last lt $min) {
1596             }
1597              
1598             else {
1599 0         0 die __FILE__, ": subroutine _range_regexp panic.";
1600             }
1601             }
1602              
1603 0         0 return @range_regexp;
1604             }
1605              
1606             #
1607             # Latin-4 open character list for qr and not qr
1608             #
1609             sub _charlist {
1610              
1611 0     0   0 my $modifier = pop @_;
1612 0         0 my @char = @_;
1613              
1614 0 0       0 my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
1615              
1616             # unescape character
1617 0         0 for (my $i=0; $i <= $#char; $i++) {
1618              
1619             # escape - to ...
1620 0 0 0     0 if ($char[$i] eq '-') {
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
1621 0 0 0     0 if ((0 < $i) and ($i < $#char)) {
1622 0         0 $char[$i] = '...';
1623             }
1624             }
1625              
1626             # octal escape sequence
1627             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
1628 0         0 $char[$i] = octchr($1);
1629             }
1630              
1631             # hexadecimal escape sequence
1632             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
1633 0         0 $char[$i] = hexchr($1);
1634             }
1635              
1636             # \N{CHARNAME} --> N\{CHARNAME}
1637             elsif ($char[$i] =~ /\A \\ (N) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
1638 0         0 $char[$i] = $1 . '\\' . $2;
1639             }
1640              
1641             # \p{PROPERTY} --> p\{PROPERTY}
1642             elsif ($char[$i] =~ /\A \\ (p) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
1643 0         0 $char[$i] = $1 . '\\' . $2;
1644             }
1645              
1646             # \P{PROPERTY} --> P\{PROPERTY}
1647             elsif ($char[$i] =~ /\A \\ (P) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
1648 0         0 $char[$i] = $1 . '\\' . $2;
1649             }
1650              
1651             # \p, \P, \X --> p, P, X
1652             elsif ($char[$i] =~ /\A \\ ( [pPX] ) \z/oxms) {
1653 0         0 $char[$i] = $1;
1654             }
1655              
1656             elsif ($char[$i] =~ /\A \\ ([0-7]{2,3}) \z/oxms) {
1657 0         0 $char[$i] = CORE::chr oct $1;
1658             }
1659             elsif ($char[$i] =~ /\A \\x ([0-9A-Fa-f]{1,2}) \z/oxms) {
1660 0         0 $char[$i] = CORE::chr hex $1;
1661             }
1662             elsif ($char[$i] =~ /\A \\c ([\x40-\x5F]) \z/oxms) {
1663 0         0 $char[$i] = CORE::chr(CORE::ord($1) & 0x1F);
1664             }
1665             elsif ($char[$i] =~ /\A (\\ [0nrtfbaedswDSWHVhvR]) \z/oxms) {
1666 0         0 $char[$i] = {
1667             '\0' => "\0",
1668             '\n' => "\n",
1669             '\r' => "\r",
1670             '\t' => "\t",
1671             '\f' => "\f",
1672             '\b' => "\x08", # \b means backspace in character class
1673             '\a' => "\a",
1674             '\e' => "\e",
1675             '\d' => '[0-9]',
1676              
1677             # Vertical tabs are now whitespace
1678             # \s in a regex now matches a vertical tab in all circumstances.
1679             # http://search.cpan.org/dist/perl-5.18.0/pod/perldelta.pod#Vertical_tabs_are_now_whitespace
1680             # \t \n \v \f \r space
1681             # '\s' => '[\x09\x0A \x0C\x0D\x20]',
1682             # '\s' => '[\x09\x0A\x0B\x0C\x0D\x20]',
1683             '\s' => '\s',
1684              
1685             '\w' => '[0-9A-Z_a-z]',
1686             '\D' => '${Char::Elatin4::eD}',
1687             '\S' => '${Char::Elatin4::eS}',
1688             '\W' => '${Char::Elatin4::eW}',
1689              
1690             '\H' => '${Char::Elatin4::eH}',
1691             '\V' => '${Char::Elatin4::eV}',
1692             '\h' => '[\x09\x20]',
1693             '\v' => '[\x0A\x0B\x0C\x0D]',
1694             '\R' => '${Char::Elatin4::eR}',
1695              
1696             }->{$1};
1697             }
1698              
1699             # POSIX-style character classes
1700             elsif ($ignorecase and ($char[$i] =~ /\A ( \[\: \^? (?:lower|upper) :\] ) \z/oxms)) {
1701 0         0 $char[$i] = {
1702              
1703             '[:lower:]' => '[\x41-\x5A\x61-\x7A]',
1704             '[:upper:]' => '[\x41-\x5A\x61-\x7A]',
1705             '[:^lower:]' => '${Char::Elatin4::not_lower_i}',
1706             '[:^upper:]' => '${Char::Elatin4::not_upper_i}',
1707              
1708             }->{$1};
1709             }
1710             elsif ($char[$i] =~ /\A ( \[\: \^? (?:alnum|alpha|ascii|blank|cntrl|digit|graph|lower|print|punct|space|upper|word|xdigit) :\] ) \z/oxms) {
1711 0         0 $char[$i] = {
1712              
1713             '[:alnum:]' => '[\x30-\x39\x41-\x5A\x61-\x7A]',
1714             '[:alpha:]' => '[\x41-\x5A\x61-\x7A]',
1715             '[:ascii:]' => '[\x00-\x7F]',
1716             '[:blank:]' => '[\x09\x20]',
1717             '[:cntrl:]' => '[\x00-\x1F\x7F]',
1718             '[:digit:]' => '[\x30-\x39]',
1719             '[:graph:]' => '[\x21-\x7F]',
1720             '[:lower:]' => '[\x61-\x7A]',
1721             '[:print:]' => '[\x20-\x7F]',
1722             '[:punct:]' => '[\x21-\x2F\x3A-\x3F\x40\x5B-\x5F\x60\x7B-\x7E]',
1723              
1724             # P.174 POSIX-Style Character Classes
1725             # in Chapter 5: Pattern Matching
1726             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
1727              
1728             # P.311 11.2.4 Character Classes and other Special Escapes
1729             # in Chapter 11: perlre: Perl regular expressions
1730             # of ISBN-13: 978-1-906966-02-7 The Perl Language Reference Manual (for Perl version 5.12.1)
1731              
1732             # P.210 POSIX-Style Character Classes
1733             # in Chapter 5: Pattern Matching
1734             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
1735              
1736             '[:space:]' => '[\s\x0B]', # "\s" plus vertical tab ("\cK")
1737              
1738             '[:upper:]' => '[\x41-\x5A]',
1739             '[:word:]' => '[\x30-\x39\x41-\x5A\x5F\x61-\x7A]',
1740             '[:xdigit:]' => '[\x30-\x39\x41-\x46\x61-\x66]',
1741             '[:^alnum:]' => '${Char::Elatin4::not_alnum}',
1742             '[:^alpha:]' => '${Char::Elatin4::not_alpha}',
1743             '[:^ascii:]' => '${Char::Elatin4::not_ascii}',
1744             '[:^blank:]' => '${Char::Elatin4::not_blank}',
1745             '[:^cntrl:]' => '${Char::Elatin4::not_cntrl}',
1746             '[:^digit:]' => '${Char::Elatin4::not_digit}',
1747             '[:^graph:]' => '${Char::Elatin4::not_graph}',
1748             '[:^lower:]' => '${Char::Elatin4::not_lower}',
1749             '[:^print:]' => '${Char::Elatin4::not_print}',
1750             '[:^punct:]' => '${Char::Elatin4::not_punct}',
1751             '[:^space:]' => '${Char::Elatin4::not_space}',
1752             '[:^upper:]' => '${Char::Elatin4::not_upper}',
1753             '[:^word:]' => '${Char::Elatin4::not_word}',
1754             '[:^xdigit:]' => '${Char::Elatin4::not_xdigit}',
1755              
1756             }->{$1};
1757             }
1758             elsif ($char[$i] =~ /\A \\ ($q_char) \z/oxms) {
1759 0         0 $char[$i] = $1;
1760             }
1761             }
1762              
1763             # open character list
1764 0         0 my @singleoctet = ();
1765 0         0 my @multipleoctet = ();
1766 0         0 for (my $i=0; $i <= $#char; ) {
1767              
1768             # escaped -
1769 0 0 0     0 if (defined($char[$i+1]) and ($char[$i+1] eq '...')) {
    0          
    0          
    0          
    0          
    0          
1770 0         0 $i += 1;
1771 0         0 next;
1772             }
1773              
1774             # make range regexp
1775             elsif ($char[$i] eq '...') {
1776              
1777             # range error
1778 0 0       0 if (CORE::length($char[$i-1]) > CORE::length($char[$i+1])) {
    0          
1779 0         0 croak 'Invalid [] range in regexp (length(A) > length(B)) ' . '\x' . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]);
1780             }
1781             elsif (CORE::length($char[$i-1]) == CORE::length($char[$i+1])) {
1782 0 0       0 if ($char[$i-1] gt $char[$i+1]) {
1783 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]);
1784             }
1785             }
1786              
1787             # make range regexp per length
1788 0         0 for my $length (CORE::length($char[$i-1]) .. CORE::length($char[$i+1])) {
1789 0         0 my @regexp = ();
1790              
1791             # is first and last
1792 0 0 0     0 if (($length == CORE::length($char[$i-1])) and ($length == CORE::length($char[$i+1]))) {
    0 0        
    0          
    0          
1793 0         0 push @regexp, _range_regexp($length, $char[$i-1], $char[$i+1]);
1794             }
1795              
1796             # is first
1797             elsif ($length == CORE::length($char[$i-1])) {
1798 0         0 push @regexp, _range_regexp($length, $char[$i-1], "\xFF" x $length);
1799             }
1800              
1801             # is inside in first and last
1802             elsif ((CORE::length($char[$i-1]) < $length) and ($length < CORE::length($char[$i+1]))) {
1803 0         0 push @regexp, _range_regexp($length, "\x00" x $length, "\xFF" x $length);
1804             }
1805              
1806             # is last
1807             elsif ($length == CORE::length($char[$i+1])) {
1808 0         0 push @regexp, _range_regexp($length, "\x00" x $length, $char[$i+1]);
1809             }
1810              
1811             else {
1812 0         0 die __FILE__, ": subroutine make_regexp panic.";
1813             }
1814              
1815 0 0       0 if ($length == 1) {
1816 0         0 push @singleoctet, @regexp;
1817             }
1818             else {
1819 0         0 push @multipleoctet, @regexp;
1820             }
1821             }
1822              
1823 0         0 $i += 2;
1824             }
1825              
1826             # with /i modifier
1827             elsif ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) {
1828 0 0       0 if ($modifier =~ /i/oxms) {
1829 0         0 my $uc = Char::Elatin4::uc($char[$i]);
1830 0         0 my $fc = Char::Elatin4::fc($char[$i]);
1831 0 0       0 if ($uc ne $fc) {
1832 0 0       0 if (CORE::length($fc) == 1) {
1833 0         0 push @singleoctet, $uc, $fc;
1834             }
1835             else {
1836 0         0 push @singleoctet, $uc;
1837 0         0 push @multipleoctet, $fc;
1838             }
1839             }
1840             else {
1841 0         0 push @singleoctet, $char[$i];
1842             }
1843             }
1844             else {
1845 0         0 push @singleoctet, $char[$i];
1846             }
1847 0         0 $i += 1;
1848             }
1849              
1850             # single character of single octet code
1851             elsif ($char[$i] =~ /\A (?: \\h ) \z/oxms) {
1852 0         0 push @singleoctet, "\t", "\x20";
1853 0         0 $i += 1;
1854             }
1855             elsif ($char[$i] =~ /\A (?: \\v ) \z/oxms) {
1856 0         0 push @singleoctet, "\x0A", "\x0B", "\x0C", "\x0D";
1857 0         0 $i += 1;
1858             }
1859             elsif ($char[$i] =~ /\A (?: \\d | \\s | \\w ) \z/oxms) {
1860 0         0 push @singleoctet, $char[$i];
1861 0         0 $i += 1;
1862             }
1863              
1864             # single character of multiple-octet code
1865             else {
1866 0         0 push @multipleoctet, $char[$i];
1867 0         0 $i += 1;
1868             }
1869             }
1870              
1871             # quote metachar
1872 0         0 for (@singleoctet) {
1873 0 0       0 if ($_ eq '...') {
    0          
    0          
    0          
    0          
1874 0         0 $_ = '-';
1875             }
1876             elsif (/\A \n \z/oxms) {
1877 0         0 $_ = '\n';
1878             }
1879             elsif (/\A \r \z/oxms) {
1880 0         0 $_ = '\r';
1881             }
1882             elsif (/\A ([\x00-\x20\x7F-\xFF]) \z/oxms) {
1883 0         0 $_ = sprintf('\x%02X', CORE::ord $1);
1884             }
1885             elsif (/\A [\x00-\xFF] \z/oxms) {
1886 0         0 $_ = quotemeta $_;
1887             }
1888             }
1889              
1890             # return character list
1891 0         0 return \@singleoctet, \@multipleoctet;
1892             }
1893              
1894             #
1895             # Latin-4 octal escape sequence
1896             #
1897             sub octchr {
1898 0     0 0 0 my($octdigit) = @_;
1899              
1900 0         0 my @binary = ();
1901 0         0 for my $octal (split(//,$octdigit)) {
1902 0         0 push @binary, {
1903             '0' => '000',
1904             '1' => '001',
1905             '2' => '010',
1906             '3' => '011',
1907             '4' => '100',
1908             '5' => '101',
1909             '6' => '110',
1910             '7' => '111',
1911             }->{$octal};
1912             }
1913 0         0 my $binary = join '', @binary;
1914              
1915 0         0 my $octchr = {
1916             # 1234567
1917             1 => pack('B*', "0000000$binary"),
1918             2 => pack('B*', "000000$binary"),
1919             3 => pack('B*', "00000$binary"),
1920             4 => pack('B*', "0000$binary"),
1921             5 => pack('B*', "000$binary"),
1922             6 => pack('B*', "00$binary"),
1923             7 => pack('B*', "0$binary"),
1924             0 => pack('B*', "$binary"),
1925              
1926             }->{CORE::length($binary) % 8};
1927              
1928 0         0 return $octchr;
1929             }
1930              
1931             #
1932             # Latin-4 hexadecimal escape sequence
1933             #
1934             sub hexchr {
1935 0     0 0 0 my($hexdigit) = @_;
1936              
1937 0         0 my $hexchr = {
1938             1 => pack('H*', "0$hexdigit"),
1939             0 => pack('H*', "$hexdigit"),
1940              
1941             }->{CORE::length($_[0]) % 2};
1942              
1943 0         0 return $hexchr;
1944             }
1945              
1946             #
1947             # Latin-4 open character list for qr
1948             #
1949             sub charlist_qr {
1950              
1951 0     0 0 0 my $modifier = pop @_;
1952 0         0 my @char = @_;
1953              
1954 0         0 my($singleoctet, $multipleoctet) = _charlist(@char, $modifier);
1955 0         0 my @singleoctet = @$singleoctet;
1956 0         0 my @multipleoctet = @$multipleoctet;
1957              
1958             # return character list
1959 0 0       0 if (scalar(@singleoctet) >= 1) {
1960              
1961             # with /i modifier
1962 0 0       0 if ($modifier =~ m/i/oxms) {
1963 0         0 my %singleoctet_ignorecase = ();
1964 0         0 for (@singleoctet) {
1965 0   0     0 while (s/ \A \\x(..) - \\x(..) //oxms or s/ \A \\x((..)) //oxms) {
1966 0         0 for my $ord (hex($1) .. hex($2)) {
1967 0         0 my $char = CORE::chr($ord);
1968 0         0 my $uc = Char::Elatin4::uc($char);
1969 0         0 my $fc = Char::Elatin4::fc($char);
1970 0 0       0 if ($uc eq $fc) {
1971 0         0 $singleoctet_ignorecase{unpack 'C*', $char} = 1;
1972             }
1973             else {
1974 0 0       0 if (CORE::length($fc) == 1) {
1975 0         0 $singleoctet_ignorecase{unpack 'C*', $uc} = 1;
1976 0         0 $singleoctet_ignorecase{unpack 'C*', $fc} = 1;
1977             }
1978             else {
1979 0         0 $singleoctet_ignorecase{unpack 'C*', $uc} = 1;
1980 0         0 push @multipleoctet, join '', map {sprintf('\x%02X',$_)} unpack 'C*', $fc;
  0         0  
1981             }
1982             }
1983             }
1984             }
1985 0 0       0 if ($_ ne '') {
1986 0         0 $singleoctet_ignorecase{unpack 'C*', $_} = 1;
1987             }
1988             }
1989 0         0 my $i = 0;
1990 0         0 my @singleoctet_ignorecase = ();
1991 0         0 for my $ord (0 .. 255) {
1992 0 0       0 if (exists $singleoctet_ignorecase{$ord}) {
1993 0         0 push @{$singleoctet_ignorecase[$i]}, $ord;
  0         0  
1994             }
1995             else {
1996 0         0 $i++;
1997             }
1998             }
1999 0         0 @singleoctet = ();
2000 0         0 for my $range (@singleoctet_ignorecase) {
2001 0 0       0 if (ref $range) {
2002 0 0       0 if (scalar(@{$range}) == 1) {
  0 0       0  
  0         0  
2003 0         0 push @singleoctet, sprintf('\x%02X', @{$range}[0]);
  0         0  
2004             }
2005             elsif (scalar(@{$range}) == 2) {
2006 0         0 push @singleoctet, sprintf('\x%02X\x%02X', @{$range}[0], @{$range}[-1]);
  0         0  
  0         0  
2007             }
2008             else {
2009 0         0 push @singleoctet, sprintf('\x%02X-\x%02X', @{$range}[0], @{$range}[-1]);
  0         0  
  0         0  
2010             }
2011             }
2012             }
2013             }
2014              
2015 0         0 my $not_anchor = '';
2016              
2017 0         0 push @multipleoctet, join('', $not_anchor, '[', @singleoctet, ']' );
2018             }
2019 0 0       0 if (scalar(@multipleoctet) >= 2) {
2020 0         0 return '(?:' . join('|', @multipleoctet) . ')';
2021             }
2022             else {
2023 0         0 return $multipleoctet[0];
2024             }
2025             }
2026              
2027             #
2028             # Latin-4 open character list for not qr
2029             #
2030             sub charlist_not_qr {
2031              
2032 0     0 0 0 my $modifier = pop @_;
2033 0         0 my @char = @_;
2034              
2035 0         0 my($singleoctet, $multipleoctet) = _charlist(@char, $modifier);
2036 0         0 my @singleoctet = @$singleoctet;
2037 0         0 my @multipleoctet = @$multipleoctet;
2038              
2039             # with /i modifier
2040 0 0       0 if ($modifier =~ m/i/oxms) {
2041 0         0 my %singleoctet_ignorecase = ();
2042 0         0 for (@singleoctet) {
2043 0   0     0 while (s/ \A \\x(..) - \\x(..) //oxms or s/ \A \\x((..)) //oxms) {
2044 0         0 for my $ord (hex($1) .. hex($2)) {
2045 0         0 my $char = CORE::chr($ord);
2046 0         0 my $uc = Char::Elatin4::uc($char);
2047 0         0 my $fc = Char::Elatin4::fc($char);
2048 0 0       0 if ($uc eq $fc) {
2049 0         0 $singleoctet_ignorecase{unpack 'C*', $char} = 1;
2050             }
2051             else {
2052 0 0       0 if (CORE::length($fc) == 1) {
2053 0         0 $singleoctet_ignorecase{unpack 'C*', $uc} = 1;
2054 0         0 $singleoctet_ignorecase{unpack 'C*', $fc} = 1;
2055             }
2056             else {
2057 0         0 $singleoctet_ignorecase{unpack 'C*', $uc} = 1;
2058 0         0 push @multipleoctet, join '', map {sprintf('\x%02X',$_)} unpack 'C*', $fc;
  0         0  
2059             }
2060             }
2061             }
2062             }
2063 0 0       0 if ($_ ne '') {
2064 0         0 $singleoctet_ignorecase{unpack 'C*', $_} = 1;
2065             }
2066             }
2067 0         0 my $i = 0;
2068 0         0 my @singleoctet_ignorecase = ();
2069 0         0 for my $ord (0 .. 255) {
2070 0 0       0 if (exists $singleoctet_ignorecase{$ord}) {
2071 0         0 push @{$singleoctet_ignorecase[$i]}, $ord;
  0         0  
2072             }
2073             else {
2074 0         0 $i++;
2075             }
2076             }
2077 0         0 @singleoctet = ();
2078 0         0 for my $range (@singleoctet_ignorecase) {
2079 0 0       0 if (ref $range) {
2080 0 0       0 if (scalar(@{$range}) == 1) {
  0 0       0  
  0         0  
2081 0         0 push @singleoctet, sprintf('\x%02X', @{$range}[0]);
  0         0  
2082             }
2083             elsif (scalar(@{$range}) == 2) {
2084 0         0 push @singleoctet, sprintf('\x%02X\x%02X', @{$range}[0], @{$range}[-1]);
  0         0  
  0         0  
2085             }
2086             else {
2087 0         0 push @singleoctet, sprintf('\x%02X-\x%02X', @{$range}[0], @{$range}[-1]);
  0         0  
  0         0  
2088             }
2089             }
2090             }
2091             }
2092              
2093             # return character list
2094 0 0       0 if (scalar(@multipleoctet) >= 1) {
2095 0 0       0 if (scalar(@singleoctet) >= 1) {
2096              
2097             # any character other than multiple-octet and single octet character class
2098 0         0 return '(?!' . join('|', @multipleoctet) . ')(?:[^' . join('', @singleoctet) . '])';
2099             }
2100             else {
2101              
2102             # any character other than multiple-octet character class
2103 0         0 return '(?!' . join('|', @multipleoctet) . ")(?:$your_char)";
2104             }
2105             }
2106             else {
2107 0 0       0 if (scalar(@singleoctet) >= 1) {
2108              
2109             # any character other than single octet character class
2110 0         0 return '(?:[^' . join('', @singleoctet) . '])';
2111             }
2112             else {
2113              
2114             # any character
2115 0         0 return "(?:$your_char)";
2116             }
2117             }
2118             }
2119              
2120             #
2121             # open file in read mode
2122             #
2123             sub _open_r {
2124 197     197   668 my(undef,$file) = @_;
2125 197         789 $file =~ s#\A (\s) #./$1#oxms;
2126 197   33     23655 return CORE::eval(q{open($_[0],'<',$_[1])}) ||
2127             open($_[0],"< $file\0");
2128             }
2129              
2130             #
2131             # open file in write mode
2132             #
2133             sub _open_w {
2134 0     0   0 my(undef,$file) = @_;
2135 0         0 $file =~ s#\A (\s) #./$1#oxms;
2136 0   0     0 return CORE::eval(q{open($_[0],'>',$_[1])}) ||
2137             open($_[0],"> $file\0");
2138             }
2139              
2140             #
2141             # open file in append mode
2142             #
2143             sub _open_a {
2144 0     0   0 my(undef,$file) = @_;
2145 0         0 $file =~ s#\A (\s) #./$1#oxms;
2146 0   0     0 return CORE::eval(q{open($_[0],'>>',$_[1])}) ||
2147             open($_[0],">> $file\0");
2148             }
2149              
2150             #
2151             # safe system
2152             #
2153             sub _systemx {
2154              
2155             # P.707 29.2.33. exec
2156             # in Chapter 29: Functions
2157             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
2158             #
2159             # Be aware that in older releases of Perl, exec (and system) did not flush
2160             # your output buffer, so you needed to enable command buffering by setting $|
2161             # on one or more filehandles to avoid lost output in the case of exec, or
2162             # misordererd output in the case of system. This situation was largely remedied
2163             # in the 5.6 release of Perl. (So, 5.005 release not yet.)
2164              
2165             # P.855 exec
2166             # in Chapter 27: Functions
2167             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
2168             #
2169             # In very old release of Perl (before v5.6), exec (and system) did not flush
2170             # your output buffer, so you needed to enable command buffering by setting $|
2171             # on one or more filehandles to avoid lost output with exec or misordered
2172             # output with system.
2173              
2174 197     197   726 $| = 1;
2175              
2176             # P.565 23.1.2. Cleaning Up Your Environment
2177             # in Chapter 23: Security
2178             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
2179              
2180             # P.656 Cleaning Up Your Environment
2181             # in Chapter 20: Security
2182             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
2183              
2184             # local $ENV{'PATH'} = '.';
2185 197         2130 local @ENV{qw(IFS CDPATH ENV BASH_ENV)}; # Make %ENV safer
2186              
2187             # P.707 29.2.33. exec
2188             # in Chapter 29: Functions
2189             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
2190             #
2191             # As we mentioned earlier, exec treats a discrete list of arguments as an
2192             # indication that it should bypass shell processing. However, there is one
2193             # place where you might still get tripped up. The exec call (and system, too)
2194             # will not distinguish between a single scalar argument and an array containing
2195             # only one element.
2196             #
2197             # @args = ("echo surprise"); # just one element in list
2198             # exec @args # still subject to shell escapes
2199             # or die "exec: $!"; # because @args == 1
2200             #
2201             # To avoid this, you can use the PATHNAME syntax, explicitly duplicating the
2202             # first argument as the pathname, which forces the rest of the arguments to be
2203             # interpreted as a list, even if there is only one of them:
2204             #
2205             # exec { $args[0] } @args # safe even with one-argument list
2206             # or die "can't exec @args: $!";
2207              
2208             # P.855 exec
2209             # in Chapter 27: Functions
2210             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
2211             #
2212             # As we mentioned earlier, exec treats a discrete list of arguments as a
2213             # directive to bypass shell processing. However, there is one place where
2214             # you might still get tripped up. The exec call (and system, too) cannot
2215             # distinguish between a single scalar argument and an array containing
2216             # only one element.
2217             #
2218             # @args = ("echo surprise"); # just one element in list
2219             # exec @args # still subject to shell escapes
2220             # || die "exec: $!"; # because @args == 1
2221             #
2222             # To avoid this, use the PATHNAME syntax, explicitly duplicating the first
2223             # argument as the pathname, which forces the rest of the arguments to be
2224             # interpreted as a list, even if there is only one of them:
2225             #
2226             # exec { $args[0] } @args # safe even with one-argument list
2227             # || die "can't exec @args: $!";
2228              
2229 197         392 return CORE::system { $_[0] } @_; # safe even with one-argument list
  197         23272745  
2230             }
2231              
2232             #
2233             # Latin-4 order to character (with parameter)
2234             #
2235             sub Char::Elatin4::chr(;$) {
2236              
2237 0 0   0 0   my $c = @_ ? $_[0] : $_;
2238              
2239 0 0         if ($c == 0x00) {
2240 0           return "\x00";
2241             }
2242             else {
2243 0           my @chr = ();
2244 0           while ($c > 0) {
2245 0           unshift @chr, ($c % 0x100);
2246 0           $c = int($c / 0x100);
2247             }
2248 0           return pack 'C*', @chr;
2249             }
2250             }
2251              
2252             #
2253             # Latin-4 order to character (without parameter)
2254             #
2255             sub Char::Elatin4::chr_() {
2256              
2257 0     0 0   my $c = $_;
2258              
2259 0 0         if ($c == 0x00) {
2260 0           return "\x00";
2261             }
2262             else {
2263 0           my @chr = ();
2264 0           while ($c > 0) {
2265 0           unshift @chr, ($c % 0x100);
2266 0           $c = int($c / 0x100);
2267             }
2268 0           return pack 'C*', @chr;
2269             }
2270             }
2271              
2272             #
2273             # Latin-4 path globbing (with parameter)
2274             #
2275             sub Char::Elatin4::glob($) {
2276              
2277 0 0   0 0   if (wantarray) {
2278 0           my @glob = _DOS_like_glob(@_);
2279 0           for my $glob (@glob) {
2280 0           $glob =~ s{ \A (?:\./)+ }{}oxms;
2281             }
2282 0           return @glob;
2283             }
2284             else {
2285 0           my $glob = _DOS_like_glob(@_);
2286 0           $glob =~ s{ \A (?:\./)+ }{}oxms;
2287 0           return $glob;
2288             }
2289             }
2290              
2291             #
2292             # Latin-4 path globbing (without parameter)
2293             #
2294             sub Char::Elatin4::glob_() {
2295              
2296 0 0   0 0   if (wantarray) {
2297 0           my @glob = _DOS_like_glob();
2298 0           for my $glob (@glob) {
2299 0           $glob =~ s{ \A (?:\./)+ }{}oxms;
2300             }
2301 0           return @glob;
2302             }
2303             else {
2304 0           my $glob = _DOS_like_glob();
2305 0           $glob =~ s{ \A (?:\./)+ }{}oxms;
2306 0           return $glob;
2307             }
2308             }
2309              
2310             #
2311             # Latin-4 path globbing via File::DosGlob 1.10
2312             #
2313             # Often I confuse "_dosglob" and "_doglob".
2314             # So, I renamed "_dosglob" to "_DOS_like_glob".
2315             #
2316             my %iter;
2317             my %entries;
2318             sub _DOS_like_glob {
2319              
2320             # context (keyed by second cxix argument provided by core)
2321 0     0     my($expr,$cxix) = @_;
2322              
2323             # glob without args defaults to $_
2324 0 0         $expr = $_ if not defined $expr;
2325              
2326             # represents the current user's home directory
2327             #
2328             # 7.3. Expanding Tildes in Filenames
2329             # in Chapter 7. File Access
2330             # of ISBN 0-596-00313-7 Perl Cookbook, 2nd Edition.
2331             #
2332             # and File::HomeDir, File::HomeDir::Windows module
2333              
2334             # DOS-like system
2335 0 0         if ($^O =~ /\A (?: MSWin32 | NetWare | symbian | dos ) \z/oxms) {
2336 0           $expr =~ s{ \A ~ (?= [^/\\] ) }
2337 0           { my_home_MSWin32() }oxmse;
2338             }
2339              
2340             # UNIX-like system
2341             else {
2342 0           $expr =~ s{ \A ~ ( (?:[^/])* ) }
2343 0 0 0       { $1 ? (CORE::eval(q{(getpwnam($1))[7]})||my_home()) : my_home() }oxmse;
2344             }
2345              
2346             # assume global context if not provided one
2347 0 0         $cxix = '_G_' if not defined $cxix;
2348 0 0         $iter{$cxix} = 0 if not exists $iter{$cxix};
2349              
2350             # if we're just beginning, do it all first
2351 0 0         if ($iter{$cxix} == 0) {
2352 0           $entries{$cxix} = [ _do_glob(1, _parse_line($expr)) ];
2353             }
2354              
2355             # chuck it all out, quick or slow
2356 0 0         if (wantarray) {
2357 0           delete $iter{$cxix};
2358 0           return @{delete $entries{$cxix}};
  0            
2359             }
2360             else {
2361 0 0         if ($iter{$cxix} = scalar @{$entries{$cxix}}) {
  0            
2362 0           return shift @{$entries{$cxix}};
  0            
2363             }
2364             else {
2365             # return undef for EOL
2366 0           delete $iter{$cxix};
2367 0           delete $entries{$cxix};
2368 0           return undef;
2369             }
2370             }
2371             }
2372              
2373             #
2374             # Latin-4 path globbing subroutine
2375             #
2376             sub _do_glob {
2377              
2378 0     0     my($cond,@expr) = @_;
2379 0           my @glob = ();
2380 0           my $fix_drive_relative_paths = 0;
2381              
2382             OUTER:
2383 0           for my $expr (@expr) {
2384 0 0         next OUTER if not defined $expr;
2385 0 0         next OUTER if $expr eq '';
2386              
2387 0           my @matched = ();
2388 0           my @globdir = ();
2389 0           my $head = '.';
2390 0           my $pathsep = '/';
2391 0           my $tail;
2392              
2393             # if argument is within quotes strip em and do no globbing
2394 0 0         if ($expr =~ /\A " ((?:$q_char)*) " \z/oxms) {
2395 0           $expr = $1;
2396 0 0         if ($cond eq 'd') {
2397 0 0         if (-d $expr) {
2398 0           push @glob, $expr;
2399             }
2400             }
2401             else {
2402 0 0         if (-e $expr) {
2403 0           push @glob, $expr;
2404             }
2405             }
2406 0           next OUTER;
2407             }
2408              
2409             # wildcards with a drive prefix such as h:*.pm must be changed
2410             # to h:./*.pm to expand correctly
2411 0 0         if ($^O =~ /\A (?: MSWin32 | NetWare | symbian | dos ) \z/oxms) {
2412 0 0         if ($expr =~ s# \A ((?:[A-Za-z]:)?) ([^/\\]) #$1./$2#oxms) {
2413 0           $fix_drive_relative_paths = 1;
2414             }
2415             }
2416              
2417 0 0         if (($head, $tail) = _parse_path($expr,$pathsep)) {
2418 0 0         if ($tail eq '') {
2419 0           push @glob, $expr;
2420 0           next OUTER;
2421             }
2422 0 0         if ($head =~ / \A (?:$q_char)*? [*?] /oxms) {
2423 0 0         if (@globdir = _do_glob('d', $head)) {
2424 0           push @glob, _do_glob($cond, map {"$_$pathsep$tail"} @globdir);
  0            
2425 0           next OUTER;
2426             }
2427             }
2428 0 0 0       if ($head eq '' or $head =~ /\A [A-Za-z]: \z/oxms) {
2429 0           $head .= $pathsep;
2430             }
2431 0           $expr = $tail;
2432             }
2433              
2434             # If file component has no wildcards, we can avoid opendir
2435 0 0         if ($expr !~ / \A (?:$q_char)*? [*?] /oxms) {
2436 0 0         if ($head eq '.') {
2437 0           $head = '';
2438             }
2439 0 0 0       if ($head ne '' and ($head =~ / \G ($q_char) /oxmsg)[-1] ne $pathsep) {
2440 0           $head .= $pathsep;
2441             }
2442 0           $head .= $expr;
2443 0 0         if ($cond eq 'd') {
2444 0 0         if (-d $head) {
2445 0           push @glob, $head;
2446             }
2447             }
2448             else {
2449 0 0         if (-e $head) {
2450 0           push @glob, $head;
2451             }
2452             }
2453 0           next OUTER;
2454             }
2455 0 0         opendir(*DIR, $head) or next OUTER;
2456 0           my @leaf = readdir DIR;
2457 0           closedir DIR;
2458              
2459 0 0         if ($head eq '.') {
2460 0           $head = '';
2461             }
2462 0 0 0       if ($head ne '' and ($head =~ / \G ($q_char) /oxmsg)[-1] ne $pathsep) {
2463 0           $head .= $pathsep;
2464             }
2465              
2466 0           my $pattern = '';
2467 0           while ($expr =~ / \G ($q_char) /oxgc) {
2468 0           my $char = $1;
2469              
2470             # 6.9. Matching Shell Globs as Regular Expressions
2471             # in Chapter 6. Pattern Matching
2472             # of ISBN 0-596-00313-7 Perl Cookbook, 2nd Edition.
2473             # (and so on)
2474              
2475 0 0         if ($char eq '*') {
    0          
    0          
2476 0           $pattern .= "(?:$your_char)*",
2477             }
2478             elsif ($char eq '?') {
2479 0           $pattern .= "(?:$your_char)?", # DOS style
2480             # $pattern .= "(?:$your_char)", # UNIX style
2481             }
2482             elsif ((my $fc = Char::Elatin4::fc($char)) ne $char) {
2483 0           $pattern .= $fc;
2484             }
2485             else {
2486 0           $pattern .= quotemeta $char;
2487             }
2488             }
2489 0     0     my $matchsub = sub { Char::Elatin4::fc($_[0]) =~ /\A $pattern \z/xms };
  0            
2490              
2491             # if ($@) {
2492             # print STDERR "$0: $@\n";
2493             # next OUTER;
2494             # }
2495              
2496             INNER:
2497 0           for my $leaf (@leaf) {
2498 0 0 0       if ($leaf eq '.' or $leaf eq '..') {
2499 0           next INNER;
2500             }
2501 0 0 0       if ($cond eq 'd' and not -d "$head$leaf") {
2502 0           next INNER;
2503             }
2504              
2505 0 0         if (&$matchsub($leaf)) {
2506 0           push @matched, "$head$leaf";
2507 0           next INNER;
2508             }
2509              
2510             # [DOS compatibility special case]
2511             # Failed, add a trailing dot and try again, but only...
2512              
2513 0 0 0       if (Char::Elatin4::index($leaf,'.') == -1 and # if name does not have a dot in it *and*
      0        
2514             CORE::length($leaf) <= 8 and # name is shorter than or equal to 8 chars *and*
2515             Char::Elatin4::index($pattern,'\\.') != -1 # pattern has a dot.
2516             ) {
2517 0 0         if (&$matchsub("$leaf.")) {
2518 0           push @matched, "$head$leaf";
2519 0           next INNER;
2520             }
2521             }
2522             }
2523 0 0         if (@matched) {
2524 0           push @glob, @matched;
2525             }
2526             }
2527 0 0         if ($fix_drive_relative_paths) {
2528 0           for my $glob (@glob) {
2529 0           $glob =~ s# \A ([A-Za-z]:) \./ #$1#oxms;
2530             }
2531             }
2532 0           return @glob;
2533             }
2534              
2535             #
2536             # Latin-4 parse line
2537             #
2538             sub _parse_line {
2539              
2540 0     0     my($line) = @_;
2541              
2542 0           $line .= ' ';
2543 0           my @piece = ();
2544 0           while ($line =~ /
2545             " ( (?: [^"] )* ) " \s+ |
2546             ( (?: [^"\s] )* ) \s+
2547             /oxmsg
2548             ) {
2549 0 0         push @piece, defined($1) ? $1 : $2;
2550             }
2551 0           return @piece;
2552             }
2553              
2554             #
2555             # Latin-4 parse path
2556             #
2557             sub _parse_path {
2558              
2559 0     0     my($path,$pathsep) = @_;
2560              
2561 0           $path .= '/';
2562 0           my @subpath = ();
2563 0           while ($path =~ /
2564             ((?: [^\/\\] )+?) [\/\\]
2565             /oxmsg
2566             ) {
2567 0           push @subpath, $1;
2568             }
2569              
2570 0           my $tail = pop @subpath;
2571 0           my $head = join $pathsep, @subpath;
2572 0           return $head, $tail;
2573             }
2574              
2575             #
2576             # via File::HomeDir::Windows 1.00
2577             #
2578             sub my_home_MSWin32 {
2579              
2580             # A lot of unix people and unix-derived tools rely on
2581             # the ability to overload HOME. We will support it too
2582             # so that they can replace raw HOME calls with File::HomeDir.
2583 0 0 0 0 0   if (exists $ENV{'HOME'} and $ENV{'HOME'}) {
    0 0        
    0 0        
      0        
      0        
2584 0           return $ENV{'HOME'};
2585             }
2586              
2587             # Do we have a user profile?
2588             elsif (exists $ENV{'USERPROFILE'} and $ENV{'USERPROFILE'}) {
2589 0           return $ENV{'USERPROFILE'};
2590             }
2591              
2592             # Some Windows use something like $ENV{'HOME'}
2593             elsif (exists $ENV{'HOMEDRIVE'} and exists $ENV{'HOMEPATH'} and $ENV{'HOMEDRIVE'} and $ENV{'HOMEPATH'}) {
2594 0           return join '', $ENV{'HOMEDRIVE'}, $ENV{'HOMEPATH'};
2595             }
2596              
2597 0           return undef;
2598             }
2599              
2600             #
2601             # via File::HomeDir::Unix 1.00
2602             #
2603             sub my_home {
2604 0     0 0   my $home;
2605              
2606 0 0 0       if (exists $ENV{'HOME'} and defined $ENV{'HOME'}) {
    0 0        
2607 0           $home = $ENV{'HOME'};
2608             }
2609              
2610             # This is from the original code, but I'm guessing
2611             # it means "login directory" and exists on some Unixes.
2612             elsif (exists $ENV{'LOGDIR'} and $ENV{'LOGDIR'}) {
2613 0           $home = $ENV{'LOGDIR'};
2614             }
2615              
2616             ### More-desperate methods
2617              
2618             # Light desperation on any (Unixish) platform
2619             else {
2620 0           $home = CORE::eval q{ (getpwuid($<))[7] };
2621             }
2622              
2623             # On Unix in general, a non-existant home means "no home"
2624             # For example, "nobody"-like users might use /nonexistant
2625 0 0 0       if (defined $home and ! -d($home)) {
2626 0           $home = undef;
2627             }
2628 0           return $home;
2629             }
2630              
2631             #
2632             # ${^PREMATCH}, $PREMATCH, $` the string preceding what was matched
2633             #
2634             sub Char::Elatin4::PREMATCH {
2635 0     0 0   return $`;
2636             }
2637              
2638             #
2639             # ${^MATCH}, $MATCH, $& the string that matched
2640             #
2641             sub Char::Elatin4::MATCH {
2642 0     0 0   return $&;
2643             }
2644              
2645             #
2646             # ${^POSTMATCH}, $POSTMATCH, $' the string following what was matched
2647             #
2648             sub Char::Elatin4::POSTMATCH {
2649 0     0 0   return $';
2650             }
2651              
2652             #
2653             # Latin-4 character to order (with parameter)
2654             #
2655             sub Char::Latin4::ord(;$) {
2656              
2657 0 0   0 1   local $_ = shift if @_;
2658              
2659 0 0         if (/\A ($q_char) /oxms) {
2660 0           my @ord = unpack 'C*', $1;
2661 0           my $ord = 0;
2662 0           while (my $o = shift @ord) {
2663 0           $ord = $ord * 0x100 + $o;
2664             }
2665 0           return $ord;
2666             }
2667             else {
2668 0           return CORE::ord $_;
2669             }
2670             }
2671              
2672             #
2673             # Latin-4 character to order (without parameter)
2674             #
2675             sub Char::Latin4::ord_() {
2676              
2677 0 0   0 0   if (/\A ($q_char) /oxms) {
2678 0           my @ord = unpack 'C*', $1;
2679 0           my $ord = 0;
2680 0           while (my $o = shift @ord) {
2681 0           $ord = $ord * 0x100 + $o;
2682             }
2683 0           return $ord;
2684             }
2685             else {
2686 0           return CORE::ord $_;
2687             }
2688             }
2689              
2690             #
2691             # Latin-4 reverse
2692             #
2693             sub Char::Latin4::reverse(@) {
2694              
2695 0 0   0 0   if (wantarray) {
2696 0           return CORE::reverse @_;
2697             }
2698             else {
2699              
2700             # One of us once cornered Larry in an elevator and asked him what
2701             # problem he was solving with this, but he looked as far off into
2702             # the distance as he could in an elevator and said, "It seemed like
2703             # a good idea at the time."
2704              
2705 0           return join '', CORE::reverse(join('',@_) =~ /\G ($q_char) /oxmsg);
2706             }
2707             }
2708              
2709             #
2710             # Latin-4 getc (with parameter, without parameter)
2711             #
2712             sub Char::Latin4::getc(;*@) {
2713              
2714 0     0 0   my($package) = caller;
2715 0 0         my $fh = @_ ? qualify_to_ref(shift,$package) : \*STDIN;
2716 0 0 0       croak 'Too many arguments for Char::Latin4::getc' if @_ and not wantarray;
2717              
2718 0           my @length = sort { $a <=> $b } keys %range_tr;
  0            
2719 0           my $getc = '';
2720 0           for my $length ($length[0] .. $length[-1]) {
2721 0           $getc .= CORE::getc($fh);
2722 0 0         if (exists $range_tr{CORE::length($getc)}) {
2723 0 0         if ($getc =~ /\A ${Char::Elatin4::dot_s} \z/oxms) {
2724 0 0         return wantarray ? ($getc,@_) : $getc;
2725             }
2726             }
2727             }
2728 0 0         return wantarray ? ($getc,@_) : $getc;
2729             }
2730              
2731             #
2732             # Latin-4 length by character
2733             #
2734             sub Char::Latin4::length(;$) {
2735              
2736 0 0   0 1   local $_ = shift if @_;
2737              
2738 0           local @_ = /\G ($q_char) /oxmsg;
2739 0           return scalar @_;
2740             }
2741              
2742             #
2743             # Latin-4 substr by character
2744             #
2745             BEGIN {
2746              
2747             # P.232 The lvalue Attribute
2748             # in Chapter 6: Subroutines
2749             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
2750              
2751             # P.336 The lvalue Attribute
2752             # in Chapter 7: Subroutines
2753             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
2754              
2755             # P.144 8.4 Lvalue subroutines
2756             # in Chapter 8: perlsub: Perl subroutines
2757             # of ISBN-13: 978-1-906966-02-7 The Perl Language Reference Manual (for Perl version 5.12.1)
2758              
2759 197 50 0 197 1 153604 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            
2760             # vv----------------*******
2761             sub Char::Latin4::substr($$;$$) %s {
2762              
2763             my @char = $_[0] =~ /\G ($q_char) /oxmsg;
2764              
2765             # If the substring is beyond either end of the string, substr() returns the undefined
2766             # value and produces a warning. When used as an lvalue, specifying a substring that
2767             # is entirely outside the string raises an exception.
2768             # http://perldoc.perl.org/functions/substr.html
2769              
2770             # A return with no argument returns the scalar value undef in scalar context,
2771             # an empty list () in list context, and (naturally) nothing at all in void
2772             # context.
2773              
2774             my $offset = $_[1];
2775             if (($offset > scalar(@char)) or ($offset < (-1 * scalar(@char)))) {
2776             return;
2777             }
2778              
2779             # substr($string,$offset,$length,$replacement)
2780             if (@_ == 4) {
2781             my(undef,undef,$length,$replacement) = @_;
2782             my $substr = join '', splice(@char, $offset, $length, $replacement);
2783             $_[0] = join '', @char;
2784              
2785             # return $substr; this doesn't work, don't say "return"
2786             $substr;
2787             }
2788              
2789             # substr($string,$offset,$length)
2790             elsif (@_ == 3) {
2791             my(undef,undef,$length) = @_;
2792             my $octet_offset = 0;
2793             my $octet_length = 0;
2794             if ($offset == 0) {
2795             $octet_offset = 0;
2796             }
2797             elsif ($offset > 0) {
2798             $octet_offset = CORE::length(join '', @char[0..$offset-1]);
2799             }
2800             else {
2801             $octet_offset = -1 * CORE::length(join '', @char[$#char+$offset+1..$#char]);
2802             }
2803             if ($length == 0) {
2804             $octet_length = 0;
2805             }
2806             elsif ($length > 0) {
2807             $octet_length = CORE::length(join '', @char[$offset..$offset+$length-1]);
2808             }
2809             else {
2810             $octet_length = -1 * CORE::length(join '', @char[$#char+$length+1..$#char]);
2811             }
2812             CORE::substr($_[0], $octet_offset, $octet_length);
2813             }
2814              
2815             # substr($string,$offset)
2816             else {
2817             my $octet_offset = 0;
2818             if ($offset == 0) {
2819             $octet_offset = 0;
2820             }
2821             elsif ($offset > 0) {
2822             $octet_offset = CORE::length(join '', @char[0..$offset-1]);
2823             }
2824             else {
2825             $octet_offset = -1 * CORE::length(join '', @char[$#char+$offset+1..$#char]);
2826             }
2827             CORE::substr($_[0], $octet_offset);
2828             }
2829             }
2830             END
2831             }
2832              
2833             #
2834             # Latin-4 index by character
2835             #
2836             sub Char::Latin4::index($$;$) {
2837              
2838 0     0 1   my $index;
2839 0 0         if (@_ == 3) {
2840 0           $index = Char::Elatin4::index($_[0], $_[1], CORE::length(Char::Latin4::substr($_[0], 0, $_[2])));
2841             }
2842             else {
2843 0           $index = Char::Elatin4::index($_[0], $_[1]);
2844             }
2845              
2846 0 0         if ($index == -1) {
2847 0           return -1;
2848             }
2849             else {
2850 0           return Char::Latin4::length(CORE::substr $_[0], 0, $index);
2851             }
2852             }
2853              
2854             #
2855             # Latin-4 rindex by character
2856             #
2857             sub Char::Latin4::rindex($$;$) {
2858              
2859 0     0 1   my $rindex;
2860 0 0         if (@_ == 3) {
2861 0           $rindex = Char::Elatin4::rindex($_[0], $_[1], CORE::length(Char::Latin4::substr($_[0], 0, $_[2])));
2862             }
2863             else {
2864 0           $rindex = Char::Elatin4::rindex($_[0], $_[1]);
2865             }
2866              
2867 0 0         if ($rindex == -1) {
2868 0           return -1;
2869             }
2870             else {
2871 0           return Char::Latin4::length(CORE::substr $_[0], 0, $rindex);
2872             }
2873             }
2874              
2875             # when 'm//', '/' means regexp match 'm//' and '?' means regexp match '??'
2876             # when 'div', '/' means division operator and '?' means conditional operator (condition ? then : else)
2877 197     197   16466 BEGIN { CORE::eval q{ use vars qw($slash) } } $slash = 'm//';
  197     197   2253  
  197         400  
  197         16212  
2878              
2879             # ord() to ord() or Char::Latin4::ord()
2880 197     197   12842 BEGIN { CORE::eval q{ use vars qw($function_ord) } } $function_ord = 'ord';
  197     197   1134  
  197         419  
  197         13781  
2881              
2882             # ord to ord or Char::Latin4::ord_
2883 197     197   11912 BEGIN { CORE::eval q{ use vars qw($function_ord_) } } $function_ord_ = 'ord';
  197     197   1565  
  197         402  
  197         13597  
2884              
2885             # reverse to reverse or Char::Latin4::reverse
2886 197     197   12315 BEGIN { CORE::eval q{ use vars qw($function_reverse) } } $function_reverse = 'reverse';
  197     197   1538  
  197         387  
  197         12899  
2887              
2888             # getc to getc or Char::Latin4::getc
2889 197     197   12443 BEGIN { CORE::eval q{ use vars qw($function_getc) } } $function_getc = 'getc';
  197     197   1250  
  197         362  
  197         13753  
2890              
2891             # P.1023 Appendix W.9 Multibyte Anchoring
2892             # of ISBN 1-56592-224-7 CJKV Information Processing
2893              
2894             my $anchor = '';
2895              
2896 197     197   12846 BEGIN { CORE::eval q{ use vars qw($nest) } }
  197     197   1121  
  197         367  
  197         12206329  
2897              
2898             # regexp of nested parens in qqXX
2899              
2900             # P.340 Matching Nested Constructs with Embedded Code
2901             # in Chapter 7: Perl
2902             # of ISBN 0-596-00289-0 Mastering Regular Expressions, Second edition
2903              
2904             my $qq_paren = qr{(?{local $nest=0}) (?>(?:
2905             \\c[\x40-\x5F] |
2906             \\ [\x00-\xFF] |
2907             [^()] |
2908             \( (?{$nest++}) |
2909             \) (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!))
2910             }xms;
2911             my $qq_brace = qr{(?{local $nest=0}) (?>(?:
2912             \\c[\x40-\x5F] |
2913             \\ [\x00-\xFF] |
2914             [^{}] |
2915             \{ (?{$nest++}) |
2916             \} (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!))
2917             }xms;
2918             my $qq_bracket = qr{(?{local $nest=0}) (?>(?:
2919             \\c[\x40-\x5F] |
2920             \\ [\x00-\xFF] |
2921             [^[\]] |
2922             \[ (?{$nest++}) |
2923             \] (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!))
2924             }xms;
2925             my $qq_angle = qr{(?{local $nest=0}) (?>(?:
2926             \\c[\x40-\x5F] |
2927             \\ [\x00-\xFF] |
2928             [^<>] |
2929             \< (?{$nest++}) |
2930             \> (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!))
2931             }xms;
2932             my $qq_scalar = qr{(?: \{ (?:$qq_brace)*? \} |
2933             (?: ::)? (?:
2934             [a-zA-Z_][a-zA-Z_0-9]*
2935             (?: ::[a-zA-Z_][a-zA-Z_0-9]* )* (?: \[ (?: \$\[ | \$\] | $qq_char )*? \] | \{ (?:$qq_brace)*? \} )*
2936             (?: (?: -> )? (?: [\$\@\%\&\*]\* | \$\#\* | [\@\%]? \[ (?: \$\[ | \$\] | $qq_char )*? \] | [\@\%\*]? \{ (?:$qq_brace)*? \} ) )*
2937             ))
2938             }xms;
2939             my $qq_variable = qr{(?: \{ (?:$qq_brace)*? \} |
2940             (?: ::)? (?:
2941             [0-9]+ |
2942             [^a-zA-Z_0-9\[\]] |
2943             ^[A-Z] |
2944             [a-zA-Z_][a-zA-Z_0-9]*
2945             (?: ::[a-zA-Z_][a-zA-Z_0-9]* )* (?: \[ (?: \$\[ | \$\] | $qq_char )*? \] | \{ (?:$qq_brace)*? \} )*
2946             (?: (?: -> )? (?: [\$\@\%\&\*]\* | \$\#\* | [\@\%]? \[ (?: \$\[ | \$\] | $qq_char )*? \] | [\@\%\*]? \{ (?:$qq_brace)*? \} ) )*
2947             ))
2948             }xms;
2949             my $qq_substr = qr{(?: Char::Latin4::substr | CORE::substr | substr ) \( $qq_paren \)
2950             }xms;
2951              
2952             # regexp of nested parens in qXX
2953             my $q_paren = qr{(?{local $nest=0}) (?>(?:
2954             [^()] |
2955             \( (?{$nest++}) |
2956             \) (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!))
2957             }xms;
2958             my $q_brace = qr{(?{local $nest=0}) (?>(?:
2959             [^{}] |
2960             \{ (?{$nest++}) |
2961             \} (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!))
2962             }xms;
2963             my $q_bracket = qr{(?{local $nest=0}) (?>(?:
2964             [^[\]] |
2965             \[ (?{$nest++}) |
2966             \] (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!))
2967             }xms;
2968             my $q_angle = qr{(?{local $nest=0}) (?>(?:
2969             [^<>] |
2970             \< (?{$nest++}) |
2971             \> (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!))
2972             }xms;
2973              
2974             my $matched = '';
2975             my $s_matched = '';
2976              
2977             my $tr_variable = ''; # variable of tr///
2978             my $sub_variable = ''; # variable of s///
2979             my $bind_operator = ''; # =~ or !~
2980              
2981             my @heredoc = (); # here document
2982             my @heredoc_delimiter = ();
2983             my $here_script = ''; # here script
2984              
2985             #
2986             # escape Latin-4 script
2987             #
2988             sub Char::Latin4::escape(;$) {
2989 0 0   0 0   local($_) = $_[0] if @_;
2990              
2991             # P.359 The Study Function
2992             # in Chapter 7: Perl
2993             # of ISBN 0-596-00289-0 Mastering Regular Expressions, Second edition
2994              
2995 0           study $_; # Yes, I studied study yesterday.
2996              
2997             # while all script
2998              
2999             # 6.14. Matching from Where the Last Pattern Left Off
3000             # in Chapter 6. Pattern Matching
3001             # of ISBN 0-596-00313-7 Perl Cookbook, 2nd Edition.
3002             # (and so on)
3003              
3004             # one member of Tag-team
3005             #
3006             # P.128 Start of match (or end of previous match): \G
3007             # P.130 Advanced Use of \G with Perl
3008             # in Chapter 3: Overview of Regular Expression Features and Flavors
3009             # P.255 Use leading anchors
3010             # P.256 Expose ^ and \G at the front expressions
3011             # in Chapter 6: Crafting an Efficient Expression
3012             # P.315 "Tag-team" matching with /gc
3013             # in Chapter 7: Perl
3014             # of ISBN 0-596-00289-0 Mastering Regular Expressions, Second edition
3015              
3016 0           my $e_script = '';
3017 0           while (not /\G \z/oxgc) { # member
3018 0           $e_script .= Char::Latin4::escape_token();
3019             }
3020              
3021 0           return $e_script;
3022             }
3023              
3024             #
3025             # escape Latin-4 token of script
3026             #
3027             sub Char::Latin4::escape_token {
3028              
3029             # \n output here document
3030              
3031 0     0 0   my $ignore_modules = join('|', qw(
3032             utf8
3033             bytes
3034             charnames
3035             I18N::Japanese
3036             I18N::Collate
3037             I18N::JExt
3038             File::DosGlob
3039             Wild
3040             Wildcard
3041             Japanese
3042             ));
3043              
3044             # another member of Tag-team
3045             #
3046             # P.315 "Tag-team" matching with /gc
3047             # in Chapter 7: Perl
3048             # of ISBN 0-596-00289-0 Mastering Regular Expressions, Second edition
3049              
3050 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          
3051 0           my $heredoc = '';
3052 0 0         if (scalar(@heredoc_delimiter) >= 1) {
3053 0           $slash = 'm//';
3054              
3055 0           $heredoc = join '', @heredoc;
3056 0           @heredoc = ();
3057              
3058             # skip here document
3059 0           for my $heredoc_delimiter (@heredoc_delimiter) {
3060 0           /\G .*? \n $heredoc_delimiter \n/xmsgc;
3061             }
3062 0           @heredoc_delimiter = ();
3063              
3064 0           $here_script = '';
3065             }
3066 0           return "\n" . $heredoc;
3067             }
3068              
3069             # ignore space, comment
3070 0           elsif (/\G (\s+|\#.*) /oxgc) { return $1; }
3071              
3072             # if (, elsif (, unless (, while (, until (, given (, and when (
3073              
3074             # given, when
3075              
3076             # P.225 The given Statement
3077             # in Chapter 15: Smart Matching and given-when
3078             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
3079              
3080             # P.133 The given Statement
3081             # in Chapter 4: Statements and Declarations
3082             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
3083              
3084             elsif (/\G ( (?: if | elsif | unless | while | until | given | when ) \s* \( ) /oxgc) {
3085 0           $slash = 'm//';
3086 0           return $1;
3087             }
3088              
3089             # scalar variable ($scalar = ...) =~ tr///;
3090             # scalar variable ($scalar = ...) =~ s///;
3091              
3092             # state
3093              
3094             # P.68 Persistent, Private Variables
3095             # in Chapter 4: Subroutines
3096             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
3097              
3098             # P.160 Persistent Lexically Scoped Variables: state
3099             # in Chapter 4: Statements and Declarations
3100             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
3101              
3102             # (and so on)
3103              
3104             elsif (/\G ( \( \s* (?: local \b | my \b | our \b | state \b )? \s* \$ $qq_scalar ) /oxgc) {
3105 0           my $e_string = e_string($1);
3106              
3107 0 0         if (/\G ( \s* = $qq_paren \) ) ( \s* (?: =~ | !~ ) \s* ) (?= (?: tr | y ) \b ) /oxgc) {
    0          
3108 0           $tr_variable = $e_string . e_string($1);
3109 0           $bind_operator = $2;
3110 0           $slash = 'm//';
3111 0           return '';
3112             }
3113             elsif (/\G ( \s* = $qq_paren \) ) ( \s* (?: =~ | !~ ) \s* ) (?= s \b ) /oxgc) {
3114 0           $sub_variable = $e_string . e_string($1);
3115 0           $bind_operator = $2;
3116 0           $slash = 'm//';
3117 0           return '';
3118             }
3119             else {
3120 0           $slash = 'div';
3121 0           return $e_string;
3122             }
3123             }
3124              
3125             # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Char::Elatin4::PREMATCH()
3126             elsif (/\G ( \$` | \$\{`\} | \$ \s* PREMATCH \b | \$ \s* \{ \s* PREMATCH \s* \} | \$ \s* \{\^PREMATCH\} ) /oxmsgc) {
3127 0           $slash = 'div';
3128 0           return q{Char::Elatin4::PREMATCH()};
3129             }
3130              
3131             # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Char::Elatin4::MATCH()
3132             elsif (/\G ( \$& | \$\{&\} | \$ \s* MATCH \b | \$ \s* \{ \s* MATCH \s* \} | \$ \s* \{\^MATCH\} ) /oxmsgc) {
3133 0           $slash = 'div';
3134 0           return q{Char::Elatin4::MATCH()};
3135             }
3136              
3137             # $', ${'} --> $', ${'}
3138             elsif (/\G ( \$' | \$\{'\} ) /oxmsgc) {
3139 0           $slash = 'div';
3140 0           return $1;
3141             }
3142              
3143             # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Char::Elatin4::POSTMATCH()
3144             elsif (/\G ( \$ \s* POSTMATCH \b | \$ \s* \{ \s* POSTMATCH \s* \} | \$ \s* \{\^POSTMATCH\} ) /oxmsgc) {
3145 0           $slash = 'div';
3146 0           return q{Char::Elatin4::POSTMATCH()};
3147             }
3148              
3149             # scalar variable $scalar =~ tr///;
3150             # scalar variable $scalar =~ s///;
3151             # substr() =~ tr///;
3152             # substr() =~ s///;
3153             elsif (/\G ( \$ $qq_scalar | $qq_substr ) /oxgc) {
3154 0           my $scalar = e_string($1);
3155              
3156 0 0         if (/\G ( \s* (?: =~ | !~ ) \s* ) (?= (?: tr | y ) \b ) /oxgc) {
    0          
3157 0           $tr_variable = $scalar;
3158 0           $bind_operator = $1;
3159 0           $slash = 'm//';
3160 0           return '';
3161             }
3162             elsif (/\G ( \s* (?: =~ | !~ ) \s* ) (?= s \b ) /oxgc) {
3163 0           $sub_variable = $scalar;
3164 0           $bind_operator = $1;
3165 0           $slash = 'm//';
3166 0           return '';
3167             }
3168             else {
3169 0           $slash = 'div';
3170 0           return $scalar;
3171             }
3172             }
3173              
3174             # end of statement
3175             elsif (/\G ( [,;] ) /oxgc) {
3176 0           $slash = 'm//';
3177              
3178             # clear tr/// variable
3179 0           $tr_variable = '';
3180              
3181             # clear s/// variable
3182 0           $sub_variable = '';
3183              
3184 0           $bind_operator = '';
3185              
3186 0           return $1;
3187             }
3188              
3189             # bareword
3190             elsif (/\G ( \{ \s* (?: tr | index | rindex | reverse ) \s* \} ) /oxmsgc) {
3191 0           return $1;
3192             }
3193              
3194             # $0 --> $0
3195             elsif (/\G ( \$ 0 ) /oxmsgc) {
3196 0           $slash = 'div';
3197 0           return $1;
3198             }
3199             elsif (/\G ( \$ \{ \s* 0 \s* \} ) /oxmsgc) {
3200 0           $slash = 'div';
3201 0           return $1;
3202             }
3203              
3204             # $$ --> $$
3205             elsif (/\G ( \$ \$ ) (?![\w\{]) /oxmsgc) {
3206 0           $slash = 'div';
3207 0           return $1;
3208             }
3209              
3210             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
3211             # $1, $2, $3 --> $1, $2, $3 otherwise
3212             elsif (/\G \$ ([1-9][0-9]*) /oxmsgc) {
3213 0           $slash = 'div';
3214 0           return e_capture($1);
3215             }
3216             elsif (/\G \$ \{ \s* ([1-9][0-9]*) \s* \} /oxmsgc) {
3217 0           $slash = 'div';
3218 0           return e_capture($1);
3219             }
3220              
3221             # $$foo[ ... ] --> $ $foo->[ ... ]
3222             elsif (/\G \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) ( \[ .+? \] ) /oxmsgc) {
3223 0           $slash = 'div';
3224 0           return e_capture($1.'->'.$2);
3225             }
3226              
3227             # $$foo{ ... } --> $ $foo->{ ... }
3228             elsif (/\G \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) ( \{ .+? \} ) /oxmsgc) {
3229 0           $slash = 'div';
3230 0           return e_capture($1.'->'.$2);
3231             }
3232              
3233             # $$foo
3234             elsif (/\G \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) /oxmsgc) {
3235 0           $slash = 'div';
3236 0           return e_capture($1);
3237             }
3238              
3239             # ${ foo }
3240             elsif (/\G \$ \s* \{ ( \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* ) \} /oxmsgc) {
3241 0           $slash = 'div';
3242 0           return '${' . $1 . '}';
3243             }
3244              
3245             # ${ ... }
3246             elsif (/\G \$ \s* \{ \s* ( $qq_brace ) \s* \} /oxmsgc) {
3247 0           $slash = 'div';
3248 0           return e_capture($1);
3249             }
3250              
3251             # variable or function
3252             # $ @ % & * $ #
3253             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) {
3254 0           $slash = 'div';
3255 0           return $1;
3256             }
3257             # $ $ $ $ $ $ $ $ $ $ $ $ $ $
3258             # $ @ # \ ' " / ? ( ) [ ] < >
3259             elsif (/\G ( \$[\$\@\#\\\'\"\/\?\(\)\[\]\<\>] ) /oxmsgc) {
3260 0           $slash = 'div';
3261 0           return $1;
3262             }
3263              
3264             # while ()
3265             elsif (/\G \b (while \s* \( \s* <[\$]?[A-Za-z_][A-Za-z_0-9]*> \s* \)) \b /oxgc) {
3266 0           return $1;
3267             }
3268              
3269             # while () --- glob
3270              
3271             # avoid "Error: Runtime exception" of perl version 5.005_03
3272              
3273             elsif (/\G \b while \s* \( \s* < ((?:[^>\0\a\e\f\n\r\t])+?) > \s* \) \b /oxgc) {
3274 0           return 'while ($_ = Char::Elatin4::glob("' . $1 . '"))';
3275             }
3276              
3277             # while (glob)
3278             elsif (/\G \b while \s* \( \s* glob \s* \) /oxgc) {
3279 0           return 'while ($_ = Char::Elatin4::glob_)';
3280             }
3281              
3282             # while (glob(WILDCARD))
3283             elsif (/\G \b while \s* \( \s* glob \b /oxgc) {
3284 0           return 'while ($_ = Char::Elatin4::glob';
3285             }
3286              
3287             # doit if, doit unless, doit while, doit until, doit for, doit when
3288 0           elsif (/\G \b ( if | unless | while | until | for | when ) \b /oxgc) { $slash = 'm//'; return $1; }
  0            
3289              
3290             # subroutines of package Char::Elatin4
3291 0           elsif (/\G \b (CORE:: | ->[ ]* (?: atan2 | [a-z]{2,})) \b /oxgc) { $slash = 'm//'; return $1; }
  0            
3292 0           elsif (/\G \b Char::Latin4::eval (?= \s* \{ ) /oxgc) { $slash = 'm//'; return 'eval'; }
  0            
3293 0           elsif (/\G \b Char::Latin4::eval \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'eval Char::Latin4::escape'; }
  0            
3294 0           elsif (/\G \b bytes::substr \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'substr'; }
  0            
3295 0           elsif (/\G \b chop \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'Char::Elatin4::chop'; }
  0            
3296 0           elsif (/\G \b bytes::index \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'index'; }
  0            
3297 0           elsif (/\G \b Char::Latin4::index \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'Char::Latin4::index'; }
  0            
3298 0           elsif (/\G \b index \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'Char::Elatin4::index'; }
  0            
3299 0           elsif (/\G \b bytes::rindex \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'rindex'; }
  0            
3300 0           elsif (/\G \b Char::Latin4::rindex \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'Char::Latin4::rindex'; }
  0            
3301 0           elsif (/\G \b rindex \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'Char::Elatin4::rindex'; }
  0            
3302 0           elsif (/\G \b lc (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Char::Elatin4::lc'; }
  0            
3303 0           elsif (/\G \b lcfirst (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Char::Elatin4::lcfirst'; }
  0            
3304 0           elsif (/\G \b uc (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Char::Elatin4::uc'; }
  0            
3305 0           elsif (/\G \b ucfirst (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Char::Elatin4::ucfirst'; }
  0            
3306 0           elsif (/\G \b fc (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Char::Elatin4::fc'; }
  0            
3307              
3308             # "-s '' ..." means file test "-s 'filename' ..." (not means "- s/// ...")
3309 0           elsif (/\G -s \s+ \s* (\") ((?:$qq_char)+?) (\") /oxgc) { $slash = 'm//'; return '-s ' . e_qq('', $1,$3,$2); }
  0            
3310 0           elsif (/\G -s \s+ qq \s* (\#) ((?:$qq_char)+?) (\#) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0            
3311 0           elsif (/\G -s \s+ qq \s* (\() ((?:$qq_paren)+?) (\)) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0            
3312 0           elsif (/\G -s \s+ qq \s* (\{) ((?:$qq_brace)+?) (\}) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0            
3313 0           elsif (/\G -s \s+ qq \s* (\[) ((?:$qq_bracket)+?) (\]) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0            
3314 0           elsif (/\G -s \s+ qq \s* (\<) ((?:$qq_angle)+?) (\>) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0            
3315 0           elsif (/\G -s \s+ qq \s* (\S) ((?:$qq_char)+?) (\1) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0            
3316              
3317 0           elsif (/\G -s \s+ \s* (\') ((?:\\\'|\\\\|$q_char)+?) (\') /oxgc) { $slash = 'm//'; return '-s ' . e_q ('', $1,$3,$2); }
  0            
3318 0           elsif (/\G -s \s+ q \s* (\#) ((?:\\\#|\\\\|$q_char)+?) (\#) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0            
3319 0           elsif (/\G -s \s+ q \s* (\() ((?:\\\)|\\\\|$q_paren)+?) (\)) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0            
3320 0           elsif (/\G -s \s+ q \s* (\{) ((?:\\\}|\\\\|$q_brace)+?) (\}) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0            
3321 0           elsif (/\G -s \s+ q \s* (\[) ((?:\\\]|\\\\|$q_bracket)+?) (\]) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0            
3322 0           elsif (/\G -s \s+ q \s* (\<) ((?:\\\>|\\\\|$q_angle)+?) (\>) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0            
3323 0           elsif (/\G -s \s+ q \s* (\S) ((?:\\\1|\\\\|$q_char)+?) (\1) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0            
3324              
3325             elsif (/\G -s \s* (\$ \w+(?: ::\w+)* (?: (?: ->)? (?: [\$\@\%\&\*]\* | \$\#\* | \( (?:$qq_paren)*? \) | [\@\%\*]? \{ (?:$qq_brace)+? \} | [\@\%]? \[ (?:$qq_bracket)+? \] ) )*) /oxgc)
3326 0           { $slash = 'm//'; return "-s $1"; }
  0            
3327 0           elsif (/\G -s \s* \( ((?:$qq_paren)*?) \) /oxgc) { $slash = 'm//'; return "-s ($1)"; }
  0            
3328 0           elsif (/\G -s (?= \s+ [a-z]+) /oxgc) { $slash = 'm//'; return '-s'; }
  0            
3329 0           elsif (/\G -s \s+ (\w+) /oxgc) { $slash = 'm//'; return "-s $1"; }
  0            
3330              
3331 0           elsif (/\G \b bytes::length (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'length'; }
  0            
3332 0           elsif (/\G \b bytes::chr (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'chr'; }
  0            
3333 0           elsif (/\G \b chr (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Char::Elatin4::chr'; }
  0            
3334 0           elsif (/\G \b bytes::ord (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $slash = 'div'; return 'ord'; }
  0            
3335 0           elsif (/\G \b ord (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $slash = 'div'; return $function_ord; }
  0            
3336 0           elsif (/\G \b glob (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Char::Elatin4::glob'; }
  0            
3337 0           elsif (/\G \b lc \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'Char::Elatin4::lc_'; }
  0            
3338 0           elsif (/\G \b lcfirst \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'Char::Elatin4::lcfirst_'; }
  0            
3339 0           elsif (/\G \b uc \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'Char::Elatin4::uc_'; }
  0            
3340 0           elsif (/\G \b ucfirst \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'Char::Elatin4::ucfirst_'; }
  0            
3341 0           elsif (/\G \b fc \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'Char::Elatin4::fc_'; }
  0            
3342 0           elsif (/\G -s \b (?! \s* => ) /oxgc) { $slash = 'm//'; return '-s '; }
  0            
3343              
3344 0           elsif (/\G \b bytes::length \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'length'; }
  0            
3345 0           elsif (/\G \b bytes::chr \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'chr'; }
  0            
3346 0           elsif (/\G \b chr \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'Char::Elatin4::chr_'; }
  0            
3347 0           elsif (/\G \b bytes::ord \b (?! \s* => ) /oxgc) { $slash = 'div'; return 'ord'; }
  0            
3348 0           elsif (/\G \b ord \b (?! \s* => ) /oxgc) { $slash = 'div'; return $function_ord_; }
  0            
3349 0           elsif (/\G \b glob \b (?! \s* => ) /oxgc) { $slash = 'm//'; return 'Char::Elatin4::glob_'; }
  0            
3350 0           elsif (/\G \b reverse \b (?! \s* => ) /oxgc) { $slash = 'm//'; return $function_reverse; }
  0            
3351 0           elsif (/\G \b getc \b (?! \s* => ) /oxgc) { $slash = 'm//'; return $function_getc; }
  0            
3352             # split
3353             elsif (/\G \b (split) \b (?! \s* => ) /oxgc) {
3354 0           $slash = 'm//';
3355              
3356 0           my $e = '';
3357 0           while (/\G ( \s+ | \( | \#.* ) /oxgc) {
3358 0           $e .= $1;
3359             }
3360              
3361             # end of split
3362 0 0         if (/\G (?= [,;\)\}\]] ) /oxgc) { return 'Char::Elatin4::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          
3363              
3364             # split scalar value
3365 0           elsif (/\G ( [\$\@\&\*] $qq_scalar ) /oxgc) { return 'Char::Elatin4::split' . $e . e_string($1); }
3366              
3367             # split literal space
3368 0           elsif (/\G \b qq (\#) [ ] (\#) /oxgc) { return 'Char::Elatin4::split' . $e . qq {qq$1 $2}; }
3369 0           elsif (/\G \b qq (\s*) (\() [ ] (\)) /oxgc) { return 'Char::Elatin4::split' . $e . qq{$1qq$2 $3}; }
3370 0           elsif (/\G \b qq (\s*) (\{) [ ] (\}) /oxgc) { return 'Char::Elatin4::split' . $e . qq{$1qq$2 $3}; }
3371 0           elsif (/\G \b qq (\s*) (\[) [ ] (\]) /oxgc) { return 'Char::Elatin4::split' . $e . qq{$1qq$2 $3}; }
3372 0           elsif (/\G \b qq (\s*) (\<) [ ] (\>) /oxgc) { return 'Char::Elatin4::split' . $e . qq{$1qq$2 $3}; }
3373 0           elsif (/\G \b qq (\s*) (\S) [ ] (\2) /oxgc) { return 'Char::Elatin4::split' . $e . qq{$1qq$2 $3}; }
3374 0           elsif (/\G \b q (\#) [ ] (\#) /oxgc) { return 'Char::Elatin4::split' . $e . qq {q$1 $2}; }
3375 0           elsif (/\G \b q (\s*) (\() [ ] (\)) /oxgc) { return 'Char::Elatin4::split' . $e . qq {$1q$2 $3}; }
3376 0           elsif (/\G \b q (\s*) (\{) [ ] (\}) /oxgc) { return 'Char::Elatin4::split' . $e . qq {$1q$2 $3}; }
3377 0           elsif (/\G \b q (\s*) (\[) [ ] (\]) /oxgc) { return 'Char::Elatin4::split' . $e . qq {$1q$2 $3}; }
3378 0           elsif (/\G \b q (\s*) (\<) [ ] (\>) /oxgc) { return 'Char::Elatin4::split' . $e . qq {$1q$2 $3}; }
3379 0           elsif (/\G \b q (\s*) (\S) [ ] (\2) /oxgc) { return 'Char::Elatin4::split' . $e . qq {$1q$2 $3}; }
3380 0           elsif (/\G ' [ ] ' /oxgc) { return 'Char::Elatin4::split' . $e . qq {' '}; }
3381 0           elsif (/\G " [ ] " /oxgc) { return 'Char::Elatin4::split' . $e . qq {" "}; }
3382              
3383             # split qq//
3384             elsif (/\G \b (qq) \b /oxgc) {
3385 0 0         if (/\G (\#) ((?:$qq_char)*?) (\#) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq# # --> qr # #
  0            
3386             else {
3387 0           while (not /\G \z/oxgc) {
3388 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
3389 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq ( ) --> qr ( )
3390 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq { } --> qr { }
3391 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq [ ] --> qr [ ]
3392 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq < > --> qr < >
3393 0           elsif (/\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) /oxgc) { return e_split($e.'qr','{','}',$2,''); } # qq | | --> qr { }
3394 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq * * --> qr * *
3395             }
3396 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3397             }
3398             }
3399              
3400             # split qr//
3401             elsif (/\G \b (qr) \b /oxgc) {
3402 0 0         if (/\G (\#) ((?:$qq_char)*?) (\#) ([imosxpadlubB]*) /oxgc) { return e_split ($e.'qr',$1,$3,$2,$4); } # qr# #
  0            
3403             else {
3404 0           while (not /\G \z/oxgc) {
3405 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
3406 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([imosxpadlubB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # qr ( )
3407 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([imosxpadlubB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # qr { }
3408 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([imosxpadlubB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # qr [ ]
3409 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([imosxpadlubB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # qr < >
3410 0           elsif (/\G (\') ((?:$qq_char)*?) (\') ([imosxpadlubB]*) /oxgc) { return e_split_q($e.'qr',$1, $3, $2,$4); } # qr ' '
3411 0           elsif (/\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ([imosxpadlubB]*) /oxgc) { return e_split ($e.'qr','{','}',$2,$4); } # qr | | --> qr { }
3412 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([imosxpadlubB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # qr * *
3413             }
3414 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3415             }
3416             }
3417              
3418             # split q//
3419             elsif (/\G \b (q) \b /oxgc) {
3420 0 0         if (/\G (\#) ((?:\\\#|\\\\|$q_char)*?) (\#) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q# # --> qr # #
  0            
3421             else {
3422 0           while (not /\G \z/oxgc) {
3423 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
3424 0           elsif (/\G (\() ((?:\\\\|\\\)|\\\(|$q_paren)*?) (\)) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q ( ) --> qr ( )
3425 0           elsif (/\G (\{) ((?:\\\\|\\\}|\\\{|$q_brace)*?) (\}) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q { } --> qr { }
3426 0           elsif (/\G (\[) ((?:\\\\|\\\]|\\\[|$q_bracket)*?) (\]) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q [ ] --> qr [ ]
3427 0           elsif (/\G (\<) ((?:\\\\|\\\>|\\\<|$q_angle)*?) (\>) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q < > --> qr < >
3428 0           elsif (/\G ([*\-:?\\^|]) ((?:$q_char)*?) (\1) /oxgc) { return e_split_q($e.'qr','{','}',$2,''); } # q | | --> qr { }
3429 0           elsif (/\G (\S) ((?:\\\\|\\\1| $q_char)*?) (\1) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q * * --> qr * *
3430             }
3431 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3432             }
3433             }
3434              
3435             # split m//
3436             elsif (/\G \b (m) \b /oxgc) {
3437 0 0         if (/\G (\#) ((?:$qq_char)*?) (\#) ([cgimosxpadlubB]*) /oxgc) { return e_split ($e.'qr',$1,$3,$2,$4); } # m# # --> qr # #
  0            
3438             else {
3439 0           while (not /\G \z/oxgc) {
3440 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
3441 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cgimosxpadlubB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # m ( ) --> qr ( )
3442 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cgimosxpadlubB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # m { } --> qr { }
3443 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cgimosxpadlubB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # m [ ] --> qr [ ]
3444 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cgimosxpadlubB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # m < > --> qr < >
3445 0           elsif (/\G (\') ((?:$qq_char)*?) (\') ([cgimosxpadlubB]*) /oxgc) { return e_split_q($e.'qr',$1, $3, $2,$4); } # m ' ' --> qr ' '
3446 0           elsif (/\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ([cgimosxpadlubB]*) /oxgc) { return e_split ($e.'qr','{','}',$2,$4); } # m | | --> qr { }
3447 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cgimosxpadlubB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # m * * --> qr * *
3448             }
3449 0           die __FILE__, ": Search pattern not terminated";
3450             }
3451             }
3452              
3453             # split ''
3454             elsif (/\G (\') /oxgc) {
3455 0           my $q_string = '';
3456 0           while (not /\G \z/oxgc) {
3457 0 0         if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0          
    0          
    0          
3458 0           elsif (/\G (\\\') /oxgc) { $q_string .= $1; } # splitqr'' --> split qr''
3459 0           elsif (/\G \' /oxgc) { return e_split_q($e.q{ qr},"'","'",$q_string,''); } # ' ' --> qr ' '
3460 0           elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3461             }
3462 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3463             }
3464              
3465             # split ""
3466             elsif (/\G (\") /oxgc) {
3467 0           my $qq_string = '';
3468 0           while (not /\G \z/oxgc) {
3469 0 0         if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0          
    0          
    0          
3470 0           elsif (/\G (\\\") /oxgc) { $qq_string .= $1; } # splitqr"" --> split qr""
3471 0           elsif (/\G \" /oxgc) { return e_split($e.q{ qr},'"','"',$qq_string,''); } # " " --> qr " "
3472 0           elsif (/\G ($q_char) /oxgc) { $qq_string .= $1; }
3473             }
3474 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3475             }
3476              
3477             # split //
3478             elsif (/\G (\/) /oxgc) {
3479 0           my $regexp = '';
3480 0           while (not /\G \z/oxgc) {
3481 0 0         if (/\G (\\\\) /oxgc) { $regexp .= $1; }
  0 0          
    0          
    0          
3482 0           elsif (/\G (\\\/) /oxgc) { $regexp .= $1; } # splitqr// --> split qr//
3483 0           elsif (/\G \/ ([cgimosxpadlubB]*) /oxgc) { return e_split($e.q{ qr}, '/','/',$regexp,$1); } # / / --> qr / /
3484 0           elsif (/\G ($q_char) /oxgc) { $regexp .= $1; }
3485             }
3486 0           die __FILE__, ": Search pattern not terminated";
3487             }
3488             }
3489              
3490             # tr/// or y///
3491              
3492             # about [cdsrbB]* (/B modifier)
3493             #
3494             # P.559 appendix C
3495             # of ISBN 4-89052-384-7 Programming perl
3496             # (Japanese title is: Perl puroguramingu)
3497              
3498             elsif (/\G \b ( tr | y ) \b /oxgc) {
3499 0           my $ope = $1;
3500              
3501             # $1 $2 $3 $4 $5 $6
3502 0 0         if (/\G (\#) ((?:$qq_char)*?) (\#) ((?:$qq_char)*?) (\#) ([cdsrbB]*) /oxgc) { # tr# # #
3503 0           my @tr = ($tr_variable,$2);
3504 0           return e_tr(@tr,'',$4,$6);
3505             }
3506             else {
3507 0           my $e = '';
3508 0           while (not /\G \z/oxgc) {
3509 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3510             elsif (/\G (\() ((?:$qq_paren)*?) (\)) /oxgc) {
3511 0           my @tr = ($tr_variable,$2);
3512 0           while (not /\G \z/oxgc) {
3513 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3514 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr ( ) ( )
3515 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr ( ) { }
3516 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr ( ) [ ]
3517 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr ( ) < >
3518 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr ( ) * *
3519             }
3520 0           die __FILE__, ": Transliteration replacement not terminated";
3521             }
3522             elsif (/\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) {
3523 0           my @tr = ($tr_variable,$2);
3524 0           while (not /\G \z/oxgc) {
3525 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3526 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr { } ( )
3527 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr { } { }
3528 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr { } [ ]
3529 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr { } < >
3530 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr { } * *
3531             }
3532 0           die __FILE__, ": Transliteration replacement not terminated";
3533             }
3534             elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) {
3535 0           my @tr = ($tr_variable,$2);
3536 0           while (not /\G \z/oxgc) {
3537 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3538 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr [ ] ( )
3539 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr [ ] { }
3540 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr [ ] [ ]
3541 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr [ ] < >
3542 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr [ ] * *
3543             }
3544 0           die __FILE__, ": Transliteration replacement not terminated";
3545             }
3546             elsif (/\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) {
3547 0           my @tr = ($tr_variable,$2);
3548 0           while (not /\G \z/oxgc) {
3549 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3550 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr < > ( )
3551 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr < > { }
3552 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr < > [ ]
3553 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr < > < >
3554 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr < > * *
3555             }
3556 0           die __FILE__, ": Transliteration replacement not terminated";
3557             }
3558             # $1 $2 $3 $4 $5 $6
3559             elsif (/\G (\S) ((?:$qq_char)*?) (\1) ((?:$qq_char)*?) (\1) ([cdsrbB]*) /oxgc) { # tr * * *
3560 0           my @tr = ($tr_variable,$2);
3561 0           return e_tr(@tr,'',$4,$6);
3562             }
3563             }
3564 0           die __FILE__, ": Transliteration pattern not terminated";
3565             }
3566             }
3567              
3568             # qq//
3569             elsif (/\G \b (qq) \b /oxgc) {
3570 0           my $ope = $1;
3571              
3572             # if (/\G (\#) ((?:$qq_char)*?) (\#) /oxgc) { return e_qq($ope,$1,$3,$2); } # qq# #
3573 0 0         if (/\G (\#) /oxgc) { # qq# #
3574 0           my $qq_string = '';
3575 0           while (not /\G \z/oxgc) {
3576 0 0         if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0          
    0          
    0          
3577 0           elsif (/\G (\\\#) /oxgc) { $qq_string .= $1; }
3578 0           elsif (/\G (\#) /oxgc) { return e_qq($ope,'#','#',$qq_string); }
3579 0           elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3580             }
3581 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3582             }
3583              
3584             else {
3585 0           my $e = '';
3586 0           while (not /\G \z/oxgc) {
3587 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3588              
3589             # elsif (/\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qq ( )
3590             elsif (/\G (\() /oxgc) { # qq ( )
3591 0           my $qq_string = '';
3592 0           local $nest = 1;
3593 0           while (not /\G \z/oxgc) {
3594 0 0         if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0          
    0          
    0          
    0          
3595 0           elsif (/\G (\\\)) /oxgc) { $qq_string .= $1; }
3596 0           elsif (/\G (\() /oxgc) { $qq_string .= $1; $nest++; }
  0            
3597             elsif (/\G (\)) /oxgc) {
3598 0 0         if (--$nest == 0) { return $e . e_qq($ope,'(',')',$qq_string); }
  0            
3599 0           else { $qq_string .= $1; }
3600             }
3601 0           elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3602             }
3603 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3604             }
3605              
3606             # elsif (/\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qq { }
3607             elsif (/\G (\{) /oxgc) { # qq { }
3608 0           my $qq_string = '';
3609 0           local $nest = 1;
3610 0           while (not /\G \z/oxgc) {
3611 0 0         if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0          
    0          
    0          
    0          
3612 0           elsif (/\G (\\\}) /oxgc) { $qq_string .= $1; }
3613 0           elsif (/\G (\{) /oxgc) { $qq_string .= $1; $nest++; }
  0            
3614             elsif (/\G (\}) /oxgc) {
3615 0 0         if (--$nest == 0) { return $e . e_qq($ope,'{','}',$qq_string); }
  0            
3616 0           else { $qq_string .= $1; }
3617             }
3618 0           elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3619             }
3620 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3621             }
3622              
3623             # elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qq [ ]
3624             elsif (/\G (\[) /oxgc) { # qq [ ]
3625 0           my $qq_string = '';
3626 0           local $nest = 1;
3627 0           while (not /\G \z/oxgc) {
3628 0 0         if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0          
    0          
    0          
    0          
3629 0           elsif (/\G (\\\]) /oxgc) { $qq_string .= $1; }
3630 0           elsif (/\G (\[) /oxgc) { $qq_string .= $1; $nest++; }
  0            
3631             elsif (/\G (\]) /oxgc) {
3632 0 0         if (--$nest == 0) { return $e . e_qq($ope,'[',']',$qq_string); }
  0            
3633 0           else { $qq_string .= $1; }
3634             }
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             # elsif (/\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qq < >
3641             elsif (/\G (\<) /oxgc) { # qq < >
3642 0           my $qq_string = '';
3643 0           local $nest = 1;
3644 0           while (not /\G \z/oxgc) {
3645 0 0         if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0          
    0          
    0          
    0          
3646 0           elsif (/\G (\\\>) /oxgc) { $qq_string .= $1; }
3647 0           elsif (/\G (\<) /oxgc) { $qq_string .= $1; $nest++; }
  0            
3648             elsif (/\G (\>) /oxgc) {
3649 0 0         if (--$nest == 0) { return $e . e_qq($ope,'<','>',$qq_string); }
  0            
3650 0           else { $qq_string .= $1; }
3651             }
3652 0           elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3653             }
3654 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3655             }
3656              
3657             # elsif (/\G (\S) ((?:$qq_char)*?) (\1) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qq * *
3658             elsif (/\G (\S) /oxgc) { # qq * *
3659 0           my $delimiter = $1;
3660 0           my $qq_string = '';
3661 0           while (not /\G \z/oxgc) {
3662 0 0         if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0          
    0          
    0          
3663 0           elsif (/\G (\\\Q$delimiter\E) /oxgc) { $qq_string .= $1; }
3664 0           elsif (/\G (\Q$delimiter\E) /oxgc) { return $e . e_qq($ope,$delimiter,$delimiter,$qq_string); }
3665 0           elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3666             }
3667 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3668             }
3669             }
3670 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3671             }
3672             }
3673              
3674             # qr//
3675             elsif (/\G \b (qr) \b /oxgc) {
3676 0           my $ope = $1;
3677 0 0         if (/\G (\#) ((?:$qq_char)*?) (\#) ([imosxpadlubB]*) /oxgc) { # qr# # #
3678 0           return e_qr($ope,$1,$3,$2,$4);
3679             }
3680             else {
3681 0           my $e = '';
3682 0           while (not /\G \z/oxgc) {
3683 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
3684 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([imosxpadlubB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # qr ( )
3685 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([imosxpadlubB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # qr { }
3686 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([imosxpadlubB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # qr [ ]
3687 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([imosxpadlubB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # qr < >
3688 0           elsif (/\G (\') ((?:$qq_char)*?) (\') ([imosxpadlubB]*) /oxgc) { return $e . e_qr_q($ope,$1, $3, $2,$4); } # qr ' '
3689 0           elsif (/\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ([imosxpadlubB]*) /oxgc) { return $e . e_qr ($ope,'{','}',$2,$4); } # qr | | --> qr { }
3690 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([imosxpadlubB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # qr * *
3691             }
3692 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3693             }
3694             }
3695              
3696             # qw//
3697             elsif (/\G \b (qw) \b /oxgc) {
3698 0           my $ope = $1;
3699 0 0         if (/\G (\#) (.*?) (\#) /oxmsgc) { # qw# #
3700 0           return e_qw($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          
    0          
    0          
    0          
    0          
3706              
3707 0           elsif (/\G (\() ([^(]*?) (\)) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw ( )
3708 0           elsif (/\G (\() ((?:$q_paren)*?) (\)) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw ( )
3709              
3710 0           elsif (/\G (\{) ([^{]*?) (\}) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw { }
3711 0           elsif (/\G (\{) ((?:$q_brace)*?) (\}) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw { }
3712              
3713 0           elsif (/\G (\[) ([^[]*?) (\]) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw [ ]
3714 0           elsif (/\G (\[) ((?:$q_bracket)*?) (\]) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw [ ]
3715              
3716 0           elsif (/\G (\<) ([^<]*?) (\>) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw < >
3717 0           elsif (/\G (\<) ((?:$q_angle)*?) (\>) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw < >
3718              
3719 0           elsif (/\G ([\x21-\x3F]) (.*?) (\1) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw * *
3720 0           elsif (/\G (\S) ((?:$q_char)*?) (\1) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw * *
3721             }
3722 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3723             }
3724             }
3725              
3726             # qx//
3727             elsif (/\G \b (qx) \b /oxgc) {
3728 0           my $ope = $1;
3729 0 0         if (/\G (\#) ((?:$qq_char)*?) (\#) /oxgc) { # qx# #
3730 0           return e_qq($ope,$1,$3,$2);
3731             }
3732             else {
3733 0           my $e = '';
3734 0           while (not /\G \z/oxgc) {
3735 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
3736 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qx ( )
3737 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qx { }
3738 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qx [ ]
3739 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qx < >
3740 0           elsif (/\G (\') ((?:$qq_char)*?) (\') /oxgc) { return $e . e_q ($ope,$1,$3,$2); } # qx ' '
3741 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qx * *
3742             }
3743 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3744             }
3745             }
3746              
3747             # q//
3748             elsif (/\G \b (q) \b /oxgc) {
3749 0           my $ope = $1;
3750              
3751             # if (/\G (\#) ((?:\\\#|\\\\|$q_char)*?) (\#) /oxgc) { return e_q($ope,$1,$3,$2); } # q# #
3752              
3753             # avoid "Error: Runtime exception" of perl version 5.005_03
3754             # (and so on)
3755              
3756 0 0         if (/\G (\#) /oxgc) { # q# #
3757 0           my $q_string = '';
3758 0           while (not /\G \z/oxgc) {
3759 0 0         if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0          
    0          
    0          
3760 0           elsif (/\G (\\\#) /oxgc) { $q_string .= $1; }
3761 0           elsif (/\G (\#) /oxgc) { return e_q($ope,'#','#',$q_string); }
3762 0           elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3763             }
3764 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3765             }
3766              
3767             else {
3768 0           my $e = '';
3769 0           while (not /\G \z/oxgc) {
3770 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3771              
3772             # elsif (/\G (\() ((?:\\\)|\\\\|$q_paren)*?) (\)) /oxgc) { return $e . e_q($ope,$1,$3,$2); } # q ( )
3773             elsif (/\G (\() /oxgc) { # q ( )
3774 0           my $q_string = '';
3775 0           local $nest = 1;
3776 0           while (not /\G \z/oxgc) {
3777 0 0         if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3778 0           elsif (/\G (\\\)) /oxgc) { $q_string .= $1; }
3779 0           elsif (/\G (\\\() /oxgc) { $q_string .= $1; }
3780 0           elsif (/\G (\() /oxgc) { $q_string .= $1; $nest++; }
  0            
3781             elsif (/\G (\)) /oxgc) {
3782 0 0         if (--$nest == 0) { return $e . e_q($ope,'(',')',$q_string); }
  0            
3783 0           else { $q_string .= $1; }
3784             }
3785 0           elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3786             }
3787 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3788             }
3789              
3790             # elsif (/\G (\{) ((?:\\\}|\\\\|$q_brace)*?) (\}) /oxgc) { return $e . e_q($ope,$1,$3,$2); } # q { }
3791             elsif (/\G (\{) /oxgc) { # q { }
3792 0           my $q_string = '';
3793 0           local $nest = 1;
3794 0           while (not /\G \z/oxgc) {
3795 0 0         if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3796 0           elsif (/\G (\\\}) /oxgc) { $q_string .= $1; }
3797 0           elsif (/\G (\\\{) /oxgc) { $q_string .= $1; }
3798 0           elsif (/\G (\{) /oxgc) { $q_string .= $1; $nest++; }
  0            
3799             elsif (/\G (\}) /oxgc) {
3800 0 0         if (--$nest == 0) { return $e . e_q($ope,'{','}',$q_string); }
  0            
3801 0           else { $q_string .= $1; }
3802             }
3803 0           elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3804             }
3805 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3806             }
3807              
3808             # elsif (/\G (\[) ((?:\\\]|\\\\|$q_bracket)*?) (\]) /oxgc) { return $e . e_q($ope,$1,$3,$2); } # q [ ]
3809             elsif (/\G (\[) /oxgc) { # q [ ]
3810 0           my $q_string = '';
3811 0           local $nest = 1;
3812 0           while (not /\G \z/oxgc) {
3813 0 0         if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3814 0           elsif (/\G (\\\]) /oxgc) { $q_string .= $1; }
3815 0           elsif (/\G (\\\[) /oxgc) { $q_string .= $1; }
3816 0           elsif (/\G (\[) /oxgc) { $q_string .= $1; $nest++; }
  0            
3817             elsif (/\G (\]) /oxgc) {
3818 0 0         if (--$nest == 0) { return $e . e_q($ope,'[',']',$q_string); }
  0            
3819 0           else { $q_string .= $1; }
3820             }
3821 0           elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3822             }
3823 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3824             }
3825              
3826             # elsif (/\G (\<) ((?:\\\>|\\\\|$q_angle)*?) (\>) /oxgc) { return $e . e_q($ope,$1,$3,$2); } # q < >
3827             elsif (/\G (\<) /oxgc) { # q < >
3828 0           my $q_string = '';
3829 0           local $nest = 1;
3830 0           while (not /\G \z/oxgc) {
3831 0 0         if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0          
    0          
    0          
    0          
    0          
3832 0           elsif (/\G (\\\>) /oxgc) { $q_string .= $1; }
3833 0           elsif (/\G (\\\<) /oxgc) { $q_string .= $1; }
3834 0           elsif (/\G (\<) /oxgc) { $q_string .= $1; $nest++; }
  0            
3835             elsif (/\G (\>) /oxgc) {
3836 0 0         if (--$nest == 0) { return $e . e_q($ope,'<','>',$q_string); }
  0            
3837 0           else { $q_string .= $1; }
3838             }
3839 0           elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3840             }
3841 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3842             }
3843              
3844             # elsif (/\G (\S) ((?:\\\1|\\\\|$q_char)*?) (\1) /oxgc) { return $e . e_q($ope,$1,$3,$2); } # q * *
3845             elsif (/\G (\S) /oxgc) { # q * *
3846 0           my $delimiter = $1;
3847 0           my $q_string = '';
3848 0           while (not /\G \z/oxgc) {
3849 0 0         if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0          
    0          
    0          
3850 0           elsif (/\G (\\\Q$delimiter\E) /oxgc) { $q_string .= $1; }
3851 0           elsif (/\G (\Q$delimiter\E) /oxgc) { return $e . e_q($ope,$delimiter,$delimiter,$q_string); }
3852 0           elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3853             }
3854 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3855             }
3856             }
3857 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
3858             }
3859             }
3860              
3861             # m//
3862             elsif (/\G \b (m) \b /oxgc) {
3863 0           my $ope = $1;
3864 0 0         if (/\G (\#) ((?:$qq_char)*?) (\#) ([cgimosxpadlubB]*) /oxgc) { # m# #
3865 0           return e_qr($ope,$1,$3,$2,$4);
3866             }
3867             else {
3868 0           my $e = '';
3869 0           while (not /\G \z/oxgc) {
3870 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
3871 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cgimosxpadlubB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m ( )
3872 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cgimosxpadlubB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m { }
3873 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cgimosxpadlubB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m [ ]
3874 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cgimosxpadlubB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m < >
3875 0           elsif (/\G (\?) ((?:$qq_char)*?) (\?) ([cgimosxpadlubB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m ? ?
3876 0           elsif (/\G (\') ((?:$qq_char)*?) (\') ([cgimosxpadlubB]*) /oxgc) { return $e . e_qr_q($ope,$1, $3, $2,$4); } # m ' '
3877 0           elsif (/\G ([*\-:\\^|]) ((?:$qq_char)*?) (\1) ([cgimosxpadlubB]*) /oxgc) { return $e . e_qr ($ope,'{','}',$2,$4); } # m | | --> m { }
3878 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cgimosxpadlubB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m * *
3879             }
3880 0           die __FILE__, ": Search pattern not terminated";
3881             }
3882             }
3883              
3884             # s///
3885              
3886             # about [cegimosxpradlubB]* (/cg modifier)
3887             #
3888             # P.67 Pattern-Matching Operators
3889             # of ISBN 0-596-00241-6 Perl in a Nutshell, Second Edition.
3890              
3891             elsif (/\G \b (s) \b /oxgc) {
3892 0           my $ope = $1;
3893              
3894             # $1 $2 $3 $4 $5 $6
3895 0 0         if (/\G (\#) ((?:$qq_char)*?) (\#) ((?:$qq_char)*?) (\#) ([cegimosxpradlubB]*) /oxgc) { # s# # #
3896 0           return e_sub($sub_variable,$1,$2,$3,$3,$4,$5,$6);
3897             }
3898             else {
3899 0           my $e = '';
3900 0           while (not /\G \z/oxgc) {
3901 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
3902             elsif (/\G (\() ((?:$qq_paren)*?) (\)) /oxgc) {
3903 0           my @s = ($1,$2,$3);
3904 0           while (not /\G \z/oxgc) {
3905 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
3906             # $1 $2 $3 $4
3907 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3908 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3909 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3910 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3911 0           elsif (/\G (\') ((?:$qq_char)*?) (\') ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3912 0           elsif (/\G (\$) ((?:$qq_char)*?) (\$) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3913 0           elsif (/\G (\:) ((?:$qq_char)*?) (\:) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3914 0           elsif (/\G (\@) ((?:$qq_char)*?) (\@) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3915 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3916             }
3917 0           die __FILE__, ": Substitution replacement not terminated";
3918             }
3919             elsif (/\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) {
3920 0           my @s = ($1,$2,$3);
3921 0           while (not /\G \z/oxgc) {
3922 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
3923             # $1 $2 $3 $4
3924 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3925 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3926 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3927 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3928 0           elsif (/\G (\') ((?:$qq_char)*?) (\') ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3929 0           elsif (/\G (\$) ((?:$qq_char)*?) (\$) ([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 (\S) ((?:$qq_char)*?) (\1) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3933             }
3934 0           die __FILE__, ": Substitution replacement not terminated";
3935             }
3936             elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) {
3937 0           my @s = ($1,$2,$3);
3938 0           while (not /\G \z/oxgc) {
3939 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
3940             # $1 $2 $3 $4
3941 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3942 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3943 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3944 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3945 0           elsif (/\G (\') ((?:$qq_char)*?) (\') ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3946 0           elsif (/\G (\$) ((?:$qq_char)*?) (\$) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3947 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3948             }
3949 0           die __FILE__, ": Substitution replacement not terminated";
3950             }
3951             elsif (/\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) {
3952 0           my @s = ($1,$2,$3);
3953 0           while (not /\G \z/oxgc) {
3954 0 0         if (/\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
3955             # $1 $2 $3 $4
3956 0           elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3957 0           elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3958 0           elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3959 0           elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3960 0           elsif (/\G (\') ((?:$qq_char)*?) (\') ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3961 0           elsif (/\G (\$) ((?:$qq_char)*?) (\$) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3962 0           elsif (/\G (\:) ((?:$qq_char)*?) (\:) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3963 0           elsif (/\G (\@) ((?:$qq_char)*?) (\@) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3964 0           elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cegimosxpradlubB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3965             }
3966 0           die __FILE__, ": Substitution replacement not terminated";
3967             }
3968             # $1 $2 $3 $4 $5 $6
3969             elsif (/\G (\') ((?:$qq_char)*?) (\') ((?:$qq_char)*?) (\') ([cegimosxpradlubB]*) /oxgc) {
3970 0           return e_sub($sub_variable,$1,$2,$3,$3,$4,$5,$6);
3971             }
3972             # $1 $2 $3 $4 $5 $6
3973             elsif (/\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ((?:$qq_char)*?) (\1) ([cegimosxpradlubB]*) /oxgc) {
3974 0           return e_sub($sub_variable,'{',$2,'}','{',$4,'}',$6); # s | | | --> s { } { }
3975             }
3976             # $1 $2 $3 $4 $5 $6
3977             elsif (/\G (\$) ((?:$qq_char)*?) (\1) ((?:$qq_char)*?) (\1) ([cegimosxpradlubB]*) /oxgc) {
3978 0           return e_sub($sub_variable,$1,$2,$3,$3,$4,$5,$6);
3979             }
3980             # $1 $2 $3 $4 $5 $6
3981             elsif (/\G (\S) ((?:$qq_char)*?) (\1) ((?:$qq_char)*?) (\1) ([cegimosxpradlubB]*) /oxgc) {
3982 0           return e_sub($sub_variable,$1,$2,$3,$3,$4,$5,$6);
3983             }
3984             }
3985 0           die __FILE__, ": Substitution pattern not terminated";
3986             }
3987             }
3988              
3989             # require ignore module
3990 0           elsif (/\G \b require (\s+ (?:$ignore_modules) .*? ;) ([ \t]* [#\n]) /oxmsgc) { return "# require$1$2"; }
3991 0           elsif (/\G \b require (\s+ (?:$ignore_modules) .*? ;) ([ \t]* [^#]) /oxmsgc) { return "# require$1\n$2"; }
3992 0           elsif (/\G \b require (\s+ (?:$ignore_modules)) \b /oxmsgc) { return "# require$1"; }
3993              
3994             # use strict; --> use strict; no strict qw(refs);
3995 0           elsif (/\G \b use (\s+ strict .*? ;) ([ \t]* [#\n]) /oxmsgc) { return "use$1 no strict qw(refs);$2"; }
3996 0           elsif (/\G \b use (\s+ strict .*? ;) ([ \t]* [^#]) /oxmsgc) { return "use$1 no strict qw(refs);\n$2"; }
3997 0           elsif (/\G \b use (\s+ strict) \b /oxmsgc) { return "use$1; no strict qw(refs)"; }
3998              
3999             # use 5.12.0; --> use 5.12.0; no strict qw(refs);
4000             elsif (/\G \b use \s+ (([1-9][0-9_]*)(?:\.([0-9_]+))*) \s* ; /oxmsgc) {
4001 0 0 0       if (($2 >= 6) or (($2 == 5) and ($3 ge '012'))) {
      0        
4002 0           return "use $1; no strict qw(refs);";
4003             }
4004             else {
4005 0           return "use $1;";
4006             }
4007             }
4008             elsif (/\G \b use \s+ (v([0-9][0-9_]*)(?:\.([0-9_]+))*) \s* ; /oxmsgc) {
4009 0 0 0       if (($2 >= 6) or (($2 == 5) and ($3 >= 12))) {
      0        
4010 0           return "use $1; no strict qw(refs);";
4011             }
4012             else {
4013 0           return "use $1;";
4014             }
4015             }
4016              
4017             # ignore use module
4018 0           elsif (/\G \b use (\s+ (?:$ignore_modules) .*? ;) ([ \t]* [#\n]) /oxmsgc) { return "# use$1$2"; }
4019 0           elsif (/\G \b use (\s+ (?:$ignore_modules) .*? ;) ([ \t]* [^#]) /oxmsgc) { return "# use$1\n$2"; }
4020 0           elsif (/\G \b use (\s+ (?:$ignore_modules)) \b /oxmsgc) { return "# use$1"; }
4021              
4022             # ignore no module
4023 0           elsif (/\G \b no (\s+ (?:$ignore_modules) .*? ;) ([ \t]* [#\n]) /oxmsgc) { return "# no$1$2"; }
4024 0           elsif (/\G \b no (\s+ (?:$ignore_modules) .*? ;) ([ \t]* [^#]) /oxmsgc) { return "# no$1\n$2"; }
4025 0           elsif (/\G \b no (\s+ (?:$ignore_modules)) \b /oxmsgc) { return "# no$1"; }
4026              
4027             # use else
4028 0           elsif (/\G \b use \b /oxmsgc) { return "use"; }
4029              
4030             # use else
4031 0           elsif (/\G \b no \b /oxmsgc) { return "no"; }
4032              
4033             # ''
4034             elsif (/\G (?
4035 0           my $q_string = '';
4036 0           while (not /\G \z/oxgc) {
4037 0 0         if (/\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0          
    0          
    0          
4038 0           elsif (/\G (\\\') /oxgc) { $q_string .= $1; }
4039 0           elsif (/\G \' /oxgc) { return e_q('', "'","'",$q_string); }
4040 0           elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
4041             }
4042 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
4043             }
4044              
4045             # ""
4046             elsif (/\G (\") /oxgc) {
4047 0           my $qq_string = '';
4048 0           while (not /\G \z/oxgc) {
4049 0 0         if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0          
    0          
    0          
4050 0           elsif (/\G (\\\") /oxgc) { $qq_string .= $1; }
4051 0           elsif (/\G \" /oxgc) { return e_qq('', '"','"',$qq_string); }
4052 0           elsif (/\G ($q_char) /oxgc) { $qq_string .= $1; }
4053             }
4054 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
4055             }
4056              
4057             # ``
4058             elsif (/\G (\`) /oxgc) {
4059 0           my $qx_string = '';
4060 0           while (not /\G \z/oxgc) {
4061 0 0         if (/\G (\\\\) /oxgc) { $qx_string .= $1; }
  0 0          
    0          
    0          
4062 0           elsif (/\G (\\\`) /oxgc) { $qx_string .= $1; }
4063 0           elsif (/\G \` /oxgc) { return e_qq('', '`','`',$qx_string); }
4064 0           elsif (/\G ($q_char) /oxgc) { $qx_string .= $1; }
4065             }
4066 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
4067             }
4068              
4069             # // --- not divide operator (num / num), not defined-or
4070             elsif (($slash eq 'm//') and /\G (\/) /oxgc) {
4071 0           my $regexp = '';
4072 0           while (not /\G \z/oxgc) {
4073 0 0         if (/\G (\\\\) /oxgc) { $regexp .= $1; }
  0 0          
    0          
    0          
4074 0           elsif (/\G (\\\/) /oxgc) { $regexp .= $1; }
4075 0           elsif (/\G \/ ([cgimosxpadlubB]*) /oxgc) { return e_qr('', '/','/',$regexp,$1); }
4076 0           elsif (/\G ($q_char) /oxgc) { $regexp .= $1; }
4077             }
4078 0           die __FILE__, ": Search pattern not terminated";
4079             }
4080              
4081             # ?? --- not conditional operator (condition ? then : else)
4082             elsif (($slash eq 'm//') and /\G (\?) /oxgc) {
4083 0           my $regexp = '';
4084 0           while (not /\G \z/oxgc) {
4085 0 0         if (/\G (\\\\) /oxgc) { $regexp .= $1; }
  0 0          
    0          
    0          
4086 0           elsif (/\G (\\\?) /oxgc) { $regexp .= $1; }
4087 0           elsif (/\G \? ([cgimosxpadlubB]*) /oxgc) { return e_qr('m','?','?',$regexp,$1); }
4088 0           elsif (/\G ($q_char) /oxgc) { $regexp .= $1; }
4089             }
4090 0           die __FILE__, ": Search pattern not terminated";
4091             }
4092              
4093             # << (bit shift) --- not here document
4094 0           elsif (/\G ( << \s* ) (?= [0-9\$\@\&] ) /oxgc) { $slash = 'm//'; return $1; }
  0            
4095              
4096             # <<'HEREDOC'
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              
4119             # P.66 2.6.6. "Here" Documents
4120             # in Chapter 2: Bits and Pieces
4121             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
4122              
4123             # P.73 "Here" Documents
4124             # in Chapter 2: Bits and Pieces
4125             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
4126              
4127             elsif (/\G ( << \\([a-zA-Z_0-9]+) ) /oxgc) {
4128 0           $slash = 'm//';
4129 0           my $here_quote = $1;
4130 0           my $delimiter = $2;
4131              
4132             # get here document
4133 0 0         if ($here_script eq '') {
4134 0           $here_script = CORE::substr $_, pos $_;
4135 0           $here_script =~ s/.*?\n//oxm;
4136             }
4137 0 0         if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4138 0           push @heredoc, $1 . qq{\n$delimiter\n};
4139 0           push @heredoc_delimiter, $delimiter;
4140             }
4141             else {
4142 0           die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF";
4143             }
4144 0           return $here_quote;
4145             }
4146              
4147             # <<"HEREDOC"
4148             elsif (/\G ( << "([a-zA-Z_0-9]*)" ) /oxgc) {
4149 0           $slash = 'm//';
4150 0           my $here_quote = $1;
4151 0           my $delimiter = $2;
4152              
4153             # get here document
4154 0 0         if ($here_script eq '') {
4155 0           $here_script = CORE::substr $_, pos $_;
4156 0           $here_script =~ s/.*?\n//oxm;
4157             }
4158 0 0         if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4159 0           push @heredoc, e_heredoc($1) . qq{\n$delimiter\n};
4160 0           push @heredoc_delimiter, $delimiter;
4161             }
4162             else {
4163 0           die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF";
4164             }
4165 0           return $here_quote;
4166             }
4167              
4168             # <
4169             elsif (/\G ( << ([a-zA-Z_0-9]+) ) /oxgc) {
4170 0           $slash = 'm//';
4171 0           my $here_quote = $1;
4172 0           my $delimiter = $2;
4173              
4174             # get here document
4175 0 0         if ($here_script eq '') {
4176 0           $here_script = CORE::substr $_, pos $_;
4177 0           $here_script =~ s/.*?\n//oxm;
4178             }
4179 0 0         if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4180 0           push @heredoc, e_heredoc($1) . qq{\n$delimiter\n};
4181 0           push @heredoc_delimiter, $delimiter;
4182             }
4183             else {
4184 0           die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF";
4185             }
4186 0           return $here_quote;
4187             }
4188              
4189             # <<`HEREDOC`
4190             elsif (/\G ( << `([a-zA-Z_0-9]*)` ) /oxgc) {
4191 0           $slash = 'm//';
4192 0           my $here_quote = $1;
4193 0           my $delimiter = $2;
4194              
4195             # get here document
4196 0 0         if ($here_script eq '') {
4197 0           $here_script = CORE::substr $_, pos $_;
4198 0           $here_script =~ s/.*?\n//oxm;
4199             }
4200 0 0         if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4201 0           push @heredoc, e_heredoc($1) . qq{\n$delimiter\n};
4202 0           push @heredoc_delimiter, $delimiter;
4203             }
4204             else {
4205 0           die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF";
4206             }
4207 0           return $here_quote;
4208             }
4209              
4210             # <<= <=> <= < operator
4211             elsif (/\G ( <<= | <=> | <= | < ) (?= \s* [A-Za-z_0-9'"`\$\@\&\*\(\+\-] )/oxgc) {
4212 0           return $1;
4213             }
4214              
4215             #
4216             elsif (/\G (<[\$]?[A-Za-z_][A-Za-z_0-9]*>) /oxgc) {
4217 0           return $1;
4218             }
4219              
4220             # --- glob
4221              
4222             # avoid "Error: Runtime exception" of perl version 5.005_03
4223              
4224             elsif (/\G < ((?:[^>\0\a\e\f\n\r\t])+?) > /oxgc) {
4225 0           return 'Char::Elatin4::glob("' . $1 . '")';
4226             }
4227              
4228             # __DATA__
4229 0           elsif (/\G ^ ( __DATA__ \n .*) \z /oxmsgc) { return $1; }
4230              
4231             # __END__
4232 0           elsif (/\G ^ ( __END__ \n .*) \z /oxmsgc) { return $1; }
4233              
4234             # \cD Control-D
4235              
4236             # P.68 2.6.8. Other Literal Tokens
4237             # in Chapter 2: Bits and Pieces
4238             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
4239              
4240             # P.76 Other Literal Tokens
4241             # in Chapter 2: Bits and Pieces
4242             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
4243              
4244 0           elsif (/\G ( \cD .*) \z /oxmsgc) { return $1; }
4245              
4246             # \cZ Control-Z
4247 0           elsif (/\G ( \cZ .*) \z /oxmsgc) { return $1; }
4248              
4249             # any operator before div
4250             elsif (/\G (
4251             -- | \+\+ |
4252             [\)\}\]]
4253              
4254 0           ) /oxgc) { $slash = 'div'; return $1; }
  0            
4255              
4256             # yada-yada or triple-dot operator
4257             elsif (/\G (
4258             \.\.\.
4259              
4260 0           ) /oxgc) { $slash = 'm//'; return q{die('Unimplemented')}; }
  0            
4261              
4262             # any operator before m//
4263              
4264             # //, //= (defined-or)
4265              
4266             # P.164 Logical Operators
4267             # in Chapter 10: More Control Structures
4268             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
4269              
4270             # P.119 C-Style Logical (Short-Circuit) Operators
4271             # in Chapter 3: Unary and Binary Operators
4272             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
4273              
4274             # (and so on)
4275              
4276             # ~~
4277              
4278             # P.221 The Smart Match Operator
4279             # in Chapter 15: Smart Matching and given-when
4280             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
4281              
4282             # P.112 Smartmatch Operator
4283             # in Chapter 3: Unary and Binary Operators
4284             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
4285              
4286             # (and so on)
4287              
4288             elsif (/\G (
4289              
4290             !~~ | !~ | != | ! |
4291             %= | % |
4292             &&= | && | &= | & |
4293             -= | -> | - |
4294             :\s*= |
4295             : |
4296             <<= | <=> | <= | < |
4297             == | => | =~ | = |
4298             >>= | >> | >= | > |
4299             \*\*= | \*\* | \*= | \* |
4300             \+= | \+ |
4301             \.\. | \.= | \. |
4302             \/\/= | \/\/ |
4303             \/= | \/ |
4304             \? |
4305             \\ |
4306             \^= | \^ |
4307             \b x= |
4308             \|\|= | \|\| | \|= | \| |
4309             ~~ | ~ |
4310             \b(?: and | cmp | eq | ge | gt | le | lt | ne | not | or | xor | x )\b |
4311             \b(?: print )\b |
4312              
4313             [,;\(\{\[]
4314              
4315 0           ) /oxgc) { $slash = 'm//'; return $1; }
  0            
4316              
4317             # other any character
4318 0           elsif (/\G ($q_char) /oxgc) { $slash = 'div'; return $1; }
  0            
4319              
4320             # system error
4321             else {
4322 0           die __FILE__, ": Oops, this shouldn't happen!";
4323             }
4324             }
4325              
4326             # escape Latin-4 string
4327             sub e_string {
4328 0     0 0   my($string) = @_;
4329 0           my $e_string = '';
4330              
4331 0           local $slash = 'm//';
4332              
4333             # P.1024 Appendix W.10 Multibyte Processing
4334             # of ISBN 1-56592-224-7 CJKV Information Processing
4335             # (and so on)
4336              
4337 0           my @char = $string =~ / \G (\\?(?:$q_char)) /oxmsg;
4338              
4339             # without { ... }
4340 0 0 0       if (not (grep(/\A \{ \z/xms, @char) and grep(/\A \} \z/xms, @char))) {
4341 0 0         if ($string !~ /<
4342 0           return $string;
4343             }
4344             }
4345              
4346             E_STRING_LOOP:
4347 0           while ($string !~ /\G \z/oxgc) {
4348 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          
4349             }
4350              
4351             # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> @{[Char::Elatin4::PREMATCH()]}
4352 0           elsif ($string =~ /\G ( \$` | \$\{`\} | \$ \s* PREMATCH \b | \$ \s* \{ \s* PREMATCH \s* \} | \$ \s* \{\^PREMATCH\} ) /oxmsgc) {
4353 0           $e_string .= q{Char::Elatin4::PREMATCH()};
4354 0           $slash = 'div';
4355             }
4356              
4357             # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> @{[Char::Elatin4::MATCH()]}
4358             elsif ($string =~ /\G ( \$& | \$\{&\} | \$ \s* MATCH \b | \$ \s* \{ \s* MATCH \s* \} | \$ \s* \{\^MATCH\} ) /oxmsgc) {
4359 0           $e_string .= q{Char::Elatin4::MATCH()};
4360 0           $slash = 'div';
4361             }
4362              
4363             # $', ${'} --> $', ${'}
4364             elsif ($string =~ /\G ( \$' | \$\{'\} ) /oxmsgc) {
4365 0           $e_string .= $1;
4366 0           $slash = 'div';
4367             }
4368              
4369             # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> @{[Char::Elatin4::POSTMATCH()]}
4370             elsif ($string =~ /\G ( \$ \s* POSTMATCH \b | \$ \s* \{ \s* POSTMATCH \s* \} | \$ \s* \{\^POSTMATCH\} ) /oxmsgc) {
4371 0           $e_string .= q{Char::Elatin4::POSTMATCH()};
4372 0           $slash = 'div';
4373             }
4374              
4375             # bareword
4376             elsif ($string =~ /\G ( \{ \s* (?: tr | index | rindex | reverse ) \s* \} ) /oxmsgc) {
4377 0           $e_string .= $1;
4378 0           $slash = 'div';
4379             }
4380              
4381             # $0 --> $0
4382             elsif ($string =~ /\G ( \$ 0 ) /oxmsgc) {
4383 0           $e_string .= $1;
4384 0           $slash = 'div';
4385             }
4386             elsif ($string =~ /\G ( \$ \{ \s* 0 \s* \} ) /oxmsgc) {
4387 0           $e_string .= $1;
4388 0           $slash = 'div';
4389             }
4390              
4391             # $$ --> $$
4392             elsif ($string =~ /\G ( \$ \$ ) (?![\w\{]) /oxmsgc) {
4393 0           $e_string .= $1;
4394 0           $slash = 'div';
4395             }
4396              
4397             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
4398             # $1, $2, $3 --> $1, $2, $3 otherwise
4399             elsif ($string =~ /\G \$ ([1-9][0-9]*) /oxmsgc) {
4400 0           $e_string .= e_capture($1);
4401 0           $slash = 'div';
4402             }
4403             elsif ($string =~ /\G \$ \{ \s* ([1-9][0-9]*) \s* \} /oxmsgc) {
4404 0           $e_string .= e_capture($1);
4405 0           $slash = 'div';
4406             }
4407              
4408             # $$foo[ ... ] --> $ $foo->[ ... ]
4409             elsif ($string =~ /\G \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) ( \[ .+? \] ) /oxmsgc) {
4410 0           $e_string .= e_capture($1.'->'.$2);
4411 0           $slash = 'div';
4412             }
4413              
4414             # $$foo{ ... } --> $ $foo->{ ... }
4415             elsif ($string =~ /\G \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) ( \{ .+? \} ) /oxmsgc) {
4416 0           $e_string .= e_capture($1.'->'.$2);
4417 0           $slash = 'div';
4418             }
4419              
4420             # $$foo
4421             elsif ($string =~ /\G \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) /oxmsgc) {
4422 0           $e_string .= e_capture($1);
4423 0           $slash = 'div';
4424             }
4425              
4426             # ${ foo }
4427             elsif ($string =~ /\G \$ \s* \{ ( \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* ) \} /oxmsgc) {
4428 0           $e_string .= '${' . $1 . '}';
4429 0           $slash = 'div';
4430             }
4431              
4432             # ${ ... }
4433             elsif ($string =~ /\G \$ \s* \{ \s* ( $qq_brace ) \s* \} /oxmsgc) {
4434 0           $e_string .= e_capture($1);
4435 0           $slash = 'div';
4436             }
4437              
4438             # variable or function
4439             # $ @ % & * $ #
4440             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) {
4441 0           $e_string .= $1;
4442 0           $slash = 'div';
4443             }
4444             # $ $ $ $ $ $ $ $ $ $ $ $ $ $
4445             # $ @ # \ ' " / ? ( ) [ ] < >
4446             elsif ($string =~ /\G ( \$[\$\@\#\\\'\"\/\?\(\)\[\]\<\>] ) /oxmsgc) {
4447 0           $e_string .= $1;
4448 0           $slash = 'div';
4449             }
4450              
4451             # subroutines of package Char::Elatin4
4452 0           elsif ($string =~ /\G \b (CORE:: | ->[ ]* (?: atan2 | [a-z]{2,})) \b /oxgc) { $e_string .= $1; $slash = 'm//'; }
  0            
4453 0           elsif ($string =~ /\G \b Char::Latin4::eval (?= \s* \{ ) /oxgc) { $e_string .= 'eval'; $slash = 'm//'; }
  0            
4454 0           elsif ($string =~ /\G \b Char::Latin4::eval \b /oxgc) { $e_string .= 'eval Char::Latin4::escape'; $slash = 'm//'; }
  0            
4455 0           elsif ($string =~ /\G \b bytes::substr \b /oxgc) { $e_string .= 'substr'; $slash = 'm//'; }
  0            
4456 0           elsif ($string =~ /\G \b chop \b /oxgc) { $e_string .= 'Char::Elatin4::chop'; $slash = 'm//'; }
  0            
4457 0           elsif ($string =~ /\G \b bytes::index \b /oxgc) { $e_string .= 'index'; $slash = 'm//'; }
  0            
4458 0           elsif ($string =~ /\G \b Char::Latin4::index \b /oxgc) { $e_string .= 'Char::Latin4::index'; $slash = 'm//'; }
  0            
4459 0           elsif ($string =~ /\G \b index \b /oxgc) { $e_string .= 'Char::Elatin4::index'; $slash = 'm//'; }
  0            
4460 0           elsif ($string =~ /\G \b bytes::rindex \b /oxgc) { $e_string .= 'rindex'; $slash = 'm//'; }
  0            
4461 0           elsif ($string =~ /\G \b Char::Latin4::rindex \b /oxgc) { $e_string .= 'Char::Latin4::rindex'; $slash = 'm//'; }
  0            
4462 0           elsif ($string =~ /\G \b rindex \b /oxgc) { $e_string .= 'Char::Elatin4::rindex'; $slash = 'm//'; }
  0            
4463 0           elsif ($string =~ /\G \b lc (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Char::Elatin4::lc'; $slash = 'm//'; }
  0            
4464 0           elsif ($string =~ /\G \b lcfirst (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Char::Elatin4::lcfirst'; $slash = 'm//'; }
  0            
4465 0           elsif ($string =~ /\G \b uc (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Char::Elatin4::uc'; $slash = 'm//'; }
  0            
4466 0           elsif ($string =~ /\G \b ucfirst (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Char::Elatin4::ucfirst'; $slash = 'm//'; }
  0            
4467 0           elsif ($string =~ /\G \b fc (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Char::Elatin4::fc'; $slash = 'm//'; }
  0            
4468              
4469             # "-s '' ..." means file test "-s 'filename' ..." (not means "- s/// ...")
4470 0           elsif ($string =~ /\G -s \s+ \s* (\") ((?:$qq_char)+?) (\") /oxgc) { $e_string .= '-s ' . e_qq('', $1,$3,$2); $slash = 'm//'; }
  0            
4471 0           elsif ($string =~ /\G -s \s+ qq \s* (\#) ((?:$qq_char)+?) (\#) /oxgc) { $e_string .= '-s ' . e_qq('qq',$1,$3,$2); $slash = 'm//'; }
  0            
4472 0           elsif ($string =~ /\G -s \s+ qq \s* (\() ((?:$qq_paren)+?) (\)) /oxgc) { $e_string .= '-s ' . e_qq('qq',$1,$3,$2); $slash = 'm//'; }
  0            
4473 0           elsif ($string =~ /\G -s \s+ qq \s* (\{) ((?:$qq_brace)+?) (\}) /oxgc) { $e_string .= '-s ' . e_qq('qq',$1,$3,$2); $slash = 'm//'; }
  0            
4474 0           elsif ($string =~ /\G -s \s+ qq \s* (\[) ((?:$qq_bracket)+?) (\]) /oxgc) { $e_string .= '-s ' . e_qq('qq',$1,$3,$2); $slash = 'm//'; }
  0            
4475 0           elsif ($string =~ /\G -s \s+ qq \s* (\<) ((?:$qq_angle)+?) (\>) /oxgc) { $e_string .= '-s ' . e_qq('qq',$1,$3,$2); $slash = 'm//'; }
  0            
4476 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            
4477              
4478 0           elsif ($string =~ /\G -s \s+ \s* (\') ((?:\\\'|\\\\|$q_char)+?) (\') /oxgc) { $e_string .= '-s ' . e_q ('', $1,$3,$2); $slash = 'm//'; }
  0            
4479 0           elsif ($string =~ /\G -s \s+ q \s* (\#) ((?:\\\#|\\\\|$q_char)+?) (\#) /oxgc) { $e_string .= '-s ' . e_q ('q', $1,$3,$2); $slash = 'm//'; }
  0            
4480 0           elsif ($string =~ /\G -s \s+ q \s* (\() ((?:\\\)|\\\\|$q_paren)+?) (\)) /oxgc) { $e_string .= '-s ' . e_q ('q', $1,$3,$2); $slash = 'm//'; }
  0            
4481 0           elsif ($string =~ /\G -s \s+ q \s* (\{) ((?:\\\}|\\\\|$q_brace)+?) (\}) /oxgc) { $e_string .= '-s ' . e_q ('q', $1,$3,$2); $slash = 'm//'; }
  0            
4482 0           elsif ($string =~ /\G -s \s+ q \s* (\[) ((?:\\\]|\\\\|$q_bracket)+?) (\]) /oxgc) { $e_string .= '-s ' . e_q ('q', $1,$3,$2); $slash = 'm//'; }
  0            
4483 0           elsif ($string =~ /\G -s \s+ q \s* (\<) ((?:\\\>|\\\\|$q_angle)+?) (\>) /oxgc) { $e_string .= '-s ' . e_q ('q', $1,$3,$2); $slash = 'm//'; }
  0            
4484 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            
4485              
4486             elsif ($string =~ /\G -s \s* (\$ \w+(?: ::\w+)* (?: (?: ->)? (?: [\$\@\%\&\*]\* | \$\#\* | \( (?:$qq_paren)*? \) | [\@\%\*]? \{ (?:$qq_brace)+? \} | [\@\%]? \[ (?:$qq_bracket)+? \] ) )*) /oxgc)
4487 0           { $e_string .= "-s $1"; $slash = 'm//'; }
  0            
4488 0           elsif ($string =~ /\G -s \s* \( ((?:$qq_paren)*?) \) /oxgc) { $e_string .= "-s ($1)"; $slash = 'm//'; }
  0            
4489 0           elsif ($string =~ /\G -s (?= \s+ [a-z]+) /oxgc) { $e_string .= '-s'; $slash = 'm//'; }
  0            
4490 0           elsif ($string =~ /\G -s \s+ (\w+) /oxgc) { $e_string .= "-s $1"; $slash = 'm//'; }
  0            
4491              
4492 0           elsif ($string =~ /\G \b bytes::length (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'length'; $slash = 'm//'; }
  0            
4493 0           elsif ($string =~ /\G \b bytes::chr (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'chr'; $slash = 'm//'; }
  0            
4494 0           elsif ($string =~ /\G \b chr (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Char::Elatin4::chr'; $slash = 'm//'; }
  0            
4495 0           elsif ($string =~ /\G \b bytes::ord (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'ord'; $slash = 'div'; }
  0            
4496 0           elsif ($string =~ /\G \b ord (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $e_string .= $function_ord; $slash = 'div'; }
  0            
4497 0           elsif ($string =~ /\G \b glob (?= \s+[A-Za-z_]|\s*['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Char::Elatin4::glob'; $slash = 'm//'; }
  0            
4498 0           elsif ($string =~ /\G \b lc \b /oxgc) { $e_string .= 'Char::Elatin4::lc_'; $slash = 'm//'; }
  0            
4499 0           elsif ($string =~ /\G \b lcfirst \b /oxgc) { $e_string .= 'Char::Elatin4::lcfirst_'; $slash = 'm//'; }
  0            
4500 0           elsif ($string =~ /\G \b uc \b /oxgc) { $e_string .= 'Char::Elatin4::uc_'; $slash = 'm//'; }
  0            
4501 0           elsif ($string =~ /\G \b ucfirst \b /oxgc) { $e_string .= 'Char::Elatin4::ucfirst_'; $slash = 'm//'; }
  0            
4502 0           elsif ($string =~ /\G \b fc \b /oxgc) { $e_string .= 'Char::Elatin4::fc_'; $slash = 'm//'; }
  0            
4503 0           elsif ($string =~ /\G -s \b /oxgc) { $e_string .= '-s '; $slash = 'm//'; }
  0            
4504              
4505 0           elsif ($string =~ /\G \b bytes::length \b /oxgc) { $e_string .= 'length'; $slash = 'm//'; }
  0            
4506 0           elsif ($string =~ /\G \b bytes::chr \b /oxgc) { $e_string .= 'chr'; $slash = 'm//'; }
  0            
4507 0           elsif ($string =~ /\G \b chr \b /oxgc) { $e_string .= 'Char::Elatin4::chr_'; $slash = 'm//'; }
  0            
4508 0           elsif ($string =~ /\G \b bytes::ord \b /oxgc) { $e_string .= 'ord'; $slash = 'div'; }
  0            
4509 0           elsif ($string =~ /\G \b ord \b /oxgc) { $e_string .= $function_ord_; $slash = 'div'; }
  0            
4510 0           elsif ($string =~ /\G \b glob \b /oxgc) { $e_string .= 'Char::Elatin4::glob_'; $slash = 'm//'; }
  0            
4511 0           elsif ($string =~ /\G \b reverse \b /oxgc) { $e_string .= $function_reverse; $slash = 'm//'; }
  0            
4512 0           elsif ($string =~ /\G \b getc \b /oxgc) { $e_string .= $function_getc; $slash = 'm//'; }
  0            
4513             # split
4514             elsif ($string =~ /\G \b (split) \b (?! \s* => ) /oxgc) {
4515 0           $slash = 'm//';
4516              
4517 0           my $e = '';
4518 0           while ($string =~ /\G ( \s+ | \( | \#.* ) /oxgc) {
4519 0           $e .= $1;
4520             }
4521              
4522             # end of split
4523 0 0         if ($string =~ /\G (?= [,;\)\}\]] ) /oxgc) { return 'Char::Elatin4::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          
4524              
4525             # split scalar value
4526 0           elsif ($string =~ /\G ( [\$\@\&\*] $qq_scalar ) /oxgc) { $e_string .= 'Char::Elatin4::split' . $e . e_string($1); next E_STRING_LOOP; }
  0            
4527              
4528             # split literal space
4529 0           elsif ($string =~ /\G \b qq (\#) [ ] (\#) /oxgc) { $e_string .= 'Char::Elatin4::split' . $e . qq {qq$1 $2}; next E_STRING_LOOP; }
  0            
4530 0           elsif ($string =~ /\G \b qq (\s*) (\() [ ] (\)) /oxgc) { $e_string .= 'Char::Elatin4::split' . $e . qq{$1qq$2 $3}; next E_STRING_LOOP; }
  0            
4531 0           elsif ($string =~ /\G \b qq (\s*) (\{) [ ] (\}) /oxgc) { $e_string .= 'Char::Elatin4::split' . $e . qq{$1qq$2 $3}; next E_STRING_LOOP; }
  0            
4532 0           elsif ($string =~ /\G \b qq (\s*) (\[) [ ] (\]) /oxgc) { $e_string .= 'Char::Elatin4::split' . $e . qq{$1qq$2 $3}; next E_STRING_LOOP; }
  0            
4533 0           elsif ($string =~ /\G \b qq (\s*) (\<) [ ] (\>) /oxgc) { $e_string .= 'Char::Elatin4::split' . $e . qq{$1qq$2 $3}; next E_STRING_LOOP; }
  0            
4534 0           elsif ($string =~ /\G \b qq (\s*) (\S) [ ] (\2) /oxgc) { $e_string .= 'Char::Elatin4::split' . $e . qq{$1qq$2 $3}; next E_STRING_LOOP; }
  0            
4535 0           elsif ($string =~ /\G \b q (\#) [ ] (\#) /oxgc) { $e_string .= 'Char::Elatin4::split' . $e . qq {q$1 $2}; next E_STRING_LOOP; }
  0            
4536 0           elsif ($string =~ /\G \b q (\s*) (\() [ ] (\)) /oxgc) { $e_string .= 'Char::Elatin4::split' . $e . qq {$1q$2 $3}; next E_STRING_LOOP; }
  0            
4537 0           elsif ($string =~ /\G \b q (\s*) (\{) [ ] (\}) /oxgc) { $e_string .= 'Char::Elatin4::split' . $e . qq {$1q$2 $3}; next E_STRING_LOOP; }
  0            
4538 0           elsif ($string =~ /\G \b q (\s*) (\[) [ ] (\]) /oxgc) { $e_string .= 'Char::Elatin4::split' . $e . qq {$1q$2 $3}; next E_STRING_LOOP; }
  0            
4539 0           elsif ($string =~ /\G \b q (\s*) (\<) [ ] (\>) /oxgc) { $e_string .= 'Char::Elatin4::split' . $e . qq {$1q$2 $3}; next E_STRING_LOOP; }
  0            
4540 0           elsif ($string =~ /\G \b q (\s*) (\S) [ ] (\2) /oxgc) { $e_string .= 'Char::Elatin4::split' . $e . qq {$1q$2 $3}; next E_STRING_LOOP; }
  0            
4541 0           elsif ($string =~ /\G ' [ ] ' /oxgc) { $e_string .= 'Char::Elatin4::split' . $e . qq {' '}; next E_STRING_LOOP; }
  0            
4542 0           elsif ($string =~ /\G " [ ] " /oxgc) { $e_string .= 'Char::Elatin4::split' . $e . qq {" "}; next E_STRING_LOOP; }
  0            
4543              
4544             # split qq//
4545             elsif ($string =~ /\G \b (qq) \b /oxgc) {
4546 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            
4547             else {
4548 0           while ($string !~ /\G \z/oxgc) {
4549 0 0         if ($string =~ /\G (\s+|\#.*) /oxgc) { $e_string .= $e . $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
4550 0           elsif ($string =~ /\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { $e_string .= e_split($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # qq ( ) --> qr ( )
  0            
4551 0           elsif ($string =~ /\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { $e_string .= e_split($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # qq { } --> qr { }
  0            
4552 0           elsif ($string =~ /\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { $e_string .= e_split($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # qq [ ] --> qr [ ]
  0            
4553 0           elsif ($string =~ /\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { $e_string .= e_split($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # qq < > --> qr < >
  0            
4554 0           elsif ($string =~ /\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) /oxgc) { $e_string .= e_split($e.'qr','{','}',$2,''); next E_STRING_LOOP; } # qq | | --> qr { }
  0            
4555 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            
4556             }
4557 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
4558             }
4559             }
4560              
4561             # split qr//
4562             elsif ($string =~ /\G \b (qr) \b /oxgc) {
4563 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            
4564             else {
4565 0           while ($string !~ /\G \z/oxgc) {
4566 0 0         if ($string =~ /\G (\s+|\#.*) /oxgc) { $e_string .= $e . $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
4567 0           elsif ($string =~ /\G (\() ((?:$qq_paren)*?) (\)) ([imosxpadlubB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # qr ( )
  0            
4568 0           elsif ($string =~ /\G (\{) ((?:$qq_brace)*?) (\}) ([imosxpadlubB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # qr { }
  0            
4569 0           elsif ($string =~ /\G (\[) ((?:$qq_bracket)*?) (\]) ([imosxpadlubB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # qr [ ]
  0            
4570 0           elsif ($string =~ /\G (\<) ((?:$qq_angle)*?) (\>) ([imosxpadlubB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # qr < >
  0            
4571 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            
4572 0           elsif ($string =~ /\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ([imosxpadlubB]*) /oxgc) { $e_string .= e_split ($e.'qr','{','}',$2,$4); next E_STRING_LOOP; } # qr | | --> qr { }
  0            
4573 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            
4574             }
4575 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
4576             }
4577             }
4578              
4579             # split q//
4580             elsif ($string =~ /\G \b (q) \b /oxgc) {
4581 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            
4582             else {
4583 0           while ($string !~ /\G \z/oxgc) {
4584 0 0         if ($string =~ /\G (\s+|\#.*) /oxgc) { $e_string .= $e . $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
4585 0           elsif ($string =~ /\G (\() ((?:\\\\|\\\)|\\\(|$q_paren)*?) (\)) /oxgc) { $e_string .= e_split_q($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # q ( ) --> qr ( )
  0            
4586 0           elsif ($string =~ /\G (\{) ((?:\\\\|\\\}|\\\{|$q_brace)*?) (\}) /oxgc) { $e_string .= e_split_q($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # q { } --> qr { }
  0            
4587 0           elsif ($string =~ /\G (\[) ((?:\\\\|\\\]|\\\[|$q_bracket)*?) (\]) /oxgc) { $e_string .= e_split_q($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # q [ ] --> qr [ ]
  0            
4588 0           elsif ($string =~ /\G (\<) ((?:\\\\|\\\>|\\\<|$q_angle)*?) (\>) /oxgc) { $e_string .= e_split_q($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # q < > --> qr < >
  0            
4589 0           elsif ($string =~ /\G ([*\-:?\\^|]) ((?:$q_char)*?) (\1) /oxgc) { $e_string .= e_split_q($e.'qr','{','}',$2,''); next E_STRING_LOOP; } # q | | --> qr { }
  0            
4590 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            
4591             }
4592 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
4593             }
4594             }
4595              
4596             # split m//
4597             elsif ($string =~ /\G \b (m) \b /oxgc) {
4598 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            
4599             else {
4600 0           while ($string !~ /\G \z/oxgc) {
4601 0 0         if ($string =~ /\G (\s+|\#.*) /oxgc) { $e_string .= $e . $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
4602 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            
4603 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            
4604 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            
4605 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            
4606 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            
4607 0           elsif ($string =~ /\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ([cgimosxpadlubB]*) /oxgc) { $e_string .= e_split ($e.'qr','{','}',$2,$4); next E_STRING_LOOP; } # m | | --> qr { }
  0            
4608 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            
4609             }
4610 0           die __FILE__, ": Search pattern not terminated";
4611             }
4612             }
4613              
4614             # split ''
4615             elsif ($string =~ /\G (\') /oxgc) {
4616 0           my $q_string = '';
4617 0           while ($string !~ /\G \z/oxgc) {
4618 0 0         if ($string =~ /\G (\\\\) /oxgc) { $q_string .= $1; }
  0 0          
    0          
    0          
4619 0           elsif ($string =~ /\G (\\\') /oxgc) { $q_string .= $1; } # splitqr'' --> split qr''
4620 0           elsif ($string =~ /\G \' /oxgc) { $e_string .= e_split_q($e.q{ qr},"'","'",$q_string,''); next E_STRING_LOOP; } # ' ' --> qr ' '
  0            
4621 0           elsif ($string =~ /\G ($q_char) /oxgc) { $q_string .= $1; }
4622             }
4623 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
4624             }
4625              
4626             # split ""
4627             elsif ($string =~ /\G (\") /oxgc) {
4628 0           my $qq_string = '';
4629 0           while ($string !~ /\G \z/oxgc) {
4630 0 0         if ($string =~ /\G (\\\\) /oxgc) { $qq_string .= $1; }
  0 0          
    0          
    0          
4631 0           elsif ($string =~ /\G (\\\") /oxgc) { $qq_string .= $1; } # splitqr"" --> split qr""
4632 0           elsif ($string =~ /\G \" /oxgc) { $e_string .= e_split($e.q{ qr},'"','"',$qq_string,''); next E_STRING_LOOP; } # " " --> qr " "
  0            
4633 0           elsif ($string =~ /\G ($q_char) /oxgc) { $qq_string .= $1; }
4634             }
4635 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
4636             }
4637              
4638             # split //
4639             elsif ($string =~ /\G (\/) /oxgc) {
4640 0           my $regexp = '';
4641 0           while ($string !~ /\G \z/oxgc) {
4642 0 0         if ($string =~ /\G (\\\\) /oxgc) { $regexp .= $1; }
  0 0          
    0          
    0          
4643 0           elsif ($string =~ /\G (\\\/) /oxgc) { $regexp .= $1; } # splitqr// --> split qr//
4644 0           elsif ($string =~ /\G \/ ([cgimosxpadlubB]*) /oxgc) { $e_string .= e_split($e.q{ qr}, '/','/',$regexp,$1); next E_STRING_LOOP; } # / / --> qr / /
  0            
4645 0           elsif ($string =~ /\G ($q_char) /oxgc) { $regexp .= $1; }
4646             }
4647 0           die __FILE__, ": Search pattern not terminated";
4648             }
4649             }
4650              
4651             # qq//
4652             elsif ($string =~ /\G \b (qq) \b /oxgc) {
4653 0           my $ope = $1;
4654 0 0         if ($string =~ /\G (\#) ((?:$qq_char)*?) (\#) /oxgc) { # qq# #
4655 0           $e_string .= e_qq($ope,$1,$3,$2);
4656             }
4657             else {
4658 0           my $e = '';
4659 0           while ($string !~ /\G \z/oxgc) {
4660 0 0         if ($string =~ /\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
4661 0           elsif ($string =~ /\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qq ( )
  0            
4662 0           elsif ($string =~ /\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qq { }
  0            
4663 0           elsif ($string =~ /\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qq [ ]
  0            
4664 0           elsif ($string =~ /\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qq < >
  0            
4665 0           elsif ($string =~ /\G (\S) ((?:$qq_char)*?) (\1) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qq * *
  0            
4666             }
4667 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
4668             }
4669             }
4670              
4671             # qx//
4672             elsif ($string =~ /\G \b (qx) \b /oxgc) {
4673 0           my $ope = $1;
4674 0 0         if ($string =~ /\G (\#) ((?:$qq_char)*?) (\#) /oxgc) { # qx# #
4675 0           $e_string .= e_qq($ope,$1,$3,$2);
4676             }
4677             else {
4678 0           my $e = '';
4679 0           while ($string !~ /\G \z/oxgc) {
4680 0 0         if ($string =~ /\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
    0          
4681 0           elsif ($string =~ /\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qx ( )
  0            
4682 0           elsif ($string =~ /\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qx { }
  0            
4683 0           elsif ($string =~ /\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qx [ ]
  0            
4684 0           elsif ($string =~ /\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qx < >
  0            
4685 0           elsif ($string =~ /\G (\') ((?:$qq_char)*?) (\') /oxgc) { $e_string .= $e . e_q ($ope,$1,$3,$2); next E_STRING_LOOP; } # qx ' '
  0            
4686 0           elsif ($string =~ /\G (\S) ((?:$qq_char)*?) (\1) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qx * *
  0            
4687             }
4688 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
4689             }
4690             }
4691              
4692             # q//
4693             elsif ($string =~ /\G \b (q) \b /oxgc) {
4694 0           my $ope = $1;
4695 0 0         if ($string =~ /\G (\#) ((?:\\\#|\\\\|$q_char)*?) (\#) /oxgc) { # q# #
4696 0           $e_string .= e_q($ope,$1,$3,$2);
4697             }
4698             else {
4699 0           my $e = '';
4700 0           while ($string !~ /\G \z/oxgc) {
4701 0 0         if ($string =~ /\G (\s+|\#.*) /oxgc) { $e .= $1; }
  0 0          
    0          
    0          
    0          
    0          
4702 0           elsif ($string =~ /\G (\() ((?:\\\\|\\\)|\\\(|$q_paren)*?) (\)) /oxgc) { $e_string .= $e . e_q($ope,$1,$3,$2); next E_STRING_LOOP; } # q ( )
  0            
4703 0           elsif ($string =~ /\G (\{) ((?:\\\\|\\\}|\\\{|$q_brace)*?) (\}) /oxgc) { $e_string .= $e . e_q($ope,$1,$3,$2); next E_STRING_LOOP; } # q { }
  0            
4704 0           elsif ($string =~ /\G (\[) ((?:\\\\|\\\]|\\\[|$q_bracket)*?) (\]) /oxgc) { $e_string .= $e . e_q($ope,$1,$3,$2); next E_STRING_LOOP; } # q [ ]
  0            
4705 0           elsif ($string =~ /\G (\<) ((?:\\\\|\\\>|\\\<|$q_angle)*?) (\>) /oxgc) { $e_string .= $e . e_q($ope,$1,$3,$2); next E_STRING_LOOP; } # q < >
  0            
4706 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            
4707             }
4708 0           die __FILE__, ": Can't find string terminator anywhere before EOF";
4709             }
4710             }
4711              
4712             # ''
4713 0           elsif ($string =~ /\G (?
4714              
4715             # ""
4716 0           elsif ($string =~ /\G (\") ((?:$qq_char)*?) (\") /oxgc) { $e_string .= e_qq('',$1,$3,$2); }
4717              
4718             # ``
4719 0           elsif ($string =~ /\G (\`) ((?:$qq_char)*?) (\`) /oxgc) { $e_string .= e_qq('',$1,$3,$2); }
4720              
4721             # <<= <=> <= < operator
4722             elsif ($string =~ /\G ( <<= | <=> | <= | < ) (?= \s* [A-Za-z_0-9'"`\$\@\&\*\(\+\-] )/oxgc)
4723 0           { $e_string .= $1; }
4724              
4725             #
4726 0           elsif ($string =~ /\G (<[\$]?[A-Za-z_][A-Za-z_0-9]*>) /oxgc) { $e_string .= $1; }
4727              
4728             # --- glob
4729             elsif ($string =~ /\G < ((?:$q_char)+?) > /oxgc) {
4730 0           $e_string .= 'Char::Elatin4::glob("' . $1 . '")';
4731             }
4732              
4733             # << (bit shift) --- not here document
4734 0           elsif ($string =~ /\G ( << \s* ) (?= [0-9\$\@\&] ) /oxgc) { $slash = 'm//'; $e_string .= $1; }
  0            
4735              
4736             # <<'HEREDOC'
4737             elsif ($string =~ /\G ( << '([a-zA-Z_0-9]*)' ) /oxgc) {
4738 0           $slash = 'm//';
4739 0           my $here_quote = $1;
4740 0           my $delimiter = $2;
4741              
4742             # get here document
4743 0 0         if ($here_script eq '') {
4744 0           $here_script = CORE::substr $_, pos $_;
4745 0           $here_script =~ s/.*?\n//oxm;
4746             }
4747 0 0         if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4748 0           push @heredoc, $1 . qq{\n$delimiter\n};
4749 0           push @heredoc_delimiter, $delimiter;
4750             }
4751             else {
4752 0           die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF";
4753             }
4754 0           $e_string .= $here_quote;
4755             }
4756              
4757             # <<\HEREDOC
4758             elsif ($string =~ /\G ( << \\([a-zA-Z_0-9]+) ) /oxgc) {
4759 0           $slash = 'm//';
4760 0           my $here_quote = $1;
4761 0           my $delimiter = $2;
4762              
4763             # get here document
4764 0 0         if ($here_script eq '') {
4765 0           $here_script = CORE::substr $_, pos $_;
4766 0           $here_script =~ s/.*?\n//oxm;
4767             }
4768 0 0         if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4769 0           push @heredoc, $1 . qq{\n$delimiter\n};
4770 0           push @heredoc_delimiter, $delimiter;
4771             }
4772             else {
4773 0           die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF";
4774             }
4775 0           $e_string .= $here_quote;
4776             }
4777              
4778             # <<"HEREDOC"
4779             elsif ($string =~ /\G ( << "([a-zA-Z_0-9]*)" ) /oxgc) {
4780 0           $slash = 'm//';
4781 0           my $here_quote = $1;
4782 0           my $delimiter = $2;
4783              
4784             # get here document
4785 0 0         if ($here_script eq '') {
4786 0           $here_script = CORE::substr $_, pos $_;
4787 0           $here_script =~ s/.*?\n//oxm;
4788             }
4789 0 0         if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4790 0           push @heredoc, e_heredoc($1) . qq{\n$delimiter\n};
4791 0           push @heredoc_delimiter, $delimiter;
4792             }
4793             else {
4794 0           die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF";
4795             }
4796 0           $e_string .= $here_quote;
4797             }
4798              
4799             # <
4800             elsif ($string =~ /\G ( << ([a-zA-Z_0-9]+) ) /oxgc) {
4801 0           $slash = 'm//';
4802 0           my $here_quote = $1;
4803 0           my $delimiter = $2;
4804              
4805             # get here document
4806 0 0         if ($here_script eq '') {
4807 0           $here_script = CORE::substr $_, pos $_;
4808 0           $here_script =~ s/.*?\n//oxm;
4809             }
4810 0 0         if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4811 0           push @heredoc, e_heredoc($1) . qq{\n$delimiter\n};
4812 0           push @heredoc_delimiter, $delimiter;
4813             }
4814             else {
4815 0           die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF";
4816             }
4817 0           $e_string .= $here_quote;
4818             }
4819              
4820             # <<`HEREDOC`
4821             elsif ($string =~ /\G ( << `([a-zA-Z_0-9]*)` ) /oxgc) {
4822 0           $slash = 'm//';
4823 0           my $here_quote = $1;
4824 0           my $delimiter = $2;
4825              
4826             # get here document
4827 0 0         if ($here_script eq '') {
4828 0           $here_script = CORE::substr $_, pos $_;
4829 0           $here_script =~ s/.*?\n//oxm;
4830             }
4831 0 0         if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4832 0           push @heredoc, e_heredoc($1) . qq{\n$delimiter\n};
4833 0           push @heredoc_delimiter, $delimiter;
4834             }
4835             else {
4836 0           die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF";
4837             }
4838 0           $e_string .= $here_quote;
4839             }
4840              
4841             # any operator before div
4842             elsif ($string =~ /\G (
4843             -- | \+\+ |
4844             [\)\}\]]
4845              
4846 0           ) /oxgc) { $slash = 'div'; $e_string .= $1; }
  0            
4847              
4848             # yada-yada or triple-dot operator
4849             elsif ($string =~ /\G (
4850             \.\.\.
4851              
4852 0           ) /oxgc) { $slash = 'm//'; $e_string .= q{die('Unimplemented')}; }
  0            
4853              
4854             # any operator before m//
4855             elsif ($string =~ /\G (
4856              
4857             !~~ | !~ | != | ! |
4858             %= | % |
4859             &&= | && | &= | & |
4860             -= | -> | - |
4861             :\s*= |
4862             : |
4863             <<= | <=> | <= | < |
4864             == | => | =~ | = |
4865             >>= | >> | >= | > |
4866             \*\*= | \*\* | \*= | \* |
4867             \+= | \+ |
4868             \.\. | \.= | \. |
4869             \/\/= | \/\/ |
4870             \/= | \/ |
4871             \? |
4872             \\ |
4873             \^= | \^ |
4874             \b x= |
4875             \|\|= | \|\| | \|= | \| |
4876             ~~ | ~ |
4877             \b(?: and | cmp | eq | ge | gt | le | lt | ne | not | or | xor | x )\b |
4878             \b(?: print )\b |
4879              
4880             [,;\(\{\[]
4881              
4882 0           ) /oxgc) { $slash = 'm//'; $e_string .= $1; }
  0            
4883              
4884             # other any character
4885 0           elsif ($string =~ /\G ($q_char) /oxgc) { $e_string .= $1; }
4886              
4887             # system error
4888             else {
4889 0           die __FILE__, ": Oops, this shouldn't happen!";
4890             }
4891             }
4892              
4893 0           return $e_string;
4894             }
4895              
4896             #
4897             # character class
4898             #
4899             sub character_class {
4900 0     0 0   my($char,$modifier) = @_;
4901              
4902 0 0         if ($char eq '.') {
4903 0 0         if ($modifier =~ /s/) {
4904 0           return '${Char::Elatin4::dot_s}';
4905             }
4906             else {
4907 0           return '${Char::Elatin4::dot}';
4908             }
4909             }
4910             else {
4911 0           return Char::Elatin4::classic_character_class($char);
4912             }
4913             }
4914              
4915             #
4916             # escape capture ($1, $2, $3, ...)
4917             #
4918             sub e_capture {
4919              
4920 0     0 0   return join '', '${', $_[0], '}';
4921             }
4922              
4923             #
4924             # escape transliteration (tr/// or y///)
4925             #
4926             sub e_tr {
4927 0     0 0   my($variable,$charclass,$e,$charclass2,$modifier) = @_;
4928 0           my $e_tr = '';
4929 0   0       $modifier ||= '';
4930              
4931 0           $slash = 'div';
4932              
4933             # quote character class 1
4934 0           $charclass = q_tr($charclass);
4935              
4936             # quote character class 2
4937 0           $charclass2 = q_tr($charclass2);
4938              
4939             # /b /B modifier
4940 0 0         if ($modifier =~ tr/bB//d) {
4941 0 0         if ($variable eq '') {
4942 0           $e_tr = qq{tr$charclass$e$charclass2$modifier};
4943             }
4944             else {
4945 0           $e_tr = qq{$variable${bind_operator}tr$charclass$e$charclass2$modifier};
4946             }
4947             }
4948             else {
4949 0 0         if ($variable eq '') {
4950 0           $e_tr = qq{Char::Elatin4::tr(\$_,' =~ ',$charclass,$e$charclass2,'$modifier')};
4951             }
4952             else {
4953 0           $e_tr = qq{Char::Elatin4::tr($variable,'$bind_operator',$charclass,$e$charclass2,'$modifier')};
4954             }
4955             }
4956              
4957             # clear tr/// variable
4958 0           $tr_variable = '';
4959 0           $bind_operator = '';
4960              
4961 0           return $e_tr;
4962             }
4963              
4964             #
4965             # quote for escape transliteration (tr/// or y///)
4966             #
4967             sub q_tr {
4968 0     0 0   my($charclass) = @_;
4969              
4970             # quote character class
4971 0 0         if ($charclass !~ /'/oxms) {
    0          
    0          
    0          
    0          
    0          
4972 0           return e_q('', "'", "'", $charclass); # --> q' '
4973             }
4974             elsif ($charclass !~ /\//oxms) {
4975 0           return e_q('q', '/', '/', $charclass); # --> q/ /
4976             }
4977             elsif ($charclass !~ /\#/oxms) {
4978 0           return e_q('q', '#', '#', $charclass); # --> q# #
4979             }
4980             elsif ($charclass !~ /[\<\>]/oxms) {
4981 0           return e_q('q', '<', '>', $charclass); # --> q< >
4982             }
4983             elsif ($charclass !~ /[\(\)]/oxms) {
4984 0           return e_q('q', '(', ')', $charclass); # --> q( )
4985             }
4986             elsif ($charclass !~ /[\{\}]/oxms) {
4987 0           return e_q('q', '{', '}', $charclass); # --> q{ }
4988             }
4989             else {
4990 0           for my $char (qw( ! " $ % & * + . : = ? @ ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
4991 0 0         if ($charclass !~ /\Q$char\E/xms) {
4992 0           return e_q('q', $char, $char, $charclass);
4993             }
4994             }
4995             }
4996              
4997 0           return e_q('q', '{', '}', $charclass);
4998             }
4999              
5000             #
5001             # escape q string (q//, '')
5002             #
5003             sub e_q {
5004 0     0 0   my($ope,$delimiter,$end_delimiter,$string) = @_;
5005              
5006 0           $slash = 'div';
5007              
5008 0           return join '', $ope, $delimiter, $string, $end_delimiter;
5009             }
5010              
5011             #
5012             # escape qq string (qq//, "", qx//, ``)
5013             #
5014             sub e_qq {
5015 0     0 0   my($ope,$delimiter,$end_delimiter,$string) = @_;
5016              
5017 0           $slash = 'div';
5018              
5019 0           my $left_e = 0;
5020 0           my $right_e = 0;
5021 0           my @char = $string =~ /\G(
5022             \\o\{ [0-7]+ \} |
5023             \\x\{ [0-9A-Fa-f]+ \} |
5024             \\N\{ [^0-9\}][^\}]* \} |
5025             \$` | \$\{`\} | \$ \s* PREMATCH | \$ \s* \{ \s* PREMATCH \s* \} | \$ \s* \{\^PREMATCH\} |
5026             \$& | \$\{&\} | \$ \s* MATCH | \$ \s* \{ \s* MATCH \s* \} | \$ \s* \{\^MATCH\} |
5027             \$ \s* POSTMATCH | \$ \s* \{ \s* POSTMATCH \s* \} | \$ \s* \{\^POSTMATCH\} |
5028             \$ \s* \d+ |
5029             \$ \s* \{ \s* \d+ \s* \} |
5030             \$ \$ (?![\w\{]) |
5031             \$ \s* \$ \s* $qq_variable |
5032             \\?(?:$q_char)
5033             )/oxmsg;
5034              
5035 0           for (my $i=0; $i <= $#char; $i++) {
5036              
5037             # "\L\u" --> "\u\L"
5038 0 0 0       if (($char[$i] eq '\L') and ($char[$i+1] eq '\u')) {
    0 0        
    0          
    0          
    0          
5039 0           @char[$i,$i+1] = @char[$i+1,$i];
5040             }
5041              
5042             # "\U\l" --> "\l\U"
5043             elsif (($char[$i] eq '\U') and ($char[$i+1] eq '\l')) {
5044 0           @char[$i,$i+1] = @char[$i+1,$i];
5045             }
5046              
5047             # octal escape sequence
5048             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
5049 0           $char[$i] = Char::Elatin4::octchr($1);
5050             }
5051              
5052             # hexadecimal escape sequence
5053             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
5054 0           $char[$i] = Char::Elatin4::hexchr($1);
5055             }
5056              
5057             # \N{CHARNAME} --> N{CHARNAME}
5058             elsif ($char[$i] =~ /\A \\ ( N\{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
5059 0           $char[$i] = $1;
5060             }
5061              
5062 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          
5063             }
5064              
5065             # \F
5066             #
5067             # P.69 Table 2-6. Translation escapes
5068             # in Chapter 2: Bits and Pieces
5069             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
5070             # (and so on)
5071              
5072             # \u \l \U \L \F \Q \E
5073 0           elsif ($char[$i] =~ /\A ([<>]) \z/oxms) {
5074 0 0         if ($right_e < $left_e) {
5075 0           $char[$i] = '\\' . $char[$i];
5076             }
5077             }
5078             elsif ($char[$i] eq '\u') {
5079              
5080             # "STRING @{[ LIST EXPR ]} MORE STRING"
5081              
5082             # P.257 Other Tricks You Can Do with Hard References
5083             # in Chapter 8: References
5084             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
5085              
5086             # P.353 Other Tricks You Can Do with Hard References
5087             # in Chapter 8: References
5088             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
5089              
5090             # (and so on)
5091              
5092 0           $char[$i] = '@{[Char::Elatin4::ucfirst qq<';
5093 0           $left_e++;
5094             }
5095             elsif ($char[$i] eq '\l') {
5096 0           $char[$i] = '@{[Char::Elatin4::lcfirst qq<';
5097 0           $left_e++;
5098             }
5099             elsif ($char[$i] eq '\U') {
5100 0           $char[$i] = '@{[Char::Elatin4::uc qq<';
5101 0           $left_e++;
5102             }
5103             elsif ($char[$i] eq '\L') {
5104 0           $char[$i] = '@{[Char::Elatin4::lc qq<';
5105 0           $left_e++;
5106             }
5107             elsif ($char[$i] eq '\F') {
5108 0           $char[$i] = '@{[Char::Elatin4::fc qq<';
5109 0           $left_e++;
5110             }
5111             elsif ($char[$i] eq '\Q') {
5112 0           $char[$i] = '@{[CORE::quotemeta qq<';
5113 0           $left_e++;
5114             }
5115             elsif ($char[$i] eq '\E') {
5116 0 0         if ($right_e < $left_e) {
5117 0           $char[$i] = '>]}';
5118 0           $right_e++;
5119             }
5120             else {
5121 0           $char[$i] = '';
5122             }
5123             }
5124             elsif ($char[$i] eq '\Q') {
5125 0           while (1) {
5126 0 0         if (++$i > $#char) {
5127 0           last;
5128             }
5129 0 0         if ($char[$i] eq '\E') {
5130 0           last;
5131             }
5132             }
5133             }
5134             elsif ($char[$i] eq '\E') {
5135             }
5136              
5137             # $0 --> $0
5138             elsif ($char[$i] =~ /\A \$ 0 \z/oxms) {
5139             }
5140             elsif ($char[$i] =~ /\A \$ \{ \s* 0 \s* \} \z/oxms) {
5141             }
5142              
5143             # $$ --> $$
5144             elsif ($char[$i] =~ /\A \$\$ \z/oxms) {
5145             }
5146              
5147             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
5148             # $1, $2, $3 --> $1, $2, $3 otherwise
5149             elsif ($char[$i] =~ /\A \$ ([1-9][0-9]*) \z/oxms) {
5150 0           $char[$i] = e_capture($1);
5151             }
5152             elsif ($char[$i] =~ /\A \$ \{ \s* ([1-9][0-9]*) \s* \} \z/oxms) {
5153 0           $char[$i] = e_capture($1);
5154             }
5155              
5156             # $$foo[ ... ] --> $ $foo->[ ... ]
5157             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) ( \[ (?:$qq_bracket)*? \] ) \z/oxms) {
5158 0           $char[$i] = e_capture($1.'->'.$2);
5159             }
5160              
5161             # $$foo{ ... } --> $ $foo->{ ... }
5162             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) ( \{ (?:$qq_brace)*? \} ) \z/oxms) {
5163 0           $char[$i] = e_capture($1.'->'.$2);
5164             }
5165              
5166             # $$foo
5167             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) \z/oxms) {
5168 0           $char[$i] = e_capture($1);
5169             }
5170              
5171             # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Char::Elatin4::PREMATCH()
5172             elsif ($char[$i] =~ /\A ( \$` | \$\{`\} | \$ \s* PREMATCH | \$ \s* \{ \s* PREMATCH \s* \} | \$ \s* \{\^PREMATCH\} ) \z/oxmsgc) {
5173 0           $char[$i] = '@{[Char::Elatin4::PREMATCH()]}';
5174             }
5175              
5176             # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Char::Elatin4::MATCH()
5177             elsif ($char[$i] =~ /\A ( \$& | \$\{&\} | \$ \s* MATCH | \$ \s* \{ \s* MATCH \s* \} | \$ \s* \{\^MATCH\} ) \z/oxmsgc) {
5178 0           $char[$i] = '@{[Char::Elatin4::MATCH()]}';
5179             }
5180              
5181             # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Char::Elatin4::POSTMATCH()
5182             elsif ($char[$i] =~ /\A ( \$ \s* POSTMATCH | \$ \s* \{ \s* POSTMATCH \s* \} | \$ \s* \{\^POSTMATCH\} ) \z/oxmsgc) {
5183 0           $char[$i] = '@{[Char::Elatin4::POSTMATCH()]}';
5184             }
5185              
5186             # ${ foo } --> ${ foo }
5187             elsif ($char[$i] =~ /\A \$ \s* \{ \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* \} \z/oxms) {
5188             }
5189              
5190             # ${ ... }
5191             elsif ($char[$i] =~ /\A \$ \s* \{ \s* ( .+ ) \s* \} \z/oxms) {
5192 0           $char[$i] = e_capture($1);
5193             }
5194             }
5195              
5196             # return string
5197 0 0         if ($left_e > $right_e) {
5198 0           return join '', $ope, $delimiter, @char, '>]}' x ($left_e - $right_e), $end_delimiter;
5199             }
5200 0           return join '', $ope, $delimiter, @char, $end_delimiter;
5201             }
5202              
5203             #
5204             # escape qw string (qw//)
5205             #
5206             sub e_qw {
5207 0     0 0   my($ope,$delimiter,$end_delimiter,$string) = @_;
5208              
5209 0           $slash = 'div';
5210              
5211             # choice again delimiter
5212 0           my %octet = map {$_ => 1} ($string =~ /\G ([\x00-\xFF]) /oxmsg);
  0            
5213 0 0         if (not $octet{$end_delimiter}) {
    0          
    0          
    0          
    0          
5214 0           return join '', $ope, $delimiter, $string, $end_delimiter;
5215             }
5216             elsif (not $octet{')'}) {
5217 0           return join '', $ope, '(', $string, ')';
5218             }
5219             elsif (not $octet{'}'}) {
5220 0           return join '', $ope, '{', $string, '}';
5221             }
5222             elsif (not $octet{']'}) {
5223 0           return join '', $ope, '[', $string, ']';
5224             }
5225             elsif (not $octet{'>'}) {
5226 0           return join '', $ope, '<', $string, '>';
5227             }
5228             else {
5229 0           for my $char (qw( ! " $ % & * + - . / : = ? @ ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
5230 0 0         if (not $octet{$char}) {
5231 0           return join '', $ope, $char, $string, $char;
5232             }
5233             }
5234             }
5235              
5236             # qw/AAA BBB C'CC/ --> ('AAA', 'BBB', 'C\'CC')
5237 0           my @string = CORE::split(/\s+/, $string);
5238 0           for my $string (@string) {
5239 0           my @octet = $string =~ /\G ([\x00-\xFF]) /oxmsg;
5240 0           for my $octet (@octet) {
5241 0 0         if ($octet =~ /\A (['\\]) \z/oxms) {
5242 0           $octet = '\\' . $1;
5243             }
5244             }
5245 0           $string = join '', @octet;
5246             }
5247 0           return join '', '(', (join ', ', map { "'$_'" } @string), ')';
  0            
5248             }
5249              
5250             #
5251             # escape here document (<<"HEREDOC", <
5252             #
5253             sub e_heredoc {
5254 0     0 0   my($string) = @_;
5255              
5256 0           $slash = 'm//';
5257              
5258 0           my $metachar = qr/[\@\\|]/oxms; # '|' is for <<`HEREDOC`
5259              
5260 0           my $left_e = 0;
5261 0           my $right_e = 0;
5262 0           my @char = $string =~ /\G(
5263             \\o\{ [0-7]+ \} |
5264             \\x\{ [0-9A-Fa-f]+ \} |
5265             \\N\{ [^0-9\}][^\}]* \} |
5266             \$` | \$\{`\} | \$ \s* PREMATCH | \$ \s* \{ \s* PREMATCH \s* \} | \$ \s* \{\^PREMATCH\} |
5267             \$& | \$\{&\} | \$ \s* MATCH | \$ \s* \{ \s* MATCH \s* \} | \$ \s* \{\^MATCH\} |
5268             \$ \s* POSTMATCH | \$ \s* \{ \s* POSTMATCH \s* \} | \$ \s* \{\^POSTMATCH\} |
5269             \$ \s* \d+ |
5270             \$ \s* \{ \s* \d+ \s* \} |
5271             \$ \$ (?![\w\{]) |
5272             \$ \s* \$ \s* $qq_variable |
5273             \\?(?:$q_char)
5274             )/oxmsg;
5275              
5276 0           for (my $i=0; $i <= $#char; $i++) {
5277              
5278             # "\L\u" --> "\u\L"
5279 0 0 0       if (($char[$i] eq '\L') and ($char[$i+1] eq '\u')) {
    0 0        
    0          
    0          
    0          
5280 0           @char[$i,$i+1] = @char[$i+1,$i];
5281             }
5282              
5283             # "\U\l" --> "\l\U"
5284             elsif (($char[$i] eq '\U') and ($char[$i+1] eq '\l')) {
5285 0           @char[$i,$i+1] = @char[$i+1,$i];
5286             }
5287              
5288             # octal escape sequence
5289             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
5290 0           $char[$i] = Char::Elatin4::octchr($1);
5291             }
5292              
5293             # hexadecimal escape sequence
5294             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
5295 0           $char[$i] = Char::Elatin4::hexchr($1);
5296             }
5297              
5298             # \N{CHARNAME} --> N{CHARNAME}
5299             elsif ($char[$i] =~ /\A \\ ( N\{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
5300 0           $char[$i] = $1;
5301             }
5302              
5303 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          
5304             }
5305              
5306             # \u \l \U \L \F \Q \E
5307 0           elsif ($char[$i] =~ /\A ([<>]) \z/oxms) {
5308 0 0         if ($right_e < $left_e) {
5309 0           $char[$i] = '\\' . $char[$i];
5310             }
5311             }
5312             elsif ($char[$i] eq '\u') {
5313 0           $char[$i] = '@{[Char::Elatin4::ucfirst qq<';
5314 0           $left_e++;
5315             }
5316             elsif ($char[$i] eq '\l') {
5317 0           $char[$i] = '@{[Char::Elatin4::lcfirst qq<';
5318 0           $left_e++;
5319             }
5320             elsif ($char[$i] eq '\U') {
5321 0           $char[$i] = '@{[Char::Elatin4::uc qq<';
5322 0           $left_e++;
5323             }
5324             elsif ($char[$i] eq '\L') {
5325 0           $char[$i] = '@{[Char::Elatin4::lc qq<';
5326 0           $left_e++;
5327             }
5328             elsif ($char[$i] eq '\F') {
5329 0           $char[$i] = '@{[Char::Elatin4::fc qq<';
5330 0           $left_e++;
5331             }
5332             elsif ($char[$i] eq '\Q') {
5333 0           $char[$i] = '@{[CORE::quotemeta qq<';
5334 0           $left_e++;
5335             }
5336             elsif ($char[$i] eq '\E') {
5337 0 0         if ($right_e < $left_e) {
5338 0           $char[$i] = '>]}';
5339 0           $right_e++;
5340             }
5341             else {
5342 0           $char[$i] = '';
5343             }
5344             }
5345             elsif ($char[$i] eq '\Q') {
5346 0           while (1) {
5347 0 0         if (++$i > $#char) {
5348 0           last;
5349             }
5350 0 0         if ($char[$i] eq '\E') {
5351 0           last;
5352             }
5353             }
5354             }
5355             elsif ($char[$i] eq '\E') {
5356             }
5357              
5358             # $0 --> $0
5359             elsif ($char[$i] =~ /\A \$ 0 \z/oxms) {
5360             }
5361             elsif ($char[$i] =~ /\A \$ \{ \s* 0 \s* \} \z/oxms) {
5362             }
5363              
5364             # $$ --> $$
5365             elsif ($char[$i] =~ /\A \$\$ \z/oxms) {
5366             }
5367              
5368             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
5369             # $1, $2, $3 --> $1, $2, $3 otherwise
5370             elsif ($char[$i] =~ /\A \$ ([1-9][0-9]*) \z/oxms) {
5371 0           $char[$i] = e_capture($1);
5372             }
5373             elsif ($char[$i] =~ /\A \$ \{ \s* ([1-9][0-9]*) \s* \} \z/oxms) {
5374 0           $char[$i] = e_capture($1);
5375             }
5376              
5377             # $$foo[ ... ] --> $ $foo->[ ... ]
5378             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) ( \[ (?:$qq_bracket)*? \] ) \z/oxms) {
5379 0           $char[$i] = e_capture($1.'->'.$2);
5380             }
5381              
5382             # $$foo{ ... } --> $ $foo->{ ... }
5383             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) ( \{ (?:$qq_brace)*? \} ) \z/oxms) {
5384 0           $char[$i] = e_capture($1.'->'.$2);
5385             }
5386              
5387             # $$foo
5388             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) \z/oxms) {
5389 0           $char[$i] = e_capture($1);
5390             }
5391              
5392             # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Char::Elatin4::PREMATCH()
5393             elsif ($char[$i] =~ /\A ( \$` | \$\{`\} | \$ \s* PREMATCH | \$ \s* \{ \s* PREMATCH \s* \} | \$ \s* \{\^PREMATCH\} ) \z/oxmsgc) {
5394 0           $char[$i] = '@{[Char::Elatin4::PREMATCH()]}';
5395             }
5396              
5397             # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Char::Elatin4::MATCH()
5398             elsif ($char[$i] =~ /\A ( \$& | \$\{&\} | \$ \s* MATCH | \$ \s* \{ \s* MATCH \s* \} | \$ \s* \{\^MATCH\} ) \z/oxmsgc) {
5399 0           $char[$i] = '@{[Char::Elatin4::MATCH()]}';
5400             }
5401              
5402             # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Char::Elatin4::POSTMATCH()
5403             elsif ($char[$i] =~ /\A ( \$ \s* POSTMATCH | \$ \s* \{ \s* POSTMATCH \s* \} | \$ \s* \{\^POSTMATCH\} ) \z/oxmsgc) {
5404 0           $char[$i] = '@{[Char::Elatin4::POSTMATCH()]}';
5405             }
5406              
5407             # ${ foo } --> ${ foo }
5408             elsif ($char[$i] =~ /\A \$ \s* \{ \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* \} \z/oxms) {
5409             }
5410              
5411             # ${ ... }
5412             elsif ($char[$i] =~ /\A \$ \s* \{ \s* ( .+ ) \s* \} \z/oxms) {
5413 0           $char[$i] = e_capture($1);
5414             }
5415             }
5416              
5417             # return string
5418 0 0         if ($left_e > $right_e) {
5419 0           return join '', @char, '>]}' x ($left_e - $right_e);
5420             }
5421 0           return join '', @char;
5422             }
5423              
5424             #
5425             # escape regexp (m//, qr//)
5426             #
5427             sub e_qr {
5428 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
5429 0   0       $modifier ||= '';
5430              
5431 0           $modifier =~ tr/p//d;
5432 0 0         if ($modifier =~ /([adlu])/oxms) {
5433 0           my $line = 0;
5434 0           for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
5435 0 0         if ($filename ne __FILE__) {
5436 0           $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
5437 0           last;
5438             }
5439             }
5440 0           die qq{Unsupported modifier "$1" used at line $line.\n};
5441             }
5442              
5443 0           $slash = 'div';
5444              
5445             # literal null string pattern
5446 0 0         if ($string eq '') {
    0          
5447 0           $modifier =~ tr/bB//d;
5448 0           $modifier =~ tr/i//d;
5449 0           return join '', $ope, $delimiter, $end_delimiter, $modifier;
5450             }
5451              
5452             # /b /B modifier
5453             elsif ($modifier =~ tr/bB//d) {
5454              
5455             # choice again delimiter
5456 0 0         if ($delimiter =~ / [\@:] /oxms) {
5457 0           my @char = $string =~ /\G([\x00-\xFF])/oxmsg;
5458 0           my %octet = map {$_ => 1} @char;
  0            
5459 0 0         if (not $octet{')'}) {
    0          
    0          
    0          
5460 0           $delimiter = '(';
5461 0           $end_delimiter = ')';
5462             }
5463             elsif (not $octet{'}'}) {
5464 0           $delimiter = '{';
5465 0           $end_delimiter = '}';
5466             }
5467             elsif (not $octet{']'}) {
5468 0           $delimiter = '[';
5469 0           $end_delimiter = ']';
5470             }
5471             elsif (not $octet{'>'}) {
5472 0           $delimiter = '<';
5473 0           $end_delimiter = '>';
5474             }
5475             else {
5476 0           for my $char (qw( ! " $ % & * + - . / = ? ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
5477 0 0         if (not $octet{$char}) {
5478 0           $delimiter = $char;
5479 0           $end_delimiter = $char;
5480 0           last;
5481             }
5482             }
5483             }
5484             }
5485              
5486 0 0 0       if (($ope =~ /\A m? \z/oxms) and ($delimiter eq '?')) {
5487 0           return join '', $ope, $delimiter, $string, $matched, $end_delimiter, $modifier;
5488             }
5489             else {
5490 0           return join '', $ope, $delimiter, '(?:', $string, ')', $matched, $end_delimiter, $modifier;
5491             }
5492             }
5493              
5494 0 0         my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
5495 0           my $metachar = qr/[\@\\|[\]{^]/oxms;
5496              
5497             # split regexp
5498 0           my @char = $string =~ /\G(
5499             \\o\{ [0-7]+ \} |
5500             \\ [0-7]{2,3} |
5501             \\x\{ [0-9A-Fa-f]+ \} |
5502             \\x [0-9A-Fa-f]{1,2} |
5503             \\c [\x40-\x5F] |
5504             \\N\{ [^0-9\}][^\}]* \} |
5505             \\p\{ [^0-9\}][^\}]* \} |
5506             \\P\{ [^0-9\}][^\}]* \} |
5507             \\ (?:$q_char) |
5508             \$` | \$\{`\} | \$ \s* PREMATCH | \$ \s* \{ \s* PREMATCH \s* \} | \$ \s* \{\^PREMATCH\} |
5509             \$& | \$\{&\} | \$ \s* MATCH | \$ \s* \{ \s* MATCH \s* \} | \$ \s* \{\^MATCH\} |
5510             \$ \s* POSTMATCH | \$ \s* \{ \s* POSTMATCH \s* \} | \$ \s* \{\^POSTMATCH\} |
5511             [\$\@] $qq_variable |
5512             \$ \s* \d+ |
5513             \$ \s* \{ \s* \d+ \s* \} |
5514             \$ \$ (?![\w\{]) |
5515             \$ \s* \$ \s* $qq_variable |
5516             \[\:\^ (?:alnum|alpha|ascii|blank|cntrl|digit|graph|lower|print|punct|space|upper|word|xdigit) :\] |
5517             \[\: (?:alnum|alpha|ascii|blank|cntrl|digit|graph|lower|print|punct|space|upper|word|xdigit) :\] |
5518             \[\^ |
5519             \(\? |
5520             (?:$q_char)
5521             )/oxmsg;
5522              
5523             # choice again delimiter
5524 0 0         if ($delimiter =~ / [\@:] /oxms) {
5525 0           my %octet = map {$_ => 1} @char;
  0            
5526 0 0         if (not $octet{')'}) {
    0          
    0          
    0          
5527 0           $delimiter = '(';
5528 0           $end_delimiter = ')';
5529             }
5530             elsif (not $octet{'}'}) {
5531 0           $delimiter = '{';
5532 0           $end_delimiter = '}';
5533             }
5534             elsif (not $octet{']'}) {
5535 0           $delimiter = '[';
5536 0           $end_delimiter = ']';
5537             }
5538             elsif (not $octet{'>'}) {
5539 0           $delimiter = '<';
5540 0           $end_delimiter = '>';
5541             }
5542             else {
5543 0           for my $char (qw( ! " $ % & * + - . / = ? ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
5544 0 0         if (not $octet{$char}) {
5545 0           $delimiter = $char;
5546 0           $end_delimiter = $char;
5547 0           last;
5548             }
5549             }
5550             }
5551             }
5552              
5553 0           my $left_e = 0;
5554 0           my $right_e = 0;
5555 0           for (my $i=0; $i <= $#char; $i++) {
5556              
5557             # "\L\u" --> "\u\L"
5558 0 0 0       if (($char[$i] eq '\L') and ($char[$i+1] eq '\u')) {
    0 0        
    0          
    0          
    0          
    0          
    0          
    0          
5559 0           @char[$i,$i+1] = @char[$i+1,$i];
5560             }
5561              
5562             # "\U\l" --> "\l\U"
5563             elsif (($char[$i] eq '\U') and ($char[$i+1] eq '\l')) {
5564 0           @char[$i,$i+1] = @char[$i+1,$i];
5565             }
5566              
5567             # octal escape sequence
5568             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
5569 0           $char[$i] = Char::Elatin4::octchr($1);
5570             }
5571              
5572             # hexadecimal escape sequence
5573             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
5574 0           $char[$i] = Char::Elatin4::hexchr($1);
5575             }
5576              
5577             # \N{CHARNAME} --> N\{CHARNAME}
5578             elsif ($char[$i] =~ /\A \\ (N) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
5579 0           $char[$i] = $1 . '\\' . $2;
5580             }
5581              
5582             # \p{PROPERTY} --> p\{PROPERTY}
5583             elsif ($char[$i] =~ /\A \\ (p) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
5584 0           $char[$i] = $1 . '\\' . $2;
5585             }
5586              
5587             # \P{PROPERTY} --> P\{PROPERTY}
5588             elsif ($char[$i] =~ /\A \\ (P) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
5589 0           $char[$i] = $1 . '\\' . $2;
5590             }
5591              
5592             # \p, \P, \X --> p, P, X
5593             elsif ($char[$i] =~ /\A \\ ( [pPX] ) \z/oxms) {
5594 0           $char[$i] = $1;
5595             }
5596              
5597 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          
5598             }
5599              
5600             # join separated multiple-octet
5601 0           elsif ($char[$i] =~ /\A (?: \\ [0-7]{2,3} | \\x [0-9A-Fa-f]{1,2}) \z/oxms) {
5602 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        
5603 0           $char[$i] .= join '', splice @char, $i+1, 3;
5604             }
5605             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)) {
5606 0           $char[$i] .= join '', splice @char, $i+1, 2;
5607             }
5608             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)) {
5609 0           $char[$i] .= join '', splice @char, $i+1, 1;
5610             }
5611             }
5612              
5613             # open character class [...]
5614             elsif ($char[$i] eq '[') {
5615 0           my $left = $i;
5616              
5617             # [] make die "Unmatched [] in regexp ..."
5618             # (and so on)
5619              
5620 0 0         if ($char[$i+1] eq ']') {
5621 0           $i++;
5622             }
5623              
5624 0           while (1) {
5625 0 0         if (++$i > $#char) {
5626 0           die __FILE__, ": Unmatched [] in regexp";
5627             }
5628 0 0         if ($char[$i] eq ']') {
5629 0           my $right = $i;
5630              
5631             # [...]
5632 0 0         if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
5633 0           splice @char, $left, $right-$left+1, sprintf(q{@{[Char::Elatin4::charlist_qr(%s,'%s')]}}, join(',', map {qq_stuff($delimiter,$end_delimiter,$_)} @char[$left+1..$right-1]), $modifier);
  0            
5634             }
5635             else {
5636 0           splice @char, $left, $right-$left+1, Char::Elatin4::charlist_qr(@char[$left+1..$right-1], $modifier);
5637             }
5638              
5639 0           $i = $left;
5640 0           last;
5641             }
5642             }
5643             }
5644              
5645             # open character class [^...]
5646             elsif ($char[$i] eq '[^') {
5647 0           my $left = $i;
5648              
5649             # [^] make die "Unmatched [] in regexp ..."
5650             # (and so on)
5651              
5652 0 0         if ($char[$i+1] eq ']') {
5653 0           $i++;
5654             }
5655              
5656 0           while (1) {
5657 0 0         if (++$i > $#char) {
5658 0           die __FILE__, ": Unmatched [] in regexp";
5659             }
5660 0 0         if ($char[$i] eq ']') {
5661 0           my $right = $i;
5662              
5663             # [^...]
5664 0 0         if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
5665 0           splice @char, $left, $right-$left+1, sprintf(q{@{[Char::Elatin4::charlist_not_qr(%s,'%s')]}}, join(',', map {qq_stuff($delimiter,$end_delimiter,$_)} @char[$left+1..$right-1]), $modifier);
  0            
5666             }
5667             else {
5668 0           splice @char, $left, $right-$left+1, Char::Elatin4::charlist_not_qr(@char[$left+1..$right-1], $modifier);
5669             }
5670              
5671 0           $i = $left;
5672 0           last;
5673             }
5674             }
5675             }
5676              
5677             # rewrite character class or escape character
5678             elsif (my $char = character_class($char[$i],$modifier)) {
5679 0           $char[$i] = $char;
5680             }
5681              
5682             # /i modifier
5683             elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Char::Elatin4::uc($char[$i]) ne Char::Elatin4::fc($char[$i]))) {
5684 0 0         if (CORE::length(Char::Elatin4::fc($char[$i])) == 1) {
5685 0           $char[$i] = '[' . Char::Elatin4::uc($char[$i]) . Char::Elatin4::fc($char[$i]) . ']';
5686             }
5687             else {
5688 0           $char[$i] = '(?:' . Char::Elatin4::uc($char[$i]) . '|' . Char::Elatin4::fc($char[$i]) . ')';
5689             }
5690             }
5691              
5692             # \u \l \U \L \F \Q \E
5693             elsif ($char[$i] =~ /\A [<>] \z/oxms) {
5694 0 0         if ($right_e < $left_e) {
5695 0           $char[$i] = '\\' . $char[$i];
5696             }
5697             }
5698             elsif ($char[$i] eq '\u') {
5699 0           $char[$i] = '@{[Char::Elatin4::ucfirst qq<';
5700 0           $left_e++;
5701             }
5702             elsif ($char[$i] eq '\l') {
5703 0           $char[$i] = '@{[Char::Elatin4::lcfirst qq<';
5704 0           $left_e++;
5705             }
5706             elsif ($char[$i] eq '\U') {
5707 0           $char[$i] = '@{[Char::Elatin4::uc qq<';
5708 0           $left_e++;
5709             }
5710             elsif ($char[$i] eq '\L') {
5711 0           $char[$i] = '@{[Char::Elatin4::lc qq<';
5712 0           $left_e++;
5713             }
5714             elsif ($char[$i] eq '\F') {
5715 0           $char[$i] = '@{[Char::Elatin4::fc qq<';
5716 0           $left_e++;
5717             }
5718             elsif ($char[$i] eq '\Q') {
5719 0           $char[$i] = '@{[CORE::quotemeta qq<';
5720 0           $left_e++;
5721             }
5722             elsif ($char[$i] eq '\E') {
5723 0 0         if ($right_e < $left_e) {
5724 0           $char[$i] = '>]}';
5725 0           $right_e++;
5726             }
5727             else {
5728 0           $char[$i] = '';
5729             }
5730             }
5731             elsif ($char[$i] eq '\Q') {
5732 0           while (1) {
5733 0 0         if (++$i > $#char) {
5734 0           last;
5735             }
5736 0 0         if ($char[$i] eq '\E') {
5737 0           last;
5738             }
5739             }
5740             }
5741             elsif ($char[$i] eq '\E') {
5742             }
5743              
5744             # $0 --> $0
5745             elsif ($char[$i] =~ /\A \$ 0 \z/oxms) {
5746 0 0         if ($ignorecase) {
5747 0           $char[$i] = '@{[Char::Elatin4::ignorecase(' . $char[$i] . ')]}';
5748             }
5749             }
5750             elsif ($char[$i] =~ /\A \$ \{ \s* 0 \s* \} \z/oxms) {
5751 0 0         if ($ignorecase) {
5752 0           $char[$i] = '@{[Char::Elatin4::ignorecase(' . $char[$i] . ')]}';
5753             }
5754             }
5755              
5756             # $$ --> $$
5757             elsif ($char[$i] =~ /\A \$\$ \z/oxms) {
5758             }
5759              
5760             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
5761             # $1, $2, $3 --> $1, $2, $3 otherwise
5762             elsif ($char[$i] =~ /\A \$ ([1-9][0-9]*) \z/oxms) {
5763 0           $char[$i] = e_capture($1);
5764 0 0         if ($ignorecase) {
5765 0           $char[$i] = '@{[Char::Elatin4::ignorecase(' . $char[$i] . ')]}';
5766             }
5767             }
5768             elsif ($char[$i] =~ /\A \$ \{ \s* ([1-9][0-9]*) \s* \} \z/oxms) {
5769 0           $char[$i] = e_capture($1);
5770 0 0         if ($ignorecase) {
5771 0           $char[$i] = '@{[Char::Elatin4::ignorecase(' . $char[$i] . ')]}';
5772             }
5773             }
5774              
5775             # $$foo[ ... ] --> $ $foo->[ ... ]
5776             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) ( \[ (?:$qq_bracket)*? \] ) \z/oxms) {
5777 0           $char[$i] = e_capture($1.'->'.$2);
5778 0 0         if ($ignorecase) {
5779 0           $char[$i] = '@{[Char::Elatin4::ignorecase(' . $char[$i] . ')]}';
5780             }
5781             }
5782              
5783             # $$foo{ ... } --> $ $foo->{ ... }
5784             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) ( \{ (?:$qq_brace)*? \} ) \z/oxms) {
5785 0           $char[$i] = e_capture($1.'->'.$2);
5786 0 0         if ($ignorecase) {
5787 0           $char[$i] = '@{[Char::Elatin4::ignorecase(' . $char[$i] . ')]}';
5788             }
5789             }
5790              
5791             # $$foo
5792             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) \z/oxms) {
5793 0           $char[$i] = e_capture($1);
5794 0 0         if ($ignorecase) {
5795 0           $char[$i] = '@{[Char::Elatin4::ignorecase(' . $char[$i] . ')]}';
5796             }
5797             }
5798              
5799             # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Char::Elatin4::PREMATCH()
5800             elsif ($char[$i] =~ /\A ( \$` | \$\{`\} | \$ \s* PREMATCH | \$ \s* \{ \s* PREMATCH \s* \} | \$ \s* \{\^PREMATCH\} ) \z/oxmsgc) {
5801 0 0         if ($ignorecase) {
5802 0           $char[$i] = '@{[Char::Elatin4::ignorecase(Char::Elatin4::PREMATCH())]}';
5803             }
5804             else {
5805 0           $char[$i] = '@{[Char::Elatin4::PREMATCH()]}';
5806             }
5807             }
5808              
5809             # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Char::Elatin4::MATCH()
5810             elsif ($char[$i] =~ /\A ( \$& | \$\{&\} | \$ \s* MATCH | \$ \s* \{ \s* MATCH \s* \} | \$ \s* \{\^MATCH\} ) \z/oxmsgc) {
5811 0 0         if ($ignorecase) {
5812 0           $char[$i] = '@{[Char::Elatin4::ignorecase(Char::Elatin4::MATCH())]}';
5813             }
5814             else {
5815 0           $char[$i] = '@{[Char::Elatin4::MATCH()]}';
5816             }
5817             }
5818              
5819             # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Char::Elatin4::POSTMATCH()
5820             elsif ($char[$i] =~ /\A ( \$ \s* POSTMATCH | \$ \s* \{ \s* POSTMATCH \s* \} | \$ \s* \{\^POSTMATCH\} ) \z/oxmsgc) {
5821 0 0         if ($ignorecase) {
5822 0           $char[$i] = '@{[Char::Elatin4::ignorecase(Char::Elatin4::POSTMATCH())]}';
5823             }
5824             else {
5825 0           $char[$i] = '@{[Char::Elatin4::POSTMATCH()]}';
5826             }
5827             }
5828              
5829             # ${ foo }
5830             elsif ($char[$i] =~ /\A \$ \s* \{ ( \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* ) \} \z/oxms) {
5831 0 0         if ($ignorecase) {
5832 0           $char[$i] = '@{[Char::Elatin4::ignorecase(' . $char[$i] . ')]}';
5833             }
5834             }
5835              
5836             # ${ ... }
5837             elsif ($char[$i] =~ /\A \$ \s* \{ \s* ( .+ ) \s* \} \z/oxms) {
5838 0           $char[$i] = e_capture($1);
5839 0 0         if ($ignorecase) {
5840 0           $char[$i] = '@{[Char::Elatin4::ignorecase(' . $char[$i] . ')]}';
5841             }
5842             }
5843              
5844             # $scalar or @array
5845             elsif ($char[$i] =~ /\A [\$\@].+ /oxms) {
5846 0           $char[$i] = e_string($char[$i]);
5847 0 0         if ($ignorecase) {
5848 0           $char[$i] = '@{[Char::Elatin4::ignorecase(' . $char[$i] . ')]}';
5849             }
5850             }
5851              
5852             # quote character before ? + * {
5853             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
5854 0 0 0       if ($char[$i-1] =~ /\A (?:\\[0-7]{2,3}|\\x[0-9-A-Fa-f]{1,2}) \z/oxms) {
    0          
5855             }
5856             elsif (($ope =~ /\A m? \z/oxms) and ($delimiter eq '?')) {
5857 0           my $char = $char[$i-1];
5858 0 0         if ($char[$i] eq '{') {
5859 0           die __FILE__, qq{: "MULTIBYTE{n}" should be "(MULTIBYTE){n}" in m?? (and shift \$1,\$2,\$3,...) ($char){n}};
5860             }
5861             else {
5862 0           die __FILE__, qq{: "MULTIBYTE$char[$i]" should be "(MULTIBYTE)$char[$i]" in m?? (and shift \$1,\$2,\$3,...) ($char)$char[$i]};
5863             }
5864             }
5865             else {
5866 0           $char[$i-1] = '(?:' . $char[$i-1] . ')';
5867             }
5868             }
5869             }
5870              
5871             # make regexp string
5872 0           $modifier =~ tr/i//d;
5873 0 0         if ($left_e > $right_e) {
5874 0 0 0       if (($ope =~ /\A m? \z/oxms) and ($delimiter eq '?')) {
5875 0           return join '', $ope, $delimiter, $anchor, @char, '>]}' x ($left_e - $right_e), $matched, $end_delimiter, $modifier;
5876             }
5877             else {
5878 0           return join '', $ope, $delimiter, $anchor, '(?:', @char, '>]}' x ($left_e - $right_e), ')', $matched, $end_delimiter, $modifier;
5879             }
5880             }
5881 0 0 0       if (($ope =~ /\A m? \z/oxms) and ($delimiter eq '?')) {
5882 0           return join '', $ope, $delimiter, $anchor, @char, $matched, $end_delimiter, $modifier;
5883             }
5884             else {
5885 0           return join '', $ope, $delimiter, $anchor, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
5886             }
5887             }
5888              
5889             #
5890             # double quote stuff
5891             #
5892             sub qq_stuff {
5893 0     0 0   my($delimiter,$end_delimiter,$stuff) = @_;
5894              
5895             # scalar variable or array variable
5896 0 0         if ($stuff =~ /\A [\$\@] /oxms) {
5897 0           return $stuff;
5898             }
5899              
5900             # quote by delimiter
5901 0           my %octet = map {$_ => 1} ($stuff =~ /\G ([\x00-\xFF]) /oxmsg);
  0            
5902 0           for my $char (qw( ! " $ % & * + - . / : = ? @ ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
5903 0 0         next if $char eq $delimiter;
5904 0 0         next if $char eq $end_delimiter;
5905 0 0         if (not $octet{$char}) {
5906 0           return join '', 'qq', $char, $stuff, $char;
5907             }
5908             }
5909 0           return join '', 'qq', '<', $stuff, '>';
5910             }
5911              
5912             #
5913             # escape regexp (m'', qr'', and m''b, qr''b)
5914             #
5915             sub e_qr_q {
5916 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
5917 0   0       $modifier ||= '';
5918              
5919 0           $modifier =~ tr/p//d;
5920 0 0         if ($modifier =~ /([adlu])/oxms) {
5921 0           my $line = 0;
5922 0           for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
5923 0 0         if ($filename ne __FILE__) {
5924 0           $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
5925 0           last;
5926             }
5927             }
5928 0           die qq{Unsupported modifier "$1" used at line $line.\n};
5929             }
5930              
5931 0           $slash = 'div';
5932              
5933             # literal null string pattern
5934 0 0         if ($string eq '') {
    0          
5935 0           $modifier =~ tr/bB//d;
5936 0           $modifier =~ tr/i//d;
5937 0           return join '', $ope, $delimiter, $end_delimiter, $modifier;
5938             }
5939              
5940             # with /b /B modifier
5941             elsif ($modifier =~ tr/bB//d) {
5942 0           return e_qr_qb($ope,$delimiter,$end_delimiter,$string,$modifier);
5943             }
5944              
5945             # without /b /B modifier
5946             else {
5947 0           return e_qr_qt($ope,$delimiter,$end_delimiter,$string,$modifier);
5948             }
5949             }
5950              
5951             #
5952             # escape regexp (m'', qr'')
5953             #
5954             sub e_qr_qt {
5955 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
5956              
5957 0 0         my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
5958              
5959             # split regexp
5960 0           my @char = $string =~ /\G(
5961             \[\:\^ [a-z]+ \:\] |
5962             \[\: [a-z]+ \:\] |
5963             \[\^ |
5964             [\$\@\/\\] |
5965             \\? (?:$q_char)
5966             )/oxmsg;
5967              
5968             # unescape character
5969 0           for (my $i=0; $i <= $#char; $i++) {
5970 0 0 0       if (0) {
    0 0        
    0 0        
    0          
    0          
    0          
5971             }
5972              
5973             # open character class [...]
5974 0           elsif ($char[$i] eq '[') {
5975 0           my $left = $i;
5976 0 0         if ($char[$i+1] eq ']') {
5977 0           $i++;
5978             }
5979 0           while (1) {
5980 0 0         if (++$i > $#char) {
5981 0           die __FILE__, ": Unmatched [] in regexp";
5982             }
5983 0 0         if ($char[$i] eq ']') {
5984 0           my $right = $i;
5985              
5986             # [...]
5987 0           splice @char, $left, $right-$left+1, Char::Elatin4::charlist_qr(@char[$left+1..$right-1], $modifier);
5988              
5989 0           $i = $left;
5990 0           last;
5991             }
5992             }
5993             }
5994              
5995             # open character class [^...]
5996             elsif ($char[$i] eq '[^') {
5997 0           my $left = $i;
5998 0 0         if ($char[$i+1] eq ']') {
5999 0           $i++;
6000             }
6001 0           while (1) {
6002 0 0         if (++$i > $#char) {
6003 0           die __FILE__, ": Unmatched [] in regexp";
6004             }
6005 0 0         if ($char[$i] eq ']') {
6006 0           my $right = $i;
6007              
6008             # [^...]
6009 0           splice @char, $left, $right-$left+1, Char::Elatin4::charlist_not_qr(@char[$left+1..$right-1], $modifier);
6010              
6011 0           $i = $left;
6012 0           last;
6013             }
6014             }
6015             }
6016              
6017             # escape $ @ / and \
6018             elsif ($char[$i] =~ /\A [\$\@\/\\] \z/oxms) {
6019 0           $char[$i] = '\\' . $char[$i];
6020             }
6021              
6022             # rewrite character class or escape character
6023             elsif (my $char = character_class($char[$i],$modifier)) {
6024 0           $char[$i] = $char;
6025             }
6026              
6027             # /i modifier
6028             elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Char::Elatin4::uc($char[$i]) ne Char::Elatin4::fc($char[$i]))) {
6029 0 0         if (CORE::length(Char::Elatin4::fc($char[$i])) == 1) {
6030 0           $char[$i] = '[' . Char::Elatin4::uc($char[$i]) . Char::Elatin4::fc($char[$i]) . ']';
6031             }
6032             else {
6033 0           $char[$i] = '(?:' . Char::Elatin4::uc($char[$i]) . '|' . Char::Elatin4::fc($char[$i]) . ')';
6034             }
6035             }
6036              
6037             # quote character before ? + * {
6038             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
6039 0 0         if ($char[$i-1] =~ /\A [\x00-\xFF] \z/oxms) {
6040             }
6041             else {
6042 0           $char[$i-1] = '(?:' . $char[$i-1] . ')';
6043             }
6044             }
6045             }
6046              
6047 0           $delimiter = '/';
6048 0           $end_delimiter = '/';
6049              
6050 0           $modifier =~ tr/i//d;
6051 0           return join '', $ope, $delimiter, $anchor, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
6052             }
6053              
6054             #
6055             # escape regexp (m''b, qr''b)
6056             #
6057             sub e_qr_qb {
6058 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6059              
6060             # split regexp
6061 0           my @char = $string =~ /\G(
6062             \\\\ |
6063             [\$\@\/\\] |
6064             [\x00-\xFF]
6065             )/oxmsg;
6066              
6067             # unescape character
6068 0           for (my $i=0; $i <= $#char; $i++) {
6069 0 0         if (0) {
    0          
6070             }
6071              
6072             # remain \\
6073 0           elsif ($char[$i] eq '\\\\') {
6074             }
6075              
6076             # escape $ @ / and \
6077             elsif ($char[$i] =~ /\A [\$\@\/\\] \z/oxms) {
6078 0           $char[$i] = '\\' . $char[$i];
6079             }
6080             }
6081              
6082 0           $delimiter = '/';
6083 0           $end_delimiter = '/';
6084 0           return join '', $ope, $delimiter, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
6085             }
6086              
6087             #
6088             # escape regexp (s/here//)
6089             #
6090             sub e_s1 {
6091 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6092 0   0       $modifier ||= '';
6093              
6094 0           $modifier =~ tr/p//d;
6095 0 0         if ($modifier =~ /([adlu])/oxms) {
6096 0           my $line = 0;
6097 0           for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
6098 0 0         if ($filename ne __FILE__) {
6099 0           $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
6100 0           last;
6101             }
6102             }
6103 0           die qq{Unsupported modifier "$1" used at line $line.\n};
6104             }
6105              
6106 0           $slash = 'div';
6107              
6108             # literal null string pattern
6109 0 0         if ($string eq '') {
    0          
6110 0           $modifier =~ tr/bB//d;
6111 0           $modifier =~ tr/i//d;
6112 0           return join '', $ope, $delimiter, $end_delimiter, $modifier;
6113             }
6114              
6115             # /b /B modifier
6116             elsif ($modifier =~ tr/bB//d) {
6117              
6118             # choice again delimiter
6119 0 0         if ($delimiter =~ / [\@:] /oxms) {
6120 0           my @char = $string =~ /\G([\x00-\xFF])/oxmsg;
6121 0           my %octet = map {$_ => 1} @char;
  0            
6122 0 0         if (not $octet{')'}) {
    0          
    0          
    0          
6123 0           $delimiter = '(';
6124 0           $end_delimiter = ')';
6125             }
6126             elsif (not $octet{'}'}) {
6127 0           $delimiter = '{';
6128 0           $end_delimiter = '}';
6129             }
6130             elsif (not $octet{']'}) {
6131 0           $delimiter = '[';
6132 0           $end_delimiter = ']';
6133             }
6134             elsif (not $octet{'>'}) {
6135 0           $delimiter = '<';
6136 0           $end_delimiter = '>';
6137             }
6138             else {
6139 0           for my $char (qw( ! " $ % & * + - . / = ? ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
6140 0 0         if (not $octet{$char}) {
6141 0           $delimiter = $char;
6142 0           $end_delimiter = $char;
6143 0           last;
6144             }
6145             }
6146             }
6147             }
6148              
6149 0           my $prematch = '';
6150 0           return join '', $ope, $delimiter, $prematch, '(?:', $string, ')', $matched, $end_delimiter, $modifier;
6151             }
6152              
6153 0 0         my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
6154 0           my $metachar = qr/[\@\\|[\]{^]/oxms;
6155              
6156             # split regexp
6157 0           my @char = $string =~ /\G(
6158             \\g \s* \{ \s* - \s* [1-9][0-9]* \s* \} |
6159             \\g \s* \{ \s* [1-9][0-9]* \s* \} |
6160             \\g \s* [1-9][0-9]* |
6161             \\o\{ [0-7]+ \} |
6162             \\ [1-9][0-9]* |
6163             \\ [0-7]{2,3} |
6164             \\x\{ [0-9A-Fa-f]+ \} |
6165             \\x [0-9A-Fa-f]{1,2} |
6166             \\c [\x40-\x5F] |
6167             \\N\{ [^0-9\}][^\}]* \} |
6168             \\p\{ [^0-9\}][^\}]* \} |
6169             \\P\{ [^0-9\}][^\}]* \} |
6170             \\ (?:$q_char) |
6171             \$` | \$\{`\} | \$ \s* PREMATCH | \$ \s* \{ \s* PREMATCH \s* \} | \$ \s* \{\^PREMATCH\} |
6172             \$& | \$\{&\} | \$ \s* MATCH | \$ \s* \{ \s* MATCH \s* \} | \$ \s* \{\^MATCH\} |
6173             \$ \s* POSTMATCH | \$ \s* \{ \s* POSTMATCH \s* \} | \$ \s* \{\^POSTMATCH\} |
6174             [\$\@] $qq_variable |
6175             \$ \s* \d+ |
6176             \$ \s* \{ \s* \d+ \s* \} |
6177             \$ \$ (?![\w\{]) |
6178             \$ \s* \$ \s* $qq_variable |
6179             \[\:\^ (?:alnum|alpha|ascii|blank|cntrl|digit|graph|lower|print|punct|space|upper|word|xdigit) :\] |
6180             \[\: (?:alnum|alpha|ascii|blank|cntrl|digit|graph|lower|print|punct|space|upper|word|xdigit) :\] |
6181             \[\^ |
6182             \(\? |
6183             (?:$q_char)
6184             )/oxmsg;
6185              
6186             # choice again delimiter
6187 0 0         if ($delimiter =~ / [\@:] /oxms) {
6188 0           my %octet = map {$_ => 1} @char;
  0            
6189 0 0         if (not $octet{')'}) {
    0          
    0          
    0          
6190 0           $delimiter = '(';
6191 0           $end_delimiter = ')';
6192             }
6193             elsif (not $octet{'}'}) {
6194 0           $delimiter = '{';
6195 0           $end_delimiter = '}';
6196             }
6197             elsif (not $octet{']'}) {
6198 0           $delimiter = '[';
6199 0           $end_delimiter = ']';
6200             }
6201             elsif (not $octet{'>'}) {
6202 0           $delimiter = '<';
6203 0           $end_delimiter = '>';
6204             }
6205             else {
6206 0           for my $char (qw( ! " $ % & * + - . / = ? ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
6207 0 0         if (not $octet{$char}) {
6208 0           $delimiter = $char;
6209 0           $end_delimiter = $char;
6210 0           last;
6211             }
6212             }
6213             }
6214             }
6215              
6216             # count '('
6217 0           my $parens = grep { $_ eq '(' } @char;
  0            
6218              
6219 0           my $left_e = 0;
6220 0           my $right_e = 0;
6221 0           for (my $i=0; $i <= $#char; $i++) {
6222              
6223             # "\L\u" --> "\u\L"
6224 0 0 0       if (($char[$i] eq '\L') and ($char[$i+1] eq '\u')) {
    0 0        
    0          
    0          
    0          
    0          
    0          
    0          
6225 0           @char[$i,$i+1] = @char[$i+1,$i];
6226             }
6227              
6228             # "\U\l" --> "\l\U"
6229             elsif (($char[$i] eq '\U') and ($char[$i+1] eq '\l')) {
6230 0           @char[$i,$i+1] = @char[$i+1,$i];
6231             }
6232              
6233             # octal escape sequence
6234             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
6235 0           $char[$i] = Char::Elatin4::octchr($1);
6236             }
6237              
6238             # hexadecimal escape sequence
6239             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
6240 0           $char[$i] = Char::Elatin4::hexchr($1);
6241             }
6242              
6243             # \N{CHARNAME} --> N\{CHARNAME}
6244             elsif ($char[$i] =~ /\A \\ (N) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
6245 0           $char[$i] = $1 . '\\' . $2;
6246             }
6247              
6248             # \p{PROPERTY} --> p\{PROPERTY}
6249             elsif ($char[$i] =~ /\A \\ (p) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
6250 0           $char[$i] = $1 . '\\' . $2;
6251             }
6252              
6253             # \P{PROPERTY} --> P\{PROPERTY}
6254             elsif ($char[$i] =~ /\A \\ (P) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
6255 0           $char[$i] = $1 . '\\' . $2;
6256             }
6257              
6258             # \p, \P, \X --> p, P, X
6259             elsif ($char[$i] =~ /\A \\ ( [pPX] ) \z/oxms) {
6260 0           $char[$i] = $1;
6261             }
6262              
6263 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          
6264             }
6265              
6266             # join separated multiple-octet
6267 0           elsif ($char[$i] =~ /\A (?: \\ [0-7]{2,3} | \\x [0-9A-Fa-f]{1,2}) \z/oxms) {
6268 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        
6269 0           $char[$i] .= join '', splice @char, $i+1, 3;
6270             }
6271             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)) {
6272 0           $char[$i] .= join '', splice @char, $i+1, 2;
6273             }
6274             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)) {
6275 0           $char[$i] .= join '', splice @char, $i+1, 1;
6276             }
6277             }
6278              
6279             # open character class [...]
6280             elsif ($char[$i] eq '[') {
6281 0           my $left = $i;
6282 0 0         if ($char[$i+1] eq ']') {
6283 0           $i++;
6284             }
6285 0           while (1) {
6286 0 0         if (++$i > $#char) {
6287 0           die __FILE__, ": Unmatched [] in regexp";
6288             }
6289 0 0         if ($char[$i] eq ']') {
6290 0           my $right = $i;
6291              
6292             # [...]
6293 0 0         if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
6294 0           splice @char, $left, $right-$left+1, sprintf(q{@{[Char::Elatin4::charlist_qr(%s,'%s')]}}, join(',', map {qq_stuff($delimiter,$end_delimiter,$_)} @char[$left+1..$right-1]), $modifier);
  0            
6295             }
6296             else {
6297 0           splice @char, $left, $right-$left+1, Char::Elatin4::charlist_qr(@char[$left+1..$right-1], $modifier);
6298             }
6299              
6300 0           $i = $left;
6301 0           last;
6302             }
6303             }
6304             }
6305              
6306             # open character class [^...]
6307             elsif ($char[$i] eq '[^') {
6308 0           my $left = $i;
6309 0 0         if ($char[$i+1] eq ']') {
6310 0           $i++;
6311             }
6312 0           while (1) {
6313 0 0         if (++$i > $#char) {
6314 0           die __FILE__, ": Unmatched [] in regexp";
6315             }
6316 0 0         if ($char[$i] eq ']') {
6317 0           my $right = $i;
6318              
6319             # [^...]
6320 0 0         if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
6321 0           splice @char, $left, $right-$left+1, sprintf(q{@{[Char::Elatin4::charlist_not_qr(%s,'%s')]}}, join(',', map {qq_stuff($delimiter,$end_delimiter,$_)} @char[$left+1..$right-1]), $modifier);
  0            
6322             }
6323             else {
6324 0           splice @char, $left, $right-$left+1, Char::Elatin4::charlist_not_qr(@char[$left+1..$right-1], $modifier);
6325             }
6326              
6327 0           $i = $left;
6328 0           last;
6329             }
6330             }
6331             }
6332              
6333             # rewrite character class or escape character
6334             elsif (my $char = character_class($char[$i],$modifier)) {
6335 0           $char[$i] = $char;
6336             }
6337              
6338             # /i modifier
6339             elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Char::Elatin4::uc($char[$i]) ne Char::Elatin4::fc($char[$i]))) {
6340 0 0         if (CORE::length(Char::Elatin4::fc($char[$i])) == 1) {
6341 0           $char[$i] = '[' . Char::Elatin4::uc($char[$i]) . Char::Elatin4::fc($char[$i]) . ']';
6342             }
6343             else {
6344 0           $char[$i] = '(?:' . Char::Elatin4::uc($char[$i]) . '|' . Char::Elatin4::fc($char[$i]) . ')';
6345             }
6346             }
6347              
6348             # \u \l \U \L \F \Q \E
6349             elsif ($char[$i] =~ /\A [<>] \z/oxms) {
6350 0 0         if ($right_e < $left_e) {
6351 0           $char[$i] = '\\' . $char[$i];
6352             }
6353             }
6354             elsif ($char[$i] eq '\u') {
6355 0           $char[$i] = '@{[Char::Elatin4::ucfirst qq<';
6356 0           $left_e++;
6357             }
6358             elsif ($char[$i] eq '\l') {
6359 0           $char[$i] = '@{[Char::Elatin4::lcfirst qq<';
6360 0           $left_e++;
6361             }
6362             elsif ($char[$i] eq '\U') {
6363 0           $char[$i] = '@{[Char::Elatin4::uc qq<';
6364 0           $left_e++;
6365             }
6366             elsif ($char[$i] eq '\L') {
6367 0           $char[$i] = '@{[Char::Elatin4::lc qq<';
6368 0           $left_e++;
6369             }
6370             elsif ($char[$i] eq '\F') {
6371 0           $char[$i] = '@{[Char::Elatin4::fc qq<';
6372 0           $left_e++;
6373             }
6374             elsif ($char[$i] eq '\Q') {
6375 0           $char[$i] = '@{[CORE::quotemeta qq<';
6376 0           $left_e++;
6377             }
6378             elsif ($char[$i] eq '\E') {
6379 0 0         if ($right_e < $left_e) {
6380 0           $char[$i] = '>]}';
6381 0           $right_e++;
6382             }
6383             else {
6384 0           $char[$i] = '';
6385             }
6386             }
6387             elsif ($char[$i] eq '\Q') {
6388 0           while (1) {
6389 0 0         if (++$i > $#char) {
6390 0           last;
6391             }
6392 0 0         if ($char[$i] eq '\E') {
6393 0           last;
6394             }
6395             }
6396             }
6397             elsif ($char[$i] eq '\E') {
6398             }
6399              
6400             # \0 --> \0
6401             elsif ($char[$i] =~ /\A \\ \s* 0 \z/oxms) {
6402             }
6403              
6404             # \g{N}, \g{-N}
6405              
6406             # P.108 Using Simple Patterns
6407             # in Chapter 7: In the World of Regular Expressions
6408             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
6409              
6410             # P.221 Capturing
6411             # in Chapter 5: Pattern Matching
6412             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
6413              
6414             # \g{-1}, \g{-2}, \g{-3} --> \g{-1}, \g{-2}, \g{-3}
6415             elsif ($char[$i] =~ /\A \\g \s* \{ \s* - \s* ([1-9][0-9]*) \s* \} \z/oxms) {
6416             }
6417              
6418             # \g{1}, \g{2}, \g{3} --> \g{2}, \g{3}, \g{4} (only when multibyte anchoring is enable)
6419             elsif ($char[$i] =~ /\A \\g \s* \{ \s* ([1-9][0-9]*) \s* \} \z/oxms) {
6420             }
6421              
6422             # \g1, \g2, \g3 --> \g2, \g3, \g4 (only when multibyte anchoring is enable)
6423             elsif ($char[$i] =~ /\A \\g \s* ([1-9][0-9]*) \z/oxms) {
6424             }
6425              
6426             # \1, \2, \3 --> \2, \3, \4 (only when multibyte anchoring is enable)
6427             elsif ($char[$i] =~ /\A \\ \s* ([1-9][0-9]*) \z/oxms) {
6428             }
6429              
6430             # $0 --> $0
6431             elsif ($char[$i] =~ /\A \$ 0 \z/oxms) {
6432 0 0         if ($ignorecase) {
6433 0           $char[$i] = '@{[Char::Elatin4::ignorecase(' . $char[$i] . ')]}';
6434             }
6435             }
6436             elsif ($char[$i] =~ /\A \$ \{ \s* 0 \s* \} \z/oxms) {
6437 0 0         if ($ignorecase) {
6438 0           $char[$i] = '@{[Char::Elatin4::ignorecase(' . $char[$i] . ')]}';
6439             }
6440             }
6441              
6442             # $$ --> $$
6443             elsif ($char[$i] =~ /\A \$\$ \z/oxms) {
6444             }
6445              
6446             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
6447             # $1, $2, $3 --> $1, $2, $3 otherwise
6448             elsif ($char[$i] =~ /\A \$ ([1-9][0-9]*) \z/oxms) {
6449 0           $char[$i] = e_capture($1);
6450 0 0         if ($ignorecase) {
6451 0           $char[$i] = '@{[Char::Elatin4::ignorecase(' . $char[$i] . ')]}';
6452             }
6453             }
6454             elsif ($char[$i] =~ /\A \$ \{ \s* ([1-9][0-9]*) \s* \} \z/oxms) {
6455 0           $char[$i] = e_capture($1);
6456 0 0         if ($ignorecase) {
6457 0           $char[$i] = '@{[Char::Elatin4::ignorecase(' . $char[$i] . ')]}';
6458             }
6459             }
6460              
6461             # $$foo[ ... ] --> $ $foo->[ ... ]
6462             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) ( \[ (?:$qq_bracket)*? \] ) \z/oxms) {
6463 0           $char[$i] = e_capture($1.'->'.$2);
6464 0 0         if ($ignorecase) {
6465 0           $char[$i] = '@{[Char::Elatin4::ignorecase(' . $char[$i] . ')]}';
6466             }
6467             }
6468              
6469             # $$foo{ ... } --> $ $foo->{ ... }
6470             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) ( \{ (?:$qq_brace)*? \} ) \z/oxms) {
6471 0           $char[$i] = e_capture($1.'->'.$2);
6472 0 0         if ($ignorecase) {
6473 0           $char[$i] = '@{[Char::Elatin4::ignorecase(' . $char[$i] . ')]}';
6474             }
6475             }
6476              
6477             # $$foo
6478             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) \z/oxms) {
6479 0           $char[$i] = e_capture($1);
6480 0 0         if ($ignorecase) {
6481 0           $char[$i] = '@{[Char::Elatin4::ignorecase(' . $char[$i] . ')]}';
6482             }
6483             }
6484              
6485             # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Char::Elatin4::PREMATCH()
6486             elsif ($char[$i] =~ /\A ( \$` | \$\{`\} | \$ \s* PREMATCH | \$ \s* \{ \s* PREMATCH \s* \} | \$ \s* \{\^PREMATCH\} ) \z/oxmsgc) {
6487 0 0         if ($ignorecase) {
6488 0           $char[$i] = '@{[Char::Elatin4::ignorecase(Char::Elatin4::PREMATCH())]}';
6489             }
6490             else {
6491 0           $char[$i] = '@{[Char::Elatin4::PREMATCH()]}';
6492             }
6493             }
6494              
6495             # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Char::Elatin4::MATCH()
6496             elsif ($char[$i] =~ /\A ( \$& | \$\{&\} | \$ \s* MATCH | \$ \s* \{ \s* MATCH \s* \} | \$ \s* \{\^MATCH\} ) \z/oxmsgc) {
6497 0 0         if ($ignorecase) {
6498 0           $char[$i] = '@{[Char::Elatin4::ignorecase(Char::Elatin4::MATCH())]}';
6499             }
6500             else {
6501 0           $char[$i] = '@{[Char::Elatin4::MATCH()]}';
6502             }
6503             }
6504              
6505             # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Char::Elatin4::POSTMATCH()
6506             elsif ($char[$i] =~ /\A ( \$ \s* POSTMATCH | \$ \s* \{ \s* POSTMATCH \s* \} | \$ \s* \{\^POSTMATCH\} ) \z/oxmsgc) {
6507 0 0         if ($ignorecase) {
6508 0           $char[$i] = '@{[Char::Elatin4::ignorecase(Char::Elatin4::POSTMATCH())]}';
6509             }
6510             else {
6511 0           $char[$i] = '@{[Char::Elatin4::POSTMATCH()]}';
6512             }
6513             }
6514              
6515             # ${ foo }
6516             elsif ($char[$i] =~ /\A \$ \s* \{ ( \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* ) \} \z/oxms) {
6517 0 0         if ($ignorecase) {
6518 0           $char[$i] = '@{[Char::Elatin4::ignorecase(' . $char[$i] . ')]}';
6519             }
6520             }
6521              
6522             # ${ ... }
6523             elsif ($char[$i] =~ /\A \$ \s* \{ \s* ( .+ ) \s* \} \z/oxms) {
6524 0           $char[$i] = e_capture($1);
6525 0 0         if ($ignorecase) {
6526 0           $char[$i] = '@{[Char::Elatin4::ignorecase(' . $char[$i] . ')]}';
6527             }
6528             }
6529              
6530             # $scalar or @array
6531             elsif ($char[$i] =~ /\A [\$\@].+ /oxms) {
6532 0           $char[$i] = e_string($char[$i]);
6533 0 0         if ($ignorecase) {
6534 0           $char[$i] = '@{[Char::Elatin4::ignorecase(' . $char[$i] . ')]}';
6535             }
6536             }
6537              
6538             # quote character before ? + * {
6539             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
6540 0 0         if ($char[$i-1] =~ /\A (?:\\[0-7]{2,3}|\\x[0-9-A-Fa-f]{1,2}) \z/oxms) {
6541             }
6542             else {
6543 0           $char[$i-1] = '(?:' . $char[$i-1] . ')';
6544             }
6545             }
6546             }
6547              
6548             # make regexp string
6549 0           my $prematch = '';
6550 0           $modifier =~ tr/i//d;
6551 0 0         if ($left_e > $right_e) {
6552 0           return join '', $ope, $delimiter, $prematch, '(?:', @char, '>]}' x ($left_e - $right_e), ')', $matched, $end_delimiter, $modifier;
6553             }
6554 0           return join '', $ope, $delimiter, $prematch, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
6555             }
6556              
6557             #
6558             # escape regexp (s'here'' or s'here''b)
6559             #
6560             sub e_s1_q {
6561 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6562 0   0       $modifier ||= '';
6563              
6564 0           $modifier =~ tr/p//d;
6565 0 0         if ($modifier =~ /([adlu])/oxms) {
6566 0           my $line = 0;
6567 0           for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
6568 0 0         if ($filename ne __FILE__) {
6569 0           $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
6570 0           last;
6571             }
6572             }
6573 0           die qq{Unsupported modifier "$1" used at line $line.\n};
6574             }
6575              
6576 0           $slash = 'div';
6577              
6578             # literal null string pattern
6579 0 0         if ($string eq '') {
    0          
6580 0           $modifier =~ tr/bB//d;
6581 0           $modifier =~ tr/i//d;
6582 0           return join '', $ope, $delimiter, $end_delimiter, $modifier;
6583             }
6584              
6585             # with /b /B modifier
6586             elsif ($modifier =~ tr/bB//d) {
6587 0           return e_s1_qb($ope,$delimiter,$end_delimiter,$string,$modifier);
6588             }
6589              
6590             # without /b /B modifier
6591             else {
6592 0           return e_s1_qt($ope,$delimiter,$end_delimiter,$string,$modifier);
6593             }
6594             }
6595              
6596             #
6597             # escape regexp (s'here'')
6598             #
6599             sub e_s1_qt {
6600 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6601              
6602 0 0         my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
6603              
6604             # split regexp
6605 0           my @char = $string =~ /\G(
6606             \[\:\^ [a-z]+ \:\] |
6607             \[\: [a-z]+ \:\] |
6608             \[\^ |
6609             [\$\@\/\\] |
6610             \\? (?:$q_char)
6611             )/oxmsg;
6612              
6613             # unescape character
6614 0           for (my $i=0; $i <= $#char; $i++) {
6615 0 0 0       if (0) {
    0 0        
    0 0        
    0          
    0          
    0          
6616             }
6617              
6618             # open character class [...]
6619 0           elsif ($char[$i] eq '[') {
6620 0           my $left = $i;
6621 0 0         if ($char[$i+1] eq ']') {
6622 0           $i++;
6623             }
6624 0           while (1) {
6625 0 0         if (++$i > $#char) {
6626 0           die __FILE__, ": Unmatched [] in regexp";
6627             }
6628 0 0         if ($char[$i] eq ']') {
6629 0           my $right = $i;
6630              
6631             # [...]
6632 0           splice @char, $left, $right-$left+1, Char::Elatin4::charlist_qr(@char[$left+1..$right-1], $modifier);
6633              
6634 0           $i = $left;
6635 0           last;
6636             }
6637             }
6638             }
6639              
6640             # open character class [^...]
6641             elsif ($char[$i] eq '[^') {
6642 0           my $left = $i;
6643 0 0         if ($char[$i+1] eq ']') {
6644 0           $i++;
6645             }
6646 0           while (1) {
6647 0 0         if (++$i > $#char) {
6648 0           die __FILE__, ": Unmatched [] in regexp";
6649             }
6650 0 0         if ($char[$i] eq ']') {
6651 0           my $right = $i;
6652              
6653             # [^...]
6654 0           splice @char, $left, $right-$left+1, Char::Elatin4::charlist_not_qr(@char[$left+1..$right-1], $modifier);
6655              
6656 0           $i = $left;
6657 0           last;
6658             }
6659             }
6660             }
6661              
6662             # escape $ @ / and \
6663             elsif ($char[$i] =~ /\A [\$\@\/\\] \z/oxms) {
6664 0           $char[$i] = '\\' . $char[$i];
6665             }
6666              
6667             # rewrite character class or escape character
6668             elsif (my $char = character_class($char[$i],$modifier)) {
6669 0           $char[$i] = $char;
6670             }
6671              
6672             # /i modifier
6673             elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Char::Elatin4::uc($char[$i]) ne Char::Elatin4::fc($char[$i]))) {
6674 0 0         if (CORE::length(Char::Elatin4::fc($char[$i])) == 1) {
6675 0           $char[$i] = '[' . Char::Elatin4::uc($char[$i]) . Char::Elatin4::fc($char[$i]) . ']';
6676             }
6677             else {
6678 0           $char[$i] = '(?:' . Char::Elatin4::uc($char[$i]) . '|' . Char::Elatin4::fc($char[$i]) . ')';
6679             }
6680             }
6681              
6682             # quote character before ? + * {
6683             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
6684 0 0         if ($char[$i-1] =~ /\A [\x00-\xFF] \z/oxms) {
6685             }
6686             else {
6687 0           $char[$i-1] = '(?:' . $char[$i-1] . ')';
6688             }
6689             }
6690             }
6691              
6692 0           $modifier =~ tr/i//d;
6693 0           $delimiter = '/';
6694 0           $end_delimiter = '/';
6695 0           my $prematch = '';
6696 0           return join '', $ope, $delimiter, $prematch, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
6697             }
6698              
6699             #
6700             # escape regexp (s'here''b)
6701             #
6702             sub e_s1_qb {
6703 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6704              
6705             # split regexp
6706 0           my @char = $string =~ /\G(
6707             \\\\ |
6708             [\$\@\/\\] |
6709             [\x00-\xFF]
6710             )/oxmsg;
6711              
6712             # unescape character
6713 0           for (my $i=0; $i <= $#char; $i++) {
6714 0 0         if (0) {
    0          
6715             }
6716              
6717             # remain \\
6718 0           elsif ($char[$i] eq '\\\\') {
6719             }
6720              
6721             # escape $ @ / and \
6722             elsif ($char[$i] =~ /\A [\$\@\/\\] \z/oxms) {
6723 0           $char[$i] = '\\' . $char[$i];
6724             }
6725             }
6726              
6727 0           $delimiter = '/';
6728 0           $end_delimiter = '/';
6729 0           my $prematch = '';
6730 0           return join '', $ope, $delimiter, $prematch, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
6731             }
6732              
6733             #
6734             # escape regexp (s''here')
6735             #
6736             sub e_s2_q {
6737 0     0 0   my($ope,$delimiter,$end_delimiter,$string) = @_;
6738              
6739 0           $slash = 'div';
6740              
6741 0           my @char = $string =~ / \G (\\\\|[\$\@\/\\]|$q_char) /oxmsg;
6742 0           for (my $i=0; $i <= $#char; $i++) {
6743 0 0         if (0) {
    0          
6744             }
6745              
6746             # not escape \\
6747 0           elsif ($char[$i] =~ /\A \\\\ \z/oxms) {
6748             }
6749              
6750             # escape $ @ / and \
6751             elsif ($char[$i] =~ /\A [\$\@\/\\] \z/oxms) {
6752 0           $char[$i] = '\\' . $char[$i];
6753             }
6754             }
6755              
6756 0           return join '', $ope, $delimiter, @char, $end_delimiter;
6757             }
6758              
6759             #
6760             # escape regexp (s/here/and here/modifier)
6761             #
6762             sub e_sub {
6763 0     0 0   my($variable,$delimiter1,$pattern,$end_delimiter1,$delimiter2,$replacement,$end_delimiter2,$modifier) = @_;
6764 0   0       $modifier ||= '';
6765              
6766 0           $modifier =~ tr/p//d;
6767 0 0         if ($modifier =~ /([adlu])/oxms) {
6768 0           my $line = 0;
6769 0           for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
6770 0 0         if ($filename ne __FILE__) {
6771 0           $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
6772 0           last;
6773             }
6774             }
6775 0           die qq{Unsupported modifier "$1" used at line $line.\n};
6776             }
6777              
6778 0 0         if ($variable eq '') {
6779 0           $variable = '$_';
6780 0           $bind_operator = ' =~ ';
6781             }
6782              
6783 0           $slash = 'div';
6784              
6785             # P.128 Start of match (or end of previous match): \G
6786             # P.130 Advanced Use of \G with Perl
6787             # in Chapter 3: Overview of Regular Expression Features and Flavors
6788             # P.312 Iterative Matching: Scalar Context, with /g
6789             # in Chapter 7: Perl
6790             # of ISBN 0-596-00289-0 Mastering Regular Expressions, Second edition
6791              
6792             # P.181 Where You Left Off: The \G Assertion
6793             # in Chapter 5: Pattern Matching
6794             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
6795              
6796             # P.220 Where You Left Off: The \G Assertion
6797             # in Chapter 5: Pattern Matching
6798             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
6799              
6800 0           my $e_modifier = $modifier =~ tr/e//d;
6801 0           my $r_modifier = $modifier =~ tr/r//d;
6802              
6803 0           my $my = '';
6804 0 0         if ($variable =~ s/\A \( \s* ( (?: local \b | my \b | our \b | state \b )? .+ ) \) \z/$1/oxms) {
6805 0           $my = $variable;
6806 0           $variable =~ s/ (?: local \b | my \b | our \b | state \b ) \s* //oxms;
6807 0           $variable =~ s/ = .+ \z//oxms;
6808             }
6809              
6810 0           (my $variable_basename = $variable) =~ s/ [\[\{].* \z//oxms;
6811 0           $variable_basename =~ s/ \s+ \z//oxms;
6812              
6813             # quote replacement string
6814 0           my $e_replacement = '';
6815 0 0         if ($e_modifier >= 1) {
6816 0           $e_replacement = e_qq('', '', '', $replacement);
6817 0           $e_modifier--;
6818             }
6819             else {
6820 0 0         if ($delimiter2 eq "'") {
6821 0           $e_replacement = e_s2_q('qq', '/', '/', $replacement);
6822             }
6823             else {
6824 0           $e_replacement = e_qq ('qq', $delimiter2, $end_delimiter2, $replacement);
6825             }
6826             }
6827              
6828 0           my $sub = '';
6829              
6830             # with /r
6831 0 0         if ($r_modifier) {
6832 0 0         if (0) {
6833             }
6834              
6835             # s///gr without multibyte anchoring
6836 0           elsif ($modifier =~ /g/oxms) {
6837 0 0         $sub = sprintf(
6838             # 1 2 3 4 5
6839             q,
6840              
6841             $variable, # 1
6842             ($delimiter1 eq "'") ? # 2
6843             e_s1_q('m', $delimiter1, $end_delimiter1, $pattern, $modifier) : # :
6844             e_s1 ('m', $delimiter1, $end_delimiter1, $pattern, $modifier), # :
6845             $s_matched, # 3
6846             $e_replacement, # 4
6847             '$Char::Latin4::re_r=CORE::eval $Char::Latin4::re_r; ' x $e_modifier, # 5
6848             );
6849             }
6850              
6851             # s///r
6852             else {
6853              
6854 0           my $prematch = q{$`};
6855              
6856 0 0         $sub = sprintf(
6857             # 1 2 3 4 5 6 7
6858             q<(%s =~ %s) ? CORE::eval{%s local $^W=0; local $Char::Latin4::re_r=%s; %s"%s$Char::Latin4::re_r$'" } : %s>,
6859              
6860             $variable, # 1
6861             ($delimiter1 eq "'") ? # 2
6862             e_s1_q('m', $delimiter1, $end_delimiter1, $pattern, $modifier) : # :
6863             e_s1 ('m', $delimiter1, $end_delimiter1, $pattern, $modifier), # :
6864             $s_matched, # 3
6865             $e_replacement, # 4
6866             '$Char::Latin4::re_r=CORE::eval $Char::Latin4::re_r; ' x $e_modifier, # 5
6867             $prematch, # 6
6868             $variable, # 7
6869             );
6870             }
6871              
6872             # $var !~ s///r doesn't make sense
6873 0 0         if ($bind_operator =~ / !~ /oxms) {
6874 0           $sub = q{die("$0: Using !~ with s///r doesn't make sense"), } . $sub;
6875             }
6876             }
6877              
6878             # without /r
6879             else {
6880 0 0         if (0) {
6881             }
6882              
6883             # s///g without multibyte anchoring
6884 0           elsif ($modifier =~ /g/oxms) {
6885 0 0         $sub = sprintf(
    0          
6886             # 1 2 3 4 5 6 7 8
6887             q,
6888              
6889             $variable, # 1
6890             ($delimiter1 eq "'") ? # 2
6891             e_s1_q('m', $delimiter1, $end_delimiter1, $pattern, $modifier) : # :
6892             e_s1 ('m', $delimiter1, $end_delimiter1, $pattern, $modifier), # :
6893             $s_matched, # 3
6894             $e_replacement, # 4
6895             '$Char::Latin4::re_r=CORE::eval $Char::Latin4::re_r; ' x $e_modifier, # 5
6896             $variable, # 6
6897             $variable, # 7
6898             ($bind_operator =~ / !~ /oxms) ? '!' : '', # 8
6899             );
6900             }
6901              
6902             # s///
6903             else {
6904              
6905 0           my $prematch = q{$`};
6906              
6907 0 0         $sub = sprintf(
    0          
6908              
6909             ($bind_operator =~ / =~ /oxms) ?
6910              
6911             # 1 2 3 4 5 6 7 8
6912             q<(%s%s%s) ? CORE::eval{%s local $^W=0; local $Char::Latin4::re_r=%s; %s%s="%s$Char::Latin4::re_r$'"; 1 } : undef> :
6913              
6914             # 1 2 3 4 5 6 7 8
6915             q<(%s%s%s) ? 1 : CORE::eval{%s local $^W=0; local $Char::Latin4::re_r=%s; %s%s="%s$Char::Latin4::re_r$'"; undef }>,
6916              
6917             $variable, # 1
6918             $bind_operator, # 2
6919             ($delimiter1 eq "'") ? # 3
6920             e_s1_q('m', $delimiter1, $end_delimiter1, $pattern, $modifier) : # :
6921             e_s1 ('m', $delimiter1, $end_delimiter1, $pattern, $modifier), # :
6922             $s_matched, # 4
6923             $e_replacement, # 5
6924             '$Char::Latin4::re_r=CORE::eval $Char::Latin4::re_r; ' x $e_modifier, # 6
6925             $variable, # 7
6926             $prematch, # 8
6927             );
6928             }
6929             }
6930              
6931             # (my $foo = $bar) =~ s/// --> (my $foo = $bar, CORE::eval { ... })[1]
6932 0 0         if ($my ne '') {
6933 0           $sub = "($my, $sub)[1]";
6934             }
6935              
6936             # clear s/// variable
6937 0           $sub_variable = '';
6938 0           $bind_operator = '';
6939              
6940 0           return $sub;
6941             }
6942              
6943             #
6944             # escape regexp of split qr//
6945             #
6946             sub e_split {
6947 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6948 0   0       $modifier ||= '';
6949              
6950 0           $modifier =~ tr/p//d;
6951 0 0         if ($modifier =~ /([adlu])/oxms) {
6952 0           my $line = 0;
6953 0           for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
6954 0 0         if ($filename ne __FILE__) {
6955 0           $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
6956 0           last;
6957             }
6958             }
6959 0           die qq{Unsupported modifier "$1" used at line $line.\n};
6960             }
6961              
6962 0           $slash = 'div';
6963              
6964             # /b /B modifier
6965 0 0         if ($modifier =~ tr/bB//d) {
6966 0           return join '', 'split', $ope, $delimiter, $string, $end_delimiter, $modifier;
6967             }
6968              
6969 0 0         my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
6970 0           my $metachar = qr/[\@\\|[\]{^]/oxms;
6971              
6972             # split regexp
6973 0           my @char = $string =~ /\G(
6974             \\o\{ [0-7]+ \} |
6975             \\ [0-7]{2,3} |
6976             \\x\{ [0-9A-Fa-f]+ \} |
6977             \\x [0-9A-Fa-f]{1,2} |
6978             \\c [\x40-\x5F] |
6979             \\N\{ [^0-9\}][^\}]* \} |
6980             \\p\{ [^0-9\}][^\}]* \} |
6981             \\P\{ [^0-9\}][^\}]* \} |
6982             \\ (?:$q_char) |
6983             \$` | \$\{`\} | \$ \s* PREMATCH | \$ \s* \{ \s* PREMATCH \s* \} | \$ \s* \{\^PREMATCH\} |
6984             \$& | \$\{&\} | \$ \s* MATCH | \$ \s* \{ \s* MATCH \s* \} | \$ \s* \{\^MATCH\} |
6985             \$ \s* POSTMATCH | \$ \s* \{ \s* POSTMATCH \s* \} | \$ \s* \{\^POSTMATCH\} |
6986             [\$\@] $qq_variable |
6987             \$ \s* \d+ |
6988             \$ \s* \{ \s* \d+ \s* \} |
6989             \$ \$ (?![\w\{]) |
6990             \$ \s* \$ \s* $qq_variable |
6991             \[\:\^ (?:alnum|alpha|ascii|blank|cntrl|digit|graph|lower|print|punct|space|upper|word|xdigit) :\] |
6992             \[\: (?:alnum|alpha|ascii|blank|cntrl|digit|graph|lower|print|punct|space|upper|word|xdigit) :\] |
6993             \[\^ |
6994             \(\? |
6995             (?:$q_char)
6996             )/oxmsg;
6997              
6998 0           my $left_e = 0;
6999 0           my $right_e = 0;
7000 0           for (my $i=0; $i <= $#char; $i++) {
7001              
7002             # "\L\u" --> "\u\L"
7003 0 0 0       if (($char[$i] eq '\L') and ($char[$i+1] eq '\u')) {
    0 0        
    0          
    0          
    0          
    0          
    0          
    0          
7004 0           @char[$i,$i+1] = @char[$i+1,$i];
7005             }
7006              
7007             # "\U\l" --> "\l\U"
7008             elsif (($char[$i] eq '\U') and ($char[$i+1] eq '\l')) {
7009 0           @char[$i,$i+1] = @char[$i+1,$i];
7010             }
7011              
7012             # octal escape sequence
7013             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
7014 0           $char[$i] = Char::Elatin4::octchr($1);
7015             }
7016              
7017             # hexadecimal escape sequence
7018             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
7019 0           $char[$i] = Char::Elatin4::hexchr($1);
7020             }
7021              
7022             # \N{CHARNAME} --> N\{CHARNAME}
7023             elsif ($char[$i] =~ /\A \\ (N) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
7024 0           $char[$i] = $1 . '\\' . $2;
7025             }
7026              
7027             # \p{PROPERTY} --> p\{PROPERTY}
7028             elsif ($char[$i] =~ /\A \\ (p) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
7029 0           $char[$i] = $1 . '\\' . $2;
7030             }
7031              
7032             # \P{PROPERTY} --> P\{PROPERTY}
7033             elsif ($char[$i] =~ /\A \\ (P) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
7034 0           $char[$i] = $1 . '\\' . $2;
7035             }
7036              
7037             # \p, \P, \X --> p, P, X
7038             elsif ($char[$i] =~ /\A \\ ( [pPX] ) \z/oxms) {
7039 0           $char[$i] = $1;
7040             }
7041              
7042 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          
7043             }
7044              
7045             # join separated multiple-octet
7046 0           elsif ($char[$i] =~ /\A (?: \\ [0-7]{2,3} | \\x [0-9A-Fa-f]{1,2}) \z/oxms) {
7047 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        
7048 0           $char[$i] .= join '', splice @char, $i+1, 3;
7049             }
7050             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)) {
7051 0           $char[$i] .= join '', splice @char, $i+1, 2;
7052             }
7053             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)) {
7054 0           $char[$i] .= join '', splice @char, $i+1, 1;
7055             }
7056             }
7057              
7058             # open character class [...]
7059             elsif ($char[$i] eq '[') {
7060 0           my $left = $i;
7061 0 0         if ($char[$i+1] eq ']') {
7062 0           $i++;
7063             }
7064 0           while (1) {
7065 0 0         if (++$i > $#char) {
7066 0           die __FILE__, ": Unmatched [] in regexp";
7067             }
7068 0 0         if ($char[$i] eq ']') {
7069 0           my $right = $i;
7070              
7071             # [...]
7072 0 0         if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
7073 0           splice @char, $left, $right-$left+1, sprintf(q{@{[Char::Elatin4::charlist_qr(%s,'%s')]}}, join(',', map {qq_stuff($delimiter,$end_delimiter,$_)} @char[$left+1..$right-1]), $modifier);
  0            
7074             }
7075             else {
7076 0           splice @char, $left, $right-$left+1, Char::Elatin4::charlist_qr(@char[$left+1..$right-1], $modifier);
7077             }
7078              
7079 0           $i = $left;
7080 0           last;
7081             }
7082             }
7083             }
7084              
7085             # open character class [^...]
7086             elsif ($char[$i] eq '[^') {
7087 0           my $left = $i;
7088 0 0         if ($char[$i+1] eq ']') {
7089 0           $i++;
7090             }
7091 0           while (1) {
7092 0 0         if (++$i > $#char) {
7093 0           die __FILE__, ": Unmatched [] in regexp";
7094             }
7095 0 0         if ($char[$i] eq ']') {
7096 0           my $right = $i;
7097              
7098             # [^...]
7099 0 0         if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
7100 0           splice @char, $left, $right-$left+1, sprintf(q{@{[Char::Elatin4::charlist_not_qr(%s,'%s')]}}, join(',', map {qq_stuff($delimiter,$end_delimiter,$_)} @char[$left+1..$right-1]), $modifier);
  0            
7101             }
7102             else {
7103 0           splice @char, $left, $right-$left+1, Char::Elatin4::charlist_not_qr(@char[$left+1..$right-1], $modifier);
7104             }
7105              
7106 0           $i = $left;
7107 0           last;
7108             }
7109             }
7110             }
7111              
7112             # rewrite character class or escape character
7113             elsif (my $char = character_class($char[$i],$modifier)) {
7114 0           $char[$i] = $char;
7115             }
7116              
7117             # P.794 29.2.161. split
7118             # in Chapter 29: Functions
7119             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
7120              
7121             # P.951 split
7122             # in Chapter 27: Functions
7123             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
7124              
7125             # said "The //m modifier is assumed when you split on the pattern /^/",
7126             # but perl5.008 is not so. Therefore, this software adds //m.
7127             # (and so on)
7128              
7129             # split(m/^/) --> split(m/^/m)
7130             elsif (($char[$i] eq '^') and ($modifier !~ /m/oxms)) {
7131 0           $modifier .= 'm';
7132             }
7133              
7134             # /i modifier
7135             elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Char::Elatin4::uc($char[$i]) ne Char::Elatin4::fc($char[$i]))) {
7136 0 0         if (CORE::length(Char::Elatin4::fc($char[$i])) == 1) {
7137 0           $char[$i] = '[' . Char::Elatin4::uc($char[$i]) . Char::Elatin4::fc($char[$i]) . ']';
7138             }
7139             else {
7140 0           $char[$i] = '(?:' . Char::Elatin4::uc($char[$i]) . '|' . Char::Elatin4::fc($char[$i]) . ')';
7141             }
7142             }
7143              
7144             # \u \l \U \L \F \Q \E
7145             elsif ($char[$i] =~ /\A ([<>]) \z/oxms) {
7146 0 0         if ($right_e < $left_e) {
7147 0           $char[$i] = '\\' . $char[$i];
7148             }
7149             }
7150             elsif ($char[$i] eq '\u') {
7151 0           $char[$i] = '@{[Char::Elatin4::ucfirst qq<';
7152 0           $left_e++;
7153             }
7154             elsif ($char[$i] eq '\l') {
7155 0           $char[$i] = '@{[Char::Elatin4::lcfirst qq<';
7156 0           $left_e++;
7157             }
7158             elsif ($char[$i] eq '\U') {
7159 0           $char[$i] = '@{[Char::Elatin4::uc qq<';
7160 0           $left_e++;
7161             }
7162             elsif ($char[$i] eq '\L') {
7163 0           $char[$i] = '@{[Char::Elatin4::lc qq<';
7164 0           $left_e++;
7165             }
7166             elsif ($char[$i] eq '\F') {
7167 0           $char[$i] = '@{[Char::Elatin4::fc qq<';
7168 0           $left_e++;
7169             }
7170             elsif ($char[$i] eq '\Q') {
7171 0           $char[$i] = '@{[CORE::quotemeta qq<';
7172 0           $left_e++;
7173             }
7174             elsif ($char[$i] eq '\E') {
7175 0 0         if ($right_e < $left_e) {
7176 0           $char[$i] = '>]}';
7177 0           $right_e++;
7178             }
7179             else {
7180 0           $char[$i] = '';
7181             }
7182             }
7183             elsif ($char[$i] eq '\Q') {
7184 0           while (1) {
7185 0 0         if (++$i > $#char) {
7186 0           last;
7187             }
7188 0 0         if ($char[$i] eq '\E') {
7189 0           last;
7190             }
7191             }
7192             }
7193             elsif ($char[$i] eq '\E') {
7194             }
7195              
7196             # $0 --> $0
7197             elsif ($char[$i] =~ /\A \$ 0 \z/oxms) {
7198 0 0         if ($ignorecase) {
7199 0           $char[$i] = '@{[Char::Elatin4::ignorecase(' . $char[$i] . ')]}';
7200             }
7201             }
7202             elsif ($char[$i] =~ /\A \$ \{ \s* 0 \s* \} \z/oxms) {
7203 0 0         if ($ignorecase) {
7204 0           $char[$i] = '@{[Char::Elatin4::ignorecase(' . $char[$i] . ')]}';
7205             }
7206             }
7207              
7208             # $$ --> $$
7209             elsif ($char[$i] =~ /\A \$\$ \z/oxms) {
7210             }
7211              
7212             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
7213             # $1, $2, $3 --> $1, $2, $3 otherwise
7214             elsif ($char[$i] =~ /\A \$ ([1-9][0-9]*) \z/oxms) {
7215 0           $char[$i] = e_capture($1);
7216 0 0         if ($ignorecase) {
7217 0           $char[$i] = '@{[Char::Elatin4::ignorecase(' . $char[$i] . ')]}';
7218             }
7219             }
7220             elsif ($char[$i] =~ /\A \$ \{ \s* ([1-9][0-9]*) \s* \} \z/oxms) {
7221 0           $char[$i] = e_capture($1);
7222 0 0         if ($ignorecase) {
7223 0           $char[$i] = '@{[Char::Elatin4::ignorecase(' . $char[$i] . ')]}';
7224             }
7225             }
7226              
7227             # $$foo[ ... ] --> $ $foo->[ ... ]
7228             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) ( \[ (?:$qq_bracket)*? \] ) \z/oxms) {
7229 0           $char[$i] = e_capture($1.'->'.$2);
7230 0 0         if ($ignorecase) {
7231 0           $char[$i] = '@{[Char::Elatin4::ignorecase(' . $char[$i] . ')]}';
7232             }
7233             }
7234              
7235             # $$foo{ ... } --> $ $foo->{ ... }
7236             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) ( \{ (?:$qq_brace)*? \} ) \z/oxms) {
7237 0           $char[$i] = e_capture($1.'->'.$2);
7238 0 0         if ($ignorecase) {
7239 0           $char[$i] = '@{[Char::Elatin4::ignorecase(' . $char[$i] . ')]}';
7240             }
7241             }
7242              
7243             # $$foo
7244             elsif ($char[$i] =~ /\A \$ ( \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) \z/oxms) {
7245 0           $char[$i] = e_capture($1);
7246 0 0         if ($ignorecase) {
7247 0           $char[$i] = '@{[Char::Elatin4::ignorecase(' . $char[$i] . ')]}';
7248             }
7249             }
7250              
7251             # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Char::Elatin4::PREMATCH()
7252             elsif ($char[$i] =~ /\A ( \$` | \$\{`\} | \$ \s* PREMATCH | \$ \s* \{ \s* PREMATCH \s* \} | \$ \s* \{\^PREMATCH\} ) \z/oxmsgc) {
7253 0 0         if ($ignorecase) {
7254 0           $char[$i] = '@{[Char::Elatin4::ignorecase(Char::Elatin4::PREMATCH())]}';
7255             }
7256             else {
7257 0           $char[$i] = '@{[Char::Elatin4::PREMATCH()]}';
7258             }
7259             }
7260              
7261             # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Char::Elatin4::MATCH()
7262             elsif ($char[$i] =~ /\A ( \$& | \$\{&\} | \$ \s* MATCH | \$ \s* \{ \s* MATCH \s* \} | \$ \s* \{\^MATCH\} ) \z/oxmsgc) {
7263 0 0         if ($ignorecase) {
7264 0           $char[$i] = '@{[Char::Elatin4::ignorecase(Char::Elatin4::MATCH())]}';
7265             }
7266             else {
7267 0           $char[$i] = '@{[Char::Elatin4::MATCH()]}';
7268             }
7269             }
7270              
7271             # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Char::Elatin4::POSTMATCH()
7272             elsif ($char[$i] =~ /\A ( \$ \s* POSTMATCH | \$ \s* \{ \s* POSTMATCH \s* \} | \$ \s* \{\^POSTMATCH\} ) \z/oxmsgc) {
7273 0 0         if ($ignorecase) {
7274 0           $char[$i] = '@{[Char::Elatin4::ignorecase(Char::Elatin4::POSTMATCH())]}';
7275             }
7276             else {
7277 0           $char[$i] = '@{[Char::Elatin4::POSTMATCH()]}';
7278             }
7279             }
7280              
7281             # ${ foo }
7282             elsif ($char[$i] =~ /\A \$ \s* \{ ( \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* ) \} \z/oxms) {
7283 0 0         if ($ignorecase) {
7284 0           $char[$i] = '@{[Char::Elatin4::ignorecase(' . $1 . ')]}';
7285             }
7286             }
7287              
7288             # ${ ... }
7289             elsif ($char[$i] =~ /\A \$ \s* \{ \s* ( .+ ) \s* \} \z/oxms) {
7290 0           $char[$i] = e_capture($1);
7291 0 0         if ($ignorecase) {
7292 0           $char[$i] = '@{[Char::Elatin4::ignorecase(' . $char[$i] . ')]}';
7293             }
7294             }
7295              
7296             # $scalar or @array
7297             elsif ($char[$i] =~ /\A [\$\@].+ /oxms) {
7298 0           $char[$i] = e_string($char[$i]);
7299 0 0         if ($ignorecase) {
7300 0           $char[$i] = '@{[Char::Elatin4::ignorecase(' . $char[$i] . ')]}';
7301             }
7302             }
7303              
7304             # quote character before ? + * {
7305             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
7306 0 0         if ($char[$i-1] =~ /\A (?:\\[0-7]{2,3}|\\x[0-9-A-Fa-f]{1,2}) \z/oxms) {
7307             }
7308             else {
7309 0           $char[$i-1] = '(?:' . $char[$i-1] . ')';
7310             }
7311             }
7312             }
7313              
7314             # make regexp string
7315 0           $modifier =~ tr/i//d;
7316 0 0         if ($left_e > $right_e) {
7317 0           return join '', 'Char::Elatin4::split', $ope, $delimiter, @char, '>]}' x ($left_e - $right_e), $end_delimiter, $modifier;
7318             }
7319 0           return join '', 'Char::Elatin4::split', $ope, $delimiter, @char, $end_delimiter, $modifier;
7320             }
7321              
7322             #
7323             # escape regexp of split qr''
7324             #
7325             sub e_split_q {
7326 0     0 0   my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
7327 0   0       $modifier ||= '';
7328              
7329 0           $modifier =~ tr/p//d;
7330 0 0         if ($modifier =~ /([adlu])/oxms) {
7331 0           my $line = 0;
7332 0           for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
7333 0 0         if ($filename ne __FILE__) {
7334 0           $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
7335 0           last;
7336             }
7337             }
7338 0           die qq{Unsupported modifier "$1" used at line $line.\n};
7339             }
7340              
7341 0           $slash = 'div';
7342              
7343             # /b /B modifier
7344 0 0         if ($modifier =~ tr/bB//d) {
7345 0           return join '', 'split', $ope, $delimiter, $string, $end_delimiter, $modifier;
7346             }
7347              
7348 0 0         my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
7349              
7350             # split regexp
7351 0           my @char = $string =~ /\G(
7352             \[\:\^ [a-z]+ \:\] |
7353             \[\: [a-z]+ \:\] |
7354             \[\^ |
7355             \\? (?:$q_char)
7356             )/oxmsg;
7357              
7358             # unescape character
7359 0           for (my $i=0; $i <= $#char; $i++) {
7360 0 0 0       if (0) {
    0 0        
    0 0        
    0 0        
    0          
    0          
7361             }
7362              
7363             # open character class [...]
7364 0           elsif ($char[$i] eq '[') {
7365 0           my $left = $i;
7366 0 0         if ($char[$i+1] eq ']') {
7367 0           $i++;
7368             }
7369 0           while (1) {
7370 0 0         if (++$i > $#char) {
7371 0           die __FILE__, ": Unmatched [] in regexp";
7372             }
7373 0 0         if ($char[$i] eq ']') {
7374 0           my $right = $i;
7375              
7376             # [...]
7377 0           splice @char, $left, $right-$left+1, Char::Elatin4::charlist_qr(@char[$left+1..$right-1], $modifier);
7378              
7379 0           $i = $left;
7380 0           last;
7381             }
7382             }
7383             }
7384              
7385             # open character class [^...]
7386             elsif ($char[$i] eq '[^') {
7387 0           my $left = $i;
7388 0 0         if ($char[$i+1] eq ']') {
7389 0           $i++;
7390             }
7391 0           while (1) {
7392 0 0         if (++$i > $#char) {
7393 0           die __FILE__, ": Unmatched [] in regexp";
7394             }
7395 0 0         if ($char[$i] eq ']') {
7396 0           my $right = $i;
7397              
7398             # [^...]
7399 0           splice @char, $left, $right-$left+1, Char::Elatin4::charlist_not_qr(@char[$left+1..$right-1], $modifier);
7400              
7401 0           $i = $left;
7402 0           last;
7403             }
7404             }
7405             }
7406              
7407             # rewrite character class or escape character
7408             elsif (my $char = character_class($char[$i],$modifier)) {
7409 0           $char[$i] = $char;
7410             }
7411              
7412             # split(m/^/) --> split(m/^/m)
7413             elsif (($char[$i] eq '^') and ($modifier !~ /m/oxms)) {
7414 0           $modifier .= 'm';
7415             }
7416              
7417             # /i modifier
7418             elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Char::Elatin4::uc($char[$i]) ne Char::Elatin4::fc($char[$i]))) {
7419 0 0         if (CORE::length(Char::Elatin4::fc($char[$i])) == 1) {
7420 0           $char[$i] = '[' . Char::Elatin4::uc($char[$i]) . Char::Elatin4::fc($char[$i]) . ']';
7421             }
7422             else {
7423 0           $char[$i] = '(?:' . Char::Elatin4::uc($char[$i]) . '|' . Char::Elatin4::fc($char[$i]) . ')';
7424             }
7425             }
7426              
7427             # quote character before ? + * {
7428             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
7429 0 0         if ($char[$i-1] =~ /\A [\x00-\xFF] \z/oxms) {
7430             }
7431             else {
7432 0           $char[$i-1] = '(?:' . $char[$i-1] . ')';
7433             }
7434             }
7435             }
7436              
7437 0           $modifier =~ tr/i//d;
7438 0           return join '', 'Char::Elatin4::split', $ope, $delimiter, @char, $end_delimiter, $modifier;
7439             }
7440              
7441             #
7442             # instead of Carp::carp
7443             #
7444             sub carp {
7445 0     0 0   my($package,$filename,$line) = caller(1);
7446 0           print STDERR "@_ at $filename line $line.\n";
7447             }
7448              
7449             #
7450             # instead of Carp::croak
7451             #
7452             sub croak {
7453 0     0 0   my($package,$filename,$line) = caller(1);
7454 0           print STDERR "@_ at $filename line $line.\n";
7455 0           die "\n";
7456             }
7457              
7458             #
7459             # instead of Carp::cluck
7460             #
7461             sub cluck {
7462 0     0 0   my $i = 0;
7463 0           my @cluck = ();
7464 0           while (my($package,$filename,$line,$subroutine) = caller($i)) {
7465 0           push @cluck, "[$i] $filename($line) $package::$subroutine\n";
7466 0           $i++;
7467             }
7468 0           print STDERR CORE::reverse @cluck;
7469 0           print STDERR "\n";
7470 0           carp @_;
7471             }
7472              
7473             #
7474             # instead of Carp::confess
7475             #
7476             sub confess {
7477 0     0 0   my $i = 0;
7478 0           my @confess = ();
7479 0           while (my($package,$filename,$line,$subroutine) = caller($i)) {
7480 0           push @confess, "[$i] $filename($line) $package::$subroutine\n";
7481 0           $i++;
7482             }
7483 0           print STDERR CORE::reverse @confess;
7484 0           print STDERR "\n";
7485 0           croak @_;
7486             }
7487              
7488             1;
7489              
7490             __END__