File Coverage

blib/lib/Elatin7.pm
Criterion Covered Total %
statement 905 3194 28.3
branch 968 2740 35.3
condition 98 355 27.6
subroutine 52 110 47.2
pod 7 74 9.4
total 2030 6473 31.3


line stmt bran cond sub pod time code
1             package Elatin7;
2 204     204   1273 use strict;
  204         322  
  204         6775  
3             ######################################################################
4             #
5             # Elatin7 - Run-time routines for Latin7.pm
6             #
7             # http://search.cpan.org/dist/Char-Latin7/
8             #
9             # Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2018, 2019 INABA Hitoshi
10             ######################################################################
11              
12 204     204   4106 use 5.00503; # Galapagos Consensus 1998 for primetools
  204         851  
13             # use 5.008001; # Lancaster Consensus 2013 for toolchains
14              
15             # 12.3. Delaying use Until Runtime
16             # in Chapter 12. Packages, Libraries, and Modules
17             # of ISBN 0-596-00313-7 Perl Cookbook, 2nd Edition.
18             # (and so on)
19              
20             # Version numbers should be boring
21             # http://www.dagolden.com/index.php/369/version-numbers-should-be-boring/
22             # For the impatient, the disinterested or those who just want to follow
23             # a recipe, my advice for all modules is this:
24             # our $VERSION = "0.001"; # or "0.001_001" for a dev release
25             # $VERSION = eval $VERSION; # No!! because '1.10' makes '1.1'
26              
27 204     204   984 use vars qw($VERSION);
  204         341  
  204         31242  
28             $VERSION = '1.13';
29             $VERSION = $VERSION;
30              
31             BEGIN {
32 204 50   204   1486 if ($^X =~ / jperl /oxmsi) {
33 0         0 die __FILE__, ": needs perl(not jperl) 5.00503 or later. (\$^X==$^X)\n";
34             }
35 204         655 if (CORE::ord('A') == 193) {
36             die __FILE__, ": is not US-ASCII script (may be EBCDIC or EBCDIK script).\n";
37             }
38 204         30402 if (CORE::ord('A') != 0x41) {
39             die __FILE__, ": is not US-ASCII script (must be US-ASCII script).\n";
40             }
41             }
42              
43             BEGIN {
44              
45             # instead of utf8.pm
46 204     204   15409 CORE::eval q{
  204     204   1510  
  204     66   413  
  204         22131  
  0         0  
  0         0  
  0         0  
  0         0  
47             no warnings qw(redefine);
48             *utf8::upgrade = sub { CORE::length $_[0] };
49             *utf8::downgrade = sub { 1 };
50             *utf8::encode = sub { };
51             *utf8::decode = sub { 1 };
52             *utf8::is_utf8 = sub { };
53             *utf8::valid = sub { 1 };
54             };
55 204 50       84434 if ($@) {
56 0         0 *utf8::upgrade = sub { CORE::length $_[0] };
  0         0  
57 0         0 *utf8::downgrade = sub { 1 };
  0         0  
58 0         0 *utf8::encode = sub { };
59 0         0 *utf8::decode = sub { 1 };
  0         0  
60 0         0 *utf8::is_utf8 = sub { };
61 0         0 *utf8::valid = sub { 1 };
  0         0  
62             }
63             }
64              
65             # instead of Symbol.pm
66 0         0 BEGIN {
67             sub gensym () {
68 0     0 0 0 return \do { local *_ };
  0         0  
69             }
70              
71             sub qualify ($$) {
72 0     0 0 0 my($name) = @_;
73              
74 0 0       0 if (ref $name) {
    0          
    0          
    0          
    0          
    0          
    0          
75 0         0 return $name;
76             }
77             elsif (Elatin7::index($name,'::') >= 0) {
78 0         0 return $name;
79             }
80             elsif (Elatin7::index($name,"'") >= 0) {
81 0         0 return $name;
82             }
83              
84             # special character, "^xyz"
85             elsif ($name =~ /\A \^ [ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_]+ \z/x) {
86              
87             # RGS 2001-11-05 : translate leading ^X to control-char
88 0         0 $name =~ s{\A \^ ([ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_]) }{'qq(\c'.$1.')'}xee;
  0         0  
89 0         0 return 'main::' . $name;
90             }
91              
92             # Global names
93             elsif ($name =~ /\A (?: ARGV | ARGVOUT | ENV | INC | SIG | STDERR | STDIN | STDOUT ) \z/x) {
94 0         0 return 'main::' . $name;
95             }
96              
97             # or other
98             elsif ($name =~ /\A [^ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz] \z/x) {
99 0         0 return 'main::' . $name;
100             }
101              
102             elsif (defined $_[1]) {
103 0         0 return $_[1] . '::' . $name;
104             }
105             else {
106 0         0 return (caller)[0] . '::' . $name;
107             }
108             }
109              
110             sub qualify_to_ref ($;$) {
111 0 0   0 0 0 if (defined $_[1]) {
112 204     204   1686 no strict qw(refs);
  204         366  
  204         19377  
113 0         0 return \*{ qualify $_[0], $_[1] };
  0         0  
114             }
115             else {
116 204     204   2281 no strict qw(refs);
  204     0   360  
  204         38573  
117 0         0 return \*{ qualify $_[0], (caller)[0] };
  0         0  
118             }
119             }
120             }
121              
122             # P.714 29.2.39. flock
123             # in Chapter 29: Functions
124             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
125              
126             # P.863 flock
127             # in Chapter 27: Functions
128             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
129              
130             sub LOCK_SH() {1}
131             sub LOCK_EX() {2}
132             sub LOCK_UN() {8}
133             sub LOCK_NB() {4}
134              
135             # instead of Carp.pm
136             sub carp;
137             sub croak;
138             sub cluck;
139             sub confess;
140              
141             # 6.18. Matching Multiple-Byte Characters
142             # in Chapter 6. Pattern Matching
143             # of ISBN 978-1-56592-243-3 Perl Perl Cookbook.
144             # (and so on)
145              
146             # regexp of character
147             my $your_char = q{[\x00-\xFF]};
148 204     204   1225 use vars qw($qq_char); $qq_char = qr/\\c[\x40-\x5F]|\\?(?:$your_char)/oxms;
  204         386  
  204         16589  
149 204     204   1208 use vars qw($q_char); $q_char = qr/$your_char/oxms;
  204         468  
  204         375574  
150              
151             #
152             # Latin-7 character range per length
153             #
154             my %range_tr = ();
155              
156             #
157             # Latin-7 case conversion
158             #
159             my %lc = ();
160             @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)} =
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 %uc = ();
163             @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)} =
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             my %fc = ();
166             @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)} =
167             qw(a b c d e f g h i j k l m n o p q r s t u v w x y z);
168              
169             if (0) {
170             }
171              
172             elsif (__PACKAGE__ =~ / \b Elatin7 \z/oxms) {
173             %range_tr = (
174             1 => [ [0x00..0xFF],
175             ],
176             );
177              
178             %lc = (%lc,
179             "\xA8" => "\xB8", # LATIN LETTER O WITH STROKE
180             "\xAA" => "\xBA", # LATIN LETTER R WITH CEDILLA
181             "\xAF" => "\xBF", # LATIN LETTER AE
182             "\xC0" => "\xE0", # LATIN LETTER A WITH OGONEK
183             "\xC1" => "\xE1", # LATIN LETTER I WITH OGONEK
184             "\xC2" => "\xE2", # LATIN LETTER A WITH MACRON
185             "\xC3" => "\xE3", # LATIN LETTER C WITH ACUTE
186             "\xC4" => "\xE4", # LATIN LETTER A WITH DIAERESIS
187             "\xC5" => "\xE5", # LATIN LETTER A WITH RING ABOVE
188             "\xC6" => "\xE6", # LATIN LETTER E WITH OGONEK
189             "\xC7" => "\xE7", # LATIN LETTER E WITH MACRON
190             "\xC8" => "\xE8", # LATIN LETTER C WITH CARON
191             "\xC9" => "\xE9", # LATIN LETTER E WITH ACUTE
192             "\xCA" => "\xEA", # LATIN LETTER Z WITH ACUTE
193             "\xCB" => "\xEB", # LATIN LETTER E WITH DOT ABOVE
194             "\xCC" => "\xEC", # LATIN LETTER G WITH CEDILLA
195             "\xCD" => "\xED", # LATIN LETTER K WITH CEDILLA
196             "\xCE" => "\xEE", # LATIN LETTER I WITH MACRON
197             "\xCF" => "\xEF", # LATIN LETTER L WITH CEDILLA
198             "\xD0" => "\xF0", # LATIN LETTER S WITH CARON
199             "\xD1" => "\xF1", # LATIN LETTER N WITH ACUTE
200             "\xD2" => "\xF2", # LATIN LETTER N WITH CEDILLA
201             "\xD3" => "\xF3", # LATIN LETTER O WITH ACUTE
202             "\xD4" => "\xF4", # LATIN LETTER O WITH MACRON
203             "\xD5" => "\xF5", # LATIN LETTER O WITH TILDE
204             "\xD6" => "\xF6", # LATIN LETTER O WITH DIAERESIS
205             "\xD8" => "\xF8", # LATIN LETTER U WITH OGONEK
206             "\xD9" => "\xF9", # LATIN LETTER L WITH STROKE
207             "\xDA" => "\xFA", # LATIN LETTER S WITH ACUTE
208             "\xDB" => "\xFB", # LATIN LETTER U WITH MACRON
209             "\xDC" => "\xFC", # LATIN LETTER U WITH DIAERESIS
210             "\xDD" => "\xFD", # LATIN LETTER Z WITH DOT ABOVE
211             "\xDE" => "\xFE", # LATIN LETTER Z WITH CARON
212             );
213              
214             %uc = (%uc,
215             "\xB8" => "\xA8", # LATIN LETTER O WITH STROKE
216             "\xBA" => "\xAA", # LATIN LETTER R WITH CEDILLA
217             "\xBF" => "\xAF", # LATIN LETTER AE
218             "\xE0" => "\xC0", # LATIN LETTER A WITH OGONEK
219             "\xE1" => "\xC1", # LATIN LETTER I WITH OGONEK
220             "\xE2" => "\xC2", # LATIN LETTER A WITH MACRON
221             "\xE3" => "\xC3", # LATIN LETTER C WITH ACUTE
222             "\xE4" => "\xC4", # LATIN LETTER A WITH DIAERESIS
223             "\xE5" => "\xC5", # LATIN LETTER A WITH RING ABOVE
224             "\xE6" => "\xC6", # LATIN LETTER E WITH OGONEK
225             "\xE7" => "\xC7", # LATIN LETTER E WITH MACRON
226             "\xE8" => "\xC8", # LATIN LETTER C WITH CARON
227             "\xE9" => "\xC9", # LATIN LETTER E WITH ACUTE
228             "\xEA" => "\xCA", # LATIN LETTER Z WITH ACUTE
229             "\xEB" => "\xCB", # LATIN LETTER E WITH DOT ABOVE
230             "\xEC" => "\xCC", # LATIN LETTER G WITH CEDILLA
231             "\xED" => "\xCD", # LATIN LETTER K WITH CEDILLA
232             "\xEE" => "\xCE", # LATIN LETTER I WITH MACRON
233             "\xEF" => "\xCF", # LATIN LETTER L WITH CEDILLA
234             "\xF0" => "\xD0", # LATIN LETTER S WITH CARON
235             "\xF1" => "\xD1", # LATIN LETTER N WITH ACUTE
236             "\xF2" => "\xD2", # LATIN LETTER N WITH CEDILLA
237             "\xF3" => "\xD3", # LATIN LETTER O WITH ACUTE
238             "\xF4" => "\xD4", # LATIN LETTER O WITH MACRON
239             "\xF5" => "\xD5", # LATIN LETTER O WITH TILDE
240             "\xF6" => "\xD6", # LATIN LETTER O WITH DIAERESIS
241             "\xF8" => "\xD8", # LATIN LETTER U WITH OGONEK
242             "\xF9" => "\xD9", # LATIN LETTER L WITH STROKE
243             "\xFA" => "\xDA", # LATIN LETTER S WITH ACUTE
244             "\xFB" => "\xDB", # LATIN LETTER U WITH MACRON
245             "\xFC" => "\xDC", # LATIN LETTER U WITH DIAERESIS
246             "\xFD" => "\xDD", # LATIN LETTER Z WITH DOT ABOVE
247             "\xFE" => "\xDE", # LATIN LETTER Z WITH CARON
248             );
249              
250             %fc = (%fc,
251             "\xA8" => "\xB8", # LATIN CAPITAL LETTER O WITH STROKE --> LATIN SMALL LETTER O WITH STROKE
252             "\xAA" => "\xBA", # LATIN CAPITAL LETTER R WITH CEDILLA --> LATIN SMALL LETTER R WITH CEDILLA
253             "\xAF" => "\xBF", # LATIN CAPITAL LETTER AE --> LATIN SMALL LETTER AE
254             "\xC0" => "\xE0", # LATIN CAPITAL LETTER A WITH OGONEK --> LATIN SMALL LETTER A WITH OGONEK
255             "\xC1" => "\xE1", # LATIN CAPITAL LETTER I WITH OGONEK --> LATIN SMALL LETTER I WITH OGONEK
256             "\xC2" => "\xE2", # LATIN CAPITAL LETTER A WITH MACRON --> LATIN SMALL LETTER A WITH MACRON
257             "\xC3" => "\xE3", # LATIN CAPITAL LETTER C WITH ACUTE --> LATIN SMALL LETTER C WITH ACUTE
258             "\xC4" => "\xE4", # LATIN CAPITAL LETTER A WITH DIAERESIS --> LATIN SMALL LETTER A WITH DIAERESIS
259             "\xC5" => "\xE5", # LATIN CAPITAL LETTER A WITH RING ABOVE --> LATIN SMALL LETTER A WITH RING ABOVE
260             "\xC6" => "\xE6", # LATIN CAPITAL LETTER E WITH OGONEK --> LATIN SMALL LETTER E WITH OGONEK
261             "\xC7" => "\xE7", # LATIN CAPITAL LETTER E WITH MACRON --> LATIN SMALL LETTER E WITH MACRON
262             "\xC8" => "\xE8", # LATIN CAPITAL LETTER C WITH CARON --> LATIN SMALL LETTER C WITH CARON
263             "\xC9" => "\xE9", # LATIN CAPITAL LETTER E WITH ACUTE --> LATIN SMALL LETTER E WITH ACUTE
264             "\xCA" => "\xEA", # LATIN CAPITAL LETTER Z WITH ACUTE --> LATIN SMALL LETTER Z WITH ACUTE
265             "\xCB" => "\xEB", # LATIN CAPITAL LETTER E WITH DOT ABOVE --> LATIN SMALL LETTER E WITH DOT ABOVE
266             "\xCC" => "\xEC", # LATIN CAPITAL LETTER G WITH CEDILLA --> LATIN SMALL LETTER G WITH CEDILLA
267             "\xCD" => "\xED", # LATIN CAPITAL LETTER K WITH CEDILLA --> LATIN SMALL LETTER K WITH CEDILLA
268             "\xCE" => "\xEE", # LATIN CAPITAL LETTER I WITH MACRON --> LATIN SMALL LETTER I WITH MACRON
269             "\xCF" => "\xEF", # LATIN CAPITAL LETTER L WITH CEDILLA --> LATIN SMALL LETTER L WITH CEDILLA
270             "\xD0" => "\xF0", # LATIN CAPITAL LETTER S WITH CARON --> LATIN SMALL LETTER S WITH CARON
271             "\xD1" => "\xF1", # LATIN CAPITAL LETTER N WITH ACUTE --> LATIN SMALL LETTER N WITH ACUTE
272             "\xD2" => "\xF2", # LATIN CAPITAL LETTER N WITH CEDILLA --> LATIN SMALL LETTER N WITH CEDILLA
273             "\xD3" => "\xF3", # LATIN CAPITAL LETTER O WITH ACUTE --> LATIN SMALL LETTER O WITH ACUTE
274             "\xD4" => "\xF4", # LATIN CAPITAL LETTER O WITH MACRON --> LATIN SMALL LETTER O WITH MACRON
275             "\xD5" => "\xF5", # LATIN CAPITAL LETTER O WITH TILDE --> LATIN SMALL LETTER O WITH TILDE
276             "\xD6" => "\xF6", # LATIN CAPITAL LETTER O WITH DIAERESIS --> LATIN SMALL LETTER O WITH DIAERESIS
277             "\xD8" => "\xF8", # LATIN CAPITAL LETTER U WITH OGONEK --> LATIN SMALL LETTER U WITH OGONEK
278             "\xD9" => "\xF9", # LATIN CAPITAL LETTER L WITH STROKE --> LATIN SMALL LETTER L WITH STROKE
279             "\xDA" => "\xFA", # LATIN CAPITAL LETTER S WITH ACUTE --> LATIN SMALL LETTER S WITH ACUTE
280             "\xDB" => "\xFB", # LATIN CAPITAL LETTER U WITH MACRON --> LATIN SMALL LETTER U WITH MACRON
281             "\xDC" => "\xFC", # LATIN CAPITAL LETTER U WITH DIAERESIS --> LATIN SMALL LETTER U WITH DIAERESIS
282             "\xDD" => "\xFD", # LATIN CAPITAL LETTER Z WITH DOT ABOVE --> LATIN SMALL LETTER Z WITH DOT ABOVE
283             "\xDE" => "\xFE", # LATIN CAPITAL LETTER Z WITH CARON --> LATIN SMALL LETTER Z WITH CARON
284             "\xDF" => "\x73\x73", # LATIN SMALL LETTER SHARP S --> LATIN SMALL LETTER S, LATIN SMALL LETTER S
285             );
286             }
287              
288             else {
289             croak "Don't know my package name '@{[__PACKAGE__]}'";
290             }
291              
292             #
293             # @ARGV wildcard globbing
294             #
295             sub import {
296              
297 0 0   0   0 if ($^O =~ /\A (?: MSWin32 | NetWare | symbian | dos ) \z/oxms) {
298 0         0 my @argv = ();
299 0         0 for (@ARGV) {
300              
301             # has space
302 0 0       0 if (/\A (?:$q_char)*? [ ] /oxms) {
    0          
303 0 0       0 if (my @glob = Elatin7::glob(qq{"$_"})) {
304 0         0 push @argv, @glob;
305             }
306             else {
307 0         0 push @argv, $_;
308             }
309             }
310              
311             # has wildcard metachar
312             elsif (/\A (?:$q_char)*? [*?] /oxms) {
313 0 0       0 if (my @glob = Elatin7::glob($_)) {
314 0         0 push @argv, @glob;
315             }
316             else {
317 0         0 push @argv, $_;
318             }
319             }
320              
321             # no wildcard globbing
322             else {
323 0         0 push @argv, $_;
324             }
325             }
326 0         0 @ARGV = @argv;
327             }
328              
329 0         0 *Char::ord = \&Latin7::ord;
330 0         0 *Char::ord_ = \&Latin7::ord_;
331 0         0 *Char::reverse = \&Latin7::reverse;
332 0         0 *Char::getc = \&Latin7::getc;
333 0         0 *Char::length = \&Latin7::length;
334 0         0 *Char::substr = \&Latin7::substr;
335 0         0 *Char::index = \&Latin7::index;
336 0         0 *Char::rindex = \&Latin7::rindex;
337 0         0 *Char::eval = \&Latin7::eval;
338 0         0 *Char::escape = \&Latin7::escape;
339 0         0 *Char::escape_token = \&Latin7::escape_token;
340 0         0 *Char::escape_script = \&Latin7::escape_script;
341             }
342              
343             # P.230 Care with Prototypes
344             # in Chapter 6: Subroutines
345             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
346             #
347             # If you aren't careful, you can get yourself into trouble with prototypes.
348             # But if you are careful, you can do a lot of neat things with them. This is
349             # all very powerful, of course, and should only be used in moderation to make
350             # the world a better place.
351              
352             # P.332 Care with Prototypes
353             # in Chapter 7: Subroutines
354             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
355             #
356             # If you aren't careful, you can get yourself into trouble with prototypes.
357             # But if you are careful, you can do a lot of neat things with them. This is
358             # all very powerful, of course, and should only be used in moderation to make
359             # the world a better place.
360              
361             #
362             # Prototypes of subroutines
363             #
364       0     sub unimport {}
365             sub Elatin7::split(;$$$);
366             sub Elatin7::tr($$$$;$);
367             sub Elatin7::chop(@);
368             sub Elatin7::index($$;$);
369             sub Elatin7::rindex($$;$);
370             sub Elatin7::lcfirst(@);
371             sub Elatin7::lcfirst_();
372             sub Elatin7::lc(@);
373             sub Elatin7::lc_();
374             sub Elatin7::ucfirst(@);
375             sub Elatin7::ucfirst_();
376             sub Elatin7::uc(@);
377             sub Elatin7::uc_();
378             sub Elatin7::fc(@);
379             sub Elatin7::fc_();
380             sub Elatin7::ignorecase;
381             sub Elatin7::classic_character_class;
382             sub Elatin7::capture;
383             sub Elatin7::chr(;$);
384             sub Elatin7::chr_();
385             sub Elatin7::glob($);
386             sub Elatin7::glob_();
387              
388             sub Latin7::ord(;$);
389             sub Latin7::ord_();
390             sub Latin7::reverse(@);
391             sub Latin7::getc(;*@);
392             sub Latin7::length(;$);
393             sub Latin7::substr($$;$$);
394             sub Latin7::index($$;$);
395             sub Latin7::rindex($$;$);
396             sub Latin7::escape(;$);
397              
398             #
399             # Regexp work
400             #
401 204         18086 use vars qw(
402             $re_a
403             $re_t
404             $re_n
405             $re_r
406 204     204   1685 );
  204         409  
407              
408             #
409             # Character class
410             #
411 204         2290105 use vars qw(
412             $dot
413             $dot_s
414             $eD
415             $eS
416             $eW
417             $eH
418             $eV
419             $eR
420             $eN
421             $not_alnum
422             $not_alpha
423             $not_ascii
424             $not_blank
425             $not_cntrl
426             $not_digit
427             $not_graph
428             $not_lower
429             $not_lower_i
430             $not_print
431             $not_punct
432             $not_space
433             $not_upper
434             $not_upper_i
435             $not_word
436             $not_xdigit
437             $eb
438             $eB
439 204     204   1467 );
  204         355  
440              
441             ${Elatin7::dot} = qr{(?>[^\x0A])};
442             ${Elatin7::dot_s} = qr{(?>[\x00-\xFF])};
443             ${Elatin7::eD} = qr{(?>[^0-9])};
444              
445             # Vertical tabs are now whitespace
446             # \s in a regex now matches a vertical tab in all circumstances.
447             # http://search.cpan.org/dist/perl-5.18.0/pod/perldelta.pod#Vertical_tabs_are_now_whitespace
448             # ${Elatin7::eS} = qr{(?>[^\x09\x0A \x0C\x0D\x20])};
449             # ${Elatin7::eS} = qr{(?>[^\x09\x0A\x0B\x0C\x0D\x20])};
450             ${Elatin7::eS} = qr{(?>[^\s])};
451              
452             ${Elatin7::eW} = qr{(?>[^0-9A-Z_a-z])};
453             ${Elatin7::eH} = qr{(?>[^\x09\x20])};
454             ${Elatin7::eV} = qr{(?>[^\x0A\x0B\x0C\x0D])};
455             ${Elatin7::eR} = qr{(?>\x0D\x0A|[\x0A\x0D])};
456             ${Elatin7::eN} = qr{(?>[^\x0A])};
457             ${Elatin7::not_alnum} = qr{(?>[^\x30-\x39\x41-\x5A\x61-\x7A])};
458             ${Elatin7::not_alpha} = qr{(?>[^\x41-\x5A\x61-\x7A])};
459             ${Elatin7::not_ascii} = qr{(?>[^\x00-\x7F])};
460             ${Elatin7::not_blank} = qr{(?>[^\x09\x20])};
461             ${Elatin7::not_cntrl} = qr{(?>[^\x00-\x1F\x7F])};
462             ${Elatin7::not_digit} = qr{(?>[^\x30-\x39])};
463             ${Elatin7::not_graph} = qr{(?>[^\x21-\x7F])};
464             ${Elatin7::not_lower} = qr{(?>[^\x61-\x7A])};
465             ${Elatin7::not_lower_i} = qr{(?>[^\x41-\x5A\x61-\x7A])}; # Perl 5.16 compatible
466             # ${Elatin7::not_lower_i} = qr{(?>[\x00-\xFF])}; # older Perl compatible
467             ${Elatin7::not_print} = qr{(?>[^\x20-\x7F])};
468             ${Elatin7::not_punct} = qr{(?>[^\x21-\x2F\x3A-\x3F\x40\x5B-\x5F\x60\x7B-\x7E])};
469             ${Elatin7::not_space} = qr{(?>[^\s\x0B])};
470             ${Elatin7::not_upper} = qr{(?>[^\x41-\x5A])};
471             ${Elatin7::not_upper_i} = qr{(?>[^\x41-\x5A\x61-\x7A])}; # Perl 5.16 compatible
472             # ${Elatin7::not_upper_i} = qr{(?>[\x00-\xFF])}; # older Perl compatible
473             ${Elatin7::not_word} = qr{(?>[^\x30-\x39\x41-\x5A\x5F\x61-\x7A])};
474             ${Elatin7::not_xdigit} = qr{(?>[^\x30-\x39\x41-\x46\x61-\x66])};
475             ${Elatin7::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))};
476             ${Elatin7::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]))};
477              
478             # avoid: Name "Elatin7::foo" used only once: possible typo at here.
479             ${Elatin7::dot} = ${Elatin7::dot};
480             ${Elatin7::dot_s} = ${Elatin7::dot_s};
481             ${Elatin7::eD} = ${Elatin7::eD};
482             ${Elatin7::eS} = ${Elatin7::eS};
483             ${Elatin7::eW} = ${Elatin7::eW};
484             ${Elatin7::eH} = ${Elatin7::eH};
485             ${Elatin7::eV} = ${Elatin7::eV};
486             ${Elatin7::eR} = ${Elatin7::eR};
487             ${Elatin7::eN} = ${Elatin7::eN};
488             ${Elatin7::not_alnum} = ${Elatin7::not_alnum};
489             ${Elatin7::not_alpha} = ${Elatin7::not_alpha};
490             ${Elatin7::not_ascii} = ${Elatin7::not_ascii};
491             ${Elatin7::not_blank} = ${Elatin7::not_blank};
492             ${Elatin7::not_cntrl} = ${Elatin7::not_cntrl};
493             ${Elatin7::not_digit} = ${Elatin7::not_digit};
494             ${Elatin7::not_graph} = ${Elatin7::not_graph};
495             ${Elatin7::not_lower} = ${Elatin7::not_lower};
496             ${Elatin7::not_lower_i} = ${Elatin7::not_lower_i};
497             ${Elatin7::not_print} = ${Elatin7::not_print};
498             ${Elatin7::not_punct} = ${Elatin7::not_punct};
499             ${Elatin7::not_space} = ${Elatin7::not_space};
500             ${Elatin7::not_upper} = ${Elatin7::not_upper};
501             ${Elatin7::not_upper_i} = ${Elatin7::not_upper_i};
502             ${Elatin7::not_word} = ${Elatin7::not_word};
503             ${Elatin7::not_xdigit} = ${Elatin7::not_xdigit};
504             ${Elatin7::eb} = ${Elatin7::eb};
505             ${Elatin7::eB} = ${Elatin7::eB};
506              
507             #
508             # Latin-7 split
509             #
510             sub Elatin7::split(;$$$) {
511              
512             # P.794 29.2.161. split
513             # in Chapter 29: Functions
514             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
515              
516             # P.951 split
517             # in Chapter 27: Functions
518             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
519              
520 0     0 0 0 my $pattern = $_[0];
521 0         0 my $string = $_[1];
522 0         0 my $limit = $_[2];
523              
524             # if $pattern is also omitted or is the literal space, " "
525 0 0       0 if (not defined $pattern) {
526 0         0 $pattern = ' ';
527             }
528              
529             # if $string is omitted, the function splits the $_ string
530 0 0       0 if (not defined $string) {
531 0 0       0 if (defined $_) {
532 0         0 $string = $_;
533             }
534             else {
535 0         0 $string = '';
536             }
537             }
538              
539 0         0 my @split = ();
540              
541             # when string is empty
542 0 0       0 if ($string eq '') {
    0          
543              
544             # resulting list value in list context
545 0 0       0 if (wantarray) {
546 0         0 return @split;
547             }
548              
549             # count of substrings in scalar context
550             else {
551 0 0       0 carp "Use of implicit split to \@_ is deprecated" if $^W;
552 0         0 @_ = @split;
553 0         0 return scalar @_;
554             }
555             }
556              
557             # split's first argument is more consistently interpreted
558             #
559             # After some changes earlier in v5.17, split's behavior has been simplified:
560             # if the PATTERN argument evaluates to a string containing one space, it is
561             # treated the way that a literal string containing one space once was.
562             # http://search.cpan.org/dist/perl-5.18.0/pod/perldelta.pod#split's_first_argument_is_more_consistently_interpreted
563              
564             # if $pattern is also omitted or is the literal space, " ", the function splits
565             # on whitespace, /\s+/, after skipping any leading whitespace
566             # (and so on)
567              
568             elsif ($pattern eq ' ') {
569 0 0       0 if (not defined $limit) {
570 0         0 return CORE::split(' ', $string);
571             }
572             else {
573 0         0 return CORE::split(' ', $string, $limit);
574             }
575             }
576              
577             # if $limit is negative, it is treated as if an arbitrarily large $limit has been specified
578 0 0 0     0 if ((not defined $limit) or ($limit <= 0)) {
    0          
579              
580             # a pattern capable of matching either the null string or something longer than the
581             # null string will split the value of $string into separate characters wherever it
582             # matches the null string between characters
583             # (and so on)
584              
585 0 0       0 if ('' =~ / \A $pattern \z /xms) {
586 0         0 my $last_subexpression_offsets = _last_subexpression_offsets($pattern);
587 0         0 my $limit = scalar(() = $string =~ /($pattern)/oxmsg);
588              
589             # P.1024 Appendix W.10 Multibyte Processing
590             # of ISBN 1-56592-224-7 CJKV Information Processing
591             # (and so on)
592              
593             # the //m modifier is assumed when you split on the pattern /^/
594             # (and so on)
595              
596             # V
597 0   0     0 while ((--$limit > 0) and ($string =~ s/\A((?:$q_char)+?)$pattern//m)) {
598              
599             # if the $pattern contains parentheses, then the substring matched by each pair of parentheses
600             # is included in the resulting list, interspersed with the fields that are ordinarily returned
601             # (and so on)
602              
603 0         0 local $@;
604 0         0 for (my $digit=1; $digit <= ($last_subexpression_offsets + 1); $digit++) {
605 0         0 push @split, CORE::eval('$' . $digit);
606             }
607             }
608             }
609              
610             else {
611 0         0 my $last_subexpression_offsets = _last_subexpression_offsets($pattern);
612              
613             # V
614 0         0 while ($string =~ s/\A((?:$q_char)*?)$pattern//m) {
615 0         0 local $@;
616 0         0 for (my $digit=1; $digit <= ($last_subexpression_offsets + 1); $digit++) {
617 0         0 push @split, CORE::eval('$' . $digit);
618             }
619             }
620             }
621             }
622              
623             elsif ($limit > 0) {
624 0 0       0 if ('' =~ / \A $pattern \z /xms) {
625 0         0 my $last_subexpression_offsets = _last_subexpression_offsets($pattern);
626 0   0     0 while ((--$limit > 0) and (CORE::length($string) > 0)) {
627              
628             # V
629 0 0       0 if ($string =~ s/\A((?:$q_char)+?)$pattern//m) {
630 0         0 local $@;
631 0         0 for (my $digit=1; $digit <= ($last_subexpression_offsets + 1); $digit++) {
632 0         0 push @split, CORE::eval('$' . $digit);
633             }
634             }
635             }
636             }
637             else {
638 0         0 my $last_subexpression_offsets = _last_subexpression_offsets($pattern);
639 0   0     0 while ((--$limit > 0) and (CORE::length($string) > 0)) {
640              
641             # V
642 0 0       0 if ($string =~ s/\A((?:$q_char)*?)$pattern//m) {
643 0         0 local $@;
644 0         0 for (my $digit=1; $digit <= ($last_subexpression_offsets + 1); $digit++) {
645 0         0 push @split, CORE::eval('$' . $digit);
646             }
647             }
648             }
649             }
650             }
651              
652 0 0       0 if (CORE::length($string) > 0) {
653 0         0 push @split, $string;
654             }
655              
656             # if $_[2] (NOT "$limit") is omitted or zero, trailing null fields are stripped from the result
657 0 0 0     0 if ((not defined $_[2]) or ($_[2] == 0)) {
658 0   0     0 while ((scalar(@split) >= 1) and ($split[-1] eq '')) {
659 0         0 pop @split;
660             }
661             }
662              
663             # resulting list value in list context
664 0 0       0 if (wantarray) {
665 0         0 return @split;
666             }
667              
668             # count of substrings in scalar context
669             else {
670 0 0       0 carp "Use of implicit split to \@_ is deprecated" if $^W;
671 0         0 @_ = @split;
672 0         0 return scalar @_;
673             }
674             }
675              
676             #
677             # get last subexpression offsets
678             #
679             sub _last_subexpression_offsets {
680 0     0   0 my $pattern = $_[0];
681              
682             # remove comment
683 0         0 $pattern =~ s/\(\?\# .*? \)//oxmsg;
684              
685 0         0 my $modifier = '';
686 0 0       0 if ($pattern =~ /\(\?\^? ([\-A-Za-z]+) :/oxms) {
687 0         0 $modifier = $1;
688 0         0 $modifier =~ s/-[A-Za-z]*//;
689             }
690              
691             # with /x modifier
692 0         0 my @char = ();
693 0 0       0 if ($modifier =~ /x/oxms) {
694 0         0 @char = $pattern =~ /\G((?>
695             [^\\\#\[\(] |
696             \\ $q_char |
697             \# (?>[^\n]*) $ |
698             \[ (?>(?:[^\\\]]|\\\\|\\\]|$q_char)+) \] |
699             \(\? |
700             $q_char
701             ))/oxmsg;
702             }
703              
704             # without /x modifier
705             else {
706 0         0 @char = $pattern =~ /\G((?>
707             [^\\\[\(] |
708             \\ $q_char |
709             \[ (?>(?:[^\\\]]|\\\\|\\\]|$q_char)+) \] |
710             \(\? |
711             $q_char
712             ))/oxmsg;
713             }
714              
715 0         0 return scalar grep { $_ eq '(' } @char;
  0         0  
716             }
717              
718             #
719             # Latin-7 transliteration (tr///)
720             #
721             sub Elatin7::tr($$$$;$) {
722              
723 0     0 0 0 my $bind_operator = $_[1];
724 0         0 my $searchlist = $_[2];
725 0         0 my $replacementlist = $_[3];
726 0   0     0 my $modifier = $_[4] || '';
727              
728 0 0       0 if ($modifier =~ /r/oxms) {
729 0 0       0 if ($bind_operator =~ / !~ /oxms) {
730 0         0 croak "Using !~ with tr///r doesn't make sense";
731             }
732             }
733              
734 0         0 my @char = $_[0] =~ /\G (?>$q_char) /oxmsg;
735 0         0 my @searchlist = _charlist_tr($searchlist);
736 0         0 my @replacementlist = _charlist_tr($replacementlist);
737              
738 0         0 my %tr = ();
739 0         0 for (my $i=0; $i <= $#searchlist; $i++) {
740 0 0       0 if (not exists $tr{$searchlist[$i]}) {
741 0 0 0     0 if (defined $replacementlist[$i] and ($replacementlist[$i] ne '')) {
    0 0        
    0          
742 0         0 $tr{$searchlist[$i]} = $replacementlist[$i];
743             }
744             elsif ($modifier =~ /d/oxms) {
745 0         0 $tr{$searchlist[$i]} = '';
746             }
747             elsif (defined $replacementlist[-1] and ($replacementlist[-1] ne '')) {
748 0         0 $tr{$searchlist[$i]} = $replacementlist[-1];
749             }
750             else {
751 0         0 $tr{$searchlist[$i]} = $searchlist[$i];
752             }
753             }
754             }
755              
756 0         0 my $tr = 0;
757 0         0 my $replaced = '';
758 0 0       0 if ($modifier =~ /c/oxms) {
759 0         0 while (defined(my $char = shift @char)) {
760 0 0       0 if (not exists $tr{$char}) {
761 0 0       0 if (defined $replacementlist[0]) {
762 0         0 $replaced .= $replacementlist[0];
763             }
764 0         0 $tr++;
765 0 0       0 if ($modifier =~ /s/oxms) {
766 0   0     0 while (@char and (not exists $tr{$char[0]})) {
767 0         0 shift @char;
768 0         0 $tr++;
769             }
770             }
771             }
772             else {
773 0         0 $replaced .= $char;
774             }
775             }
776             }
777             else {
778 0         0 while (defined(my $char = shift @char)) {
779 0 0       0 if (exists $tr{$char}) {
780 0         0 $replaced .= $tr{$char};
781 0         0 $tr++;
782 0 0       0 if ($modifier =~ /s/oxms) {
783 0   0     0 while (@char and (exists $tr{$char[0]}) and ($tr{$char[0]} eq $tr{$char})) {
      0        
784 0         0 shift @char;
785 0         0 $tr++;
786             }
787             }
788             }
789             else {
790 0         0 $replaced .= $char;
791             }
792             }
793             }
794              
795 0 0       0 if ($modifier =~ /r/oxms) {
796 0         0 return $replaced;
797             }
798             else {
799 0         0 $_[0] = $replaced;
800 0 0       0 if ($bind_operator =~ / !~ /oxms) {
801 0         0 return not $tr;
802             }
803             else {
804 0         0 return $tr;
805             }
806             }
807             }
808              
809             #
810             # Latin-7 chop
811             #
812             sub Elatin7::chop(@) {
813              
814 0     0 0 0 my $chop;
815 0 0       0 if (@_ == 0) {
816 0         0 my @char = /\G (?>$q_char) /oxmsg;
817 0         0 $chop = pop @char;
818 0         0 $_ = join '', @char;
819             }
820             else {
821 0         0 for (@_) {
822 0         0 my @char = /\G (?>$q_char) /oxmsg;
823 0         0 $chop = pop @char;
824 0         0 $_ = join '', @char;
825             }
826             }
827 0         0 return $chop;
828             }
829              
830             #
831             # Latin-7 index by octet
832             #
833             sub Elatin7::index($$;$) {
834              
835 0     0 1 0 my($str,$substr,$position) = @_;
836 0   0     0 $position ||= 0;
837 0         0 my $pos = 0;
838              
839 0         0 while ($pos < CORE::length($str)) {
840 0 0       0 if (CORE::substr($str,$pos,CORE::length($substr)) eq $substr) {
841 0 0       0 if ($pos >= $position) {
842 0         0 return $pos;
843             }
844             }
845 0 0       0 if (CORE::substr($str,$pos) =~ /\A ($q_char) /oxms) {
846 0         0 $pos += CORE::length($1);
847             }
848             else {
849 0         0 $pos += 1;
850             }
851             }
852 0         0 return -1;
853             }
854              
855             #
856             # Latin-7 reverse index
857             #
858             sub Elatin7::rindex($$;$) {
859              
860 0     0 0 0 my($str,$substr,$position) = @_;
861 0   0     0 $position ||= CORE::length($str) - 1;
862 0         0 my $pos = 0;
863 0         0 my $rindex = -1;
864              
865 0   0     0 while (($pos < CORE::length($str)) and ($pos <= $position)) {
866 0 0       0 if (CORE::substr($str,$pos,CORE::length($substr)) eq $substr) {
867 0         0 $rindex = $pos;
868             }
869 0 0       0 if (CORE::substr($str,$pos) =~ /\A ($q_char) /oxms) {
870 0         0 $pos += CORE::length($1);
871             }
872             else {
873 0         0 $pos += 1;
874             }
875             }
876 0         0 return $rindex;
877             }
878              
879             #
880             # Latin-7 lower case first with parameter
881             #
882             sub Elatin7::lcfirst(@) {
883 0 0   0 0 0 if (@_) {
884 0         0 my $s = shift @_;
885 0 0 0     0 if (@_ and wantarray) {
886 0         0 return Elatin7::lc(CORE::substr($s,0,1)) . CORE::substr($s,1), @_;
887             }
888             else {
889 0         0 return Elatin7::lc(CORE::substr($s,0,1)) . CORE::substr($s,1);
890             }
891             }
892             else {
893 0         0 return Elatin7::lc(CORE::substr($_,0,1)) . CORE::substr($_,1);
894             }
895             }
896              
897             #
898             # Latin-7 lower case first without parameter
899             #
900             sub Elatin7::lcfirst_() {
901 0     0 0 0 return Elatin7::lc(CORE::substr($_,0,1)) . CORE::substr($_,1);
902             }
903              
904             #
905             # Latin-7 lower case with parameter
906             #
907             sub Elatin7::lc(@) {
908 0 0   0 0 0 if (@_) {
909 0         0 my $s = shift @_;
910 0 0 0     0 if (@_ and wantarray) {
911 0 0       0 return join('', map {defined($lc{$_}) ? $lc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg)), @_;
  0         0  
912             }
913             else {
914 0 0       0 return join('', map {defined($lc{$_}) ? $lc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg));
  0         0  
915             }
916             }
917             else {
918 0         0 return Elatin7::lc_();
919             }
920             }
921              
922             #
923             # Latin-7 lower case without parameter
924             #
925             sub Elatin7::lc_() {
926 0     0 0 0 my $s = $_;
927 0 0       0 return join '', map {defined($lc{$_}) ? $lc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg);
  0         0  
928             }
929              
930             #
931             # Latin-7 upper case first with parameter
932             #
933             sub Elatin7::ucfirst(@) {
934 0 0   0 0 0 if (@_) {
935 0         0 my $s = shift @_;
936 0 0 0     0 if (@_ and wantarray) {
937 0         0 return Elatin7::uc(CORE::substr($s,0,1)) . CORE::substr($s,1), @_;
938             }
939             else {
940 0         0 return Elatin7::uc(CORE::substr($s,0,1)) . CORE::substr($s,1);
941             }
942             }
943             else {
944 0         0 return Elatin7::uc(CORE::substr($_,0,1)) . CORE::substr($_,1);
945             }
946             }
947              
948             #
949             # Latin-7 upper case first without parameter
950             #
951             sub Elatin7::ucfirst_() {
952 0     0 0 0 return Elatin7::uc(CORE::substr($_,0,1)) . CORE::substr($_,1);
953             }
954              
955             #
956             # Latin-7 upper case with parameter
957             #
958             sub Elatin7::uc(@) {
959 0 50   174 0 0 if (@_) {
960 174         337 my $s = shift @_;
961 174 50 33     237 if (@_ and wantarray) {
962 174 0       478 return join('', map {defined($uc{$_}) ? $uc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg)), @_;
  0         0  
963             }
964             else {
965 0 100       0 return join('', map {defined($uc{$_}) ? $uc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg));
  174         862  
966             }
967             }
968             else {
969 174         1251 return Elatin7::uc_();
970             }
971             }
972              
973             #
974             # Latin-7 upper case without parameter
975             #
976             sub Elatin7::uc_() {
977 0     0 0 0 my $s = $_;
978 0 0       0 return join '', map {defined($uc{$_}) ? $uc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg);
  0         0  
979             }
980              
981             #
982             # Latin-7 fold case with parameter
983             #
984             sub Elatin7::fc(@) {
985 0 50   197 0 0 if (@_) {
986 197         346 my $s = shift @_;
987 197 50 33     241 if (@_ and wantarray) {
988 197 0       401 return join('', map {defined($fc{$_}) ? $fc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg)), @_;
  0         0  
989             }
990             else {
991 0 100       0 return join('', map {defined($fc{$_}) ? $fc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg));
  197         840  
992             }
993             }
994             else {
995 197         1487 return Elatin7::fc_();
996             }
997             }
998              
999             #
1000             # Latin-7 fold case without parameter
1001             #
1002             sub Elatin7::fc_() {
1003 0     0 0 0 my $s = $_;
1004 0 0       0 return join '', map {defined($fc{$_}) ? $fc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg);
  0         0  
1005             }
1006              
1007             #
1008             # Latin-7 regexp capture
1009             #
1010             {
1011             sub Elatin7::capture {
1012 0     0 1 0 return $_[0];
1013             }
1014             }
1015              
1016             #
1017             # Latin-7 regexp ignore case modifier
1018             #
1019             sub Elatin7::ignorecase {
1020              
1021 0     0 0 0 my @string = @_;
1022 0         0 my $metachar = qr/[\@\\|[\]{]/oxms;
1023              
1024             # ignore case of $scalar or @array
1025 0         0 for my $string (@string) {
1026              
1027             # split regexp
1028 0         0 my @char = $string =~ /\G (?>\[\^|\\$q_char|$q_char) /oxmsg;
1029              
1030             # unescape character
1031 0         0 for (my $i=0; $i <= $#char; $i++) {
1032 0 0       0 next if not defined $char[$i];
1033              
1034             # open character class [...]
1035 0 0       0 if ($char[$i] eq '[') {
    0          
    0          
    0          
1036 0         0 my $left = $i;
1037              
1038             # [] make die "unmatched [] in regexp ...\n"
1039              
1040 0 0       0 if ($char[$i+1] eq ']') {
1041 0         0 $i++;
1042             }
1043              
1044 0         0 while (1) {
1045 0 0       0 if (++$i > $#char) {
1046 0         0 croak "Unmatched [] in regexp";
1047             }
1048 0 0       0 if ($char[$i] eq ']') {
1049 0         0 my $right = $i;
1050 0         0 my @charlist = charlist_qr(@char[$left+1..$right-1], 'i');
1051              
1052             # escape character
1053 0         0 for my $char (@charlist) {
1054 0 0       0 if (0) {
1055             }
1056              
1057 0         0 elsif ($char =~ /\A [.|)] \z/oxms) {
1058 0         0 $char = '\\' . $char;
1059             }
1060             }
1061              
1062             # [...]
1063 0         0 splice @char, $left, $right-$left+1, '(?:' . join('|', @charlist) . ')';
1064              
1065 0         0 $i = $left;
1066 0         0 last;
1067             }
1068             }
1069             }
1070              
1071             # open character class [^...]
1072             elsif ($char[$i] eq '[^') {
1073 0         0 my $left = $i;
1074              
1075             # [^] make die "unmatched [] in regexp ...\n"
1076              
1077 0 0       0 if ($char[$i+1] eq ']') {
1078 0         0 $i++;
1079             }
1080              
1081 0         0 while (1) {
1082 0 0       0 if (++$i > $#char) {
1083 0         0 croak "Unmatched [] in regexp";
1084             }
1085 0 0       0 if ($char[$i] eq ']') {
1086 0         0 my $right = $i;
1087 0         0 my @charlist = charlist_not_qr(@char[$left+1..$right-1], 'i');
1088              
1089             # escape character
1090 0         0 for my $char (@charlist) {
1091 0 0       0 if (0) {
1092             }
1093              
1094 0         0 elsif ($char =~ /\A [.|)] \z/oxms) {
1095 0         0 $char = '\\' . $char;
1096             }
1097             }
1098              
1099             # [^...]
1100 0         0 splice @char, $left, $right-$left+1, '(?!' . join('|', @charlist) . ")(?:$your_char)";
1101              
1102 0         0 $i = $left;
1103 0         0 last;
1104             }
1105             }
1106             }
1107              
1108             # rewrite classic character class or escape character
1109             elsif (my $char = classic_character_class($char[$i])) {
1110 0         0 $char[$i] = $char;
1111             }
1112              
1113             # with /i modifier
1114             elsif ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) {
1115 0         0 my $uc = Elatin7::uc($char[$i]);
1116 0         0 my $fc = Elatin7::fc($char[$i]);
1117 0 0       0 if ($uc ne $fc) {
1118 0 0       0 if (CORE::length($fc) == 1) {
1119 0         0 $char[$i] = '[' . $uc . $fc . ']';
1120             }
1121             else {
1122 0         0 $char[$i] = '(?:' . $uc . '|' . $fc . ')';
1123             }
1124             }
1125             }
1126             }
1127              
1128             # characterize
1129 0         0 for (my $i=0; $i <= $#char; $i++) {
1130 0 0       0 next if not defined $char[$i];
1131              
1132 0 0       0 if (0) {
1133             }
1134              
1135             # quote character before ? + * {
1136 0 0       0 elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
1137 0 0       0 if ($char[$i-1] !~ /\A [\x00-\xFF] \z/oxms) {
1138 0         0 $char[$i-1] = '(?:' . $char[$i-1] . ')';
1139             }
1140             }
1141             }
1142              
1143 0         0 $string = join '', @char;
1144             }
1145              
1146             # make regexp string
1147 0         0 return @string;
1148             }
1149              
1150             #
1151             # classic character class ( \D \S \W \d \s \w \C \X \H \V \h \v \R \N \b \B )
1152             #
1153             sub Elatin7::classic_character_class {
1154 0     1867 0 0 my($char) = @_;
1155              
1156             return {
1157             '\D' => '${Elatin7::eD}',
1158             '\S' => '${Elatin7::eS}',
1159             '\W' => '${Elatin7::eW}',
1160             '\d' => '[0-9]',
1161              
1162             # Before Perl 5.6, \s only matched the five whitespace characters
1163             # tab, newline, form-feed, carriage return, and the space character
1164             # itself, which, taken together, is the character class [\t\n\f\r ].
1165              
1166             # Vertical tabs are now whitespace
1167             # \s in a regex now matches a vertical tab in all circumstances.
1168             # http://search.cpan.org/dist/perl-5.18.0/pod/perldelta.pod#Vertical_tabs_are_now_whitespace
1169             # \t \n \v \f \r space
1170             # '\s' => '[\x09\x0A \x0C\x0D\x20]',
1171             # '\s' => '[\x09\x0A\x0B\x0C\x0D\x20]',
1172             '\s' => '\s',
1173              
1174             '\w' => '[0-9A-Z_a-z]',
1175             '\C' => '[\x00-\xFF]',
1176             '\X' => 'X',
1177              
1178             # \h \v \H \V
1179              
1180             # P.114 Character Class Shortcuts
1181             # in Chapter 7: In the World of Regular Expressions
1182             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
1183              
1184             # P.357 13.2.3 Whitespace
1185             # in Chapter 13: perlrecharclass: Perl Regular Expression Character Classes
1186             # of ISBN-13: 978-1-906966-02-7 The Perl Language Reference Manual (for Perl version 5.12.1)
1187             #
1188             # 0x00009 CHARACTER TABULATION h s
1189             # 0x0000a LINE FEED (LF) vs
1190             # 0x0000b LINE TABULATION v
1191             # 0x0000c FORM FEED (FF) vs
1192             # 0x0000d CARRIAGE RETURN (CR) vs
1193             # 0x00020 SPACE h s
1194              
1195             # P.196 Table 5-9. Alphanumeric regex metasymbols
1196             # in Chapter 5. Pattern Matching
1197             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
1198              
1199             # (and so on)
1200              
1201             '\H' => '${Elatin7::eH}',
1202             '\V' => '${Elatin7::eV}',
1203             '\h' => '[\x09\x20]',
1204             '\v' => '[\x0A\x0B\x0C\x0D]',
1205             '\R' => '${Elatin7::eR}',
1206              
1207             # \N
1208             #
1209             # http://perldoc.perl.org/perlre.html
1210             # Character Classes and other Special Escapes
1211             # Any character but \n (experimental). Not affected by /s modifier
1212              
1213             '\N' => '${Elatin7::eN}',
1214              
1215             # \b \B
1216              
1217             # P.180 Boundaries: The \b and \B Assertions
1218             # in Chapter 5: Pattern Matching
1219             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
1220              
1221             # P.219 Boundaries: The \b and \B Assertions
1222             # in Chapter 5: Pattern Matching
1223             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
1224              
1225             # \b really means (?:(?<=\w)(?!\w)|(?
1226             # or (?:(?<=\A|\W)(?=\w)|(?<=\w)(?=\W|\z))
1227             '\b' => '${Elatin7::eb}',
1228              
1229             # \B really means (?:(?<=\w)(?=\w)|(?
1230             # or (?:(?<=\w)(?=\w)|(?<=\W)(?=\W))
1231             '\B' => '${Elatin7::eB}',
1232              
1233 1867   100     2658 }->{$char} || '';
1234             }
1235              
1236             #
1237             # prepare Latin-7 characters per length
1238             #
1239              
1240             # 1 octet characters
1241             my @chars1 = ();
1242             sub chars1 {
1243 1867 0   0 0 76717 if (@chars1) {
1244 0         0 return @chars1;
1245             }
1246 0 0       0 if (exists $range_tr{1}) {
1247 0         0 my @ranges = @{ $range_tr{1} };
  0         0  
1248 0         0 while (my @range = splice(@ranges,0,1)) {
1249 0         0 for my $oct0 (@{$range[0]}) {
  0         0  
1250 0         0 push @chars1, pack 'C', $oct0;
1251             }
1252             }
1253             }
1254 0         0 return @chars1;
1255             }
1256              
1257             # 2 octets characters
1258             my @chars2 = ();
1259             sub chars2 {
1260 0 0   0 0 0 if (@chars2) {
1261 0         0 return @chars2;
1262             }
1263 0 0       0 if (exists $range_tr{2}) {
1264 0         0 my @ranges = @{ $range_tr{2} };
  0         0  
1265 0         0 while (my @range = splice(@ranges,0,2)) {
1266 0         0 for my $oct0 (@{$range[0]}) {
  0         0  
1267 0         0 for my $oct1 (@{$range[1]}) {
  0         0  
1268 0         0 push @chars2, pack 'CC', $oct0,$oct1;
1269             }
1270             }
1271             }
1272             }
1273 0         0 return @chars2;
1274             }
1275              
1276             # 3 octets characters
1277             my @chars3 = ();
1278             sub chars3 {
1279 0 0   0 0 0 if (@chars3) {
1280 0         0 return @chars3;
1281             }
1282 0 0       0 if (exists $range_tr{3}) {
1283 0         0 my @ranges = @{ $range_tr{3} };
  0         0  
1284 0         0 while (my @range = splice(@ranges,0,3)) {
1285 0         0 for my $oct0 (@{$range[0]}) {
  0         0  
1286 0         0 for my $oct1 (@{$range[1]}) {
  0         0  
1287 0         0 for my $oct2 (@{$range[2]}) {
  0         0  
1288 0         0 push @chars3, pack 'CCC', $oct0,$oct1,$oct2;
1289             }
1290             }
1291             }
1292             }
1293             }
1294 0         0 return @chars3;
1295             }
1296              
1297             # 4 octets characters
1298             my @chars4 = ();
1299             sub chars4 {
1300 0 0   0 0 0 if (@chars4) {
1301 0         0 return @chars4;
1302             }
1303 0 0       0 if (exists $range_tr{4}) {
1304 0         0 my @ranges = @{ $range_tr{4} };
  0         0  
1305 0         0 while (my @range = splice(@ranges,0,4)) {
1306 0         0 for my $oct0 (@{$range[0]}) {
  0         0  
1307 0         0 for my $oct1 (@{$range[1]}) {
  0         0  
1308 0         0 for my $oct2 (@{$range[2]}) {
  0         0  
1309 0         0 for my $oct3 (@{$range[3]}) {
  0         0  
1310 0         0 push @chars4, pack 'CCCC', $oct0,$oct1,$oct2,$oct3;
1311             }
1312             }
1313             }
1314             }
1315             }
1316             }
1317 0         0 return @chars4;
1318             }
1319              
1320             #
1321             # Latin-7 open character list for tr
1322             #
1323             sub _charlist_tr {
1324              
1325 0     0   0 local $_ = shift @_;
1326              
1327             # unescape character
1328 0         0 my @char = ();
1329 0         0 while (not /\G \z/oxmsgc) {
1330 0 0       0 if (/\G (\\0?55|\\x2[Dd]|\\-) /oxmsgc) {
    0          
    0          
    0          
    0          
    0          
    0          
1331 0         0 push @char, '\-';
1332             }
1333             elsif (/\G \\ ([0-7]{2,3}) /oxmsgc) {
1334 0         0 push @char, CORE::chr(oct $1);
1335             }
1336             elsif (/\G \\x ([0-9A-Fa-f]{1,2}) /oxmsgc) {
1337 0         0 push @char, CORE::chr(hex $1);
1338             }
1339             elsif (/\G \\c ([\x40-\x5F]) /oxmsgc) {
1340 0         0 push @char, CORE::chr(CORE::ord($1) & 0x1F);
1341             }
1342             elsif (/\G (\\ [0nrtfbae]) /oxmsgc) {
1343             push @char, {
1344             '\0' => "\0",
1345             '\n' => "\n",
1346             '\r' => "\r",
1347             '\t' => "\t",
1348             '\f' => "\f",
1349             '\b' => "\x08", # \b means backspace in character class
1350             '\a' => "\a",
1351             '\e' => "\e",
1352 0         0 }->{$1};
1353             }
1354             elsif (/\G \\ ($q_char) /oxmsgc) {
1355 0         0 push @char, $1;
1356             }
1357             elsif (/\G ($q_char) /oxmsgc) {
1358 0         0 push @char, $1;
1359             }
1360             }
1361              
1362             # join separated multiple-octet
1363 0         0 @char = join('',@char) =~ /\G (?>\\-|$q_char) /oxmsg;
1364              
1365             # unescape '-'
1366 0         0 my @i = ();
1367 0         0 for my $i (0 .. $#char) {
1368 0 0       0 if ($char[$i] eq '\-') {
    0          
1369 0         0 $char[$i] = '-';
1370             }
1371             elsif ($char[$i] eq '-') {
1372 0 0 0     0 if ((0 < $i) and ($i < $#char)) {
1373 0         0 push @i, $i;
1374             }
1375             }
1376             }
1377              
1378             # open character list (reverse for splice)
1379 0         0 for my $i (CORE::reverse @i) {
1380 0         0 my @range = ();
1381              
1382             # range error
1383 0 0 0     0 if ((CORE::length($char[$i-1]) > CORE::length($char[$i+1])) or ($char[$i-1] gt $char[$i+1])) {
1384 0         0 croak "Invalid tr/// range \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1385             }
1386              
1387             # range of multiple-octet code
1388 0 0       0 if (CORE::length($char[$i-1]) == 1) {
    0          
    0          
    0          
1389 0 0       0 if (CORE::length($char[$i+1]) == 1) {
    0          
    0          
    0          
1390 0 0       0 push @range, grep {($char[$i-1] le $_) and ($_ le $char[$i+1])} chars1();
  0         0  
1391             }
1392             elsif (CORE::length($char[$i+1]) == 2) {
1393 0         0 push @range, grep {$char[$i-1] le $_} chars1();
  0         0  
1394 0         0 push @range, grep {$_ le $char[$i+1]} chars2();
  0         0  
1395             }
1396             elsif (CORE::length($char[$i+1]) == 3) {
1397 0         0 push @range, grep {$char[$i-1] le $_} chars1();
  0         0  
1398 0         0 push @range, chars2();
1399 0         0 push @range, grep {$_ le $char[$i+1]} chars3();
  0         0  
1400             }
1401             elsif (CORE::length($char[$i+1]) == 4) {
1402 0         0 push @range, grep {$char[$i-1] le $_} chars1();
  0         0  
1403 0         0 push @range, chars2();
1404 0         0 push @range, chars3();
1405 0         0 push @range, grep {$_ le $char[$i+1]} chars4();
  0         0  
1406             }
1407             else {
1408 0         0 croak "Invalid tr/// range (over 4octets) \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1409             }
1410             }
1411             elsif (CORE::length($char[$i-1]) == 2) {
1412 0 0       0 if (CORE::length($char[$i+1]) == 2) {
    0          
    0          
1413 0 0       0 push @range, grep {($char[$i-1] le $_) and ($_ le $char[$i+1])} chars2();
  0         0  
1414             }
1415             elsif (CORE::length($char[$i+1]) == 3) {
1416 0         0 push @range, grep {$char[$i-1] le $_} chars2();
  0         0  
1417 0         0 push @range, grep {$_ le $char[$i+1]} chars3();
  0         0  
1418             }
1419             elsif (CORE::length($char[$i+1]) == 4) {
1420 0         0 push @range, grep {$char[$i-1] le $_} chars2();
  0         0  
1421 0         0 push @range, chars3();
1422 0         0 push @range, grep {$_ le $char[$i+1]} chars4();
  0         0  
1423             }
1424             else {
1425 0         0 croak "Invalid tr/// range (over 4octets) \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1426             }
1427             }
1428             elsif (CORE::length($char[$i-1]) == 3) {
1429 0 0       0 if (CORE::length($char[$i+1]) == 3) {
    0          
1430 0 0       0 push @range, grep {($char[$i-1] le $_) and ($_ le $char[$i+1])} chars3();
  0         0  
1431             }
1432             elsif (CORE::length($char[$i+1]) == 4) {
1433 0         0 push @range, grep {$char[$i-1] le $_} chars3();
  0         0  
1434 0         0 push @range, grep {$_ le $char[$i+1]} chars4();
  0         0  
1435             }
1436             else {
1437 0         0 croak "Invalid tr/// range (over 4octets) \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1438             }
1439             }
1440             elsif (CORE::length($char[$i-1]) == 4) {
1441 0 0       0 if (CORE::length($char[$i+1]) == 4) {
1442 0 0       0 push @range, grep {($char[$i-1] le $_) and ($_ le $char[$i+1])} chars4();
  0         0  
1443             }
1444             else {
1445 0         0 croak "Invalid tr/// range (over 4octets) \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1446             }
1447             }
1448             else {
1449 0         0 croak "Invalid tr/// range (over 4octets) \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1450             }
1451              
1452 0         0 splice @char, $i-1, 3, @range;
1453             }
1454              
1455 0         0 return @char;
1456             }
1457              
1458             #
1459             # Latin-7 open character class
1460             #
1461             sub _cc {
1462 0 0   0   0 if (scalar(@_) == 0) {
    0          
    0          
1463 0         0 die __FILE__, ": subroutine cc got no parameter.\n";
1464             }
1465             elsif (scalar(@_) == 1) {
1466 0         0 return sprintf('\x%02X',$_[0]);
1467             }
1468             elsif (scalar(@_) == 2) {
1469 0 0       0 if ($_[0] > $_[1]) {
    0          
    0          
1470 0         0 die __FILE__, ": subroutine cc got \$_[0] > \$_[1] parameters).\n";
1471             }
1472             elsif ($_[0] == $_[1]) {
1473 0         0 return sprintf('\x%02X',$_[0]);
1474             }
1475             elsif (($_[0]+1) == $_[1]) {
1476 0         0 return sprintf('[\\x%02X\\x%02X]',$_[0],$_[1]);
1477             }
1478             else {
1479 0         0 return sprintf('[\\x%02X-\\x%02X]',$_[0],$_[1]);
1480             }
1481             }
1482             else {
1483 0         0 die __FILE__, ": subroutine cc got 3 or more parameters (@{[scalar(@_)]} parameters).\n";
  0         0  
1484             }
1485             }
1486              
1487             #
1488             # Latin-7 octet range
1489             #
1490             sub _octets {
1491 0     182   0 my $length = shift @_;
1492              
1493 182 50       651 if ($length == 1) {
1494 182         387 my($a1) = unpack 'C', $_[0];
1495 182         656 my($z1) = unpack 'C', $_[1];
1496              
1497 182 50       348 if ($a1 > $z1) {
1498 182         348 croak 'Invalid [] range in regexp (CORE::ord(A) > CORE::ord(B)) ' . '\x' . unpack('H*',$a1) . '-\x' . unpack('H*',$z1);
1499             }
1500              
1501 0 50       0 if ($a1 == $z1) {
    50          
1502 182         452 return sprintf('\x%02X',$a1);
1503             }
1504             elsif (($a1+1) == $z1) {
1505 0         0 return sprintf('\x%02X\x%02X',$a1,$z1);
1506             }
1507             else {
1508 0         0 return sprintf('\x%02X-\x%02X',$a1,$z1);
1509             }
1510             }
1511             else {
1512 182         1185 die __FILE__, ": subroutine _octets got invalid length ($length).\n";
1513             }
1514             }
1515              
1516             #
1517             # Latin-7 range regexp
1518             #
1519             sub _range_regexp {
1520 0     182   0 my($length,$first,$last) = @_;
1521              
1522 182         418 my @range_regexp = ();
1523 182 50       256 if (not exists $range_tr{$length}) {
1524 182         483 return @range_regexp;
1525             }
1526              
1527 0         0 my @ranges = @{ $range_tr{$length} };
  182         281  
1528 182         406 while (my @range = splice(@ranges,0,$length)) {
1529 182         609 my $min = '';
1530 182         274 my $max = '';
1531 182         253 for (my $i=0; $i < $length; $i++) {
1532 182         485 $min .= pack 'C', $range[$i][0];
1533 182         823 $max .= pack 'C', $range[$i][-1];
1534             }
1535              
1536             # min___max
1537             # FIRST_____________LAST
1538             # (nothing)
1539              
1540 182 50 33     635 if ($max lt $first) {
    50 33        
    50 33        
    50 33        
    50 33        
    0 0        
    0 0        
1541             }
1542              
1543             # **********
1544             # min_________max
1545             # FIRST_____________LAST
1546             # **********
1547              
1548             elsif (($min le $first) and ($first le $max) and ($max le $last)) {
1549 182         2002 push @range_regexp, _octets($length,$first,$max,$min,$max);
1550             }
1551              
1552             # **********************
1553             # min________________max
1554             # FIRST_____________LAST
1555             # **********************
1556              
1557             elsif (($min eq $first) and ($max eq $last)) {
1558 0         0 push @range_regexp, _octets($length,$first,$last,$min,$max);
1559             }
1560              
1561             # *********
1562             # min___max
1563             # FIRST_____________LAST
1564             # *********
1565              
1566             elsif (($first le $min) and ($max le $last)) {
1567 0         0 push @range_regexp, _octets($length,$min,$max,$min,$max);
1568             }
1569              
1570             # **********************
1571             # min__________________________max
1572             # FIRST_____________LAST
1573             # **********************
1574              
1575             elsif (($min le $first) and ($last le $max)) {
1576 0         0 push @range_regexp, _octets($length,$first,$last,$min,$max);
1577             }
1578              
1579             # *********
1580             # min________max
1581             # FIRST_____________LAST
1582             # *********
1583              
1584             elsif (($first le $min) and ($min le $last) and ($last le $max)) {
1585 182         661 push @range_regexp, _octets($length,$min,$last,$min,$max);
1586             }
1587              
1588             # min___max
1589             # FIRST_____________LAST
1590             # (nothing)
1591              
1592             elsif ($last lt $min) {
1593             }
1594              
1595             else {
1596 0         0 die __FILE__, ": subroutine _range_regexp panic.\n";
1597             }
1598             }
1599              
1600 0         0 return @range_regexp;
1601             }
1602              
1603             #
1604             # Latin-7 open character list for qr and not qr
1605             #
1606             sub _charlist {
1607              
1608 182     358   409 my $modifier = pop @_;
1609 358         654 my @char = @_;
1610              
1611 358 100       760 my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
1612              
1613             # unescape character
1614 358         842 for (my $i=0; $i <= $#char; $i++) {
1615              
1616             # escape - to ...
1617 358 100 100     1299 if ($char[$i] eq '-') {
    50          
    50          
    50          
    50          
    50          
    100          
    50          
    100          
    100          
    100          
    100          
1618 1125 100 100     9004 if ((0 < $i) and ($i < $#char)) {
1619 206         896 $char[$i] = '...';
1620             }
1621             }
1622              
1623             # octal escape sequence
1624             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
1625 182         413 $char[$i] = octchr($1);
1626             }
1627              
1628             # hexadecimal escape sequence
1629             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
1630 0         0 $char[$i] = hexchr($1);
1631             }
1632              
1633             # \b{...} --> b\{...}
1634             # \B{...} --> B\{...}
1635             # \N{CHARNAME} --> N\{CHARNAME}
1636             # \p{PROPERTY} --> p\{PROPERTY}
1637             # \P{PROPERTY} --> P\{PROPERTY}
1638             elsif ($char[$i] =~ /\A \\ ([bBNpP]) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
1639 0         0 $char[$i] = $1 . '\\' . $2;
1640             }
1641              
1642             # \p, \P, \X --> p, P, X
1643             elsif ($char[$i] =~ /\A \\ ( [pPX] ) \z/oxms) {
1644 0         0 $char[$i] = $1;
1645             }
1646              
1647             elsif ($char[$i] =~ /\A \\ ([0-7]{2,3}) \z/oxms) {
1648 0         0 $char[$i] = CORE::chr oct $1;
1649             }
1650             elsif ($char[$i] =~ /\A \\x ([0-9A-Fa-f]{1,2}) \z/oxms) {
1651 0         0 $char[$i] = CORE::chr hex $1;
1652             }
1653             elsif ($char[$i] =~ /\A \\c ([\x40-\x5F]) \z/oxms) {
1654 22         105 $char[$i] = CORE::chr(CORE::ord($1) & 0x1F);
1655             }
1656             elsif ($char[$i] =~ /\A (\\ [0nrtfbaedswDSWHVhvR]) \z/oxms) {
1657             $char[$i] = {
1658             '\0' => "\0",
1659             '\n' => "\n",
1660             '\r' => "\r",
1661             '\t' => "\t",
1662             '\f' => "\f",
1663             '\b' => "\x08", # \b means backspace in character class
1664             '\a' => "\a",
1665             '\e' => "\e",
1666             '\d' => '[0-9]',
1667              
1668             # Vertical tabs are now whitespace
1669             # \s in a regex now matches a vertical tab in all circumstances.
1670             # http://search.cpan.org/dist/perl-5.18.0/pod/perldelta.pod#Vertical_tabs_are_now_whitespace
1671             # \t \n \v \f \r space
1672             # '\s' => '[\x09\x0A \x0C\x0D\x20]',
1673             # '\s' => '[\x09\x0A\x0B\x0C\x0D\x20]',
1674             '\s' => '\s',
1675              
1676             '\w' => '[0-9A-Z_a-z]',
1677             '\D' => '${Elatin7::eD}',
1678             '\S' => '${Elatin7::eS}',
1679             '\W' => '${Elatin7::eW}',
1680              
1681             '\H' => '${Elatin7::eH}',
1682             '\V' => '${Elatin7::eV}',
1683             '\h' => '[\x09\x20]',
1684             '\v' => '[\x0A\x0B\x0C\x0D]',
1685             '\R' => '${Elatin7::eR}',
1686              
1687 0         0 }->{$1};
1688             }
1689              
1690             # POSIX-style character classes
1691             elsif ($ignorecase and ($char[$i] =~ /\A ( \[\: \^? (?:lower|upper) :\] ) \z/oxms)) {
1692             $char[$i] = {
1693              
1694             '[:lower:]' => '[\x41-\x5A\x61-\x7A]',
1695             '[:upper:]' => '[\x41-\x5A\x61-\x7A]',
1696             '[:^lower:]' => '${Elatin7::not_lower_i}',
1697             '[:^upper:]' => '${Elatin7::not_upper_i}',
1698              
1699 25         414 }->{$1};
1700             }
1701             elsif ($char[$i] =~ /\A ( \[\: \^? (?:alnum|alpha|ascii|blank|cntrl|digit|graph|lower|print|punct|space|upper|word|xdigit) :\] ) \z/oxms) {
1702             $char[$i] = {
1703              
1704             '[:alnum:]' => '[\x30-\x39\x41-\x5A\x61-\x7A]',
1705             '[:alpha:]' => '[\x41-\x5A\x61-\x7A]',
1706             '[:ascii:]' => '[\x00-\x7F]',
1707             '[:blank:]' => '[\x09\x20]',
1708             '[:cntrl:]' => '[\x00-\x1F\x7F]',
1709             '[:digit:]' => '[\x30-\x39]',
1710             '[:graph:]' => '[\x21-\x7F]',
1711             '[:lower:]' => '[\x61-\x7A]',
1712             '[:print:]' => '[\x20-\x7F]',
1713             '[:punct:]' => '[\x21-\x2F\x3A-\x3F\x40\x5B-\x5F\x60\x7B-\x7E]',
1714              
1715             # P.174 POSIX-Style Character Classes
1716             # in Chapter 5: Pattern Matching
1717             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
1718              
1719             # P.311 11.2.4 Character Classes and other Special Escapes
1720             # in Chapter 11: perlre: Perl regular expressions
1721             # of ISBN-13: 978-1-906966-02-7 The Perl Language Reference Manual (for Perl version 5.12.1)
1722              
1723             # P.210 POSIX-Style Character Classes
1724             # in Chapter 5: Pattern Matching
1725             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
1726              
1727             '[:space:]' => '[\s\x0B]', # "\s" plus vertical tab ("\cK")
1728              
1729             '[:upper:]' => '[\x41-\x5A]',
1730             '[:word:]' => '[\x30-\x39\x41-\x5A\x5F\x61-\x7A]',
1731             '[:xdigit:]' => '[\x30-\x39\x41-\x46\x61-\x66]',
1732             '[:^alnum:]' => '${Elatin7::not_alnum}',
1733             '[:^alpha:]' => '${Elatin7::not_alpha}',
1734             '[:^ascii:]' => '${Elatin7::not_ascii}',
1735             '[:^blank:]' => '${Elatin7::not_blank}',
1736             '[:^cntrl:]' => '${Elatin7::not_cntrl}',
1737             '[:^digit:]' => '${Elatin7::not_digit}',
1738             '[:^graph:]' => '${Elatin7::not_graph}',
1739             '[:^lower:]' => '${Elatin7::not_lower}',
1740             '[:^print:]' => '${Elatin7::not_print}',
1741             '[:^punct:]' => '${Elatin7::not_punct}',
1742             '[:^space:]' => '${Elatin7::not_space}',
1743             '[:^upper:]' => '${Elatin7::not_upper}',
1744             '[:^word:]' => '${Elatin7::not_word}',
1745             '[:^xdigit:]' => '${Elatin7::not_xdigit}',
1746              
1747 8         58 }->{$1};
1748             }
1749             elsif ($char[$i] =~ /\A \\ ($q_char) \z/oxms) {
1750 70         1232 $char[$i] = $1;
1751             }
1752             }
1753              
1754             # open character list
1755 7         32 my @singleoctet = ();
1756 358         629 my @multipleoctet = ();
1757 358         554 for (my $i=0; $i <= $#char; ) {
1758              
1759             # escaped -
1760 358 100 100     1204 if (defined($char[$i+1]) and ($char[$i+1] eq '...')) {
    100          
    100          
    50          
    50          
    100          
1761 943         4086 $i += 1;
1762 182         264 next;
1763             }
1764              
1765             # make range regexp
1766             elsif ($char[$i] eq '...') {
1767              
1768             # range error
1769 182 50       332 if (CORE::length($char[$i-1]) > CORE::length($char[$i+1])) {
    50          
1770 182         752 croak 'Invalid [] range in regexp (length(A) > length(B)) ' . '\x' . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]);
1771             }
1772             elsif (CORE::length($char[$i-1]) == CORE::length($char[$i+1])) {
1773 0 50       0 if ($char[$i-1] gt $char[$i+1]) {
1774 182         483 croak 'Invalid [] range in regexp (CORE::ord(A) > CORE::ord(B)) ' . '\x' . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]);
1775             }
1776             }
1777              
1778             # make range regexp per length
1779 0         0 for my $length (CORE::length($char[$i-1]) .. CORE::length($char[$i+1])) {
1780 182         642 my @regexp = ();
1781              
1782             # is first and last
1783 182 50 33     341 if (($length == CORE::length($char[$i-1])) and ($length == CORE::length($char[$i+1]))) {
    0 0        
    0          
    0          
1784 182         671 push @regexp, _range_regexp($length, $char[$i-1], $char[$i+1]);
1785             }
1786              
1787             # is first
1788             elsif ($length == CORE::length($char[$i-1])) {
1789 182         549 push @regexp, _range_regexp($length, $char[$i-1], "\xFF" x $length);
1790             }
1791              
1792             # is inside in first and last
1793             elsif ((CORE::length($char[$i-1]) < $length) and ($length < CORE::length($char[$i+1]))) {
1794 0         0 push @regexp, _range_regexp($length, "\x00" x $length, "\xFF" x $length);
1795             }
1796              
1797             # is last
1798             elsif ($length == CORE::length($char[$i+1])) {
1799 0         0 push @regexp, _range_regexp($length, "\x00" x $length, $char[$i+1]);
1800             }
1801              
1802             else {
1803 0         0 die __FILE__, ": subroutine make_regexp panic.\n";
1804             }
1805              
1806 0 50       0 if ($length == 1) {
1807 182         369 push @singleoctet, @regexp;
1808             }
1809             else {
1810 182         462 push @multipleoctet, @regexp;
1811             }
1812             }
1813              
1814 0         0 $i += 2;
1815             }
1816              
1817             # with /i modifier
1818             elsif ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) {
1819 182 100       438 if ($modifier =~ /i/oxms) {
1820 493         813 my $uc = Elatin7::uc($char[$i]);
1821 24         69 my $fc = Elatin7::fc($char[$i]);
1822 24 100       66 if ($uc ne $fc) {
1823 24 50       56 if (CORE::length($fc) == 1) {
1824 12         39 push @singleoctet, $uc, $fc;
1825             }
1826             else {
1827 12         25 push @singleoctet, $uc;
1828 0         0 push @multipleoctet, $fc;
1829             }
1830             }
1831             else {
1832 0         0 push @singleoctet, $char[$i];
1833             }
1834             }
1835             else {
1836 12         31 push @singleoctet, $char[$i];
1837             }
1838 469         1814 $i += 1;
1839             }
1840              
1841             # single character of single octet code
1842             elsif ($char[$i] =~ /\A (?: \\h ) \z/oxms) {
1843 493         928 push @singleoctet, "\t", "\x20";
1844 0         0 $i += 1;
1845             }
1846             elsif ($char[$i] =~ /\A (?: \\v ) \z/oxms) {
1847 0         0 push @singleoctet, "\x0A", "\x0B", "\x0C", "\x0D";
1848 0         0 $i += 1;
1849             }
1850             elsif ($char[$i] =~ /\A (?: \\d | \\s | \\w ) \z/oxms) {
1851 0         0 push @singleoctet, $char[$i];
1852 2         6 $i += 1;
1853             }
1854              
1855             # single character of multiple-octet code
1856             else {
1857 2         4 push @multipleoctet, $char[$i];
1858 84         156 $i += 1;
1859             }
1860             }
1861              
1862             # quote metachar
1863 84         145 for (@singleoctet) {
1864 358 50       1820 if ($_ eq '...') {
    100          
    100          
    100          
    100          
1865 689         3161 $_ = '-';
1866             }
1867             elsif (/\A \n \z/oxms) {
1868 0         0 $_ = '\n';
1869             }
1870             elsif (/\A \r \z/oxms) {
1871 8         22 $_ = '\r';
1872             }
1873             elsif (/\A ([\x00-\x20\x7F-\xFF]) \z/oxms) {
1874 8         25 $_ = sprintf('\x%02X', CORE::ord $1);
1875             }
1876             elsif (/\A [\x00-\xFF] \z/oxms) {
1877 60         1336 $_ = quotemeta $_;
1878             }
1879             }
1880              
1881             # return character list
1882 429         644 return \@singleoctet, \@multipleoctet;
1883             }
1884              
1885             #
1886             # Latin-7 octal escape sequence
1887             #
1888             sub octchr {
1889 358     5 0 1517 my($octdigit) = @_;
1890              
1891 5         15 my @binary = ();
1892 5         6 for my $octal (split(//,$octdigit)) {
1893             push @binary, {
1894             '0' => '000',
1895             '1' => '001',
1896             '2' => '010',
1897             '3' => '011',
1898             '4' => '100',
1899             '5' => '101',
1900             '6' => '110',
1901             '7' => '111',
1902 5         23 }->{$octal};
1903             }
1904 50         182 my $binary = join '', @binary;
1905              
1906             my $octchr = {
1907             # 1234567
1908             1 => pack('B*', "0000000$binary"),
1909             2 => pack('B*', "000000$binary"),
1910             3 => pack('B*', "00000$binary"),
1911             4 => pack('B*', "0000$binary"),
1912             5 => pack('B*', "000$binary"),
1913             6 => pack('B*', "00$binary"),
1914             7 => pack('B*', "0$binary"),
1915             0 => pack('B*', "$binary"),
1916              
1917 5         14 }->{CORE::length($binary) % 8};
1918              
1919 5         64 return $octchr;
1920             }
1921              
1922             #
1923             # Latin-7 hexadecimal escape sequence
1924             #
1925             sub hexchr {
1926 5     5 0 19 my($hexdigit) = @_;
1927              
1928             my $hexchr = {
1929             1 => pack('H*', "0$hexdigit"),
1930             0 => pack('H*', "$hexdigit"),
1931              
1932 5         158 }->{CORE::length($_[0]) % 2};
1933              
1934 5         51 return $hexchr;
1935             }
1936              
1937             #
1938             # Latin-7 open character list for qr
1939             #
1940             sub charlist_qr {
1941              
1942 5     314 0 18 my $modifier = pop @_;
1943 314         680 my @char = @_;
1944              
1945 314         815 my($singleoctet, $multipleoctet) = _charlist(@char, $modifier);
1946 314         939 my @singleoctet = @$singleoctet;
1947 314         682 my @multipleoctet = @$multipleoctet;
1948              
1949             # return character list
1950 314 100       504 if (scalar(@singleoctet) >= 1) {
1951              
1952             # with /i modifier
1953 314 100       782 if ($modifier =~ m/i/oxms) {
1954 236         604 my %singleoctet_ignorecase = ();
1955 22         39 for (@singleoctet) {
1956 22   100     39 while (s/ \A \\x(..) - \\x(..) //oxms or s/ \A \\x((..)) //oxms) {
1957 46         226 for my $ord (hex($1) .. hex($2)) {
1958 46         156 my $char = CORE::chr($ord);
1959 66         161 my $uc = Elatin7::uc($char);
1960 66         679 my $fc = Elatin7::fc($char);
1961 66 100       118 if ($uc eq $fc) {
1962 66         816 $singleoctet_ignorecase{unpack 'C*', $char} = 1;
1963             }
1964             else {
1965 12 50       107 if (CORE::length($fc) == 1) {
1966 54         102 $singleoctet_ignorecase{unpack 'C*', $uc} = 1;
1967 54         196 $singleoctet_ignorecase{unpack 'C*', $fc} = 1;
1968             }
1969             else {
1970 54         209 $singleoctet_ignorecase{unpack 'C*', $uc} = 1;
1971 0         0 push @multipleoctet, join '', map {sprintf('\x%02X',$_)} unpack 'C*', $fc;
  0         0  
1972             }
1973             }
1974             }
1975             }
1976 0 50       0 if ($_ ne '') {
1977 46         104 $singleoctet_ignorecase{unpack 'C*', $_} = 1;
1978             }
1979             }
1980 0         0 my $i = 0;
1981 22         36 my @singleoctet_ignorecase = ();
1982 22         35 for my $ord (0 .. 255) {
1983 22 100       42 if (exists $singleoctet_ignorecase{$ord}) {
1984 5632         9126 push @{$singleoctet_ignorecase[$i]}, $ord;
  96         93  
1985             }
1986             else {
1987 96         302 $i++;
1988             }
1989             }
1990 5536         7187 @singleoctet = ();
1991 22         114 for my $range (@singleoctet_ignorecase) {
1992 22 100       78 if (ref $range) {
1993 3648 100       9757 if (scalar(@{$range}) == 1) {
  56 50       65  
1994 56         98 push @singleoctet, sprintf('\x%02X', @{$range}[0]);
  36         49  
1995             }
1996 36         282 elsif (scalar(@{$range}) == 2) {
1997 20         27 push @singleoctet, sprintf('\x%02X\x%02X', @{$range}[0], @{$range}[-1]);
  0         0  
  0         0  
1998             }
1999             else {
2000 0         0 push @singleoctet, sprintf('\x%02X-\x%02X', @{$range}[0], @{$range}[-1]);
  20         23  
  20         27  
2001             }
2002             }
2003             }
2004             }
2005              
2006 20         90 my $not_anchor = '';
2007              
2008 236         411 push @multipleoctet, join('', $not_anchor, '[', @singleoctet, ']' );
2009             }
2010 236 100       678 if (scalar(@multipleoctet) >= 2) {
2011 314         662 return '(?:' . join('|', @multipleoctet) . ')';
2012             }
2013             else {
2014 6         31 return $multipleoctet[0];
2015             }
2016             }
2017              
2018             #
2019             # Latin-7 open character list for not qr
2020             #
2021             sub charlist_not_qr {
2022              
2023 308     44 0 1285 my $modifier = pop @_;
2024 44         159 my @char = @_;
2025              
2026 44         120 my($singleoctet, $multipleoctet) = _charlist(@char, $modifier);
2027 44         137 my @singleoctet = @$singleoctet;
2028 44         108 my @multipleoctet = @$multipleoctet;
2029              
2030             # with /i modifier
2031 44 100       153 if ($modifier =~ m/i/oxms) {
2032 44         205 my %singleoctet_ignorecase = ();
2033 10         14 for (@singleoctet) {
2034 10   66     20 while (s/ \A \\x(..) - \\x(..) //oxms or s/ \A \\x((..)) //oxms) {
2035 10         54 for my $ord (hex($1) .. hex($2)) {
2036 10         46 my $char = CORE::chr($ord);
2037 30         48 my $uc = Elatin7::uc($char);
2038 30         56 my $fc = Elatin7::fc($char);
2039 30 50       55 if ($uc eq $fc) {
2040 30         55 $singleoctet_ignorecase{unpack 'C*', $char} = 1;
2041             }
2042             else {
2043 0 50       0 if (CORE::length($fc) == 1) {
2044 30         48 $singleoctet_ignorecase{unpack 'C*', $uc} = 1;
2045 30         76 $singleoctet_ignorecase{unpack 'C*', $fc} = 1;
2046             }
2047             else {
2048 30         1781 $singleoctet_ignorecase{unpack 'C*', $uc} = 1;
2049 0         0 push @multipleoctet, join '', map {sprintf('\x%02X',$_)} unpack 'C*', $fc;
  0         0  
2050             }
2051             }
2052             }
2053             }
2054 0 50       0 if ($_ ne '') {
2055 10         37 $singleoctet_ignorecase{unpack 'C*', $_} = 1;
2056             }
2057             }
2058 0         0 my $i = 0;
2059 10         28 my @singleoctet_ignorecase = ();
2060 10         15 for my $ord (0 .. 255) {
2061 10 100       22 if (exists $singleoctet_ignorecase{$ord}) {
2062 2560         5986 push @{$singleoctet_ignorecase[$i]}, $ord;
  60         59  
2063             }
2064             else {
2065 60         119 $i++;
2066             }
2067             }
2068 2500         4020 @singleoctet = ();
2069 10         20 for my $range (@singleoctet_ignorecase) {
2070 10 100       34 if (ref $range) {
2071 960 50       1963 if (scalar(@{$range}) == 1) {
  20 50       19  
2072 20         44 push @singleoctet, sprintf('\x%02X', @{$range}[0]);
  0         0  
2073             }
2074 0         0 elsif (scalar(@{$range}) == 2) {
2075 20         32 push @singleoctet, sprintf('\x%02X\x%02X', @{$range}[0], @{$range}[-1]);
  0         0  
  0         0  
2076             }
2077             else {
2078 0         0 push @singleoctet, sprintf('\x%02X-\x%02X', @{$range}[0], @{$range}[-1]);
  20         31  
  20         26  
2079             }
2080             }
2081             }
2082             }
2083              
2084             # return character list
2085 20 50       113 if (scalar(@multipleoctet) >= 1) {
2086 44 0       130 if (scalar(@singleoctet) >= 1) {
2087              
2088             # any character other than multiple-octet and single octet character class
2089 0         0 return '(?!' . join('|', @multipleoctet) . ')(?:[^' . join('', @singleoctet) . '])';
2090             }
2091             else {
2092              
2093             # any character other than multiple-octet character class
2094 0         0 return '(?!' . join('|', @multipleoctet) . ")(?:$your_char)";
2095             }
2096             }
2097             else {
2098 0 50       0 if (scalar(@singleoctet) >= 1) {
2099              
2100             # any character other than single octet character class
2101 44         107 return '(?:[^' . join('', @singleoctet) . '])';
2102             }
2103             else {
2104              
2105             # any character
2106 44         456 return "(?:$your_char)";
2107             }
2108             }
2109             }
2110              
2111             #
2112             # open file in read mode
2113             #
2114             sub _open_r {
2115 0     408   0 my(undef,$file) = @_;
2116 204     204   2770 use Fcntl qw(O_RDONLY);
  204         595  
  204         33087  
2117 408         2165 return CORE::sysopen($_[0], $file, &O_RDONLY);
2118             }
2119              
2120             #
2121             # open file in append mode
2122             #
2123             sub _open_a {
2124 408     204   18807 my(undef,$file) = @_;
2125 204     204   1432 use Fcntl qw(O_WRONLY O_APPEND O_CREAT);
  204         460  
  204         752219  
2126 204         668 return CORE::sysopen($_[0], $file, &O_WRONLY|&O_APPEND|&O_CREAT);
2127             }
2128              
2129             #
2130             # safe system
2131             #
2132             sub _systemx {
2133              
2134             # P.707 29.2.33. exec
2135             # in Chapter 29: Functions
2136             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
2137             #
2138             # Be aware that in older releases of Perl, exec (and system) did not flush
2139             # your output buffer, so you needed to enable command buffering by setting $|
2140             # on one or more filehandles to avoid lost output in the case of exec, or
2141             # misordererd output in the case of system. This situation was largely remedied
2142             # in the 5.6 release of Perl. (So, 5.005 release not yet.)
2143              
2144             # P.855 exec
2145             # in Chapter 27: Functions
2146             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
2147             #
2148             # In very old release of Perl (before v5.6), exec (and system) did not flush
2149             # your output buffer, so you needed to enable command buffering by setting $|
2150             # on one or more filehandles to avoid lost output with exec or misordered
2151             # output with system.
2152              
2153 204     204   32670 $| = 1;
2154              
2155             # P.565 23.1.2. Cleaning Up Your Environment
2156             # in Chapter 23: Security
2157             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
2158              
2159             # P.656 Cleaning Up Your Environment
2160             # in Chapter 20: Security
2161             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
2162              
2163             # local $ENV{'PATH'} = '.';
2164 204         681 local @ENV{qw(IFS CDPATH ENV BASH_ENV)}; # Make %ENV safer
2165              
2166             # P.707 29.2.33. exec
2167             # in Chapter 29: Functions
2168             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
2169             #
2170             # As we mentioned earlier, exec treats a discrete list of arguments as an
2171             # indication that it should bypass shell processing. However, there is one
2172             # place where you might still get tripped up. The exec call (and system, too)
2173             # will not distinguish between a single scalar argument and an array containing
2174             # only one element.
2175             #
2176             # @args = ("echo surprise"); # just one element in list
2177             # exec @args # still subject to shell escapes
2178             # or die "exec: $!"; # because @args == 1
2179             #
2180             # To avoid this, you can use the PATHNAME syntax, explicitly duplicating the
2181             # first argument as the pathname, which forces the rest of the arguments to be
2182             # interpreted as a list, even if there is only one of them:
2183             #
2184             # exec { $args[0] } @args # safe even with one-argument list
2185             # or die "can't exec @args: $!";
2186              
2187             # P.855 exec
2188             # in Chapter 27: Functions
2189             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
2190             #
2191             # As we mentioned earlier, exec treats a discrete list of arguments as a
2192             # directive to bypass shell processing. However, there is one place where
2193             # you might still get tripped up. The exec call (and system, too) cannot
2194             # 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             # || die "exec: $!"; # because @args == 1
2200             #
2201             # To avoid this, use the PATHNAME syntax, explicitly duplicating the first
2202             # 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             # || die "can't exec @args: $!";
2207              
2208 204         1840 return CORE::system { $_[0] } @_; # safe even with one-argument list
  204         459  
2209             }
2210              
2211             #
2212             # Latin-7 order to character (with parameter)
2213             #
2214             sub Elatin7::chr(;$) {
2215              
2216 204 0   0 0 20766473 my $c = @_ ? $_[0] : $_;
2217              
2218 0 0       0 if ($c == 0x00) {
2219 0         0 return "\x00";
2220             }
2221             else {
2222 0         0 my @chr = ();
2223 0         0 while ($c > 0) {
2224 0         0 unshift @chr, ($c % 0x100);
2225 0         0 $c = int($c / 0x100);
2226             }
2227 0         0 return pack 'C*', @chr;
2228             }
2229             }
2230              
2231             #
2232             # Latin-7 order to character (without parameter)
2233             #
2234             sub Elatin7::chr_() {
2235              
2236 0     0 0 0 my $c = $_;
2237              
2238 0 0       0 if ($c == 0x00) {
2239 0         0 return "\x00";
2240             }
2241             else {
2242 0         0 my @chr = ();
2243 0         0 while ($c > 0) {
2244 0         0 unshift @chr, ($c % 0x100);
2245 0         0 $c = int($c / 0x100);
2246             }
2247 0         0 return pack 'C*', @chr;
2248             }
2249             }
2250              
2251             #
2252             # Latin-7 path globbing (with parameter)
2253             #
2254             sub Elatin7::glob($) {
2255              
2256 0 0   0 0 0 if (wantarray) {
2257 0         0 my @glob = _DOS_like_glob(@_);
2258 0         0 for my $glob (@glob) {
2259 0         0 $glob =~ s{ \A (?:\./)+ }{}oxms;
2260             }
2261 0         0 return @glob;
2262             }
2263             else {
2264 0         0 my $glob = _DOS_like_glob(@_);
2265 0         0 $glob =~ s{ \A (?:\./)+ }{}oxms;
2266 0         0 return $glob;
2267             }
2268             }
2269              
2270             #
2271             # Latin-7 path globbing (without parameter)
2272             #
2273             sub Elatin7::glob_() {
2274              
2275 0 0   0 0 0 if (wantarray) {
2276 0         0 my @glob = _DOS_like_glob();
2277 0         0 for my $glob (@glob) {
2278 0         0 $glob =~ s{ \A (?:\./)+ }{}oxms;
2279             }
2280 0         0 return @glob;
2281             }
2282             else {
2283 0         0 my $glob = _DOS_like_glob();
2284 0         0 $glob =~ s{ \A (?:\./)+ }{}oxms;
2285 0         0 return $glob;
2286             }
2287             }
2288              
2289             #
2290             # Latin-7 path globbing via File::DosGlob 1.10
2291             #
2292             # Often I confuse "_dosglob" and "_doglob".
2293             # So, I renamed "_dosglob" to "_DOS_like_glob".
2294             #
2295             my %iter;
2296             my %entries;
2297             sub _DOS_like_glob {
2298              
2299             # context (keyed by second cxix argument provided by core)
2300 0     0   0 my($expr,$cxix) = @_;
2301              
2302             # glob without args defaults to $_
2303 0 0       0 $expr = $_ if not defined $expr;
2304              
2305             # represents the current user's home directory
2306             #
2307             # 7.3. Expanding Tildes in Filenames
2308             # in Chapter 7. File Access
2309             # of ISBN 0-596-00313-7 Perl Cookbook, 2nd Edition.
2310             #
2311             # and File::HomeDir, File::HomeDir::Windows module
2312              
2313             # DOS-like system
2314 0 0       0 if ($^O =~ /\A (?: MSWin32 | NetWare | symbian | dos ) \z/oxms) {
2315 0         0 $expr =~ s{ \A ~ (?= [^/\\] ) }
  0         0  
2316             { my_home_MSWin32() }oxmse;
2317             }
2318              
2319             # UNIX-like system
2320 0 0 0     0 else {
  0         0  
2321             $expr =~ s{ \A ~ ( (?:[^/])* ) }
2322             { $1 ? (CORE::eval(q{(getpwnam($1))[7]})||my_home()) : my_home() }oxmse;
2323             }
2324 0 0       0  
2325 0 0       0 # assume global context if not provided one
2326             $cxix = '_G_' if not defined $cxix;
2327             $iter{$cxix} = 0 if not exists $iter{$cxix};
2328 0 0       0  
2329 0         0 # if we're just beginning, do it all first
2330             if ($iter{$cxix} == 0) {
2331             $entries{$cxix} = [ _do_glob(1, _parse_line($expr)) ];
2332             }
2333 0 0       0  
2334 0         0 # chuck it all out, quick or slow
2335 0         0 if (wantarray) {
  0         0  
2336             delete $iter{$cxix};
2337             return @{delete $entries{$cxix}};
2338 0 0       0 }
  0         0  
2339 0         0 else {
  0         0  
2340             if ($iter{$cxix} = scalar @{$entries{$cxix}}) {
2341             return shift @{$entries{$cxix}};
2342             }
2343 0         0 else {
2344 0         0 # return undef for EOL
2345 0         0 delete $iter{$cxix};
2346             delete $entries{$cxix};
2347             return undef;
2348             }
2349             }
2350             }
2351              
2352             #
2353             # Latin-7 path globbing subroutine
2354             #
2355 0     0   0 sub _do_glob {
2356 0         0  
2357 0         0 my($cond,@expr) = @_;
2358             my @glob = ();
2359             my $fix_drive_relative_paths = 0;
2360 0         0  
2361 0 0       0 OUTER:
2362 0 0       0 for my $expr (@expr) {
2363             next OUTER if not defined $expr;
2364 0         0 next OUTER if $expr eq '';
2365 0         0  
2366 0         0 my @matched = ();
2367 0         0 my @globdir = ();
2368 0         0 my $head = '.';
2369             my $pathsep = '/';
2370             my $tail;
2371 0 0       0  
2372 0         0 # if argument is within quotes strip em and do no globbing
2373 0 0       0 if ($expr =~ /\A " ((?:$q_char)*?) " \z/oxms) {
2374 0 0       0 $expr = $1;
2375 0         0 if ($cond eq 'd') {
2376             if (-d $expr) {
2377             push @glob, $expr;
2378             }
2379 0 0       0 }
2380 0         0 else {
2381             if (-e $expr) {
2382             push @glob, $expr;
2383 0         0 }
2384             }
2385             next OUTER;
2386             }
2387              
2388 0 0       0 # wildcards with a drive prefix such as h:*.pm must be changed
2389 0 0       0 # to h:./*.pm to expand correctly
2390 0         0 if ($^O =~ /\A (?: MSWin32 | NetWare | symbian | dos ) \z/oxms) {
2391             if ($expr =~ s# \A ((?:[A-Za-z]:)?) ([^/\\]) #$1./$2#oxms) {
2392             $fix_drive_relative_paths = 1;
2393             }
2394 0 0       0 }
2395 0 0       0  
2396 0         0 if (($head, $tail) = _parse_path($expr,$pathsep)) {
2397 0         0 if ($tail eq '') {
2398             push @glob, $expr;
2399 0 0       0 next OUTER;
2400 0 0       0 }
2401 0         0 if ($head =~ / \A (?:$q_char)*? [*?] /oxms) {
  0         0  
2402 0         0 if (@globdir = _do_glob('d', $head)) {
2403             push @glob, _do_glob($cond, map {"$_$pathsep$tail"} @globdir);
2404             next OUTER;
2405 0 0 0     0 }
2406 0         0 }
2407             if ($head eq '' or $head =~ /\A [A-Za-z]: \z/oxms) {
2408 0         0 $head .= $pathsep;
2409             }
2410             $expr = $tail;
2411             }
2412 0 0       0  
2413 0 0       0 # If file component has no wildcards, we can avoid opendir
2414 0         0 if ($expr !~ / \A (?:$q_char)*? [*?] /oxms) {
2415             if ($head eq '.') {
2416 0 0 0     0 $head = '';
2417 0         0 }
2418             if ($head ne '' and ($head =~ / \G ($q_char) /oxmsg)[-1] ne $pathsep) {
2419 0         0 $head .= $pathsep;
2420 0 0       0 }
2421 0 0       0 $head .= $expr;
2422 0         0 if ($cond eq 'd') {
2423             if (-d $head) {
2424             push @glob, $head;
2425             }
2426 0 0       0 }
2427 0         0 else {
2428             if (-e $head) {
2429             push @glob, $head;
2430 0         0 }
2431             }
2432 0 0       0 next OUTER;
2433 0         0 }
2434 0         0 opendir(*DIR, $head) or next OUTER;
2435             my @leaf = readdir DIR;
2436 0 0       0 closedir DIR;
2437 0         0  
2438             if ($head eq '.') {
2439 0 0 0     0 $head = '';
2440 0         0 }
2441             if ($head ne '' and ($head =~ / \G ($q_char) /oxmsg)[-1] ne $pathsep) {
2442             $head .= $pathsep;
2443 0         0 }
2444 0         0  
2445 0         0 my $pattern = '';
2446             while ($expr =~ / \G ($q_char) /oxgc) {
2447             my $char = $1;
2448              
2449             # 6.9. Matching Shell Globs as Regular Expressions
2450             # in Chapter 6. Pattern Matching
2451             # of ISBN 0-596-00313-7 Perl Cookbook, 2nd Edition.
2452 0 0       0 # (and so on)
    0          
    0          
2453 0         0  
2454             if ($char eq '*') {
2455             $pattern .= "(?:$your_char)*",
2456 0         0 }
2457             elsif ($char eq '?') {
2458             $pattern .= "(?:$your_char)?", # DOS style
2459             # $pattern .= "(?:$your_char)", # UNIX style
2460 0         0 }
2461             elsif ((my $fc = Elatin7::fc($char)) ne $char) {
2462             $pattern .= $fc;
2463 0         0 }
2464             else {
2465             $pattern .= quotemeta $char;
2466 0     0   0 }
  0         0  
2467             }
2468             my $matchsub = sub { Elatin7::fc($_[0]) =~ /\A $pattern \z/xms };
2469              
2470             # if ($@) {
2471             # print STDERR "$0: $@\n";
2472             # next OUTER;
2473             # }
2474 0         0  
2475 0 0 0     0 INNER:
2476 0         0 for my $leaf (@leaf) {
2477             if ($leaf eq '.' or $leaf eq '..') {
2478 0 0 0     0 next INNER;
2479 0         0 }
2480             if ($cond eq 'd' and not -d "$head$leaf") {
2481             next INNER;
2482 0 0       0 }
2483 0         0  
2484 0         0 if (&$matchsub($leaf)) {
2485             push @matched, "$head$leaf";
2486             next INNER;
2487             }
2488              
2489             # [DOS compatibility special case]
2490 0 0 0     0 # Failed, add a trailing dot and try again, but only...
      0        
2491              
2492             if (Elatin7::index($leaf,'.') == -1 and # if name does not have a dot in it *and*
2493             CORE::length($leaf) <= 8 and # name is shorter than or equal to 8 chars *and*
2494 0 0       0 Elatin7::index($pattern,'\\.') != -1 # pattern has a dot.
2495 0         0 ) {
2496 0         0 if (&$matchsub("$leaf.")) {
2497             push @matched, "$head$leaf";
2498             next INNER;
2499             }
2500 0 0       0 }
2501 0         0 }
2502             if (@matched) {
2503             push @glob, @matched;
2504 0 0       0 }
2505 0         0 }
2506 0         0 if ($fix_drive_relative_paths) {
2507             for my $glob (@glob) {
2508             $glob =~ s# \A ([A-Za-z]:) \./ #$1#oxms;
2509 0         0 }
2510             }
2511             return @glob;
2512             }
2513              
2514             #
2515             # Latin-7 parse line
2516             #
2517 0     0   0 sub _parse_line {
2518              
2519 0         0 my($line) = @_;
2520 0         0  
2521 0         0 $line .= ' ';
2522             my @piece = ();
2523             while ($line =~ /
2524             " ( (?>(?: [^"] )* ) ) " (?>\s+) |
2525             ( (?>(?: [^"\s] )* ) ) (?>\s+)
2526 0 0       0 /oxmsg
2527             ) {
2528 0         0 push @piece, defined($1) ? $1 : $2;
2529             }
2530             return @piece;
2531             }
2532              
2533             #
2534             # Latin-7 parse path
2535             #
2536 0     0   0 sub _parse_path {
2537              
2538 0         0 my($path,$pathsep) = @_;
2539 0         0  
2540 0         0 $path .= '/';
2541             my @subpath = ();
2542             while ($path =~ /
2543             ((?: [^\/\\] )+?) [\/\\]
2544 0         0 /oxmsg
2545             ) {
2546             push @subpath, $1;
2547 0         0 }
2548 0         0  
2549 0         0 my $tail = pop @subpath;
2550             my $head = join $pathsep, @subpath;
2551             return $head, $tail;
2552             }
2553              
2554             #
2555             # via File::HomeDir::Windows 1.00
2556             #
2557             sub my_home_MSWin32 {
2558              
2559             # A lot of unix people and unix-derived tools rely on
2560 0 0 0 0 0 0 # the ability to overload HOME. We will support it too
    0 0        
    0 0        
      0        
      0        
2561 0         0 # so that they can replace raw HOME calls with File::HomeDir.
2562             if (exists $ENV{'HOME'} and $ENV{'HOME'}) {
2563             return $ENV{'HOME'};
2564             }
2565              
2566 0         0 # Do we have a user profile?
2567             elsif (exists $ENV{'USERPROFILE'} and $ENV{'USERPROFILE'}) {
2568             return $ENV{'USERPROFILE'};
2569             }
2570              
2571 0         0 # Some Windows use something like $ENV{'HOME'}
2572             elsif (exists $ENV{'HOMEDRIVE'} and exists $ENV{'HOMEPATH'} and $ENV{'HOMEDRIVE'} and $ENV{'HOMEPATH'}) {
2573             return join '', $ENV{'HOMEDRIVE'}, $ENV{'HOMEPATH'};
2574 0         0 }
2575              
2576             return undef;
2577             }
2578              
2579             #
2580             # via File::HomeDir::Unix 1.00
2581 0     0 0 0 #
2582             sub my_home {
2583 0 0 0     0 my $home;
    0 0        
2584 0         0  
2585             if (exists $ENV{'HOME'} and defined $ENV{'HOME'}) {
2586             $home = $ENV{'HOME'};
2587             }
2588              
2589             # This is from the original code, but I'm guessing
2590 0         0 # it means "login directory" and exists on some Unixes.
2591             elsif (exists $ENV{'LOGDIR'} and $ENV{'LOGDIR'}) {
2592             $home = $ENV{'LOGDIR'};
2593             }
2594              
2595             ### More-desperate methods
2596              
2597 0         0 # Light desperation on any (Unixish) platform
2598             else {
2599             $home = CORE::eval q{ (getpwuid($<))[7] };
2600             }
2601              
2602 0 0 0     0 # On Unix in general, a non-existant home means "no home"
2603 0         0 # For example, "nobody"-like users might use /nonexistant
2604             if (defined $home and ! -d($home)) {
2605 0         0 $home = undef;
2606             }
2607             return $home;
2608             }
2609              
2610             #
2611             # ${^PREMATCH}, $PREMATCH, $` the string preceding what was matched
2612 0     0 0 0 #
2613             sub Elatin7::PREMATCH {
2614             return $`;
2615             }
2616              
2617             #
2618             # ${^MATCH}, $MATCH, $& the string that matched
2619 0     0 0 0 #
2620             sub Elatin7::MATCH {
2621             return $&;
2622             }
2623              
2624             #
2625             # ${^POSTMATCH}, $POSTMATCH, $' the string following what was matched
2626 0     0 0 0 #
2627             sub Elatin7::POSTMATCH {
2628             return $';
2629             }
2630              
2631             #
2632             # Latin-7 character to order (with parameter)
2633             #
2634 0 0   0 1 0 sub Latin7::ord(;$) {
2635              
2636 0 0       0 local $_ = shift if @_;
2637 0         0  
2638 0         0 if (/\A ($q_char) /oxms) {
2639 0         0 my @ord = unpack 'C*', $1;
2640 0         0 my $ord = 0;
2641             while (my $o = shift @ord) {
2642 0         0 $ord = $ord * 0x100 + $o;
2643             }
2644             return $ord;
2645 0         0 }
2646             else {
2647             return CORE::ord $_;
2648             }
2649             }
2650              
2651             #
2652             # Latin-7 character to order (without parameter)
2653             #
2654 0 0   0 0 0 sub Latin7::ord_() {
2655 0         0  
2656 0         0 if (/\A ($q_char) /oxms) {
2657 0         0 my @ord = unpack 'C*', $1;
2658 0         0 my $ord = 0;
2659             while (my $o = shift @ord) {
2660 0         0 $ord = $ord * 0x100 + $o;
2661             }
2662             return $ord;
2663 0         0 }
2664             else {
2665             return CORE::ord $_;
2666             }
2667             }
2668              
2669             #
2670             # Latin-7 reverse
2671             #
2672 0 0   0 0 0 sub Latin7::reverse(@) {
2673 0         0  
2674             if (wantarray) {
2675             return CORE::reverse @_;
2676             }
2677             else {
2678              
2679             # One of us once cornered Larry in an elevator and asked him what
2680             # problem he was solving with this, but he looked as far off into
2681             # the distance as he could in an elevator and said, "It seemed like
2682 0         0 # a good idea at the time."
2683              
2684             return join '', CORE::reverse(join('',@_) =~ /\G ($q_char) /oxmsg);
2685             }
2686             }
2687              
2688             #
2689             # Latin-7 getc (with parameter, without parameter)
2690             #
2691 0     0 0 0 sub Latin7::getc(;*@) {
2692 0 0       0  
2693 0 0 0     0 my($package) = caller;
2694             my $fh = @_ ? qualify_to_ref(shift,$package) : \*STDIN;
2695 0         0 croak 'Too many arguments for Latin7::getc' if @_ and not wantarray;
  0         0  
2696 0         0  
2697 0         0 my @length = sort { $a <=> $b } keys %range_tr;
2698 0         0 my $getc = '';
2699 0 0       0 for my $length ($length[0] .. $length[-1]) {
2700 0 0       0 $getc .= CORE::getc($fh);
2701 0 0       0 if (exists $range_tr{CORE::length($getc)}) {
2702             if ($getc =~ /\A ${Elatin7::dot_s} \z/oxms) {
2703             return wantarray ? ($getc,@_) : $getc;
2704             }
2705 0 0       0 }
2706             }
2707             return wantarray ? ($getc,@_) : $getc;
2708             }
2709              
2710             #
2711             # Latin-7 length by character
2712             #
2713 0 0   0 1 0 sub Latin7::length(;$) {
2714              
2715 0         0 local $_ = shift if @_;
2716 0         0  
2717             local @_ = /\G ($q_char) /oxmsg;
2718             return scalar @_;
2719             }
2720              
2721             #
2722             # Latin-7 substr by character
2723             #
2724             BEGIN {
2725              
2726             # P.232 The lvalue Attribute
2727             # in Chapter 6: Subroutines
2728             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
2729              
2730             # P.336 The lvalue Attribute
2731             # in Chapter 7: Subroutines
2732             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
2733              
2734             # P.144 8.4 Lvalue subroutines
2735             # in Chapter 8: perlsub: Perl subroutines
2736 204 50 0 204 1 151670 # of ISBN-13: 978-1-906966-02-7 The Perl Language Reference Manual (for Perl version 5.12.1)
  0 0   0   0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
2737              
2738             CORE::eval sprintf(<<'END', ($] >= 5.014000) ? ':lvalue' : '');
2739             # vv----------------------*******
2740             sub Latin7::substr($$;$$) %s {
2741              
2742             my @char = $_[0] =~ /\G (?>$q_char) /oxmsg;
2743              
2744             # If the substring is beyond either end of the string, substr() returns the undefined
2745             # value and produces a warning. When used as an lvalue, specifying a substring that
2746             # is entirely outside the string raises an exception.
2747             # http://perldoc.perl.org/functions/substr.html
2748              
2749             # A return with no argument returns the scalar value undef in scalar context,
2750             # an empty list () in list context, and (naturally) nothing at all in void
2751             # context.
2752              
2753             my $offset = $_[1];
2754             if (($offset > scalar(@char)) or ($offset < (-1 * scalar(@char)))) {
2755             return;
2756             }
2757              
2758             # substr($string,$offset,$length,$replacement)
2759             if (@_ == 4) {
2760             my(undef,undef,$length,$replacement) = @_;
2761             my $substr = join '', splice(@char, $offset, $length, $replacement);
2762             $_[0] = join '', @char;
2763              
2764             # return $substr; this doesn't work, don't say "return"
2765             $substr;
2766             }
2767              
2768             # substr($string,$offset,$length)
2769             elsif (@_ == 3) {
2770             my(undef,undef,$length) = @_;
2771             my $octet_offset = 0;
2772             my $octet_length = 0;
2773             if ($offset == 0) {
2774             $octet_offset = 0;
2775             }
2776             elsif ($offset > 0) {
2777             $octet_offset = CORE::length(join '', @char[0..$offset-1]);
2778             }
2779             else {
2780             $octet_offset = -1 * CORE::length(join '', @char[$#char+$offset+1..$#char]);
2781             }
2782             if ($length == 0) {
2783             $octet_length = 0;
2784             }
2785             elsif ($length > 0) {
2786             $octet_length = CORE::length(join '', @char[$offset..$offset+$length-1]);
2787             }
2788             else {
2789             $octet_length = -1 * CORE::length(join '', @char[$#char+$length+1..$#char]);
2790             }
2791             CORE::substr($_[0], $octet_offset, $octet_length);
2792             }
2793              
2794             # substr($string,$offset)
2795             else {
2796             my $octet_offset = 0;
2797             if ($offset == 0) {
2798             $octet_offset = 0;
2799             }
2800             elsif ($offset > 0) {
2801             $octet_offset = CORE::length(join '', @char[0..$offset-1]);
2802             }
2803             else {
2804             $octet_offset = -1 * CORE::length(join '', @char[$#char+$offset+1..$#char]);
2805             }
2806             CORE::substr($_[0], $octet_offset);
2807             }
2808             }
2809             END
2810             }
2811              
2812             #
2813             # Latin-7 index by character
2814             #
2815 0     0 1 0 sub Latin7::index($$;$) {
2816 0 0       0  
2817 0         0 my $index;
2818             if (@_ == 3) {
2819             $index = Elatin7::index($_[0], $_[1], CORE::length(Latin7::substr($_[0], 0, $_[2])));
2820 0         0 }
2821             else {
2822             $index = Elatin7::index($_[0], $_[1]);
2823 0 0       0 }
2824 0         0  
2825             if ($index == -1) {
2826             return -1;
2827 0         0 }
2828             else {
2829             return Latin7::length(CORE::substr $_[0], 0, $index);
2830             }
2831             }
2832              
2833             #
2834             # Latin-7 rindex by character
2835             #
2836 0     0 1 0 sub Latin7::rindex($$;$) {
2837 0 0       0  
2838 0         0 my $rindex;
2839             if (@_ == 3) {
2840             $rindex = Elatin7::rindex($_[0], $_[1], CORE::length(Latin7::substr($_[0], 0, $_[2])));
2841 0         0 }
2842             else {
2843             $rindex = Elatin7::rindex($_[0], $_[1]);
2844 0 0       0 }
2845 0         0  
2846             if ($rindex == -1) {
2847             return -1;
2848 0         0 }
2849             else {
2850             return Latin7::length(CORE::substr $_[0], 0, $rindex);
2851             }
2852             }
2853              
2854 204     204   1913 # when 'm//', '/' means regexp match 'm//' and '?' means regexp match '??'
  204         518  
  204         33933  
2855             # when 'div', '/' means division operator and '?' means conditional operator (condition ? then : else)
2856             use vars qw($slash); $slash = 'm//';
2857              
2858             # ord() to ord() or Latin7::ord()
2859             my $function_ord = 'ord';
2860              
2861             # ord to ord or Latin7::ord_
2862             my $function_ord_ = 'ord';
2863              
2864             # reverse to reverse or Latin7::reverse
2865             my $function_reverse = 'reverse';
2866              
2867             # getc to getc or Latin7::getc
2868             my $function_getc = 'getc';
2869              
2870             # P.1023 Appendix W.9 Multibyte Anchoring
2871             # of ISBN 1-56592-224-7 CJKV Information Processing
2872              
2873 204     204   1855 my $anchor = '';
  204     0   398  
  204         10300594  
2874              
2875             use vars qw($nest);
2876              
2877             # regexp of nested parens in qqXX
2878              
2879             # P.340 Matching Nested Constructs with Embedded Code
2880             # in Chapter 7: Perl
2881             # of ISBN 0-596-00289-0 Mastering Regular Expressions, Second edition
2882              
2883             my $qq_paren = qr{(?{local $nest=0}) (?>(?:
2884             [^\\()] |
2885             \( (?{$nest++}) |
2886             \) (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!)) |
2887             \\ [^c] |
2888             \\c[\x40-\x5F] |
2889             [\x00-\xFF]
2890             }xms;
2891              
2892             my $qq_brace = qr{(?{local $nest=0}) (?>(?:
2893             [^\\{}] |
2894             \{ (?{$nest++}) |
2895             \} (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!)) |
2896             \\ [^c] |
2897             \\c[\x40-\x5F] |
2898             [\x00-\xFF]
2899             }xms;
2900              
2901             my $qq_bracket = qr{(?{local $nest=0}) (?>(?:
2902             [^\\\[\]] |
2903             \[ (?{$nest++}) |
2904             \] (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!)) |
2905             \\ [^c] |
2906             \\c[\x40-\x5F] |
2907             [\x00-\xFF]
2908             }xms;
2909              
2910             my $qq_angle = qr{(?{local $nest=0}) (?>(?:
2911             [^\\<>] |
2912             \< (?{$nest++}) |
2913             \> (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!)) |
2914             \\ [^c] |
2915             \\c[\x40-\x5F] |
2916             [\x00-\xFF]
2917             }xms;
2918              
2919             my $qq_scalar = qr{(?: \{ (?:$qq_brace)*? \} |
2920             (?: ::)? (?:
2921             (?> [a-zA-Z_][a-zA-Z_0-9]* (?: ::[a-zA-Z_][a-zA-Z_0-9]*)* )
2922             (?>(?: \[ (?: \$\[ | \$\] | $qq_char )*? \] | \{ (?:$qq_brace)*? \} )*)
2923             (?>(?: (?: -> )? (?: [\$\@\%\&\*]\* | \$\#\* | [\@\%]? \[ (?: \$\[ | \$\] | $qq_char )*? \] | [\@\%\*]? \{ (?:$qq_brace)*? \} ) )*)
2924             ))
2925             }xms;
2926              
2927             my $qq_variable = qr{(?: \{ (?:$qq_brace)*? \} |
2928             (?: ::)? (?:
2929             (?>[0-9]+) |
2930             [^a-zA-Z_0-9\[\]] |
2931             ^[A-Z] |
2932             (?> [a-zA-Z_][a-zA-Z_0-9]* (?: ::[a-zA-Z_][a-zA-Z_0-9]*)* )
2933             (?>(?: \[ (?: \$\[ | \$\] | $qq_char )*? \] | \{ (?:$qq_brace)*? \} )*)
2934             (?>(?: (?: -> )? (?: [\$\@\%\&\*]\* | \$\#\* | [\@\%]? \[ (?: \$\[ | \$\] | $qq_char )*? \] | [\@\%\*]? \{ (?:$qq_brace)*? \} ) )*)
2935             ))
2936             }xms;
2937              
2938             my $qq_substr = qr{(?> Char::substr | Latin7::substr | CORE::substr | substr ) (?>\s*) \( $qq_paren \)
2939             }xms;
2940              
2941             # regexp of nested parens in qXX
2942             my $q_paren = qr{(?{local $nest=0}) (?>(?:
2943             [^()] |
2944             \( (?{$nest++}) |
2945             \) (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!)) |
2946             [\x00-\xFF]
2947             }xms;
2948              
2949             my $q_brace = qr{(?{local $nest=0}) (?>(?:
2950             [^\{\}] |
2951             \{ (?{$nest++}) |
2952             \} (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!)) |
2953             [\x00-\xFF]
2954             }xms;
2955              
2956             my $q_bracket = qr{(?{local $nest=0}) (?>(?:
2957             [^\[\]] |
2958             \[ (?{$nest++}) |
2959             \] (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!)) |
2960             [\x00-\xFF]
2961             }xms;
2962              
2963             my $q_angle = qr{(?{local $nest=0}) (?>(?:
2964             [^<>] |
2965             \< (?{$nest++}) |
2966             \> (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!)) |
2967             [\x00-\xFF]
2968             }xms;
2969              
2970             my $matched = '';
2971             my $s_matched = '';
2972              
2973             my $tr_variable = ''; # variable of tr///
2974             my $sub_variable = ''; # variable of s///
2975             my $bind_operator = ''; # =~ or !~
2976              
2977             my @heredoc = (); # here document
2978             my @heredoc_delimiter = ();
2979             my $here_script = ''; # here script
2980              
2981             #
2982             # escape Latin-7 script
2983 0 50   204 0 0 #
2984             sub Latin7::escape(;$) {
2985             local($_) = $_[0] if @_;
2986              
2987             # P.359 The Study Function
2988             # in Chapter 7: Perl
2989 204         639 # of ISBN 0-596-00289-0 Mastering Regular Expressions, Second edition
2990              
2991             study $_; # Yes, I studied study yesterday.
2992              
2993             # while all script
2994              
2995             # 6.14. Matching from Where the Last Pattern Left Off
2996             # in Chapter 6. Pattern Matching
2997             # of ISBN 0-596-00313-7 Perl Cookbook, 2nd Edition.
2998             # (and so on)
2999              
3000             # one member of Tag-team
3001             #
3002             # P.128 Start of match (or end of previous match): \G
3003             # P.130 Advanced Use of \G with Perl
3004             # in Chapter 3: Overview of Regular Expression Features and Flavors
3005             # P.255 Use leading anchors
3006             # P.256 Expose ^ and \G at the front expressions
3007             # in Chapter 6: Crafting an Efficient Expression
3008             # P.315 "Tag-team" matching with /gc
3009             # in Chapter 7: Perl
3010 204         432 # of ISBN 0-596-00289-0 Mastering Regular Expressions, Second edition
3011 204         365  
3012 204         793 my $e_script = '';
3013             while (not /\G \z/oxgc) { # member
3014             $e_script .= Latin7::escape_token();
3015 74767         134761 }
3016              
3017             return $e_script;
3018             }
3019              
3020             #
3021             # escape Latin-7 token of script
3022             #
3023             sub Latin7::escape_token {
3024              
3025 204     74767 0 2860 # \n output here document
3026              
3027             my $ignore_modules = join('|', qw(
3028             utf8
3029             bytes
3030             charnames
3031             I18N::Japanese
3032             I18N::Collate
3033             I18N::JExt
3034             File::DosGlob
3035             Wild
3036             Wildcard
3037             Japanese
3038             ));
3039              
3040             # another member of Tag-team
3041             #
3042             # P.315 "Tag-team" matching with /gc
3043             # in Chapter 7: Perl
3044 74767 100 100     98457 # of ISBN 0-596-00289-0 Mastering Regular Expressions, Second edition
    100 66        
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    50          
    100          
    50          
    100          
    100          
    50          
    50          
    50          
    50          
    50          
    50          
    100          
    100          
    50          
    50          
    50          
    50          
    100          
    100          
    50          
    100          
    50          
    100          
    100          
    50          
    100          
    50          
    50          
    50          
    100          
    50          
    50          
    50          
    100          
    50          
    100          
    50          
    100          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    100          
    100          
    100          
    100          
    100          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    100          
    100          
    100          
    100          
    50          
    100          
    50          
    100          
    100          
    100          
    50          
    50          
    50          
    100          
    50          
    50          
    100          
    50          
    100          
    50          
    50          
    50          
    50          
    50          
    50          
    100          
    100          
    100          
    100          
    100          
    50          
    50          
    50          
    100          
    100          
    100          
    100          
    100          
    100          
    50          
    100          
    100          
    50          
    100          
    50          
    50          
    50          
    100          
    50          
    50          
    100          
    100          
    100          
    50          
3045 74767         3306154  
3046 12511 100       21421 if (/\G ( \n ) /oxgc) { # another member (and so on)
3047 12511         22225 my $heredoc = '';
3048             if (scalar(@heredoc_delimiter) >= 1) {
3049 174         218 $slash = 'm//';
3050 174         15475  
3051             $heredoc = join '', @heredoc;
3052             @heredoc = ();
3053 174         759  
3054 174         328 # skip here document
3055             for my $heredoc_delimiter (@heredoc_delimiter) {
3056 174         1128 /\G .*? \n $heredoc_delimiter \n/xmsgc;
3057             }
3058 174         324 @heredoc_delimiter = ();
3059              
3060 174         261 $here_script = '';
3061             }
3062             return "\n" . $heredoc;
3063             }
3064 12511         39962  
3065             # ignore space, comment
3066             elsif (/\G ((?>\s+)|\#.*) /oxgc) { return $1; }
3067              
3068             # if (, elsif (, unless (, while (, until (, given (, and when (
3069              
3070             # given, when
3071              
3072             # P.225 The given Statement
3073             # in Chapter 15: Smart Matching and given-when
3074             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
3075              
3076             # P.133 The given Statement
3077             # in Chapter 4: Statements and Declarations
3078             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
3079 17919         73312  
3080 1401         2306 elsif (/\G ( (?: if | elsif | unless | while | until | given | when ) (?>\s*) \( ) /oxgc) {
3081             $slash = 'm//';
3082             return $1;
3083             }
3084              
3085             # scalar variable ($scalar = ...) =~ tr///;
3086             # scalar variable ($scalar = ...) =~ s///;
3087              
3088             # state
3089              
3090             # P.68 Persistent, Private Variables
3091             # in Chapter 4: Subroutines
3092             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
3093              
3094             # P.160 Persistent Lexically Scoped Variables: state
3095             # in Chapter 4: Statements and Declarations
3096             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
3097              
3098             # (and so on)
3099 1401         4457  
3100             elsif (/\G ( \( (?>\s*) (?: local \b | my \b | our \b | state \b )? (?>\s*) \$ $qq_scalar ) /oxgc) {
3101 86 50       185 my $e_string = e_string($1);
    50          
3102 86         2027  
3103 0         0 if (/\G ( (?>\s*) = $qq_paren \) ) ( (?>\s*) (?: =~ | !~ ) (?>\s*) ) (?= (?: tr | y ) \b ) /oxgc) {
3104 0         0 $tr_variable = $e_string . e_string($1);
3105 0         0 $bind_operator = $2;
3106             $slash = 'm//';
3107             return '';
3108 0         0 }
3109 0         0 elsif (/\G ( (?>\s*) = $qq_paren \) ) ( (?>\s*) (?: =~ | !~ ) (?>\s*) ) (?= s \b ) /oxgc) {
3110 0         0 $sub_variable = $e_string . e_string($1);
3111 0         0 $bind_operator = $2;
3112             $slash = 'm//';
3113             return '';
3114 0         0 }
3115 86         149 else {
3116             $slash = 'div';
3117             return $e_string;
3118             }
3119             }
3120              
3121 86         281 # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Elatin7::PREMATCH()
3122 4         9 elsif (/\G ( \$` | \$\{`\} | \$ (?>\s*) PREMATCH \b | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} ) /oxmsgc) {
3123             $slash = 'div';
3124             return q{Elatin7::PREMATCH()};
3125             }
3126              
3127 4         15 # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Elatin7::MATCH()
3128 28         211 elsif (/\G ( \$& | \$\{&\} | \$ (?>\s*) MATCH \b | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} ) /oxmsgc) {
3129             $slash = 'div';
3130             return q{Elatin7::MATCH()};
3131             }
3132              
3133 28         96 # $', ${'} --> $', ${'}
3134 1         2 elsif (/\G ( \$' | \$\{'\} ) /oxmsgc) {
3135             $slash = 'div';
3136             return $1;
3137             }
3138              
3139 1         4 # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Elatin7::POSTMATCH()
3140 3         6 elsif (/\G ( \$ (?>\s*) POSTMATCH \b | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} ) /oxmsgc) {
3141             $slash = 'div';
3142             return q{Elatin7::POSTMATCH()};
3143             }
3144              
3145             # scalar variable $scalar =~ tr///;
3146             # scalar variable $scalar =~ s///;
3147             # substr() =~ tr///;
3148 3         10 # substr() =~ s///;
3149             elsif (/\G ( \$ $qq_scalar | $qq_substr ) /oxgc) {
3150 1671 100       4056 my $scalar = e_string($1);
    100          
3151 1671         8218  
3152 1         3 if (/\G ( (?>\s*) (?: =~ | !~ ) (?>\s*) ) (?= (?: tr | y ) \b ) /oxgc) {
3153 1         2 $tr_variable = $scalar;
3154 1         2 $bind_operator = $1;
3155             $slash = 'm//';
3156             return '';
3157 1         3 }
3158 61         131 elsif (/\G ( (?>\s*) (?: =~ | !~ ) (?>\s*) ) (?= s \b ) /oxgc) {
3159 61         125 $sub_variable = $scalar;
3160 61         106 $bind_operator = $1;
3161             $slash = 'm//';
3162             return '';
3163 61         371 }
3164 1609         2383 else {
3165             $slash = 'div';
3166             return $scalar;
3167             }
3168             }
3169              
3170 1609         4198 # end of statement
3171             elsif (/\G ( [,;] ) /oxgc) {
3172             $slash = 'm//';
3173 4987         7717  
3174             # clear tr/// variable
3175             $tr_variable = '';
3176 4987         6443  
3177             # clear s/// variable
3178 4987         6234 $sub_variable = '';
3179              
3180 4987         5498 $bind_operator = '';
3181              
3182             return $1;
3183             }
3184              
3185 4987         21430 # bareword
3186             elsif (/\G ( \{ (?>\s*) (?: tr | index | rindex | reverse ) (?>\s*) \} ) /oxmsgc) {
3187             return $1;
3188             }
3189              
3190 0         0 # $0 --> $0
3191 2         4 elsif (/\G ( \$ 0 ) /oxmsgc) {
3192             $slash = 'div';
3193             return $1;
3194 2         8 }
3195 0         0 elsif (/\G ( \$ \{ (?>\s*) 0 (?>\s*) \} ) /oxmsgc) {
3196             $slash = 'div';
3197             return $1;
3198             }
3199              
3200 0         0 # $$ --> $$
3201 1         3 elsif (/\G ( \$ \$ ) (?![\w\{]) /oxmsgc) {
3202             $slash = 'div';
3203             return $1;
3204             }
3205              
3206             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
3207 1         3 # $1, $2, $3 --> $1, $2, $3 otherwise
3208 4         8 elsif (/\G \$ ((?>[1-9][0-9]*)) /oxmsgc) {
3209             $slash = 'div';
3210             return e_capture($1);
3211 4         9 }
3212 0         0 elsif (/\G \$ \{ (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} /oxmsgc) {
3213             $slash = 'div';
3214             return e_capture($1);
3215             }
3216              
3217 0         0 # $$foo[ ... ] --> $ $foo->[ ... ]
3218 0         0 elsif (/\G \$ ( \$ (?> [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \[ .+? \] ) /oxmsgc) {
3219             $slash = 'div';
3220             return e_capture($1.'->'.$2);
3221             }
3222              
3223 0         0 # $$foo{ ... } --> $ $foo->{ ... }
3224 0         0 elsif (/\G \$ ( \$ (?> [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \{ .+? \} ) /oxmsgc) {
3225             $slash = 'div';
3226             return e_capture($1.'->'.$2);
3227             }
3228              
3229 0         0 # $$foo
3230 0         0 elsif (/\G \$ ( \$ (?> [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) /oxmsgc) {
3231             $slash = 'div';
3232             return e_capture($1);
3233             }
3234              
3235 0         0 # ${ foo }
3236 0         0 elsif (/\G \$ (?>\s*) \{ ( (?>\s*) (?> [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) (?>\s*) ) \} /oxmsgc) {
3237             $slash = 'div';
3238             return '${' . $1 . '}';
3239             }
3240              
3241 0         0 # ${ ... }
3242 0         0 elsif (/\G \$ (?>\s*) \{ (?>\s*) ( $qq_brace ) (?>\s*) \} /oxmsgc) {
3243             $slash = 'div';
3244             return e_capture($1);
3245             }
3246              
3247             # variable or function
3248 0         0 # $ @ % & * $ #
3249 42         74 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) {
3250             $slash = 'div';
3251             return $1;
3252             }
3253             # $ $ $ $ $ $ $ $ $ $ $ $ $ $
3254 42         135 # $ @ # \ ' " / ? ( ) [ ] < >
3255 62         135 elsif (/\G ( \$[\$\@\#\\\'\"\/\?\(\)\[\]\<\>] ) /oxmsgc) {
3256             $slash = 'div';
3257             return $1;
3258             }
3259              
3260 62         234 # while ()
3261             elsif (/\G \b (while (?>\s*) \( (?>\s*) <[\$]?[A-Za-z_][A-Za-z_0-9]*> (?>\s*) \)) \b /oxgc) {
3262             return $1;
3263             }
3264              
3265             # while () --- glob
3266              
3267             # avoid "Error: Runtime exception" of perl version 5.005_03
3268 0         0  
3269             elsif (/\G \b while (?>\s*) \( (?>\s*) < ((?:[^>\0\a\e\f\n\r\t])+?) > (?>\s*) \) \b /oxgc) {
3270             return 'while ($_ = Elatin7::glob("' . $1 . '"))';
3271             }
3272              
3273 0         0 # while (glob)
3274             elsif (/\G \b while (?>\s*) \( (?>\s*) glob (?>\s*) \) /oxgc) {
3275             return 'while ($_ = Elatin7::glob_)';
3276             }
3277              
3278 0         0 # while (glob(WILDCARD))
3279             elsif (/\G \b while (?>\s*) \( (?>\s*) glob \b /oxgc) {
3280             return 'while ($_ = Elatin7::glob';
3281             }
3282 0         0  
  248         677  
3283             # doit if, doit unless, doit while, doit until, doit for, doit when
3284             elsif (/\G \b ( if | unless | while | until | for | when ) \b /oxgc) { $slash = 'm//'; return $1; }
3285 248         885  
  19         38  
3286 19         61 # subroutines of package Elatin7
  0         0  
3287 0         0 elsif (/\G \b (CORE:: | ->(>?\s*) (?: atan2 | [a-z]{2,})) \b /oxgc) { $slash = 'm//'; return $1; }
  13         111  
3288 13         52 elsif (/\G \b Char::eval (?= (?>\s*) \{ ) /oxgc) { $slash = 'm//'; return 'eval'; }
  0         0  
3289 0         0 elsif (/\G \b Latin7::eval (?= (?>\s*) \{ ) /oxgc) { $slash = 'm//'; return 'eval'; }
  114         178  
3290 114         482 elsif (/\G \b Char::eval \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'eval Char::escape'; }
  2         4  
3291 2         6 elsif (/\G \b Latin7::eval \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'eval Latin7::escape'; }
  0         0  
3292 0         0 elsif (/\G \b bytes::substr \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'substr'; }
  2         5  
3293 2         6 elsif (/\G \b chop \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Elatin7::chop'; }
  0         0  
3294 0         0 elsif (/\G \b bytes::index \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'index'; }
  0         0  
3295 0         0 elsif (/\G \b Char::index \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Char::index'; }
  0         0  
3296 0         0 elsif (/\G \b Latin7::index \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Latin7::index'; }
  2         5  
3297 2         6 elsif (/\G \b index \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Elatin7::index'; }
  0         0  
3298 0         0 elsif (/\G \b bytes::rindex \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'rindex'; }
  0         0  
3299 0         0 elsif (/\G \b Char::rindex \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Char::rindex'; }
  0         0  
3300 0         0 elsif (/\G \b Latin7::rindex \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Latin7::rindex'; }
  1         3  
3301 1         3 elsif (/\G \b rindex \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Elatin7::rindex'; }
  0         0  
3302 0         0 elsif (/\G \b lc (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Elatin7::lc'; }
  1         2  
3303 1         3 elsif (/\G \b lcfirst (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Elatin7::lcfirst'; }
  0         0  
3304 0         0 elsif (/\G \b uc (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Elatin7::uc'; }
  6         11  
3305             elsif (/\G \b ucfirst (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Elatin7::ucfirst'; }
3306             elsif (/\G \b fc (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Elatin7::fc'; }
3307 6         21  
  0         0  
3308 0         0 # "-s '' ..." means file test "-s 'filename' ..." (not means "- s/// ...")
  0         0  
3309 0         0 elsif (/\G -s (?>\s*) (\") ((?:$qq_char)+?) (\") /oxgc) { $slash = 'm//'; return '-s ' . e_qq('', $1,$3,$2); }
  0         0  
3310 0         0 elsif (/\G -s (?>\s+) qq (?>\s*) (\#) ((?:$qq_char)+?) (\#) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0         0  
3311 0         0 elsif (/\G -s (?>\s+) qq (?>\s*) (\() ((?:$qq_paren)+?) (\)) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0         0  
3312 0         0 elsif (/\G -s (?>\s+) qq (?>\s*) (\{) ((?:$qq_brace)+?) (\}) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0         0  
3313 0         0 elsif (/\G -s (?>\s+) qq (?>\s*) (\[) ((?:$qq_bracket)+?) (\]) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0         0  
3314             elsif (/\G -s (?>\s+) qq (?>\s*) (\<) ((?:$qq_angle)+?) (\>) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
3315 0         0 elsif (/\G -s (?>\s+) qq (?>\s*) (\S) ((?:$qq_char)+?) (\1) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0         0  
3316 0         0  
  0         0  
3317 0         0 elsif (/\G -s (?>\s*) (\') ((?:\\\'|\\\\|$q_char)+?) (\') /oxgc) { $slash = 'm//'; return '-s ' . e_q ('', $1,$3,$2); }
  0         0  
3318 0         0 elsif (/\G -s (?>\s+) q (?>\s*) (\#) ((?:\\\#|\\\\|$q_char)+?) (\#) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0         0  
3319 0         0 elsif (/\G -s (?>\s+) q (?>\s*) (\() ((?:\\\)|\\\\|$q_paren)+?) (\)) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0         0  
3320 0         0 elsif (/\G -s (?>\s+) q (?>\s*) (\{) ((?:\\\}|\\\\|$q_brace)+?) (\}) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0         0  
3321 0         0 elsif (/\G -s (?>\s+) q (?>\s*) (\[) ((?:\\\]|\\\\|$q_bracket)+?) (\]) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0         0  
3322             elsif (/\G -s (?>\s+) q (?>\s*) (\<) ((?:\\\>|\\\\|$q_angle)+?) (\>) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
3323             elsif (/\G -s (?>\s+) q (?>\s*) (\S) ((?:\\\1|\\\\|$q_char)+?) (\1) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
3324 0         0  
  0         0  
3325 0         0 elsif (/\G -s (?>\s*) (\$ (?> \w+ (?: ::\w+)* ) (?: (?: ->)? (?: [\$\@\%\&\*]\* | \$\#\* | \( (?:$qq_paren)*? \) | [\@\%\*]? \{ (?:$qq_brace)+? \} | [\@\%]? \[ (?:$qq_bracket)+? \] ) )*) /oxgc)
  0         0  
3326 0         0 { $slash = 'm//'; return "-s $1"; }
  0         0  
3327 0         0 elsif (/\G -s (?>\s*) \( ((?:$qq_paren)*?) \) /oxgc) { $slash = 'm//'; return "-s ($1)"; }
  0         0  
3328             elsif (/\G -s (?= (?>\s+) [a-z]+) /oxgc) { $slash = 'm//'; return '-s'; }
3329 0         0 elsif (/\G -s (?>\s+) ((?>\w+)) /oxgc) { $slash = 'm//'; return "-s $1"; }
  2         4  
3330 2         6  
  2         4  
3331 2         7 elsif (/\G \b bytes::length (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'length'; }
  36         61  
3332 36         101 elsif (/\G \b bytes::chr (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'chr'; }
  2         8  
3333 2         9 elsif (/\G \b chr (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Elatin7::chr'; }
  8         12  
3334 8         22 elsif (/\G \b bytes::ord (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'div'; return 'ord'; }
  0         0  
3335 0         0 elsif (/\G \b ord (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'div'; return $function_ord; }
  0         0  
3336 0         0 elsif (/\G \b glob (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Elatin7::glob'; }
  0         0  
3337 0         0 elsif (/\G \b lc \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Elatin7::lc_'; }
  0         0  
3338 0         0 elsif (/\G \b lcfirst \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Elatin7::lcfirst_'; }
  0         0  
3339 0         0 elsif (/\G \b uc \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Elatin7::uc_'; }
  0         0  
3340 0         0 elsif (/\G \b ucfirst \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Elatin7::ucfirst_'; }
  0         0  
3341             elsif (/\G \b fc \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Elatin7::fc_'; }
3342 0         0 elsif (/\G -s \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return '-s '; }
  0         0  
3343 0         0  
  0         0  
3344 0         0 elsif (/\G \b bytes::length \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'length'; }
  0         0  
3345 0         0 elsif (/\G \b bytes::chr \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'chr'; }
  0         0  
3346 0         0 elsif (/\G \b chr \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Elatin7::chr_'; }
  0         0  
3347 0         0 elsif (/\G \b bytes::ord \b (?! (?>\s*) => ) /oxgc) { $slash = 'div'; return 'ord'; }
  0         0  
3348 0         0 elsif (/\G \b ord \b (?! (?>\s*) => ) /oxgc) { $slash = 'div'; return $function_ord_; }
  0         0  
3349 0         0 elsif (/\G \b glob \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Elatin7::glob_'; }
  8         23  
3350             elsif (/\G \b reverse \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return $function_reverse; }
3351             elsif (/\G \b getc \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return $function_getc; }
3352 8         31 # split
3353             elsif (/\G \b (split) \b (?! (?>\s*) => ) /oxgc) {
3354 87         179 $slash = 'm//';
3355 87         304  
3356 87         345 my $e = '';
3357             while (/\G ( (?>\s+) | \( | \#.* ) /oxgc) {
3358             $e .= $1;
3359             }
3360 85 100       327  
  87 100       5818  
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    100          
    50          
    50          
    100          
    50          
    100          
    50          
    50          
    50          
3361             # end of split
3362             if (/\G (?= [,;\)\}\]] ) /oxgc) { return 'Elatin7::split' . $e; }
3363 2         10  
3364             # split scalar value
3365             elsif (/\G ( [\$\@\&\*] $qq_scalar ) /oxgc) { return 'Elatin7::split' . $e . e_string($1); }
3366 1         6  
3367 0         0 # split literal space
3368 0         0 elsif (/\G \b qq (\#) [ ] (\#) /oxgc) { return 'Elatin7::split' . $e . qq {qq$1 $2}; }
3369 0         0 elsif (/\G \b qq ((?>\s*)) (\() [ ] (\)) /oxgc) { return 'Elatin7::split' . $e . qq{$1qq$2 $3}; }
3370 0         0 elsif (/\G \b qq ((?>\s*)) (\{) [ ] (\}) /oxgc) { return 'Elatin7::split' . $e . qq{$1qq$2 $3}; }
3371 0         0 elsif (/\G \b qq ((?>\s*)) (\[) [ ] (\]) /oxgc) { return 'Elatin7::split' . $e . qq{$1qq$2 $3}; }
3372 0         0 elsif (/\G \b qq ((?>\s*)) (\<) [ ] (\>) /oxgc) { return 'Elatin7::split' . $e . qq{$1qq$2 $3}; }
3373 0         0 elsif (/\G \b qq ((?>\s*)) (\S) [ ] (\2) /oxgc) { return 'Elatin7::split' . $e . qq{$1qq$2 $3}; }
3374 0         0 elsif (/\G \b q (\#) [ ] (\#) /oxgc) { return 'Elatin7::split' . $e . qq {q$1 $2}; }
3375 0         0 elsif (/\G \b q ((?>\s*)) (\() [ ] (\)) /oxgc) { return 'Elatin7::split' . $e . qq {$1q$2 $3}; }
3376 0         0 elsif (/\G \b q ((?>\s*)) (\{) [ ] (\}) /oxgc) { return 'Elatin7::split' . $e . qq {$1q$2 $3}; }
3377 0         0 elsif (/\G \b q ((?>\s*)) (\[) [ ] (\]) /oxgc) { return 'Elatin7::split' . $e . qq {$1q$2 $3}; }
3378 0         0 elsif (/\G \b q ((?>\s*)) (\<) [ ] (\>) /oxgc) { return 'Elatin7::split' . $e . qq {$1q$2 $3}; }
3379 10         41 elsif (/\G \b q ((?>\s*)) (\S) [ ] (\2) /oxgc) { return 'Elatin7::split' . $e . qq {$1q$2 $3}; }
3380             elsif (/\G ' [ ] ' /oxgc) { return 'Elatin7::split' . $e . qq {' '}; }
3381             elsif (/\G " [ ] " /oxgc) { return 'Elatin7::split' . $e . qq {" "}; }
3382              
3383 0 0       0 # split qq//
  0         0  
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 # #
3386 0 0       0 else {
  0 0       0  
    0          
    0          
    0          
    0          
    0          
3387 0         0 while (not /\G \z/oxgc) {
3388 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3389 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq ( ) --> qr ( )
3390 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq { } --> qr { }
3391 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq [ ] --> qr [ ]
3392 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq < > --> qr < >
3393             elsif (/\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) /oxgc) { return e_split($e.'qr','{','}',$2,''); } # qq | | --> qr { }
3394 0         0 elsif (/\G (\S) ((?:$qq_char)*?) (\1) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq * * --> qr * *
3395             }
3396             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3397             }
3398             }
3399              
3400 0 50       0 # split qr//
  12         413  
3401             elsif (/\G \b (qr) \b /oxgc) {
3402 0         0 if (/\G (\#) ((?:$qq_char)*?) (\#) ([imosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1,$3,$2,$4); } # qr# #
3403 12 50       62 else {
  12 50       3231  
    50          
    50          
    50          
    50          
    50          
    50          
3404 0         0 while (not /\G \z/oxgc) {
3405 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3406 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([imosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # qr ( )
3407 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([imosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # qr { }
3408 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([imosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # qr [ ]
3409 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([imosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # qr < >
3410 0         0 elsif (/\G (\') ((?:$qq_char)*?) (\') ([imosxpadlunbB]*) /oxgc) { return e_split_q($e.'qr',$1, $3, $2,$4); } # qr ' '
3411             elsif (/\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ([imosxpadlunbB]*) /oxgc) { return e_split ($e.'qr','{','}',$2,$4); } # qr | | --> qr { }
3412 12         88 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([imosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # qr * *
3413             }
3414             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3415             }
3416             }
3417              
3418 0 0       0 # split q//
  0         0  
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 # #
3421 0 0       0 else {
  0 0       0  
    0          
    0          
    0          
    0          
    0          
3422 0         0 while (not /\G \z/oxgc) {
3423 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3424 0         0 elsif (/\G (\() ((?:\\\\|\\\)|\\\(|$q_paren)*?) (\)) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q ( ) --> qr ( )
3425 0         0 elsif (/\G (\{) ((?:\\\\|\\\}|\\\{|$q_brace)*?) (\}) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q { } --> qr { }
3426 0         0 elsif (/\G (\[) ((?:\\\\|\\\]|\\\[|$q_bracket)*?) (\]) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q [ ] --> qr [ ]
3427 0         0 elsif (/\G (\<) ((?:\\\\|\\\>|\\\<|$q_angle)*?) (\>) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q < > --> qr < >
3428             elsif (/\G ([*\-:?\\^|]) ((?:$q_char)*?) (\1) /oxgc) { return e_split_q($e.'qr','{','}',$2,''); } # q | | --> qr { }
3429 0         0 elsif (/\G (\S) ((?:\\\\|\\\1| $q_char)*?) (\1) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q * * --> qr * *
3430             }
3431             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3432             }
3433             }
3434              
3435 0 50       0 # split m//
  18         498  
3436             elsif (/\G \b (m) \b /oxgc) {
3437 0         0 if (/\G (\#) ((?:$qq_char)*?) (\#) ([cgimosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1,$3,$2,$4); } # m# # --> qr # #
3438 18 50       85 else {
  18 50       3849  
    50          
    50          
    50          
    50          
    50          
    50          
3439 0         0 while (not /\G \z/oxgc) {
3440 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3441 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cgimosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # m ( ) --> qr ( )
3442 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cgimosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # m { } --> qr { }
3443 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cgimosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # m [ ] --> qr [ ]
3444 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cgimosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # m < > --> qr < >
3445 0         0 elsif (/\G (\') ((?:$qq_char)*?) (\') ([cgimosxpadlunbB]*) /oxgc) { return e_split_q($e.'qr',$1, $3, $2,$4); } # m ' ' --> qr ' '
3446             elsif (/\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ([cgimosxpadlunbB]*) /oxgc) { return e_split ($e.'qr','{','}',$2,$4); } # m | | --> qr { }
3447 18         108 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cgimosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # m * * --> qr * *
3448             }
3449             die __FILE__, ": Search pattern not terminated\n";
3450             }
3451             }
3452              
3453 0         0 # split ''
3454 0         0 elsif (/\G (\') /oxgc) {
3455 0 0       0 my $q_string = '';
  0 0       0  
    0          
    0          
3456 0         0 while (not /\G \z/oxgc) {
3457 0         0 if (/\G (\\\\) /oxgc) { $q_string .= $1; }
3458 0         0 elsif (/\G (\\\') /oxgc) { $q_string .= $1; } # splitqr'' --> split qr''
3459             elsif (/\G \' /oxgc) { return e_split_q($e.q{ qr},"'","'",$q_string,''); } # ' ' --> qr ' '
3460 0         0 elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3461             }
3462             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3463             }
3464              
3465 0         0 # split ""
3466 0         0 elsif (/\G (\") /oxgc) {
3467 0 0       0 my $qq_string = '';
  0 0       0  
    0          
    0          
3468 0         0 while (not /\G \z/oxgc) {
3469 0         0 if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
3470 0         0 elsif (/\G (\\\") /oxgc) { $qq_string .= $1; } # splitqr"" --> split qr""
3471             elsif (/\G \" /oxgc) { return e_split($e.q{ qr},'"','"',$qq_string,''); } # " " --> qr " "
3472 0         0 elsif (/\G ($q_char) /oxgc) { $qq_string .= $1; }
3473             }
3474             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3475             }
3476              
3477 0         0 # split //
3478 44         131 elsif (/\G (\/) /oxgc) {
3479 44 50       186 my $regexp = '';
  381 50       1560  
    100          
    50          
3480 0         0 while (not /\G \z/oxgc) {
3481 0         0 if (/\G (\\\\) /oxgc) { $regexp .= $1; }
3482 44         188 elsif (/\G (\\\/) /oxgc) { $regexp .= $1; } # splitqr// --> split qr//
3483             elsif (/\G \/ ([cgimosxpadlunbB]*) /oxgc) { return e_split($e.q{ qr}, '/','/',$regexp,$1); } # / / --> qr / /
3484 337         649 elsif (/\G ($q_char) /oxgc) { $regexp .= $1; }
3485             }
3486             die __FILE__, ": Search pattern not terminated\n";
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 0         0  
3498             elsif (/\G \b ( tr | y ) \b /oxgc) {
3499             my $ope = $1;
3500 3 50       8  
3501 3         47 # $1 $2 $3 $4 $5 $6
3502 0         0 if (/\G (\#) ((?:$qq_char)*?) (\#) ((?:$qq_char)*?) (\#) ([cdsrbB]*) /oxgc) { # tr# # #
3503             my @tr = ($tr_variable,$2);
3504             return e_tr(@tr,'',$4,$6);
3505 0         0 }
3506 3         5 else {
3507 3 50       9 my $e = '';
  3 50       215  
    50          
    50          
    50          
    50          
3508             while (not /\G \z/oxgc) {
3509 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3510 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) /oxgc) {
3511 0 0       0 my @tr = ($tr_variable,$2);
  0 0       0  
    0          
    0          
    0          
    0          
3512 0         0 while (not /\G \z/oxgc) {
3513 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3514 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr ( ) ( )
3515 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr ( ) { }
3516 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr ( ) [ ]
3517             elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr ( ) < >
3518 0         0 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr ( ) * *
3519             }
3520             die __FILE__, ": Transliteration replacement not terminated\n";
3521 0         0 }
3522 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) {
3523 0 0       0 my @tr = ($tr_variable,$2);
  0 0       0  
    0          
    0          
    0          
    0          
3524 0         0 while (not /\G \z/oxgc) {
3525 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3526 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr { } ( )
3527 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr { } { }
3528 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr { } [ ]
3529             elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr { } < >
3530 0         0 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr { } * *
3531             }
3532             die __FILE__, ": Transliteration replacement not terminated\n";
3533 0         0 }
3534 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) {
3535 0 0       0 my @tr = ($tr_variable,$2);
  0 0       0  
    0          
    0          
    0          
    0          
3536 0         0 while (not /\G \z/oxgc) {
3537 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3538 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr [ ] ( )
3539 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr [ ] { }
3540 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr [ ] [ ]
3541             elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr [ ] < >
3542 0         0 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr [ ] * *
3543             }
3544             die __FILE__, ": Transliteration replacement not terminated\n";
3545 0         0 }
3546 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) {
3547 0 0       0 my @tr = ($tr_variable,$2);
  0 0       0  
    0          
    0          
    0          
    0          
3548 0         0 while (not /\G \z/oxgc) {
3549 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3550 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr < > ( )
3551 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr < > { }
3552 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr < > [ ]
3553             elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr < > < >
3554 0         0 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr < > * *
3555             }
3556             die __FILE__, ": Transliteration replacement not terminated\n";
3557             }
3558 0         0 # $1 $2 $3 $4 $5 $6
3559 3         12 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ((?:$qq_char)*?) (\1) ([cdsrbB]*) /oxgc) { # tr * * *
3560             my @tr = ($tr_variable,$2);
3561             return e_tr(@tr,'',$4,$6);
3562 3         8 }
3563             }
3564             die __FILE__, ": Transliteration pattern not terminated\n";
3565             }
3566             }
3567              
3568 0         0 # qq//
3569             elsif (/\G \b (qq) \b /oxgc) {
3570             my $ope = $1;
3571 2180 50       16701  
3572 2180         5061 # if (/\G (\#) ((?:$qq_char)*?) (\#) /oxgc) { return e_qq($ope,$1,$3,$2); } # qq# #
3573 0         0 if (/\G (\#) /oxgc) { # qq# #
3574 0 0       0 my $qq_string = '';
  0 0       0  
    0          
    0          
3575 0         0 while (not /\G \z/oxgc) {
3576 0         0 if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
3577 0         0 elsif (/\G (\\\#) /oxgc) { $qq_string .= $1; }
3578             elsif (/\G (\#) /oxgc) { return e_qq($ope,'#','#',$qq_string); }
3579 0         0 elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3580             }
3581             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3582             }
3583 0         0  
3584 2180         3388 else {
3585 2180 50       5742 my $e = '';
  2180 50       9442  
    100          
    50          
    50          
    0          
3586             while (not /\G \z/oxgc) {
3587             if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3588              
3589 0         0 # elsif (/\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qq ( )
3590 0         0 elsif (/\G (\() /oxgc) { # qq ( )
3591 0         0 my $qq_string = '';
3592 0 0       0 local $nest = 1;
  0 0       0  
    0          
    0          
    0          
3593 0         0 while (not /\G \z/oxgc) {
3594 0         0 if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0         0  
3595             elsif (/\G (\\\)) /oxgc) { $qq_string .= $1; }
3596 0 0       0 elsif (/\G (\() /oxgc) { $qq_string .= $1; $nest++; }
  0         0  
3597 0         0 elsif (/\G (\)) /oxgc) {
3598             if (--$nest == 0) { return $e . e_qq($ope,'(',')',$qq_string); }
3599 0         0 else { $qq_string .= $1; }
3600             }
3601 0         0 elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3602             }
3603             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3604             }
3605              
3606 0         0 # elsif (/\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qq { }
3607 2150         3046 elsif (/\G (\{) /oxgc) { # qq { }
3608 2150         4550 my $qq_string = '';
3609 2150 100       5048 local $nest = 1;
  84006 50       302983  
    100          
    100          
    50          
3610 722         1387 while (not /\G \z/oxgc) {
3611 0         0 if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  1153         1662  
3612             elsif (/\G (\\\}) /oxgc) { $qq_string .= $1; }
3613 1153 100       1953 elsif (/\G (\{) /oxgc) { $qq_string .= $1; $nest++; }
  3303         6686  
3614 2150         5120 elsif (/\G (\}) /oxgc) {
3615             if (--$nest == 0) { return $e . e_qq($ope,'{','}',$qq_string); }
3616 1153         2758 else { $qq_string .= $1; }
3617             }
3618 78828         189035 elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3619             }
3620             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3621             }
3622              
3623 0         0 # elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qq [ ]
3624 0         0 elsif (/\G (\[) /oxgc) { # qq [ ]
3625 0         0 my $qq_string = '';
3626 0 0       0 local $nest = 1;
  0 0       0  
    0          
    0          
    0          
3627 0         0 while (not /\G \z/oxgc) {
3628 0         0 if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0         0  
3629             elsif (/\G (\\\]) /oxgc) { $qq_string .= $1; }
3630 0 0       0 elsif (/\G (\[) /oxgc) { $qq_string .= $1; $nest++; }
  0         0  
3631 0         0 elsif (/\G (\]) /oxgc) {
3632             if (--$nest == 0) { return $e . e_qq($ope,'[',']',$qq_string); }
3633 0         0 else { $qq_string .= $1; }
3634             }
3635 0         0 elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3636             }
3637             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3638             }
3639              
3640 0         0 # elsif (/\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qq < >
3641 30         54 elsif (/\G (\<) /oxgc) { # qq < >
3642 30         55 my $qq_string = '';
3643 30 100       95 local $nest = 1;
  1166 50       3839  
    50          
    100          
    50          
3644 22         50 while (not /\G \z/oxgc) {
3645 0         0 if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0         0  
3646             elsif (/\G (\\\>) /oxgc) { $qq_string .= $1; }
3647 0 50       0 elsif (/\G (\<) /oxgc) { $qq_string .= $1; $nest++; }
  30         72  
3648 30         72 elsif (/\G (\>) /oxgc) {
3649             if (--$nest == 0) { return $e . e_qq($ope,'<','>',$qq_string); }
3650 0         0 else { $qq_string .= $1; }
3651             }
3652 1114         2251 elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3653             }
3654             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3655             }
3656              
3657 0         0 # elsif (/\G (\S) ((?:$qq_char)*?) (\1) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qq * *
3658 0         0 elsif (/\G (\S) /oxgc) { # qq * *
3659 0         0 my $delimiter = $1;
3660 0 0       0 my $qq_string = '';
  0 0       0  
    0          
    0          
3661 0         0 while (not /\G \z/oxgc) {
3662 0         0 if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
3663 0         0 elsif (/\G (\\\Q$delimiter\E) /oxgc) { $qq_string .= $1; }
3664             elsif (/\G (\Q$delimiter\E) /oxgc) { return $e . e_qq($ope,$delimiter,$delimiter,$qq_string); }
3665 0         0 elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3666             }
3667             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3668 0         0 }
3669             }
3670             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3671             }
3672             }
3673              
3674 0         0 # qr//
3675 0 0       0 elsif (/\G \b (qr) \b /oxgc) {
3676 0         0 my $ope = $1;
3677             if (/\G (\#) ((?:$qq_char)*?) (\#) ([imosxpadlunbB]*) /oxgc) { # qr# # #
3678             return e_qr($ope,$1,$3,$2,$4);
3679 0         0 }
3680 0         0 else {
3681 0 0       0 my $e = '';
  0 0       0  
    0          
    0          
    0          
    0          
    0          
    0          
3682 0         0 while (not /\G \z/oxgc) {
3683 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3684 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([imosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # qr ( )
3685 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([imosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # qr { }
3686 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([imosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # qr [ ]
3687 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([imosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # qr < >
3688 0         0 elsif (/\G (\') ((?:$qq_char)*?) (\') ([imosxpadlunbB]*) /oxgc) { return $e . e_qr_q($ope,$1, $3, $2,$4); } # qr ' '
3689             elsif (/\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ([imosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,'{','}',$2,$4); } # qr | | --> qr { }
3690 0         0 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([imosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # qr * *
3691             }
3692             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3693             }
3694             }
3695              
3696 0         0 # qw//
3697 16 50       46 elsif (/\G \b (qw) \b /oxgc) {
3698 16         70 my $ope = $1;
3699             if (/\G (\#) (.*?) (\#) /oxmsgc) { # qw# #
3700             return e_qw($ope,$1,$3,$2);
3701 0         0 }
3702 16         28 else {
3703 16 50       51 my $e = '';
  16 50       122  
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
3704             while (not /\G \z/oxgc) {
3705 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3706 16         53  
3707             elsif (/\G (\() ([^(]*?) (\)) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw ( )
3708 0         0 elsif (/\G (\() ((?:$q_paren)*?) (\)) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw ( )
3709 0         0  
3710             elsif (/\G (\{) ([^{]*?) (\}) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw { }
3711 0         0 elsif (/\G (\{) ((?:$q_brace)*?) (\}) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw { }
3712 0         0  
3713             elsif (/\G (\[) ([^[]*?) (\]) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw [ ]
3714 0         0 elsif (/\G (\[) ((?:$q_bracket)*?) (\]) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw [ ]
3715 0         0  
3716             elsif (/\G (\<) ([^<]*?) (\>) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw < >
3717 0         0 elsif (/\G (\<) ((?:$q_angle)*?) (\>) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw < >
3718 0         0  
3719             elsif (/\G ([\x21-\x3F]) (.*?) (\1) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw * *
3720 0         0 elsif (/\G (\S) ((?:$q_char)*?) (\1) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw * *
3721             }
3722             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3723             }
3724             }
3725              
3726 0         0 # qx//
3727 0 0       0 elsif (/\G \b (qx) \b /oxgc) {
3728 0         0 my $ope = $1;
3729             if (/\G (\#) ((?:$qq_char)*?) (\#) /oxgc) { # qx# #
3730             return e_qq($ope,$1,$3,$2);
3731 0         0 }
3732 0         0 else {
3733 0 0       0 my $e = '';
  0 0       0  
    0          
    0          
    0          
    0          
    0          
3734 0         0 while (not /\G \z/oxgc) {
3735 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3736 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qx ( )
3737 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qx { }
3738 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qx [ ]
3739 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qx < >
3740             elsif (/\G (\') ((?:$qq_char)*?) (\') /oxgc) { return $e . e_q ($ope,$1,$3,$2); } # qx ' '
3741 0         0 elsif (/\G (\S) ((?:$qq_char)*?) (\1) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qx * *
3742             }
3743             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3744             }
3745             }
3746              
3747 0         0 # q//
3748             elsif (/\G \b (q) \b /oxgc) {
3749             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 410 50       1130 # (and so on)
3755 410         1175  
3756 0         0 if (/\G (\#) /oxgc) { # q# #
3757 0 0       0 my $q_string = '';
  0 0       0  
    0          
    0          
3758 0         0 while (not /\G \z/oxgc) {
3759 0         0 if (/\G (\\\\) /oxgc) { $q_string .= $1; }
3760 0         0 elsif (/\G (\\\#) /oxgc) { $q_string .= $1; }
3761             elsif (/\G (\#) /oxgc) { return e_q($ope,'#','#',$q_string); }
3762 0         0 elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3763             }
3764             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3765             }
3766 0         0  
3767 410         711 else {
3768 410 50       1675 my $e = '';
  410 50       2406  
    100          
    50          
    100          
    50          
3769             while (not /\G \z/oxgc) {
3770             if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3771              
3772 0         0 # elsif (/\G (\() ((?:\\\)|\\\\|$q_paren)*?) (\)) /oxgc) { return $e . e_q($ope,$1,$3,$2); } # q ( )
3773 0         0 elsif (/\G (\() /oxgc) { # q ( )
3774 0         0 my $q_string = '';
3775 0 0       0 local $nest = 1;
  0 0       0  
    0          
    0          
    0          
    0          
3776 0         0 while (not /\G \z/oxgc) {
3777 0         0 if (/\G (\\\\) /oxgc) { $q_string .= $1; }
3778 0         0 elsif (/\G (\\\)) /oxgc) { $q_string .= $1; }
  0         0  
3779             elsif (/\G (\\\() /oxgc) { $q_string .= $1; }
3780 0 0       0 elsif (/\G (\() /oxgc) { $q_string .= $1; $nest++; }
  0         0  
3781 0         0 elsif (/\G (\)) /oxgc) {
3782             if (--$nest == 0) { return $e . e_q($ope,'(',')',$q_string); }
3783 0         0 else { $q_string .= $1; }
3784             }
3785 0         0 elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3786             }
3787             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3788             }
3789              
3790 0         0 # elsif (/\G (\{) ((?:\\\}|\\\\|$q_brace)*?) (\}) /oxgc) { return $e . e_q($ope,$1,$3,$2); } # q { }
3791 404         909 elsif (/\G (\{) /oxgc) { # q { }
3792 404         709 my $q_string = '';
3793 404 50       1083 local $nest = 1;
  6770 50       35082  
    50          
    100          
    100          
    50          
3794 0         0 while (not /\G \z/oxgc) {
3795 0         0 if (/\G (\\\\) /oxgc) { $q_string .= $1; }
3796 0         0 elsif (/\G (\\\}) /oxgc) { $q_string .= $1; }
  107         164  
3797             elsif (/\G (\\\{) /oxgc) { $q_string .= $1; }
3798 107 100       186 elsif (/\G (\{) /oxgc) { $q_string .= $1; $nest++; }
  511         978  
3799 404         1148 elsif (/\G (\}) /oxgc) {
3800             if (--$nest == 0) { return $e . e_q($ope,'{','}',$q_string); }
3801 107         264 else { $q_string .= $1; }
3802             }
3803 6152         14396 elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3804             }
3805             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3806             }
3807              
3808 0         0 # elsif (/\G (\[) ((?:\\\]|\\\\|$q_bracket)*?) (\]) /oxgc) { return $e . e_q($ope,$1,$3,$2); } # q [ ]
3809 0         0 elsif (/\G (\[) /oxgc) { # q [ ]
3810 0         0 my $q_string = '';
3811 0 0       0 local $nest = 1;
  0 0       0  
    0          
    0          
    0          
    0          
3812 0         0 while (not /\G \z/oxgc) {
3813 0         0 if (/\G (\\\\) /oxgc) { $q_string .= $1; }
3814 0         0 elsif (/\G (\\\]) /oxgc) { $q_string .= $1; }
  0         0  
3815             elsif (/\G (\\\[) /oxgc) { $q_string .= $1; }
3816 0 0       0 elsif (/\G (\[) /oxgc) { $q_string .= $1; $nest++; }
  0         0  
3817 0         0 elsif (/\G (\]) /oxgc) {
3818             if (--$nest == 0) { return $e . e_q($ope,'[',']',$q_string); }
3819 0         0 else { $q_string .= $1; }
3820             }
3821 0         0 elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3822             }
3823             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3824             }
3825              
3826 0         0 # elsif (/\G (\<) ((?:\\\>|\\\\|$q_angle)*?) (\>) /oxgc) { return $e . e_q($ope,$1,$3,$2); } # q < >
3827 5         12 elsif (/\G (\<) /oxgc) { # q < >
3828 5         9 my $q_string = '';
3829 5 50       19 local $nest = 1;
  88 50       412  
    50          
    50          
    100          
    50          
3830 0         0 while (not /\G \z/oxgc) {
3831 0         0 if (/\G (\\\\) /oxgc) { $q_string .= $1; }
3832 0         0 elsif (/\G (\\\>) /oxgc) { $q_string .= $1; }
  0         0  
3833             elsif (/\G (\\\<) /oxgc) { $q_string .= $1; }
3834 0 50       0 elsif (/\G (\<) /oxgc) { $q_string .= $1; $nest++; }
  5         12  
3835 5         14 elsif (/\G (\>) /oxgc) {
3836             if (--$nest == 0) { return $e . e_q($ope,'<','>',$q_string); }
3837 0         0 else { $q_string .= $1; }
3838             }
3839 83         177 elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3840             }
3841             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3842             }
3843              
3844 0         0 # elsif (/\G (\S) ((?:\\\1|\\\\|$q_char)*?) (\1) /oxgc) { return $e . e_q($ope,$1,$3,$2); } # q * *
3845 1         2 elsif (/\G (\S) /oxgc) { # q * *
3846 1         2 my $delimiter = $1;
3847 1 50       3 my $q_string = '';
  14 50       67  
    100          
    50          
3848 0         0 while (not /\G \z/oxgc) {
3849 0         0 if (/\G (\\\\) /oxgc) { $q_string .= $1; }
3850 1         12 elsif (/\G (\\\Q$delimiter\E) /oxgc) { $q_string .= $1; }
3851             elsif (/\G (\Q$delimiter\E) /oxgc) { return $e . e_q($ope,$delimiter,$delimiter,$q_string); }
3852 13         22 elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3853             }
3854             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3855 0         0 }
3856             }
3857             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3858             }
3859             }
3860              
3861 0         0 # m//
3862 209 50       541 elsif (/\G \b (m) \b /oxgc) {
3863 209         1526 my $ope = $1;
3864             if (/\G (\#) ((?:$qq_char)*?) (\#) ([cgimosxpadlunbB]*) /oxgc) { # m# #
3865             return e_qr($ope,$1,$3,$2,$4);
3866 0         0 }
3867 209         331 else {
3868 209 50       568 my $e = '';
  209 50       11717  
    50          
    50          
    50          
    50          
    100          
    50          
    50          
3869 0         0 while (not /\G \z/oxgc) {
3870 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3871 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cgimosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m ( )
3872 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cgimosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m { }
3873 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cgimosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m [ ]
3874 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cgimosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m < >
3875 10         35 elsif (/\G (\?) ((?:$qq_char)*?) (\?) ([cgimosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m ? ?
3876 0         0 elsif (/\G (\') ((?:$qq_char)*?) (\') ([cgimosxpadlunbB]*) /oxgc) { return $e . e_qr_q($ope,$1, $3, $2,$4); } # m ' '
3877             elsif (/\G ([*\-:\\^|]) ((?:$qq_char)*?) (\1) ([cgimosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,'{','}',$2,$4); } # m | | --> m { }
3878 199         697 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cgimosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m * *
3879             }
3880             die __FILE__, ": Search pattern not terminated\n";
3881             }
3882             }
3883              
3884             # s///
3885              
3886             # about [cegimosxpradlunbB]* (/cg modifier)
3887             #
3888             # P.67 Pattern-Matching Operators
3889             # of ISBN 0-596-00241-6 Perl in a Nutshell, Second Edition.
3890 0         0  
3891             elsif (/\G \b (s) \b /oxgc) {
3892             my $ope = $1;
3893 97 100       506  
3894 97         3789 # $1 $2 $3 $4 $5 $6
3895             if (/\G (\#) ((?:$qq_char)*?) (\#) ((?:$qq_char)*?) (\#) ([cegimosxpradlunbB]*) /oxgc) { # s# # #
3896             return e_sub($sub_variable,$1,$2,$3,$3,$4,$5,$6);
3897 1         4 }
3898 96         213 else {
3899 96 50       341 my $e = '';
  96 50       12816  
    50          
    50          
    50          
    100          
    50          
    50          
    50          
3900             while (not /\G \z/oxgc) {
3901 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3902 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) /oxgc) {
3903 0 0       0 my @s = ($1,$2,$3);
  0 0       0  
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
3904             while (not /\G \z/oxgc) {
3905 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3906 0         0 # $1 $2 $3 $4
3907 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3908 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3909 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3910 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3911 0         0 elsif (/\G (\') ((?:$qq_char)*?) (\') ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3912 0         0 elsif (/\G (\$) ((?:$qq_char)*?) (\$) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3913 0         0 elsif (/\G (\:) ((?:$qq_char)*?) (\:) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3914             elsif (/\G (\@) ((?:$qq_char)*?) (\@) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3915 0         0 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3916             }
3917             die __FILE__, ": Substitution replacement not terminated\n";
3918 0         0 }
3919 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) {
3920 0 0       0 my @s = ($1,$2,$3);
  0 0       0  
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
3921             while (not /\G \z/oxgc) {
3922 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3923 0         0 # $1 $2 $3 $4
3924 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3925 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3926 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3927 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3928 0         0 elsif (/\G (\') ((?:$qq_char)*?) (\') ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3929 0         0 elsif (/\G (\$) ((?:$qq_char)*?) (\$) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3930 0         0 elsif (/\G (\:) ((?:$qq_char)*?) (\:) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3931             elsif (/\G (\@) ((?:$qq_char)*?) (\@) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3932 0         0 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3933             }
3934             die __FILE__, ": Substitution replacement not terminated\n";
3935 0         0 }
3936 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) {
3937 0 0       0 my @s = ($1,$2,$3);
  0 0       0  
    0          
    0          
    0          
    0          
    0          
    0          
3938             while (not /\G \z/oxgc) {
3939 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3940 0         0 # $1 $2 $3 $4
3941 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3942 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3943 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3944 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3945 0         0 elsif (/\G (\') ((?:$qq_char)*?) (\') ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3946             elsif (/\G (\$) ((?:$qq_char)*?) (\$) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3947 0         0 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3948             }
3949             die __FILE__, ": Substitution replacement not terminated\n";
3950 0         0 }
3951 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) {
3952 0 0       0 my @s = ($1,$2,$3);
  0 0       0  
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
3953             while (not /\G \z/oxgc) {
3954 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3955 0         0 # $1 $2 $3 $4
3956 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3957 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3958 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3959 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3960 0         0 elsif (/\G (\') ((?:$qq_char)*?) (\') ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3961 0         0 elsif (/\G (\$) ((?:$qq_char)*?) (\$) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3962 0         0 elsif (/\G (\:) ((?:$qq_char)*?) (\:) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3963             elsif (/\G (\@) ((?:$qq_char)*?) (\@) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3964 0         0 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3965             }
3966             die __FILE__, ": Substitution replacement not terminated\n";
3967             }
3968 0         0 # $1 $2 $3 $4 $5 $6
3969             elsif (/\G (\') ((?:$qq_char)*?) (\') ((?:$qq_char)*?) (\') ([cegimosxpradlunbB]*) /oxgc) {
3970             return e_sub($sub_variable,$1,$2,$3,$3,$4,$5,$6);
3971             }
3972 21         59 # $1 $2 $3 $4 $5 $6
3973             elsif (/\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ((?:$qq_char)*?) (\1) ([cegimosxpradlunbB]*) /oxgc) {
3974             return e_sub($sub_variable,'{',$2,'}','{',$4,'}',$6); # s | | | --> s { } { }
3975             }
3976 0         0 # $1 $2 $3 $4 $5 $6
3977             elsif (/\G (\$) ((?:$qq_char)*?) (\1) ((?:$qq_char)*?) (\1) ([cegimosxpradlunbB]*) /oxgc) {
3978             return e_sub($sub_variable,$1,$2,$3,$3,$4,$5,$6);
3979             }
3980 0         0 # $1 $2 $3 $4 $5 $6
3981             elsif (/\G (\S) ((?:$qq_char)*?) (\1) ((?:$qq_char)*?) (\1) ([cegimosxpradlunbB]*) /oxgc) {
3982             return e_sub($sub_variable,$1,$2,$3,$3,$4,$5,$6);
3983 75         389 }
3984             }
3985             die __FILE__, ": Substitution pattern not terminated\n";
3986             }
3987             }
3988 0         0  
3989 0         0 # require ignore module
3990 0         0 elsif (/\G \b require ((?>\s+) (?:$ignore_modules) .*? ;) ([ \t]* [#\n]) /oxmsgc) { return "# require$1$2"; }
3991             elsif (/\G \b require ((?>\s+) (?:$ignore_modules) .*? ;) ([ \t]* [^#]) /oxmsgc) { return "# require$1\n$2"; }
3992             elsif (/\G \b require ((?>\s+) (?:$ignore_modules)) \b /oxmsgc) { return "# require$1"; }
3993 0         0  
3994 37         291 # use strict; --> use strict; no strict qw(refs);
3995 0         0 elsif (/\G \b use ((?>\s+) strict .*? ;) ([ \t]* [#\n]) /oxmsgc) { return "use$1 no strict qw(refs);$2"; }
3996             elsif (/\G \b use ((?>\s+) strict .*? ;) ([ \t]* [^#]) /oxmsgc) { return "use$1 no strict qw(refs);\n$2"; }
3997             elsif (/\G \b use ((?>\s+) strict) \b /oxmsgc) { return "use$1; no strict qw(refs)"; }
3998              
3999 0 50 33     0 # use 5.12.0; --> use 5.12.0; no strict qw(refs);
      33        
4000 2         23 elsif (/\G \b use (?>\s+) ((?>([1-9][0-9_]*)(?:\.([0-9_]+))*)) (?>\s*) ; /oxmsgc) {
4001             if (($2 >= 6) or (($2 == 5) and ($3 ge '012'))) {
4002             return "use $1; no strict qw(refs);";
4003 0         0 }
4004             else {
4005             return "use $1;";
4006             }
4007 2 0 0     11 }
      0        
4008 0         0 elsif (/\G \b use (?>\s+) ((?>v([0-9][0-9_]*)(?:\.([0-9_]+))*)) (?>\s*) ; /oxmsgc) {
4009             if (($2 >= 6) or (($2 == 5) and ($3 >= 12))) {
4010             return "use $1; no strict qw(refs);";
4011 0         0 }
4012             else {
4013             return "use $1;";
4014             }
4015             }
4016 0         0  
4017 2         14 # ignore use module
4018 0         0 elsif (/\G \b use ((?>\s+) (?:$ignore_modules) .*? ;) ([ \t]* [#\n]) /oxmsgc) { return "# use$1$2"; }
4019             elsif (/\G \b use ((?>\s+) (?:$ignore_modules) .*? ;) ([ \t]* [^#]) /oxmsgc) { return "# use$1\n$2"; }
4020             elsif (/\G \b use ((?>\s+) (?:$ignore_modules)) \b /oxmsgc) { return "# use$1"; }
4021 0         0  
4022 0         0 # ignore no module
4023 0         0 elsif (/\G \b no ((?>\s+) (?:$ignore_modules) .*? ;) ([ \t]* [#\n]) /oxmsgc) { return "# no$1$2"; }
4024             elsif (/\G \b no ((?>\s+) (?:$ignore_modules) .*? ;) ([ \t]* [^#]) /oxmsgc) { return "# no$1\n$2"; }
4025             elsif (/\G \b no ((?>\s+) (?:$ignore_modules)) \b /oxmsgc) { return "# no$1"; }
4026 0         0  
4027             # use else
4028             elsif (/\G \b use \b /oxmsgc) { return "use"; }
4029 0         0  
4030             # use else
4031             elsif (/\G \b no \b /oxmsgc) { return "no"; }
4032              
4033 2         10 # ''
4034 848         1710 elsif (/\G (?
4035 848 100       2209 my $q_string = '';
  8254 100       28301  
    100          
    50          
4036 4         12 while (not /\G \z/oxgc) {
4037 48         89 if (/\G (\\\\) /oxgc) { $q_string .= $1; }
4038 848         2051 elsif (/\G (\\\') /oxgc) { $q_string .= $1; }
4039             elsif (/\G \' /oxgc) { return e_q('', "'","'",$q_string); }
4040 7354         14441 elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
4041             }
4042             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4043             }
4044              
4045 0         0 # ""
4046 1782         4038 elsif (/\G (\") /oxgc) {
4047 1782 100       4972 my $qq_string = '';
  35079 100       112062  
    100          
    50          
4048 67         153 while (not /\G \z/oxgc) {
4049 12         32 if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
4050 1782         4248 elsif (/\G (\\\") /oxgc) { $qq_string .= $1; }
4051             elsif (/\G \" /oxgc) { return e_qq('', '"','"',$qq_string); }
4052 33218         68277 elsif (/\G ($q_char) /oxgc) { $qq_string .= $1; }
4053             }
4054             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4055             }
4056              
4057 0         0 # ``
4058 1         3 elsif (/\G (\`) /oxgc) {
4059 1 50       3 my $qx_string = '';
  19 50       61  
    100          
    50          
4060 0         0 while (not /\G \z/oxgc) {
4061 0         0 if (/\G (\\\\) /oxgc) { $qx_string .= $1; }
4062 1         3 elsif (/\G (\\\`) /oxgc) { $qx_string .= $1; }
4063             elsif (/\G \` /oxgc) { return e_qq('', '`','`',$qx_string); }
4064 18         36 elsif (/\G ($q_char) /oxgc) { $qx_string .= $1; }
4065             }
4066             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4067             }
4068              
4069 0         0 # // --- not divide operator (num / num), not defined-or
4070 453         1544 elsif (($slash eq 'm//') and /\G (\/) /oxgc) {
4071 453 50       1403 my $regexp = '';
  4496 50       18400  
    100          
    50          
4072 0         0 while (not /\G \z/oxgc) {
4073 0         0 if (/\G (\\\\) /oxgc) { $regexp .= $1; }
4074 453         2912 elsif (/\G (\\\/) /oxgc) { $regexp .= $1; }
4075             elsif (/\G \/ ([cgimosxpadlunbB]*) /oxgc) { return e_qr('', '/','/',$regexp,$1); }
4076 4043         10422 elsif (/\G ($q_char) /oxgc) { $regexp .= $1; }
4077             }
4078             die __FILE__, ": Search pattern not terminated\n";
4079             }
4080              
4081 0         0 # ?? --- not conditional operator (condition ? then : else)
4082 0         0 elsif (($slash eq 'm//') and /\G (\?) /oxgc) {
4083 0 0       0 my $regexp = '';
  0 0       0  
    0          
    0          
4084 0         0 while (not /\G \z/oxgc) {
4085 0         0 if (/\G (\\\\) /oxgc) { $regexp .= $1; }
4086 0         0 elsif (/\G (\\\?) /oxgc) { $regexp .= $1; }
4087             elsif (/\G \? ([cgimosxpadlunbB]*) /oxgc) { return e_qr('m','?','?',$regexp,$1); }
4088 0         0 elsif (/\G ($q_char) /oxgc) { $regexp .= $1; }
4089             }
4090             die __FILE__, ": Search pattern not terminated\n";
4091             }
4092 0         0  
  0         0  
4093             # <<>> (a safer ARGV)
4094             elsif (/\G ( <<>> ) /oxgc) { $slash = 'm//'; return $1; }
4095 0         0  
  0         0  
4096             # << (bit shift) --- not here document
4097             elsif (/\G ( << (?>\s*) ) (?= [0-9\$\@\&] ) /oxgc) { $slash = 'm//'; return $1; }
4098              
4099 0         0 # <<~'HEREDOC'
4100 6         16 elsif (/\G ( <<~ [\t ]* '([a-zA-Z_0-9]*)' ) /oxgc) {
4101 6         11 $slash = 'm//';
4102             my $here_quote = $1;
4103             my $delimiter = $2;
4104 6 50       12  
4105 6         14 # get here document
4106 6         29 if ($here_script eq '') {
4107             $here_script = CORE::substr $_, pos $_;
4108 6 50       34 $here_script =~ s/.*?\n//oxm;
4109 6         67 }
4110 6         16 if ($here_script =~ s/\A (.*?) \n ([\t ]*) $delimiter \n //xms) {
4111 6         10 my $heredoc = $1;
4112 6         50 my $indent = $2;
4113 6         19 $heredoc =~ s{^$indent}{}msg; # no /ox
4114             push @heredoc, $heredoc . qq{\n$delimiter\n};
4115             push @heredoc_delimiter, qq{\\s*$delimiter};
4116 6         14 }
4117             else {
4118 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4119             }
4120             return qq{<<'$delimiter'};
4121             }
4122              
4123             # <<~\HEREDOC
4124              
4125             # P.66 2.6.6. "Here" Documents
4126             # in Chapter 2: Bits and Pieces
4127             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
4128              
4129             # P.73 "Here" Documents
4130             # in Chapter 2: Bits and Pieces
4131             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
4132 6         25  
4133 3         7 elsif (/\G ( <<~ \\([a-zA-Z_0-9]+) ) /oxgc) {
4134 3         7 $slash = 'm//';
4135             my $here_quote = $1;
4136             my $delimiter = $2;
4137 3 50       16  
4138 3         7 # get here document
4139 3         14 if ($here_script eq '') {
4140             $here_script = CORE::substr $_, pos $_;
4141 3 50       29 $here_script =~ s/.*?\n//oxm;
4142 3         42 }
4143 3         8 if ($here_script =~ s/\A (.*?) \n ([\t ]*) $delimiter \n //xms) {
4144 3         6 my $heredoc = $1;
4145 3         36 my $indent = $2;
4146 3         13 $heredoc =~ s{^$indent}{}msg; # no /ox
4147             push @heredoc, $heredoc . qq{\n$delimiter\n};
4148             push @heredoc_delimiter, qq{\\s*$delimiter};
4149 3         8 }
4150             else {
4151 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4152             }
4153             return qq{<<\\$delimiter};
4154             }
4155              
4156 3         11 # <<~"HEREDOC"
4157 6         13 elsif (/\G ( <<~ [\t ]* "([a-zA-Z_0-9]*)" ) /oxgc) {
4158 6         12 $slash = 'm//';
4159             my $here_quote = $1;
4160             my $delimiter = $2;
4161 6 50       12  
4162 6         13 # get here document
4163 6         34 if ($here_script eq '') {
4164             $here_script = CORE::substr $_, pos $_;
4165 6 50       33 $here_script =~ s/.*?\n//oxm;
4166 6         73 }
4167 6         17 if ($here_script =~ s/\A (.*?) \n ([\t ]*) $delimiter \n //xms) {
4168 6         9 my $heredoc = $1;
4169 6         49 my $indent = $2;
4170 6         21 $heredoc =~ s{^$indent}{}msg; # no /ox
4171             push @heredoc, e_heredoc($heredoc) . qq{\n$delimiter\n};
4172             push @heredoc_delimiter, qq{\\s*$delimiter};
4173 6         15 }
4174             else {
4175 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4176             }
4177             return qq{<<"$delimiter"};
4178             }
4179              
4180 6         25 # <<~HEREDOC
4181 3         7 elsif (/\G ( <<~ ([a-zA-Z_0-9]+) ) /oxgc) {
4182 3         7 $slash = 'm//';
4183             my $here_quote = $1;
4184             my $delimiter = $2;
4185 3 50       7  
4186 3         10 # get here document
4187 3         21 if ($here_script eq '') {
4188             $here_script = CORE::substr $_, pos $_;
4189 3 50       19 $here_script =~ s/.*?\n//oxm;
4190 3         42 }
4191 3         9 if ($here_script =~ s/\A (.*?) \n ([\t ]*) $delimiter \n //xms) {
4192 3         7 my $heredoc = $1;
4193 3         144 my $indent = $2;
4194 3         16 $heredoc =~ s{^$indent}{}msg; # no /ox
4195             push @heredoc, e_heredoc($heredoc) . qq{\n$delimiter\n};
4196             push @heredoc_delimiter, qq{\\s*$delimiter};
4197 3         9 }
4198             else {
4199 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4200             }
4201             return qq{<<$delimiter};
4202             }
4203              
4204 3         13 # <<~`HEREDOC`
4205 6         15 elsif (/\G ( <<~ [\t ]* `([a-zA-Z_0-9]*)` ) /oxgc) {
4206 6         14 $slash = 'm//';
4207             my $here_quote = $1;
4208             my $delimiter = $2;
4209 6 50       9  
4210 6         14 # get here document
4211 6         19 if ($here_script eq '') {
4212             $here_script = CORE::substr $_, pos $_;
4213 6 50       39 $here_script =~ s/.*?\n//oxm;
4214 6         59 }
4215 6         13 if ($here_script =~ s/\A (.*?) \n ([\t ]*) $delimiter \n //xms) {
4216 6         10 my $heredoc = $1;
4217 6         50 my $indent = $2;
4218 6         19 $heredoc =~ s{^$indent}{}msg; # no /ox
4219             push @heredoc, e_heredoc($heredoc) . qq{\n$delimiter\n};
4220             push @heredoc_delimiter, qq{\\s*$delimiter};
4221 6         15 }
4222             else {
4223 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4224             }
4225             return qq{<<`$delimiter`};
4226             }
4227              
4228 6         23 # <<'HEREDOC'
4229 72         145 elsif (/\G ( << '([a-zA-Z_0-9]*)' ) /oxgc) {
4230 72         198 $slash = 'm//';
4231             my $here_quote = $1;
4232             my $delimiter = $2;
4233 72 50       120  
4234 72         214 # get here document
4235 72         351 if ($here_script eq '') {
4236             $here_script = CORE::substr $_, pos $_;
4237 72 50       511 $here_script =~ s/.*?\n//oxm;
4238 72         553 }
4239 72         240 if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4240             push @heredoc, $1 . qq{\n$delimiter\n};
4241             push @heredoc_delimiter, $delimiter;
4242 72         119 }
4243             else {
4244 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4245             }
4246             return $here_quote;
4247             }
4248              
4249             # <<\HEREDOC
4250              
4251             # P.66 2.6.6. "Here" Documents
4252             # in Chapter 2: Bits and Pieces
4253             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
4254              
4255             # P.73 "Here" Documents
4256             # in Chapter 2: Bits and Pieces
4257             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
4258 72         273  
4259 0         0 elsif (/\G ( << \\([a-zA-Z_0-9]+) ) /oxgc) {
4260 0         0 $slash = 'm//';
4261             my $here_quote = $1;
4262             my $delimiter = $2;
4263 0 0       0  
4264 0         0 # get here document
4265 0         0 if ($here_script eq '') {
4266             $here_script = CORE::substr $_, pos $_;
4267 0 0       0 $here_script =~ s/.*?\n//oxm;
4268 0         0 }
4269 0         0 if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4270             push @heredoc, $1 . qq{\n$delimiter\n};
4271             push @heredoc_delimiter, $delimiter;
4272 0         0 }
4273             else {
4274 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4275             }
4276             return $here_quote;
4277             }
4278              
4279 0         0 # <<"HEREDOC"
4280 36         91 elsif (/\G ( << "([a-zA-Z_0-9]*)" ) /oxgc) {
4281 36         83 $slash = 'm//';
4282             my $here_quote = $1;
4283             my $delimiter = $2;
4284 36 50       69  
4285 36         92 # get here document
4286 36         258 if ($here_script eq '') {
4287             $here_script = CORE::substr $_, pos $_;
4288 36 50       211 $here_script =~ s/.*?\n//oxm;
4289 36         512 }
4290 36         187 if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4291             push @heredoc, e_heredoc($1) . qq{\n$delimiter\n};
4292             push @heredoc_delimiter, $delimiter;
4293 36         92 }
4294             else {
4295 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4296             }
4297             return $here_quote;
4298             }
4299              
4300 36         145 # <
4301 42         177 elsif (/\G ( << ([a-zA-Z_0-9]+) ) /oxgc) {
4302 42         100 $slash = 'm//';
4303             my $here_quote = $1;
4304             my $delimiter = $2;
4305 42 50       78  
4306 42         113 # get here document
4307 42         329 if ($here_script eq '') {
4308             $here_script = CORE::substr $_, pos $_;
4309 42 50       303 $here_script =~ s/.*?\n//oxm;
4310 42         661 }
4311 42         171 if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4312             push @heredoc, e_heredoc($1) . qq{\n$delimiter\n};
4313             push @heredoc_delimiter, $delimiter;
4314 42         187 }
4315             else {
4316 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4317             }
4318             return $here_quote;
4319             }
4320              
4321 42         196 # <<`HEREDOC`
4322 0         0 elsif (/\G ( << `([a-zA-Z_0-9]*)` ) /oxgc) {
4323 0         0 $slash = 'm//';
4324             my $here_quote = $1;
4325             my $delimiter = $2;
4326 0 0       0  
4327 0         0 # get here document
4328 0         0 if ($here_script eq '') {
4329             $here_script = CORE::substr $_, pos $_;
4330 0 0       0 $here_script =~ s/.*?\n//oxm;
4331 0         0 }
4332 0         0 if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4333             push @heredoc, e_heredoc($1) . qq{\n$delimiter\n};
4334             push @heredoc_delimiter, $delimiter;
4335 0         0 }
4336             else {
4337 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4338             }
4339             return $here_quote;
4340             }
4341              
4342 0         0 # <<= <=> <= < operator
4343             elsif (/\G ( <<= | <=> | <= | < ) (?= (?>\s*) [A-Za-z_0-9'"`\$\@\&\*\(\+\-] )/oxgc) {
4344             return $1;
4345             }
4346              
4347 12         62 #
4348             elsif (/\G (<[\$]?[A-Za-z_][A-Za-z_0-9]*>) /oxgc) {
4349             return $1;
4350             }
4351              
4352             # --- glob
4353              
4354             # avoid "Error: Runtime exception" of perl version 5.005_03
4355 0         0  
4356             elsif (/\G < ((?:[^>\0\a\e\f\n\r\t])+?) > /oxgc) {
4357             return 'Elatin7::glob("' . $1 . '")';
4358             }
4359 0         0  
4360             # __DATA__
4361             elsif (/\G ^ ( __DATA__ \n .*) \z /oxmsgc) { return $1; }
4362 0         0  
4363             # __END__
4364             elsif (/\G ^ ( __END__ \n .*) \z /oxmsgc) { return $1; }
4365              
4366             # \cD Control-D
4367              
4368             # P.68 2.6.8. Other Literal Tokens
4369             # in Chapter 2: Bits and Pieces
4370             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
4371              
4372             # P.76 Other Literal Tokens
4373             # in Chapter 2: Bits and Pieces
4374 204         1472 # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
4375              
4376             elsif (/\G ( \cD .*) \z /oxmsgc) { return $1; }
4377 0         0  
4378             # \cZ Control-Z
4379             elsif (/\G ( \cZ .*) \z /oxmsgc) { return $1; }
4380              
4381             # any operator before div
4382             elsif (/\G (
4383             -- | \+\+ |
4384 0         0 [\)\}\]]
  5081         11285  
4385              
4386             ) /oxgc) { $slash = 'div'; return $1; }
4387              
4388             # yada-yada or triple-dot operator
4389             elsif (/\G (
4390 5081         26661 \.\.\.
  7         14  
4391              
4392             ) /oxgc) { $slash = 'm//'; return q{die('Unimplemented')}; }
4393              
4394             # any operator before m//
4395              
4396             # //, //= (defined-or)
4397              
4398             # P.164 Logical Operators
4399             # in Chapter 10: More Control Structures
4400             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
4401              
4402             # P.119 C-Style Logical (Short-Circuit) Operators
4403             # in Chapter 3: Unary and Binary Operators
4404             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
4405              
4406             # (and so on)
4407              
4408             # ~~
4409              
4410             # P.221 The Smart Match Operator
4411             # in Chapter 15: Smart Matching and given-when
4412             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
4413              
4414             # P.112 Smartmatch Operator
4415             # in Chapter 3: Unary and Binary Operators
4416             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
4417              
4418             # (and so on)
4419              
4420             elsif (/\G ((?>
4421              
4422             !~~ | !~ | != | ! |
4423             %= | % |
4424             &&= | && | &= | &\.= | &\. | & |
4425             -= | -> | - |
4426             :(?>\s*)= |
4427             : |
4428             <<>> |
4429             <<= | <=> | <= | < |
4430             == | => | =~ | = |
4431             >>= | >> | >= | > |
4432             \*\*= | \*\* | \*= | \* |
4433             \+= | \+ |
4434             \.\. | \.= | \. |
4435             \/\/= | \/\/ |
4436             \/= | \/ |
4437             \? |
4438             \\ |
4439             \^= | \^\.= | \^\. | \^ |
4440             \b x= |
4441             \|\|= | \|\| | \|= | \|\.= | \|\. | \| |
4442             ~~ | ~\. | ~ |
4443             \b(?: and | cmp | eq | ge | gt | le | lt | ne | not | or | xor | x )\b |
4444             \b(?: print )\b |
4445              
4446 7         23 [,;\(\{\[]
  8835         20715  
4447              
4448             )) /oxgc) { $slash = 'm//'; return $1; }
4449 8835         42979  
  15137         58377  
4450             # other any character
4451             elsif (/\G ($q_char) /oxgc) { $slash = 'div'; return $1; }
4452              
4453 15137         73728 # system error
4454             else {
4455             die __FILE__, ": Oops, this shouldn't happen!\n";
4456             }
4457             }
4458              
4459 0     1786 0 0 # escape Latin-7 string
4460 1786         4060 sub e_string {
4461             my($string) = @_;
4462 1786         2683 my $e_string = '';
4463              
4464             local $slash = 'm//';
4465              
4466             # P.1024 Appendix W.10 Multibyte Processing
4467             # of ISBN 1-56592-224-7 CJKV Information Processing
4468 1786         2697 # (and so on)
4469              
4470             my @char = $string =~ / \G (?>[^\\]|\\$q_char|$q_char) /oxmsg;
4471 1786 100 66     30275  
4472 1786 50       8282 # without { ... }
4473 1769         3900 if (not (grep(/\A \{ \z/xms, @char) and grep(/\A \} \z/xms, @char))) {
4474             if ($string !~ /<
4475             return $string;
4476             }
4477             }
4478 1769         4348  
4479 17 50       66 E_STRING_LOOP:
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    100          
    100          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    100          
    50          
    100          
    50          
4480             while ($string !~ /\G \z/oxgc) {
4481             if (0) {
4482             }
4483 190         11716  
4484 0         0 # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> @{[Elatin7::PREMATCH()]}
4485 0         0 elsif ($string =~ /\G ( \$` | \$\{`\} | \$ (?>\s*) PREMATCH \b | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} ) /oxmsgc) {
4486             $e_string .= q{Elatin7::PREMATCH()};
4487             $slash = 'div';
4488             }
4489              
4490 0         0 # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> @{[Elatin7::MATCH()]}
4491 0         0 elsif ($string =~ /\G ( \$& | \$\{&\} | \$ (?>\s*) MATCH \b | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} ) /oxmsgc) {
4492             $e_string .= q{Elatin7::MATCH()};
4493             $slash = 'div';
4494             }
4495              
4496 0         0 # $', ${'} --> $', ${'}
4497 0         0 elsif ($string =~ /\G ( \$' | \$\{'\} ) /oxmsgc) {
4498             $e_string .= $1;
4499             $slash = 'div';
4500             }
4501              
4502 0         0 # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> @{[Elatin7::POSTMATCH()]}
4503 0         0 elsif ($string =~ /\G ( \$ (?>\s*) POSTMATCH \b | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} ) /oxmsgc) {
4504             $e_string .= q{Elatin7::POSTMATCH()};
4505             $slash = 'div';
4506             }
4507              
4508 0         0 # bareword
4509 0         0 elsif ($string =~ /\G ( \{ (?>\s*) (?: tr | index | rindex | reverse ) (?>\s*) \} ) /oxmsgc) {
4510             $e_string .= $1;
4511             $slash = 'div';
4512             }
4513              
4514 0         0 # $0 --> $0
4515 0         0 elsif ($string =~ /\G ( \$ 0 ) /oxmsgc) {
4516             $e_string .= $1;
4517             $slash = 'div';
4518 0         0 }
4519 0         0 elsif ($string =~ /\G ( \$ \{ (?>\s*) 0 (?>\s*) \} ) /oxmsgc) {
4520             $e_string .= $1;
4521             $slash = 'div';
4522             }
4523              
4524 0         0 # $$ --> $$
4525 0         0 elsif ($string =~ /\G ( \$ \$ ) (?![\w\{]) /oxmsgc) {
4526             $e_string .= $1;
4527             $slash = 'div';
4528             }
4529              
4530             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
4531 0         0 # $1, $2, $3 --> $1, $2, $3 otherwise
4532 0         0 elsif ($string =~ /\G \$ ((?>[1-9][0-9]*)) /oxmsgc) {
4533             $e_string .= e_capture($1);
4534             $slash = 'div';
4535 0         0 }
4536 0         0 elsif ($string =~ /\G \$ \{ (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} /oxmsgc) {
4537             $e_string .= e_capture($1);
4538             $slash = 'div';
4539             }
4540              
4541 0         0 # $$foo[ ... ] --> $ $foo->[ ... ]
4542 0         0 elsif ($string =~ /\G \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \[ .+? \] ) /oxmsgc) {
4543             $e_string .= e_capture($1.'->'.$2);
4544             $slash = 'div';
4545             }
4546              
4547 0         0 # $$foo{ ... } --> $ $foo->{ ... }
4548 0         0 elsif ($string =~ /\G \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \{ .+? \} ) /oxmsgc) {
4549             $e_string .= e_capture($1.'->'.$2);
4550             $slash = 'div';
4551             }
4552              
4553 0         0 # $$foo
4554 0         0 elsif ($string =~ /\G \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) /oxmsgc) {
4555             $e_string .= e_capture($1);
4556             $slash = 'div';
4557             }
4558              
4559 0         0 # ${ foo }
4560 0         0 elsif ($string =~ /\G \$ (?>\s*) \{ ((?> \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* )) \} /oxmsgc) {
4561             $e_string .= '${' . $1 . '}';
4562             $slash = 'div';
4563             }
4564              
4565 0         0 # ${ ... }
4566 3         9 elsif ($string =~ /\G \$ (?>\s*) \{ (?>\s*) ( $qq_brace ) (?>\s*) \} /oxmsgc) {
4567             $e_string .= e_capture($1);
4568             $slash = 'div';
4569             }
4570              
4571             # variable or function
4572 3         15 # $ @ % & * $ #
4573 7         23 elsif ($string =~ /\G ( (?: [\$\@\%\&\*] | \$\# | -> | \b sub \b) (?>\s*) (?: split | chop | index | rindex | lc | uc | fc | chr | ord | reverse | getc | tr | y | q | qq | qx | qw | m | s | qr | glob | lstat | opendir | stat | unlink | chdir ) ) \b /oxmsgc) {
4574             $e_string .= $1;
4575             $slash = 'div';
4576             }
4577             # $ $ $ $ $ $ $ $ $ $ $ $ $ $
4578 7         20 # $ @ # \ ' " / ? ( ) [ ] < >
4579 0         0 elsif ($string =~ /\G ( \$[\$\@\#\\\'\"\/\?\(\)\[\]\<\>] ) /oxmsgc) {
4580             $e_string .= $1;
4581             $slash = 'div';
4582             }
4583 0         0  
  0         0  
4584 0         0 # subroutines of package Elatin7
  0         0  
4585 0         0 elsif ($string =~ /\G \b (CORE:: | ->(>?\s*) (?: atan2 | [a-z]{2,})) \b /oxgc) { $e_string .= $1; $slash = 'm//'; }
  0         0  
4586 0         0 elsif ($string =~ /\G \b Char::eval (?= (?>\s*) \{ ) /oxgc) { $e_string .= 'eval'; $slash = 'm//'; }
  0         0  
4587 0         0 elsif ($string =~ /\G \b Latin7::eval (?= (?>\s*) \{ ) /oxgc) { $e_string .= 'eval'; $slash = 'm//'; }
  0         0  
4588 0         0 elsif ($string =~ /\G \b Char::eval \b /oxgc) { $e_string .= 'eval Char::escape'; $slash = 'm//'; }
  0         0  
4589 0         0 elsif ($string =~ /\G \b Latin7::eval \b /oxgc) { $e_string .= 'eval Latin7::escape'; $slash = 'm//'; }
  0         0  
4590 0         0 elsif ($string =~ /\G \b bytes::substr \b /oxgc) { $e_string .= 'substr'; $slash = 'm//'; }
  0         0  
4591 0         0 elsif ($string =~ /\G \b chop \b /oxgc) { $e_string .= 'Elatin7::chop'; $slash = 'm//'; }
  0         0  
4592 0         0 elsif ($string =~ /\G \b bytes::index \b /oxgc) { $e_string .= 'index'; $slash = 'm//'; }
  0         0  
4593 0         0 elsif ($string =~ /\G \b Char::index \b /oxgc) { $e_string .= 'Char::index'; $slash = 'm//'; }
  0         0  
4594 0         0 elsif ($string =~ /\G \b Latin7::index \b /oxgc) { $e_string .= 'Latin7::index'; $slash = 'm//'; }
  0         0  
4595 0         0 elsif ($string =~ /\G \b index \b /oxgc) { $e_string .= 'Elatin7::index'; $slash = 'm//'; }
  0         0  
4596 0         0 elsif ($string =~ /\G \b bytes::rindex \b /oxgc) { $e_string .= 'rindex'; $slash = 'm//'; }
  0         0  
4597 0         0 elsif ($string =~ /\G \b Char::rindex \b /oxgc) { $e_string .= 'Char::rindex'; $slash = 'm//'; }
  0         0  
4598 0         0 elsif ($string =~ /\G \b Latin7::rindex \b /oxgc) { $e_string .= 'Latin7::rindex'; $slash = 'm//'; }
  0         0  
4599 0         0 elsif ($string =~ /\G \b rindex \b /oxgc) { $e_string .= 'Elatin7::rindex'; $slash = 'm//'; }
  0         0  
4600 0         0 elsif ($string =~ /\G \b lc (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Elatin7::lc'; $slash = 'm//'; }
  0         0  
4601 0         0 elsif ($string =~ /\G \b lcfirst (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Elatin7::lcfirst'; $slash = 'm//'; }
  0         0  
4602 0         0 elsif ($string =~ /\G \b uc (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Elatin7::uc'; $slash = 'm//'; }
  0         0  
4603             elsif ($string =~ /\G \b ucfirst (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Elatin7::ucfirst'; $slash = 'm//'; }
4604             elsif ($string =~ /\G \b fc (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Elatin7::fc'; $slash = 'm//'; }
4605 0         0  
  0         0  
4606 0         0 # "-s '' ..." means file test "-s 'filename' ..." (not means "- s/// ...")
  0         0  
4607 0         0 elsif ($string =~ /\G -s (?>\s*) (\") ((?:$qq_char)+?) (\") /oxgc) { $e_string .= '-s ' . e_qq('', $1,$3,$2); $slash = 'm//'; }
  0         0  
4608 0         0 elsif ($string =~ /\G -s (?>\s+) qq (?>\s*) (\#) ((?:$qq_char)+?) (\#) /oxgc) { $e_string .= '-s ' . e_qq('qq',$1,$3,$2); $slash = 'm//'; }
  0         0  
4609 0         0 elsif ($string =~ /\G -s (?>\s+) qq (?>\s*) (\() ((?:$qq_paren)+?) (\)) /oxgc) { $e_string .= '-s ' . e_qq('qq',$1,$3,$2); $slash = 'm//'; }
  0         0  
4610 0         0 elsif ($string =~ /\G -s (?>\s+) qq (?>\s*) (\{) ((?:$qq_brace)+?) (\}) /oxgc) { $e_string .= '-s ' . e_qq('qq',$1,$3,$2); $slash = 'm//'; }
  0         0  
4611 0         0 elsif ($string =~ /\G -s (?>\s+) qq (?>\s*) (\[) ((?:$qq_bracket)+?) (\]) /oxgc) { $e_string .= '-s ' . e_qq('qq',$1,$3,$2); $slash = 'm//'; }
  0         0  
4612             elsif ($string =~ /\G -s (?>\s+) qq (?>\s*) (\<) ((?:$qq_angle)+?) (\>) /oxgc) { $e_string .= '-s ' . e_qq('qq',$1,$3,$2); $slash = 'm//'; }
4613 0         0 elsif ($string =~ /\G -s (?>\s+) qq (?>\s*) (\S) ((?:$qq_char)+?) (\1) /oxgc) { $e_string .= '-s ' . e_qq('qq',$1,$3,$2); $slash = 'm//'; }
  0         0  
4614 0         0  
  0         0  
4615 0         0 elsif ($string =~ /\G -s (?>\s*) (\') ((?:\\\'|\\\\|$q_char)+?) (\') /oxgc) { $e_string .= '-s ' . e_q ('', $1,$3,$2); $slash = 'm//'; }
  0         0  
4616 0         0 elsif ($string =~ /\G -s (?>\s+) q (?>\s*) (\#) ((?:\\\#|\\\\|$q_char)+?) (\#) /oxgc) { $e_string .= '-s ' . e_q ('q', $1,$3,$2); $slash = 'm//'; }
  0         0  
4617 0         0 elsif ($string =~ /\G -s (?>\s+) q (?>\s*) (\() ((?:\\\)|\\\\|$q_paren)+?) (\)) /oxgc) { $e_string .= '-s ' . e_q ('q', $1,$3,$2); $slash = 'm//'; }
  0         0  
4618 0         0 elsif ($string =~ /\G -s (?>\s+) q (?>\s*) (\{) ((?:\\\}|\\\\|$q_brace)+?) (\}) /oxgc) { $e_string .= '-s ' . e_q ('q', $1,$3,$2); $slash = 'm//'; }
  0         0  
4619 0         0 elsif ($string =~ /\G -s (?>\s+) q (?>\s*) (\[) ((?:\\\]|\\\\|$q_bracket)+?) (\]) /oxgc) { $e_string .= '-s ' . e_q ('q', $1,$3,$2); $slash = 'm//'; }
  0         0  
4620             elsif ($string =~ /\G -s (?>\s+) q (?>\s*) (\<) ((?:\\\>|\\\\|$q_angle)+?) (\>) /oxgc) { $e_string .= '-s ' . e_q ('q', $1,$3,$2); $slash = 'm//'; }
4621             elsif ($string =~ /\G -s (?>\s+) q (?>\s*) (\S) ((?:\\\1|\\\\|$q_char)+?) (\1) /oxgc) { $e_string .= '-s ' . e_q ('q', $1,$3,$2); $slash = 'm//'; }
4622 0         0  
  0         0  
4623 0         0 elsif ($string =~ /\G -s (?>\s*) (\$ (?> \w+ (?: ::\w+)*) (?: (?: ->)? (?: [\$\@\%\&\*]\* | \$\#\* | \( (?:$qq_paren)*? \) | [\@\%\*]? \{ (?:$qq_brace)+? \} | [\@\%]? \[ (?:$qq_bracket)+? \] ))*) /oxgc)
  0         0  
4624 0         0 { $e_string .= "-s $1"; $slash = 'm//'; }
  0         0  
4625 0         0 elsif ($string =~ /\G -s (?>\s*) \( ((?:$qq_paren)*?) \) /oxgc) { $e_string .= "-s ($1)"; $slash = 'm//'; }
  0         0  
4626             elsif ($string =~ /\G -s (?= (?>\s+) [a-z]+) /oxgc) { $e_string .= '-s'; $slash = 'm//'; }
4627 0         0 elsif ($string =~ /\G -s (?>\s+) ((?>\w+)) /oxgc) { $e_string .= "-s $1"; $slash = 'm//'; }
  0         0  
4628 0         0  
  0         0  
4629 0         0 elsif ($string =~ /\G \b bytes::length (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'length'; $slash = 'm//'; }
  0         0  
4630 0         0 elsif ($string =~ /\G \b bytes::chr (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'chr'; $slash = 'm//'; }
  0         0  
4631 0         0 elsif ($string =~ /\G \b chr (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Elatin7::chr'; $slash = 'm//'; }
  0         0  
4632 0         0 elsif ($string =~ /\G \b bytes::ord (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'ord'; $slash = 'div'; }
  0         0  
4633 0         0 elsif ($string =~ /\G \b ord (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $e_string .= $function_ord; $slash = 'div'; }
  0         0  
4634 0         0 elsif ($string =~ /\G \b glob (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $e_string .= 'Elatin7::glob'; $slash = 'm//'; }
  0         0  
4635 0         0 elsif ($string =~ /\G \b lc \b /oxgc) { $e_string .= 'Elatin7::lc_'; $slash = 'm//'; }
  0         0  
4636 0         0 elsif ($string =~ /\G \b lcfirst \b /oxgc) { $e_string .= 'Elatin7::lcfirst_'; $slash = 'm//'; }
  0         0  
4637 0         0 elsif ($string =~ /\G \b uc \b /oxgc) { $e_string .= 'Elatin7::uc_'; $slash = 'm//'; }
  0         0  
4638 0         0 elsif ($string =~ /\G \b ucfirst \b /oxgc) { $e_string .= 'Elatin7::ucfirst_'; $slash = 'm//'; }
  0         0  
4639             elsif ($string =~ /\G \b fc \b /oxgc) { $e_string .= 'Elatin7::fc_'; $slash = 'm//'; }
4640 0         0 elsif ($string =~ /\G -s \b /oxgc) { $e_string .= '-s '; $slash = 'm//'; }
  0         0  
4641 0         0  
  0         0  
4642 0         0 elsif ($string =~ /\G \b bytes::length \b /oxgc) { $e_string .= 'length'; $slash = 'm//'; }
  0         0  
4643 0         0 elsif ($string =~ /\G \b bytes::chr \b /oxgc) { $e_string .= 'chr'; $slash = 'm//'; }
  0         0  
4644 0         0 elsif ($string =~ /\G \b chr \b /oxgc) { $e_string .= 'Elatin7::chr_'; $slash = 'm//'; }
  0         0  
4645 0         0 elsif ($string =~ /\G \b bytes::ord \b /oxgc) { $e_string .= 'ord'; $slash = 'div'; }
  0         0  
4646 0         0 elsif ($string =~ /\G \b ord \b /oxgc) { $e_string .= $function_ord_; $slash = 'div'; }
  0         0  
4647 0         0 elsif ($string =~ /\G \b glob \b /oxgc) { $e_string .= 'Elatin7::glob_'; $slash = 'm//'; }
  0         0  
4648             elsif ($string =~ /\G \b reverse \b /oxgc) { $e_string .= $function_reverse; $slash = 'm//'; }
4649             elsif ($string =~ /\G \b getc \b /oxgc) { $e_string .= $function_getc; $slash = 'm//'; }
4650 0         0 # split
4651             elsif ($string =~ /\G \b (split) \b (?! (?>\s*) => ) /oxgc) {
4652 0         0 $slash = 'm//';
4653 0         0  
4654 0         0 my $e = '';
4655             while ($string =~ /\G ( (?>\s+) | \( | \#.* ) /oxgc) {
4656             $e .= $1;
4657             }
4658 0 0       0  
  0 0       0  
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
4659             # end of split
4660             if ($string =~ /\G (?= [,;\)\}\]] ) /oxgc) { return 'Elatin7::split' . $e; }
4661 0         0  
  0         0  
4662             # split scalar value
4663             elsif ($string =~ /\G ( [\$\@\&\*] $qq_scalar ) /oxgc) { $e_string .= 'Elatin7::split' . $e . e_string($1); next E_STRING_LOOP; }
4664 0         0  
  0         0  
4665 0         0 # split literal space
  0         0  
4666 0         0 elsif ($string =~ /\G \b qq (\#) [ ] (\#) /oxgc) { $e_string .= 'Elatin7::split' . $e . qq {qq$1 $2}; next E_STRING_LOOP; }
  0         0  
4667 0         0 elsif ($string =~ /\G \b qq ((?>\s*)) (\() [ ] (\)) /oxgc) { $e_string .= 'Elatin7::split' . $e . qq{$1qq$2 $3}; next E_STRING_LOOP; }
  0         0  
4668 0         0 elsif ($string =~ /\G \b qq ((?>\s*)) (\{) [ ] (\}) /oxgc) { $e_string .= 'Elatin7::split' . $e . qq{$1qq$2 $3}; next E_STRING_LOOP; }
  0         0  
4669 0         0 elsif ($string =~ /\G \b qq ((?>\s*)) (\[) [ ] (\]) /oxgc) { $e_string .= 'Elatin7::split' . $e . qq{$1qq$2 $3}; next E_STRING_LOOP; }
  0         0  
4670 0         0 elsif ($string =~ /\G \b qq ((?>\s*)) (\<) [ ] (\>) /oxgc) { $e_string .= 'Elatin7::split' . $e . qq{$1qq$2 $3}; next E_STRING_LOOP; }
  0         0  
4671 0         0 elsif ($string =~ /\G \b qq ((?>\s*)) (\S) [ ] (\2) /oxgc) { $e_string .= 'Elatin7::split' . $e . qq{$1qq$2 $3}; next E_STRING_LOOP; }
  0         0  
4672 0         0 elsif ($string =~ /\G \b q (\#) [ ] (\#) /oxgc) { $e_string .= 'Elatin7::split' . $e . qq {q$1 $2}; next E_STRING_LOOP; }
  0         0  
4673 0         0 elsif ($string =~ /\G \b q ((?>\s*)) (\() [ ] (\)) /oxgc) { $e_string .= 'Elatin7::split' . $e . qq {$1q$2 $3}; next E_STRING_LOOP; }
  0         0  
4674 0         0 elsif ($string =~ /\G \b q ((?>\s*)) (\{) [ ] (\}) /oxgc) { $e_string .= 'Elatin7::split' . $e . qq {$1q$2 $3}; next E_STRING_LOOP; }
  0         0  
4675 0         0 elsif ($string =~ /\G \b q ((?>\s*)) (\[) [ ] (\]) /oxgc) { $e_string .= 'Elatin7::split' . $e . qq {$1q$2 $3}; next E_STRING_LOOP; }
  0         0  
4676 0         0 elsif ($string =~ /\G \b q ((?>\s*)) (\<) [ ] (\>) /oxgc) { $e_string .= 'Elatin7::split' . $e . qq {$1q$2 $3}; next E_STRING_LOOP; }
  0         0  
4677 0         0 elsif ($string =~ /\G \b q ((?>\s*)) (\S) [ ] (\2) /oxgc) { $e_string .= 'Elatin7::split' . $e . qq {$1q$2 $3}; next E_STRING_LOOP; }
  0         0  
4678             elsif ($string =~ /\G ' [ ] ' /oxgc) { $e_string .= 'Elatin7::split' . $e . qq {' '}; next E_STRING_LOOP; }
4679             elsif ($string =~ /\G " [ ] " /oxgc) { $e_string .= 'Elatin7::split' . $e . qq {" "}; next E_STRING_LOOP; }
4680              
4681 0 0       0 # split qq//
  0         0  
  0         0  
4682             elsif ($string =~ /\G \b (qq) \b /oxgc) {
4683 0         0 if ($string =~ /\G (\#) ((?:$qq_char)*?) (\#) /oxgc) { $e_string .= e_split($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # qq# # --> qr # #
4684 0 0       0 else {
  0 0       0  
    0          
    0          
    0          
    0          
    0          
4685 0         0 while ($string !~ /\G \z/oxgc) {
  0         0  
4686 0         0 if ($string =~ /\G ((?>\s+)|\#.*) /oxgc) { $e_string .= $e . $1; }
  0         0  
4687 0         0 elsif ($string =~ /\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { $e_string .= e_split($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # qq ( ) --> qr ( )
  0         0  
4688 0         0 elsif ($string =~ /\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { $e_string .= e_split($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # qq { } --> qr { }
  0         0  
4689 0         0 elsif ($string =~ /\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { $e_string .= e_split($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # qq [ ] --> qr [ ]
  0         0  
4690 0         0 elsif ($string =~ /\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { $e_string .= e_split($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # qq < > --> qr < >
  0         0  
4691             elsif ($string =~ /\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) /oxgc) { $e_string .= e_split($e.'qr','{','}',$2,''); next E_STRING_LOOP; } # qq | | --> qr { }
4692 0         0 elsif ($string =~ /\G (\S) ((?:$qq_char)*?) (\1) /oxgc) { $e_string .= e_split($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # qq * * --> qr * *
4693             }
4694             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4695             }
4696             }
4697              
4698 0 0       0 # split qr//
  0         0  
  0         0  
4699             elsif ($string =~ /\G \b (qr) \b /oxgc) {
4700 0         0 if ($string =~ /\G (\#) ((?:$qq_char)*?) (\#) ([imosxpadlunbB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1,$3,$2,$4); next E_STRING_LOOP; } # qr# #
4701 0 0       0 else {
  0 0       0  
    0          
    0          
    0          
    0          
    0          
    0          
4702 0         0 while ($string !~ /\G \z/oxgc) {
  0         0  
4703 0         0 if ($string =~ /\G ((?>\s+)|\#.*) /oxgc) { $e_string .= $e . $1; }
  0         0  
4704 0         0 elsif ($string =~ /\G (\() ((?:$qq_paren)*?) (\)) ([imosxpadlunbB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # qr ( )
  0         0  
4705 0         0 elsif ($string =~ /\G (\{) ((?:$qq_brace)*?) (\}) ([imosxpadlunbB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # qr { }
  0         0  
4706 0         0 elsif ($string =~ /\G (\[) ((?:$qq_bracket)*?) (\]) ([imosxpadlunbB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # qr [ ]
  0         0  
4707 0         0 elsif ($string =~ /\G (\<) ((?:$qq_angle)*?) (\>) ([imosxpadlunbB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # qr < >
  0         0  
4708 0         0 elsif ($string =~ /\G (\') ((?:$qq_char)*?) (\') ([imosxpadlunbB]*) /oxgc) { $e_string .= e_split_q($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # qr ' '
  0         0  
4709             elsif ($string =~ /\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ([imosxpadlunbB]*) /oxgc) { $e_string .= e_split ($e.'qr','{','}',$2,$4); next E_STRING_LOOP; } # qr | | --> qr { }
4710 0         0 elsif ($string =~ /\G (\S) ((?:$qq_char)*?) (\1) ([imosxpadlunbB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # qr * *
4711             }
4712             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4713             }
4714             }
4715              
4716 0 0       0 # split q//
  0         0  
  0         0  
4717             elsif ($string =~ /\G \b (q) \b /oxgc) {
4718 0         0 if ($string =~ /\G (\#) ((?:\\\#|\\\\|$q_char)*?) (\#) /oxgc) { $e_string .= e_split_q($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # q# # --> qr # #
4719 0 0       0 else {
  0 0       0  
    0          
    0          
    0          
    0          
    0          
4720 0         0 while ($string !~ /\G \z/oxgc) {
  0         0  
4721 0         0 if ($string =~ /\G ((?>\s+)|\#.*) /oxgc) { $e_string .= $e . $1; }
  0         0  
4722 0         0 elsif ($string =~ /\G (\() ((?:\\\\|\\\)|\\\(|$q_paren)*?) (\)) /oxgc) { $e_string .= e_split_q($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # q ( ) --> qr ( )
  0         0  
4723 0         0 elsif ($string =~ /\G (\{) ((?:\\\\|\\\}|\\\{|$q_brace)*?) (\}) /oxgc) { $e_string .= e_split_q($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # q { } --> qr { }
  0         0  
4724 0         0 elsif ($string =~ /\G (\[) ((?:\\\\|\\\]|\\\[|$q_bracket)*?) (\]) /oxgc) { $e_string .= e_split_q($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # q [ ] --> qr [ ]
  0         0  
4725 0         0 elsif ($string =~ /\G (\<) ((?:\\\\|\\\>|\\\<|$q_angle)*?) (\>) /oxgc) { $e_string .= e_split_q($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # q < > --> qr < >
  0         0  
4726             elsif ($string =~ /\G ([*\-:?\\^|]) ((?:$q_char)*?) (\1) /oxgc) { $e_string .= e_split_q($e.'qr','{','}',$2,''); next E_STRING_LOOP; } # q | | --> qr { }
4727 0         0 elsif ($string =~ /\G (\S) ((?:\\\\|\\\1| $q_char)*?) (\1) /oxgc) { $e_string .= e_split_q($e.'qr',$1,$3,$2,''); next E_STRING_LOOP; } # q * * --> qr * *
4728             }
4729             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4730             }
4731             }
4732              
4733 0 0       0 # split m//
  0         0  
  0         0  
4734             elsif ($string =~ /\G \b (m) \b /oxgc) {
4735 0         0 if ($string =~ /\G (\#) ((?:$qq_char)*?) (\#) ([cgimosxpadlunbB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1,$3,$2,$4); next E_STRING_LOOP; } # m# # --> qr # #
4736 0 0       0 else {
  0 0       0  
    0          
    0          
    0          
    0          
    0          
    0          
4737 0         0 while ($string !~ /\G \z/oxgc) {
  0         0  
4738 0         0 if ($string =~ /\G ((?>\s+)|\#.*) /oxgc) { $e_string .= $e . $1; }
  0         0  
4739 0         0 elsif ($string =~ /\G (\() ((?:$qq_paren)*?) (\)) ([cgimosxpadlunbB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # m ( ) --> qr ( )
  0         0  
4740 0         0 elsif ($string =~ /\G (\{) ((?:$qq_brace)*?) (\}) ([cgimosxpadlunbB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # m { } --> qr { }
  0         0  
4741 0         0 elsif ($string =~ /\G (\[) ((?:$qq_bracket)*?) (\]) ([cgimosxpadlunbB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # m [ ] --> qr [ ]
  0         0  
4742 0         0 elsif ($string =~ /\G (\<) ((?:$qq_angle)*?) (\>) ([cgimosxpadlunbB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # m < > --> qr < >
  0         0  
4743 0         0 elsif ($string =~ /\G (\') ((?:$qq_char)*?) (\') ([cgimosxpadlunbB]*) /oxgc) { $e_string .= e_split_q($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # m ' ' --> qr ' '
  0         0  
4744             elsif ($string =~ /\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ([cgimosxpadlunbB]*) /oxgc) { $e_string .= e_split ($e.'qr','{','}',$2,$4); next E_STRING_LOOP; } # m | | --> qr { }
4745 0         0 elsif ($string =~ /\G (\S) ((?:$qq_char)*?) (\1) ([cgimosxpadlunbB]*) /oxgc) { $e_string .= e_split ($e.'qr',$1, $3, $2,$4); next E_STRING_LOOP; } # m * * --> qr * *
4746             }
4747             die __FILE__, ": Search pattern not terminated\n";
4748             }
4749             }
4750              
4751 0         0 # split ''
4752 0         0 elsif ($string =~ /\G (\') /oxgc) {
4753 0 0       0 my $q_string = '';
  0 0       0  
    0          
    0          
4754 0         0 while ($string !~ /\G \z/oxgc) {
4755 0         0 if ($string =~ /\G (\\\\) /oxgc) { $q_string .= $1; }
  0         0  
4756 0         0 elsif ($string =~ /\G (\\\') /oxgc) { $q_string .= $1; } # splitqr'' --> split qr''
4757             elsif ($string =~ /\G \' /oxgc) { $e_string .= e_split_q($e.q{ qr},"'","'",$q_string,''); next E_STRING_LOOP; } # ' ' --> qr ' '
4758 0         0 elsif ($string =~ /\G ($q_char) /oxgc) { $q_string .= $1; }
4759             }
4760             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4761             }
4762              
4763 0         0 # split ""
4764 0         0 elsif ($string =~ /\G (\") /oxgc) {
4765 0 0       0 my $qq_string = '';
  0 0       0  
    0          
    0          
4766 0         0 while ($string !~ /\G \z/oxgc) {
4767 0         0 if ($string =~ /\G (\\\\) /oxgc) { $qq_string .= $1; }
  0         0  
4768 0         0 elsif ($string =~ /\G (\\\") /oxgc) { $qq_string .= $1; } # splitqr"" --> split qr""
4769             elsif ($string =~ /\G \" /oxgc) { $e_string .= e_split($e.q{ qr},'"','"',$qq_string,''); next E_STRING_LOOP; } # " " --> qr " "
4770 0         0 elsif ($string =~ /\G ($q_char) /oxgc) { $qq_string .= $1; }
4771             }
4772             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4773             }
4774              
4775 0         0 # split //
4776 0         0 elsif ($string =~ /\G (\/) /oxgc) {
4777 0 0       0 my $regexp = '';
  0 0       0  
    0          
    0          
4778 0         0 while ($string !~ /\G \z/oxgc) {
4779 0         0 if ($string =~ /\G (\\\\) /oxgc) { $regexp .= $1; }
  0         0  
4780 0         0 elsif ($string =~ /\G (\\\/) /oxgc) { $regexp .= $1; } # splitqr// --> split qr//
4781             elsif ($string =~ /\G \/ ([cgimosxpadlunbB]*) /oxgc) { $e_string .= e_split($e.q{ qr}, '/','/',$regexp,$1); next E_STRING_LOOP; } # / / --> qr / /
4782 0         0 elsif ($string =~ /\G ($q_char) /oxgc) { $regexp .= $1; }
4783             }
4784             die __FILE__, ": Search pattern not terminated\n";
4785             }
4786             }
4787              
4788 0         0 # qq//
4789 0 0       0 elsif ($string =~ /\G \b (qq) \b /oxgc) {
4790 0         0 my $ope = $1;
4791             if ($string =~ /\G (\#) ((?:$qq_char)*?) (\#) /oxgc) { # qq# #
4792             $e_string .= e_qq($ope,$1,$3,$2);
4793 0         0 }
4794 0         0 else {
4795 0 0       0 my $e = '';
  0 0       0  
    0          
    0          
    0          
    0          
4796 0         0 while ($string !~ /\G \z/oxgc) {
  0         0  
4797 0         0 if ($string =~ /\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0         0  
4798 0         0 elsif ($string =~ /\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qq ( )
  0         0  
4799 0         0 elsif ($string =~ /\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qq { }
  0         0  
4800 0         0 elsif ($string =~ /\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qq [ ]
  0         0  
4801             elsif ($string =~ /\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qq < >
4802 0         0 elsif ($string =~ /\G (\S) ((?:$qq_char)*?) (\1) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qq * *
4803             }
4804             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4805             }
4806             }
4807              
4808 0         0 # qx//
4809 0 0       0 elsif ($string =~ /\G \b (qx) \b /oxgc) {
4810 0         0 my $ope = $1;
4811             if ($string =~ /\G (\#) ((?:$qq_char)*?) (\#) /oxgc) { # qx# #
4812             $e_string .= e_qq($ope,$1,$3,$2);
4813 0         0 }
4814 0         0 else {
4815 0 0       0 my $e = '';
  0 0       0  
    0          
    0          
    0          
    0          
    0          
4816 0         0 while ($string !~ /\G \z/oxgc) {
  0         0  
4817 0         0 if ($string =~ /\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0         0  
4818 0         0 elsif ($string =~ /\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qx ( )
  0         0  
4819 0         0 elsif ($string =~ /\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qx { }
  0         0  
4820 0         0 elsif ($string =~ /\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qx [ ]
  0         0  
4821 0         0 elsif ($string =~ /\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qx < >
  0         0  
4822             elsif ($string =~ /\G (\') ((?:$qq_char)*?) (\') /oxgc) { $e_string .= $e . e_q ($ope,$1,$3,$2); next E_STRING_LOOP; } # qx ' '
4823 0         0 elsif ($string =~ /\G (\S) ((?:$qq_char)*?) (\1) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qx * *
4824             }
4825             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4826             }
4827             }
4828              
4829 0         0 # q//
4830 0 0       0 elsif ($string =~ /\G \b (q) \b /oxgc) {
4831 0         0 my $ope = $1;
4832             if ($string =~ /\G (\#) ((?:\\\#|\\\\|$q_char)*?) (\#) /oxgc) { # q# #
4833             $e_string .= e_q($ope,$1,$3,$2);
4834 0         0 }
4835 0         0 else {
4836 0 0       0 my $e = '';
  0 0       0  
    0          
    0          
    0          
    0          
4837 0         0 while ($string !~ /\G \z/oxgc) {
  0         0  
4838 0         0 if ($string =~ /\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0         0  
4839 0         0 elsif ($string =~ /\G (\() ((?:\\\\|\\\)|\\\(|$q_paren)*?) (\)) /oxgc) { $e_string .= $e . e_q($ope,$1,$3,$2); next E_STRING_LOOP; } # q ( )
  0         0  
4840 0         0 elsif ($string =~ /\G (\{) ((?:\\\\|\\\}|\\\{|$q_brace)*?) (\}) /oxgc) { $e_string .= $e . e_q($ope,$1,$3,$2); next E_STRING_LOOP; } # q { }
  0         0  
4841 0         0 elsif ($string =~ /\G (\[) ((?:\\\\|\\\]|\\\[|$q_bracket)*?) (\]) /oxgc) { $e_string .= $e . e_q($ope,$1,$3,$2); next E_STRING_LOOP; } # q [ ]
  0         0  
4842             elsif ($string =~ /\G (\<) ((?:\\\\|\\\>|\\\<|$q_angle)*?) (\>) /oxgc) { $e_string .= $e . e_q($ope,$1,$3,$2); next E_STRING_LOOP; } # q < >
4843 0         0 elsif ($string =~ /\G (\S) ((?:\\\\|\\\1| $q_char)*?) (\1) /oxgc) { $e_string .= $e . e_q($ope,$1,$3,$2); next E_STRING_LOOP; } # q * *
4844             }
4845             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4846             }
4847             }
4848 0         0  
4849             # ''
4850             elsif ($string =~ /\G (?
4851 0         0  
4852             # ""
4853             elsif ($string =~ /\G (\") ((?:$qq_char)*?) (\") /oxgc) { $e_string .= e_qq('',$1,$3,$2); }
4854 0         0  
4855             # ``
4856             elsif ($string =~ /\G (\`) ((?:$qq_char)*?) (\`) /oxgc) { $e_string .= e_qq('',$1,$3,$2); }
4857 0         0  
4858             # <<>> (a safer ARGV)
4859             elsif ($string =~ /\G ( <<>> ) /oxgc) { $e_string .= $1; }
4860 0         0  
4861             # <<= <=> <= < operator
4862             elsif ($string =~ /\G ( <<= | <=> | <= | < ) (?= (?>\s*) [A-Za-z_0-9'"`\$\@\&\*\(\+\-] )/oxgc) { $e_string .= $1; }
4863 0         0  
4864             #
4865             elsif ($string =~ /\G (<[\$]?[A-Za-z_][A-Za-z_0-9]*>) /oxgc) { $e_string .= $1; }
4866              
4867 0         0 # --- glob
4868             elsif ($string =~ /\G < ((?:$q_char)+?) > /oxgc) {
4869             $e_string .= 'Elatin7::glob("' . $1 . '")';
4870             }
4871              
4872 0         0 # << (bit shift) --- not here document
4873 0         0 elsif ($string =~ /\G ( << (?>\s*) ) (?= [0-9\$\@\&] ) /oxgc) {
4874             $slash = 'm//';
4875             $e_string .= $1;
4876             }
4877              
4878 0         0 # <<~'HEREDOC'
4879 0         0 elsif ($string =~ /\G ( <<~ [\t ]* '([a-zA-Z_0-9]*)' ) /oxgc) {
4880 0         0 $slash = 'm//';
4881             my $here_quote = $1;
4882             my $delimiter = $2;
4883 0 0       0  
4884 0         0 # get here document
4885 0         0 if ($here_script eq '') {
4886             $here_script = CORE::substr $_, pos $_;
4887 0 0       0 $here_script =~ s/.*?\n//oxm;
4888 0         0 }
4889 0         0 if ($here_script =~ s/\A (.*?) \n ([\t ]*) $delimiter \n //xms) {
4890 0         0 my $heredoc = $1;
4891 0         0 my $indent = $2;
4892 0         0 $heredoc =~ s{^$indent}{}msg; # no /ox
4893             push @heredoc, $heredoc . qq{\n$delimiter\n};
4894             push @heredoc_delimiter, qq{\\s*$delimiter};
4895 0         0 }
4896             else {
4897 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4898             }
4899             $e_string .= qq{<<'$delimiter'};
4900             }
4901              
4902 0         0 # <<~\HEREDOC
4903 0         0 elsif ($string =~ /\G ( <<~ \\([a-zA-Z_0-9]+) ) /oxgc) {
4904 0         0 $slash = 'm//';
4905             my $here_quote = $1;
4906             my $delimiter = $2;
4907 0 0       0  
4908 0         0 # get here document
4909 0         0 if ($here_script eq '') {
4910             $here_script = CORE::substr $_, pos $_;
4911 0 0       0 $here_script =~ s/.*?\n//oxm;
4912 0         0 }
4913 0         0 if ($here_script =~ s/\A (.*?) \n ([\t ]*) $delimiter \n //xms) {
4914 0         0 my $heredoc = $1;
4915 0         0 my $indent = $2;
4916 0         0 $heredoc =~ s{^$indent}{}msg; # no /ox
4917             push @heredoc, $heredoc . qq{\n$delimiter\n};
4918             push @heredoc_delimiter, qq{\\s*$delimiter};
4919 0         0 }
4920             else {
4921 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4922             }
4923             $e_string .= qq{<<\\$delimiter};
4924             }
4925              
4926 0         0 # <<~"HEREDOC"
4927 0         0 elsif ($string =~ /\G ( <<~ [\t ]* "([a-zA-Z_0-9]*)" ) /oxgc) {
4928 0         0 $slash = 'm//';
4929             my $here_quote = $1;
4930             my $delimiter = $2;
4931 0 0       0  
4932 0         0 # get here document
4933 0         0 if ($here_script eq '') {
4934             $here_script = CORE::substr $_, pos $_;
4935 0 0       0 $here_script =~ s/.*?\n//oxm;
4936 0         0 }
4937 0         0 if ($here_script =~ s/\A (.*?) \n ([\t ]*) $delimiter \n //xms) {
4938 0         0 my $heredoc = $1;
4939 0         0 my $indent = $2;
4940 0         0 $heredoc =~ s{^$indent}{}msg; # no /ox
4941             push @heredoc, e_heredoc($heredoc) . qq{\n$delimiter\n};
4942             push @heredoc_delimiter, qq{\\s*$delimiter};
4943 0         0 }
4944             else {
4945 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4946             }
4947             $e_string .= qq{<<"$delimiter"};
4948             }
4949              
4950 0         0 # <<~HEREDOC
4951 0         0 elsif ($string =~ /\G ( <<~ ([a-zA-Z_0-9]+) ) /oxgc) {
4952 0         0 $slash = 'm//';
4953             my $here_quote = $1;
4954             my $delimiter = $2;
4955 0 0       0  
4956 0         0 # get here document
4957 0         0 if ($here_script eq '') {
4958             $here_script = CORE::substr $_, pos $_;
4959 0 0       0 $here_script =~ s/.*?\n//oxm;
4960 0         0 }
4961 0         0 if ($here_script =~ s/\A (.*?) \n ([\t ]*) $delimiter \n //xms) {
4962 0         0 my $heredoc = $1;
4963 0         0 my $indent = $2;
4964 0         0 $heredoc =~ s{^$indent}{}msg; # no /ox
4965             push @heredoc, e_heredoc($heredoc) . qq{\n$delimiter\n};
4966             push @heredoc_delimiter, qq{\\s*$delimiter};
4967 0         0 }
4968             else {
4969 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4970             }
4971             $e_string .= qq{<<$delimiter};
4972             }
4973              
4974 0         0 # <<~`HEREDOC`
4975 0         0 elsif ($string =~ /\G ( <<~ [\t ]* `([a-zA-Z_0-9]*)` ) /oxgc) {
4976 0         0 $slash = 'm//';
4977             my $here_quote = $1;
4978             my $delimiter = $2;
4979 0 0       0  
4980 0         0 # get here document
4981 0         0 if ($here_script eq '') {
4982             $here_script = CORE::substr $_, pos $_;
4983 0 0       0 $here_script =~ s/.*?\n//oxm;
4984 0         0 }
4985 0         0 if ($here_script =~ s/\A (.*?) \n ([\t ]*) $delimiter \n //xms) {
4986 0         0 my $heredoc = $1;
4987 0         0 my $indent = $2;
4988 0         0 $heredoc =~ s{^$indent}{}msg; # no /ox
4989             push @heredoc, e_heredoc($heredoc) . qq{\n$delimiter\n};
4990             push @heredoc_delimiter, qq{\\s*$delimiter};
4991 0         0 }
4992             else {
4993 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4994             }
4995             $e_string .= qq{<<`$delimiter`};
4996             }
4997              
4998 0         0 # <<'HEREDOC'
4999 0         0 elsif ($string =~ /\G ( << '([a-zA-Z_0-9]*)' ) /oxgc) {
5000 0         0 $slash = 'm//';
5001             my $here_quote = $1;
5002             my $delimiter = $2;
5003 0 0       0  
5004 0         0 # get here document
5005 0         0 if ($here_script eq '') {
5006             $here_script = CORE::substr $_, pos $_;
5007 0 0       0 $here_script =~ s/.*?\n//oxm;
5008 0         0 }
5009 0         0 if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
5010             push @heredoc, $1 . qq{\n$delimiter\n};
5011             push @heredoc_delimiter, $delimiter;
5012 0         0 }
5013             else {
5014 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
5015             }
5016             $e_string .= $here_quote;
5017             }
5018              
5019 0         0 # <<\HEREDOC
5020 0         0 elsif ($string =~ /\G ( << \\([a-zA-Z_0-9]+) ) /oxgc) {
5021 0         0 $slash = 'm//';
5022             my $here_quote = $1;
5023             my $delimiter = $2;
5024 0 0       0  
5025 0         0 # get here document
5026 0         0 if ($here_script eq '') {
5027             $here_script = CORE::substr $_, pos $_;
5028 0 0       0 $here_script =~ s/.*?\n//oxm;
5029 0         0 }
5030 0         0 if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
5031             push @heredoc, $1 . qq{\n$delimiter\n};
5032             push @heredoc_delimiter, $delimiter;
5033 0         0 }
5034             else {
5035 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
5036             }
5037             $e_string .= $here_quote;
5038             }
5039              
5040 0         0 # <<"HEREDOC"
5041 0         0 elsif ($string =~ /\G ( << "([a-zA-Z_0-9]*)" ) /oxgc) {
5042 0         0 $slash = 'm//';
5043             my $here_quote = $1;
5044             my $delimiter = $2;
5045 0 0       0  
5046 0         0 # get here document
5047 0         0 if ($here_script eq '') {
5048             $here_script = CORE::substr $_, pos $_;
5049 0 0       0 $here_script =~ s/.*?\n//oxm;
5050 0         0 }
5051 0         0 if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
5052             push @heredoc, e_heredoc($1) . qq{\n$delimiter\n};
5053             push @heredoc_delimiter, $delimiter;
5054 0         0 }
5055             else {
5056 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
5057             }
5058             $e_string .= $here_quote;
5059             }
5060              
5061 0         0 # <
5062 0         0 elsif ($string =~ /\G ( << ([a-zA-Z_0-9]+) ) /oxgc) {
5063 0         0 $slash = 'm//';
5064             my $here_quote = $1;
5065             my $delimiter = $2;
5066 0 0       0  
5067 0         0 # get here document
5068 0         0 if ($here_script eq '') {
5069             $here_script = CORE::substr $_, pos $_;
5070 0 0       0 $here_script =~ s/.*?\n//oxm;
5071 0         0 }
5072 0         0 if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
5073             push @heredoc, e_heredoc($1) . qq{\n$delimiter\n};
5074             push @heredoc_delimiter, $delimiter;
5075 0         0 }
5076             else {
5077 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
5078             }
5079             $e_string .= $here_quote;
5080             }
5081              
5082 0         0 # <<`HEREDOC`
5083 0         0 elsif ($string =~ /\G ( << `([a-zA-Z_0-9]*)` ) /oxgc) {
5084 0         0 $slash = 'm//';
5085             my $here_quote = $1;
5086             my $delimiter = $2;
5087 0 0       0  
5088 0         0 # get here document
5089 0         0 if ($here_script eq '') {
5090             $here_script = CORE::substr $_, pos $_;
5091 0 0       0 $here_script =~ s/.*?\n//oxm;
5092 0         0 }
5093 0         0 if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
5094             push @heredoc, e_heredoc($1) . qq{\n$delimiter\n};
5095             push @heredoc_delimiter, $delimiter;
5096 0         0 }
5097             else {
5098 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
5099             }
5100             $e_string .= $here_quote;
5101             }
5102              
5103             # any operator before div
5104             elsif ($string =~ /\G (
5105             -- | \+\+ |
5106 0         0 [\)\}\]]
  18         31  
5107              
5108             ) /oxgc) { $slash = 'div'; $e_string .= $1; }
5109              
5110             # yada-yada or triple-dot operator
5111             elsif ($string =~ /\G (
5112 18         58 \.\.\.
  0         0  
5113              
5114             ) /oxgc) { $slash = 'm//'; $e_string .= q{die('Unimplemented')}; }
5115              
5116             # any operator before m//
5117             elsif ($string =~ /\G ((?>
5118              
5119             !~~ | !~ | != | ! |
5120             %= | % |
5121             &&= | && | &= | &\.= | &\. | & |
5122             -= | -> | - |
5123             :(?>\s*)= |
5124             : |
5125             <<>> |
5126             <<= | <=> | <= | < |
5127             == | => | =~ | = |
5128             >>= | >> | >= | > |
5129             \*\*= | \*\* | \*= | \* |
5130             \+= | \+ |
5131             \.\. | \.= | \. |
5132             \/\/= | \/\/ |
5133             \/= | \/ |
5134             \? |
5135             \\ |
5136             \^= | \^\.= | \^\. | \^ |
5137             \b x= |
5138             \|\|= | \|\| | \|= | \|\.= | \|\. | \| |
5139             ~~ | ~\. | ~ |
5140             \b(?: and | cmp | eq | ge | gt | le | lt | ne | not | or | xor | x )\b |
5141             \b(?: print )\b |
5142              
5143 0         0 [,;\(\{\[]
  31         69  
5144              
5145             )) /oxgc) { $slash = 'm//'; $e_string .= $1; }
5146 31         111  
5147             # other any character
5148             elsif ($string =~ /\G ($q_char) /oxgc) { $e_string .= $1; }
5149              
5150 131         353 # system error
5151             else {
5152             die __FILE__, ": Oops, this shouldn't happen!\n";
5153             }
5154 0         0 }
5155              
5156             return $e_string;
5157             }
5158              
5159             #
5160             # character class
5161 17     1919 0 72 #
5162             sub character_class {
5163 1919 100       3554 my($char,$modifier) = @_;
5164 1919 100       3016  
5165 52         108 if ($char eq '.') {
5166             if ($modifier =~ /s/) {
5167             return '${Elatin7::dot_s}';
5168 17         38 }
5169             else {
5170             return '${Elatin7::dot}';
5171             }
5172 35         72 }
5173             else {
5174             return Elatin7::classic_character_class($char);
5175             }
5176             }
5177              
5178             #
5179             # escape capture ($1, $2, $3, ...)
5180             #
5181 1867     212 0 3738 sub e_capture {
5182              
5183             return join '', '${', $_[0], '}';
5184             }
5185              
5186             #
5187             # escape transliteration (tr/// or y///)
5188 212     3 0 835 #
5189 3         15 sub e_tr {
5190 3   50     7 my($variable,$charclass,$e,$charclass2,$modifier) = @_;
5191             my $e_tr = '';
5192 3         6 $modifier ||= '';
5193              
5194             $slash = 'div';
5195 3         3  
5196             # quote character class 1
5197             $charclass = q_tr($charclass);
5198 3         7  
5199             # quote character class 2
5200             $charclass2 = q_tr($charclass2);
5201 3 50       10  
5202 3 0       7 # /b /B modifier
5203 0         0 if ($modifier =~ tr/bB//d) {
5204             if ($variable eq '') {
5205             $e_tr = qq{tr$charclass$e$charclass2$modifier};
5206 0         0 }
5207             else {
5208             $e_tr = qq{$variable${bind_operator}tr$charclass$e$charclass2$modifier};
5209             }
5210 0 100       0 }
5211 3         7 else {
5212             if ($variable eq '') {
5213             $e_tr = qq{Elatin7::tr(\$_,' =~ ',$charclass,$e$charclass2,'$modifier')};
5214 2         7 }
5215             else {
5216             $e_tr = qq{Elatin7::tr($variable,'$bind_operator',$charclass,$e$charclass2,'$modifier')};
5217             }
5218             }
5219 1         4  
5220 3         5 # clear tr/// variable
5221             $tr_variable = '';
5222 3         4 $bind_operator = '';
5223              
5224             return $e_tr;
5225             }
5226              
5227             #
5228             # quote for escape transliteration (tr/// or y///)
5229 3     6 0 15 #
5230             sub q_tr {
5231             my($charclass) = @_;
5232 6 50       8  
    0          
    0          
    0          
    0          
    0          
5233 6         13 # quote character class
5234             if ($charclass !~ /'/oxms) {
5235             return e_q('', "'", "'", $charclass); # --> q' '
5236 6         11 }
5237             elsif ($charclass !~ /\//oxms) {
5238             return e_q('q', '/', '/', $charclass); # --> q/ /
5239 0         0 }
5240             elsif ($charclass !~ /\#/oxms) {
5241             return e_q('q', '#', '#', $charclass); # --> q# #
5242 0         0 }
5243             elsif ($charclass !~ /[\<\>]/oxms) {
5244             return e_q('q', '<', '>', $charclass); # --> q< >
5245 0         0 }
5246             elsif ($charclass !~ /[\(\)]/oxms) {
5247             return e_q('q', '(', ')', $charclass); # --> q( )
5248 0         0 }
5249             elsif ($charclass !~ /[\{\}]/oxms) {
5250             return e_q('q', '{', '}', $charclass); # --> q{ }
5251 0         0 }
5252 0 0       0 else {
5253 0         0 for my $char (qw( ! " $ % & * + . : = ? @ ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
5254             if ($charclass !~ /\Q$char\E/xms) {
5255             return e_q('q', $char, $char, $charclass);
5256             }
5257             }
5258 0         0 }
5259              
5260             return e_q('q', '{', '}', $charclass);
5261             }
5262              
5263             #
5264             # escape q string (q//, '')
5265 0     1264 0 0 #
5266             sub e_q {
5267 1264         3221 my($ope,$delimiter,$end_delimiter,$string) = @_;
5268              
5269 1264         1812 $slash = 'div';
5270              
5271             return join '', $ope, $delimiter, $string, $end_delimiter;
5272             }
5273              
5274             #
5275             # escape qq string (qq//, "", qx//, ``)
5276 1264     4044 0 6566 #
5277             sub e_qq {
5278 4044         11016 my($ope,$delimiter,$end_delimiter,$string) = @_;
5279              
5280 4044         8847 $slash = 'div';
5281 4044         5289  
5282             my $left_e = 0;
5283             my $right_e = 0;
5284 4044         5296  
5285             # split regexp
5286             my @char = $string =~ /\G((?>
5287             [^\\\$] |
5288             \\x\{ (?>[0-9A-Fa-f]+) \} |
5289             \\o\{ (?>[0-7]+) \} |
5290             \\N\{ (?>[^0-9\}][^\}]*) \} |
5291             \\ $q_char |
5292             \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} |
5293             \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} |
5294             \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} |
5295             \$ (?>\s* [0-9]+) |
5296             \$ (?>\s*) \{ (?>\s* [0-9]+ \s*) \} |
5297             \$ \$ (?![\w\{]) |
5298             \$ (?>\s*) \$ (?>\s*) $qq_variable |
5299             $q_char
5300 4044         141654 ))/oxmsg;
5301              
5302             for (my $i=0; $i <= $#char; $i++) {
5303 4044 50 33     12531  
    50 33        
    100          
    100          
    50          
5304 113775         448546 # "\L\u" --> "\u\L"
5305             if (($char[$i] eq '\L') and ($char[$i+1] eq '\u')) {
5306             @char[$i,$i+1] = @char[$i+1,$i];
5307             }
5308              
5309 0         0 # "\U\l" --> "\l\U"
5310             elsif (($char[$i] eq '\U') and ($char[$i+1] eq '\l')) {
5311             @char[$i,$i+1] = @char[$i+1,$i];
5312             }
5313              
5314 0         0 # octal escape sequence
5315             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
5316             $char[$i] = Elatin7::octchr($1);
5317             }
5318              
5319 1         4 # hexadecimal escape sequence
5320             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
5321             $char[$i] = Elatin7::hexchr($1);
5322             }
5323              
5324 1         4 # \N{CHARNAME} --> N{CHARNAME}
5325             elsif ($char[$i] =~ /\A \\ ( N\{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
5326             $char[$i] = $1;
5327 0 100       0 }
    50          
    50          
    50          
    50          
    100          
    50          
    100          
    50          
    50          
    100          
    50          
    50          
    100          
    50          
    50          
    50          
    50          
    100          
    100          
    100          
    50          
    50          
5328              
5329             if (0) {
5330             }
5331              
5332             # \F
5333             #
5334             # P.69 Table 2-6. Translation escapes
5335             # in Chapter 2: Bits and Pieces
5336             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
5337             # (and so on)
5338 113775         1102078  
5339 0 50       0 # \u \l \U \L \F \Q \E
5340 484         1222 elsif ($char[$i] =~ /\A ([<>]) \z/oxms) {
5341             if ($right_e < $left_e) {
5342             $char[$i] = '\\' . $char[$i];
5343             }
5344             }
5345             elsif ($char[$i] eq '\u') {
5346              
5347             # "STRING @{[ LIST EXPR ]} MORE STRING"
5348              
5349             # P.257 Other Tricks You Can Do with Hard References
5350             # in Chapter 8: References
5351             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
5352              
5353             # P.353 Other Tricks You Can Do with Hard References
5354             # in Chapter 8: References
5355             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
5356              
5357 0         0 # (and so on)
5358 0         0  
5359             $char[$i] = '@{[Elatin7::ucfirst qq<';
5360             $left_e++;
5361 0         0 }
5362 0         0 elsif ($char[$i] eq '\l') {
5363             $char[$i] = '@{[Elatin7::lcfirst qq<';
5364             $left_e++;
5365 0         0 }
5366 0         0 elsif ($char[$i] eq '\U') {
5367             $char[$i] = '@{[Elatin7::uc qq<';
5368             $left_e++;
5369 0         0 }
5370 0         0 elsif ($char[$i] eq '\L') {
5371             $char[$i] = '@{[Elatin7::lc qq<';
5372             $left_e++;
5373 0         0 }
5374 24         867 elsif ($char[$i] eq '\F') {
5375             $char[$i] = '@{[Elatin7::fc qq<';
5376             $left_e++;
5377 24         53 }
5378 0         0 elsif ($char[$i] eq '\Q') {
5379             $char[$i] = '@{[CORE::quotemeta qq<';
5380             $left_e++;
5381 0 50       0 }
5382 24         75 elsif ($char[$i] eq '\E') {
5383 24         34 if ($right_e < $left_e) {
5384             $char[$i] = '>]}';
5385             $right_e++;
5386 24         372 }
5387             else {
5388             $char[$i] = '';
5389             }
5390 0         0 }
5391 0 0       0 elsif ($char[$i] eq '\Q') {
5392 0         0 while (1) {
5393             if (++$i > $#char) {
5394 0 0       0 last;
5395 0         0 }
5396             if ($char[$i] eq '\E') {
5397             last;
5398             }
5399             }
5400             }
5401             elsif ($char[$i] eq '\E') {
5402             }
5403              
5404             # $0 --> $0
5405             elsif ($char[$i] =~ /\A \$ 0 \z/oxms) {
5406             }
5407             elsif ($char[$i] =~ /\A \$ \{ (?>\s*) 0 (?>\s*) \} \z/oxms) {
5408             }
5409              
5410             # $$ --> $$
5411             elsif ($char[$i] =~ /\A \$\$ \z/oxms) {
5412             }
5413              
5414             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
5415 0         0 # $1, $2, $3 --> $1, $2, $3 otherwise
5416             elsif ($char[$i] =~ /\A \$ ((?>[1-9][0-9]*)) \z/oxms) {
5417             $char[$i] = e_capture($1);
5418 205         412 }
5419             elsif ($char[$i] =~ /\A \$ \{ (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} \z/oxms) {
5420             $char[$i] = e_capture($1);
5421             }
5422              
5423 0         0 # $$foo[ ... ] --> $ $foo->[ ... ]
5424             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \[ (?:$qq_bracket)*? \] ) \z/oxms) {
5425             $char[$i] = e_capture($1.'->'.$2);
5426             }
5427              
5428 0         0 # $$foo{ ... } --> $ $foo->{ ... }
5429             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \{ (?:$qq_brace)*? \} ) \z/oxms) {
5430             $char[$i] = e_capture($1.'->'.$2);
5431             }
5432              
5433 0         0 # $$foo
5434             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) \z/oxms) {
5435             $char[$i] = e_capture($1);
5436             }
5437              
5438 0         0 # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Elatin7::PREMATCH()
5439             elsif ($char[$i] =~ /\A ( \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} ) \z/oxmsgc) {
5440             $char[$i] = '@{[Elatin7::PREMATCH()]}';
5441             }
5442              
5443 44         120 # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Elatin7::MATCH()
5444             elsif ($char[$i] =~ /\A ( \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} ) \z/oxmsgc) {
5445             $char[$i] = '@{[Elatin7::MATCH()]}';
5446             }
5447              
5448 45         126 # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Elatin7::POSTMATCH()
5449             elsif ($char[$i] =~ /\A ( \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} ) \z/oxmsgc) {
5450             $char[$i] = '@{[Elatin7::POSTMATCH()]}';
5451             }
5452              
5453             # ${ foo } --> ${ foo }
5454             elsif ($char[$i] =~ /\A \$ (?>\s*) \{ (?> \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* ) \} \z/oxms) {
5455             }
5456              
5457 33         89 # ${ ... }
5458             elsif ($char[$i] =~ /\A \$ (?>\s*) \{ ( .+ ) \} \z/oxms) {
5459             $char[$i] = e_capture($1);
5460             }
5461             }
5462 0 50       0  
5463 4044         8372 # return string
5464             if ($left_e > $right_e) {
5465 0         0 return join '', $ope, $delimiter, @char, '>]}' x ($left_e - $right_e), $end_delimiter;
5466             }
5467             return join '', $ope, $delimiter, @char, $end_delimiter;
5468             }
5469              
5470             #
5471             # escape qw string (qw//)
5472 4044     16 0 43655 #
5473             sub e_qw {
5474 16         74 my($ope,$delimiter,$end_delimiter,$string) = @_;
5475              
5476             $slash = 'div';
5477 16         32  
  16         220  
5478 483 50       790 # choice again delimiter
    0          
    0          
    0          
    0          
5479 16         98 my %octet = map {$_ => 1} ($string =~ /\G ([\x00-\xFF]) /oxmsg);
5480             if (not $octet{$end_delimiter}) {
5481             return join '', $ope, $delimiter, $string, $end_delimiter;
5482 16         149 }
5483             elsif (not $octet{')'}) {
5484             return join '', $ope, '(', $string, ')';
5485 0         0 }
5486             elsif (not $octet{'}'}) {
5487             return join '', $ope, '{', $string, '}';
5488 0         0 }
5489             elsif (not $octet{']'}) {
5490             return join '', $ope, '[', $string, ']';
5491 0         0 }
5492             elsif (not $octet{'>'}) {
5493             return join '', $ope, '<', $string, '>';
5494 0         0 }
5495 0 0       0 else {
5496 0         0 for my $char (qw( ! " $ % & * + - . / : = ? @ ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
5497             if (not $octet{$char}) {
5498             return join '', $ope, $char, $string, $char;
5499             }
5500             }
5501             }
5502 0         0  
5503 0         0 # qw/AAA BBB C'CC/ --> ('AAA', 'BBB', 'C\'CC')
5504 0         0 my @string = CORE::split(/\s+/, $string);
5505 0         0 for my $string (@string) {
5506 0 0       0 my @octet = $string =~ /\G ([\x00-\xFF]) /oxmsg;
5507 0         0 for my $octet (@octet) {
5508             if ($octet =~ /\A (['\\]) \z/oxms) {
5509             $octet = '\\' . $1;
5510 0         0 }
5511             }
5512 0         0 $string = join '', @octet;
  0         0  
5513             }
5514             return join '', '(', (join ', ', map { "'$_'" } @string), ')';
5515             }
5516              
5517             #
5518             # escape here document (<<"HEREDOC", <
5519 0     93 0 0 #
5520             sub e_heredoc {
5521 93         334 my($string) = @_;
5522              
5523 93         157 $slash = 'm//';
5524              
5525 93         331 my $metachar = qr/[\@\\|]/oxms; # '|' is for <<`HEREDOC`
5526 93         150  
5527             my $left_e = 0;
5528             my $right_e = 0;
5529 93         118  
5530             # split regexp
5531             my @char = $string =~ /\G((?>
5532             [^\\\$] |
5533             \\x\{ (?>[0-9A-Fa-f]+) \} |
5534             \\o\{ (?>[0-7]+) \} |
5535             \\N\{ (?>[^0-9\}][^\}]*) \} |
5536             \\ $q_char |
5537             \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} |
5538             \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} |
5539             \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} |
5540             \$ (?>\s* [0-9]+) |
5541             \$ (?>\s*) \{ (?>\s* [0-9]+ \s*) \} |
5542             \$ \$ (?![\w\{]) |
5543             \$ (?>\s*) \$ (?>\s*) $qq_variable |
5544             $q_char
5545 93         8037 ))/oxmsg;
5546              
5547             for (my $i=0; $i <= $#char; $i++) {
5548 93 50 33     550  
    50 33        
    100          
    100          
    50          
5549 3177         9951 # "\L\u" --> "\u\L"
5550             if (($char[$i] eq '\L') and ($char[$i+1] eq '\u')) {
5551             @char[$i,$i+1] = @char[$i+1,$i];
5552             }
5553              
5554 0         0 # "\U\l" --> "\l\U"
5555             elsif (($char[$i] eq '\U') and ($char[$i+1] eq '\l')) {
5556             @char[$i,$i+1] = @char[$i+1,$i];
5557             }
5558              
5559 0         0 # octal escape sequence
5560             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
5561             $char[$i] = Elatin7::octchr($1);
5562             }
5563              
5564 1         3 # hexadecimal escape sequence
5565             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
5566             $char[$i] = Elatin7::hexchr($1);
5567             }
5568              
5569 1         2 # \N{CHARNAME} --> N{CHARNAME}
5570             elsif ($char[$i] =~ /\A \\ ( N\{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
5571             $char[$i] = $1;
5572 0 50       0 }
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    100          
    100          
    100          
    50          
    50          
5573              
5574             if (0) {
5575             }
5576 3177         26854  
5577 0 0       0 # \u \l \U \L \F \Q \E
5578 0         0 elsif ($char[$i] =~ /\A ([<>]) \z/oxms) {
5579             if ($right_e < $left_e) {
5580             $char[$i] = '\\' . $char[$i];
5581             }
5582 0         0 }
5583 0         0 elsif ($char[$i] eq '\u') {
5584             $char[$i] = '@{[Elatin7::ucfirst qq<';
5585             $left_e++;
5586 0         0 }
5587 0         0 elsif ($char[$i] eq '\l') {
5588             $char[$i] = '@{[Elatin7::lcfirst qq<';
5589             $left_e++;
5590 0         0 }
5591 0         0 elsif ($char[$i] eq '\U') {
5592             $char[$i] = '@{[Elatin7::uc qq<';
5593             $left_e++;
5594 0         0 }
5595 0         0 elsif ($char[$i] eq '\L') {
5596             $char[$i] = '@{[Elatin7::lc qq<';
5597             $left_e++;
5598 0         0 }
5599 0         0 elsif ($char[$i] eq '\F') {
5600             $char[$i] = '@{[Elatin7::fc qq<';
5601             $left_e++;
5602 0         0 }
5603 0         0 elsif ($char[$i] eq '\Q') {
5604             $char[$i] = '@{[CORE::quotemeta qq<';
5605             $left_e++;
5606 0 0       0 }
5607 0         0 elsif ($char[$i] eq '\E') {
5608 0         0 if ($right_e < $left_e) {
5609             $char[$i] = '>]}';
5610             $right_e++;
5611 0         0 }
5612             else {
5613             $char[$i] = '';
5614             }
5615 0         0 }
5616 0 0       0 elsif ($char[$i] eq '\Q') {
5617 0         0 while (1) {
5618             if (++$i > $#char) {
5619 0 0       0 last;
5620 0         0 }
5621             if ($char[$i] eq '\E') {
5622             last;
5623             }
5624             }
5625             }
5626             elsif ($char[$i] eq '\E') {
5627             }
5628              
5629             # $0 --> $0
5630             elsif ($char[$i] =~ /\A \$ 0 \z/oxms) {
5631             }
5632             elsif ($char[$i] =~ /\A \$ \{ (?>\s*) 0 (?>\s*) \} \z/oxms) {
5633             }
5634              
5635             # $$ --> $$
5636             elsif ($char[$i] =~ /\A \$\$ \z/oxms) {
5637             }
5638              
5639             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
5640 0         0 # $1, $2, $3 --> $1, $2, $3 otherwise
5641             elsif ($char[$i] =~ /\A \$ ((?>[1-9][0-9]*)) \z/oxms) {
5642             $char[$i] = e_capture($1);
5643 0         0 }
5644             elsif ($char[$i] =~ /\A \$ \{ (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} \z/oxms) {
5645             $char[$i] = e_capture($1);
5646             }
5647              
5648 0         0 # $$foo[ ... ] --> $ $foo->[ ... ]
5649             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \[ (?:$qq_bracket)*? \] ) \z/oxms) {
5650             $char[$i] = e_capture($1.'->'.$2);
5651             }
5652              
5653 0         0 # $$foo{ ... } --> $ $foo->{ ... }
5654             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \{ (?:$qq_brace)*? \} ) \z/oxms) {
5655             $char[$i] = e_capture($1.'->'.$2);
5656             }
5657              
5658 0         0 # $$foo
5659             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) \z/oxms) {
5660             $char[$i] = e_capture($1);
5661             }
5662              
5663 0         0 # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Elatin7::PREMATCH()
5664             elsif ($char[$i] =~ /\A ( \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} ) \z/oxmsgc) {
5665             $char[$i] = '@{[Elatin7::PREMATCH()]}';
5666             }
5667              
5668 8         46 # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Elatin7::MATCH()
5669             elsif ($char[$i] =~ /\A ( \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} ) \z/oxmsgc) {
5670             $char[$i] = '@{[Elatin7::MATCH()]}';
5671             }
5672              
5673 8         62 # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Elatin7::POSTMATCH()
5674             elsif ($char[$i] =~ /\A ( \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} ) \z/oxmsgc) {
5675             $char[$i] = '@{[Elatin7::POSTMATCH()]}';
5676             }
5677              
5678             # ${ foo } --> ${ foo }
5679             elsif ($char[$i] =~ /\A \$ (?>\s*) \{ (?> \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* ) \} \z/oxms) {
5680             }
5681              
5682 6         41 # ${ ... }
5683             elsif ($char[$i] =~ /\A \$ (?>\s*) \{ ( .+ ) \} \z/oxms) {
5684             $char[$i] = e_capture($1);
5685             }
5686             }
5687 0 50       0  
5688 93         287 # return string
5689             if ($left_e > $right_e) {
5690 0         0 return join '', @char, '>]}' x ($left_e - $right_e);
5691             }
5692             return join '', @char;
5693             }
5694              
5695             #
5696             # escape regexp (m//, qr//)
5697 93     652 0 765 #
5698 652   100     2952 sub e_qr {
5699             my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
5700 652         3854 $modifier ||= '';
5701 652 50       1280  
5702 652         1720 $modifier =~ tr/p//d;
5703 0         0 if ($modifier =~ /([adlu])/oxms) {
5704 0 0       0 my $line = 0;
5705 0         0 for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
5706 0         0 if ($filename ne __FILE__) {
5707             $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
5708             last;
5709 0         0 }
5710             }
5711             die qq{Unsupported modifier "$1" used at line $line.\n};
5712 0         0 }
5713              
5714             $slash = 'div';
5715 652 100       1468  
    100          
5716 652         2289 # literal null string pattern
5717 8         11 if ($string eq '') {
5718 8         13 $modifier =~ tr/bB//d;
5719             $modifier =~ tr/i//d;
5720             return join '', $ope, $delimiter, $end_delimiter, $modifier;
5721             }
5722              
5723             # /b /B modifier
5724             elsif ($modifier =~ tr/bB//d) {
5725 8 50       41  
5726 2         6 # choice again delimiter
5727 0         0 if ($delimiter =~ / [\@:] /oxms) {
  0         0  
5728 0 0       0 my @char = $string =~ /\G ([\x00-\xFF]) /oxmsg;
    0          
    0          
    0          
5729 0         0 my %octet = map {$_ => 1} @char;
5730 0         0 if (not $octet{')'}) {
5731             $delimiter = '(';
5732             $end_delimiter = ')';
5733 0         0 }
5734 0         0 elsif (not $octet{'}'}) {
5735             $delimiter = '{';
5736             $end_delimiter = '}';
5737 0         0 }
5738 0         0 elsif (not $octet{']'}) {
5739             $delimiter = '[';
5740             $end_delimiter = ']';
5741 0         0 }
5742 0         0 elsif (not $octet{'>'}) {
5743             $delimiter = '<';
5744             $end_delimiter = '>';
5745 0         0 }
5746 0 0       0 else {
5747 0         0 for my $char (qw( ! " $ % & * + - . / = ? ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
5748 0         0 if (not $octet{$char}) {
5749 0         0 $delimiter = $char;
5750             $end_delimiter = $char;
5751             last;
5752             }
5753             }
5754             }
5755 0 50 33     0 }
5756 2         10  
5757             if (($ope =~ /\A m? \z/oxms) and ($delimiter eq '?')) {
5758             return join '', $ope, $delimiter, $string, $matched, $end_delimiter, $modifier;
5759 0         0 }
5760             else {
5761             return join '', $ope, $delimiter, '(?:', $string, ')', $matched, $end_delimiter, $modifier;
5762             }
5763 2 100       10 }
5764 642         1558  
5765             my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
5766             my $metachar = qr/[\@\\|[\]{^]/oxms;
5767 642         3131  
5768             # split regexp
5769             my @char = $string =~ /\G((?>
5770             [^\\\$\@\[\(] |
5771             \\x (?>[0-9A-Fa-f]{1,2}) |
5772             \\ (?>[0-7]{2,3}) |
5773             \\c [\x40-\x5F] |
5774             \\x\{ (?>[0-9A-Fa-f]+) \} |
5775             \\o\{ (?>[0-7]+) \} |
5776             \\[bBNpP]\{ (?>[^0-9\}][^\}]*) \} |
5777             \\ $q_char |
5778             \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} |
5779             \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} |
5780             \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} |
5781             [\$\@] $qq_variable |
5782             \$ (?>\s* [0-9]+) |
5783             \$ (?>\s*) \{ (?>\s* [0-9]+ \s*) \} |
5784             \$ \$ (?![\w\{]) |
5785             \$ (?>\s*) \$ (?>\s*) $qq_variable |
5786             \[\^ |
5787             \[\: (?>[a-z]+) :\] |
5788             \[\:\^ (?>[a-z]+) :\] |
5789             \(\? |
5790             $q_char
5791             ))/oxmsg;
5792 642 50       68004  
5793 642         3034 # choice again delimiter
  0         0  
5794 0 0       0 if ($delimiter =~ / [\@:] /oxms) {
    0          
    0          
    0          
5795 0         0 my %octet = map {$_ => 1} @char;
5796 0         0 if (not $octet{')'}) {
5797             $delimiter = '(';
5798             $end_delimiter = ')';
5799 0         0 }
5800 0         0 elsif (not $octet{'}'}) {
5801             $delimiter = '{';
5802             $end_delimiter = '}';
5803 0         0 }
5804 0         0 elsif (not $octet{']'}) {
5805             $delimiter = '[';
5806             $end_delimiter = ']';
5807 0         0 }
5808 0         0 elsif (not $octet{'>'}) {
5809             $delimiter = '<';
5810             $end_delimiter = '>';
5811 0         0 }
5812 0 0       0 else {
5813 0         0 for my $char (qw( ! " $ % & * + - . / = ? ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
5814 0         0 if (not $octet{$char}) {
5815 0         0 $delimiter = $char;
5816             $end_delimiter = $char;
5817             last;
5818             }
5819             }
5820             }
5821 0         0 }
5822 642         1088  
5823 642         890 my $left_e = 0;
5824             my $right_e = 0;
5825             for (my $i=0; $i <= $#char; $i++) {
5826 642 50 66     1735  
    50 66        
    100          
    100          
    100          
    100          
5827 1872         10571 # "\L\u" --> "\u\L"
5828             if (($char[$i] eq '\L') and ($char[$i+1] eq '\u')) {
5829             @char[$i,$i+1] = @char[$i+1,$i];
5830             }
5831              
5832 0         0 # "\U\l" --> "\l\U"
5833             elsif (($char[$i] eq '\U') and ($char[$i+1] eq '\l')) {
5834             @char[$i,$i+1] = @char[$i+1,$i];
5835             }
5836              
5837 0         0 # octal escape sequence
5838             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
5839             $char[$i] = Elatin7::octchr($1);
5840             }
5841              
5842 1         3 # hexadecimal escape sequence
5843             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
5844             $char[$i] = Elatin7::hexchr($1);
5845             }
5846              
5847             # \b{...} --> b\{...}
5848             # \B{...} --> B\{...}
5849             # \N{CHARNAME} --> N\{CHARNAME}
5850             # \p{PROPERTY} --> p\{PROPERTY}
5851 1         4 # \P{PROPERTY} --> P\{PROPERTY}
5852             elsif ($char[$i] =~ /\A \\ ([bBNpP]) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
5853             $char[$i] = $1 . '\\' . $2;
5854             }
5855              
5856 6         30 # \p, \P, \X --> p, P, X
5857             elsif ($char[$i] =~ /\A \\ ( [pPX] ) \z/oxms) {
5858             $char[$i] = $1;
5859 4 100 100     13 }
    100 100        
    100 100        
    100          
    100          
    100          
    50          
    50          
    100          
    100          
    100          
    100          
    100          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    100          
    100          
    100          
    50          
    50          
    100          
    100          
5860              
5861             if (0) {
5862             }
5863 1872         6172  
5864 0 50 33     0 # join separated multiple-octet
    50 33        
    50 33        
      33        
      66        
      33        
5865 6         82 elsif ($char[$i] =~ /\A (?: \\ [0-7]{2,3} | \\x [0-9A-Fa-f]{1,2}) \z/oxms) {
5866             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)) {
5867             $char[$i] .= join '', splice @char, $i+1, 3;
5868 0         0 }
5869             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)) {
5870             $char[$i] .= join '', splice @char, $i+1, 2;
5871 0         0 }
5872             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)) {
5873             $char[$i] .= join '', splice @char, $i+1, 1;
5874             }
5875             }
5876              
5877 0         0 # open character class [...]
5878             elsif ($char[$i] eq '[') {
5879             my $left = $i;
5880              
5881             # [] make die "Unmatched [] in regexp ...\n"
5882 328 100       461 # (and so on)
5883 328         808  
5884             if ($char[$i+1] eq ']') {
5885             $i++;
5886 3         6 }
5887 328 50       611  
5888 1379         1986 while (1) {
5889             if (++$i > $#char) {
5890 0 100       0 die __FILE__, ": Unmatched [] in regexp\n";
5891 1379         2017 }
5892             if ($char[$i] eq ']') {
5893             my $right = $i;
5894 328 100       420  
5895 328         1694 # [...]
  30         69  
5896             if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
5897             splice @char, $left, $right-$left+1, sprintf(q{@{[Elatin7::charlist_qr(%s,'%s')]}}, join(',', map {qq_stuff($delimiter,$end_delimiter,$_)} @char[$left+1..$right-1]), $modifier);
5898 90         145 }
5899             else {
5900             splice @char, $left, $right-$left+1, Elatin7::charlist_qr(@char[$left+1..$right-1], $modifier);
5901 298         1745 }
5902 328         567  
5903             $i = $left;
5904             last;
5905             }
5906             }
5907             }
5908              
5909 328         913 # open character class [^...]
5910             elsif ($char[$i] eq '[^') {
5911             my $left = $i;
5912              
5913             # [^] make die "Unmatched [] in regexp ...\n"
5914 74 100       100 # (and so on)
5915 74         169  
5916             if ($char[$i+1] eq ']') {
5917             $i++;
5918 4         6 }
5919 74 50       107  
5920 272         568 while (1) {
5921             if (++$i > $#char) {
5922 0 100       0 die __FILE__, ": Unmatched [] in regexp\n";
5923 272         2271 }
5924             if ($char[$i] eq ']') {
5925             my $right = $i;
5926 74 100       103  
5927 74         595 # [^...]
  30         79  
5928             if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
5929             splice @char, $left, $right-$left+1, sprintf(q{@{[Elatin7::charlist_not_qr(%s,'%s')]}}, join(',', map {qq_stuff($delimiter,$end_delimiter,$_)} @char[$left+1..$right-1]), $modifier);
5930 90         158 }
5931             else {
5932             splice @char, $left, $right-$left+1, Elatin7::charlist_not_qr(@char[$left+1..$right-1], $modifier);
5933 44         191 }
5934 74         144  
5935             $i = $left;
5936             last;
5937             }
5938             }
5939             }
5940              
5941 74         718 # rewrite character class or escape character
5942             elsif (my $char = character_class($char[$i],$modifier)) {
5943             $char[$i] = $char;
5944             }
5945              
5946 139 50       355 # /i modifier
5947 20         33 elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Elatin7::uc($char[$i]) ne Elatin7::fc($char[$i]))) {
5948             if (CORE::length(Elatin7::fc($char[$i])) == 1) {
5949             $char[$i] = '[' . Elatin7::uc($char[$i]) . Elatin7::fc($char[$i]) . ']';
5950 20         41 }
5951             else {
5952             $char[$i] = '(?:' . Elatin7::uc($char[$i]) . '|' . Elatin7::fc($char[$i]) . ')';
5953             }
5954             }
5955              
5956 0 50       0 # \u \l \U \L \F \Q \E
5957 1         4 elsif ($char[$i] =~ /\A [<>] \z/oxms) {
5958             if ($right_e < $left_e) {
5959             $char[$i] = '\\' . $char[$i];
5960             }
5961 0         0 }
5962 0         0 elsif ($char[$i] eq '\u') {
5963             $char[$i] = '@{[Elatin7::ucfirst qq<';
5964             $left_e++;
5965 0         0 }
5966 0         0 elsif ($char[$i] eq '\l') {
5967             $char[$i] = '@{[Elatin7::lcfirst qq<';
5968             $left_e++;
5969 0         0 }
5970 1         3 elsif ($char[$i] eq '\U') {
5971             $char[$i] = '@{[Elatin7::uc qq<';
5972             $left_e++;
5973 1         4 }
5974 1         2 elsif ($char[$i] eq '\L') {
5975             $char[$i] = '@{[Elatin7::lc qq<';
5976             $left_e++;
5977 1         3 }
5978 18         41 elsif ($char[$i] eq '\F') {
5979             $char[$i] = '@{[Elatin7::fc qq<';
5980             $left_e++;
5981 18         46 }
5982 1         2 elsif ($char[$i] eq '\Q') {
5983             $char[$i] = '@{[CORE::quotemeta qq<';
5984             $left_e++;
5985 1 50       4 }
5986 21         58 elsif ($char[$i] eq '\E') {
5987 21         35 if ($right_e < $left_e) {
5988             $char[$i] = '>]}';
5989             $right_e++;
5990 21         49 }
5991             else {
5992             $char[$i] = '';
5993             }
5994 0         0 }
5995 0 0       0 elsif ($char[$i] eq '\Q') {
5996 0         0 while (1) {
5997             if (++$i > $#char) {
5998 0 0       0 last;
5999 0         0 }
6000             if ($char[$i] eq '\E') {
6001             last;
6002             }
6003             }
6004             }
6005             elsif ($char[$i] eq '\E') {
6006             }
6007              
6008 0 0       0 # $0 --> $0
6009 0         0 elsif ($char[$i] =~ /\A \$ 0 \z/oxms) {
6010             if ($ignorecase) {
6011             $char[$i] = '@{[Elatin7::ignorecase(' . $char[$i] . ')]}';
6012             }
6013 0 0       0 }
6014 0         0 elsif ($char[$i] =~ /\A \$ \{ (?>\s*) 0 (?>\s*) \} \z/oxms) {
6015             if ($ignorecase) {
6016             $char[$i] = '@{[Elatin7::ignorecase(' . $char[$i] . ')]}';
6017             }
6018             }
6019              
6020             # $$ --> $$
6021             elsif ($char[$i] =~ /\A \$\$ \z/oxms) {
6022             }
6023              
6024             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
6025 0         0 # $1, $2, $3 --> $1, $2, $3 otherwise
6026 0 0       0 elsif ($char[$i] =~ /\A \$ ((?>[1-9][0-9]*)) \z/oxms) {
6027 0         0 $char[$i] = e_capture($1);
6028             if ($ignorecase) {
6029             $char[$i] = '@{[Elatin7::ignorecase(' . $char[$i] . ')]}';
6030             }
6031 0         0 }
6032 0 0       0 elsif ($char[$i] =~ /\A \$ \{ (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} \z/oxms) {
6033 0         0 $char[$i] = e_capture($1);
6034             if ($ignorecase) {
6035             $char[$i] = '@{[Elatin7::ignorecase(' . $char[$i] . ')]}';
6036             }
6037             }
6038              
6039 0         0 # $$foo[ ... ] --> $ $foo->[ ... ]
6040 0 0       0 elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \[ (?:$qq_bracket)*? \] ) \z/oxms) {
6041 0         0 $char[$i] = e_capture($1.'->'.$2);
6042             if ($ignorecase) {
6043             $char[$i] = '@{[Elatin7::ignorecase(' . $char[$i] . ')]}';
6044             }
6045             }
6046              
6047 0         0 # $$foo{ ... } --> $ $foo->{ ... }
6048 0 0       0 elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \{ (?:$qq_brace)*? \} ) \z/oxms) {
6049 0         0 $char[$i] = e_capture($1.'->'.$2);
6050             if ($ignorecase) {
6051             $char[$i] = '@{[Elatin7::ignorecase(' . $char[$i] . ')]}';
6052             }
6053             }
6054              
6055 0         0 # $$foo
6056 0 0       0 elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) \z/oxms) {
6057 0         0 $char[$i] = e_capture($1);
6058             if ($ignorecase) {
6059             $char[$i] = '@{[Elatin7::ignorecase(' . $char[$i] . ')]}';
6060             }
6061             }
6062              
6063 0 50       0 # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Elatin7::PREMATCH()
6064 8         24 elsif ($char[$i] =~ /\A ( \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} ) \z/oxmsgc) {
6065             if ($ignorecase) {
6066             $char[$i] = '@{[Elatin7::ignorecase(Elatin7::PREMATCH())]}';
6067 0         0 }
6068             else {
6069             $char[$i] = '@{[Elatin7::PREMATCH()]}';
6070             }
6071             }
6072              
6073 8 50       24 # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Elatin7::MATCH()
6074 8         31 elsif ($char[$i] =~ /\A ( \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} ) \z/oxmsgc) {
6075             if ($ignorecase) {
6076             $char[$i] = '@{[Elatin7::ignorecase(Elatin7::MATCH())]}';
6077 0         0 }
6078             else {
6079             $char[$i] = '@{[Elatin7::MATCH()]}';
6080             }
6081             }
6082              
6083 8 50       25 # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Elatin7::POSTMATCH()
6084 6         18 elsif ($char[$i] =~ /\A ( \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} ) \z/oxmsgc) {
6085             if ($ignorecase) {
6086             $char[$i] = '@{[Elatin7::ignorecase(Elatin7::POSTMATCH())]}';
6087 0         0 }
6088             else {
6089             $char[$i] = '@{[Elatin7::POSTMATCH()]}';
6090             }
6091             }
6092              
6093 6 0       20 # ${ foo }
6094 0         0 elsif ($char[$i] =~ /\A \$ (?>\s*) \{ ((?> \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* )) \} \z/oxms) {
6095             if ($ignorecase) {
6096             $char[$i] = '@{[Elatin7::ignorecase(' . $char[$i] . ')]}';
6097             }
6098             }
6099              
6100 0         0 # ${ ... }
6101 0 0       0 elsif ($char[$i] =~ /\A \$ (?>\s*) \{ ( .+ ) \} \z/oxms) {
6102 0         0 $char[$i] = e_capture($1);
6103             if ($ignorecase) {
6104             $char[$i] = '@{[Elatin7::ignorecase(' . $char[$i] . ')]}';
6105             }
6106             }
6107              
6108 0         0 # $scalar or @array
6109 21 100       74 elsif ($char[$i] =~ /\A [\$\@].+ /oxms) {
6110 21         125 $char[$i] = e_string($char[$i]);
6111             if ($ignorecase) {
6112             $char[$i] = '@{[Elatin7::ignorecase(' . $char[$i] . ')]}';
6113             }
6114             }
6115              
6116 11 100 33     37 # quote character before ? + * {
    50          
6117             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
6118             if ($char[$i-1] =~ /\A (?:[\x00-\xFF]|\\[0-7]{2,3}|\\x[0-9-A-Fa-f]{1,2}) \z/oxms) {
6119 138         1057 }
6120 0 0       0 elsif (($ope =~ /\A m? \z/oxms) and ($delimiter eq '?')) {
6121 0         0 my $char = $char[$i-1];
6122             if ($char[$i] eq '{') {
6123             die __FILE__, qq{: "MULTIBYTE{n}" should be "(MULTIBYTE){n}" in m?? (and shift \$1,\$2,\$3,...) ($char){n}\n};
6124 0         0 }
6125             else {
6126             die __FILE__, qq{: "MULTIBYTE$char[$i]" should be "(MULTIBYTE)$char[$i]" in m?? (and shift \$1,\$2,\$3,...) ($char)$char[$i]\n};
6127             }
6128 0         0 }
6129             else {
6130             $char[$i-1] = '(?:' . $char[$i-1] . ')';
6131             }
6132             }
6133             }
6134 127         510  
6135 642 50       1374 # make regexp string
6136 642 0 0     1457 $modifier =~ tr/i//d;
6137 0         0 if ($left_e > $right_e) {
6138             if (($ope =~ /\A m? \z/oxms) and ($delimiter eq '?')) {
6139             return join '', $ope, $delimiter, $anchor, @char, '>]}' x ($left_e - $right_e), $matched, $end_delimiter, $modifier;
6140 0         0 }
6141             else {
6142             return join '', $ope, $delimiter, $anchor, '(?:', @char, '>]}' x ($left_e - $right_e), ')', $matched, $end_delimiter, $modifier;
6143 0 50 33     0 }
6144 642         4099 }
6145             if (($ope =~ /\A m? \z/oxms) and ($delimiter eq '?')) {
6146             return join '', $ope, $delimiter, $anchor, @char, $matched, $end_delimiter, $modifier;
6147 0         0 }
6148             else {
6149             return join '', $ope, $delimiter, $anchor, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
6150             }
6151             }
6152              
6153             #
6154             # double quote stuff
6155 642     180 0 5531 #
6156             sub qq_stuff {
6157             my($delimiter,$end_delimiter,$stuff) = @_;
6158 180 100       265  
6159 180         402 # scalar variable or array variable
6160             if ($stuff =~ /\A [\$\@] /oxms) {
6161             return $stuff;
6162             }
6163 100         388  
  80         192  
6164 80         232 # quote by delimiter
6165 80 50       247 my %octet = map {$_ => 1} ($stuff =~ /\G ([\x00-\xFF]) /oxmsg);
6166 80 50       133 for my $char (qw( ! " $ % & * + - . / : = ? @ ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
6167 80 50       120 next if $char eq $delimiter;
6168 80         137 next if $char eq $end_delimiter;
6169             if (not $octet{$char}) {
6170             return join '', 'qq', $char, $stuff, $char;
6171 80         326 }
6172             }
6173             return join '', 'qq', '<', $stuff, '>';
6174             }
6175              
6176             #
6177             # escape regexp (m'', qr'', and m''b, qr''b)
6178 0     10 0 0 #
6179 10   50     48 sub e_qr_q {
6180             my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6181 10         44 $modifier ||= '';
6182 10 50       16  
6183 10         22 $modifier =~ tr/p//d;
6184 0         0 if ($modifier =~ /([adlu])/oxms) {
6185 0 0       0 my $line = 0;
6186 0         0 for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
6187 0         0 if ($filename ne __FILE__) {
6188             $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
6189             last;
6190 0         0 }
6191             }
6192             die qq{Unsupported modifier "$1" used at line $line.\n};
6193 0         0 }
6194              
6195             $slash = 'div';
6196 10 100       17  
    50          
6197 10         24 # literal null string pattern
6198 8         10 if ($string eq '') {
6199 8         11 $modifier =~ tr/bB//d;
6200             $modifier =~ tr/i//d;
6201             return join '', $ope, $delimiter, $end_delimiter, $modifier;
6202             }
6203              
6204 8         37 # with /b /B modifier
6205             elsif ($modifier =~ tr/bB//d) {
6206             return e_qr_qb($ope,$delimiter,$end_delimiter,$string,$modifier);
6207             }
6208              
6209 0         0 # without /b /B modifier
6210             else {
6211             return e_qr_qt($ope,$delimiter,$end_delimiter,$string,$modifier);
6212             }
6213             }
6214              
6215             #
6216             # escape regexp (m'', qr'')
6217 2     2 0 7 #
6218             sub e_qr_qt {
6219 2 50       8 my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6220              
6221             my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
6222 2         5  
6223             # split regexp
6224             my @char = $string =~ /\G((?>
6225             [^\\\[\$\@\/] |
6226             [\x00-\xFF] |
6227             \[\^ |
6228             \[\: (?>[a-z]+) \:\] |
6229             \[\:\^ (?>[a-z]+) \:\] |
6230             [\$\@\/] |
6231             \\ (?:$q_char) |
6232             (?:$q_char)
6233             ))/oxmsg;
6234 2         62  
6235 2 50 33     11 # unescape character
    50 33        
    50 33        
    50          
    50          
    50          
6236             for (my $i=0; $i <= $#char; $i++) {
6237             if (0) {
6238             }
6239 2         15  
6240 0         0 # open character class [...]
6241 0 0       0 elsif ($char[$i] eq '[') {
6242 0         0 my $left = $i;
6243             if ($char[$i+1] eq ']') {
6244 0         0 $i++;
6245 0 0       0 }
6246 0         0 while (1) {
6247             if (++$i > $#char) {
6248 0 0       0 die __FILE__, ": Unmatched [] in regexp\n";
6249 0         0 }
6250             if ($char[$i] eq ']') {
6251             my $right = $i;
6252 0         0  
6253             # [...]
6254 0         0 splice @char, $left, $right-$left+1, Elatin7::charlist_qr(@char[$left+1..$right-1], $modifier);
6255 0         0  
6256             $i = $left;
6257             last;
6258             }
6259             }
6260             }
6261              
6262 0         0 # open character class [^...]
6263 0 0       0 elsif ($char[$i] eq '[^') {
6264 0         0 my $left = $i;
6265             if ($char[$i+1] eq ']') {
6266 0         0 $i++;
6267 0 0       0 }
6268 0         0 while (1) {
6269             if (++$i > $#char) {
6270 0 0       0 die __FILE__, ": Unmatched [] in regexp\n";
6271 0         0 }
6272             if ($char[$i] eq ']') {
6273             my $right = $i;
6274 0         0  
6275             # [^...]
6276 0         0 splice @char, $left, $right-$left+1, Elatin7::charlist_not_qr(@char[$left+1..$right-1], $modifier);
6277 0         0  
6278             $i = $left;
6279             last;
6280             }
6281             }
6282             }
6283              
6284 0         0 # escape $ @ / and \
6285             elsif ($char[$i] =~ /\A [\$\@\/\\] \z/oxms) {
6286             $char[$i] = '\\' . $char[$i];
6287             }
6288              
6289 0         0 # rewrite character class or escape character
6290             elsif (my $char = character_class($char[$i],$modifier)) {
6291             $char[$i] = $char;
6292             }
6293              
6294 0 0       0 # /i modifier
6295 0         0 elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Elatin7::uc($char[$i]) ne Elatin7::fc($char[$i]))) {
6296             if (CORE::length(Elatin7::fc($char[$i])) == 1) {
6297             $char[$i] = '[' . Elatin7::uc($char[$i]) . Elatin7::fc($char[$i]) . ']';
6298 0         0 }
6299             else {
6300             $char[$i] = '(?:' . Elatin7::uc($char[$i]) . '|' . Elatin7::fc($char[$i]) . ')';
6301             }
6302             }
6303              
6304 0 0       0 # quote character before ? + * {
6305             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
6306             if ($char[$i-1] =~ /\A [\x00-\xFF] \z/oxms) {
6307 0         0 }
6308             else {
6309             $char[$i-1] = '(?:' . $char[$i-1] . ')';
6310             }
6311             }
6312 0         0 }
6313 2         5  
6314             $delimiter = '/';
6315 2         5 $end_delimiter = '/';
6316 2         3  
6317             $modifier =~ tr/i//d;
6318             return join '', $ope, $delimiter, $anchor, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
6319             }
6320              
6321             #
6322             # escape regexp (m''b, qr''b)
6323 2     0 0 16 #
6324             sub e_qr_qb {
6325             my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6326 0         0  
6327             # split regexp
6328             my @char = $string =~ /\G ((?>[^\\]|\\\\)) /oxmsg;
6329 0         0  
6330 0 0       0 # unescape character
    0          
6331             for (my $i=0; $i <= $#char; $i++) {
6332             if (0) {
6333             }
6334 0         0  
6335             # remain \\
6336             elsif ($char[$i] eq '\\\\') {
6337             }
6338              
6339 0         0 # escape $ @ / and \
6340             elsif ($char[$i] =~ /\A [\$\@\/\\] \z/oxms) {
6341             $char[$i] = '\\' . $char[$i];
6342             }
6343 0         0 }
6344 0         0  
6345 0         0 $delimiter = '/';
6346             $end_delimiter = '/';
6347             return join '', $ope, $delimiter, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
6348             }
6349              
6350             #
6351             # escape regexp (s/here//)
6352 0     76 0 0 #
6353 76   100     241 sub e_s1 {
6354             my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6355 76         389 $modifier ||= '';
6356 76 50       119  
6357 76         269 $modifier =~ tr/p//d;
6358 0         0 if ($modifier =~ /([adlu])/oxms) {
6359 0 0       0 my $line = 0;
6360 0         0 for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
6361 0         0 if ($filename ne __FILE__) {
6362             $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
6363             last;
6364 0         0 }
6365             }
6366             die qq{Unsupported modifier "$1" used at line $line.\n};
6367 0         0 }
6368              
6369             $slash = 'div';
6370 76 100       317  
    50          
6371 76         310 # literal null string pattern
6372 8         11 if ($string eq '') {
6373 8         12 $modifier =~ tr/bB//d;
6374             $modifier =~ tr/i//d;
6375             return join '', $ope, $delimiter, $end_delimiter, $modifier;
6376             }
6377              
6378             # /b /B modifier
6379             elsif ($modifier =~ tr/bB//d) {
6380 8 0       98  
6381 0         0 # choice again delimiter
6382 0         0 if ($delimiter =~ / [\@:] /oxms) {
  0         0  
6383 0 0       0 my @char = $string =~ /\G ([\x00-\xFF]) /oxmsg;
    0          
    0          
    0          
6384 0         0 my %octet = map {$_ => 1} @char;
6385 0         0 if (not $octet{')'}) {
6386             $delimiter = '(';
6387             $end_delimiter = ')';
6388 0         0 }
6389 0         0 elsif (not $octet{'}'}) {
6390             $delimiter = '{';
6391             $end_delimiter = '}';
6392 0         0 }
6393 0         0 elsif (not $octet{']'}) {
6394             $delimiter = '[';
6395             $end_delimiter = ']';
6396 0         0 }
6397 0         0 elsif (not $octet{'>'}) {
6398             $delimiter = '<';
6399             $end_delimiter = '>';
6400 0         0 }
6401 0 0       0 else {
6402 0         0 for my $char (qw( ! " $ % & * + - . / = ? ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
6403 0         0 if (not $octet{$char}) {
6404 0         0 $delimiter = $char;
6405             $end_delimiter = $char;
6406             last;
6407             }
6408             }
6409             }
6410 0         0 }
6411 0         0  
6412             my $prematch = '';
6413             return join '', $ope, $delimiter, $prematch, '(?:', $string, ')', $matched, $end_delimiter, $modifier;
6414 0 100       0 }
6415 68         218  
6416             my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
6417             my $metachar = qr/[\@\\|[\]{^]/oxms;
6418 68         564  
6419             # split regexp
6420             my @char = $string =~ /\G((?>
6421             [^\\\$\@\[\(] |
6422             \\ (?>[1-9][0-9]*) |
6423             \\g (?>\s*) (?>[1-9][0-9]*) |
6424             \\g (?>\s*) \{ (?>\s*) (?>[1-9][0-9]*) (?>\s*) \} |
6425             \\g (?>\s*) \{ (?>\s*) - (?>\s*) (?>[1-9][0-9]*) (?>\s*) \} |
6426             \\x (?>[0-9A-Fa-f]{1,2}) |
6427             \\ (?>[0-7]{2,3}) |
6428             \\c [\x40-\x5F] |
6429             \\x\{ (?>[0-9A-Fa-f]+) \} |
6430             \\o\{ (?>[0-7]+) \} |
6431             \\[bBNpP]\{ (?>[^0-9\}][^\}]*) \} |
6432             \\ $q_char |
6433             \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} |
6434             \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} |
6435             \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} |
6436             [\$\@] $qq_variable |
6437             \$ (?>\s* [0-9]+) |
6438             \$ (?>\s*) \{ (?>\s* [0-9]+ \s*) \} |
6439             \$ \$ (?![\w\{]) |
6440             \$ (?>\s*) \$ (?>\s*) $qq_variable |
6441             \[\^ |
6442             \[\: (?>[a-z]+) :\] |
6443             \[\:\^ (?>[a-z]+) :\] |
6444             \(\? |
6445             $q_char
6446             ))/oxmsg;
6447 68 50       25498  
6448 68         549 # choice again delimiter
  0         0  
6449 0 0       0 if ($delimiter =~ / [\@:] /oxms) {
    0          
    0          
    0          
6450 0         0 my %octet = map {$_ => 1} @char;
6451 0         0 if (not $octet{')'}) {
6452             $delimiter = '(';
6453             $end_delimiter = ')';
6454 0         0 }
6455 0         0 elsif (not $octet{'}'}) {
6456             $delimiter = '{';
6457             $end_delimiter = '}';
6458 0         0 }
6459 0         0 elsif (not $octet{']'}) {
6460             $delimiter = '[';
6461             $end_delimiter = ']';
6462 0         0 }
6463 0         0 elsif (not $octet{'>'}) {
6464             $delimiter = '<';
6465             $end_delimiter = '>';
6466 0         0 }
6467 0 0       0 else {
6468 0         0 for my $char (qw( ! " $ % & * + - . / = ? ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
6469 0         0 if (not $octet{$char}) {
6470 0         0 $delimiter = $char;
6471             $end_delimiter = $char;
6472             last;
6473             }
6474             }
6475             }
6476             }
6477 0         0  
  68         153  
6478             # count '('
6479 253         454 my $parens = grep { $_ eq '(' } @char;
6480 68         121  
6481 68         105 my $left_e = 0;
6482             my $right_e = 0;
6483             for (my $i=0; $i <= $#char; $i++) {
6484 68 50 33     215  
    50 33        
    100          
    100          
    50          
    50          
6485 195         1256 # "\L\u" --> "\u\L"
6486             if (($char[$i] eq '\L') and ($char[$i+1] eq '\u')) {
6487             @char[$i,$i+1] = @char[$i+1,$i];
6488             }
6489              
6490 0         0 # "\U\l" --> "\l\U"
6491             elsif (($char[$i] eq '\U') and ($char[$i+1] eq '\l')) {
6492             @char[$i,$i+1] = @char[$i+1,$i];
6493             }
6494              
6495 0         0 # octal escape sequence
6496             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
6497             $char[$i] = Elatin7::octchr($1);
6498             }
6499              
6500 1         4 # hexadecimal escape sequence
6501             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
6502             $char[$i] = Elatin7::hexchr($1);
6503             }
6504              
6505             # \b{...} --> b\{...}
6506             # \B{...} --> B\{...}
6507             # \N{CHARNAME} --> N\{CHARNAME}
6508             # \p{PROPERTY} --> p\{PROPERTY}
6509 1         3 # \P{PROPERTY} --> P\{PROPERTY}
6510             elsif ($char[$i] =~ /\A \\ ([bBNpP]) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
6511             $char[$i] = $1 . '\\' . $2;
6512             }
6513              
6514 0         0 # \p, \P, \X --> p, P, X
6515             elsif ($char[$i] =~ /\A \\ ( [pPX] ) \z/oxms) {
6516             $char[$i] = $1;
6517 0 50 66     0 }
    100 66        
    50 100        
    100          
    100          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    100          
    100          
    100          
    50          
    50          
    100          
    100          
6518              
6519             if (0) {
6520             }
6521 195         769  
6522 0 0 0     0 # join separated multiple-octet
    0 0        
    0 0        
      0        
      0        
      0        
6523 0         0 elsif ($char[$i] =~ /\A (?: \\ [0-7]{2,3} | \\x [0-9A-Fa-f]{1,2}) \z/oxms) {
6524             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)) {
6525             $char[$i] .= join '', splice @char, $i+1, 3;
6526 0         0 }
6527             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)) {
6528             $char[$i] .= join '', splice @char, $i+1, 2;
6529 0         0 }
6530             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)) {
6531             $char[$i] .= join '', splice @char, $i+1, 1;
6532             }
6533             }
6534              
6535 0         0 # open character class [...]
6536 13 50       21 elsif ($char[$i] eq '[') {
6537 13         61 my $left = $i;
6538             if ($char[$i+1] eq ']') {
6539 0         0 $i++;
6540 13 50       19 }
6541 58         85 while (1) {
6542             if (++$i > $#char) {
6543 0 100       0 die __FILE__, ": Unmatched [] in regexp\n";
6544 58         130 }
6545             if ($char[$i] eq ']') {
6546             my $right = $i;
6547 13 50       23  
6548 13         120 # [...]
  0         0  
6549             if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
6550             splice @char, $left, $right-$left+1, sprintf(q{@{[Elatin7::charlist_qr(%s,'%s')]}}, join(',', map {qq_stuff($delimiter,$end_delimiter,$_)} @char[$left+1..$right-1]), $modifier);
6551 0         0 }
6552             else {
6553             splice @char, $left, $right-$left+1, Elatin7::charlist_qr(@char[$left+1..$right-1], $modifier);
6554 13         65 }
6555 13         33  
6556             $i = $left;
6557             last;
6558             }
6559             }
6560             }
6561              
6562 13         37 # open character class [^...]
6563 0 0       0 elsif ($char[$i] eq '[^') {
6564 0         0 my $left = $i;
6565             if ($char[$i+1] eq ']') {
6566 0         0 $i++;
6567 0 0       0 }
6568 0         0 while (1) {
6569             if (++$i > $#char) {
6570 0 0       0 die __FILE__, ": Unmatched [] in regexp\n";
6571 0         0 }
6572             if ($char[$i] eq ']') {
6573             my $right = $i;
6574 0 0       0  
6575 0         0 # [^...]
  0         0  
6576             if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
6577             splice @char, $left, $right-$left+1, sprintf(q{@{[Elatin7::charlist_not_qr(%s,'%s')]}}, join(',', map {qq_stuff($delimiter,$end_delimiter,$_)} @char[$left+1..$right-1]), $modifier);
6578 0         0 }
6579             else {
6580             splice @char, $left, $right-$left+1, Elatin7::charlist_not_qr(@char[$left+1..$right-1], $modifier);
6581 0         0 }
6582 0         0  
6583             $i = $left;
6584             last;
6585             }
6586             }
6587             }
6588              
6589 0         0 # rewrite character class or escape character
6590             elsif (my $char = character_class($char[$i],$modifier)) {
6591             $char[$i] = $char;
6592             }
6593              
6594 7 50       13 # /i modifier
6595 3         6 elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Elatin7::uc($char[$i]) ne Elatin7::fc($char[$i]))) {
6596             if (CORE::length(Elatin7::fc($char[$i])) == 1) {
6597             $char[$i] = '[' . Elatin7::uc($char[$i]) . Elatin7::fc($char[$i]) . ']';
6598 3         5 }
6599             else {
6600             $char[$i] = '(?:' . Elatin7::uc($char[$i]) . '|' . Elatin7::fc($char[$i]) . ')';
6601             }
6602             }
6603              
6604 0 0       0 # \u \l \U \L \F \Q \E
6605 0         0 elsif ($char[$i] =~ /\A [<>] \z/oxms) {
6606             if ($right_e < $left_e) {
6607             $char[$i] = '\\' . $char[$i];
6608             }
6609 0         0 }
6610 0         0 elsif ($char[$i] eq '\u') {
6611             $char[$i] = '@{[Elatin7::ucfirst qq<';
6612             $left_e++;
6613 0         0 }
6614 0         0 elsif ($char[$i] eq '\l') {
6615             $char[$i] = '@{[Elatin7::lcfirst qq<';
6616             $left_e++;
6617 0         0 }
6618 0         0 elsif ($char[$i] eq '\U') {
6619             $char[$i] = '@{[Elatin7::uc qq<';
6620             $left_e++;
6621 0         0 }
6622 0         0 elsif ($char[$i] eq '\L') {
6623             $char[$i] = '@{[Elatin7::lc qq<';
6624             $left_e++;
6625 0         0 }
6626 0         0 elsif ($char[$i] eq '\F') {
6627             $char[$i] = '@{[Elatin7::fc qq<';
6628             $left_e++;
6629 0         0 }
6630 0         0 elsif ($char[$i] eq '\Q') {
6631             $char[$i] = '@{[CORE::quotemeta qq<';
6632             $left_e++;
6633 0 0       0 }
6634 0         0 elsif ($char[$i] eq '\E') {
6635 0         0 if ($right_e < $left_e) {
6636             $char[$i] = '>]}';
6637             $right_e++;
6638 0         0 }
6639             else {
6640             $char[$i] = '';
6641             }
6642 0         0 }
6643 0 0       0 elsif ($char[$i] eq '\Q') {
6644 0         0 while (1) {
6645             if (++$i > $#char) {
6646 0 0       0 last;
6647 0         0 }
6648             if ($char[$i] eq '\E') {
6649             last;
6650             }
6651             }
6652             }
6653             elsif ($char[$i] eq '\E') {
6654             }
6655              
6656             # \0 --> \0
6657             elsif ($char[$i] =~ /\A \\ (?>\s*) 0 \z/oxms) {
6658             }
6659              
6660             # \g{N}, \g{-N}
6661              
6662             # P.108 Using Simple Patterns
6663             # in Chapter 7: In the World of Regular Expressions
6664             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
6665              
6666             # P.221 Capturing
6667             # in Chapter 5: Pattern Matching
6668             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
6669              
6670             # \g{-1}, \g{-2}, \g{-3} --> \g{-1}, \g{-2}, \g{-3}
6671             elsif ($char[$i] =~ /\A \\g (?>\s*) \{ (?>\s*) - (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} \z/oxms) {
6672             }
6673              
6674             # \g{1}, \g{2}, \g{3} --> \g{2}, \g{3}, \g{4} (only when multibyte anchoring is enable)
6675             elsif ($char[$i] =~ /\A \\g (?>\s*) \{ (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} \z/oxms) {
6676             }
6677              
6678             # \g1, \g2, \g3 --> \g2, \g3, \g4 (only when multibyte anchoring is enable)
6679             elsif ($char[$i] =~ /\A \\g (?>\s*) ((?>[1-9][0-9]*)) \z/oxms) {
6680             }
6681              
6682             # \1, \2, \3 --> \2, \3, \4 (only when multibyte anchoring is enable)
6683             elsif ($char[$i] =~ /\A \\ (?>\s*) ((?>[1-9][0-9]*)) \z/oxms) {
6684             }
6685              
6686 0 0       0 # $0 --> $0
6687 0         0 elsif ($char[$i] =~ /\A \$ 0 \z/oxms) {
6688             if ($ignorecase) {
6689             $char[$i] = '@{[Elatin7::ignorecase(' . $char[$i] . ')]}';
6690             }
6691 0 0       0 }
6692 0         0 elsif ($char[$i] =~ /\A \$ \{ (?>\s*) 0 (?>\s*) \} \z/oxms) {
6693             if ($ignorecase) {
6694             $char[$i] = '@{[Elatin7::ignorecase(' . $char[$i] . ')]}';
6695             }
6696             }
6697              
6698             # $$ --> $$
6699             elsif ($char[$i] =~ /\A \$\$ \z/oxms) {
6700             }
6701              
6702             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
6703 0         0 # $1, $2, $3 --> $1, $2, $3 otherwise
6704 0 0       0 elsif ($char[$i] =~ /\A \$ ((?>[1-9][0-9]*)) \z/oxms) {
6705 0         0 $char[$i] = e_capture($1);
6706             if ($ignorecase) {
6707             $char[$i] = '@{[Elatin7::ignorecase(' . $char[$i] . ')]}';
6708             }
6709 0         0 }
6710 0 0       0 elsif ($char[$i] =~ /\A \$ \{ (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} \z/oxms) {
6711 0         0 $char[$i] = e_capture($1);
6712             if ($ignorecase) {
6713             $char[$i] = '@{[Elatin7::ignorecase(' . $char[$i] . ')]}';
6714             }
6715             }
6716              
6717 0         0 # $$foo[ ... ] --> $ $foo->[ ... ]
6718 0 0       0 elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \[ (?:$qq_bracket)*? \] ) \z/oxms) {
6719 0         0 $char[$i] = e_capture($1.'->'.$2);
6720             if ($ignorecase) {
6721             $char[$i] = '@{[Elatin7::ignorecase(' . $char[$i] . ')]}';
6722             }
6723             }
6724              
6725 0         0 # $$foo{ ... } --> $ $foo->{ ... }
6726 0 0       0 elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \{ (?:$qq_brace)*? \} ) \z/oxms) {
6727 0         0 $char[$i] = e_capture($1.'->'.$2);
6728             if ($ignorecase) {
6729             $char[$i] = '@{[Elatin7::ignorecase(' . $char[$i] . ')]}';
6730             }
6731             }
6732              
6733 0         0 # $$foo
6734 0 0       0 elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) \z/oxms) {
6735 0         0 $char[$i] = e_capture($1);
6736             if ($ignorecase) {
6737             $char[$i] = '@{[Elatin7::ignorecase(' . $char[$i] . ')]}';
6738             }
6739             }
6740              
6741 0 50       0 # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Elatin7::PREMATCH()
6742 4         14 elsif ($char[$i] =~ /\A ( \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} ) \z/oxmsgc) {
6743             if ($ignorecase) {
6744             $char[$i] = '@{[Elatin7::ignorecase(Elatin7::PREMATCH())]}';
6745 0         0 }
6746             else {
6747             $char[$i] = '@{[Elatin7::PREMATCH()]}';
6748             }
6749             }
6750              
6751 4 50       16 # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Elatin7::MATCH()
6752 4         14 elsif ($char[$i] =~ /\A ( \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} ) \z/oxmsgc) {
6753             if ($ignorecase) {
6754             $char[$i] = '@{[Elatin7::ignorecase(Elatin7::MATCH())]}';
6755 0         0 }
6756             else {
6757             $char[$i] = '@{[Elatin7::MATCH()]}';
6758             }
6759             }
6760              
6761 4 50       15 # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Elatin7::POSTMATCH()
6762 3         9 elsif ($char[$i] =~ /\A ( \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} ) \z/oxmsgc) {
6763             if ($ignorecase) {
6764             $char[$i] = '@{[Elatin7::ignorecase(Elatin7::POSTMATCH())]}';
6765 0         0 }
6766             else {
6767             $char[$i] = '@{[Elatin7::POSTMATCH()]}';
6768             }
6769             }
6770              
6771 3 0       12 # ${ foo }
6772 0         0 elsif ($char[$i] =~ /\A \$ (?>\s*) \{ ((?> \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* )) \} \z/oxms) {
6773             if ($ignorecase) {
6774             $char[$i] = '@{[Elatin7::ignorecase(' . $char[$i] . ')]}';
6775             }
6776             }
6777              
6778 0         0 # ${ ... }
6779 0 0       0 elsif ($char[$i] =~ /\A \$ (?>\s*) \{ ( .+ ) \} \z/oxms) {
6780 0         0 $char[$i] = e_capture($1);
6781             if ($ignorecase) {
6782             $char[$i] = '@{[Elatin7::ignorecase(' . $char[$i] . ')]}';
6783             }
6784             }
6785              
6786 0         0 # $scalar or @array
6787 4 50       38 elsif ($char[$i] =~ /\A [\$\@].+ /oxms) {
6788 4         24 $char[$i] = e_string($char[$i]);
6789             if ($ignorecase) {
6790             $char[$i] = '@{[Elatin7::ignorecase(' . $char[$i] . ')]}';
6791             }
6792             }
6793              
6794 0 50       0 # quote character before ? + * {
6795             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
6796             if ($char[$i-1] =~ /\A (?:[\x00-\xFF]|\\[0-7]{2,3}|\\x[0-9-A-Fa-f]{1,2}) \z/oxms) {
6797 13         61 }
6798             else {
6799             $char[$i-1] = '(?:' . $char[$i-1] . ')';
6800             }
6801             }
6802             }
6803 13         62  
6804 68         178 # make regexp string
6805 68 50       544 my $prematch = '';
6806 68         223 $modifier =~ tr/i//d;
6807             if ($left_e > $right_e) {
6808 0         0 return join '', $ope, $delimiter, $prematch, '(?:', @char, '>]}' x ($left_e - $right_e), ')', $matched, $end_delimiter, $modifier;
6809             }
6810             return join '', $ope, $delimiter, $prematch, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
6811             }
6812              
6813             #
6814             # escape regexp (s'here'' or s'here''b)
6815 68     21 0 1243 #
6816 21   100     47 sub e_s1_q {
6817             my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6818 21         69 $modifier ||= '';
6819 21 50       29  
6820 21         44 $modifier =~ tr/p//d;
6821 0         0 if ($modifier =~ /([adlu])/oxms) {
6822 0 0       0 my $line = 0;
6823 0         0 for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
6824 0         0 if ($filename ne __FILE__) {
6825             $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
6826             last;
6827 0         0 }
6828             }
6829             die qq{Unsupported modifier "$1" used at line $line.\n};
6830 0         0 }
6831              
6832             $slash = 'div';
6833 21 100       29  
    50          
6834 21         54 # literal null string pattern
6835 8         10 if ($string eq '') {
6836 8         13 $modifier =~ tr/bB//d;
6837             $modifier =~ tr/i//d;
6838             return join '', $ope, $delimiter, $end_delimiter, $modifier;
6839             }
6840              
6841 8         48 # with /b /B modifier
6842             elsif ($modifier =~ tr/bB//d) {
6843             return e_s1_qb($ope,$delimiter,$end_delimiter,$string,$modifier);
6844             }
6845              
6846 0         0 # without /b /B modifier
6847             else {
6848             return e_s1_qt($ope,$delimiter,$end_delimiter,$string,$modifier);
6849             }
6850             }
6851              
6852             #
6853             # escape regexp (s'here'')
6854 13     13 0 30 #
6855             sub e_s1_qt {
6856 13 50       28 my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6857              
6858             my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
6859 13         24  
6860             # split regexp
6861             my @char = $string =~ /\G((?>
6862             [^\\\[\$\@\/] |
6863             [\x00-\xFF] |
6864             \[\^ |
6865             \[\: (?>[a-z]+) \:\] |
6866             \[\:\^ (?>[a-z]+) \:\] |
6867             [\$\@\/] |
6868             \\ (?:$q_char) |
6869             (?:$q_char)
6870             ))/oxmsg;
6871 13         189  
6872 13 50 33     40 # unescape character
    50 33        
    50 66        
    100          
    50          
    50          
6873             for (my $i=0; $i <= $#char; $i++) {
6874             if (0) {
6875             }
6876 25         91  
6877 0         0 # open character class [...]
6878 0 0       0 elsif ($char[$i] eq '[') {
6879 0         0 my $left = $i;
6880             if ($char[$i+1] eq ']') {
6881 0         0 $i++;
6882 0 0       0 }
6883 0         0 while (1) {
6884             if (++$i > $#char) {
6885 0 0       0 die __FILE__, ": Unmatched [] in regexp\n";
6886 0         0 }
6887             if ($char[$i] eq ']') {
6888             my $right = $i;
6889 0         0  
6890             # [...]
6891 0         0 splice @char, $left, $right-$left+1, Elatin7::charlist_qr(@char[$left+1..$right-1], $modifier);
6892 0         0  
6893             $i = $left;
6894             last;
6895             }
6896             }
6897             }
6898              
6899 0         0 # open character class [^...]
6900 0 0       0 elsif ($char[$i] eq '[^') {
6901 0         0 my $left = $i;
6902             if ($char[$i+1] eq ']') {
6903 0         0 $i++;
6904 0 0       0 }
6905 0         0 while (1) {
6906             if (++$i > $#char) {
6907 0 0       0 die __FILE__, ": Unmatched [] in regexp\n";
6908 0         0 }
6909             if ($char[$i] eq ']') {
6910             my $right = $i;
6911 0         0  
6912             # [^...]
6913 0         0 splice @char, $left, $right-$left+1, Elatin7::charlist_not_qr(@char[$left+1..$right-1], $modifier);
6914 0         0  
6915             $i = $left;
6916             last;
6917             }
6918             }
6919             }
6920              
6921 0         0 # escape $ @ / and \
6922             elsif ($char[$i] =~ /\A [\$\@\/\\] \z/oxms) {
6923             $char[$i] = '\\' . $char[$i];
6924             }
6925              
6926 0         0 # rewrite character class or escape character
6927             elsif (my $char = character_class($char[$i],$modifier)) {
6928             $char[$i] = $char;
6929             }
6930              
6931 6 0       13 # /i modifier
6932 0         0 elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Elatin7::uc($char[$i]) ne Elatin7::fc($char[$i]))) {
6933             if (CORE::length(Elatin7::fc($char[$i])) == 1) {
6934             $char[$i] = '[' . Elatin7::uc($char[$i]) . Elatin7::fc($char[$i]) . ']';
6935 0         0 }
6936             else {
6937             $char[$i] = '(?:' . Elatin7::uc($char[$i]) . '|' . Elatin7::fc($char[$i]) . ')';
6938             }
6939             }
6940              
6941 0 0       0 # quote character before ? + * {
6942             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
6943             if ($char[$i-1] =~ /\A [\x00-\xFF] \z/oxms) {
6944 0         0 }
6945             else {
6946             $char[$i-1] = '(?:' . $char[$i-1] . ')';
6947             }
6948             }
6949 0         0 }
6950 13         27  
6951 13         19 $modifier =~ tr/i//d;
6952 13         17 $delimiter = '/';
6953 13         17 $end_delimiter = '/';
6954             my $prematch = '';
6955             return join '', $ope, $delimiter, $prematch, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
6956             }
6957              
6958             #
6959             # escape regexp (s'here''b)
6960 13     0 0 95 #
6961             sub e_s1_qb {
6962             my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6963 0         0  
6964             # split regexp
6965             my @char = $string =~ /\G (?>[^\\]|\\\\) /oxmsg;
6966 0         0  
6967 0 0       0 # unescape character
    0          
6968             for (my $i=0; $i <= $#char; $i++) {
6969             if (0) {
6970             }
6971 0         0  
6972             # remain \\
6973             elsif ($char[$i] eq '\\\\') {
6974             }
6975              
6976 0         0 # escape $ @ / and \
6977             elsif ($char[$i] =~ /\A [\$\@\/\\] \z/oxms) {
6978             $char[$i] = '\\' . $char[$i];
6979             }
6980 0         0 }
6981 0         0  
6982 0         0 $delimiter = '/';
6983 0         0 $end_delimiter = '/';
6984             my $prematch = '';
6985             return join '', $ope, $delimiter, $prematch, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
6986             }
6987              
6988             #
6989             # escape regexp (s''here')
6990 0     16 0 0 #
6991             sub e_s2_q {
6992 16         33 my($ope,$delimiter,$end_delimiter,$string) = @_;
6993              
6994 16         21 $slash = 'div';
6995 16         98  
6996 16 100       47 my @char = $string =~ / \G (?>[^\\]|\\\\|$q_char) /oxmsg;
    100          
6997             for (my $i=0; $i <= $#char; $i++) {
6998             if (0) {
6999             }
7000 9         34  
7001             # not escape \\
7002             elsif ($char[$i] =~ /\A \\\\ \z/oxms) {
7003             }
7004              
7005 0         0 # escape $ @ / and \
7006             elsif ($char[$i] =~ /\A [\$\@\/\\] \z/oxms) {
7007             $char[$i] = '\\' . $char[$i];
7008             }
7009 5         17 }
7010              
7011             return join '', $ope, $delimiter, @char, $end_delimiter;
7012             }
7013              
7014             #
7015             # escape regexp (s/here/and here/modifier)
7016 16     97 0 52 #
7017 97   100     1144 sub e_sub {
7018             my($variable,$delimiter1,$pattern,$end_delimiter1,$delimiter2,$replacement,$end_delimiter2,$modifier) = @_;
7019 97         523 $modifier ||= '';
7020 97 50       220  
7021 97         291 $modifier =~ tr/p//d;
7022 0         0 if ($modifier =~ /([adlu])/oxms) {
7023 0 0       0 my $line = 0;
7024 0         0 for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
7025 0         0 if ($filename ne __FILE__) {
7026             $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
7027             last;
7028 0         0 }
7029             }
7030             die qq{Unsupported modifier "$1" used at line $line.\n};
7031 0 100       0 }
7032 97         277  
7033 36         48 if ($variable eq '') {
7034             $variable = '$_';
7035             $bind_operator = ' =~ ';
7036 36         45 }
7037              
7038             $slash = 'div';
7039              
7040             # P.128 Start of match (or end of previous match): \G
7041             # P.130 Advanced Use of \G with Perl
7042             # in Chapter 3: Overview of Regular Expression Features and Flavors
7043             # P.312 Iterative Matching: Scalar Context, with /g
7044             # in Chapter 7: Perl
7045             # of ISBN 0-596-00289-0 Mastering Regular Expressions, Second edition
7046              
7047             # P.181 Where You Left Off: The \G Assertion
7048             # in Chapter 5: Pattern Matching
7049             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
7050              
7051             # P.220 Where You Left Off: The \G Assertion
7052             # in Chapter 5: Pattern Matching
7053 97         176 # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
7054 97         281  
7055             my $e_modifier = $modifier =~ tr/e//d;
7056 97         170 my $r_modifier = $modifier =~ tr/r//d;
7057 97 50       258  
7058 97         302 my $my = '';
7059 0         0 if ($variable =~ s/\A \( (?>\s*) ( (?>(?: local \b | my \b | our \b | state \b )?) .+ ) \) \z/$1/oxms) {
7060 0         0 $my = $variable;
7061             $variable =~ s/ (?: local \b | my \b | our \b | state \b ) (?>\s*) //oxms;
7062             $variable =~ s/ = .+ \z//oxms;
7063 0         0 }
7064 97         272  
7065             (my $variable_basename = $variable) =~ s/ [\[\{].* \z//oxms;
7066             $variable_basename =~ s/ \s+ \z//oxms;
7067 97         266  
7068 97 100       155 # quote replacement string
7069 97         381 my $e_replacement = '';
7070 17         30 if ($e_modifier >= 1) {
7071             $e_replacement = e_qq('', '', '', $replacement);
7072             $e_modifier--;
7073 17 100       22 }
7074 80         273 else {
7075             if ($delimiter2 eq "'") {
7076             $e_replacement = e_s2_q('qq', '/', '/', $replacement);
7077 16         34 }
7078             else {
7079             $e_replacement = e_qq ('qq', $delimiter2, $end_delimiter2, $replacement);
7080             }
7081 64         187 }
7082              
7083             my $sub = '';
7084 97 100       248  
7085 97 100       238 # with /r
7086             if ($r_modifier) {
7087             if (0) {
7088             }
7089 8         25  
7090 0 50       0 # s///gr without multibyte anchoring
7091             elsif ($modifier =~ /g/oxms) {
7092             $sub = sprintf(
7093             # 1 2 3 4 5
7094             q,
7095              
7096             $variable, # 1
7097             ($delimiter1 eq "'") ? # 2
7098             e_s1_q('m', $delimiter1, $end_delimiter1, $pattern, $modifier) : # :
7099             e_s1 ('m', $delimiter1, $end_delimiter1, $pattern, $modifier), # :
7100             $s_matched, # 3
7101             $e_replacement, # 4
7102             '$Elatin7::re_r=CORE::eval $Elatin7::re_r; ' x $e_modifier, # 5
7103             );
7104             }
7105              
7106             # s///r
7107 4         23 else {
7108              
7109 4 50       9 my $prematch = q{$`};
7110              
7111             $sub = sprintf(
7112             # 1 2 3 4 5 6 7
7113             q<(%s =~ %s) ? CORE::eval{%s local $^W=0; local $Elatin7::re_r=%s; %s"%s$Elatin7::re_r$'" } : %s>,
7114              
7115             $variable, # 1
7116             ($delimiter1 eq "'") ? # 2
7117             e_s1_q('m', $delimiter1, $end_delimiter1, $pattern, $modifier) : # :
7118             e_s1 ('m', $delimiter1, $end_delimiter1, $pattern, $modifier), # :
7119             $s_matched, # 3
7120             $e_replacement, # 4
7121             '$Elatin7::re_r=CORE::eval $Elatin7::re_r; ' x $e_modifier, # 5
7122             $prematch, # 6
7123             $variable, # 7
7124             );
7125             }
7126 4 50       23  
7127 8         31 # $var !~ s///r doesn't make sense
7128             if ($bind_operator =~ / !~ /oxms) {
7129             $sub = q{die("$0: Using !~ with s///r doesn't make sense"), } . $sub;
7130             }
7131             }
7132              
7133 0 100       0 # without /r
7134             else {
7135             if (0) {
7136             }
7137 89         272  
7138 0 100       0 # s///g without multibyte anchoring
    100          
7139             elsif ($modifier =~ /g/oxms) {
7140             $sub = sprintf(
7141             # 1 2 3 4 5 6 7 8
7142             q,
7143              
7144             $variable, # 1
7145             ($delimiter1 eq "'") ? # 2
7146             e_s1_q('m', $delimiter1, $end_delimiter1, $pattern, $modifier) : # :
7147             e_s1 ('m', $delimiter1, $end_delimiter1, $pattern, $modifier), # :
7148             $s_matched, # 3
7149             $e_replacement, # 4
7150             '$Elatin7::re_r=CORE::eval $Elatin7::re_r; ' x $e_modifier, # 5
7151             $variable, # 6
7152             $variable, # 7
7153             ($bind_operator =~ / !~ /oxms) ? '!' : '', # 8
7154             );
7155             }
7156              
7157             # s///
7158 22         533 else {
7159              
7160 67 100       121 my $prematch = q{$`};
    100          
7161              
7162             $sub = sprintf(
7163              
7164             ($bind_operator =~ / =~ /oxms) ?
7165              
7166             # 1 2 3 4 5 6 7 8
7167             q<(%s%s%s) ? CORE::eval{%s local $^W=0; local $Elatin7::re_r=%s; %s%s="%s$Elatin7::re_r$'"; 1 } : undef> :
7168              
7169             # 1 2 3 4 5 6 7 8
7170             q<(%s%s%s) ? 1 : CORE::eval{%s local $^W=0; local $Elatin7::re_r=%s; %s%s="%s$Elatin7::re_r$'"; undef }>,
7171              
7172             $variable, # 1
7173             $bind_operator, # 2
7174             ($delimiter1 eq "'") ? # 3
7175             e_s1_q('m', $delimiter1, $end_delimiter1, $pattern, $modifier) : # :
7176             e_s1 ('m', $delimiter1, $end_delimiter1, $pattern, $modifier), # :
7177             $s_matched, # 4
7178             $e_replacement, # 5
7179             '$Elatin7::re_r=CORE::eval $Elatin7::re_r; ' x $e_modifier, # 6
7180             $variable, # 7
7181             $prematch, # 8
7182             );
7183             }
7184             }
7185 67 50       543  
7186 97         344 # (my $foo = $bar) =~ s/// --> (my $foo = $bar, CORE::eval { ... })[1]
7187             if ($my ne '') {
7188             $sub = "($my, $sub)[1]";
7189             }
7190 0         0  
7191 97         181 # clear s/// variable
7192             $sub_variable = '';
7193 97         141 $bind_operator = '';
7194              
7195             return $sub;
7196             }
7197              
7198             #
7199             # escape regexp of split qr//
7200 97     74 0 838 #
7201 74   100     353 sub e_split {
7202             my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
7203 74         359 $modifier ||= '';
7204 74 50       132  
7205 74         182 $modifier =~ tr/p//d;
7206 0         0 if ($modifier =~ /([adlu])/oxms) {
7207 0 0       0 my $line = 0;
7208 0         0 for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
7209 0         0 if ($filename ne __FILE__) {
7210             $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
7211             last;
7212 0         0 }
7213             }
7214             die qq{Unsupported modifier "$1" used at line $line.\n};
7215 0         0 }
7216              
7217             $slash = 'div';
7218 74 50       131  
7219 74         207 # /b /B modifier
7220             if ($modifier =~ tr/bB//d) {
7221             return join '', 'split', $ope, $delimiter, $string, $end_delimiter, $modifier;
7222 0 50       0 }
7223 74         236  
7224             my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
7225             my $metachar = qr/[\@\\|[\]{^]/oxms;
7226 74         272  
7227             # split regexp
7228             my @char = $string =~ /\G((?>
7229             [^\\\$\@\[\(] |
7230             \\x (?>[0-9A-Fa-f]{1,2}) |
7231             \\ (?>[0-7]{2,3}) |
7232             \\c [\x40-\x5F] |
7233             \\x\{ (?>[0-9A-Fa-f]+) \} |
7234             \\o\{ (?>[0-7]+) \} |
7235             \\[bBNpP]\{ (?>[^0-9\}][^\}]*) \} |
7236             \\ $q_char |
7237             \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} |
7238             \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} |
7239             \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} |
7240             [\$\@] $qq_variable |
7241             \$ (?>\s* [0-9]+) |
7242             \$ (?>\s*) \{ (?>\s* [0-9]+ \s*) \} |
7243             \$ \$ (?![\w\{]) |
7244             \$ (?>\s*) \$ (?>\s*) $qq_variable |
7245             \[\^ |
7246             \[\: (?>[a-z]+) :\] |
7247             \[\:\^ (?>[a-z]+) :\] |
7248             \(\? |
7249             $q_char
7250 74         8728 ))/oxmsg;
7251 74         235  
7252 74         119 my $left_e = 0;
7253             my $right_e = 0;
7254             for (my $i=0; $i <= $#char; $i++) {
7255 74 50 33     471  
    50 33        
    100          
    100          
    50          
    50          
7256 249         1308 # "\L\u" --> "\u\L"
7257             if (($char[$i] eq '\L') and ($char[$i+1] eq '\u')) {
7258             @char[$i,$i+1] = @char[$i+1,$i];
7259             }
7260              
7261 0         0 # "\U\l" --> "\l\U"
7262             elsif (($char[$i] eq '\U') and ($char[$i+1] eq '\l')) {
7263             @char[$i,$i+1] = @char[$i+1,$i];
7264             }
7265              
7266 0         0 # octal escape sequence
7267             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
7268             $char[$i] = Elatin7::octchr($1);
7269             }
7270              
7271 1         4 # hexadecimal escape sequence
7272             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
7273             $char[$i] = Elatin7::hexchr($1);
7274             }
7275              
7276             # \b{...} --> b\{...}
7277             # \B{...} --> B\{...}
7278             # \N{CHARNAME} --> N\{CHARNAME}
7279             # \p{PROPERTY} --> p\{PROPERTY}
7280 1         4 # \P{PROPERTY} --> P\{PROPERTY}
7281             elsif ($char[$i] =~ /\A \\ ([bBNpP]) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
7282             $char[$i] = $1 . '\\' . $2;
7283             }
7284              
7285 0         0 # \p, \P, \X --> p, P, X
7286             elsif ($char[$i] =~ /\A \\ ( [pPX] ) \z/oxms) {
7287             $char[$i] = $1;
7288 0 50 100     0 }
    100 33        
    50 33        
    100 100        
    100          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    100          
    100          
    100          
    50          
    50          
    100          
    100          
7289              
7290             if (0) {
7291             }
7292 249         820  
7293 0 0 0     0 # join separated multiple-octet
    0 0        
    0 0        
      0        
      0        
      0        
7294 0         0 elsif ($char[$i] =~ /\A (?: \\ [0-7]{2,3} | \\x [0-9A-Fa-f]{1,2}) \z/oxms) {
7295             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)) {
7296             $char[$i] .= join '', splice @char, $i+1, 3;
7297 0         0 }
7298             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)) {
7299             $char[$i] .= join '', splice @char, $i+1, 2;
7300 0         0 }
7301             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)) {
7302             $char[$i] .= join '', splice @char, $i+1, 1;
7303             }
7304             }
7305              
7306 0         0 # open character class [...]
7307 3 50       7 elsif ($char[$i] eq '[') {
7308 3         10 my $left = $i;
7309             if ($char[$i+1] eq ']') {
7310 0         0 $i++;
7311 3 50       4 }
7312 7         12 while (1) {
7313             if (++$i > $#char) {
7314 0 100       0 die __FILE__, ": Unmatched [] in regexp\n";
7315 7         14 }
7316             if ($char[$i] eq ']') {
7317             my $right = $i;
7318 3 50       6  
7319 3         18 # [...]
  0         0  
7320             if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
7321             splice @char, $left, $right-$left+1, sprintf(q{@{[Elatin7::charlist_qr(%s,'%s')]}}, join(',', map {qq_stuff($delimiter,$end_delimiter,$_)} @char[$left+1..$right-1]), $modifier);
7322 0         0 }
7323             else {
7324             splice @char, $left, $right-$left+1, Elatin7::charlist_qr(@char[$left+1..$right-1], $modifier);
7325 3         21 }
7326 3         4  
7327             $i = $left;
7328             last;
7329             }
7330             }
7331             }
7332              
7333 3         10 # open character class [^...]
7334 0 0       0 elsif ($char[$i] eq '[^') {
7335 0         0 my $left = $i;
7336             if ($char[$i+1] eq ']') {
7337 0         0 $i++;
7338 0 0       0 }
7339 0         0 while (1) {
7340             if (++$i > $#char) {
7341 0 0       0 die __FILE__, ": Unmatched [] in regexp\n";
7342 0         0 }
7343             if ($char[$i] eq ']') {
7344             my $right = $i;
7345 0 0       0  
7346 0         0 # [^...]
  0         0  
7347             if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
7348             splice @char, $left, $right-$left+1, sprintf(q{@{[Elatin7::charlist_not_qr(%s,'%s')]}}, join(',', map {qq_stuff($delimiter,$end_delimiter,$_)} @char[$left+1..$right-1]), $modifier);
7349 0         0 }
7350             else {
7351             splice @char, $left, $right-$left+1, Elatin7::charlist_not_qr(@char[$left+1..$right-1], $modifier);
7352 0         0 }
7353 0         0  
7354             $i = $left;
7355             last;
7356             }
7357             }
7358             }
7359              
7360 0         0 # rewrite character class or escape character
7361             elsif (my $char = character_class($char[$i],$modifier)) {
7362             $char[$i] = $char;
7363             }
7364              
7365             # P.794 29.2.161. split
7366             # in Chapter 29: Functions
7367             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
7368              
7369             # P.951 split
7370             # in Chapter 27: Functions
7371             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
7372              
7373             # said "The //m modifier is assumed when you split on the pattern /^/",
7374             # but perl5.008 is not so. Therefore, this software adds //m.
7375             # (and so on)
7376              
7377 1         3 # split(m/^/) --> split(m/^/m)
7378             elsif (($char[$i] eq '^') and ($modifier !~ /m/oxms)) {
7379             $modifier .= 'm';
7380             }
7381              
7382 7 0       23 # /i modifier
7383 0         0 elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Elatin7::uc($char[$i]) ne Elatin7::fc($char[$i]))) {
7384             if (CORE::length(Elatin7::fc($char[$i])) == 1) {
7385             $char[$i] = '[' . Elatin7::uc($char[$i]) . Elatin7::fc($char[$i]) . ']';
7386 0         0 }
7387             else {
7388             $char[$i] = '(?:' . Elatin7::uc($char[$i]) . '|' . Elatin7::fc($char[$i]) . ')';
7389             }
7390             }
7391              
7392 0 0       0 # \u \l \U \L \F \Q \E
7393 0         0 elsif ($char[$i] =~ /\A ([<>]) \z/oxms) {
7394             if ($right_e < $left_e) {
7395             $char[$i] = '\\' . $char[$i];
7396             }
7397 0         0 }
7398 0         0 elsif ($char[$i] eq '\u') {
7399             $char[$i] = '@{[Elatin7::ucfirst qq<';
7400             $left_e++;
7401 0         0 }
7402 0         0 elsif ($char[$i] eq '\l') {
7403             $char[$i] = '@{[Elatin7::lcfirst qq<';
7404             $left_e++;
7405 0         0 }
7406 0         0 elsif ($char[$i] eq '\U') {
7407             $char[$i] = '@{[Elatin7::uc qq<';
7408             $left_e++;
7409 0         0 }
7410 0         0 elsif ($char[$i] eq '\L') {
7411             $char[$i] = '@{[Elatin7::lc qq<';
7412             $left_e++;
7413 0         0 }
7414 0         0 elsif ($char[$i] eq '\F') {
7415             $char[$i] = '@{[Elatin7::fc qq<';
7416             $left_e++;
7417 0         0 }
7418 0         0 elsif ($char[$i] eq '\Q') {
7419             $char[$i] = '@{[CORE::quotemeta qq<';
7420             $left_e++;
7421 0 0       0 }
7422 0         0 elsif ($char[$i] eq '\E') {
7423 0         0 if ($right_e < $left_e) {
7424             $char[$i] = '>]}';
7425             $right_e++;
7426 0         0 }
7427             else {
7428             $char[$i] = '';
7429             }
7430 0         0 }
7431 0 0       0 elsif ($char[$i] eq '\Q') {
7432 0         0 while (1) {
7433             if (++$i > $#char) {
7434 0 0       0 last;
7435 0         0 }
7436             if ($char[$i] eq '\E') {
7437             last;
7438             }
7439             }
7440             }
7441             elsif ($char[$i] eq '\E') {
7442             }
7443              
7444 0 0       0 # $0 --> $0
7445 0         0 elsif ($char[$i] =~ /\A \$ 0 \z/oxms) {
7446             if ($ignorecase) {
7447             $char[$i] = '@{[Elatin7::ignorecase(' . $char[$i] . ')]}';
7448             }
7449 0 0       0 }
7450 0         0 elsif ($char[$i] =~ /\A \$ \{ (?>\s*) 0 (?>\s*) \} \z/oxms) {
7451             if ($ignorecase) {
7452             $char[$i] = '@{[Elatin7::ignorecase(' . $char[$i] . ')]}';
7453             }
7454             }
7455              
7456             # $$ --> $$
7457             elsif ($char[$i] =~ /\A \$\$ \z/oxms) {
7458             }
7459              
7460             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
7461 0         0 # $1, $2, $3 --> $1, $2, $3 otherwise
7462 0 0       0 elsif ($char[$i] =~ /\A \$ ((?>[1-9][0-9]*)) \z/oxms) {
7463 0         0 $char[$i] = e_capture($1);
7464             if ($ignorecase) {
7465             $char[$i] = '@{[Elatin7::ignorecase(' . $char[$i] . ')]}';
7466             }
7467 0         0 }
7468 0 0       0 elsif ($char[$i] =~ /\A \$ \{ (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} \z/oxms) {
7469 0         0 $char[$i] = e_capture($1);
7470             if ($ignorecase) {
7471             $char[$i] = '@{[Elatin7::ignorecase(' . $char[$i] . ')]}';
7472             }
7473             }
7474              
7475 0         0 # $$foo[ ... ] --> $ $foo->[ ... ]
7476 0 0       0 elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \[ (?:$qq_bracket)*? \] ) \z/oxms) {
7477 0         0 $char[$i] = e_capture($1.'->'.$2);
7478             if ($ignorecase) {
7479             $char[$i] = '@{[Elatin7::ignorecase(' . $char[$i] . ')]}';
7480             }
7481             }
7482              
7483 0         0 # $$foo{ ... } --> $ $foo->{ ... }
7484 0 0       0 elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \{ (?:$qq_brace)*? \} ) \z/oxms) {
7485 0         0 $char[$i] = e_capture($1.'->'.$2);
7486             if ($ignorecase) {
7487             $char[$i] = '@{[Elatin7::ignorecase(' . $char[$i] . ')]}';
7488             }
7489             }
7490              
7491 0         0 # $$foo
7492 0 0       0 elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) \z/oxms) {
7493 0         0 $char[$i] = e_capture($1);
7494             if ($ignorecase) {
7495             $char[$i] = '@{[Elatin7::ignorecase(' . $char[$i] . ')]}';
7496             }
7497             }
7498              
7499 0 50       0 # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Elatin7::PREMATCH()
7500 12         37 elsif ($char[$i] =~ /\A ( \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} ) \z/oxmsgc) {
7501             if ($ignorecase) {
7502             $char[$i] = '@{[Elatin7::ignorecase(Elatin7::PREMATCH())]}';
7503 0         0 }
7504             else {
7505             $char[$i] = '@{[Elatin7::PREMATCH()]}';
7506             }
7507             }
7508              
7509 12 50       51 # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Elatin7::MATCH()
7510 12         32 elsif ($char[$i] =~ /\A ( \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} ) \z/oxmsgc) {
7511             if ($ignorecase) {
7512             $char[$i] = '@{[Elatin7::ignorecase(Elatin7::MATCH())]}';
7513 0         0 }
7514             else {
7515             $char[$i] = '@{[Elatin7::MATCH()]}';
7516             }
7517             }
7518              
7519 12 50       51 # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Elatin7::POSTMATCH()
7520 9         25 elsif ($char[$i] =~ /\A ( \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} ) \z/oxmsgc) {
7521             if ($ignorecase) {
7522             $char[$i] = '@{[Elatin7::ignorecase(Elatin7::POSTMATCH())]}';
7523 0         0 }
7524             else {
7525             $char[$i] = '@{[Elatin7::POSTMATCH()]}';
7526             }
7527             }
7528              
7529 9 0       40 # ${ foo }
7530 0         0 elsif ($char[$i] =~ /\A \$ (?>\s*) \{ ((?> \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* )) \} \z/oxms) {
7531             if ($ignorecase) {
7532             $char[$i] = '@{[Elatin7::ignorecase(' . $1 . ')]}';
7533             }
7534             }
7535              
7536 0         0 # ${ ... }
7537 0 0       0 elsif ($char[$i] =~ /\A \$ (?>\s*) \{ ( .+ ) \} \z/oxms) {
7538 0         0 $char[$i] = e_capture($1);
7539             if ($ignorecase) {
7540             $char[$i] = '@{[Elatin7::ignorecase(' . $char[$i] . ')]}';
7541             }
7542             }
7543              
7544 0         0 # $scalar or @array
7545 3 50       11 elsif ($char[$i] =~ /\A [\$\@].+ /oxms) {
7546 3         13 $char[$i] = e_string($char[$i]);
7547             if ($ignorecase) {
7548             $char[$i] = '@{[Elatin7::ignorecase(' . $char[$i] . ')]}';
7549             }
7550             }
7551              
7552 0 50       0 # quote character before ? + * {
7553             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
7554             if ($char[$i-1] =~ /\A (?:[\x00-\xFF]|\\[0-7]{2,3}|\\x[0-9-A-Fa-f]{1,2}) \z/oxms) {
7555 1         8 }
7556             else {
7557             $char[$i-1] = '(?:' . $char[$i-1] . ')';
7558             }
7559             }
7560             }
7561 0         0  
7562 74 50       210 # make regexp string
7563 74         165 $modifier =~ tr/i//d;
7564             if ($left_e > $right_e) {
7565 0         0 return join '', 'Elatin7::split', $ope, $delimiter, @char, '>]}' x ($left_e - $right_e), $end_delimiter, $modifier;
7566             }
7567             return join '', 'Elatin7::split', $ope, $delimiter, @char, $end_delimiter, $modifier;
7568             }
7569              
7570             #
7571             # escape regexp of split qr''
7572 74     0 0 731 #
7573 0   0       sub e_split_q {
7574             my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
7575 0           $modifier ||= '';
7576 0 0          
7577 0           $modifier =~ tr/p//d;
7578 0           if ($modifier =~ /([adlu])/oxms) {
7579 0 0         my $line = 0;
7580 0           for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
7581 0           if ($filename ne __FILE__) {
7582             $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
7583             last;
7584 0           }
7585             }
7586             die qq{Unsupported modifier "$1" used at line $line.\n};
7587 0           }
7588              
7589             $slash = 'div';
7590 0 0          
7591 0           # /b /B modifier
7592             if ($modifier =~ tr/bB//d) {
7593             return join '', 'split', $ope, $delimiter, $string, $end_delimiter, $modifier;
7594 0 0         }
7595              
7596             my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
7597 0            
7598             # split regexp
7599             my @char = $string =~ /\G((?>
7600             [^\\\[] |
7601             [\x00-\xFF] |
7602             \[\^ |
7603             \[\: (?>[a-z]+) \:\] |
7604             \[\:\^ (?>[a-z]+) \:\] |
7605             \\ (?:$q_char) |
7606             (?:$q_char)
7607             ))/oxmsg;
7608 0            
7609 0 0 0       # unescape character
    0 0        
    0 0        
    0 0        
    0          
    0          
7610             for (my $i=0; $i <= $#char; $i++) {
7611             if (0) {
7612             }
7613 0            
7614 0           # open character class [...]
7615 0 0         elsif ($char[$i] eq '[') {
7616 0           my $left = $i;
7617             if ($char[$i+1] eq ']') {
7618 0           $i++;
7619 0 0         }
7620 0           while (1) {
7621             if (++$i > $#char) {
7622 0 0         die __FILE__, ": Unmatched [] in regexp\n";
7623 0           }
7624             if ($char[$i] eq ']') {
7625             my $right = $i;
7626 0            
7627             # [...]
7628 0           splice @char, $left, $right-$left+1, Elatin7::charlist_qr(@char[$left+1..$right-1], $modifier);
7629 0            
7630             $i = $left;
7631             last;
7632             }
7633             }
7634             }
7635              
7636 0           # open character class [^...]
7637 0 0         elsif ($char[$i] eq '[^') {
7638 0           my $left = $i;
7639             if ($char[$i+1] eq ']') {
7640 0           $i++;
7641 0 0         }
7642 0           while (1) {
7643             if (++$i > $#char) {
7644 0 0         die __FILE__, ": Unmatched [] in regexp\n";
7645 0           }
7646             if ($char[$i] eq ']') {
7647             my $right = $i;
7648 0            
7649             # [^...]
7650 0           splice @char, $left, $right-$left+1, Elatin7::charlist_not_qr(@char[$left+1..$right-1], $modifier);
7651 0            
7652             $i = $left;
7653             last;
7654             }
7655             }
7656             }
7657              
7658 0           # rewrite character class or escape character
7659             elsif (my $char = character_class($char[$i],$modifier)) {
7660             $char[$i] = $char;
7661             }
7662              
7663 0           # split(m/^/) --> split(m/^/m)
7664             elsif (($char[$i] eq '^') and ($modifier !~ /m/oxms)) {
7665             $modifier .= 'm';
7666             }
7667              
7668 0 0         # /i modifier
7669 0           elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Elatin7::uc($char[$i]) ne Elatin7::fc($char[$i]))) {
7670             if (CORE::length(Elatin7::fc($char[$i])) == 1) {
7671             $char[$i] = '[' . Elatin7::uc($char[$i]) . Elatin7::fc($char[$i]) . ']';
7672 0           }
7673             else {
7674             $char[$i] = '(?:' . Elatin7::uc($char[$i]) . '|' . Elatin7::fc($char[$i]) . ')';
7675             }
7676             }
7677              
7678 0 0         # quote character before ? + * {
7679             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
7680             if ($char[$i-1] =~ /\A [\x00-\xFF] \z/oxms) {
7681 0           }
7682             else {
7683             $char[$i-1] = '(?:' . $char[$i-1] . ')';
7684             }
7685             }
7686 0           }
7687 0            
7688             $modifier =~ tr/i//d;
7689             return join '', 'Elatin7::split', $ope, $delimiter, @char, $end_delimiter, $modifier;
7690             }
7691              
7692             #
7693             # instead of Carp::carp
7694 0     0 0   #
7695 0           sub carp {
7696             my($package,$filename,$line) = caller(1);
7697             print STDERR "@_ at $filename line $line.\n";
7698             }
7699              
7700             #
7701             # instead of Carp::croak
7702 0     0 0   #
7703 0           sub croak {
7704 0           my($package,$filename,$line) = caller(1);
7705             print STDERR "@_ at $filename line $line.\n";
7706             die "\n";
7707             }
7708              
7709             #
7710             # instead of Carp::cluck
7711 0     0 0   #
7712 0           sub cluck {
7713 0           my $i = 0;
7714 0           my @cluck = ();
7715 0           while (my($package,$filename,$line,$subroutine) = caller($i)) {
7716             push @cluck, "[$i] $filename($line) $package::$subroutine\n";
7717 0           $i++;
7718 0           }
7719 0           print STDERR CORE::reverse @cluck;
7720             print STDERR "\n";
7721             print STDERR @_;
7722             }
7723              
7724             #
7725             # instead of Carp::confess
7726 0     0 0   #
7727 0           sub confess {
7728 0           my $i = 0;
7729 0           my @confess = ();
7730 0           while (my($package,$filename,$line,$subroutine) = caller($i)) {
7731             push @confess, "[$i] $filename($line) $package::$subroutine\n";
7732 0           $i++;
7733 0           }
7734 0           print STDERR CORE::reverse @confess;
7735 0           print STDERR "\n";
7736             print STDERR @_;
7737             die "\n";
7738             }
7739              
7740             1;
7741              
7742             __END__