File Coverage

blib/lib/Elatin7.pm
Criterion Covered Total %
statement 905 2814 32.1
branch 890 2412 36.9
condition 98 355 27.6
subroutine 54 113 47.7
pod 7 74 9.4
total 1954 5768 33.8


line stmt bran cond sub pod time code
1             package Elatin7;
2 206     206   1109 use strict;
  206         325  
  206         7417  
3 206 50   206   3371 BEGIN { $INC{'warnings.pm'} = '' if $] < 5.006 } use warnings;
  206     206   866  
  206         310  
  206         5963  
4             ######################################################################
5             #
6             # Elatin7 - Run-time routines for Latin7.pm
7             #
8             # http://search.cpan.org/dist/Char-Latin7/
9             #
10             # Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2018, 2019 INABA Hitoshi
11             ######################################################################
12              
13 206     206   2974 use 5.00503; # Galapagos Consensus 1998 for primetools
  206         671  
14             # use 5.008001; # Lancaster Consensus 2013 for toolchains
15              
16             # 12.3. Delaying use Until Runtime
17             # in Chapter 12. Packages, Libraries, and Modules
18             # of ISBN 0-596-00313-7 Perl Cookbook, 2nd Edition.
19             # (and so on)
20              
21             # Version numbers should be boring
22             # http://www.dagolden.com/index.php/369/version-numbers-should-be-boring/
23             # For the impatient, the disinterested or those who just want to follow
24             # a recipe, my advice for all modules is this:
25             # our $VERSION = "0.001"; # or "0.001_001" for a dev release
26             # $VERSION = eval $VERSION; # No!! because '1.10' makes '1.1'
27              
28 206     206   1008 use vars qw($VERSION);
  206         401  
  206         25412  
29             $VERSION = '1.22';
30             $VERSION = $VERSION;
31              
32             BEGIN {
33 206 50   206   1182 if ($^X =~ / jperl /oxmsi) {
34 0         0 die __FILE__, ": needs perl(not jperl) 5.00503 or later. (\$^X==$^X)\n";
35             }
36 206         336 if (CORE::ord('A') == 193) {
37             die __FILE__, ": is not US-ASCII script (may be EBCDIC or EBCDIK script).\n";
38             }
39 206         24264 if (CORE::ord('A') != 0x41) {
40             die __FILE__, ": is not US-ASCII script (must be US-ASCII script).\n";
41             }
42             }
43              
44             BEGIN {
45              
46             # instead of utf8.pm
47 206     206   12420 CORE::eval q{
  206     206   1189  
  206     92   380  
  206         20850  
  0         0  
  0         0  
  0         0  
  0         0  
48             no warnings qw(redefine);
49             *utf8::upgrade = sub { CORE::length $_[0] };
50             *utf8::downgrade = sub { 1 };
51             *utf8::encode = sub { };
52             *utf8::decode = sub { 1 };
53             *utf8::is_utf8 = sub { };
54             *utf8::valid = sub { 1 };
55             };
56 206 50       71529 if ($@) {
57 0         0 *utf8::upgrade = sub { CORE::length $_[0] };
  0         0  
58 0         0 *utf8::downgrade = sub { 1 };
  0         0  
59 0         0 *utf8::encode = sub { };
60 0         0 *utf8::decode = sub { 1 };
  0         0  
61 0         0 *utf8::is_utf8 = sub { };
62 0         0 *utf8::valid = sub { 1 };
  0         0  
63             }
64             }
65              
66             # instead of Symbol.pm
67 0         0 BEGIN {
68             sub gensym () {
69 0 0   0 0 0 if ($] < 5.006) {
70 0         0 return \do { local *_ };
  0         0  
71             }
72             else {
73 0         0 return undef;
74             }
75             }
76              
77             sub qualify ($$) {
78 0     0 0 0 my($name) = @_;
79              
80 0 0       0 if (ref $name) {
    0          
    0          
    0          
    0          
    0          
    0          
81 0         0 return $name;
82             }
83             elsif (Elatin7::index($name,'::') >= 0) {
84 0         0 return $name;
85             }
86             elsif (Elatin7::index($name,"'") >= 0) {
87 0         0 return $name;
88             }
89              
90             # special character, "^xyz"
91             elsif ($name =~ /\A \^ [ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_]+ \z/x) {
92              
93             # RGS 2001-11-05 : translate leading ^X to control-char
94 0         0 $name =~ s{\A \^ ([ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_]) }{'qq(\c'.$1.')'}xee;
  0         0  
95 0         0 return 'main::' . $name;
96             }
97              
98             # Global names
99             elsif ($name =~ /\A (?: ARGV | ARGVOUT | ENV | INC | SIG | STDERR | STDIN | STDOUT ) \z/x) {
100 0         0 return 'main::' . $name;
101             }
102              
103             # or other
104             elsif ($name =~ /\A [^ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz] \z/x) {
105 0         0 return 'main::' . $name;
106             }
107              
108             elsif (defined $_[1]) {
109 0         0 return $_[1] . '::' . $name;
110             }
111             else {
112 0         0 return (caller)[0] . '::' . $name;
113             }
114             }
115              
116             sub qualify_to_ref ($;$) {
117 0 0   0 0 0 if (defined $_[1]) {
118 206     206   1376 no strict qw(refs);
  206         347  
  206         12524  
119 0         0 return \*{ qualify $_[0], $_[1] };
  0         0  
120             }
121             else {
122 206     206   1183 no strict qw(refs);
  206     0   378  
  206         32733  
123 0         0 return \*{ qualify $_[0], (caller)[0] };
  0         0  
124             }
125             }
126             }
127              
128             # P.714 29.2.39. flock
129             # in Chapter 29: Functions
130             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
131              
132             # P.863 flock
133             # in Chapter 27: Functions
134             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
135              
136             sub LOCK_SH() {1}
137             sub LOCK_EX() {2}
138             sub LOCK_UN() {8}
139             sub LOCK_NB() {4}
140              
141             # instead of Carp.pm
142             sub carp;
143             sub croak;
144             sub cluck;
145             sub confess;
146              
147             # 6.18. Matching Multiple-Byte Characters
148             # in Chapter 6. Pattern Matching
149             # of ISBN 978-1-56592-243-3 Perl Perl Cookbook.
150             # (and so on)
151              
152             # regexp of character
153             my $your_char = q{[\x00-\xFF]};
154 206     206   1261 use vars qw($qq_char); $qq_char = qr/\\c[\x40-\x5F]|\\?(?:$your_char)/oxms;
  206         370  
  206         11277  
155 206     206   1154 use vars qw($q_char); $q_char = qr/$your_char/oxms;
  206         422  
  206         298498  
156              
157             #
158             # Latin-7 character range per length
159             #
160             my %range_tr = ();
161              
162             #
163             # Latin-7 case conversion
164             #
165             my %lc = ();
166             @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)} =
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             my %uc = ();
169             @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)} =
170             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);
171             my %fc = ();
172             @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)} =
173             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);
174              
175             if (0) {
176             }
177              
178             elsif (__PACKAGE__ =~ / \b Elatin7 \z/oxms) {
179             %range_tr = (
180             1 => [ [0x00..0xFF],
181             ],
182             );
183              
184             %lc = (%lc,
185             "\xA8" => "\xB8", # LATIN LETTER O WITH STROKE
186             "\xAA" => "\xBA", # LATIN LETTER R WITH CEDILLA
187             "\xAF" => "\xBF", # LATIN LETTER AE
188             "\xC0" => "\xE0", # LATIN LETTER A WITH OGONEK
189             "\xC1" => "\xE1", # LATIN LETTER I WITH OGONEK
190             "\xC2" => "\xE2", # LATIN LETTER A WITH MACRON
191             "\xC3" => "\xE3", # LATIN LETTER C WITH ACUTE
192             "\xC4" => "\xE4", # LATIN LETTER A WITH DIAERESIS
193             "\xC5" => "\xE5", # LATIN LETTER A WITH RING ABOVE
194             "\xC6" => "\xE6", # LATIN LETTER E WITH OGONEK
195             "\xC7" => "\xE7", # LATIN LETTER E WITH MACRON
196             "\xC8" => "\xE8", # LATIN LETTER C WITH CARON
197             "\xC9" => "\xE9", # LATIN LETTER E WITH ACUTE
198             "\xCA" => "\xEA", # LATIN LETTER Z WITH ACUTE
199             "\xCB" => "\xEB", # LATIN LETTER E WITH DOT ABOVE
200             "\xCC" => "\xEC", # LATIN LETTER G WITH CEDILLA
201             "\xCD" => "\xED", # LATIN LETTER K WITH CEDILLA
202             "\xCE" => "\xEE", # LATIN LETTER I WITH MACRON
203             "\xCF" => "\xEF", # LATIN LETTER L WITH CEDILLA
204             "\xD0" => "\xF0", # LATIN LETTER S WITH CARON
205             "\xD1" => "\xF1", # LATIN LETTER N WITH ACUTE
206             "\xD2" => "\xF2", # LATIN LETTER N WITH CEDILLA
207             "\xD3" => "\xF3", # LATIN LETTER O WITH ACUTE
208             "\xD4" => "\xF4", # LATIN LETTER O WITH MACRON
209             "\xD5" => "\xF5", # LATIN LETTER O WITH TILDE
210             "\xD6" => "\xF6", # LATIN LETTER O WITH DIAERESIS
211             "\xD8" => "\xF8", # LATIN LETTER U WITH OGONEK
212             "\xD9" => "\xF9", # LATIN LETTER L WITH STROKE
213             "\xDA" => "\xFA", # LATIN LETTER S WITH ACUTE
214             "\xDB" => "\xFB", # LATIN LETTER U WITH MACRON
215             "\xDC" => "\xFC", # LATIN LETTER U WITH DIAERESIS
216             "\xDD" => "\xFD", # LATIN LETTER Z WITH DOT ABOVE
217             "\xDE" => "\xFE", # LATIN LETTER Z WITH CARON
218             );
219              
220             %uc = (%uc,
221             "\xB8" => "\xA8", # LATIN LETTER O WITH STROKE
222             "\xBA" => "\xAA", # LATIN LETTER R WITH CEDILLA
223             "\xBF" => "\xAF", # LATIN LETTER AE
224             "\xE0" => "\xC0", # LATIN LETTER A WITH OGONEK
225             "\xE1" => "\xC1", # LATIN LETTER I WITH OGONEK
226             "\xE2" => "\xC2", # LATIN LETTER A WITH MACRON
227             "\xE3" => "\xC3", # LATIN LETTER C WITH ACUTE
228             "\xE4" => "\xC4", # LATIN LETTER A WITH DIAERESIS
229             "\xE5" => "\xC5", # LATIN LETTER A WITH RING ABOVE
230             "\xE6" => "\xC6", # LATIN LETTER E WITH OGONEK
231             "\xE7" => "\xC7", # LATIN LETTER E WITH MACRON
232             "\xE8" => "\xC8", # LATIN LETTER C WITH CARON
233             "\xE9" => "\xC9", # LATIN LETTER E WITH ACUTE
234             "\xEA" => "\xCA", # LATIN LETTER Z WITH ACUTE
235             "\xEB" => "\xCB", # LATIN LETTER E WITH DOT ABOVE
236             "\xEC" => "\xCC", # LATIN LETTER G WITH CEDILLA
237             "\xED" => "\xCD", # LATIN LETTER K WITH CEDILLA
238             "\xEE" => "\xCE", # LATIN LETTER I WITH MACRON
239             "\xEF" => "\xCF", # LATIN LETTER L WITH CEDILLA
240             "\xF0" => "\xD0", # LATIN LETTER S WITH CARON
241             "\xF1" => "\xD1", # LATIN LETTER N WITH ACUTE
242             "\xF2" => "\xD2", # LATIN LETTER N WITH CEDILLA
243             "\xF3" => "\xD3", # LATIN LETTER O WITH ACUTE
244             "\xF4" => "\xD4", # LATIN LETTER O WITH MACRON
245             "\xF5" => "\xD5", # LATIN LETTER O WITH TILDE
246             "\xF6" => "\xD6", # LATIN LETTER O WITH DIAERESIS
247             "\xF8" => "\xD8", # LATIN LETTER U WITH OGONEK
248             "\xF9" => "\xD9", # LATIN LETTER L WITH STROKE
249             "\xFA" => "\xDA", # LATIN LETTER S WITH ACUTE
250             "\xFB" => "\xDB", # LATIN LETTER U WITH MACRON
251             "\xFC" => "\xDC", # LATIN LETTER U WITH DIAERESIS
252             "\xFD" => "\xDD", # LATIN LETTER Z WITH DOT ABOVE
253             "\xFE" => "\xDE", # LATIN LETTER Z WITH CARON
254             );
255              
256             %fc = (%fc,
257             "\xA8" => "\xB8", # LATIN CAPITAL LETTER O WITH STROKE --> LATIN SMALL LETTER O WITH STROKE
258             "\xAA" => "\xBA", # LATIN CAPITAL LETTER R WITH CEDILLA --> LATIN SMALL LETTER R WITH CEDILLA
259             "\xAF" => "\xBF", # LATIN CAPITAL LETTER AE --> LATIN SMALL LETTER AE
260             "\xC0" => "\xE0", # LATIN CAPITAL LETTER A WITH OGONEK --> LATIN SMALL LETTER A WITH OGONEK
261             "\xC1" => "\xE1", # LATIN CAPITAL LETTER I WITH OGONEK --> LATIN SMALL LETTER I WITH OGONEK
262             "\xC2" => "\xE2", # LATIN CAPITAL LETTER A WITH MACRON --> LATIN SMALL LETTER A WITH MACRON
263             "\xC3" => "\xE3", # LATIN CAPITAL LETTER C WITH ACUTE --> LATIN SMALL LETTER C WITH ACUTE
264             "\xC4" => "\xE4", # LATIN CAPITAL LETTER A WITH DIAERESIS --> LATIN SMALL LETTER A WITH DIAERESIS
265             "\xC5" => "\xE5", # LATIN CAPITAL LETTER A WITH RING ABOVE --> LATIN SMALL LETTER A WITH RING ABOVE
266             "\xC6" => "\xE6", # LATIN CAPITAL LETTER E WITH OGONEK --> LATIN SMALL LETTER E WITH OGONEK
267             "\xC7" => "\xE7", # LATIN CAPITAL LETTER E WITH MACRON --> LATIN SMALL LETTER E WITH MACRON
268             "\xC8" => "\xE8", # LATIN CAPITAL LETTER C WITH CARON --> LATIN SMALL LETTER C WITH CARON
269             "\xC9" => "\xE9", # LATIN CAPITAL LETTER E WITH ACUTE --> LATIN SMALL LETTER E WITH ACUTE
270             "\xCA" => "\xEA", # LATIN CAPITAL LETTER Z WITH ACUTE --> LATIN SMALL LETTER Z WITH ACUTE
271             "\xCB" => "\xEB", # LATIN CAPITAL LETTER E WITH DOT ABOVE --> LATIN SMALL LETTER E WITH DOT ABOVE
272             "\xCC" => "\xEC", # LATIN CAPITAL LETTER G WITH CEDILLA --> LATIN SMALL LETTER G WITH CEDILLA
273             "\xCD" => "\xED", # LATIN CAPITAL LETTER K WITH CEDILLA --> LATIN SMALL LETTER K WITH CEDILLA
274             "\xCE" => "\xEE", # LATIN CAPITAL LETTER I WITH MACRON --> LATIN SMALL LETTER I WITH MACRON
275             "\xCF" => "\xEF", # LATIN CAPITAL LETTER L WITH CEDILLA --> LATIN SMALL LETTER L WITH CEDILLA
276             "\xD0" => "\xF0", # LATIN CAPITAL LETTER S WITH CARON --> LATIN SMALL LETTER S WITH CARON
277             "\xD1" => "\xF1", # LATIN CAPITAL LETTER N WITH ACUTE --> LATIN SMALL LETTER N WITH ACUTE
278             "\xD2" => "\xF2", # LATIN CAPITAL LETTER N WITH CEDILLA --> LATIN SMALL LETTER N WITH CEDILLA
279             "\xD3" => "\xF3", # LATIN CAPITAL LETTER O WITH ACUTE --> LATIN SMALL LETTER O WITH ACUTE
280             "\xD4" => "\xF4", # LATIN CAPITAL LETTER O WITH MACRON --> LATIN SMALL LETTER O WITH MACRON
281             "\xD5" => "\xF5", # LATIN CAPITAL LETTER O WITH TILDE --> LATIN SMALL LETTER O WITH TILDE
282             "\xD6" => "\xF6", # LATIN CAPITAL LETTER O WITH DIAERESIS --> LATIN SMALL LETTER O WITH DIAERESIS
283             "\xD8" => "\xF8", # LATIN CAPITAL LETTER U WITH OGONEK --> LATIN SMALL LETTER U WITH OGONEK
284             "\xD9" => "\xF9", # LATIN CAPITAL LETTER L WITH STROKE --> LATIN SMALL LETTER L WITH STROKE
285             "\xDA" => "\xFA", # LATIN CAPITAL LETTER S WITH ACUTE --> LATIN SMALL LETTER S WITH ACUTE
286             "\xDB" => "\xFB", # LATIN CAPITAL LETTER U WITH MACRON --> LATIN SMALL LETTER U WITH MACRON
287             "\xDC" => "\xFC", # LATIN CAPITAL LETTER U WITH DIAERESIS --> LATIN SMALL LETTER U WITH DIAERESIS
288             "\xDD" => "\xFD", # LATIN CAPITAL LETTER Z WITH DOT ABOVE --> LATIN SMALL LETTER Z WITH DOT ABOVE
289             "\xDE" => "\xFE", # LATIN CAPITAL LETTER Z WITH CARON --> LATIN SMALL LETTER Z WITH CARON
290             "\xDF" => "\x73\x73", # LATIN SMALL LETTER SHARP S --> LATIN SMALL LETTER S, LATIN SMALL LETTER S
291             );
292             }
293              
294             else {
295             croak "Don't know my package name '@{[__PACKAGE__]}'";
296             }
297              
298             #
299             # @ARGV wildcard globbing
300             #
301             sub import {
302              
303 0 0   0   0 if ($^O =~ /\A (?: MSWin32 | NetWare | symbian | dos ) \z/oxms) {
304 0         0 my @argv = ();
305 0         0 for (@ARGV) {
306              
307             # has space
308 0 0       0 if (/\A (?:$q_char)*? [ ] /oxms) {
    0          
309 0 0       0 if (my @glob = Elatin7::glob(qq{"$_"})) {
310 0         0 push @argv, @glob;
311             }
312             else {
313 0         0 push @argv, $_;
314             }
315             }
316              
317             # has wildcard metachar
318             elsif (/\A (?:$q_char)*? [*?] /oxms) {
319 0 0       0 if (my @glob = Elatin7::glob($_)) {
320 0         0 push @argv, @glob;
321             }
322             else {
323 0         0 push @argv, $_;
324             }
325             }
326              
327             # no wildcard globbing
328             else {
329 0         0 push @argv, $_;
330             }
331             }
332 0         0 @ARGV = @argv;
333             }
334              
335 0         0 *Char::ord = \&Latin7::ord;
336 0         0 *Char::ord_ = \&Latin7::ord_;
337 0         0 *Char::reverse = \&Latin7::reverse;
338 0         0 *Char::getc = \&Latin7::getc;
339 0         0 *Char::length = \&Latin7::length;
340 0         0 *Char::substr = \&Latin7::substr;
341 0         0 *Char::index = \&Latin7::index;
342 0         0 *Char::rindex = \&Latin7::rindex;
343 0         0 *Char::eval = \&Latin7::eval;
344 0         0 *Char::escape = \&Latin7::escape;
345 0         0 *Char::escape_token = \&Latin7::escape_token;
346 0         0 *Char::escape_script = \&Latin7::escape_script;
347             }
348              
349             # P.230 Care with Prototypes
350             # in Chapter 6: Subroutines
351             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
352             #
353             # If you aren't careful, you can get yourself into trouble with prototypes.
354             # But if you are careful, you can do a lot of neat things with them. This is
355             # all very powerful, of course, and should only be used in moderation to make
356             # the world a better place.
357              
358             # P.332 Care with Prototypes
359             # in Chapter 7: Subroutines
360             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
361             #
362             # If you aren't careful, you can get yourself into trouble with prototypes.
363             # But if you are careful, you can do a lot of neat things with them. This is
364             # all very powerful, of course, and should only be used in moderation to make
365             # the world a better place.
366              
367             #
368             # Prototypes of subroutines
369             #
370       0     sub unimport {}
371             sub Elatin7::split(;$$$);
372             sub Elatin7::tr($$$$;$);
373             sub Elatin7::chop(@);
374             sub Elatin7::index($$;$);
375             sub Elatin7::rindex($$;$);
376             sub Elatin7::lcfirst(@);
377             sub Elatin7::lcfirst_();
378             sub Elatin7::lc(@);
379             sub Elatin7::lc_();
380             sub Elatin7::ucfirst(@);
381             sub Elatin7::ucfirst_();
382             sub Elatin7::uc(@);
383             sub Elatin7::uc_();
384             sub Elatin7::fc(@);
385             sub Elatin7::fc_();
386             sub Elatin7::ignorecase;
387             sub Elatin7::classic_character_class;
388             sub Elatin7::capture;
389             sub Elatin7::chr(;$);
390             sub Elatin7::chr_();
391             sub Elatin7::glob($);
392             sub Elatin7::glob_();
393              
394             sub Latin7::ord(;$);
395             sub Latin7::ord_();
396             sub Latin7::reverse(@);
397             sub Latin7::getc(;*@);
398             sub Latin7::length(;$);
399             sub Latin7::substr($$;$$);
400             sub Latin7::index($$;$);
401             sub Latin7::rindex($$;$);
402             sub Latin7::escape(;$);
403              
404             #
405             # Regexp work
406             #
407 206         14843 use vars qw(
408             $re_a
409             $re_t
410             $re_n
411             $re_r
412 206     206   1448 );
  206         386  
413              
414             #
415             # Character class
416             #
417 206         1693653 use vars qw(
418             $dot
419             $dot_s
420             $eD
421             $eS
422             $eW
423             $eH
424             $eV
425             $eR
426             $eN
427             $not_alnum
428             $not_alpha
429             $not_ascii
430             $not_blank
431             $not_cntrl
432             $not_digit
433             $not_graph
434             $not_lower
435             $not_lower_i
436             $not_print
437             $not_punct
438             $not_space
439             $not_upper
440             $not_upper_i
441             $not_word
442             $not_xdigit
443             $eb
444             $eB
445 206     206   1174 );
  206         354  
446              
447             ${Elatin7::dot} = qr{(?>[^\x0A])};
448             ${Elatin7::dot_s} = qr{(?>[\x00-\xFF])};
449             ${Elatin7::eD} = qr{(?>[^0-9])};
450              
451             # Vertical tabs are now whitespace
452             # \s in a regex now matches a vertical tab in all circumstances.
453             # http://search.cpan.org/dist/perl-5.18.0/pod/perldelta.pod#Vertical_tabs_are_now_whitespace
454             # ${Elatin7::eS} = qr{(?>[^\x09\x0A \x0C\x0D\x20])};
455             # ${Elatin7::eS} = qr{(?>[^\x09\x0A\x0B\x0C\x0D\x20])};
456             ${Elatin7::eS} = qr{(?>[^\s])};
457              
458             ${Elatin7::eW} = qr{(?>[^0-9A-Z_a-z])};
459             ${Elatin7::eH} = qr{(?>[^\x09\x20])};
460             ${Elatin7::eV} = qr{(?>[^\x0A\x0B\x0C\x0D])};
461             ${Elatin7::eR} = qr{(?>\x0D\x0A|[\x0A\x0D])};
462             ${Elatin7::eN} = qr{(?>[^\x0A])};
463             ${Elatin7::not_alnum} = qr{(?>[^\x30-\x39\x41-\x5A\x61-\x7A])};
464             ${Elatin7::not_alpha} = qr{(?>[^\x41-\x5A\x61-\x7A])};
465             ${Elatin7::not_ascii} = qr{(?>[^\x00-\x7F])};
466             ${Elatin7::not_blank} = qr{(?>[^\x09\x20])};
467             ${Elatin7::not_cntrl} = qr{(?>[^\x00-\x1F\x7F])};
468             ${Elatin7::not_digit} = qr{(?>[^\x30-\x39])};
469             ${Elatin7::not_graph} = qr{(?>[^\x21-\x7F])};
470             ${Elatin7::not_lower} = qr{(?>[^\x61-\x7A])};
471             ${Elatin7::not_lower_i} = qr{(?>[^\x41-\x5A\x61-\x7A])}; # Perl 5.16 compatible
472             # ${Elatin7::not_lower_i} = qr{(?>[\x00-\xFF])}; # older Perl compatible
473             ${Elatin7::not_print} = qr{(?>[^\x20-\x7F])};
474             ${Elatin7::not_punct} = qr{(?>[^\x21-\x2F\x3A-\x3F\x40\x5B-\x5F\x60\x7B-\x7E])};
475             ${Elatin7::not_space} = qr{(?>[^\s\x0B])};
476             ${Elatin7::not_upper} = qr{(?>[^\x41-\x5A])};
477             ${Elatin7::not_upper_i} = qr{(?>[^\x41-\x5A\x61-\x7A])}; # Perl 5.16 compatible
478             # ${Elatin7::not_upper_i} = qr{(?>[\x00-\xFF])}; # older Perl compatible
479             ${Elatin7::not_word} = qr{(?>[^\x30-\x39\x41-\x5A\x5F\x61-\x7A])};
480             ${Elatin7::not_xdigit} = qr{(?>[^\x30-\x39\x41-\x46\x61-\x66])};
481             ${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))};
482             ${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]))};
483              
484             # avoid: Name "Elatin7::foo" used only once: possible typo at here.
485             ${Elatin7::dot} = ${Elatin7::dot};
486             ${Elatin7::dot_s} = ${Elatin7::dot_s};
487             ${Elatin7::eD} = ${Elatin7::eD};
488             ${Elatin7::eS} = ${Elatin7::eS};
489             ${Elatin7::eW} = ${Elatin7::eW};
490             ${Elatin7::eH} = ${Elatin7::eH};
491             ${Elatin7::eV} = ${Elatin7::eV};
492             ${Elatin7::eR} = ${Elatin7::eR};
493             ${Elatin7::eN} = ${Elatin7::eN};
494             ${Elatin7::not_alnum} = ${Elatin7::not_alnum};
495             ${Elatin7::not_alpha} = ${Elatin7::not_alpha};
496             ${Elatin7::not_ascii} = ${Elatin7::not_ascii};
497             ${Elatin7::not_blank} = ${Elatin7::not_blank};
498             ${Elatin7::not_cntrl} = ${Elatin7::not_cntrl};
499             ${Elatin7::not_digit} = ${Elatin7::not_digit};
500             ${Elatin7::not_graph} = ${Elatin7::not_graph};
501             ${Elatin7::not_lower} = ${Elatin7::not_lower};
502             ${Elatin7::not_lower_i} = ${Elatin7::not_lower_i};
503             ${Elatin7::not_print} = ${Elatin7::not_print};
504             ${Elatin7::not_punct} = ${Elatin7::not_punct};
505             ${Elatin7::not_space} = ${Elatin7::not_space};
506             ${Elatin7::not_upper} = ${Elatin7::not_upper};
507             ${Elatin7::not_upper_i} = ${Elatin7::not_upper_i};
508             ${Elatin7::not_word} = ${Elatin7::not_word};
509             ${Elatin7::not_xdigit} = ${Elatin7::not_xdigit};
510             ${Elatin7::eb} = ${Elatin7::eb};
511             ${Elatin7::eB} = ${Elatin7::eB};
512              
513             #
514             # Latin-7 split
515             #
516             sub Elatin7::split(;$$$) {
517              
518             # P.794 29.2.161. split
519             # in Chapter 29: Functions
520             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
521              
522             # P.951 split
523             # in Chapter 27: Functions
524             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
525              
526 0     0 0 0 my $pattern = $_[0];
527 0         0 my $string = $_[1];
528 0         0 my $limit = $_[2];
529              
530             # if $pattern is also omitted or is the literal space, " "
531 0 0       0 if (not defined $pattern) {
532 0         0 $pattern = ' ';
533             }
534              
535             # if $string is omitted, the function splits the $_ string
536 0 0       0 if (not defined $string) {
537 0 0       0 if (defined $_) {
538 0         0 $string = $_;
539             }
540             else {
541 0         0 $string = '';
542             }
543             }
544              
545 0         0 my @split = ();
546              
547             # when string is empty
548 0 0       0 if ($string eq '') {
    0          
549              
550             # resulting list value in list context
551 0 0       0 if (wantarray) {
552 0         0 return @split;
553             }
554              
555             # count of substrings in scalar context
556             else {
557 0 0       0 carp "Use of implicit split to \@_ is deprecated" if $^W;
558 0         0 @_ = @split;
559 0         0 return scalar @_;
560             }
561             }
562              
563             # split's first argument is more consistently interpreted
564             #
565             # After some changes earlier in v5.17, split's behavior has been simplified:
566             # if the PATTERN argument evaluates to a string containing one space, it is
567             # treated the way that a literal string containing one space once was.
568             # http://search.cpan.org/dist/perl-5.18.0/pod/perldelta.pod#split's_first_argument_is_more_consistently_interpreted
569              
570             # if $pattern is also omitted or is the literal space, " ", the function splits
571             # on whitespace, /\s+/, after skipping any leading whitespace
572             # (and so on)
573              
574             elsif ($pattern eq ' ') {
575 0 0       0 if (not defined $limit) {
576 0         0 return CORE::split(' ', $string);
577             }
578             else {
579 0         0 return CORE::split(' ', $string, $limit);
580             }
581             }
582              
583             # if $limit is negative, it is treated as if an arbitrarily large $limit has been specified
584 0 0 0     0 if ((not defined $limit) or ($limit <= 0)) {
    0          
585              
586             # a pattern capable of matching either the null string or something longer than the
587             # null string will split the value of $string into separate characters wherever it
588             # matches the null string between characters
589             # (and so on)
590              
591 0 0       0 if ('' =~ / \A $pattern \z /xms) {
592 0         0 my $last_subexpression_offsets = _last_subexpression_offsets($pattern);
593 0         0 my $limit = scalar(() = $string =~ /($pattern)/oxmsg);
594              
595             # P.1024 Appendix W.10 Multibyte Processing
596             # of ISBN 1-56592-224-7 CJKV Information Processing
597             # (and so on)
598              
599             # the //m modifier is assumed when you split on the pattern /^/
600             # (and so on)
601              
602 0         0 eval q{ no warnings }; # avoid: Complex regular subexpression recursion limit (32766) exceeded at ...
603             # V
604 0   0     0 while ((--$limit > 0) and ($string =~ s/\A((?:$q_char)+?)$pattern//m)) {
605              
606             # if the $pattern contains parentheses, then the substring matched by each pair of parentheses
607             # is included in the resulting list, interspersed with the fields that are ordinarily returned
608             # (and so on)
609              
610 0         0 local $@;
611 0         0 eval q{ no warnings }; # avoid: Complex regular subexpression recursion limit (32766) exceeded at ...
612 0         0 for (my $digit=1; $digit <= ($last_subexpression_offsets + 1); $digit++) {
613 0         0 push @split, CORE::eval('$' . $digit);
614             }
615             }
616             }
617              
618             else {
619 0         0 my $last_subexpression_offsets = _last_subexpression_offsets($pattern);
620              
621 0         0 eval q{ no warnings }; # avoid: Complex regular subexpression recursion limit (32766) exceeded at ...
622             # V
623 0         0 while ($string =~ s/\A((?:$q_char)*?)$pattern//m) {
624 0         0 local $@;
625 0         0 eval q{ no warnings }; # avoid: Complex regular subexpression recursion limit (32766) exceeded at ...
626 0         0 for (my $digit=1; $digit <= ($last_subexpression_offsets + 1); $digit++) {
627 0         0 push @split, CORE::eval('$' . $digit);
628             }
629             }
630             }
631             }
632              
633             elsif ($limit > 0) {
634 0 0       0 if ('' =~ / \A $pattern \z /xms) {
635 0         0 my $last_subexpression_offsets = _last_subexpression_offsets($pattern);
636 0   0     0 while ((--$limit > 0) and (CORE::length($string) > 0)) {
637              
638 0         0 eval q{ no warnings }; # avoid: Complex regular subexpression recursion limit (32766) exceeded at ...
639             # V
640 0 0       0 if ($string =~ s/\A((?:$q_char)+?)$pattern//m) {
641 0         0 local $@;
642 0         0 for (my $digit=1; $digit <= ($last_subexpression_offsets + 1); $digit++) {
643 0         0 push @split, CORE::eval('$' . $digit);
644             }
645             }
646             }
647             }
648             else {
649 0         0 my $last_subexpression_offsets = _last_subexpression_offsets($pattern);
650 0   0     0 while ((--$limit > 0) and (CORE::length($string) > 0)) {
651              
652 0         0 eval q{ no warnings }; # avoid: Complex regular subexpression recursion limit (32766) exceeded at ...
653             # V
654 0 0       0 if ($string =~ s/\A((?:$q_char)*?)$pattern//m) {
655 0         0 local $@;
656 0         0 for (my $digit=1; $digit <= ($last_subexpression_offsets + 1); $digit++) {
657 0         0 push @split, CORE::eval('$' . $digit);
658             }
659             }
660             }
661             }
662             }
663              
664 0 0       0 if (CORE::length($string) > 0) {
665 0         0 push @split, $string;
666             }
667              
668             # if $_[2] (NOT "$limit") is omitted or zero, trailing null fields are stripped from the result
669 0 0 0     0 if ((not defined $_[2]) or ($_[2] == 0)) {
670 0   0     0 while ((scalar(@split) >= 1) and ($split[-1] eq '')) {
671 0         0 pop @split;
672             }
673             }
674              
675             # resulting list value in list context
676 0 0       0 if (wantarray) {
677 0         0 return @split;
678             }
679              
680             # count of substrings in scalar context
681             else {
682 0 0       0 carp "Use of implicit split to \@_ is deprecated" if $^W;
683 0         0 @_ = @split;
684 0         0 return scalar @_;
685             }
686             }
687              
688             #
689             # get last subexpression offsets
690             #
691             sub _last_subexpression_offsets {
692 0     0   0 my $pattern = $_[0];
693              
694             # remove comment
695 0         0 $pattern =~ s/\(\?\# .*? \)//oxmsg;
696              
697 0         0 my $modifier = '';
698 0 0       0 if ($pattern =~ /\(\?\^? ([\-A-Za-z]+) :/oxms) {
699 0         0 $modifier = $1;
700 0         0 $modifier =~ s/-[A-Za-z]*//;
701             }
702              
703             # with /x modifier
704 0         0 my @char = ();
705 0 0       0 if ($modifier =~ /x/oxms) {
706 0         0 @char = $pattern =~ /\G((?>
707             [^\\\#\[\(] |
708             \\ $q_char |
709             \# (?>[^\n]*) $ |
710             \[ (?>(?:[^\\\]]|\\\\|\\\]|$q_char)+) \] |
711             \(\? |
712             $q_char
713             ))/oxmsg;
714             }
715              
716             # without /x modifier
717             else {
718 0         0 @char = $pattern =~ /\G((?>
719             [^\\\[\(] |
720             \\ $q_char |
721             \[ (?>(?:[^\\\]]|\\\\|\\\]|$q_char)+) \] |
722             \(\? |
723             $q_char
724             ))/oxmsg;
725             }
726              
727 0         0 return scalar grep { $_ eq '(' } @char;
  0         0  
728             }
729              
730             #
731             # Latin-7 transliteration (tr///)
732             #
733             sub Elatin7::tr($$$$;$) {
734              
735 0     0 0 0 my $bind_operator = $_[1];
736 0         0 my $searchlist = $_[2];
737 0         0 my $replacementlist = $_[3];
738 0   0     0 my $modifier = $_[4] || '';
739              
740 0 0       0 if ($modifier =~ /r/oxms) {
741 0 0       0 if ($bind_operator =~ / !~ /oxms) {
742 0         0 croak "Using !~ with tr///r doesn't make sense";
743             }
744             }
745              
746 0         0 my @char = $_[0] =~ /\G (?>$q_char) /oxmsg;
747 0         0 my @searchlist = _charlist_tr($searchlist);
748 0         0 my @replacementlist = _charlist_tr($replacementlist);
749              
750 0         0 my %tr = ();
751 0         0 for (my $i=0; $i <= $#searchlist; $i++) {
752 0 0       0 if (not exists $tr{$searchlist[$i]}) {
753 0 0 0     0 if (defined $replacementlist[$i] and ($replacementlist[$i] ne '')) {
    0 0        
    0          
754 0         0 $tr{$searchlist[$i]} = $replacementlist[$i];
755             }
756             elsif ($modifier =~ /d/oxms) {
757 0         0 $tr{$searchlist[$i]} = '';
758             }
759             elsif (defined $replacementlist[-1] and ($replacementlist[-1] ne '')) {
760 0         0 $tr{$searchlist[$i]} = $replacementlist[-1];
761             }
762             else {
763 0         0 $tr{$searchlist[$i]} = $searchlist[$i];
764             }
765             }
766             }
767              
768 0         0 my $tr = 0;
769 0         0 my $replaced = '';
770 0 0       0 if ($modifier =~ /c/oxms) {
771 0         0 while (defined(my $char = shift @char)) {
772 0 0       0 if (not exists $tr{$char}) {
773 0 0       0 if (defined $replacementlist[-1]) {
774 0         0 $replaced .= $replacementlist[-1];
775             }
776 0         0 $tr++;
777 0 0       0 if ($modifier =~ /s/oxms) {
778 0   0     0 while (@char and (not exists $tr{$char[0]})) {
779 0         0 shift @char;
780 0         0 $tr++;
781             }
782             }
783             }
784             else {
785 0         0 $replaced .= $char;
786             }
787             }
788             }
789             else {
790 0         0 while (defined(my $char = shift @char)) {
791 0 0       0 if (exists $tr{$char}) {
792 0         0 $replaced .= $tr{$char};
793 0         0 $tr++;
794 0 0       0 if ($modifier =~ /s/oxms) {
795 0   0     0 while (@char and (exists $tr{$char[0]}) and ($tr{$char[0]} eq $tr{$char})) {
      0        
796 0         0 shift @char;
797 0         0 $tr++;
798             }
799             }
800             }
801             else {
802 0         0 $replaced .= $char;
803             }
804             }
805             }
806              
807 0 0       0 if ($modifier =~ /r/oxms) {
808 0         0 return $replaced;
809             }
810             else {
811 0         0 $_[0] = $replaced;
812 0 0       0 if ($bind_operator =~ / !~ /oxms) {
813 0         0 return not $tr;
814             }
815             else {
816 0         0 return $tr;
817             }
818             }
819             }
820              
821             #
822             # Latin-7 chop
823             #
824             sub Elatin7::chop(@) {
825              
826 0     0 0 0 my $chop;
827 0 0       0 if (@_ == 0) {
828 0         0 my @char = /\G (?>$q_char) /oxmsg;
829 0         0 $chop = pop @char;
830 0         0 $_ = join '', @char;
831             }
832             else {
833 0         0 for (@_) {
834 0         0 my @char = /\G (?>$q_char) /oxmsg;
835 0         0 $chop = pop @char;
836 0         0 $_ = join '', @char;
837             }
838             }
839 0         0 return $chop;
840             }
841              
842             #
843             # Latin-7 index by octet
844             #
845             sub Elatin7::index($$;$) {
846              
847 0     0 1 0 my($str,$substr,$position) = @_;
848 0   0     0 $position ||= 0;
849 0         0 my $pos = 0;
850              
851 0         0 while ($pos < CORE::length($str)) {
852 0 0       0 if (CORE::substr($str,$pos,CORE::length($substr)) eq $substr) {
853 0 0       0 if ($pos >= $position) {
854 0         0 return $pos;
855             }
856             }
857 0 0       0 if (CORE::substr($str,$pos) =~ /\A ($q_char) /oxms) {
858 0         0 $pos += CORE::length($1);
859             }
860             else {
861 0         0 $pos += 1;
862             }
863             }
864 0         0 return -1;
865             }
866              
867             #
868             # Latin-7 reverse index
869             #
870             sub Elatin7::rindex($$;$) {
871              
872 0     0 0 0 my($str,$substr,$position) = @_;
873 0   0     0 $position ||= CORE::length($str) - 1;
874 0         0 my $pos = 0;
875 0         0 my $rindex = -1;
876              
877 0   0     0 while (($pos < CORE::length($str)) and ($pos <= $position)) {
878 0 0       0 if (CORE::substr($str,$pos,CORE::length($substr)) eq $substr) {
879 0         0 $rindex = $pos;
880             }
881 0 0       0 if (CORE::substr($str,$pos) =~ /\A ($q_char) /oxms) {
882 0         0 $pos += CORE::length($1);
883             }
884             else {
885 0         0 $pos += 1;
886             }
887             }
888 0         0 return $rindex;
889             }
890              
891             #
892             # Latin-7 lower case first with parameter
893             #
894             sub Elatin7::lcfirst(@) {
895 0 0   0 0 0 if (@_) {
896 0         0 my $s = shift @_;
897 0 0 0     0 if (@_ and wantarray) {
898 0         0 return Elatin7::lc(CORE::substr($s,0,1)) . CORE::substr($s,1), @_;
899             }
900             else {
901 0         0 return Elatin7::lc(CORE::substr($s,0,1)) . CORE::substr($s,1);
902             }
903             }
904             else {
905 0         0 return Elatin7::lc(CORE::substr($_,0,1)) . CORE::substr($_,1);
906             }
907             }
908              
909             #
910             # Latin-7 lower case first without parameter
911             #
912             sub Elatin7::lcfirst_() {
913 0     0 0 0 return Elatin7::lc(CORE::substr($_,0,1)) . CORE::substr($_,1);
914             }
915              
916             #
917             # Latin-7 lower case with parameter
918             #
919             sub Elatin7::lc(@) {
920 0 0   0 0 0 if (@_) {
921 0         0 my $s = shift @_;
922 0 0 0     0 if (@_ and wantarray) {
923 0 0       0 return join('', map {defined($lc{$_}) ? $lc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg)), @_;
  0         0  
924             }
925             else {
926 0 0       0 return join('', map {defined($lc{$_}) ? $lc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg));
  0         0  
927             }
928             }
929             else {
930 0         0 return Elatin7::lc_();
931             }
932             }
933              
934             #
935             # Latin-7 lower case without parameter
936             #
937             sub Elatin7::lc_() {
938 0     0 0 0 my $s = $_;
939 0 0       0 return join '', map {defined($lc{$_}) ? $lc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg);
  0         0  
940             }
941              
942             #
943             # Latin-7 upper case first with parameter
944             #
945             sub Elatin7::ucfirst(@) {
946 0 0   0 0 0 if (@_) {
947 0         0 my $s = shift @_;
948 0 0 0     0 if (@_ and wantarray) {
949 0         0 return Elatin7::uc(CORE::substr($s,0,1)) . CORE::substr($s,1), @_;
950             }
951             else {
952 0         0 return Elatin7::uc(CORE::substr($s,0,1)) . CORE::substr($s,1);
953             }
954             }
955             else {
956 0         0 return Elatin7::uc(CORE::substr($_,0,1)) . CORE::substr($_,1);
957             }
958             }
959              
960             #
961             # Latin-7 upper case first without parameter
962             #
963             sub Elatin7::ucfirst_() {
964 0     0 0 0 return Elatin7::uc(CORE::substr($_,0,1)) . CORE::substr($_,1);
965             }
966              
967             #
968             # Latin-7 upper case with parameter
969             #
970             sub Elatin7::uc(@) {
971 0 50   174 0 0 if (@_) {
972 174         242 my $s = shift @_;
973 174 50 33     208 if (@_ and wantarray) {
974 174 0       315 return join('', map {defined($uc{$_}) ? $uc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg)), @_;
  0         0  
975             }
976             else {
977 0 100       0 return join('', map {defined($uc{$_}) ? $uc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg));
  174         510  
978             }
979             }
980             else {
981 174         620 return Elatin7::uc_();
982             }
983             }
984              
985             #
986             # Latin-7 upper case without parameter
987             #
988             sub Elatin7::uc_() {
989 0     0 0 0 my $s = $_;
990 0 0       0 return join '', map {defined($uc{$_}) ? $uc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg);
  0         0  
991             }
992              
993             #
994             # Latin-7 fold case with parameter
995             #
996             sub Elatin7::fc(@) {
997 0 50   197 0 0 if (@_) {
998 197         288 my $s = shift @_;
999 197 50 33     217 if (@_ and wantarray) {
1000 197 0       349 return join('', map {defined($fc{$_}) ? $fc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg)), @_;
  0         0  
1001             }
1002             else {
1003 0 100       0 return join('', map {defined($fc{$_}) ? $fc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg));
  197         480  
1004             }
1005             }
1006             else {
1007 197         1033 return Elatin7::fc_();
1008             }
1009             }
1010              
1011             #
1012             # Latin-7 fold case without parameter
1013             #
1014             sub Elatin7::fc_() {
1015 0     0 0 0 my $s = $_;
1016 0 0       0 return join '', map {defined($fc{$_}) ? $fc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg);
  0         0  
1017             }
1018              
1019             #
1020             # Latin-7 regexp capture
1021             #
1022             {
1023             sub Elatin7::capture {
1024 0     0 1 0 return $_[0];
1025             }
1026             }
1027              
1028             #
1029             # Latin-7 regexp ignore case modifier
1030             #
1031             sub Elatin7::ignorecase {
1032              
1033 0     0 0 0 my @string = @_;
1034 0         0 my $metachar = qr/[\@\\|[\]{]/oxms;
1035              
1036             # ignore case of $scalar or @array
1037 0         0 for my $string (@string) {
1038              
1039             # split regexp
1040 0         0 my @char = $string =~ /\G (?>\[\^|\\$q_char|$q_char) /oxmsg;
1041              
1042             # unescape character
1043 0         0 for (my $i=0; $i <= $#char; $i++) {
1044 0 0       0 next if not defined $char[$i];
1045              
1046             # open character class [...]
1047 0 0       0 if ($char[$i] eq '[') {
    0          
    0          
    0          
1048 0         0 my $left = $i;
1049              
1050             # [] make die "unmatched [] in regexp ...\n"
1051              
1052 0 0       0 if ($char[$i+1] eq ']') {
1053 0         0 $i++;
1054             }
1055              
1056 0         0 while (1) {
1057 0 0       0 if (++$i > $#char) {
1058 0         0 croak "Unmatched [] in regexp";
1059             }
1060 0 0       0 if ($char[$i] eq ']') {
1061 0         0 my $right = $i;
1062 0         0 my @charlist = charlist_qr(@char[$left+1..$right-1], 'i');
1063              
1064             # escape character
1065 0         0 for my $char (@charlist) {
1066 0 0       0 if (0) {
1067             }
1068              
1069 0         0 elsif ($char =~ /\A [.|)] \z/oxms) {
1070 0         0 $char = '\\' . $char;
1071             }
1072             }
1073              
1074             # [...]
1075 0         0 splice @char, $left, $right-$left+1, '(?:' . join('|', @charlist) . ')';
1076              
1077 0         0 $i = $left;
1078 0         0 last;
1079             }
1080             }
1081             }
1082              
1083             # open character class [^...]
1084             elsif ($char[$i] eq '[^') {
1085 0         0 my $left = $i;
1086              
1087             # [^] make die "unmatched [] in regexp ...\n"
1088              
1089 0 0       0 if ($char[$i+1] eq ']') {
1090 0         0 $i++;
1091             }
1092              
1093 0         0 while (1) {
1094 0 0       0 if (++$i > $#char) {
1095 0         0 croak "Unmatched [] in regexp";
1096             }
1097 0 0       0 if ($char[$i] eq ']') {
1098 0         0 my $right = $i;
1099 0         0 my @charlist = charlist_not_qr(@char[$left+1..$right-1], 'i');
1100              
1101             # escape character
1102 0         0 for my $char (@charlist) {
1103 0 0       0 if (0) {
1104             }
1105              
1106 0         0 elsif ($char =~ /\A [.|)] \z/oxms) {
1107 0         0 $char = '\\' . $char;
1108             }
1109             }
1110              
1111             # [^...]
1112 0         0 splice @char, $left, $right-$left+1, '(?!' . join('|', @charlist) . ")(?:$your_char)";
1113              
1114 0         0 $i = $left;
1115 0         0 last;
1116             }
1117             }
1118             }
1119              
1120             # rewrite classic character class or escape character
1121             elsif (my $char = classic_character_class($char[$i])) {
1122 0         0 $char[$i] = $char;
1123             }
1124              
1125             # with /i modifier
1126             elsif ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) {
1127 0         0 my $uc = Elatin7::uc($char[$i]);
1128 0         0 my $fc = Elatin7::fc($char[$i]);
1129 0 0       0 if ($uc ne $fc) {
1130 0 0       0 if (CORE::length($fc) == 1) {
1131 0         0 $char[$i] = '[' . $uc . $fc . ']';
1132             }
1133             else {
1134 0         0 $char[$i] = '(?:' . $uc . '|' . $fc . ')';
1135             }
1136             }
1137             }
1138             }
1139              
1140             # characterize
1141 0         0 for (my $i=0; $i <= $#char; $i++) {
1142 0 0       0 next if not defined $char[$i];
1143              
1144 0 0       0 if (0) {
1145             }
1146              
1147             # quote character before ? + * {
1148 0 0       0 elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
1149 0 0       0 if ($char[$i-1] !~ /\A [\x00-\xFF] \z/oxms) {
1150 0         0 $char[$i-1] = '(?:' . $char[$i-1] . ')';
1151             }
1152             }
1153             }
1154              
1155 0         0 $string = join '', @char;
1156             }
1157              
1158             # make regexp string
1159 0         0 return @string;
1160             }
1161              
1162             #
1163             # classic character class ( \D \S \W \d \s \w \C \X \H \V \h \v \R \N \b \B )
1164             #
1165             sub Elatin7::classic_character_class {
1166 0     1867 0 0 my($char) = @_;
1167              
1168             return {
1169             '\D' => '${Elatin7::eD}',
1170             '\S' => '${Elatin7::eS}',
1171             '\W' => '${Elatin7::eW}',
1172             '\d' => '[0-9]',
1173              
1174             # Before Perl 5.6, \s only matched the five whitespace characters
1175             # tab, newline, form-feed, carriage return, and the space character
1176             # itself, which, taken together, is the character class [\t\n\f\r ].
1177              
1178             # Vertical tabs are now whitespace
1179             # \s in a regex now matches a vertical tab in all circumstances.
1180             # http://search.cpan.org/dist/perl-5.18.0/pod/perldelta.pod#Vertical_tabs_are_now_whitespace
1181             # \t \n \v \f \r space
1182             # '\s' => '[\x09\x0A \x0C\x0D\x20]',
1183             # '\s' => '[\x09\x0A\x0B\x0C\x0D\x20]',
1184             '\s' => '\s',
1185              
1186             '\w' => '[0-9A-Z_a-z]',
1187             '\C' => '[\x00-\xFF]',
1188             '\X' => 'X',
1189              
1190             # \h \v \H \V
1191              
1192             # P.114 Character Class Shortcuts
1193             # in Chapter 7: In the World of Regular Expressions
1194             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
1195              
1196             # P.357 13.2.3 Whitespace
1197             # in Chapter 13: perlrecharclass: Perl Regular Expression Character Classes
1198             # of ISBN-13: 978-1-906966-02-7 The Perl Language Reference Manual (for Perl version 5.12.1)
1199             #
1200             # 0x00009 CHARACTER TABULATION h s
1201             # 0x0000a LINE FEED (LF) vs
1202             # 0x0000b LINE TABULATION v
1203             # 0x0000c FORM FEED (FF) vs
1204             # 0x0000d CARRIAGE RETURN (CR) vs
1205             # 0x00020 SPACE h s
1206              
1207             # P.196 Table 5-9. Alphanumeric regex metasymbols
1208             # in Chapter 5. Pattern Matching
1209             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
1210              
1211             # (and so on)
1212              
1213             '\H' => '${Elatin7::eH}',
1214             '\V' => '${Elatin7::eV}',
1215             '\h' => '[\x09\x20]',
1216             '\v' => '[\x0A\x0B\x0C\x0D]',
1217             '\R' => '${Elatin7::eR}',
1218              
1219             # \N
1220             #
1221             # http://perldoc.perl.org/perlre.html
1222             # Character Classes and other Special Escapes
1223             # Any character but \n (experimental). Not affected by /s modifier
1224              
1225             '\N' => '${Elatin7::eN}',
1226              
1227             # \b \B
1228              
1229             # P.180 Boundaries: The \b and \B Assertions
1230             # in Chapter 5: Pattern Matching
1231             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
1232              
1233             # P.219 Boundaries: The \b and \B Assertions
1234             # in Chapter 5: Pattern Matching
1235             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
1236              
1237             # \b really means (?:(?<=\w)(?!\w)|(?
1238             # or (?:(?<=\A|\W)(?=\w)|(?<=\w)(?=\W|\z))
1239             '\b' => '${Elatin7::eb}',
1240              
1241             # \B really means (?:(?<=\w)(?=\w)|(?
1242             # or (?:(?<=\w)(?=\w)|(?<=\W)(?=\W))
1243             '\B' => '${Elatin7::eB}',
1244              
1245 1867   100     2430 }->{$char} || '';
1246             }
1247              
1248             #
1249             # prepare Latin-7 characters per length
1250             #
1251              
1252             # 1 octet characters
1253             my @chars1 = ();
1254             sub chars1 {
1255 1867 0   0 0 62300 if (@chars1) {
1256 0         0 return @chars1;
1257             }
1258 0 0       0 if (exists $range_tr{1}) {
1259 0         0 my @ranges = @{ $range_tr{1} };
  0         0  
1260 0         0 while (my @range = splice(@ranges,0,1)) {
1261 0         0 for my $oct0 (@{$range[0]}) {
  0         0  
1262 0         0 push @chars1, pack 'C', $oct0;
1263             }
1264             }
1265             }
1266 0         0 return @chars1;
1267             }
1268              
1269             # 2 octets characters
1270             my @chars2 = ();
1271             sub chars2 {
1272 0 0   0 0 0 if (@chars2) {
1273 0         0 return @chars2;
1274             }
1275 0 0       0 if (exists $range_tr{2}) {
1276 0         0 my @ranges = @{ $range_tr{2} };
  0         0  
1277 0         0 while (my @range = splice(@ranges,0,2)) {
1278 0         0 for my $oct0 (@{$range[0]}) {
  0         0  
1279 0         0 for my $oct1 (@{$range[1]}) {
  0         0  
1280 0         0 push @chars2, pack 'CC', $oct0,$oct1;
1281             }
1282             }
1283             }
1284             }
1285 0         0 return @chars2;
1286             }
1287              
1288             # 3 octets characters
1289             my @chars3 = ();
1290             sub chars3 {
1291 0 0   0 0 0 if (@chars3) {
1292 0         0 return @chars3;
1293             }
1294 0 0       0 if (exists $range_tr{3}) {
1295 0         0 my @ranges = @{ $range_tr{3} };
  0         0  
1296 0         0 while (my @range = splice(@ranges,0,3)) {
1297 0         0 for my $oct0 (@{$range[0]}) {
  0         0  
1298 0         0 for my $oct1 (@{$range[1]}) {
  0         0  
1299 0         0 for my $oct2 (@{$range[2]}) {
  0         0  
1300 0         0 push @chars3, pack 'CCC', $oct0,$oct1,$oct2;
1301             }
1302             }
1303             }
1304             }
1305             }
1306 0         0 return @chars3;
1307             }
1308              
1309             # 4 octets characters
1310             my @chars4 = ();
1311             sub chars4 {
1312 0 0   0 0 0 if (@chars4) {
1313 0         0 return @chars4;
1314             }
1315 0 0       0 if (exists $range_tr{4}) {
1316 0         0 my @ranges = @{ $range_tr{4} };
  0         0  
1317 0         0 while (my @range = splice(@ranges,0,4)) {
1318 0         0 for my $oct0 (@{$range[0]}) {
  0         0  
1319 0         0 for my $oct1 (@{$range[1]}) {
  0         0  
1320 0         0 for my $oct2 (@{$range[2]}) {
  0         0  
1321 0         0 for my $oct3 (@{$range[3]}) {
  0         0  
1322 0         0 push @chars4, pack 'CCCC', $oct0,$oct1,$oct2,$oct3;
1323             }
1324             }
1325             }
1326             }
1327             }
1328             }
1329 0         0 return @chars4;
1330             }
1331              
1332             #
1333             # Latin-7 open character list for tr
1334             #
1335             sub _charlist_tr {
1336              
1337 0     0   0 local $_ = shift @_;
1338              
1339             # unescape character
1340 0         0 my @char = ();
1341 0         0 while (not /\G \z/oxmsgc) {
1342 0 0       0 if (/\G (\\0?55|\\x2[Dd]|\\-) /oxmsgc) {
    0          
    0          
    0          
    0          
    0          
    0          
1343 0         0 push @char, '\-';
1344             }
1345             elsif (/\G \\ ([0-7]{2,3}) /oxmsgc) {
1346 0         0 push @char, CORE::chr(oct $1);
1347             }
1348             elsif (/\G \\x ([0-9A-Fa-f]{1,2}) /oxmsgc) {
1349 0         0 push @char, CORE::chr(hex $1);
1350             }
1351             elsif (/\G \\c ([\x40-\x5F]) /oxmsgc) {
1352 0         0 push @char, CORE::chr(CORE::ord($1) & 0x1F);
1353             }
1354             elsif (/\G (\\ [0nrtfbae]) /oxmsgc) {
1355             push @char, {
1356             '\0' => "\0",
1357             '\n' => "\n",
1358             '\r' => "\r",
1359             '\t' => "\t",
1360             '\f' => "\f",
1361             '\b' => "\x08", # \b means backspace in character class
1362             '\a' => "\a",
1363             '\e' => "\e",
1364 0         0 }->{$1};
1365             }
1366             elsif (/\G \\ ($q_char) /oxmsgc) {
1367 0         0 push @char, $1;
1368             }
1369             elsif (/\G ($q_char) /oxmsgc) {
1370 0         0 push @char, $1;
1371             }
1372             }
1373              
1374             # join separated multiple-octet
1375 0         0 @char = join('',@char) =~ /\G (?>\\-|$q_char) /oxmsg;
1376              
1377             # unescape '-'
1378 0         0 my @i = ();
1379 0         0 for my $i (0 .. $#char) {
1380 0 0       0 if ($char[$i] eq '\-') {
    0          
1381 0         0 $char[$i] = '-';
1382             }
1383             elsif ($char[$i] eq '-') {
1384 0 0 0     0 if ((0 < $i) and ($i < $#char)) {
1385 0         0 push @i, $i;
1386             }
1387             }
1388             }
1389              
1390             # open character list (reverse for splice)
1391 0         0 for my $i (CORE::reverse @i) {
1392 0         0 my @range = ();
1393              
1394             # range error
1395 0 0 0     0 if ((CORE::length($char[$i-1]) > CORE::length($char[$i+1])) or ($char[$i-1] gt $char[$i+1])) {
1396 0         0 croak "Invalid tr/// range \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1397             }
1398              
1399             # range of multiple-octet code
1400 0 0       0 if (CORE::length($char[$i-1]) == 1) {
    0          
    0          
    0          
1401 0 0       0 if (CORE::length($char[$i+1]) == 1) {
    0          
    0          
    0          
1402 0 0       0 push @range, grep {($char[$i-1] le $_) and ($_ le $char[$i+1])} chars1();
  0         0  
1403             }
1404             elsif (CORE::length($char[$i+1]) == 2) {
1405 0         0 push @range, grep {$char[$i-1] le $_} chars1();
  0         0  
1406 0         0 push @range, grep {$_ le $char[$i+1]} chars2();
  0         0  
1407             }
1408             elsif (CORE::length($char[$i+1]) == 3) {
1409 0         0 push @range, grep {$char[$i-1] le $_} chars1();
  0         0  
1410 0         0 push @range, chars2();
1411 0         0 push @range, grep {$_ le $char[$i+1]} chars3();
  0         0  
1412             }
1413             elsif (CORE::length($char[$i+1]) == 4) {
1414 0         0 push @range, grep {$char[$i-1] le $_} chars1();
  0         0  
1415 0         0 push @range, chars2();
1416 0         0 push @range, chars3();
1417 0         0 push @range, grep {$_ le $char[$i+1]} chars4();
  0         0  
1418             }
1419             else {
1420 0         0 croak "Invalid tr/// range (over 4octets) \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1421             }
1422             }
1423             elsif (CORE::length($char[$i-1]) == 2) {
1424 0 0       0 if (CORE::length($char[$i+1]) == 2) {
    0          
    0          
1425 0 0       0 push @range, grep {($char[$i-1] le $_) and ($_ le $char[$i+1])} chars2();
  0         0  
1426             }
1427             elsif (CORE::length($char[$i+1]) == 3) {
1428 0         0 push @range, grep {$char[$i-1] le $_} chars2();
  0         0  
1429 0         0 push @range, grep {$_ le $char[$i+1]} chars3();
  0         0  
1430             }
1431             elsif (CORE::length($char[$i+1]) == 4) {
1432 0         0 push @range, grep {$char[$i-1] le $_} chars2();
  0         0  
1433 0         0 push @range, chars3();
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]) == 3) {
1441 0 0       0 if (CORE::length($char[$i+1]) == 3) {
    0          
1442 0 0       0 push @range, grep {($char[$i-1] le $_) and ($_ le $char[$i+1])} chars3();
  0         0  
1443             }
1444             elsif (CORE::length($char[$i+1]) == 4) {
1445 0         0 push @range, grep {$char[$i-1] le $_} chars3();
  0         0  
1446 0         0 push @range, grep {$_ le $char[$i+1]} chars4();
  0         0  
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             elsif (CORE::length($char[$i-1]) == 4) {
1453 0 0       0 if (CORE::length($char[$i+1]) == 4) {
1454 0 0       0 push @range, grep {($char[$i-1] le $_) and ($_ le $char[$i+1])} chars4();
  0         0  
1455             }
1456             else {
1457 0         0 croak "Invalid tr/// range (over 4octets) \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1458             }
1459             }
1460             else {
1461 0         0 croak "Invalid tr/// range (over 4octets) \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1462             }
1463              
1464 0         0 splice @char, $i-1, 3, @range;
1465             }
1466              
1467 0         0 return @char;
1468             }
1469              
1470             #
1471             # Latin-7 open character class
1472             #
1473             sub _cc {
1474 0 0   0   0 if (scalar(@_) == 0) {
    0          
    0          
1475 0         0 die __FILE__, ": subroutine cc got no parameter.\n";
1476             }
1477             elsif (scalar(@_) == 1) {
1478 0         0 return sprintf('\x%02X',$_[0]);
1479             }
1480             elsif (scalar(@_) == 2) {
1481 0 0       0 if ($_[0] > $_[1]) {
    0          
    0          
1482 0         0 die __FILE__, ": subroutine cc got \$_[0] > \$_[1] parameters).\n";
1483             }
1484             elsif ($_[0] == $_[1]) {
1485 0         0 return sprintf('\x%02X',$_[0]);
1486             }
1487             elsif (($_[0]+1) == $_[1]) {
1488 0         0 return sprintf('[\\x%02X\\x%02X]',$_[0],$_[1]);
1489             }
1490             else {
1491 0         0 return sprintf('[\\x%02X-\\x%02X]',$_[0],$_[1]);
1492             }
1493             }
1494             else {
1495 0         0 die __FILE__, ": subroutine cc got 3 or more parameters (@{[scalar(@_)]} parameters).\n";
  0         0  
1496             }
1497             }
1498              
1499             #
1500             # Latin-7 octet range
1501             #
1502             sub _octets {
1503 0     182   0 my $length = shift @_;
1504              
1505 182 50       287 if ($length == 1) {
1506 182         381 my($a1) = unpack 'C', $_[0];
1507 182         433 my($z1) = unpack 'C', $_[1];
1508              
1509 182 50       297 if ($a1 > $z1) {
1510 182         351 croak 'Invalid [] range in regexp (CORE::ord(A) > CORE::ord(B)) ' . '\x' . unpack('H*',$a1) . '-\x' . unpack('H*',$z1);
1511             }
1512              
1513 0 50       0 if ($a1 == $z1) {
    50          
1514 182         431 return sprintf('\x%02X',$a1);
1515             }
1516             elsif (($a1+1) == $z1) {
1517 0         0 return sprintf('\x%02X\x%02X',$a1,$z1);
1518             }
1519             else {
1520 0         0 return sprintf('\x%02X-\x%02X',$a1,$z1);
1521             }
1522             }
1523             else {
1524 182         1128 die __FILE__, ": subroutine _octets got invalid length ($length).\n";
1525             }
1526             }
1527              
1528             #
1529             # Latin-7 range regexp
1530             #
1531             sub _range_regexp {
1532 0     182   0 my($length,$first,$last) = @_;
1533              
1534 182         366 my @range_regexp = ();
1535 182 50       253 if (not exists $range_tr{$length}) {
1536 182         406 return @range_regexp;
1537             }
1538              
1539 0         0 my @ranges = @{ $range_tr{$length} };
  182         272  
1540 182         388 while (my @range = splice(@ranges,0,$length)) {
1541 182         534 my $min = '';
1542 182         266 my $max = '';
1543 182         201 for (my $i=0; $i < $length; $i++) {
1544 182         487 $min .= pack 'C', $range[$i][0];
1545 182         593 $max .= pack 'C', $range[$i][-1];
1546             }
1547              
1548             # min___max
1549             # FIRST_____________LAST
1550             # (nothing)
1551              
1552 182 50 33     416 if ($max lt $first) {
    50 33        
    50 33        
    50 33        
    50 33        
    0 0        
    0 0        
1553             }
1554              
1555             # **********
1556             # min_________max
1557             # FIRST_____________LAST
1558             # **********
1559              
1560             elsif (($min le $first) and ($first le $max) and ($max le $last)) {
1561 182         1705 push @range_regexp, _octets($length,$first,$max,$min,$max);
1562             }
1563              
1564             # **********************
1565             # min________________max
1566             # FIRST_____________LAST
1567             # **********************
1568              
1569             elsif (($min eq $first) and ($max eq $last)) {
1570 0         0 push @range_regexp, _octets($length,$first,$last,$min,$max);
1571             }
1572              
1573             # *********
1574             # min___max
1575             # FIRST_____________LAST
1576             # *********
1577              
1578             elsif (($first le $min) and ($max le $last)) {
1579 0         0 push @range_regexp, _octets($length,$min,$max,$min,$max);
1580             }
1581              
1582             # **********************
1583             # min__________________________max
1584             # FIRST_____________LAST
1585             # **********************
1586              
1587             elsif (($min le $first) and ($last le $max)) {
1588 0         0 push @range_regexp, _octets($length,$first,$last,$min,$max);
1589             }
1590              
1591             # *********
1592             # min________max
1593             # FIRST_____________LAST
1594             # *********
1595              
1596             elsif (($first le $min) and ($min le $last) and ($last le $max)) {
1597 182         436 push @range_regexp, _octets($length,$min,$last,$min,$max);
1598             }
1599              
1600             # min___max
1601             # FIRST_____________LAST
1602             # (nothing)
1603              
1604             elsif ($last lt $min) {
1605             }
1606              
1607             else {
1608 0         0 die __FILE__, ": subroutine _range_regexp panic.\n";
1609             }
1610             }
1611              
1612 0         0 return @range_regexp;
1613             }
1614              
1615             #
1616             # Latin-7 open character list for qr and not qr
1617             #
1618             sub _charlist {
1619              
1620 182     358   365 my $modifier = pop @_;
1621 358         970 my @char = @_;
1622              
1623 358 100       702 my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
1624              
1625             # unescape character
1626 358         720 for (my $i=0; $i <= $#char; $i++) {
1627              
1628             # escape - to ...
1629 358 100 100     1102 if ($char[$i] eq '-') {
    50          
    50          
    50          
    50          
    50          
    100          
    50          
    100          
    100          
    100          
    100          
1630 1125 100 100     7499 if ((0 < $i) and ($i < $#char)) {
1631 206         734 $char[$i] = '...';
1632             }
1633             }
1634              
1635             # octal escape sequence
1636             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
1637 182         371 $char[$i] = octchr($1);
1638             }
1639              
1640             # hexadecimal escape sequence
1641             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
1642 0         0 $char[$i] = hexchr($1);
1643             }
1644              
1645             # \b{...} --> b\{...}
1646             # \B{...} --> B\{...}
1647             # \N{CHARNAME} --> N\{CHARNAME}
1648             # \p{PROPERTY} --> p\{PROPERTY}
1649             # \P{PROPERTY} --> P\{PROPERTY}
1650             elsif ($char[$i] =~ /\A \\ ([bBNpP]) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
1651 0         0 $char[$i] = $1 . '\\' . $2;
1652             }
1653              
1654             # \p, \P, \X --> p, P, X
1655             elsif ($char[$i] =~ /\A \\ ( [pPX] ) \z/oxms) {
1656 0         0 $char[$i] = $1;
1657             }
1658              
1659             elsif ($char[$i] =~ /\A \\ ([0-7]{2,3}) \z/oxms) {
1660 0         0 $char[$i] = CORE::chr oct $1;
1661             }
1662             elsif ($char[$i] =~ /\A \\x ([0-9A-Fa-f]{1,2}) \z/oxms) {
1663 0         0 $char[$i] = CORE::chr hex $1;
1664             }
1665             elsif ($char[$i] =~ /\A \\c ([\x40-\x5F]) \z/oxms) {
1666 22         93 $char[$i] = CORE::chr(CORE::ord($1) & 0x1F);
1667             }
1668             elsif ($char[$i] =~ /\A (\\ [0nrtfbaedswDSWHVhvR]) \z/oxms) {
1669             $char[$i] = {
1670             '\0' => "\0",
1671             '\n' => "\n",
1672             '\r' => "\r",
1673             '\t' => "\t",
1674             '\f' => "\f",
1675             '\b' => "\x08", # \b means backspace in character class
1676             '\a' => "\a",
1677             '\e' => "\e",
1678             '\d' => '[0-9]',
1679              
1680             # Vertical tabs are now whitespace
1681             # \s in a regex now matches a vertical tab in all circumstances.
1682             # http://search.cpan.org/dist/perl-5.18.0/pod/perldelta.pod#Vertical_tabs_are_now_whitespace
1683             # \t \n \v \f \r space
1684             # '\s' => '[\x09\x0A \x0C\x0D\x20]',
1685             # '\s' => '[\x09\x0A\x0B\x0C\x0D\x20]',
1686             '\s' => '\s',
1687              
1688             '\w' => '[0-9A-Z_a-z]',
1689             '\D' => '${Elatin7::eD}',
1690             '\S' => '${Elatin7::eS}',
1691             '\W' => '${Elatin7::eW}',
1692              
1693             '\H' => '${Elatin7::eH}',
1694             '\V' => '${Elatin7::eV}',
1695             '\h' => '[\x09\x20]',
1696             '\v' => '[\x0A\x0B\x0C\x0D]',
1697             '\R' => '${Elatin7::eR}',
1698              
1699 0         0 }->{$1};
1700             }
1701              
1702             # POSIX-style character classes
1703             elsif ($ignorecase and ($char[$i] =~ /\A ( \[\: \^? (?:lower|upper) :\] ) \z/oxms)) {
1704             $char[$i] = {
1705              
1706             '[:lower:]' => '[\x41-\x5A\x61-\x7A]',
1707             '[:upper:]' => '[\x41-\x5A\x61-\x7A]',
1708             '[:^lower:]' => '${Elatin7::not_lower_i}',
1709             '[:^upper:]' => '${Elatin7::not_upper_i}',
1710              
1711 25         413 }->{$1};
1712             }
1713             elsif ($char[$i] =~ /\A ( \[\: \^? (?:alnum|alpha|ascii|blank|cntrl|digit|graph|lower|print|punct|space|upper|word|xdigit) :\] ) \z/oxms) {
1714             $char[$i] = {
1715              
1716             '[:alnum:]' => '[\x30-\x39\x41-\x5A\x61-\x7A]',
1717             '[:alpha:]' => '[\x41-\x5A\x61-\x7A]',
1718             '[:ascii:]' => '[\x00-\x7F]',
1719             '[:blank:]' => '[\x09\x20]',
1720             '[:cntrl:]' => '[\x00-\x1F\x7F]',
1721             '[:digit:]' => '[\x30-\x39]',
1722             '[:graph:]' => '[\x21-\x7F]',
1723             '[:lower:]' => '[\x61-\x7A]',
1724             '[:print:]' => '[\x20-\x7F]',
1725             '[:punct:]' => '[\x21-\x2F\x3A-\x3F\x40\x5B-\x5F\x60\x7B-\x7E]',
1726              
1727             # P.174 POSIX-Style Character Classes
1728             # in Chapter 5: Pattern Matching
1729             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
1730              
1731             # P.311 11.2.4 Character Classes and other Special Escapes
1732             # in Chapter 11: perlre: Perl regular expressions
1733             # of ISBN-13: 978-1-906966-02-7 The Perl Language Reference Manual (for Perl version 5.12.1)
1734              
1735             # P.210 POSIX-Style Character Classes
1736             # in Chapter 5: Pattern Matching
1737             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
1738              
1739             '[:space:]' => '[\s\x0B]', # "\s" plus vertical tab ("\cK")
1740              
1741             '[:upper:]' => '[\x41-\x5A]',
1742             '[:word:]' => '[\x30-\x39\x41-\x5A\x5F\x61-\x7A]',
1743             '[:xdigit:]' => '[\x30-\x39\x41-\x46\x61-\x66]',
1744             '[:^alnum:]' => '${Elatin7::not_alnum}',
1745             '[:^alpha:]' => '${Elatin7::not_alpha}',
1746             '[:^ascii:]' => '${Elatin7::not_ascii}',
1747             '[:^blank:]' => '${Elatin7::not_blank}',
1748             '[:^cntrl:]' => '${Elatin7::not_cntrl}',
1749             '[:^digit:]' => '${Elatin7::not_digit}',
1750             '[:^graph:]' => '${Elatin7::not_graph}',
1751             '[:^lower:]' => '${Elatin7::not_lower}',
1752             '[:^print:]' => '${Elatin7::not_print}',
1753             '[:^punct:]' => '${Elatin7::not_punct}',
1754             '[:^space:]' => '${Elatin7::not_space}',
1755             '[:^upper:]' => '${Elatin7::not_upper}',
1756             '[:^word:]' => '${Elatin7::not_word}',
1757             '[:^xdigit:]' => '${Elatin7::not_xdigit}',
1758              
1759 8         50 }->{$1};
1760             }
1761             elsif ($char[$i] =~ /\A \\ ($q_char) \z/oxms) {
1762 70         1173 $char[$i] = $1;
1763             }
1764             }
1765              
1766             # open character list
1767 7         34 my @singleoctet = ();
1768 358         598 my @multipleoctet = ();
1769 358         501 for (my $i=0; $i <= $#char; ) {
1770              
1771             # escaped -
1772 358 100 100     704 if (defined($char[$i+1]) and ($char[$i+1] eq '...')) {
    100          
    100          
    50          
    50          
    100          
1773 943         3890 $i += 1;
1774 182         231 next;
1775             }
1776              
1777             # make range regexp
1778             elsif ($char[$i] eq '...') {
1779              
1780             # range error
1781 182 50       309 if (CORE::length($char[$i-1]) > CORE::length($char[$i+1])) {
    50          
1782 182         609 croak 'Invalid [] range in regexp (length(A) > length(B)) ' . '\x' . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]);
1783             }
1784             elsif (CORE::length($char[$i-1]) == CORE::length($char[$i+1])) {
1785 0 50       0 if ($char[$i-1] gt $char[$i+1]) {
1786 182         407 croak 'Invalid [] range in regexp (CORE::ord(A) > CORE::ord(B)) ' . '\x' . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]);
1787             }
1788             }
1789              
1790             # make range regexp per length
1791 0         0 for my $length (CORE::length($char[$i-1]) .. CORE::length($char[$i+1])) {
1792 182         493 my @regexp = ();
1793              
1794             # is first and last
1795 182 50 33     246 if (($length == CORE::length($char[$i-1])) and ($length == CORE::length($char[$i+1]))) {
    0 0        
    0          
    0          
1796 182         677 push @regexp, _range_regexp($length, $char[$i-1], $char[$i+1]);
1797             }
1798              
1799             # is first
1800             elsif ($length == CORE::length($char[$i-1])) {
1801 182         448 push @regexp, _range_regexp($length, $char[$i-1], "\xFF" x $length);
1802             }
1803              
1804             # is inside in first and last
1805             elsif ((CORE::length($char[$i-1]) < $length) and ($length < CORE::length($char[$i+1]))) {
1806 0         0 push @regexp, _range_regexp($length, "\x00" x $length, "\xFF" x $length);
1807             }
1808              
1809             # is last
1810             elsif ($length == CORE::length($char[$i+1])) {
1811 0         0 push @regexp, _range_regexp($length, "\x00" x $length, $char[$i+1]);
1812             }
1813              
1814             else {
1815 0         0 die __FILE__, ": subroutine make_regexp panic.\n";
1816             }
1817              
1818 0 50       0 if ($length == 1) {
1819 182         334 push @singleoctet, @regexp;
1820             }
1821             else {
1822 182         400 push @multipleoctet, @regexp;
1823             }
1824             }
1825              
1826 0         0 $i += 2;
1827             }
1828              
1829             # with /i modifier
1830             elsif ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) {
1831 182 100       349 if ($modifier =~ /i/oxms) {
1832 493         715 my $uc = Elatin7::uc($char[$i]);
1833 24         51 my $fc = Elatin7::fc($char[$i]);
1834 24 100       52 if ($uc ne $fc) {
1835 24 50       50 if (CORE::length($fc) == 1) {
1836 12         22 push @singleoctet, $uc, $fc;
1837             }
1838             else {
1839 12         21 push @singleoctet, $uc;
1840 0         0 push @multipleoctet, $fc;
1841             }
1842             }
1843             else {
1844 0         0 push @singleoctet, $char[$i];
1845             }
1846             }
1847             else {
1848 12         28 push @singleoctet, $char[$i];
1849             }
1850 469         695 $i += 1;
1851             }
1852              
1853             # single character of single octet code
1854             elsif ($char[$i] =~ /\A (?: \\h ) \z/oxms) {
1855 493         809 push @singleoctet, "\t", "\x20";
1856 0         0 $i += 1;
1857             }
1858             elsif ($char[$i] =~ /\A (?: \\v ) \z/oxms) {
1859 0         0 push @singleoctet, "\x0A", "\x0B", "\x0C", "\x0D";
1860 0         0 $i += 1;
1861             }
1862             elsif ($char[$i] =~ /\A (?: \\d | \\s | \\w ) \z/oxms) {
1863 0         0 push @singleoctet, $char[$i];
1864 2         7 $i += 1;
1865             }
1866              
1867             # single character of multiple-octet code
1868             else {
1869 2         5 push @multipleoctet, $char[$i];
1870 84         150 $i += 1;
1871             }
1872             }
1873              
1874             # quote metachar
1875 84         141 for (@singleoctet) {
1876 358 50       673 if ($_ eq '...') {
    100          
    100          
    100          
    100          
1877 689         2910 $_ = '-';
1878             }
1879             elsif (/\A \n \z/oxms) {
1880 0         0 $_ = '\n';
1881             }
1882             elsif (/\A \r \z/oxms) {
1883 8         17 $_ = '\r';
1884             }
1885             elsif (/\A ([\x00-\x20\x7F-\xFF]) \z/oxms) {
1886 8         19 $_ = sprintf('\x%02X', CORE::ord $1);
1887             }
1888             elsif (/\A [\x00-\xFF] \z/oxms) {
1889 60         193 $_ = quotemeta $_;
1890             }
1891             }
1892              
1893             # return character list
1894 429         628 return \@singleoctet, \@multipleoctet;
1895             }
1896              
1897             #
1898             # Latin-7 octal escape sequence
1899             #
1900             sub octchr {
1901 358     5 0 1154 my($octdigit) = @_;
1902              
1903 5         13 my @binary = ();
1904 5         6 for my $octal (split(//,$octdigit)) {
1905             push @binary, {
1906             '0' => '000',
1907             '1' => '001',
1908             '2' => '010',
1909             '3' => '011',
1910             '4' => '100',
1911             '5' => '101',
1912             '6' => '110',
1913             '7' => '111',
1914 5         18 }->{$octal};
1915             }
1916 50         193 my $binary = join '', @binary;
1917              
1918             my $octchr = {
1919             # 1234567
1920             1 => pack('B*', "0000000$binary"),
1921             2 => pack('B*', "000000$binary"),
1922             3 => pack('B*', "00000$binary"),
1923             4 => pack('B*', "0000$binary"),
1924             5 => pack('B*', "000$binary"),
1925             6 => pack('B*', "00$binary"),
1926             7 => pack('B*', "0$binary"),
1927             0 => pack('B*', "$binary"),
1928              
1929 5         14 }->{CORE::length($binary) % 8};
1930              
1931 5         53 return $octchr;
1932             }
1933              
1934             #
1935             # Latin-7 hexadecimal escape sequence
1936             #
1937             sub hexchr {
1938 5     5 0 17 my($hexdigit) = @_;
1939              
1940             my $hexchr = {
1941             1 => pack('H*', "0$hexdigit"),
1942             0 => pack('H*', "$hexdigit"),
1943              
1944 5         15 }->{CORE::length($_[0]) % 2};
1945              
1946 5         339 return $hexchr;
1947             }
1948              
1949             #
1950             # Latin-7 open character list for qr
1951             #
1952             sub charlist_qr {
1953              
1954 5     314 0 21 my $modifier = pop @_;
1955 314         560 my @char = @_;
1956              
1957 314         713 my($singleoctet, $multipleoctet) = _charlist(@char, $modifier);
1958 314         850 my @singleoctet = @$singleoctet;
1959 314         627 my @multipleoctet = @$multipleoctet;
1960              
1961             # return character list
1962 314 100       455 if (scalar(@singleoctet) >= 1) {
1963              
1964             # with /i modifier
1965 314 100       681 if ($modifier =~ m/i/oxms) {
1966 236         466 my %singleoctet_ignorecase = ();
1967 22         28 for (@singleoctet) {
1968 22   100     34 while (s/ \A \\x(..) - \\x(..) //oxms or s/ \A \\x((..)) //oxms) {
1969 46         194 for my $ord (hex($1) .. hex($2)) {
1970 46         122 my $char = CORE::chr($ord);
1971 66         105 my $uc = Elatin7::uc($char);
1972 66         98 my $fc = Elatin7::fc($char);
1973 66 100       103 if ($uc eq $fc) {
1974 66         109 $singleoctet_ignorecase{unpack 'C*', $char} = 1;
1975             }
1976             else {
1977 12 50       71 if (CORE::length($fc) == 1) {
1978 54         75 $singleoctet_ignorecase{unpack 'C*', $uc} = 1;
1979 54         108 $singleoctet_ignorecase{unpack 'C*', $fc} = 1;
1980             }
1981             else {
1982 54         177 $singleoctet_ignorecase{unpack 'C*', $uc} = 1;
1983 0         0 push @multipleoctet, join '', map {sprintf('\x%02X',$_)} unpack 'C*', $fc;
  0         0  
1984             }
1985             }
1986             }
1987             }
1988 0 50       0 if ($_ ne '') {
1989 46         89 $singleoctet_ignorecase{unpack 'C*', $_} = 1;
1990             }
1991             }
1992 0         0 my $i = 0;
1993 22         28 my @singleoctet_ignorecase = ();
1994 22         40 for my $ord (0 .. 255) {
1995 22 100       36 if (exists $singleoctet_ignorecase{$ord}) {
1996 5632         6394 push @{$singleoctet_ignorecase[$i]}, $ord;
  96         99  
1997             }
1998             else {
1999 96         181 $i++;
2000             }
2001             }
2002 5536         5525 @singleoctet = ();
2003 22         37 for my $range (@singleoctet_ignorecase) {
2004 22 100       55 if (ref $range) {
2005 3648 100       5691 if (scalar(@{$range}) == 1) {
  56 50       53  
2006 56         86 push @singleoctet, sprintf('\x%02X', @{$range}[0]);
  36         40  
2007             }
2008 36         116 elsif (scalar(@{$range}) == 2) {
2009 20         24 push @singleoctet, sprintf('\x%02X\x%02X', @{$range}[0], @{$range}[-1]);
  0         0  
  0         0  
2010             }
2011             else {
2012 0         0 push @singleoctet, sprintf('\x%02X-\x%02X', @{$range}[0], @{$range}[-1]);
  20         24  
  20         21  
2013             }
2014             }
2015             }
2016             }
2017              
2018 20         83 my $not_anchor = '';
2019              
2020 236         344 push @multipleoctet, join('', $not_anchor, '[', @singleoctet, ']' );
2021             }
2022 236 100       615 if (scalar(@multipleoctet) >= 2) {
2023 314         684 return '(?:' . join('|', @multipleoctet) . ')';
2024             }
2025             else {
2026 6         29 return $multipleoctet[0];
2027             }
2028             }
2029              
2030             #
2031             # Latin-7 open character list for not qr
2032             #
2033             sub charlist_not_qr {
2034              
2035 308     44 0 1261 my $modifier = pop @_;
2036 44         114 my @char = @_;
2037              
2038 44         95 my($singleoctet, $multipleoctet) = _charlist(@char, $modifier);
2039 44         105 my @singleoctet = @$singleoctet;
2040 44         93 my @multipleoctet = @$multipleoctet;
2041              
2042             # with /i modifier
2043 44 100       61 if ($modifier =~ m/i/oxms) {
2044 44         95 my %singleoctet_ignorecase = ();
2045 10         13 for (@singleoctet) {
2046 10   66     13 while (s/ \A \\x(..) - \\x(..) //oxms or s/ \A \\x((..)) //oxms) {
2047 10         42 for my $ord (hex($1) .. hex($2)) {
2048 10         30 my $char = CORE::chr($ord);
2049 30         40 my $uc = Elatin7::uc($char);
2050 30         46 my $fc = Elatin7::fc($char);
2051 30 50       48 if ($uc eq $fc) {
2052 30         48 $singleoctet_ignorecase{unpack 'C*', $char} = 1;
2053             }
2054             else {
2055 0 50       0 if (CORE::length($fc) == 1) {
2056 30         39 $singleoctet_ignorecase{unpack 'C*', $uc} = 1;
2057 30         60 $singleoctet_ignorecase{unpack 'C*', $fc} = 1;
2058             }
2059             else {
2060 30         86 $singleoctet_ignorecase{unpack 'C*', $uc} = 1;
2061 0         0 push @multipleoctet, join '', map {sprintf('\x%02X',$_)} unpack 'C*', $fc;
  0         0  
2062             }
2063             }
2064             }
2065             }
2066 0 50       0 if ($_ ne '') {
2067 10         20 $singleoctet_ignorecase{unpack 'C*', $_} = 1;
2068             }
2069             }
2070 0         0 my $i = 0;
2071 10         12 my @singleoctet_ignorecase = ();
2072 10         17 for my $ord (0 .. 255) {
2073 10 100       21 if (exists $singleoctet_ignorecase{$ord}) {
2074 2560         2822 push @{$singleoctet_ignorecase[$i]}, $ord;
  60         54  
2075             }
2076             else {
2077 60         89 $i++;
2078             }
2079             }
2080 2500         2422 @singleoctet = ();
2081 10         13 for my $range (@singleoctet_ignorecase) {
2082 10 100       23 if (ref $range) {
2083 960 50       1422 if (scalar(@{$range}) == 1) {
  20 50       20  
2084 20         26 push @singleoctet, sprintf('\x%02X', @{$range}[0]);
  0         0  
2085             }
2086 0         0 elsif (scalar(@{$range}) == 2) {
2087 20         28 push @singleoctet, sprintf('\x%02X\x%02X', @{$range}[0], @{$range}[-1]);
  0         0  
  0         0  
2088             }
2089             else {
2090 0         0 push @singleoctet, sprintf('\x%02X-\x%02X', @{$range}[0], @{$range}[-1]);
  20         21  
  20         23  
2091             }
2092             }
2093             }
2094             }
2095              
2096             # return character list
2097 20 50       80 if (scalar(@multipleoctet) >= 1) {
2098 44 0       94 if (scalar(@singleoctet) >= 1) {
2099              
2100             # any character other than multiple-octet and single octet character class
2101 0         0 return '(?!' . join('|', @multipleoctet) . ')(?:[^' . join('', @singleoctet) . '])';
2102             }
2103             else {
2104              
2105             # any character other than multiple-octet character class
2106 0         0 return '(?!' . join('|', @multipleoctet) . ")(?:$your_char)";
2107             }
2108             }
2109             else {
2110 0 50       0 if (scalar(@singleoctet) >= 1) {
2111              
2112             # any character other than single octet character class
2113 44         72 return '(?:[^' . join('', @singleoctet) . '])';
2114             }
2115             else {
2116              
2117             # any character
2118 44         231 return "(?:$your_char)";
2119             }
2120             }
2121             }
2122              
2123             #
2124             # open file in read mode
2125             #
2126             sub _open_r {
2127 0     412   0 my(undef,$file) = @_;
2128 206     206   1903 use Fcntl qw(O_RDONLY);
  206         3817  
  206         24390  
2129 412         1062 return CORE::sysopen($_[0], $file, &O_RDONLY);
2130             }
2131              
2132             #
2133             # open file in append mode
2134             #
2135             sub _open_a {
2136 412     206   15731 my(undef,$file) = @_;
2137 206     206   1330 use Fcntl qw(O_WRONLY O_APPEND O_CREAT);
  206         359  
  206         522645  
2138 206         746 return CORE::sysopen($_[0], $file, &O_WRONLY|&O_APPEND|&O_CREAT);
2139             }
2140              
2141             #
2142             # safe system
2143             #
2144             sub _systemx {
2145              
2146             # P.707 29.2.33. exec
2147             # in Chapter 29: Functions
2148             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
2149             #
2150             # Be aware that in older releases of Perl, exec (and system) did not flush
2151             # your output buffer, so you needed to enable command buffering by setting $|
2152             # on one or more filehandles to avoid lost output in the case of exec, or
2153             # misordererd output in the case of system. This situation was largely remedied
2154             # in the 5.6 release of Perl. (So, 5.005 release not yet.)
2155              
2156             # P.855 exec
2157             # in Chapter 27: Functions
2158             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
2159             #
2160             # In very old release of Perl (before v5.6), exec (and system) did not flush
2161             # your output buffer, so you needed to enable command buffering by setting $|
2162             # on one or more filehandles to avoid lost output with exec or misordered
2163             # output with system.
2164              
2165 206     206   23744 $| = 1;
2166              
2167             # P.565 23.1.2. Cleaning Up Your Environment
2168             # in Chapter 23: Security
2169             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
2170              
2171             # P.656 Cleaning Up Your Environment
2172             # in Chapter 20: Security
2173             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
2174              
2175             # local $ENV{'PATH'} = '.';
2176 206         758 local @ENV{qw(IFS CDPATH ENV BASH_ENV)}; # Make %ENV safer
2177              
2178             # P.707 29.2.33. exec
2179             # in Chapter 29: Functions
2180             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
2181             #
2182             # As we mentioned earlier, exec treats a discrete list of arguments as an
2183             # indication that it should bypass shell processing. However, there is one
2184             # place where you might still get tripped up. The exec call (and system, too)
2185             # will not distinguish between a single scalar argument and an array containing
2186             # only one element.
2187             #
2188             # @args = ("echo surprise"); # just one element in list
2189             # exec @args # still subject to shell escapes
2190             # or die "exec: $!"; # because @args == 1
2191             #
2192             # To avoid this, you can use the PATHNAME syntax, explicitly duplicating the
2193             # first argument as the pathname, which forces the rest of the arguments to be
2194             # interpreted as a list, even if there is only one of them:
2195             #
2196             # exec { $args[0] } @args # safe even with one-argument list
2197             # or die "can't exec @args: $!";
2198              
2199             # P.855 exec
2200             # in Chapter 27: Functions
2201             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
2202             #
2203             # As we mentioned earlier, exec treats a discrete list of arguments as a
2204             # directive to bypass shell processing. However, there is one place where
2205             # you might still get tripped up. The exec call (and system, too) cannot
2206             # distinguish between a single scalar argument and an array containing
2207             # only one element.
2208             #
2209             # @args = ("echo surprise"); # just one element in list
2210             # exec @args # still subject to shell escapes
2211             # || die "exec: $!"; # because @args == 1
2212             #
2213             # To avoid this, use the PATHNAME syntax, explicitly duplicating the first
2214             # argument as the pathname, which forces the rest of the arguments to be
2215             # interpreted as a list, even if there is only one of them:
2216             #
2217             # exec { $args[0] } @args # safe even with one-argument list
2218             # || die "can't exec @args: $!";
2219              
2220 206         1769 return CORE::system { $_[0] } @_; # safe even with one-argument list
  206         443  
2221             }
2222              
2223             #
2224             # Latin-7 order to character (with parameter)
2225             #
2226             sub Elatin7::chr(;$) {
2227              
2228 206 0   0 0 12867355 my $c = @_ ? $_[0] : $_;
2229              
2230 0 0       0 if ($c == 0x00) {
2231 0         0 return "\x00";
2232             }
2233             else {
2234 0         0 my @chr = ();
2235 0         0 while ($c > 0) {
2236 0         0 unshift @chr, ($c % 0x100);
2237 0         0 $c = int($c / 0x100);
2238             }
2239 0         0 return pack 'C*', @chr;
2240             }
2241             }
2242              
2243             #
2244             # Latin-7 order to character (without parameter)
2245             #
2246             sub Elatin7::chr_() {
2247              
2248 0     0 0 0 my $c = $_;
2249              
2250 0 0       0 if ($c == 0x00) {
2251 0         0 return "\x00";
2252             }
2253             else {
2254 0         0 my @chr = ();
2255 0         0 while ($c > 0) {
2256 0         0 unshift @chr, ($c % 0x100);
2257 0         0 $c = int($c / 0x100);
2258             }
2259 0         0 return pack 'C*', @chr;
2260             }
2261             }
2262              
2263             #
2264             # Latin-7 path globbing (with parameter)
2265             #
2266             sub Elatin7::glob($) {
2267              
2268 0 0   0 0 0 if (wantarray) {
2269 0         0 my @glob = _DOS_like_glob(@_);
2270 0         0 for my $glob (@glob) {
2271 0         0 $glob =~ s{ \A (?:\./)+ }{}oxms;
2272             }
2273 0         0 return @glob;
2274             }
2275             else {
2276 0         0 my $glob = _DOS_like_glob(@_);
2277 0         0 $glob =~ s{ \A (?:\./)+ }{}oxms;
2278 0         0 return $glob;
2279             }
2280             }
2281              
2282             #
2283             # Latin-7 path globbing (without parameter)
2284             #
2285             sub Elatin7::glob_() {
2286              
2287 0 0   0 0 0 if (wantarray) {
2288 0         0 my @glob = _DOS_like_glob();
2289 0         0 for my $glob (@glob) {
2290 0         0 $glob =~ s{ \A (?:\./)+ }{}oxms;
2291             }
2292 0         0 return @glob;
2293             }
2294             else {
2295 0         0 my $glob = _DOS_like_glob();
2296 0         0 $glob =~ s{ \A (?:\./)+ }{}oxms;
2297 0         0 return $glob;
2298             }
2299             }
2300              
2301             #
2302             # Latin-7 path globbing via File::DosGlob 1.10
2303             #
2304             # Often I confuse "_dosglob" and "_doglob".
2305             # So, I renamed "_dosglob" to "_DOS_like_glob".
2306             #
2307             my %iter;
2308             my %entries;
2309             sub _DOS_like_glob {
2310              
2311             # context (keyed by second cxix argument provided by core)
2312 0     0   0 my($expr,$cxix) = @_;
2313              
2314             # glob without args defaults to $_
2315 0 0       0 $expr = $_ if not defined $expr;
2316              
2317             # represents the current user's home directory
2318             #
2319             # 7.3. Expanding Tildes in Filenames
2320             # in Chapter 7. File Access
2321             # of ISBN 0-596-00313-7 Perl Cookbook, 2nd Edition.
2322             #
2323             # and File::HomeDir, File::HomeDir::Windows module
2324              
2325             # DOS-like system
2326 0 0       0 if ($^O =~ /\A (?: MSWin32 | NetWare | symbian | dos ) \z/oxms) {
2327 0         0 $expr =~ s{ \A ~ (?= [^/\\] ) }
  0         0  
2328             { my_home_MSWin32() }oxmse;
2329             }
2330              
2331             # UNIX-like system
2332 0 0 0     0 else {
  0         0  
2333             $expr =~ s{ \A ~ ( (?:[^/])* ) }
2334             { $1 ? (CORE::eval(q{(getpwnam($1))[7]})||my_home()) : my_home() }oxmse;
2335             }
2336 0 0       0  
2337 0 0       0 # assume global context if not provided one
2338             $cxix = '_G_' if not defined $cxix;
2339             $iter{$cxix} = 0 if not exists $iter{$cxix};
2340 0 0       0  
2341 0         0 # if we're just beginning, do it all first
2342             if ($iter{$cxix} == 0) {
2343             $entries{$cxix} = [ _do_glob(1, _parse_line($expr)) ];
2344             }
2345 0 0       0  
2346 0         0 # chuck it all out, quick or slow
2347 0         0 if (wantarray) {
  0         0  
2348             delete $iter{$cxix};
2349             return @{delete $entries{$cxix}};
2350 0 0       0 }
  0         0  
2351 0         0 else {
  0         0  
2352             if ($iter{$cxix} = scalar @{$entries{$cxix}}) {
2353             return shift @{$entries{$cxix}};
2354             }
2355 0         0 else {
2356 0         0 # return undef for EOL
2357 0         0 delete $iter{$cxix};
2358             delete $entries{$cxix};
2359             return undef;
2360             }
2361             }
2362             }
2363              
2364             #
2365             # Latin-7 path globbing subroutine
2366             #
2367 0     0   0 sub _do_glob {
2368 0         0  
2369 0         0 my($cond,@expr) = @_;
2370             my @glob = ();
2371             my $fix_drive_relative_paths = 0;
2372 0         0  
2373 0 0       0 OUTER:
2374 0 0       0 for my $expr (@expr) {
2375             next OUTER if not defined $expr;
2376 0         0 next OUTER if $expr eq '';
2377 0         0  
2378 0         0 my @matched = ();
2379 0         0 my @globdir = ();
2380 0         0 my $head = '.';
2381             my $pathsep = '/';
2382             my $tail;
2383 0 0       0  
2384 0         0 # if argument is within quotes strip em and do no globbing
2385 0 0       0 if ($expr =~ /\A " ((?:$q_char)*?) " \z/oxms) {
2386 0 0       0 $expr = $1;
2387 0         0 if ($cond eq 'd') {
2388             if (-d $expr) {
2389             push @glob, $expr;
2390             }
2391 0 0       0 }
2392 0         0 else {
2393             if (-e $expr) {
2394             push @glob, $expr;
2395 0         0 }
2396             }
2397             next OUTER;
2398             }
2399              
2400 0 0       0 # wildcards with a drive prefix such as h:*.pm must be changed
2401 0 0       0 # to h:./*.pm to expand correctly
2402 0         0 if ($^O =~ /\A (?: MSWin32 | NetWare | symbian | dos ) \z/oxms) {
2403             if ($expr =~ s# \A ((?:[A-Za-z]:)?) ([^/\\]) #$1./$2#oxms) {
2404             $fix_drive_relative_paths = 1;
2405             }
2406 0 0       0 }
2407 0 0       0  
2408 0         0 if (($head, $tail) = _parse_path($expr,$pathsep)) {
2409 0         0 if ($tail eq '') {
2410             push @glob, $expr;
2411 0 0       0 next OUTER;
2412 0 0       0 }
2413 0         0 if ($head =~ / \A (?:$q_char)*? [*?] /oxms) {
  0         0  
2414 0         0 if (@globdir = _do_glob('d', $head)) {
2415             push @glob, _do_glob($cond, map {"$_$pathsep$tail"} @globdir);
2416             next OUTER;
2417 0 0 0     0 }
2418 0         0 }
2419             if ($head eq '' or $head =~ /\A [A-Za-z]: \z/oxms) {
2420 0         0 $head .= $pathsep;
2421             }
2422             $expr = $tail;
2423             }
2424 0 0       0  
2425 0 0       0 # If file component has no wildcards, we can avoid opendir
2426 0         0 if ($expr !~ / \A (?:$q_char)*? [*?] /oxms) {
2427             if ($head eq '.') {
2428 0 0 0     0 $head = '';
2429 0         0 }
2430             if ($head ne '' and ($head =~ / \G ($q_char) /oxmsg)[-1] ne $pathsep) {
2431 0         0 $head .= $pathsep;
2432 0 0       0 }
2433 0 0       0 $head .= $expr;
2434 0         0 if ($cond eq 'd') {
2435             if (-d $head) {
2436             push @glob, $head;
2437             }
2438 0 0       0 }
2439 0         0 else {
2440             if (-e $head) {
2441             push @glob, $head;
2442 0         0 }
2443             }
2444 0 0       0 next OUTER;
2445 0         0 }
2446 0         0 opendir(*DIR, $head) or next OUTER;
2447             my @leaf = readdir DIR;
2448 0 0       0 closedir DIR;
2449 0         0  
2450             if ($head eq '.') {
2451 0 0 0     0 $head = '';
2452 0         0 }
2453             if ($head ne '' and ($head =~ / \G ($q_char) /oxmsg)[-1] ne $pathsep) {
2454             $head .= $pathsep;
2455 0         0 }
2456 0         0  
2457 0         0 my $pattern = '';
2458             while ($expr =~ / \G ($q_char) /oxgc) {
2459             my $char = $1;
2460              
2461             # 6.9. Matching Shell Globs as Regular Expressions
2462             # in Chapter 6. Pattern Matching
2463             # of ISBN 0-596-00313-7 Perl Cookbook, 2nd Edition.
2464 0 0       0 # (and so on)
    0          
    0          
2465 0         0  
2466             if ($char eq '*') {
2467             $pattern .= "(?:$your_char)*",
2468 0         0 }
2469             elsif ($char eq '?') {
2470             $pattern .= "(?:$your_char)?", # DOS style
2471             # $pattern .= "(?:$your_char)", # UNIX style
2472 0         0 }
2473             elsif ((my $fc = Elatin7::fc($char)) ne $char) {
2474             $pattern .= $fc;
2475 0         0 }
2476             else {
2477             $pattern .= quotemeta $char;
2478 0     0   0 }
  0         0  
2479             }
2480             my $matchsub = sub { Elatin7::fc($_[0]) =~ /\A $pattern \z/xms };
2481              
2482             # if ($@) {
2483             # print STDERR "$0: $@\n";
2484             # next OUTER;
2485             # }
2486 0         0  
2487 0 0 0     0 INNER:
2488 0         0 for my $leaf (@leaf) {
2489             if ($leaf eq '.' or $leaf eq '..') {
2490 0 0 0     0 next INNER;
2491 0         0 }
2492             if ($cond eq 'd' and not -d "$head$leaf") {
2493             next INNER;
2494 0 0       0 }
2495 0         0  
2496 0         0 if (&$matchsub($leaf)) {
2497             push @matched, "$head$leaf";
2498             next INNER;
2499             }
2500              
2501             # [DOS compatibility special case]
2502 0 0 0     0 # Failed, add a trailing dot and try again, but only...
      0        
2503              
2504             if (Elatin7::index($leaf,'.') == -1 and # if name does not have a dot in it *and*
2505             CORE::length($leaf) <= 8 and # name is shorter than or equal to 8 chars *and*
2506 0 0       0 Elatin7::index($pattern,'\\.') != -1 # pattern has a dot.
2507 0         0 ) {
2508 0         0 if (&$matchsub("$leaf.")) {
2509             push @matched, "$head$leaf";
2510             next INNER;
2511             }
2512 0 0       0 }
2513 0         0 }
2514             if (@matched) {
2515             push @glob, @matched;
2516 0 0       0 }
2517 0         0 }
2518 0         0 if ($fix_drive_relative_paths) {
2519             for my $glob (@glob) {
2520             $glob =~ s# \A ([A-Za-z]:) \./ #$1#oxms;
2521 0         0 }
2522             }
2523             return @glob;
2524             }
2525              
2526             #
2527             # Latin-7 parse line
2528             #
2529 0     0   0 sub _parse_line {
2530              
2531 0         0 my($line) = @_;
2532 0         0  
2533 0         0 $line .= ' ';
2534             my @piece = ();
2535             while ($line =~ /
2536             " ( (?>(?: [^"] )* ) ) " (?>\s+) |
2537             ( (?>(?: [^"\s] )* ) ) (?>\s+)
2538 0 0       0 /oxmsg
2539             ) {
2540 0         0 push @piece, defined($1) ? $1 : $2;
2541             }
2542             return @piece;
2543             }
2544              
2545             #
2546             # Latin-7 parse path
2547             #
2548 0     0   0 sub _parse_path {
2549              
2550 0         0 my($path,$pathsep) = @_;
2551 0         0  
2552 0         0 $path .= '/';
2553             my @subpath = ();
2554             while ($path =~ /
2555             ((?: [^\/\\] )+?) [\/\\]
2556 0         0 /oxmsg
2557             ) {
2558             push @subpath, $1;
2559 0         0 }
2560 0         0  
2561 0         0 my $tail = pop @subpath;
2562             my $head = join $pathsep, @subpath;
2563             return $head, $tail;
2564             }
2565              
2566             #
2567             # via File::HomeDir::Windows 1.00
2568             #
2569             sub my_home_MSWin32 {
2570              
2571             # A lot of unix people and unix-derived tools rely on
2572 0 0 0 0 0 0 # the ability to overload HOME. We will support it too
    0 0        
    0 0        
      0        
      0        
2573 0         0 # so that they can replace raw HOME calls with File::HomeDir.
2574             if (exists $ENV{'HOME'} and $ENV{'HOME'}) {
2575             return $ENV{'HOME'};
2576             }
2577              
2578 0         0 # Do we have a user profile?
2579             elsif (exists $ENV{'USERPROFILE'} and $ENV{'USERPROFILE'}) {
2580             return $ENV{'USERPROFILE'};
2581             }
2582              
2583 0         0 # Some Windows use something like $ENV{'HOME'}
2584             elsif (exists $ENV{'HOMEDRIVE'} and exists $ENV{'HOMEPATH'} and $ENV{'HOMEDRIVE'} and $ENV{'HOMEPATH'}) {
2585             return join '', $ENV{'HOMEDRIVE'}, $ENV{'HOMEPATH'};
2586 0         0 }
2587              
2588             return undef;
2589             }
2590              
2591             #
2592             # via File::HomeDir::Unix 1.00
2593 0     0 0 0 #
2594             sub my_home {
2595 0 0 0     0 my $home;
    0 0        
2596 0         0  
2597             if (exists $ENV{'HOME'} and defined $ENV{'HOME'}) {
2598             $home = $ENV{'HOME'};
2599             }
2600              
2601             # This is from the original code, but I'm guessing
2602 0         0 # it means "login directory" and exists on some Unixes.
2603             elsif (exists $ENV{'LOGDIR'} and $ENV{'LOGDIR'}) {
2604             $home = $ENV{'LOGDIR'};
2605             }
2606              
2607             ### More-desperate methods
2608              
2609 0         0 # Light desperation on any (Unixish) platform
2610             else {
2611             $home = CORE::eval q{ (getpwuid($<))[7] };
2612             }
2613              
2614 0 0 0     0 # On Unix in general, a non-existant home means "no home"
2615 0         0 # For example, "nobody"-like users might use /nonexistant
2616             if (defined $home and ! -d($home)) {
2617 0         0 $home = undef;
2618             }
2619             return $home;
2620             }
2621              
2622             #
2623             # ${^PREMATCH}, $PREMATCH, $` the string preceding what was matched
2624 0     0 0 0 #
2625             sub Elatin7::PREMATCH {
2626             return $`;
2627             }
2628              
2629             #
2630             # ${^MATCH}, $MATCH, $& the string that matched
2631 0     0 0 0 #
2632             sub Elatin7::MATCH {
2633             return $&;
2634             }
2635              
2636             #
2637             # ${^POSTMATCH}, $POSTMATCH, $' the string following what was matched
2638 0     0 0 0 #
2639             sub Elatin7::POSTMATCH {
2640             return $';
2641             }
2642              
2643             #
2644             # Latin-7 character to order (with parameter)
2645             #
2646 0 0   0 1 0 sub Latin7::ord(;$) {
2647              
2648 0 0       0 local $_ = shift if @_;
2649 0         0  
2650 0         0 if (/\A ($q_char) /oxms) {
2651 0         0 my @ord = unpack 'C*', $1;
2652 0         0 my $ord = 0;
2653             while (my $o = shift @ord) {
2654 0         0 $ord = $ord * 0x100 + $o;
2655             }
2656             return $ord;
2657 0         0 }
2658             else {
2659             return CORE::ord $_;
2660             }
2661             }
2662              
2663             #
2664             # Latin-7 character to order (without parameter)
2665             #
2666 0 0   0 0 0 sub Latin7::ord_() {
2667 0         0  
2668 0         0 if (/\A ($q_char) /oxms) {
2669 0         0 my @ord = unpack 'C*', $1;
2670 0         0 my $ord = 0;
2671             while (my $o = shift @ord) {
2672 0         0 $ord = $ord * 0x100 + $o;
2673             }
2674             return $ord;
2675 0         0 }
2676             else {
2677             return CORE::ord $_;
2678             }
2679             }
2680              
2681             #
2682             # Latin-7 reverse
2683             #
2684 0 0   0 0 0 sub Latin7::reverse(@) {
2685 0         0  
2686             if (wantarray) {
2687             return CORE::reverse @_;
2688             }
2689             else {
2690              
2691             # One of us once cornered Larry in an elevator and asked him what
2692             # problem he was solving with this, but he looked as far off into
2693             # the distance as he could in an elevator and said, "It seemed like
2694 0         0 # a good idea at the time."
2695              
2696             return join '', CORE::reverse(join('',@_) =~ /\G ($q_char) /oxmsg);
2697             }
2698             }
2699              
2700             #
2701             # Latin-7 getc (with parameter, without parameter)
2702             #
2703 0     0 0 0 sub Latin7::getc(;*@) {
2704 0 0       0  
2705 0 0 0     0 my($package) = caller;
2706             my $fh = @_ ? qualify_to_ref(shift,$package) : \*STDIN;
2707 0         0 croak 'Too many arguments for Latin7::getc' if @_ and not wantarray;
  0         0  
2708 0         0  
2709 0         0 my @length = sort { $a <=> $b } keys %range_tr;
2710 0         0 my $getc = '';
2711 0 0       0 for my $length ($length[0] .. $length[-1]) {
2712 0 0       0 $getc .= CORE::getc($fh);
2713 0 0       0 if (exists $range_tr{CORE::length($getc)}) {
2714             if ($getc =~ /\A ${Elatin7::dot_s} \z/oxms) {
2715             return wantarray ? ($getc,@_) : $getc;
2716             }
2717 0 0       0 }
2718             }
2719             return wantarray ? ($getc,@_) : $getc;
2720             }
2721              
2722             #
2723             # Latin-7 length by character
2724             #
2725 0 0   0 1 0 sub Latin7::length(;$) {
2726              
2727 0         0 local $_ = shift if @_;
2728 0         0  
2729             local @_ = /\G ($q_char) /oxmsg;
2730             return scalar @_;
2731             }
2732              
2733             #
2734             # Latin-7 substr by character
2735             #
2736             BEGIN {
2737              
2738             # P.232 The lvalue Attribute
2739             # in Chapter 6: Subroutines
2740             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
2741              
2742             # P.336 The lvalue Attribute
2743             # in Chapter 7: Subroutines
2744             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
2745              
2746             # P.144 8.4 Lvalue subroutines
2747             # in Chapter 8: perlsub: Perl subroutines
2748 206 50 0 206 1 123279 # 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         0  
  0         0  
  0         0  
  0         0  
  0         0  
2749              
2750             CORE::eval sprintf(<<'END', ($] >= 5.014000) ? ':lvalue' : '');
2751             # vv----------------------*******
2752             sub Latin7::substr($$;$$) %s {
2753              
2754             my @char = $_[0] =~ /\G (?>$q_char) /oxmsg;
2755              
2756             # If the substring is beyond either end of the string, substr() returns the undefined
2757             # value and produces a warning. When used as an lvalue, specifying a substring that
2758             # is entirely outside the string raises an exception.
2759             # http://perldoc.perl.org/functions/substr.html
2760              
2761             # A return with no argument returns the scalar value undef in scalar context,
2762             # an empty list () in list context, and (naturally) nothing at all in void
2763             # context.
2764              
2765             my $offset = $_[1];
2766             if (($offset > scalar(@char)) or ($offset < (-1 * scalar(@char)))) {
2767             return;
2768             }
2769              
2770             # substr($string,$offset,$length,$replacement)
2771             if (@_ == 4) {
2772             my(undef,undef,$length,$replacement) = @_;
2773             my $substr = join '', splice(@char, $offset, $length, $replacement);
2774             $_[0] = join '', @char;
2775              
2776             # return $substr; this doesn't work, don't say "return"
2777             $substr;
2778             }
2779              
2780             # substr($string,$offset,$length)
2781             elsif (@_ == 3) {
2782             my(undef,undef,$length) = @_;
2783             my $octet_offset = 0;
2784             my $octet_length = 0;
2785             if ($offset == 0) {
2786             $octet_offset = 0;
2787             }
2788             elsif ($offset > 0) {
2789             local $SIG{__WARN__} = sub {}; # avoid: Use of uninitialized value in join or string at here
2790             $octet_offset = CORE::length(join '', @char[0..$offset-1]);
2791             }
2792             else {
2793             local $SIG{__WARN__} = sub {}; # avoid: Use of uninitialized value in join or string at here
2794             $octet_offset = -1 * CORE::length(join '', @char[$#char+$offset+1..$#char]);
2795             }
2796             if ($length == 0) {
2797             $octet_length = 0;
2798             }
2799             elsif ($length > 0) {
2800             local $SIG{__WARN__} = sub {}; # avoid: Use of uninitialized value in join or string at here
2801             $octet_length = CORE::length(join '', @char[$offset..$offset+$length-1]);
2802             }
2803             else {
2804             local $SIG{__WARN__} = sub {}; # avoid: Use of uninitialized value in join or string at here
2805             $octet_length = -1 * CORE::length(join '', @char[$#char+$length+1..$#char]);
2806             }
2807             CORE::substr($_[0], $octet_offset, $octet_length);
2808             }
2809              
2810             # substr($string,$offset)
2811             else {
2812             my $octet_offset = 0;
2813             if ($offset == 0) {
2814             $octet_offset = 0;
2815             }
2816             elsif ($offset > 0) {
2817             $octet_offset = CORE::length(join '', @char[0..$offset-1]);
2818             }
2819             else {
2820             $octet_offset = -1 * CORE::length(join '', @char[$#char+$offset+1..$#char]);
2821             }
2822             CORE::substr($_[0], $octet_offset);
2823             }
2824             }
2825             END
2826             }
2827              
2828             #
2829             # Latin-7 index by character
2830             #
2831 0     0 1 0 sub Latin7::index($$;$) {
2832 0 0       0  
2833 0         0 my $index;
2834             if (@_ == 3) {
2835             $index = Elatin7::index($_[0], $_[1], CORE::length(Latin7::substr($_[0], 0, $_[2])));
2836 0         0 }
2837             else {
2838             $index = Elatin7::index($_[0], $_[1]);
2839 0 0       0 }
2840 0         0  
2841             if ($index == -1) {
2842             return -1;
2843 0         0 }
2844             else {
2845             return Latin7::length(CORE::substr $_[0], 0, $index);
2846             }
2847             }
2848              
2849             #
2850             # Latin-7 rindex by character
2851             #
2852 0     0 1 0 sub Latin7::rindex($$;$) {
2853 0 0       0  
2854 0         0 my $rindex;
2855             if (@_ == 3) {
2856             $rindex = Elatin7::rindex($_[0], $_[1], CORE::length(Latin7::substr($_[0], 0, $_[2])));
2857 0         0 }
2858             else {
2859             $rindex = Elatin7::rindex($_[0], $_[1]);
2860 0 0       0 }
2861 0         0  
2862             if ($rindex == -1) {
2863             return -1;
2864 0         0 }
2865             else {
2866             return Latin7::length(CORE::substr $_[0], 0, $rindex);
2867             }
2868             }
2869              
2870 206     206   1501 # when 'm//', '/' means regexp match 'm//' and '?' means regexp match '??'
  206         434  
  206         21258  
2871             # when 'div', '/' means division operator and '?' means conditional operator (condition ? then : else)
2872             use vars qw($slash); $slash = 'm//';
2873              
2874             # ord() to ord() or Latin7::ord()
2875             my $function_ord = 'ord';
2876              
2877             # ord to ord or Latin7::ord_
2878             my $function_ord_ = 'ord';
2879              
2880             # reverse to reverse or Latin7::reverse
2881             my $function_reverse = 'reverse';
2882              
2883             # getc to getc or Latin7::getc
2884             my $function_getc = 'getc';
2885              
2886             # P.1023 Appendix W.9 Multibyte Anchoring
2887             # of ISBN 1-56592-224-7 CJKV Information Processing
2888              
2889 206     206   1309 my $anchor = '';
  206     0   408  
  206         6919477  
2890              
2891             use vars qw($nest);
2892              
2893             # regexp of nested parens in qqXX
2894              
2895             # P.340 Matching Nested Constructs with Embedded Code
2896             # in Chapter 7: Perl
2897             # of ISBN 0-596-00289-0 Mastering Regular Expressions, Second edition
2898              
2899             my $qq_paren = qr{(?{local $nest=0}) (?>(?:
2900             [^\\()] |
2901             \( (?{$nest++}) |
2902             \) (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!)) |
2903             \\ [^c] |
2904             \\c[\x40-\x5F] |
2905             [\x00-\xFF]
2906             }xms;
2907              
2908             my $qq_brace = qr{(?{local $nest=0}) (?>(?:
2909             [^\\{}] |
2910             \{ (?{$nest++}) |
2911             \} (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!)) |
2912             \\ [^c] |
2913             \\c[\x40-\x5F] |
2914             [\x00-\xFF]
2915             }xms;
2916              
2917             my $qq_bracket = qr{(?{local $nest=0}) (?>(?:
2918             [^\\\[\]] |
2919             \[ (?{$nest++}) |
2920             \] (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!)) |
2921             \\ [^c] |
2922             \\c[\x40-\x5F] |
2923             [\x00-\xFF]
2924             }xms;
2925              
2926             my $qq_angle = qr{(?{local $nest=0}) (?>(?:
2927             [^\\<>] |
2928             \< (?{$nest++}) |
2929             \> (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!)) |
2930             \\ [^c] |
2931             \\c[\x40-\x5F] |
2932             [\x00-\xFF]
2933             }xms;
2934              
2935             my $qq_scalar = qr{(?: \{ (?:$qq_brace)*? \} |
2936             (?: ::)? (?:
2937             (?> [a-zA-Z_][a-zA-Z_0-9]* (?: ::[a-zA-Z_][a-zA-Z_0-9]*)* )
2938             (?>(?: \[ (?: \$\[ | \$\] | $qq_char )*? \] | \{ (?:$qq_brace)*? \} )*)
2939             (?>(?: (?: -> )? (?: [\$\@\%\&\*]\* | \$\#\* | [\@\%]? \[ (?: \$\[ | \$\] | $qq_char )*? \] | [\@\%\*]? \{ (?:$qq_brace)*? \} ) )*)
2940             ))
2941             }xms;
2942              
2943             my $qq_variable = qr{(?: \{ (?:$qq_brace)*? \} |
2944             (?: ::)? (?:
2945             (?>[0-9]+) |
2946             [^a-zA-Z_0-9\[\]] |
2947             ^[A-Z] |
2948             (?> [a-zA-Z_][a-zA-Z_0-9]* (?: ::[a-zA-Z_][a-zA-Z_0-9]*)* )
2949             (?>(?: \[ (?: \$\[ | \$\] | $qq_char )*? \] | \{ (?:$qq_brace)*? \} )*)
2950             (?>(?: (?: -> )? (?: [\$\@\%\&\*]\* | \$\#\* | [\@\%]? \[ (?: \$\[ | \$\] | $qq_char )*? \] | [\@\%\*]? \{ (?:$qq_brace)*? \} ) )*)
2951             ))
2952             }xms;
2953              
2954             my $qq_substr = qr{(?> Char::substr | Latin7::substr | CORE::substr | substr ) (?>\s*) \( $qq_paren \)
2955             }xms;
2956              
2957             # regexp of nested parens in qXX
2958             my $q_paren = qr{(?{local $nest=0}) (?>(?:
2959             [^()] |
2960             \( (?{$nest++}) |
2961             \) (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!)) |
2962             [\x00-\xFF]
2963             }xms;
2964              
2965             my $q_brace = qr{(?{local $nest=0}) (?>(?:
2966             [^\{\}] |
2967             \{ (?{$nest++}) |
2968             \} (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!)) |
2969             [\x00-\xFF]
2970             }xms;
2971              
2972             my $q_bracket = qr{(?{local $nest=0}) (?>(?:
2973             [^\[\]] |
2974             \[ (?{$nest++}) |
2975             \] (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!)) |
2976             [\x00-\xFF]
2977             }xms;
2978              
2979             my $q_angle = qr{(?{local $nest=0}) (?>(?:
2980             [^<>] |
2981             \< (?{$nest++}) |
2982             \> (?(?{$nest>0})(?{$nest--})|(?!)))*) (?(?{$nest!=0})(?!)) |
2983             [\x00-\xFF]
2984             }xms;
2985              
2986             my $matched = '';
2987             my $s_matched = '';
2988              
2989             my $tr_variable = ''; # variable of tr///
2990             my $sub_variable = ''; # variable of s///
2991             my $bind_operator = ''; # =~ or !~
2992              
2993             my @heredoc = (); # here document
2994             my @heredoc_delimiter = ();
2995             my $here_script = ''; # here script
2996              
2997             #
2998             # escape Latin-7 script
2999 0 50   206 0 0 #
3000             sub Latin7::escape(;$) {
3001             local($_) = $_[0] if @_;
3002              
3003             # P.359 The Study Function
3004             # in Chapter 7: Perl
3005 206         600 # of ISBN 0-596-00289-0 Mastering Regular Expressions, Second edition
3006              
3007             study $_; # Yes, I studied study yesterday.
3008              
3009             # while all script
3010              
3011             # 6.14. Matching from Where the Last Pattern Left Off
3012             # in Chapter 6. Pattern Matching
3013             # of ISBN 0-596-00313-7 Perl Cookbook, 2nd Edition.
3014             # (and so on)
3015              
3016             # one member of Tag-team
3017             #
3018             # P.128 Start of match (or end of previous match): \G
3019             # P.130 Advanced Use of \G with Perl
3020             # in Chapter 3: Overview of Regular Expression Features and Flavors
3021             # P.255 Use leading anchors
3022             # P.256 Expose ^ and \G at the front expressions
3023             # in Chapter 6: Crafting an Efficient Expression
3024             # P.315 "Tag-team" matching with /gc
3025             # in Chapter 7: Perl
3026 206         412 # of ISBN 0-596-00289-0 Mastering Regular Expressions, Second edition
3027 206         318  
3028 206         2505 my $e_script = '';
3029             while (not /\G \z/oxgc) { # member
3030             $e_script .= Latin7::escape_token();
3031 74856         106499 }
3032              
3033             return $e_script;
3034             }
3035              
3036             #
3037             # escape Latin-7 token of script
3038             #
3039             sub Latin7::escape_token {
3040              
3041 206     74856 0 2313 # \n output here document
3042              
3043             my $ignore_modules = join('|', qw(
3044             utf8
3045             bytes
3046             charnames
3047             I18N::Japanese
3048             I18N::Collate
3049             I18N::JExt
3050             File::DosGlob
3051             Wild
3052             Wildcard
3053             Japanese
3054             ));
3055              
3056             # another member of Tag-team
3057             #
3058             # P.315 "Tag-team" matching with /gc
3059             # in Chapter 7: Perl
3060 74856 100 100     81673 # 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          
3061 74856         2623512  
3062 12524 100       14410 if (/\G ( \n ) /oxgc) { # another member (and so on)
3063 12524         20438 my $heredoc = '';
3064             if (scalar(@heredoc_delimiter) >= 1) {
3065 174         209 $slash = 'm//';
3066 174         321  
3067             $heredoc = join '', @heredoc;
3068             @heredoc = ();
3069 174         264  
3070 174         288 # skip here document
3071             for my $heredoc_delimiter (@heredoc_delimiter) {
3072 174         1055 /\G .*? \n $heredoc_delimiter \n/xmsgc;
3073             }
3074 174         305 @heredoc_delimiter = ();
3075              
3076 174         227 $here_script = '';
3077             }
3078             return "\n" . $heredoc;
3079             }
3080 12524         34258  
3081             # ignore space, comment
3082             elsif (/\G ((?>\s+)|\#.*) /oxgc) { return $1; }
3083              
3084             # if (, elsif (, unless (, while (, until (, given (, and when (
3085              
3086             # given, when
3087              
3088             # P.225 The given Statement
3089             # in Chapter 15: Smart Matching and given-when
3090             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
3091              
3092             # P.133 The given Statement
3093             # in Chapter 4: Statements and Declarations
3094             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
3095 17937         51592  
3096 1401         2047 elsif (/\G ( (?: if | elsif | unless | while | until | given | when ) (?>\s*) \( ) /oxgc) {
3097             $slash = 'm//';
3098             return $1;
3099             }
3100              
3101             # scalar variable ($scalar = ...) =~ tr///;
3102             # scalar variable ($scalar = ...) =~ s///;
3103              
3104             # state
3105              
3106             # P.68 Persistent, Private Variables
3107             # in Chapter 4: Subroutines
3108             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
3109              
3110             # P.160 Persistent Lexically Scoped Variables: state
3111             # in Chapter 4: Statements and Declarations
3112             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
3113              
3114             # (and so on)
3115 1401         4040  
3116             elsif (/\G ( \( (?>\s*) (?: local \b | my \b | our \b | state \b )? (?>\s*) \$ $qq_scalar ) /oxgc) {
3117 86 50       154 my $e_string = e_string($1);
    50          
3118 86         1911  
3119 0         0 if (/\G ( (?>\s*) = $qq_paren \) ) ( (?>\s*) (?: =~ | !~ ) (?>\s*) ) (?= (?: tr | y ) \b ) /oxgc) {
3120 0         0 $tr_variable = $e_string . e_string($1);
3121 0         0 $bind_operator = $2;
3122             $slash = 'm//';
3123             return '';
3124 0         0 }
3125 0         0 elsif (/\G ( (?>\s*) = $qq_paren \) ) ( (?>\s*) (?: =~ | !~ ) (?>\s*) ) (?= s \b ) /oxgc) {
3126 0         0 $sub_variable = $e_string . e_string($1);
3127 0         0 $bind_operator = $2;
3128             $slash = 'm//';
3129             return '';
3130 0         0 }
3131 86         146 else {
3132             $slash = 'div';
3133             return $e_string;
3134             }
3135             }
3136              
3137 86         256 # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Elatin7::PREMATCH()
3138 4         6 elsif (/\G ( \$` | \$\{`\} | \$ (?>\s*) PREMATCH \b | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} ) /oxmsgc) {
3139             $slash = 'div';
3140             return q{Elatin7::PREMATCH()};
3141             }
3142              
3143 4         14 # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Elatin7::MATCH()
3144 28         50 elsif (/\G ( \$& | \$\{&\} | \$ (?>\s*) MATCH \b | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} ) /oxmsgc) {
3145             $slash = 'div';
3146             return q{Elatin7::MATCH()};
3147             }
3148              
3149 28         92 # $', ${'} --> $', ${'}
3150 1         2 elsif (/\G ( \$' | \$\{'\} ) /oxmsgc) {
3151             $slash = 'div';
3152             return $1;
3153             }
3154              
3155 1         5 # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Elatin7::POSTMATCH()
3156 3         6 elsif (/\G ( \$ (?>\s*) POSTMATCH \b | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} ) /oxmsgc) {
3157             $slash = 'div';
3158             return q{Elatin7::POSTMATCH()};
3159             }
3160              
3161             # scalar variable $scalar =~ tr///;
3162             # scalar variable $scalar =~ s///;
3163             # substr() =~ tr///;
3164 3         10 # substr() =~ s///;
3165             elsif (/\G ( \$ $qq_scalar | $qq_substr ) /oxgc) {
3166 1673 100       3494 my $scalar = e_string($1);
    100          
3167 1673         5929  
3168 1         2 if (/\G ( (?>\s*) (?: =~ | !~ ) (?>\s*) ) (?= (?: tr | y ) \b ) /oxgc) {
3169 1         2 $tr_variable = $scalar;
3170 1         1 $bind_operator = $1;
3171             $slash = 'm//';
3172             return '';
3173 1         3 }
3174 61         113 elsif (/\G ( (?>\s*) (?: =~ | !~ ) (?>\s*) ) (?= s \b ) /oxgc) {
3175 61         109 $sub_variable = $scalar;
3176 61         78 $bind_operator = $1;
3177             $slash = 'm//';
3178             return '';
3179 61         174 }
3180 1611         2189 else {
3181             $slash = 'div';
3182             return $scalar;
3183             }
3184             }
3185              
3186 1611         3990 # end of statement
3187             elsif (/\G ( [,;] ) /oxgc) {
3188             $slash = 'm//';
3189 4997         6936  
3190             # clear tr/// variable
3191             $tr_variable = '';
3192 4997         5460  
3193             # clear s/// variable
3194 4997         5220 $sub_variable = '';
3195              
3196 4997         5166 $bind_operator = '';
3197              
3198             return $1;
3199             }
3200              
3201 4997         15677 # bareword
3202             elsif (/\G ( \{ (?>\s*) (?: tr | index | rindex | reverse ) (?>\s*) \} ) /oxmsgc) {
3203             return $1;
3204             }
3205              
3206 0         0 # $0 --> $0
3207 2         4 elsif (/\G ( \$ 0 ) /oxmsgc) {
3208             $slash = 'div';
3209             return $1;
3210 2         7 }
3211 0         0 elsif (/\G ( \$ \{ (?>\s*) 0 (?>\s*) \} ) /oxmsgc) {
3212             $slash = 'div';
3213             return $1;
3214             }
3215              
3216 0         0 # $$ --> $$
3217 1         3 elsif (/\G ( \$ \$ ) (?![\w\{]) /oxmsgc) {
3218             $slash = 'div';
3219             return $1;
3220             }
3221              
3222             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
3223 1         3 # $1, $2, $3 --> $1, $2, $3 otherwise
3224 4         8 elsif (/\G \$ ((?>[1-9][0-9]*)) /oxmsgc) {
3225             $slash = 'div';
3226             return e_capture($1);
3227 4         8 }
3228 0         0 elsif (/\G \$ \{ (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} /oxmsgc) {
3229             $slash = 'div';
3230             return e_capture($1);
3231             }
3232              
3233 0         0 # $$foo[ ... ] --> $ $foo->[ ... ]
3234 0         0 elsif (/\G \$ ( \$ (?> [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \[ .+? \] ) /oxmsgc) {
3235             $slash = 'div';
3236             return e_capture($1.'->'.$2);
3237             }
3238              
3239 0         0 # $$foo{ ... } --> $ $foo->{ ... }
3240 0         0 elsif (/\G \$ ( \$ (?> [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \{ .+? \} ) /oxmsgc) {
3241             $slash = 'div';
3242             return e_capture($1.'->'.$2);
3243             }
3244              
3245 0         0 # $$foo
3246 0         0 elsif (/\G \$ ( \$ (?> [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) /oxmsgc) {
3247             $slash = 'div';
3248             return e_capture($1);
3249             }
3250              
3251 0         0 # ${ foo }
3252 0         0 elsif (/\G \$ (?>\s*) \{ ( (?>\s*) (?> [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* ) (?>\s*) ) \} /oxmsgc) {
3253             $slash = 'div';
3254             return '${' . $1 . '}';
3255             }
3256              
3257 0         0 # ${ ... }
3258 0         0 elsif (/\G \$ (?>\s*) \{ (?>\s*) ( $qq_brace ) (?>\s*) \} /oxmsgc) {
3259             $slash = 'div';
3260             return e_capture($1);
3261             }
3262              
3263             # variable or function
3264 0         0 # $ @ % & * $ #
3265 42         63 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) {
3266             $slash = 'div';
3267             return $1;
3268             }
3269             # $ $ $ $ $ $ $ $ $ $ $ $ $ $
3270 42         134 # $ @ # \ ' " / ? ( ) [ ] < >
3271 62         124 elsif (/\G ( \$[\$\@\#\\\'\"\/\?\(\)\[\]\<\>] ) /oxmsgc) {
3272             $slash = 'div';
3273             return $1;
3274             }
3275              
3276 62         216 # while ()
3277             elsif (/\G \b (while (?>\s*) \( (?>\s*) <[\$]?[A-Za-z_][A-Za-z_0-9]*> (?>\s*) \)) \b /oxgc) {
3278             return $1;
3279             }
3280              
3281             # while () --- glob
3282              
3283             # avoid "Error: Runtime exception" of perl version 5.005_03
3284 0         0  
3285             elsif (/\G \b while (?>\s*) \( (?>\s*) < ((?:[^>\0\a\e\f\n\r\t])+?) > (?>\s*) \) \b /oxgc) {
3286             return 'while ($_ = Elatin7::glob("' . $1 . '"))';
3287             }
3288              
3289 0         0 # while (glob)
3290             elsif (/\G \b while (?>\s*) \( (?>\s*) glob (?>\s*) \) /oxgc) {
3291             return 'while ($_ = Elatin7::glob_)';
3292             }
3293              
3294 0         0 # while (glob(WILDCARD))
3295             elsif (/\G \b while (?>\s*) \( (?>\s*) glob \b /oxgc) {
3296             return 'while ($_ = Elatin7::glob';
3297             }
3298 0         0  
  248         530  
3299             # doit if, doit unless, doit while, doit until, doit for, doit when
3300             elsif (/\G \b ( if | unless | while | until | for | when ) \b /oxgc) { $slash = 'm//'; return $1; }
3301 248         892  
  19         32  
3302 19         63 # subroutines of package Elatin7
  0         0  
3303 0         0 elsif (/\G \b (CORE:: | ->(>?\s*) (?: atan2 | [a-z]{2,})) \b /oxgc) { $slash = 'm//'; return $1; }
  13         17  
3304 13         35 elsif (/\G \b Char::eval (?= (?>\s*) \{ ) /oxgc) { $slash = 'm//'; return 'eval'; }
  0         0  
3305 0         0 elsif (/\G \b Latin7::eval (?= (?>\s*) \{ ) /oxgc) { $slash = 'm//'; return 'eval'; }
  114         160  
3306 114         291 elsif (/\G \b Char::eval \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'eval Char::escape'; }
  2         5  
3307 2         5 elsif (/\G \b Latin7::eval \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'eval Latin7::escape'; }
  0         0  
3308 0         0 elsif (/\G \b bytes::substr \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'substr'; }
  2         3  
3309 2         5 elsif (/\G \b chop \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Elatin7::chop'; }
  0         0  
3310 0         0 elsif (/\G \b bytes::index \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'index'; }
  0         0  
3311 0         0 elsif (/\G \b Char::index \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Char::index'; }
  0         0  
3312 0         0 elsif (/\G \b Latin7::index \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Latin7::index'; }
  2         5  
3313 2         6 elsif (/\G \b index \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Elatin7::index'; }
  0         0  
3314 0         0 elsif (/\G \b bytes::rindex \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'rindex'; }
  0         0  
3315 0         0 elsif (/\G \b Char::rindex \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Char::rindex'; }
  0         0  
3316 0         0 elsif (/\G \b Latin7::rindex \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Latin7::rindex'; }
  1         2  
3317 1         4 elsif (/\G \b rindex \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Elatin7::rindex'; }
  0         0  
3318 0         0 elsif (/\G \b lc (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Elatin7::lc'; }
  1         2  
3319 1         4 elsif (/\G \b lcfirst (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Elatin7::lcfirst'; }
  0         0  
3320 0         0 elsif (/\G \b uc (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Elatin7::uc'; }
  6         11  
3321             elsif (/\G \b ucfirst (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Elatin7::ucfirst'; }
3322             elsif (/\G \b fc (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Elatin7::fc'; }
3323 6         16  
  0         0  
3324 0         0 # "-s '' ..." means file test "-s 'filename' ..." (not means "- s/// ...")
  0         0  
3325 0         0 elsif (/\G -s (?>\s*) (\") ((?:$qq_char)+?) (\") /oxgc) { $slash = 'm//'; return '-s ' . e_qq('', $1,$3,$2); }
  0         0  
3326 0         0 elsif (/\G -s (?>\s+) qq (?>\s*) (\#) ((?:$qq_char)+?) (\#) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0         0  
3327 0         0 elsif (/\G -s (?>\s+) qq (?>\s*) (\() ((?:$qq_paren)+?) (\)) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0         0  
3328 0         0 elsif (/\G -s (?>\s+) qq (?>\s*) (\{) ((?:$qq_brace)+?) (\}) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0         0  
3329 0         0 elsif (/\G -s (?>\s+) qq (?>\s*) (\[) ((?:$qq_bracket)+?) (\]) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
  0         0  
3330             elsif (/\G -s (?>\s+) qq (?>\s*) (\<) ((?:$qq_angle)+?) (\>) /oxgc) { $slash = 'm//'; return '-s ' . e_qq('qq',$1,$3,$2); }
3331 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  
3332 0         0  
  0         0  
3333 0         0 elsif (/\G -s (?>\s*) (\') ((?:\\\'|\\\\|$q_char)+?) (\') /oxgc) { $slash = 'm//'; return '-s ' . e_q ('', $1,$3,$2); }
  0         0  
3334 0         0 elsif (/\G -s (?>\s+) q (?>\s*) (\#) ((?:\\\#|\\\\|$q_char)+?) (\#) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0         0  
3335 0         0 elsif (/\G -s (?>\s+) q (?>\s*) (\() ((?:\\\)|\\\\|$q_paren)+?) (\)) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0         0  
3336 0         0 elsif (/\G -s (?>\s+) q (?>\s*) (\{) ((?:\\\}|\\\\|$q_brace)+?) (\}) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0         0  
3337 0         0 elsif (/\G -s (?>\s+) q (?>\s*) (\[) ((?:\\\]|\\\\|$q_bracket)+?) (\]) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
  0         0  
3338             elsif (/\G -s (?>\s+) q (?>\s*) (\<) ((?:\\\>|\\\\|$q_angle)+?) (\>) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
3339             elsif (/\G -s (?>\s+) q (?>\s*) (\S) ((?:\\\1|\\\\|$q_char)+?) (\1) /oxgc) { $slash = 'm//'; return '-s ' . e_q ('q', $1,$3,$2); }
3340 0         0  
  0         0  
3341 0         0 elsif (/\G -s (?>\s*) (\$ (?> \w+ (?: ::\w+)* ) (?: (?: ->)? (?: [\$\@\%\&\*]\* | \$\#\* | \( (?:$qq_paren)*? \) | [\@\%\*]? \{ (?:$qq_brace)+? \} | [\@\%]? \[ (?:$qq_bracket)+? \] ) )*) /oxgc)
  0         0  
3342 0         0 { $slash = 'm//'; return "-s $1"; }
  0         0  
3343 0         0 elsif (/\G -s (?>\s*) \( ((?:$qq_paren)*?) \) /oxgc) { $slash = 'm//'; return "-s ($1)"; }
  0         0  
3344             elsif (/\G -s (?= (?>\s+) [a-z]+) /oxgc) { $slash = 'm//'; return '-s'; }
3345 0         0 elsif (/\G -s (?>\s+) ((?>\w+)) /oxgc) { $slash = 'm//'; return "-s $1"; }
  2         4  
3346 2         6  
  2         4  
3347 2         7 elsif (/\G \b bytes::length (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'length'; }
  36         59  
3348 36         101 elsif (/\G \b bytes::chr (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'chr'; }
  2         3  
3349 2         6 elsif (/\G \b chr (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Elatin7::chr'; }
  8         14  
3350 8         25 elsif (/\G \b bytes::ord (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'div'; return 'ord'; }
  0         0  
3351 0         0 elsif (/\G \b ord (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'div'; return $function_ord; }
  0         0  
3352 0         0 elsif (/\G \b glob (?= (?>\s+)[A-Za-z_]|(?>\s*)['"`\$\@\&\*\(]) /oxgc) { $slash = 'm//'; return 'Elatin7::glob'; }
  0         0  
3353 0         0 elsif (/\G \b lc \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Elatin7::lc_'; }
  0         0  
3354 0         0 elsif (/\G \b lcfirst \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Elatin7::lcfirst_'; }
  0         0  
3355 0         0 elsif (/\G \b uc \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Elatin7::uc_'; }
  0         0  
3356 0         0 elsif (/\G \b ucfirst \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Elatin7::ucfirst_'; }
  0         0  
3357             elsif (/\G \b fc \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Elatin7::fc_'; }
3358 0         0 elsif (/\G -s \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return '-s '; }
  0         0  
3359 0         0  
  0         0  
3360 0         0 elsif (/\G \b bytes::length \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'length'; }
  0         0  
3361 0         0 elsif (/\G \b bytes::chr \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'chr'; }
  0         0  
3362 0         0 elsif (/\G \b chr \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Elatin7::chr_'; }
  0         0  
3363 0         0 elsif (/\G \b bytes::ord \b (?! (?>\s*) => ) /oxgc) { $slash = 'div'; return 'ord'; }
  0         0  
3364 0         0 elsif (/\G \b ord \b (?! (?>\s*) => ) /oxgc) { $slash = 'div'; return $function_ord_; }
  0         0  
3365 0         0 elsif (/\G \b glob \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return 'Elatin7::glob_'; }
  8         19  
3366             elsif (/\G \b reverse \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return $function_reverse; }
3367             elsif (/\G \b getc \b (?! (?>\s*) => ) /oxgc) { $slash = 'm//'; return $function_getc; }
3368 8         29 # split
3369             elsif (/\G \b (split) \b (?! (?>\s*) => ) /oxgc) {
3370 87         162 $slash = 'm//';
3371 87         138  
3372 87         282 my $e = '';
3373             while (/\G ( (?>\s+) | \( | \#.* ) /oxgc) {
3374             $e .= $1;
3375             }
3376 85 100       298  
  87 100       5873  
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    100          
    50          
    50          
    100          
    50          
    100          
    50          
    50          
    50          
3377             # end of split
3378             if (/\G (?= [,;\)\}\]] ) /oxgc) { return 'Elatin7::split' . $e; }
3379 2         8  
3380             # split scalar value
3381             elsif (/\G ( [\$\@\&\*] $qq_scalar ) /oxgc) { return 'Elatin7::split' . $e . e_string($1); }
3382 1         6  
3383 0         0 # split literal space
3384 0         0 elsif (/\G \b qq (\#) [ ] (\#) /oxgc) { return 'Elatin7::split' . $e . qq {qq$1 $2}; }
3385 0         0 elsif (/\G \b qq ((?>\s*)) (\() [ ] (\)) /oxgc) { return 'Elatin7::split' . $e . qq{$1qq$2 $3}; }
3386 0         0 elsif (/\G \b qq ((?>\s*)) (\{) [ ] (\}) /oxgc) { return 'Elatin7::split' . $e . qq{$1qq$2 $3}; }
3387 0         0 elsif (/\G \b qq ((?>\s*)) (\[) [ ] (\]) /oxgc) { return 'Elatin7::split' . $e . qq{$1qq$2 $3}; }
3388 0         0 elsif (/\G \b qq ((?>\s*)) (\<) [ ] (\>) /oxgc) { return 'Elatin7::split' . $e . qq{$1qq$2 $3}; }
3389 0         0 elsif (/\G \b qq ((?>\s*)) (\S) [ ] (\2) /oxgc) { return 'Elatin7::split' . $e . qq{$1qq$2 $3}; }
3390 0         0 elsif (/\G \b q (\#) [ ] (\#) /oxgc) { return 'Elatin7::split' . $e . qq {q$1 $2}; }
3391 0         0 elsif (/\G \b q ((?>\s*)) (\() [ ] (\)) /oxgc) { return 'Elatin7::split' . $e . qq {$1q$2 $3}; }
3392 0         0 elsif (/\G \b q ((?>\s*)) (\{) [ ] (\}) /oxgc) { return 'Elatin7::split' . $e . qq {$1q$2 $3}; }
3393 0         0 elsif (/\G \b q ((?>\s*)) (\[) [ ] (\]) /oxgc) { return 'Elatin7::split' . $e . qq {$1q$2 $3}; }
3394 0         0 elsif (/\G \b q ((?>\s*)) (\<) [ ] (\>) /oxgc) { return 'Elatin7::split' . $e . qq {$1q$2 $3}; }
3395 10         48 elsif (/\G \b q ((?>\s*)) (\S) [ ] (\2) /oxgc) { return 'Elatin7::split' . $e . qq {$1q$2 $3}; }
3396             elsif (/\G ' [ ] ' /oxgc) { return 'Elatin7::split' . $e . qq {' '}; }
3397             elsif (/\G " [ ] " /oxgc) { return 'Elatin7::split' . $e . qq {" "}; }
3398              
3399 0 0       0 # split qq//
  0         0  
3400             elsif (/\G \b (qq) \b /oxgc) {
3401 0         0 if (/\G (\#) ((?:$qq_char)*?) (\#) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq# # --> qr # #
3402 0 0       0 else {
  0 0       0  
    0          
    0          
    0          
    0          
    0          
3403 0         0 while (not /\G \z/oxgc) {
3404 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3405 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq ( ) --> qr ( )
3406 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq { } --> qr { }
3407 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq [ ] --> qr [ ]
3408 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq < > --> qr < >
3409             elsif (/\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) /oxgc) { return e_split($e.'qr','{','}',$2,''); } # qq | | --> qr { }
3410 0         0 elsif (/\G (\S) ((?:$qq_char)*?) (\1) /oxgc) { return e_split($e.'qr',$1,$3,$2,''); } # qq * * --> qr * *
3411             }
3412             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3413             }
3414             }
3415              
3416 0 50       0 # split qr//
  12         410  
3417             elsif (/\G \b (qr) \b /oxgc) {
3418 0         0 if (/\G (\#) ((?:$qq_char)*?) (\#) ([imosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1,$3,$2,$4); } # qr# #
3419 12 50       62 else {
  12 50       3245  
    50          
    50          
    50          
    50          
    50          
    50          
3420 0         0 while (not /\G \z/oxgc) {
3421 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3422 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([imosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # qr ( )
3423 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([imosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # qr { }
3424 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([imosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # qr [ ]
3425 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([imosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # qr < >
3426 0         0 elsif (/\G (\') ((?:$qq_char)*?) (\') ([imosxpadlunbB]*) /oxgc) { return e_split_q($e.'qr',$1, $3, $2,$4); } # qr ' '
3427             elsif (/\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ([imosxpadlunbB]*) /oxgc) { return e_split ($e.'qr','{','}',$2,$4); } # qr | | --> qr { }
3428 12         80 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([imosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # qr * *
3429             }
3430             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3431             }
3432             }
3433              
3434 0 0       0 # split q//
  0         0  
3435             elsif (/\G \b (q) \b /oxgc) {
3436 0         0 if (/\G (\#) ((?:\\\#|\\\\|$q_char)*?) (\#) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q# # --> qr # #
3437 0 0       0 else {
  0 0       0  
    0          
    0          
    0          
    0          
    0          
3438 0         0 while (not /\G \z/oxgc) {
3439 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3440 0         0 elsif (/\G (\() ((?:\\\\|\\\)|\\\(|$q_paren)*?) (\)) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q ( ) --> qr ( )
3441 0         0 elsif (/\G (\{) ((?:\\\\|\\\}|\\\{|$q_brace)*?) (\}) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q { } --> qr { }
3442 0         0 elsif (/\G (\[) ((?:\\\\|\\\]|\\\[|$q_bracket)*?) (\]) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q [ ] --> qr [ ]
3443 0         0 elsif (/\G (\<) ((?:\\\\|\\\>|\\\<|$q_angle)*?) (\>) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q < > --> qr < >
3444             elsif (/\G ([*\-:?\\^|]) ((?:$q_char)*?) (\1) /oxgc) { return e_split_q($e.'qr','{','}',$2,''); } # q | | --> qr { }
3445 0         0 elsif (/\G (\S) ((?:\\\\|\\\1| $q_char)*?) (\1) /oxgc) { return e_split_q($e.'qr',$1,$3,$2,''); } # q * * --> qr * *
3446             }
3447             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3448             }
3449             }
3450              
3451 0 50       0 # split m//
  18         462  
3452             elsif (/\G \b (m) \b /oxgc) {
3453 0         0 if (/\G (\#) ((?:$qq_char)*?) (\#) ([cgimosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1,$3,$2,$4); } # m# # --> qr # #
3454 18 50       73 else {
  18 50       3788  
    50          
    50          
    50          
    50          
    50          
    50          
3455 0         0 while (not /\G \z/oxgc) {
3456 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3457 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cgimosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # m ( ) --> qr ( )
3458 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cgimosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # m { } --> qr { }
3459 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cgimosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # m [ ] --> qr [ ]
3460 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cgimosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # m < > --> qr < >
3461 0         0 elsif (/\G (\') ((?:$qq_char)*?) (\') ([cgimosxpadlunbB]*) /oxgc) { return e_split_q($e.'qr',$1, $3, $2,$4); } # m ' ' --> qr ' '
3462             elsif (/\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ([cgimosxpadlunbB]*) /oxgc) { return e_split ($e.'qr','{','}',$2,$4); } # m | | --> qr { }
3463 18         103 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cgimosxpadlunbB]*) /oxgc) { return e_split ($e.'qr',$1, $3, $2,$4); } # m * * --> qr * *
3464             }
3465             die __FILE__, ": Search pattern not terminated\n";
3466             }
3467             }
3468              
3469 0         0 # split ''
3470 0         0 elsif (/\G (\') /oxgc) {
3471 0 0       0 my $q_string = '';
  0 0       0  
    0          
    0          
3472 0         0 while (not /\G \z/oxgc) {
3473 0         0 if (/\G (\\\\) /oxgc) { $q_string .= $1; }
3474 0         0 elsif (/\G (\\\') /oxgc) { $q_string .= $1; } # splitqr'' --> split qr''
3475             elsif (/\G \' /oxgc) { return e_split_q($e.q{ qr},"'","'",$q_string,''); } # ' ' --> qr ' '
3476 0         0 elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3477             }
3478             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3479             }
3480              
3481 0         0 # split ""
3482 0         0 elsif (/\G (\") /oxgc) {
3483 0 0       0 my $qq_string = '';
  0 0       0  
    0          
    0          
3484 0         0 while (not /\G \z/oxgc) {
3485 0         0 if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
3486 0         0 elsif (/\G (\\\") /oxgc) { $qq_string .= $1; } # splitqr"" --> split qr""
3487             elsif (/\G \" /oxgc) { return e_split($e.q{ qr},'"','"',$qq_string,''); } # " " --> qr " "
3488 0         0 elsif (/\G ($q_char) /oxgc) { $qq_string .= $1; }
3489             }
3490             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3491             }
3492              
3493 0         0 # split //
3494 44         107 elsif (/\G (\/) /oxgc) {
3495 44 50       141 my $regexp = '';
  381 50       1457  
    100          
    50          
3496 0         0 while (not /\G \z/oxgc) {
3497 0         0 if (/\G (\\\\) /oxgc) { $regexp .= $1; }
3498 44         209 elsif (/\G (\\\/) /oxgc) { $regexp .= $1; } # splitqr// --> split qr//
3499             elsif (/\G \/ ([cgimosxpadlunbB]*) /oxgc) { return e_split($e.q{ qr}, '/','/',$regexp,$1); } # / / --> qr / /
3500 337         682 elsif (/\G ($q_char) /oxgc) { $regexp .= $1; }
3501             }
3502             die __FILE__, ": Search pattern not terminated\n";
3503             }
3504             }
3505              
3506             # tr/// or y///
3507              
3508             # about [cdsrbB]* (/B modifier)
3509             #
3510             # P.559 appendix C
3511             # of ISBN 4-89052-384-7 Programming perl
3512             # (Japanese title is: Perl puroguramingu)
3513 0         0  
3514             elsif (/\G \b ( tr | y ) \b /oxgc) {
3515             my $ope = $1;
3516 3 50       6  
3517 3         47 # $1 $2 $3 $4 $5 $6
3518 0         0 if (/\G (\#) ((?:$qq_char)*?) (\#) ((?:$qq_char)*?) (\#) ([cdsrbB]*) /oxgc) { # tr# # #
3519             my @tr = ($tr_variable,$2);
3520             return e_tr(@tr,'',$4,$6);
3521 0         0 }
3522 3         6 else {
3523 3 50       7 my $e = '';
  3 50       213  
    50          
    50          
    50          
    50          
3524             while (not /\G \z/oxgc) {
3525 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3526 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) /oxgc) {
3527 0 0       0 my @tr = ($tr_variable,$2);
  0 0       0  
    0          
    0          
    0          
    0          
3528 0         0 while (not /\G \z/oxgc) {
3529 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3530 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr ( ) ( )
3531 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr ( ) { }
3532 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr ( ) [ ]
3533             elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr ( ) < >
3534 0         0 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr ( ) * *
3535             }
3536             die __FILE__, ": Transliteration replacement not terminated\n";
3537 0         0 }
3538 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) {
3539 0 0       0 my @tr = ($tr_variable,$2);
  0 0       0  
    0          
    0          
    0          
    0          
3540 0         0 while (not /\G \z/oxgc) {
3541 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3542 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr { } ( )
3543 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr { } { }
3544 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr { } [ ]
3545             elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr { } < >
3546 0         0 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr { } * *
3547             }
3548             die __FILE__, ": Transliteration replacement not terminated\n";
3549 0         0 }
3550 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) {
3551 0 0       0 my @tr = ($tr_variable,$2);
  0 0       0  
    0          
    0          
    0          
    0          
3552 0         0 while (not /\G \z/oxgc) {
3553 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3554 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr [ ] ( )
3555 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr [ ] { }
3556 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr [ ] [ ]
3557             elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr [ ] < >
3558 0         0 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr [ ] * *
3559             }
3560             die __FILE__, ": Transliteration replacement not terminated\n";
3561 0         0 }
3562 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) {
3563 0 0       0 my @tr = ($tr_variable,$2);
  0 0       0  
    0          
    0          
    0          
    0          
3564 0         0 while (not /\G \z/oxgc) {
3565 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3566 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr < > ( )
3567 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr < > { }
3568 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr < > [ ]
3569             elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr < > < >
3570 0         0 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cdsrbB]*) /oxgc) { return e_tr(@tr,$e,$2,$4); } # tr < > * *
3571             }
3572             die __FILE__, ": Transliteration replacement not terminated\n";
3573             }
3574 0         0 # $1 $2 $3 $4 $5 $6
3575 3         10 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ((?:$qq_char)*?) (\1) ([cdsrbB]*) /oxgc) { # tr * * *
3576             my @tr = ($tr_variable,$2);
3577             return e_tr(@tr,'',$4,$6);
3578 3         7 }
3579             }
3580             die __FILE__, ": Transliteration pattern not terminated\n";
3581             }
3582             }
3583              
3584 0         0 # qq//
3585             elsif (/\G \b (qq) \b /oxgc) {
3586             my $ope = $1;
3587 2180 50       4521  
3588 2180         3749 # if (/\G (\#) ((?:$qq_char)*?) (\#) /oxgc) { return e_qq($ope,$1,$3,$2); } # qq# #
3589 0         0 if (/\G (\#) /oxgc) { # qq# #
3590 0 0       0 my $qq_string = '';
  0 0       0  
    0          
    0          
3591 0         0 while (not /\G \z/oxgc) {
3592 0         0 if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
3593 0         0 elsif (/\G (\\\#) /oxgc) { $qq_string .= $1; }
3594             elsif (/\G (\#) /oxgc) { return e_qq($ope,'#','#',$qq_string); }
3595 0         0 elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3596             }
3597             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3598             }
3599 0         0  
3600 2180         2714 else {
3601 2180 50       4577 my $e = '';
  2180 50       7571  
    100          
    50          
    50          
    0          
3602             while (not /\G \z/oxgc) {
3603             if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3604              
3605 0         0 # elsif (/\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qq ( )
3606 0         0 elsif (/\G (\() /oxgc) { # qq ( )
3607 0         0 my $qq_string = '';
3608 0 0       0 local $nest = 1;
  0 0       0  
    0          
    0          
    0          
3609 0         0 while (not /\G \z/oxgc) {
3610 0         0 if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0         0  
3611             elsif (/\G (\\\)) /oxgc) { $qq_string .= $1; }
3612 0 0       0 elsif (/\G (\() /oxgc) { $qq_string .= $1; $nest++; }
  0         0  
3613 0         0 elsif (/\G (\)) /oxgc) {
3614             if (--$nest == 0) { return $e . e_qq($ope,'(',')',$qq_string); }
3615 0         0 else { $qq_string .= $1; }
3616             }
3617 0         0 elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3618             }
3619             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3620             }
3621              
3622 0         0 # elsif (/\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qq { }
3623 2150         2649 elsif (/\G (\{) /oxgc) { # qq { }
3624 2150         2715 my $qq_string = '';
3625 2150 100       3942 local $nest = 1;
  84006 50       239824  
    100          
    100          
    50          
3626 722         1321 while (not /\G \z/oxgc) {
3627 0         0 if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  1153         1541  
3628             elsif (/\G (\\\}) /oxgc) { $qq_string .= $1; }
3629 1153 100       1828 elsif (/\G (\{) /oxgc) { $qq_string .= $1; $nest++; }
  3303         4687  
3630 2150         4007 elsif (/\G (\}) /oxgc) {
3631             if (--$nest == 0) { return $e . e_qq($ope,'{','}',$qq_string); }
3632 1153         2191 else { $qq_string .= $1; }
3633             }
3634 78828         144451 elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3635             }
3636             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3637             }
3638              
3639 0         0 # elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qq [ ]
3640 0         0 elsif (/\G (\[) /oxgc) { # qq [ ]
3641 0         0 my $qq_string = '';
3642 0 0       0 local $nest = 1;
  0 0       0  
    0          
    0          
    0          
3643 0         0 while (not /\G \z/oxgc) {
3644 0         0 if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0         0  
3645             elsif (/\G (\\\]) /oxgc) { $qq_string .= $1; }
3646 0 0       0 elsif (/\G (\[) /oxgc) { $qq_string .= $1; $nest++; }
  0         0  
3647 0         0 elsif (/\G (\]) /oxgc) {
3648             if (--$nest == 0) { return $e . e_qq($ope,'[',']',$qq_string); }
3649 0         0 else { $qq_string .= $1; }
3650             }
3651 0         0 elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3652             }
3653             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3654             }
3655              
3656 0         0 # elsif (/\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qq < >
3657 30         51 elsif (/\G (\<) /oxgc) { # qq < >
3658 30         46 my $qq_string = '';
3659 30 100       83 local $nest = 1;
  1166 50       3826  
    50          
    100          
    50          
3660 22         49 while (not /\G \z/oxgc) {
3661 0         0 if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
  0         0  
3662             elsif (/\G (\\\>) /oxgc) { $qq_string .= $1; }
3663 0 50       0 elsif (/\G (\<) /oxgc) { $qq_string .= $1; $nest++; }
  30         58  
3664 30         70 elsif (/\G (\>) /oxgc) {
3665             if (--$nest == 0) { return $e . e_qq($ope,'<','>',$qq_string); }
3666 0         0 else { $qq_string .= $1; }
3667             }
3668 1114         2120 elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3669             }
3670             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3671             }
3672              
3673 0         0 # elsif (/\G (\S) ((?:$qq_char)*?) (\1) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qq * *
3674 0         0 elsif (/\G (\S) /oxgc) { # qq * *
3675 0         0 my $delimiter = $1;
3676 0 0       0 my $qq_string = '';
  0 0       0  
    0          
    0          
3677 0         0 while (not /\G \z/oxgc) {
3678 0         0 if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
3679 0         0 elsif (/\G (\\\Q$delimiter\E) /oxgc) { $qq_string .= $1; }
3680             elsif (/\G (\Q$delimiter\E) /oxgc) { return $e . e_qq($ope,$delimiter,$delimiter,$qq_string); }
3681 0         0 elsif (/\G ($qq_char) /oxgc) { $qq_string .= $1; }
3682             }
3683             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3684 0         0 }
3685             }
3686             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3687             }
3688             }
3689              
3690 0         0 # qr//
3691 0 0       0 elsif (/\G \b (qr) \b /oxgc) {
3692 0         0 my $ope = $1;
3693             if (/\G (\#) ((?:$qq_char)*?) (\#) ([imosxpadlunbB]*) /oxgc) { # qr# # #
3694             return e_qr($ope,$1,$3,$2,$4);
3695 0         0 }
3696 0         0 else {
3697 0 0       0 my $e = '';
  0 0       0  
    0          
    0          
    0          
    0          
    0          
    0          
3698 0         0 while (not /\G \z/oxgc) {
3699 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3700 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([imosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # qr ( )
3701 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([imosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # qr { }
3702 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([imosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # qr [ ]
3703 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([imosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # qr < >
3704 0         0 elsif (/\G (\') ((?:$qq_char)*?) (\') ([imosxpadlunbB]*) /oxgc) { return $e . e_qr_q($ope,$1, $3, $2,$4); } # qr ' '
3705             elsif (/\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ([imosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,'{','}',$2,$4); } # qr | | --> qr { }
3706 0         0 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([imosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # qr * *
3707             }
3708             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3709             }
3710             }
3711              
3712 0         0 # qw//
3713 16 50       46 elsif (/\G \b (qw) \b /oxgc) {
3714 16         69 my $ope = $1;
3715             if (/\G (\#) (.*?) (\#) /oxmsgc) { # qw# #
3716             return e_qw($ope,$1,$3,$2);
3717 0         0 }
3718 16         30 else {
3719 16 50       56 my $e = '';
  16 50       89  
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
3720             while (not /\G \z/oxgc) {
3721 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3722 16         58  
3723             elsif (/\G (\() ([^(]*?) (\)) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw ( )
3724 0         0 elsif (/\G (\() ((?:$q_paren)*?) (\)) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw ( )
3725 0         0  
3726             elsif (/\G (\{) ([^{]*?) (\}) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw { }
3727 0         0 elsif (/\G (\{) ((?:$q_brace)*?) (\}) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw { }
3728 0         0  
3729             elsif (/\G (\[) ([^[]*?) (\]) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw [ ]
3730 0         0 elsif (/\G (\[) ((?:$q_bracket)*?) (\]) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw [ ]
3731 0         0  
3732             elsif (/\G (\<) ([^<]*?) (\>) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw < >
3733 0         0 elsif (/\G (\<) ((?:$q_angle)*?) (\>) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw < >
3734 0         0  
3735             elsif (/\G ([\x21-\x3F]) (.*?) (\1) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw * *
3736 0         0 elsif (/\G (\S) ((?:$q_char)*?) (\1) /oxmsgc) { return $e . e_qw($ope,$1,$3,$2); } # qw * *
3737             }
3738             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3739             }
3740             }
3741              
3742 0         0 # qx//
3743 0 0       0 elsif (/\G \b (qx) \b /oxgc) {
3744 0         0 my $ope = $1;
3745             if (/\G (\#) ((?:$qq_char)*?) (\#) /oxgc) { # qx# #
3746             return e_qq($ope,$1,$3,$2);
3747 0         0 }
3748 0         0 else {
3749 0 0       0 my $e = '';
  0 0       0  
    0          
    0          
    0          
    0          
    0          
3750 0         0 while (not /\G \z/oxgc) {
3751 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3752 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qx ( )
3753 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qx { }
3754 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qx [ ]
3755 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qx < >
3756             elsif (/\G (\') ((?:$qq_char)*?) (\') /oxgc) { return $e . e_q ($ope,$1,$3,$2); } # qx ' '
3757 0         0 elsif (/\G (\S) ((?:$qq_char)*?) (\1) /oxgc) { return $e . e_qq($ope,$1,$3,$2); } # qx * *
3758             }
3759             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3760             }
3761             }
3762              
3763 0         0 # q//
3764             elsif (/\G \b (q) \b /oxgc) {
3765             my $ope = $1;
3766              
3767             # if (/\G (\#) ((?:\\\#|\\\\|$q_char)*?) (\#) /oxgc) { return e_q($ope,$1,$3,$2); } # q# #
3768              
3769             # avoid "Error: Runtime exception" of perl version 5.005_03
3770 410 50       1048 # (and so on)
3771 410         921  
3772 0         0 if (/\G (\#) /oxgc) { # q# #
3773 0 0       0 my $q_string = '';
  0 0       0  
    0          
    0          
3774 0         0 while (not /\G \z/oxgc) {
3775 0         0 if (/\G (\\\\) /oxgc) { $q_string .= $1; }
3776 0         0 elsif (/\G (\\\#) /oxgc) { $q_string .= $1; }
3777             elsif (/\G (\#) /oxgc) { return e_q($ope,'#','#',$q_string); }
3778 0         0 elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3779             }
3780             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3781             }
3782 0         0  
3783 410         642 else {
3784 410 50       1123 my $e = '';
  410 50       1891  
    100          
    50          
    100          
    50          
3785             while (not /\G \z/oxgc) {
3786             if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3787              
3788 0         0 # elsif (/\G (\() ((?:\\\)|\\\\|$q_paren)*?) (\)) /oxgc) { return $e . e_q($ope,$1,$3,$2); } # q ( )
3789 0         0 elsif (/\G (\() /oxgc) { # q ( )
3790 0         0 my $q_string = '';
3791 0 0       0 local $nest = 1;
  0 0       0  
    0          
    0          
    0          
    0          
3792 0         0 while (not /\G \z/oxgc) {
3793 0         0 if (/\G (\\\\) /oxgc) { $q_string .= $1; }
3794 0         0 elsif (/\G (\\\)) /oxgc) { $q_string .= $1; }
  0         0  
3795             elsif (/\G (\\\() /oxgc) { $q_string .= $1; }
3796 0 0       0 elsif (/\G (\() /oxgc) { $q_string .= $1; $nest++; }
  0         0  
3797 0         0 elsif (/\G (\)) /oxgc) {
3798             if (--$nest == 0) { return $e . e_q($ope,'(',')',$q_string); }
3799 0         0 else { $q_string .= $1; }
3800             }
3801 0         0 elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3802             }
3803             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3804             }
3805              
3806 0         0 # elsif (/\G (\{) ((?:\\\}|\\\\|$q_brace)*?) (\}) /oxgc) { return $e . e_q($ope,$1,$3,$2); } # q { }
3807 404         611 elsif (/\G (\{) /oxgc) { # q { }
3808 404         665 my $q_string = '';
3809 404 50       969 local $nest = 1;
  6770 50       22924  
    50          
    100          
    100          
    50          
3810 0         0 while (not /\G \z/oxgc) {
3811 0         0 if (/\G (\\\\) /oxgc) { $q_string .= $1; }
3812 0         0 elsif (/\G (\\\}) /oxgc) { $q_string .= $1; }
  107         154  
3813             elsif (/\G (\\\{) /oxgc) { $q_string .= $1; }
3814 107 100       180 elsif (/\G (\{) /oxgc) { $q_string .= $1; $nest++; }
  511         948  
3815 404         967 elsif (/\G (\}) /oxgc) {
3816             if (--$nest == 0) { return $e . e_q($ope,'{','}',$q_string); }
3817 107         218 else { $q_string .= $1; }
3818             }
3819 6152         11362 elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3820             }
3821             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3822             }
3823              
3824 0         0 # elsif (/\G (\[) ((?:\\\]|\\\\|$q_bracket)*?) (\]) /oxgc) { return $e . e_q($ope,$1,$3,$2); } # q [ ]
3825 0         0 elsif (/\G (\[) /oxgc) { # q [ ]
3826 0         0 my $q_string = '';
3827 0 0       0 local $nest = 1;
  0 0       0  
    0          
    0          
    0          
    0          
3828 0         0 while (not /\G \z/oxgc) {
3829 0         0 if (/\G (\\\\) /oxgc) { $q_string .= $1; }
3830 0         0 elsif (/\G (\\\]) /oxgc) { $q_string .= $1; }
  0         0  
3831             elsif (/\G (\\\[) /oxgc) { $q_string .= $1; }
3832 0 0       0 elsif (/\G (\[) /oxgc) { $q_string .= $1; $nest++; }
  0         0  
3833 0         0 elsif (/\G (\]) /oxgc) {
3834             if (--$nest == 0) { return $e . e_q($ope,'[',']',$q_string); }
3835 0         0 else { $q_string .= $1; }
3836             }
3837 0         0 elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3838             }
3839             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3840             }
3841              
3842 0         0 # elsif (/\G (\<) ((?:\\\>|\\\\|$q_angle)*?) (\>) /oxgc) { return $e . e_q($ope,$1,$3,$2); } # q < >
3843 5         10 elsif (/\G (\<) /oxgc) { # q < >
3844 5         11 my $q_string = '';
3845 5 50       40 local $nest = 1;
  88 50       406  
    50          
    50          
    100          
    50          
3846 0         0 while (not /\G \z/oxgc) {
3847 0         0 if (/\G (\\\\) /oxgc) { $q_string .= $1; }
3848 0         0 elsif (/\G (\\\>) /oxgc) { $q_string .= $1; }
  0         0  
3849             elsif (/\G (\\\<) /oxgc) { $q_string .= $1; }
3850 0 50       0 elsif (/\G (\<) /oxgc) { $q_string .= $1; $nest++; }
  5         15  
3851 5         22 elsif (/\G (\>) /oxgc) {
3852             if (--$nest == 0) { return $e . e_q($ope,'<','>',$q_string); }
3853 0         0 else { $q_string .= $1; }
3854             }
3855 83         176 elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3856             }
3857             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3858             }
3859              
3860 0         0 # elsif (/\G (\S) ((?:\\\1|\\\\|$q_char)*?) (\1) /oxgc) { return $e . e_q($ope,$1,$3,$2); } # q * *
3861 1         3 elsif (/\G (\S) /oxgc) { # q * *
3862 1         2 my $delimiter = $1;
3863 1 50       3 my $q_string = '';
  14 50       72  
    100          
    50          
3864 0         0 while (not /\G \z/oxgc) {
3865 0         0 if (/\G (\\\\) /oxgc) { $q_string .= $1; }
3866 1         3 elsif (/\G (\\\Q$delimiter\E) /oxgc) { $q_string .= $1; }
3867             elsif (/\G (\Q$delimiter\E) /oxgc) { return $e . e_q($ope,$delimiter,$delimiter,$q_string); }
3868 13         19 elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
3869             }
3870             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3871 0         0 }
3872             }
3873             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
3874             }
3875             }
3876              
3877 0         0 # m//
3878 209 50       453 elsif (/\G \b (m) \b /oxgc) {
3879 209         1280 my $ope = $1;
3880             if (/\G (\#) ((?:$qq_char)*?) (\#) ([cgimosxpadlunbB]*) /oxgc) { # m# #
3881             return e_qr($ope,$1,$3,$2,$4);
3882 0         0 }
3883 209         292 else {
3884 209 50       500 my $e = '';
  209 50       10109  
    50          
    50          
    50          
    50          
    100          
    50          
    50          
3885 0         0 while (not /\G \z/oxgc) {
3886 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3887 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cgimosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m ( )
3888 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cgimosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m { }
3889 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cgimosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m [ ]
3890 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cgimosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m < >
3891 10         25 elsif (/\G (\?) ((?:$qq_char)*?) (\?) ([cgimosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m ? ?
3892 0         0 elsif (/\G (\') ((?:$qq_char)*?) (\') ([cgimosxpadlunbB]*) /oxgc) { return $e . e_qr_q($ope,$1, $3, $2,$4); } # m ' '
3893             elsif (/\G ([*\-:\\^|]) ((?:$qq_char)*?) (\1) ([cgimosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,'{','}',$2,$4); } # m | | --> m { }
3894 199         616 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cgimosxpadlunbB]*) /oxgc) { return $e . e_qr ($ope,$1, $3, $2,$4); } # m * *
3895             }
3896             die __FILE__, ": Search pattern not terminated\n";
3897             }
3898             }
3899              
3900             # s///
3901              
3902             # about [cegimosxpradlunbB]* (/cg modifier)
3903             #
3904             # P.67 Pattern-Matching Operators
3905             # of ISBN 0-596-00241-6 Perl in a Nutshell, Second Edition.
3906 0         0  
3907             elsif (/\G \b (s) \b /oxgc) {
3908             my $ope = $1;
3909 97 100       246  
3910 97         1585 # $1 $2 $3 $4 $5 $6
3911             if (/\G (\#) ((?:$qq_char)*?) (\#) ((?:$qq_char)*?) (\#) ([cegimosxpradlunbB]*) /oxgc) { # s# # #
3912             return e_sub($sub_variable,$1,$2,$3,$3,$4,$5,$6);
3913 1         5 }
3914 96         176 else {
3915 96 50       335 my $e = '';
  96 50       11069  
    50          
    50          
    50          
    100          
    50          
    50          
    50          
3916             while (not /\G \z/oxgc) {
3917 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3918 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) /oxgc) {
3919 0 0       0 my @s = ($1,$2,$3);
  0 0       0  
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
3920             while (not /\G \z/oxgc) {
3921 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3922 0         0 # $1 $2 $3 $4
3923 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3924 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3925 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3926 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3927 0         0 elsif (/\G (\') ((?:$qq_char)*?) (\') ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3928 0         0 elsif (/\G (\$) ((?:$qq_char)*?) (\$) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3929 0         0 elsif (/\G (\:) ((?:$qq_char)*?) (\:) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3930             elsif (/\G (\@) ((?:$qq_char)*?) (\@) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3931 0         0 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3932             }
3933             die __FILE__, ": Substitution replacement not terminated\n";
3934 0         0 }
3935 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) {
3936 0 0       0 my @s = ($1,$2,$3);
  0 0       0  
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
3937             while (not /\G \z/oxgc) {
3938 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3939 0         0 # $1 $2 $3 $4
3940 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3941 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3942 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3943 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3944 0         0 elsif (/\G (\') ((?:$qq_char)*?) (\') ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3945 0         0 elsif (/\G (\$) ((?:$qq_char)*?) (\$) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3946 0         0 elsif (/\G (\:) ((?:$qq_char)*?) (\:) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3947             elsif (/\G (\@) ((?:$qq_char)*?) (\@) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3948 0         0 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3949             }
3950             die __FILE__, ": Substitution replacement not terminated\n";
3951 0         0 }
3952 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) {
3953 0 0       0 my @s = ($1,$2,$3);
  0 0       0  
    0          
    0          
    0          
    0          
    0          
    0          
3954             while (not /\G \z/oxgc) {
3955 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3956 0         0 # $1 $2 $3 $4
3957 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3958 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3959 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3960 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([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             elsif (/\G (\$) ((?:$qq_char)*?) (\$) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3963 0         0 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3964             }
3965             die __FILE__, ": Substitution replacement not terminated\n";
3966 0         0 }
3967 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) {
3968 0 0       0 my @s = ($1,$2,$3);
  0 0       0  
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
3969             while (not /\G \z/oxgc) {
3970 0         0 if (/\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
3971 0         0 # $1 $2 $3 $4
3972 0         0 elsif (/\G (\() ((?:$qq_paren)*?) (\)) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3973 0         0 elsif (/\G (\{) ((?:$qq_brace)*?) (\}) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3974 0         0 elsif (/\G (\[) ((?:$qq_bracket)*?) (\]) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3975 0         0 elsif (/\G (\<) ((?:$qq_angle)*?) (\>) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3976 0         0 elsif (/\G (\') ((?:$qq_char)*?) (\') ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3977 0         0 elsif (/\G (\$) ((?:$qq_char)*?) (\$) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3978 0         0 elsif (/\G (\:) ((?:$qq_char)*?) (\:) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3979             elsif (/\G (\@) ((?:$qq_char)*?) (\@) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3980 0         0 elsif (/\G (\S) ((?:$qq_char)*?) (\1) ([cegimosxpradlunbB]*) /oxgc) { return e_sub($sub_variable,@s,$1,$2,$3,$4); }
3981             }
3982             die __FILE__, ": Substitution replacement not terminated\n";
3983             }
3984 0         0 # $1 $2 $3 $4 $5 $6
3985             elsif (/\G (\') ((?:$qq_char)*?) (\') ((?:$qq_char)*?) (\') ([cegimosxpradlunbB]*) /oxgc) {
3986             return e_sub($sub_variable,$1,$2,$3,$3,$4,$5,$6);
3987             }
3988 21         55 # $1 $2 $3 $4 $5 $6
3989             elsif (/\G ([*\-:?\\^|]) ((?:$qq_char)*?) (\1) ((?:$qq_char)*?) (\1) ([cegimosxpradlunbB]*) /oxgc) {
3990             return e_sub($sub_variable,'{',$2,'}','{',$4,'}',$6); # s | | | --> s { } { }
3991             }
3992 0         0 # $1 $2 $3 $4 $5 $6
3993             elsif (/\G (\$) ((?:$qq_char)*?) (\1) ((?:$qq_char)*?) (\1) ([cegimosxpradlunbB]*) /oxgc) {
3994             return e_sub($sub_variable,$1,$2,$3,$3,$4,$5,$6);
3995             }
3996 0         0 # $1 $2 $3 $4 $5 $6
3997             elsif (/\G (\S) ((?:$qq_char)*?) (\1) ((?:$qq_char)*?) (\1) ([cegimosxpradlunbB]*) /oxgc) {
3998             return e_sub($sub_variable,$1,$2,$3,$3,$4,$5,$6);
3999 75         306 }
4000             }
4001             die __FILE__, ": Substitution pattern not terminated\n";
4002             }
4003             }
4004 0         0  
4005 0         0 # require ignore module
4006 0         0 elsif (/\G \b require ((?>\s+) (?:$ignore_modules) .*? ;) ([ \t]* [#\n]) /oxmsgc) { return "# require$1$2"; }
4007             elsif (/\G \b require ((?>\s+) (?:$ignore_modules) .*? ;) ([ \t]* [^#]) /oxmsgc) { return "# require$1\n$2"; }
4008             elsif (/\G \b require ((?>\s+) (?:$ignore_modules)) \b /oxmsgc) { return "# require$1"; }
4009 0         0  
4010 37         345 # use strict; --> use strict; no strict qw(refs);
4011 0         0 elsif (/\G \b use ((?>\s+) strict .*? ;) ([ \t]* [#\n]) /oxmsgc) { return "use$1 no strict qw(refs);$2"; }
4012             elsif (/\G \b use ((?>\s+) strict .*? ;) ([ \t]* [^#]) /oxmsgc) { return "use$1 no strict qw(refs);\n$2"; }
4013             elsif (/\G \b use ((?>\s+) strict) \b /oxmsgc) { return "use$1; no strict qw(refs)"; }
4014              
4015 0 50 33     0 # use 5.12.0; --> use 5.12.0; no strict qw(refs);
      33        
4016 2         22 elsif (/\G \b use (?>\s+) ((?>([1-9][0-9_]*)(?:\.([0-9_]+))*)) (?>\s*) ; /oxmsgc) {
4017             if (($2 >= 6) or (($2 == 5) and ($3 ge '012'))) {
4018             return "use $1; no strict qw(refs);";
4019 0         0 }
4020             else {
4021             return "use $1;";
4022             }
4023 2 0 0     11 }
      0        
4024 0         0 elsif (/\G \b use (?>\s+) ((?>v([0-9][0-9_]*)(?:\.([0-9_]+))*)) (?>\s*) ; /oxmsgc) {
4025             if (($2 >= 6) or (($2 == 5) and ($3 >= 12))) {
4026             return "use $1; no strict qw(refs);";
4027 0         0 }
4028             else {
4029             return "use $1;";
4030             }
4031             }
4032 0         0  
4033 2         13 # ignore use module
4034 0         0 elsif (/\G \b use ((?>\s+) (?:$ignore_modules) .*? ;) ([ \t]* [#\n]) /oxmsgc) { return "# use$1$2"; }
4035             elsif (/\G \b use ((?>\s+) (?:$ignore_modules) .*? ;) ([ \t]* [^#]) /oxmsgc) { return "# use$1\n$2"; }
4036             elsif (/\G \b use ((?>\s+) (?:$ignore_modules)) \b /oxmsgc) { return "# use$1"; }
4037 0         0  
4038 0         0 # ignore no module
4039 0         0 elsif (/\G \b no ((?>\s+) (?:$ignore_modules) .*? ;) ([ \t]* [#\n]) /oxmsgc) { return "# no$1$2"; }
4040             elsif (/\G \b no ((?>\s+) (?:$ignore_modules) .*? ;) ([ \t]* [^#]) /oxmsgc) { return "# no$1\n$2"; }
4041             elsif (/\G \b no ((?>\s+) (?:$ignore_modules)) \b /oxmsgc) { return "# no$1"; }
4042 0         0  
4043             # use else
4044             elsif (/\G \b use \b /oxmsgc) { return "use"; }
4045 0         0  
4046             # use else
4047             elsif (/\G \b no \b /oxmsgc) { return "no"; }
4048              
4049 2         8 # ''
4050 848         1660 elsif (/\G (?
4051 848 100       2042 my $q_string = '';
  8254 100       23903  
    100          
    50          
4052 4         10 while (not /\G \z/oxgc) {
4053 48         88 if (/\G (\\\\) /oxgc) { $q_string .= $1; }
4054 848         1900 elsif (/\G (\\\') /oxgc) { $q_string .= $1; }
4055             elsif (/\G \' /oxgc) { return e_q('', "'","'",$q_string); }
4056 7354         13711 elsif (/\G ($q_char) /oxgc) { $q_string .= $1; }
4057             }
4058             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4059             }
4060              
4061 0         0 # ""
4062 1786         3224 elsif (/\G (\") /oxgc) {
4063 1786 100       3903 my $qq_string = '';
  35111 100       91793  
    100          
    50          
4064 67         152 while (not /\G \z/oxgc) {
4065 12         25 if (/\G (\\\\) /oxgc) { $qq_string .= $1; }
4066 1786         3679 elsif (/\G (\\\") /oxgc) { $qq_string .= $1; }
4067             elsif (/\G \" /oxgc) { return e_qq('', '"','"',$qq_string); }
4068 33246         60995 elsif (/\G ($q_char) /oxgc) { $qq_string .= $1; }
4069             }
4070             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4071             }
4072              
4073 0         0 # ``
4074 1         2 elsif (/\G (\`) /oxgc) {
4075 1 50       4 my $qx_string = '';
  19 50       62  
    100          
    50          
4076 0         0 while (not /\G \z/oxgc) {
4077 0         0 if (/\G (\\\\) /oxgc) { $qx_string .= $1; }
4078 1         4 elsif (/\G (\\\`) /oxgc) { $qx_string .= $1; }
4079             elsif (/\G \` /oxgc) { return e_qq('', '`','`',$qx_string); }
4080 18         35 elsif (/\G ($q_char) /oxgc) { $qx_string .= $1; }
4081             }
4082             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4083             }
4084              
4085 0         0 # // --- not divide operator (num / num), not defined-or
4086 453         948 elsif (($slash eq 'm//') and /\G (\/) /oxgc) {
4087 453 50       1132 my $regexp = '';
  4496 50       14166  
    100          
    50          
4088 0         0 while (not /\G \z/oxgc) {
4089 0         0 if (/\G (\\\\) /oxgc) { $regexp .= $1; }
4090 453         1123 elsif (/\G (\\\/) /oxgc) { $regexp .= $1; }
4091             elsif (/\G \/ ([cgimosxpadlunbB]*) /oxgc) { return e_qr('', '/','/',$regexp,$1); }
4092 4043         7697 elsif (/\G ($q_char) /oxgc) { $regexp .= $1; }
4093             }
4094             die __FILE__, ": Search pattern not terminated\n";
4095             }
4096              
4097 0         0 # ?? --- not conditional operator (condition ? then : else)
4098 0         0 elsif (($slash eq 'm//') and /\G (\?) /oxgc) {
4099 0 0       0 my $regexp = '';
  0 0       0  
    0          
    0          
4100 0         0 while (not /\G \z/oxgc) {
4101 0         0 if (/\G (\\\\) /oxgc) { $regexp .= $1; }
4102 0         0 elsif (/\G (\\\?) /oxgc) { $regexp .= $1; }
4103             elsif (/\G \? ([cgimosxpadlunbB]*) /oxgc) { return e_qr('m','?','?',$regexp,$1); }
4104 0         0 elsif (/\G ($q_char) /oxgc) { $regexp .= $1; }
4105             }
4106             die __FILE__, ": Search pattern not terminated\n";
4107             }
4108 0         0  
  0         0  
4109             # <<>> (a safer ARGV)
4110             elsif (/\G ( <<>> ) /oxgc) { $slash = 'm//'; return $1; }
4111 0         0  
  0         0  
4112             # << (bit shift) --- not here document
4113             elsif (/\G ( << (?>\s*) ) (?= [0-9\$\@\&] ) /oxgc) { $slash = 'm//'; return $1; }
4114              
4115 0         0 # <<~'HEREDOC'
4116 6         13 elsif (/\G ( <<~ [\t ]* '([a-zA-Z_0-9]*)' ) /oxgc) {
4117 6         8 $slash = 'm//';
4118             my $here_quote = $1;
4119             my $delimiter = $2;
4120 6 50       11  
4121 6         9 # get here document
4122 6         28 if ($here_script eq '') {
4123             $here_script = CORE::substr $_, pos $_;
4124 6 50       30 $here_script =~ s/.*?\n//oxm;
4125 6         61 }
4126 6         14 if ($here_script =~ s/\A (.*?) \n ([\t ]*) $delimiter \n //xms) {
4127 6         9 my $heredoc = $1;
4128 6         44 my $indent = $2;
4129 6         19 $heredoc =~ s{^$indent}{}msg; # no /ox
4130             push @heredoc, $heredoc . qq{\n$delimiter\n};
4131             push @heredoc_delimiter, qq{\\s*$delimiter};
4132 6         11 }
4133             else {
4134 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4135             }
4136             return qq{<<'$delimiter'};
4137             }
4138              
4139             # <<~\HEREDOC
4140              
4141             # P.66 2.6.6. "Here" Documents
4142             # in Chapter 2: Bits and Pieces
4143             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
4144              
4145             # P.73 "Here" Documents
4146             # in Chapter 2: Bits and Pieces
4147             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
4148 6         24  
4149 3         6 elsif (/\G ( <<~ \\([a-zA-Z_0-9]+) ) /oxgc) {
4150 3         6 $slash = 'm//';
4151             my $here_quote = $1;
4152             my $delimiter = $2;
4153 3 50       4  
4154 3         7 # get here document
4155 3         21 if ($here_script eq '') {
4156             $here_script = CORE::substr $_, pos $_;
4157 3 50       17 $here_script =~ s/.*?\n//oxm;
4158 3         42 }
4159 3         7 if ($here_script =~ s/\A (.*?) \n ([\t ]*) $delimiter \n //xms) {
4160 3         5 my $heredoc = $1;
4161 3         35 my $indent = $2;
4162 3         10 $heredoc =~ s{^$indent}{}msg; # no /ox
4163             push @heredoc, $heredoc . qq{\n$delimiter\n};
4164             push @heredoc_delimiter, qq{\\s*$delimiter};
4165 3         7 }
4166             else {
4167 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4168             }
4169             return qq{<<\\$delimiter};
4170             }
4171              
4172 3         12 # <<~"HEREDOC"
4173 6         13 elsif (/\G ( <<~ [\t ]* "([a-zA-Z_0-9]*)" ) /oxgc) {
4174 6         9 $slash = 'm//';
4175             my $here_quote = $1;
4176             my $delimiter = $2;
4177 6 50       9  
4178 6         12 # get here document
4179 6         18 if ($here_script eq '') {
4180             $here_script = CORE::substr $_, pos $_;
4181 6 50       29 $here_script =~ s/.*?\n//oxm;
4182 6         62 }
4183 6         14 if ($here_script =~ s/\A (.*?) \n ([\t ]*) $delimiter \n //xms) {
4184 6         7 my $heredoc = $1;
4185 6         45 my $indent = $2;
4186 6         18 $heredoc =~ s{^$indent}{}msg; # no /ox
4187             push @heredoc, e_heredoc($heredoc) . qq{\n$delimiter\n};
4188             push @heredoc_delimiter, qq{\\s*$delimiter};
4189 6         14 }
4190             else {
4191 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4192             }
4193             return qq{<<"$delimiter"};
4194             }
4195              
4196 6         21 # <<~HEREDOC
4197 3         5 elsif (/\G ( <<~ ([a-zA-Z_0-9]+) ) /oxgc) {
4198 3         7 $slash = 'm//';
4199             my $here_quote = $1;
4200             my $delimiter = $2;
4201 3 50       4  
4202 3         7 # get here document
4203 3         27 if ($here_script eq '') {
4204             $here_script = CORE::substr $_, pos $_;
4205 3 50       18 $here_script =~ s/.*?\n//oxm;
4206 3         44 }
4207 3         7 if ($here_script =~ s/\A (.*?) \n ([\t ]*) $delimiter \n //xms) {
4208 3         5 my $heredoc = $1;
4209 3         33 my $indent = $2;
4210 3         8 $heredoc =~ s{^$indent}{}msg; # no /ox
4211             push @heredoc, e_heredoc($heredoc) . qq{\n$delimiter\n};
4212             push @heredoc_delimiter, qq{\\s*$delimiter};
4213 3         7 }
4214             else {
4215 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4216             }
4217             return qq{<<$delimiter};
4218             }
4219              
4220 3         12 # <<~`HEREDOC`
4221 6         10 elsif (/\G ( <<~ [\t ]* `([a-zA-Z_0-9]*)` ) /oxgc) {
4222 6         10 $slash = 'm//';
4223             my $here_quote = $1;
4224             my $delimiter = $2;
4225 6 50       19  
4226 6         14 # get here document
4227 6         15 if ($here_script eq '') {
4228             $here_script = CORE::substr $_, pos $_;
4229 6 50       33 $here_script =~ s/.*?\n//oxm;
4230 6         52 }
4231 6         13 if ($here_script =~ s/\A (.*?) \n ([\t ]*) $delimiter \n //xms) {
4232 6         9 my $heredoc = $1;
4233 6         42 my $indent = $2;
4234 6         14 $heredoc =~ s{^$indent}{}msg; # no /ox
4235             push @heredoc, e_heredoc($heredoc) . qq{\n$delimiter\n};
4236             push @heredoc_delimiter, qq{\\s*$delimiter};
4237 6         20 }
4238             else {
4239 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4240             }
4241             return qq{<<`$delimiter`};
4242             }
4243              
4244 6         25 # <<'HEREDOC'
4245 72         124 elsif (/\G ( << '([a-zA-Z_0-9]*)' ) /oxgc) {
4246 72         139 $slash = 'm//';
4247             my $here_quote = $1;
4248             my $delimiter = $2;
4249 72 50       103  
4250 72         150 # get here document
4251 72         355 if ($here_script eq '') {
4252             $here_script = CORE::substr $_, pos $_;
4253 72 50       362 $here_script =~ s/.*?\n//oxm;
4254 72         519 }
4255 72         243 if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4256             push @heredoc, $1 . qq{\n$delimiter\n};
4257             push @heredoc_delimiter, $delimiter;
4258 72         110 }
4259             else {
4260 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4261             }
4262             return $here_quote;
4263             }
4264              
4265             # <<\HEREDOC
4266              
4267             # P.66 2.6.6. "Here" Documents
4268             # in Chapter 2: Bits and Pieces
4269             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
4270              
4271             # P.73 "Here" Documents
4272             # in Chapter 2: Bits and Pieces
4273             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
4274 72         257  
4275 0         0 elsif (/\G ( << \\([a-zA-Z_0-9]+) ) /oxgc) {
4276 0         0 $slash = 'm//';
4277             my $here_quote = $1;
4278             my $delimiter = $2;
4279 0 0       0  
4280 0         0 # get here document
4281 0         0 if ($here_script eq '') {
4282             $here_script = CORE::substr $_, pos $_;
4283 0 0       0 $here_script =~ s/.*?\n//oxm;
4284 0         0 }
4285 0         0 if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4286             push @heredoc, $1 . qq{\n$delimiter\n};
4287             push @heredoc_delimiter, $delimiter;
4288 0         0 }
4289             else {
4290 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4291             }
4292             return $here_quote;
4293             }
4294              
4295 0         0 # <<"HEREDOC"
4296 36         79 elsif (/\G ( << "([a-zA-Z_0-9]*)" ) /oxgc) {
4297 36         85 $slash = 'm//';
4298             my $here_quote = $1;
4299             my $delimiter = $2;
4300 36 50       477  
4301 36         97 # get here document
4302 36         218 if ($here_script eq '') {
4303             $here_script = CORE::substr $_, pos $_;
4304 36 50       213 $here_script =~ s/.*?\n//oxm;
4305 36         783 }
4306 36         112 if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4307             push @heredoc, e_heredoc($1) . qq{\n$delimiter\n};
4308             push @heredoc_delimiter, $delimiter;
4309 36         145 }
4310             else {
4311 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4312             }
4313             return $here_quote;
4314             }
4315              
4316 36         138 # <
4317 42         91 elsif (/\G ( << ([a-zA-Z_0-9]+) ) /oxgc) {
4318 42         88 $slash = 'm//';
4319             my $here_quote = $1;
4320             my $delimiter = $2;
4321 42 50       72  
4322 42         102 # get here document
4323 42         294 if ($here_script eq '') {
4324             $here_script = CORE::substr $_, pos $_;
4325 42 50       347 $here_script =~ s/.*?\n//oxm;
4326 42         577 }
4327 42         152 if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4328             push @heredoc, e_heredoc($1) . qq{\n$delimiter\n};
4329             push @heredoc_delimiter, $delimiter;
4330 42         100 }
4331             else {
4332 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4333             }
4334             return $here_quote;
4335             }
4336              
4337 42         175 # <<`HEREDOC`
4338 0         0 elsif (/\G ( << `([a-zA-Z_0-9]*)` ) /oxgc) {
4339 0         0 $slash = 'm//';
4340             my $here_quote = $1;
4341             my $delimiter = $2;
4342 0 0       0  
4343 0         0 # get here document
4344 0         0 if ($here_script eq '') {
4345             $here_script = CORE::substr $_, pos $_;
4346 0 0       0 $here_script =~ s/.*?\n//oxm;
4347 0         0 }
4348 0         0 if ($here_script =~ s/\A (.*?) \n $delimiter \n //xms) {
4349             push @heredoc, e_heredoc($1) . qq{\n$delimiter\n};
4350             push @heredoc_delimiter, $delimiter;
4351 0         0 }
4352             else {
4353 0         0 die __FILE__, ": Can't find string terminator $delimiter anywhere before EOF\n";
4354             }
4355             return $here_quote;
4356             }
4357              
4358 0         0 # <<= <=> <= < operator
4359             elsif (/\G ( <<= | <=> | <= | < ) (?= (?>\s*) [A-Za-z_0-9'"`\$\@\&\*\(\+\-] )/oxgc) {
4360             return $1;
4361             }
4362              
4363 12         61 #
4364             elsif (/\G (<[\$]?[A-Za-z_][A-Za-z_0-9]*>) /oxgc) {
4365             return $1;
4366             }
4367              
4368             # --- glob
4369              
4370             # avoid "Error: Runtime exception" of perl version 5.005_03
4371 0         0  
4372             elsif (/\G < ((?:[^>\0\a\e\f\n\r\t])+?) > /oxgc) {
4373             return 'Elatin7::glob("' . $1 . '")';
4374             }
4375 0         0  
4376             # __DATA__
4377             elsif (/\G ^ ( __DATA__ \n .*) \z /oxmsgc) { return $1; }
4378 0         0  
4379             # __END__
4380             elsif (/\G ^ ( __END__ \n .*) \z /oxmsgc) { return $1; }
4381              
4382             # \cD Control-D
4383              
4384             # P.68 2.6.8. Other Literal Tokens
4385             # in Chapter 2: Bits and Pieces
4386             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
4387              
4388             # P.76 Other Literal Tokens
4389             # in Chapter 2: Bits and Pieces
4390 204         1414 # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
4391              
4392             elsif (/\G ( \cD .*) \z /oxmsgc) { return $1; }
4393 0         0  
4394             # \cZ Control-Z
4395             elsif (/\G ( \cZ .*) \z /oxmsgc) { return $1; }
4396              
4397             # any operator before div
4398             elsif (/\G (
4399             -- | \+\+ |
4400 0         0 [\)\}\]]
  5083         9431  
4401              
4402             ) /oxgc) { $slash = 'div'; return $1; }
4403              
4404             # yada-yada or triple-dot operator
4405             elsif (/\G (
4406 5083         21230 \.\.\.
  7         16  
4407              
4408             ) /oxgc) { $slash = 'm//'; return q{die('Unimplemented')}; }
4409              
4410             # any operator before m//
4411              
4412             # //, //= (defined-or)
4413              
4414             # P.164 Logical Operators
4415             # in Chapter 10: More Control Structures
4416             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
4417              
4418             # P.119 C-Style Logical (Short-Circuit) Operators
4419             # in Chapter 3: Unary and Binary Operators
4420             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
4421              
4422             # (and so on)
4423              
4424             # ~~
4425              
4426             # P.221 The Smart Match Operator
4427             # in Chapter 15: Smart Matching and given-when
4428             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
4429              
4430             # P.112 Smartmatch Operator
4431             # in Chapter 3: Unary and Binary Operators
4432             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
4433              
4434             # (and so on)
4435              
4436             elsif (/\G ((?>
4437              
4438             !~~ | !~ | != | ! |
4439             %= | % |
4440             &&= | && | &= | &\.= | &\. | & |
4441             -= | -> | - |
4442             :(?>\s*)= |
4443             : |
4444             <<>> |
4445             <<= | <=> | <= | < |
4446             == | => | =~ | = |
4447             >>= | >> | >= | > |
4448             \*\*= | \*\* | \*= | \* |
4449             \+= | \+ |
4450             \.\. | \.= | \. |
4451             \/\/= | \/\/ |
4452             \/= | \/ |
4453             \? |
4454             \\ |
4455             \^= | \^\.= | \^\. | \^ |
4456             \b x= |
4457             \|\|= | \|\| | \|= | \|\.= | \|\. | \| |
4458             ~~ | ~\. | ~ |
4459             \b(?: and | cmp | eq | ge | gt | le | lt | ne | not | or | xor | x )\b |
4460             \b(?: print )\b |
4461              
4462 7         23 [,;\(\{\[]
  8847         15913  
4463              
4464             )) /oxgc) { $slash = 'm//'; return $1; }
4465 8847         35860  
  15165         25969  
4466             # other any character
4467             elsif (/\G ($q_char) /oxgc) { $slash = 'div'; return $1; }
4468              
4469 15165         62409 # system error
4470             else {
4471             die __FILE__, ": Oops, this shouldn't happen!\n";
4472             }
4473             }
4474              
4475 0     1788 0 0 # escape Latin-7 string
4476 1788         3965 sub e_string {
4477             my($string) = @_;
4478 1788         2379 my $e_string = '';
4479              
4480             local $slash = 'm//';
4481              
4482             # P.1024 Appendix W.10 Multibyte Processing
4483             # of ISBN 1-56592-224-7 CJKV Information Processing
4484 1788         2424 # (and so on)
4485              
4486             my @char = $string =~ / \G (?>[^\\]|\\$q_char|$q_char) /oxmsg;
4487 1788 100 66     12602  
4488 1788 50       6975 # without { ... }
4489 1769         3539 if (not (grep(/\A \{ \z/xms, @char) and grep(/\A \} \z/xms, @char))) {
4490             if ($string !~ /<
4491             return $string;
4492             }
4493             }
4494 1769         4002  
4495 19 50       55 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          
4496             while ($string !~ /\G \z/oxgc) {
4497             if (0) {
4498             }
4499 223         3523  
4500 0         0 # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> @{[Elatin7::PREMATCH()]}
4501 0         0 elsif ($string =~ /\G ( \$` | \$\{`\} | \$ (?>\s*) PREMATCH \b | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} ) /oxmsgc) {
4502             $e_string .= q{Elatin7::PREMATCH()};
4503             $slash = 'div';
4504             }
4505              
4506 0         0 # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> @{[Elatin7::MATCH()]}
4507 0         0 elsif ($string =~ /\G ( \$& | \$\{&\} | \$ (?>\s*) MATCH \b | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} ) /oxmsgc) {
4508             $e_string .= q{Elatin7::MATCH()};
4509             $slash = 'div';
4510             }
4511              
4512 0         0 # $', ${'} --> $', ${'}
4513 0         0 elsif ($string =~ /\G ( \$' | \$\{'\} ) /oxmsgc) {
4514             $e_string .= $1;
4515             $slash = 'div';
4516             }
4517              
4518 0         0 # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> @{[Elatin7::POSTMATCH()]}
4519 0         0 elsif ($string =~ /\G ( \$ (?>\s*) POSTMATCH \b | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} ) /oxmsgc) {
4520             $e_string .= q{Elatin7::POSTMATCH()};
4521             $slash = 'div';
4522             }
4523              
4524 0         0 # bareword
4525 0         0 elsif ($string =~ /\G ( \{ (?>\s*) (?: tr | index | rindex | reverse ) (?>\s*) \} ) /oxmsgc) {
4526             $e_string .= $1;
4527             $slash = 'div';
4528             }
4529              
4530 0         0 # $0 --> $0
4531 0         0 elsif ($string =~ /\G ( \$ 0 ) /oxmsgc) {
4532             $e_string .= $1;
4533             $slash = 'div';
4534 0         0 }
4535 0         0 elsif ($string =~ /\G ( \$ \{ (?>\s*) 0 (?>\s*) \} ) /oxmsgc) {
4536             $e_string .= $1;
4537             $slash = 'div';
4538             }
4539              
4540 0         0 # $$ --> $$
4541 0         0 elsif ($string =~ /\G ( \$ \$ ) (?![\w\{]) /oxmsgc) {
4542             $e_string .= $1;
4543             $slash = 'div';
4544             }
4545              
4546             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
4547 0         0 # $1, $2, $3 --> $1, $2, $3 otherwise
4548 0         0 elsif ($string =~ /\G \$ ((?>[1-9][0-9]*)) /oxmsgc) {
4549             $e_string .= e_capture($1);
4550             $slash = 'div';
4551 0         0 }
4552 0         0 elsif ($string =~ /\G \$ \{ (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} /oxmsgc) {
4553             $e_string .= e_capture($1);
4554             $slash = 'div';
4555             }
4556              
4557 0         0 # $$foo[ ... ] --> $ $foo->[ ... ]
4558 0         0 elsif ($string =~ /\G \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \[ .+? \] ) /oxmsgc) {
4559             $e_string .= e_capture($1.'->'.$2);
4560             $slash = 'div';
4561             }
4562              
4563 0         0 # $$foo{ ... } --> $ $foo->{ ... }
4564 0         0 elsif ($string =~ /\G \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \{ .+? \} ) /oxmsgc) {
4565             $e_string .= e_capture($1.'->'.$2);
4566             $slash = 'div';
4567             }
4568              
4569 0         0 # $$foo
4570 0         0 elsif ($string =~ /\G \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) /oxmsgc) {
4571             $e_string .= e_capture($1);
4572             $slash = 'div';
4573             }
4574              
4575 0         0 # ${ foo }
4576 0         0 elsif ($string =~ /\G \$ (?>\s*) \{ ((?> \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* )) \} /oxmsgc) {
4577             $e_string .= '${' . $1 . '}';
4578             $slash = 'div';
4579             }
4580              
4581 0         0 # ${ ... }
4582 3         9 elsif ($string =~ /\G \$ (?>\s*) \{ (?>\s*) ( $qq_brace ) (?>\s*) \} /oxmsgc) {
4583             $e_string .= e_capture($1);
4584             $slash = 'div';
4585             }
4586              
4587             # variable or function
4588 3         13 # $ @ % & * $ #
4589 7         19 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) {
4590             $e_string .= $1;
4591             $slash = 'div';
4592             }
4593             # $ $ $ $ $ $ $ $ $ $ $ $ $ $
4594 7         23 # $ @ # \ ' " / ? ( ) [ ] < >
4595 0         0 elsif ($string =~ /\G ( \$[\$\@\#\\\'\"\/\?\(\)\[\]\<\>] ) /oxmsgc) {
4596             $e_string .= $1;
4597             $slash = 'div';
4598             }
4599              
4600 0         0 # qq//
4601 0 0       0 elsif ($string =~ /\G \b (qq) \b /oxgc) {
4602 0         0 my $ope = $1;
4603             if ($string =~ /\G (\#) ((?:$qq_char)*?) (\#) /oxgc) { # qq# #
4604             $e_string .= e_qq($ope,$1,$3,$2);
4605 0         0 }
4606 0         0 else {
4607 0 0       0 my $e = '';
  0 0       0  
    0          
    0          
    0          
    0          
4608 0         0 while ($string !~ /\G \z/oxgc) {
  0         0  
4609 0         0 if ($string =~ /\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0         0  
4610 0         0 elsif ($string =~ /\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qq ( )
  0         0  
4611 0         0 elsif ($string =~ /\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qq { }
  0         0  
4612 0         0 elsif ($string =~ /\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qq [ ]
  0         0  
4613             elsif ($string =~ /\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qq < >
4614 0         0 elsif ($string =~ /\G (\S) ((?:$qq_char)*?) (\1) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qq * *
4615             }
4616             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4617             }
4618             }
4619              
4620 0         0 # qx//
4621 0 0       0 elsif ($string =~ /\G \b (qx) \b /oxgc) {
4622 0         0 my $ope = $1;
4623             if ($string =~ /\G (\#) ((?:$qq_char)*?) (\#) /oxgc) { # qx# #
4624             $e_string .= e_qq($ope,$1,$3,$2);
4625 0         0 }
4626 0         0 else {
4627 0 0       0 my $e = '';
  0 0       0  
    0          
    0          
    0          
    0          
    0          
4628 0         0 while ($string !~ /\G \z/oxgc) {
  0         0  
4629 0         0 if ($string =~ /\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0         0  
4630 0         0 elsif ($string =~ /\G (\() ((?:$qq_paren)*?) (\)) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qx ( )
  0         0  
4631 0         0 elsif ($string =~ /\G (\{) ((?:$qq_brace)*?) (\}) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qx { }
  0         0  
4632 0         0 elsif ($string =~ /\G (\[) ((?:$qq_bracket)*?) (\]) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qx [ ]
  0         0  
4633 0         0 elsif ($string =~ /\G (\<) ((?:$qq_angle)*?) (\>) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qx < >
  0         0  
4634             elsif ($string =~ /\G (\') ((?:$qq_char)*?) (\') /oxgc) { $e_string .= $e . e_q ($ope,$1,$3,$2); next E_STRING_LOOP; } # qx ' '
4635 0         0 elsif ($string =~ /\G (\S) ((?:$qq_char)*?) (\1) /oxgc) { $e_string .= $e . e_qq($ope,$1,$3,$2); next E_STRING_LOOP; } # qx * *
4636             }
4637             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4638             }
4639             }
4640              
4641 0         0 # q//
4642 0 0       0 elsif ($string =~ /\G \b (q) \b /oxgc) {
4643 0         0 my $ope = $1;
4644             if ($string =~ /\G (\#) ((?:\\\#|\\\\|$q_char)*?) (\#) /oxgc) { # q# #
4645             $e_string .= e_q($ope,$1,$3,$2);
4646 0         0 }
4647 0         0 else {
4648 0 0       0 my $e = '';
  0 0       0  
    0          
    0          
    0          
    0          
4649 0         0 while ($string !~ /\G \z/oxgc) {
  0         0  
4650 0         0 if ($string =~ /\G ((?>\s+)|\#.*) /oxgc) { $e .= $1; }
  0         0  
4651 0         0 elsif ($string =~ /\G (\() ((?:\\\\|\\\)|\\\(|$q_paren)*?) (\)) /oxgc) { $e_string .= $e . e_q($ope,$1,$3,$2); next E_STRING_LOOP; } # q ( )
  0         0  
4652 0         0 elsif ($string =~ /\G (\{) ((?:\\\\|\\\}|\\\{|$q_brace)*?) (\}) /oxgc) { $e_string .= $e . e_q($ope,$1,$3,$2); next E_STRING_LOOP; } # q { }
  0         0  
4653 0         0 elsif ($string =~ /\G (\[) ((?:\\\\|\\\]|\\\[|$q_bracket)*?) (\]) /oxgc) { $e_string .= $e . e_q($ope,$1,$3,$2); next E_STRING_LOOP; } # q [ ]
  0         0  
4654             elsif ($string =~ /\G (\<) ((?:\\\\|\\\>|\\\<|$q_angle)*?) (\>) /oxgc) { $e_string .= $e . e_q($ope,$1,$3,$2); next E_STRING_LOOP; } # q < >
4655 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 * *
4656             }
4657             die __FILE__, ": Can't find string terminator anywhere before EOF\n";
4658             }
4659             }
4660 0         0  
4661             # ''
4662             elsif ($string =~ /\G (?
4663 0         0  
4664             # ""
4665             elsif ($string =~ /\G (\") ((?:$qq_char)*?) (\") /oxgc) { $e_string .= e_qq('',$1,$3,$2); }
4666 0         0  
4667             # ``
4668             elsif ($string =~ /\G (\`) ((?:$qq_char)*?) (\`) /oxgc) { $e_string .= e_qq('',$1,$3,$2); }
4669 0         0  
4670             # other any character
4671             elsif ($string =~ /\G ($q_char) /oxgc) { $e_string .= $1; }
4672              
4673 213         521 # system error
4674             else {
4675             die __FILE__, ": Oops, this shouldn't happen!\n";
4676             }
4677 0         0 }
4678              
4679             return $e_string;
4680             }
4681              
4682             #
4683             # character class
4684 19     1919 0 76 #
4685             sub character_class {
4686 1919 100       3214 my($char,$modifier) = @_;
4687 1919 100       2791  
4688 52         94 if ($char eq '.') {
4689             if ($modifier =~ /s/) {
4690             return '${Elatin7::dot_s}';
4691 17         35 }
4692             else {
4693             return '${Elatin7::dot}';
4694             }
4695 35         69 }
4696             else {
4697             return Elatin7::classic_character_class($char);
4698             }
4699             }
4700              
4701             #
4702             # escape capture ($1, $2, $3, ...)
4703             #
4704 1867     212 0 2958 sub e_capture {
4705              
4706             return join '', '${', $_[0], '}';
4707             }
4708              
4709             #
4710             # escape transliteration (tr/// or y///)
4711 212     3 0 722 #
4712 3         10 sub e_tr {
4713 3   50     4 my($variable,$charclass,$e,$charclass2,$modifier) = @_;
4714             my $e_tr = '';
4715 3         6 $modifier ||= '';
4716              
4717             $slash = 'div';
4718 3         3  
4719             # quote character class 1
4720             $charclass = q_tr($charclass);
4721 3         12  
4722             # quote character class 2
4723             $charclass2 = q_tr($charclass2);
4724 3 50       5  
4725 3 0       6 # /b /B modifier
4726 0         0 if ($modifier =~ tr/bB//d) {
4727             if ($variable eq '') {
4728             $e_tr = qq{tr$charclass$e$charclass2$modifier};
4729 0         0 }
4730             else {
4731             $e_tr = qq{$variable${bind_operator}tr$charclass$e$charclass2$modifier};
4732             }
4733 0 100       0 }
4734 3         6 else {
4735             if ($variable eq '') {
4736             $e_tr = qq{Elatin7::tr(\$_,' =~ ',$charclass,$e$charclass2,'$modifier')};
4737 2         6 }
4738             else {
4739             $e_tr = qq{Elatin7::tr($variable,'$bind_operator',$charclass,$e$charclass2,'$modifier')};
4740             }
4741             }
4742 1         3  
4743 3         4 # clear tr/// variable
4744             $tr_variable = '';
4745 3         3 $bind_operator = '';
4746              
4747             return $e_tr;
4748             }
4749              
4750             #
4751             # quote for escape transliteration (tr/// or y///)
4752 3     6 0 14 #
4753             sub q_tr {
4754             my($charclass) = @_;
4755 6 50       8  
    0          
    0          
    0          
    0          
    0          
4756 6         10 # quote character class
4757             if ($charclass !~ /'/oxms) {
4758             return e_q('', "'", "'", $charclass); # --> q' '
4759 6         8 }
4760             elsif ($charclass !~ /\//oxms) {
4761             return e_q('q', '/', '/', $charclass); # --> q/ /
4762 0         0 }
4763             elsif ($charclass !~ /\#/oxms) {
4764             return e_q('q', '#', '#', $charclass); # --> q# #
4765 0         0 }
4766             elsif ($charclass !~ /[\<\>]/oxms) {
4767             return e_q('q', '<', '>', $charclass); # --> q< >
4768 0         0 }
4769             elsif ($charclass !~ /[\(\)]/oxms) {
4770             return e_q('q', '(', ')', $charclass); # --> q( )
4771 0         0 }
4772             elsif ($charclass !~ /[\{\}]/oxms) {
4773             return e_q('q', '{', '}', $charclass); # --> q{ }
4774 0         0 }
4775 0 0       0 else {
4776 0         0 for my $char (qw( ! " $ % & * + . : = ? @ ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
4777             if ($charclass !~ /\Q$char\E/xms) {
4778             return e_q('q', $char, $char, $charclass);
4779             }
4780             }
4781 0         0 }
4782              
4783             return e_q('q', '{', '}', $charclass);
4784             }
4785              
4786             #
4787             # escape q string (q//, '')
4788 0     1264 0 0 #
4789             sub e_q {
4790 1264         2932 my($ope,$delimiter,$end_delimiter,$string) = @_;
4791              
4792 1264         1640 $slash = 'div';
4793              
4794             return join '', $ope, $delimiter, $string, $end_delimiter;
4795             }
4796              
4797             #
4798             # escape qq string (qq//, "", qx//, ``)
4799 1264     4048 0 5641 #
4800             sub e_qq {
4801 4048         8251 my($ope,$delimiter,$end_delimiter,$string) = @_;
4802              
4803 4048         4908 $slash = 'div';
4804 4048         4478  
4805             my $left_e = 0;
4806             my $right_e = 0;
4807 4048         4213  
4808             # split regexp
4809             my @char = $string =~ /\G((?>
4810             [^\\\$] |
4811             \\x\{ (?>[0-9A-Fa-f]+) \} |
4812             \\o\{ (?>[0-7]+) \} |
4813             \\N\{ (?>[^0-9\}][^\}]*) \} |
4814             \\ $q_char |
4815             \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} |
4816             \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} |
4817             \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} |
4818             \$ (?>\s* [0-9]+) |
4819             \$ (?>\s*) \{ (?>\s* [0-9]+ \s*) \} |
4820             \$ \$ (?![\w\{]) |
4821             \$ (?>\s*) \$ (?>\s*) $qq_variable |
4822             $q_char
4823 4048         124917 ))/oxmsg;
4824              
4825             for (my $i=0; $i <= $#char; $i++) {
4826 4048 50 33     11447  
    50 33        
    100          
    100          
    50          
4827 113799         332490 # "\L\u" --> "\u\L"
4828             if (($char[$i] eq '\L') and ($char[$i+1] eq '\u')) {
4829             @char[$i,$i+1] = @char[$i+1,$i];
4830             }
4831              
4832 0         0 # "\U\l" --> "\l\U"
4833             elsif (($char[$i] eq '\U') and ($char[$i+1] eq '\l')) {
4834             @char[$i,$i+1] = @char[$i+1,$i];
4835             }
4836              
4837 0         0 # octal escape sequence
4838             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
4839             $char[$i] = Elatin7::octchr($1);
4840             }
4841              
4842 1         3 # hexadecimal escape sequence
4843             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
4844             $char[$i] = Elatin7::hexchr($1);
4845             }
4846              
4847 1         5 # \N{CHARNAME} --> N{CHARNAME}
4848             elsif ($char[$i] =~ /\A \\ ( N\{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
4849             $char[$i] = $1;
4850 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          
4851              
4852             if (0) {
4853             }
4854              
4855             # \F
4856             #
4857             # P.69 Table 2-6. Translation escapes
4858             # in Chapter 2: Bits and Pieces
4859             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
4860             # (and so on)
4861 113799         831677  
4862 0 50       0 # \u \l \U \L \F \Q \E
4863 484         977 elsif ($char[$i] =~ /\A ([<>]) \z/oxms) {
4864             if ($right_e < $left_e) {
4865             $char[$i] = '\\' . $char[$i];
4866             }
4867             }
4868             elsif ($char[$i] eq '\u') {
4869              
4870             # "STRING @{[ LIST EXPR ]} MORE STRING"
4871              
4872             # P.257 Other Tricks You Can Do with Hard References
4873             # in Chapter 8: References
4874             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
4875              
4876             # P.353 Other Tricks You Can Do with Hard References
4877             # in Chapter 8: References
4878             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
4879              
4880 0         0 # (and so on)
4881 0         0  
4882             $char[$i] = '@{[Elatin7::ucfirst qq<';
4883             $left_e++;
4884 0         0 }
4885 0         0 elsif ($char[$i] eq '\l') {
4886             $char[$i] = '@{[Elatin7::lcfirst qq<';
4887             $left_e++;
4888 0         0 }
4889 0         0 elsif ($char[$i] eq '\U') {
4890             $char[$i] = '@{[Elatin7::uc qq<';
4891             $left_e++;
4892 0         0 }
4893 0         0 elsif ($char[$i] eq '\L') {
4894             $char[$i] = '@{[Elatin7::lc qq<';
4895             $left_e++;
4896 0         0 }
4897 24         33 elsif ($char[$i] eq '\F') {
4898             $char[$i] = '@{[Elatin7::fc qq<';
4899             $left_e++;
4900 24         47 }
4901 0         0 elsif ($char[$i] eq '\Q') {
4902             $char[$i] = '@{[CORE::quotemeta qq<';
4903             $left_e++;
4904 0 50       0 }
4905 24         40 elsif ($char[$i] eq '\E') {
4906 24         30 if ($right_e < $left_e) {
4907             $char[$i] = '>]}';
4908             $right_e++;
4909 24         39 }
4910             else {
4911             $char[$i] = '';
4912             }
4913 0         0 }
4914 0 0       0 elsif ($char[$i] eq '\Q') {
4915 0         0 while (1) {
4916             if (++$i > $#char) {
4917 0 0       0 last;
4918 0         0 }
4919             if ($char[$i] eq '\E') {
4920             last;
4921             }
4922             }
4923             }
4924             elsif ($char[$i] eq '\E') {
4925             }
4926              
4927             # $0 --> $0
4928             elsif ($char[$i] =~ /\A \$ 0 \z/oxms) {
4929             }
4930             elsif ($char[$i] =~ /\A \$ \{ (?>\s*) 0 (?>\s*) \} \z/oxms) {
4931             }
4932              
4933             # $$ --> $$
4934             elsif ($char[$i] =~ /\A \$\$ \z/oxms) {
4935             }
4936              
4937             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
4938 0         0 # $1, $2, $3 --> $1, $2, $3 otherwise
4939             elsif ($char[$i] =~ /\A \$ ((?>[1-9][0-9]*)) \z/oxms) {
4940             $char[$i] = e_capture($1);
4941 205         508 }
4942             elsif ($char[$i] =~ /\A \$ \{ (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} \z/oxms) {
4943             $char[$i] = e_capture($1);
4944             }
4945              
4946 0         0 # $$foo[ ... ] --> $ $foo->[ ... ]
4947             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \[ (?:$qq_bracket)*? \] ) \z/oxms) {
4948             $char[$i] = e_capture($1.'->'.$2);
4949             }
4950              
4951 0         0 # $$foo{ ... } --> $ $foo->{ ... }
4952             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \{ (?:$qq_brace)*? \} ) \z/oxms) {
4953             $char[$i] = e_capture($1.'->'.$2);
4954             }
4955              
4956 0         0 # $$foo
4957             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) \z/oxms) {
4958             $char[$i] = e_capture($1);
4959             }
4960              
4961 0         0 # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Elatin7::PREMATCH()
4962             elsif ($char[$i] =~ /\A ( \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} ) \z/oxmsgc) {
4963             $char[$i] = '@{[Elatin7::PREMATCH()]}';
4964             }
4965              
4966 44         112 # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Elatin7::MATCH()
4967             elsif ($char[$i] =~ /\A ( \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} ) \z/oxmsgc) {
4968             $char[$i] = '@{[Elatin7::MATCH()]}';
4969             }
4970              
4971 45         118 # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Elatin7::POSTMATCH()
4972             elsif ($char[$i] =~ /\A ( \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} ) \z/oxmsgc) {
4973             $char[$i] = '@{[Elatin7::POSTMATCH()]}';
4974             }
4975              
4976             # ${ foo } --> ${ foo }
4977             elsif ($char[$i] =~ /\A \$ (?>\s*) \{ (?> \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* ) \} \z/oxms) {
4978             }
4979              
4980 33         91 # ${ ... }
4981             elsif ($char[$i] =~ /\A \$ (?>\s*) \{ ( .+ ) \} \z/oxms) {
4982             $char[$i] = e_capture($1);
4983             }
4984             }
4985 0 50       0  
4986 4048         7092 # return string
4987             if ($left_e > $right_e) {
4988 0         0 return join '', $ope, $delimiter, @char, '>]}' x ($left_e - $right_e), $end_delimiter;
4989             }
4990             return join '', $ope, $delimiter, @char, $end_delimiter;
4991             }
4992              
4993             #
4994             # escape qw string (qw//)
4995 4048     16 0 29685 #
4996             sub e_qw {
4997 16         131 my($ope,$delimiter,$end_delimiter,$string) = @_;
4998              
4999             $slash = 'div';
5000 16         53  
  16         203  
5001 483 50       689 # choice again delimiter
    0          
    0          
    0          
    0          
5002 16         89 my %octet = map {$_ => 1} ($string =~ /\G ([\x00-\xFF]) /oxmsg);
5003             if (not $octet{$end_delimiter}) {
5004             return join '', $ope, $delimiter, $string, $end_delimiter;
5005 16         122 }
5006             elsif (not $octet{')'}) {
5007             return join '', $ope, '(', $string, ')';
5008 0         0 }
5009             elsif (not $octet{'}'}) {
5010             return join '', $ope, '{', $string, '}';
5011 0         0 }
5012             elsif (not $octet{']'}) {
5013             return join '', $ope, '[', $string, ']';
5014 0         0 }
5015             elsif (not $octet{'>'}) {
5016             return join '', $ope, '<', $string, '>';
5017 0         0 }
5018 0 0       0 else {
5019 0         0 for my $char (qw( ! " $ % & * + - . / : = ? @ ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
5020             if (not $octet{$char}) {
5021             return join '', $ope, $char, $string, $char;
5022             }
5023             }
5024             }
5025 0         0  
5026 0         0 # qw/AAA BBB C'CC/ --> ('AAA', 'BBB', 'C\'CC')
5027 0         0 my @string = CORE::split(/\s+/, $string);
5028 0         0 for my $string (@string) {
5029 0 0       0 my @octet = $string =~ /\G ([\x00-\xFF]) /oxmsg;
5030 0         0 for my $octet (@octet) {
5031             if ($octet =~ /\A (['\\]) \z/oxms) {
5032             $octet = '\\' . $1;
5033 0         0 }
5034             }
5035 0         0 $string = join '', @octet;
  0         0  
5036             }
5037             return join '', '(', (join ', ', map { "'$_'" } @string), ')';
5038             }
5039              
5040             #
5041             # escape here document (<<"HEREDOC", <
5042 0     93 0 0 #
5043             sub e_heredoc {
5044 93         253 my($string) = @_;
5045              
5046 93         149 $slash = 'm//';
5047              
5048 93         281 my $metachar = qr/[\@\\|]/oxms; # '|' is for <<`HEREDOC`
5049 93         127  
5050             my $left_e = 0;
5051             my $right_e = 0;
5052 93         111  
5053             # split regexp
5054             my @char = $string =~ /\G((?>
5055             [^\\\$] |
5056             \\x\{ (?>[0-9A-Fa-f]+) \} |
5057             \\o\{ (?>[0-7]+) \} |
5058             \\N\{ (?>[^0-9\}][^\}]*) \} |
5059             \\ $q_char |
5060             \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} |
5061             \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} |
5062             \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} |
5063             \$ (?>\s* [0-9]+) |
5064             \$ (?>\s*) \{ (?>\s* [0-9]+ \s*) \} |
5065             \$ \$ (?![\w\{]) |
5066             \$ (?>\s*) \$ (?>\s*) $qq_variable |
5067             $q_char
5068 93         8213 ))/oxmsg;
5069              
5070             for (my $i=0; $i <= $#char; $i++) {
5071 93 50 33     387  
    50 33        
    100          
    100          
    50          
5072 3177         9118 # "\L\u" --> "\u\L"
5073             if (($char[$i] eq '\L') and ($char[$i+1] eq '\u')) {
5074             @char[$i,$i+1] = @char[$i+1,$i];
5075             }
5076              
5077 0         0 # "\U\l" --> "\l\U"
5078             elsif (($char[$i] eq '\U') and ($char[$i+1] eq '\l')) {
5079             @char[$i,$i+1] = @char[$i+1,$i];
5080             }
5081              
5082 0         0 # octal escape sequence
5083             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
5084             $char[$i] = Elatin7::octchr($1);
5085             }
5086              
5087 1         3 # hexadecimal escape sequence
5088             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
5089             $char[$i] = Elatin7::hexchr($1);
5090             }
5091              
5092 1         6 # \N{CHARNAME} --> N{CHARNAME}
5093             elsif ($char[$i] =~ /\A \\ ( N\{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
5094             $char[$i] = $1;
5095 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          
5096              
5097             if (0) {
5098             }
5099 3177         25149  
5100 0 0       0 # \u \l \U \L \F \Q \E
5101 0         0 elsif ($char[$i] =~ /\A ([<>]) \z/oxms) {
5102             if ($right_e < $left_e) {
5103             $char[$i] = '\\' . $char[$i];
5104             }
5105 0         0 }
5106 0         0 elsif ($char[$i] eq '\u') {
5107             $char[$i] = '@{[Elatin7::ucfirst qq<';
5108             $left_e++;
5109 0         0 }
5110 0         0 elsif ($char[$i] eq '\l') {
5111             $char[$i] = '@{[Elatin7::lcfirst qq<';
5112             $left_e++;
5113 0         0 }
5114 0         0 elsif ($char[$i] eq '\U') {
5115             $char[$i] = '@{[Elatin7::uc qq<';
5116             $left_e++;
5117 0         0 }
5118 0         0 elsif ($char[$i] eq '\L') {
5119             $char[$i] = '@{[Elatin7::lc qq<';
5120             $left_e++;
5121 0         0 }
5122 0         0 elsif ($char[$i] eq '\F') {
5123             $char[$i] = '@{[Elatin7::fc qq<';
5124             $left_e++;
5125 0         0 }
5126 0         0 elsif ($char[$i] eq '\Q') {
5127             $char[$i] = '@{[CORE::quotemeta qq<';
5128             $left_e++;
5129 0 0       0 }
5130 0         0 elsif ($char[$i] eq '\E') {
5131 0         0 if ($right_e < $left_e) {
5132             $char[$i] = '>]}';
5133             $right_e++;
5134 0         0 }
5135             else {
5136             $char[$i] = '';
5137             }
5138 0         0 }
5139 0 0       0 elsif ($char[$i] eq '\Q') {
5140 0         0 while (1) {
5141             if (++$i > $#char) {
5142 0 0       0 last;
5143 0         0 }
5144             if ($char[$i] eq '\E') {
5145             last;
5146             }
5147             }
5148             }
5149             elsif ($char[$i] eq '\E') {
5150             }
5151              
5152             # $0 --> $0
5153             elsif ($char[$i] =~ /\A \$ 0 \z/oxms) {
5154             }
5155             elsif ($char[$i] =~ /\A \$ \{ (?>\s*) 0 (?>\s*) \} \z/oxms) {
5156             }
5157              
5158             # $$ --> $$
5159             elsif ($char[$i] =~ /\A \$\$ \z/oxms) {
5160             }
5161              
5162             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
5163 0         0 # $1, $2, $3 --> $1, $2, $3 otherwise
5164             elsif ($char[$i] =~ /\A \$ ((?>[1-9][0-9]*)) \z/oxms) {
5165             $char[$i] = e_capture($1);
5166 0         0 }
5167             elsif ($char[$i] =~ /\A \$ \{ (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} \z/oxms) {
5168             $char[$i] = e_capture($1);
5169             }
5170              
5171 0         0 # $$foo[ ... ] --> $ $foo->[ ... ]
5172             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \[ (?:$qq_bracket)*? \] ) \z/oxms) {
5173             $char[$i] = e_capture($1.'->'.$2);
5174             }
5175              
5176 0         0 # $$foo{ ... } --> $ $foo->{ ... }
5177             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) ( \{ (?:$qq_brace)*? \} ) \z/oxms) {
5178             $char[$i] = e_capture($1.'->'.$2);
5179             }
5180              
5181 0         0 # $$foo
5182             elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) \z/oxms) {
5183             $char[$i] = e_capture($1);
5184             }
5185              
5186 0         0 # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Elatin7::PREMATCH()
5187             elsif ($char[$i] =~ /\A ( \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} ) \z/oxmsgc) {
5188             $char[$i] = '@{[Elatin7::PREMATCH()]}';
5189             }
5190              
5191 8         54 # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Elatin7::MATCH()
5192             elsif ($char[$i] =~ /\A ( \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} ) \z/oxmsgc) {
5193             $char[$i] = '@{[Elatin7::MATCH()]}';
5194             }
5195              
5196 8         47 # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Elatin7::POSTMATCH()
5197             elsif ($char[$i] =~ /\A ( \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} ) \z/oxmsgc) {
5198             $char[$i] = '@{[Elatin7::POSTMATCH()]}';
5199             }
5200              
5201             # ${ foo } --> ${ foo }
5202             elsif ($char[$i] =~ /\A \$ (?>\s*) \{ (?> \s* [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* \s* ) \} \z/oxms) {
5203             }
5204              
5205 6         32 # ${ ... }
5206             elsif ($char[$i] =~ /\A \$ (?>\s*) \{ ( .+ ) \} \z/oxms) {
5207             $char[$i] = e_capture($1);
5208             }
5209             }
5210 0 50       0  
5211 93         182 # return string
5212             if ($left_e > $right_e) {
5213 0         0 return join '', @char, '>]}' x ($left_e - $right_e);
5214             }
5215             return join '', @char;
5216             }
5217              
5218             #
5219             # escape regexp (m//, qr//)
5220 93     652 0 675 #
5221 652   100     2526 sub e_qr {
5222             my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
5223 652         2447 $modifier ||= '';
5224 652 50       1075  
5225 652         1424 $modifier =~ tr/p//d;
5226 0         0 if ($modifier =~ /([adlu])/oxms) {
5227 0 0       0 my $line = 0;
5228 0         0 for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
5229 0         0 if ($filename ne __FILE__) {
5230             $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
5231             last;
5232 0         0 }
5233             }
5234             die qq{Unsupported modifier "$1" used at line $line.\n};
5235 0         0 }
5236              
5237             $slash = 'div';
5238 652 100       963  
    100          
5239 652         1729 # literal null string pattern
5240 8         8 if ($string eq '') {
5241 8         8 $modifier =~ tr/bB//d;
5242             $modifier =~ tr/i//d;
5243             return join '', $ope, $delimiter, $end_delimiter, $modifier;
5244             }
5245              
5246             # /b /B modifier
5247             elsif ($modifier =~ tr/bB//d) {
5248 8 50       36  
5249 2         7 # choice again delimiter
5250 0         0 if ($delimiter =~ / [\@:] /oxms) {
  0         0  
5251 0 0       0 my @char = $string =~ /\G ([\x00-\xFF]) /oxmsg;
    0          
    0          
    0          
5252 0         0 my %octet = map {$_ => 1} @char;
5253 0         0 if (not $octet{')'}) {
5254             $delimiter = '(';
5255             $end_delimiter = ')';
5256 0         0 }
5257 0         0 elsif (not $octet{'}'}) {
5258             $delimiter = '{';
5259             $end_delimiter = '}';
5260 0         0 }
5261 0         0 elsif (not $octet{']'}) {
5262             $delimiter = '[';
5263             $end_delimiter = ']';
5264 0         0 }
5265 0         0 elsif (not $octet{'>'}) {
5266             $delimiter = '<';
5267             $end_delimiter = '>';
5268 0         0 }
5269 0 0       0 else {
5270 0         0 for my $char (qw( ! " $ % & * + - . / = ? ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
5271 0         0 if (not $octet{$char}) {
5272 0         0 $delimiter = $char;
5273             $end_delimiter = $char;
5274             last;
5275             }
5276             }
5277             }
5278 0 50 33     0 }
5279 2         11  
5280             if (($ope =~ /\A m? \z/oxms) and ($delimiter eq '?')) {
5281             return join '', $ope, $delimiter, $string, $matched, $end_delimiter, $modifier;
5282 0         0 }
5283             else {
5284             return join '', $ope, $delimiter, '(?:', $string, ')', $matched, $end_delimiter, $modifier;
5285             }
5286 2 100       11 }
5287 642         1310  
5288             my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
5289             my $metachar = qr/[\@\\|[\]{^]/oxms;
5290 642         2112  
5291             # split regexp
5292             my @char = $string =~ /\G((?>
5293             [^\\\$\@\[\(] |
5294             \\x (?>[0-9A-Fa-f]{1,2}) |
5295             \\ (?>[0-7]{2,3}) |
5296             \\c [\x40-\x5F] |
5297             \\x\{ (?>[0-9A-Fa-f]+) \} |
5298             \\o\{ (?>[0-7]+) \} |
5299             \\[bBNpP]\{ (?>[^0-9\}][^\}]*) \} |
5300             \\ $q_char |
5301             \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} |
5302             \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} |
5303             \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} |
5304             [\$\@] $qq_variable |
5305             \$ (?>\s* [0-9]+) |
5306             \$ (?>\s*) \{ (?>\s* [0-9]+ \s*) \} |
5307             \$ \$ (?![\w\{]) |
5308             \$ (?>\s*) \$ (?>\s*) $qq_variable |
5309             \[\^ |
5310             \[\: (?>[a-z]+) :\] |
5311             \[\:\^ (?>[a-z]+) :\] |
5312             \(\? |
5313             $q_char
5314             ))/oxmsg;
5315 642 50       62197  
5316 642         2505 # choice again delimiter
  0         0  
5317 0 0       0 if ($delimiter =~ / [\@:] /oxms) {
    0          
    0          
    0          
5318 0         0 my %octet = map {$_ => 1} @char;
5319 0         0 if (not $octet{')'}) {
5320             $delimiter = '(';
5321             $end_delimiter = ')';
5322 0         0 }
5323 0         0 elsif (not $octet{'}'}) {
5324             $delimiter = '{';
5325             $end_delimiter = '}';
5326 0         0 }
5327 0         0 elsif (not $octet{']'}) {
5328             $delimiter = '[';
5329             $end_delimiter = ']';
5330 0         0 }
5331 0         0 elsif (not $octet{'>'}) {
5332             $delimiter = '<';
5333             $end_delimiter = '>';
5334 0         0 }
5335 0 0       0 else {
5336 0         0 for my $char (qw( ! " $ % & * + - . / = ? ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
5337 0         0 if (not $octet{$char}) {
5338 0         0 $delimiter = $char;
5339             $end_delimiter = $char;
5340             last;
5341             }
5342             }
5343             }
5344 0         0 }
5345 642         946  
5346 642         845 my $left_e = 0;
5347             my $right_e = 0;
5348             for (my $i=0; $i <= $#char; $i++) {
5349 642 50 66     1501  
    50 66        
    100          
    100          
    100          
    100          
5350 1872         8842 # "\L\u" --> "\u\L"
5351             if (($char[$i] eq '\L') and ($char[$i+1] eq '\u')) {
5352             @char[$i,$i+1] = @char[$i+1,$i];
5353             }
5354              
5355 0         0 # "\U\l" --> "\l\U"
5356             elsif (($char[$i] eq '\U') and ($char[$i+1] eq '\l')) {
5357             @char[$i,$i+1] = @char[$i+1,$i];
5358             }
5359              
5360 0         0 # octal escape sequence
5361             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
5362             $char[$i] = Elatin7::octchr($1);
5363             }
5364              
5365 1         3 # hexadecimal escape sequence
5366             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
5367             $char[$i] = Elatin7::hexchr($1);
5368             }
5369              
5370             # \b{...} --> b\{...}
5371             # \B{...} --> B\{...}
5372             # \N{CHARNAME} --> N\{CHARNAME}
5373             # \p{PROPERTY} --> p\{PROPERTY}
5374 1         5 # \P{PROPERTY} --> P\{PROPERTY}
5375             elsif ($char[$i] =~ /\A \\ ([bBNpP]) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
5376             $char[$i] = $1 . '\\' . $2;
5377             }
5378              
5379 6         24 # \p, \P, \X --> p, P, X
5380             elsif ($char[$i] =~ /\A \\ ( [pPX] ) \z/oxms) {
5381             $char[$i] = $1;
5382 4 100 100     11 }
    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          
5383              
5384             if (0) {
5385             }
5386 1872         5052  
5387 0 50 33     0 # join separated multiple-octet
    50 33        
    50 33        
      33        
      66        
      33        
5388 6         97 elsif ($char[$i] =~ /\A (?: \\ [0-7]{2,3} | \\x [0-9A-Fa-f]{1,2}) \z/oxms) {
5389             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)) {
5390             $char[$i] .= join '', splice @char, $i+1, 3;
5391 0         0 }
5392             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)) {
5393             $char[$i] .= join '', splice @char, $i+1, 2;
5394 0         0 }
5395             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)) {
5396             $char[$i] .= join '', splice @char, $i+1, 1;
5397             }
5398             }
5399              
5400 0         0 # open character class [...]
5401             elsif ($char[$i] eq '[') {
5402             my $left = $i;
5403              
5404             # [] make die "Unmatched [] in regexp ...\n"
5405 328 100       405 # (and so on)
5406 328         706  
5407             if ($char[$i+1] eq ']') {
5408             $i++;
5409 3         4 }
5410 328 50       379  
5411 1379         1856 while (1) {
5412             if (++$i > $#char) {
5413 0 100       0 die __FILE__, ": Unmatched [] in regexp\n";
5414 1379         2113 }
5415             if ($char[$i] eq ']') {
5416             my $right = $i;
5417 328 100       389  
5418 328         1474 # [...]
  30         62  
5419             if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
5420             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);
5421 90         136 }
5422             else {
5423             splice @char, $left, $right-$left+1, Elatin7::charlist_qr(@char[$left+1..$right-1], $modifier);
5424 298         945 }
5425 328         566  
5426             $i = $left;
5427             last;
5428             }
5429             }
5430             }
5431              
5432 328         809 # open character class [^...]
5433             elsif ($char[$i] eq '[^') {
5434             my $left = $i;
5435              
5436             # [^] make die "Unmatched [] in regexp ...\n"
5437 74 100       92 # (and so on)
5438 74         156  
5439             if ($char[$i+1] eq ']') {
5440             $i++;
5441 4         4 }
5442 74 50       81  
5443 272         386 while (1) {
5444             if (++$i > $#char) {
5445 0 100       0 die __FILE__, ": Unmatched [] in regexp\n";
5446 272         434 }
5447             if ($char[$i] eq ']') {
5448             my $right = $i;
5449 74 100       82  
5450 74         329 # [^...]
  30         66  
5451             if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
5452             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);
5453 90         185 }
5454             else {
5455             splice @char, $left, $right-$left+1, Elatin7::charlist_not_qr(@char[$left+1..$right-1], $modifier);
5456 44         153 }
5457 74         142  
5458             $i = $left;
5459             last;
5460             }
5461             }
5462             }
5463              
5464 74         193 # rewrite character class or escape character
5465             elsif (my $char = character_class($char[$i],$modifier)) {
5466             $char[$i] = $char;
5467             }
5468              
5469 139 50       342 # /i modifier
5470 20         56 elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Elatin7::uc($char[$i]) ne Elatin7::fc($char[$i]))) {
5471             if (CORE::length(Elatin7::fc($char[$i])) == 1) {
5472             $char[$i] = '[' . Elatin7::uc($char[$i]) . Elatin7::fc($char[$i]) . ']';
5473 20         34 }
5474             else {
5475             $char[$i] = '(?:' . Elatin7::uc($char[$i]) . '|' . Elatin7::fc($char[$i]) . ')';
5476             }
5477             }
5478              
5479 0 50       0 # \u \l \U \L \F \Q \E
5480 1         5 elsif ($char[$i] =~ /\A [<>] \z/oxms) {
5481             if ($right_e < $left_e) {
5482             $char[$i] = '\\' . $char[$i];
5483             }
5484 0         0 }
5485 0         0 elsif ($char[$i] eq '\u') {
5486             $char[$i] = '@{[Elatin7::ucfirst qq<';
5487             $left_e++;
5488 0         0 }
5489 0         0 elsif ($char[$i] eq '\l') {
5490             $char[$i] = '@{[Elatin7::lcfirst qq<';
5491             $left_e++;
5492 0         0 }
5493 1         13 elsif ($char[$i] eq '\U') {
5494             $char[$i] = '@{[Elatin7::uc qq<';
5495             $left_e++;
5496 1         5 }
5497 1         3 elsif ($char[$i] eq '\L') {
5498             $char[$i] = '@{[Elatin7::lc qq<';
5499             $left_e++;
5500 1         3 }
5501 18         32 elsif ($char[$i] eq '\F') {
5502             $char[$i] = '@{[Elatin7::fc qq<';
5503             $left_e++;
5504 18         35 }
5505 1         3 elsif ($char[$i] eq '\Q') {
5506             $char[$i] = '@{[CORE::quotemeta qq<';
5507             $left_e++;
5508 1 50       3 }
5509 21         42 elsif ($char[$i] eq '\E') {
5510 21         29 if ($right_e < $left_e) {
5511             $char[$i] = '>]}';
5512             $right_e++;
5513 21         45 }
5514             else {
5515             $char[$i] = '';
5516             }
5517 0         0 }
5518 0 0       0 elsif ($char[$i] eq '\Q') {
5519 0         0 while (1) {
5520             if (++$i > $#char) {
5521 0 0       0 last;
5522 0         0 }
5523             if ($char[$i] eq '\E') {
5524             last;
5525             }
5526             }
5527             }
5528             elsif ($char[$i] eq '\E') {
5529             }
5530              
5531 0 0       0 # $0 --> $0
5532 0         0 elsif ($char[$i] =~ /\A \$ 0 \z/oxms) {
5533             if ($ignorecase) {
5534             $char[$i] = '@{[Elatin7::ignorecase(' . $char[$i] . ')]}';
5535             }
5536 0 0       0 }
5537 0         0 elsif ($char[$i] =~ /\A \$ \{ (?>\s*) 0 (?>\s*) \} \z/oxms) {
5538             if ($ignorecase) {
5539             $char[$i] = '@{[Elatin7::ignorecase(' . $char[$i] . ')]}';
5540             }
5541             }
5542              
5543             # $$ --> $$
5544             elsif ($char[$i] =~ /\A \$\$ \z/oxms) {
5545             }
5546              
5547             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
5548 0         0 # $1, $2, $3 --> $1, $2, $3 otherwise
5549 0 0       0 elsif ($char[$i] =~ /\A \$ ((?>[1-9][0-9]*)) \z/oxms) {
5550 0         0 $char[$i] = e_capture($1);
5551             if ($ignorecase) {
5552             $char[$i] = '@{[Elatin7::ignorecase(' . $char[$i] . ')]}';
5553             }
5554 0         0 }
5555 0 0       0 elsif ($char[$i] =~ /\A \$ \{ (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} \z/oxms) {
5556 0         0 $char[$i] = e_capture($1);
5557             if ($ignorecase) {
5558             $char[$i] = '@{[Elatin7::ignorecase(' . $char[$i] . ')]}';
5559             }
5560             }
5561              
5562 0         0 # $$foo[ ... ] --> $ $foo->[ ... ]
5563 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) {
5564 0         0 $char[$i] = e_capture($1.'->'.$2);
5565             if ($ignorecase) {
5566             $char[$i] = '@{[Elatin7::ignorecase(' . $char[$i] . ')]}';
5567             }
5568             }
5569              
5570 0         0 # $$foo{ ... } --> $ $foo->{ ... }
5571 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) {
5572 0         0 $char[$i] = e_capture($1.'->'.$2);
5573             if ($ignorecase) {
5574             $char[$i] = '@{[Elatin7::ignorecase(' . $char[$i] . ')]}';
5575             }
5576             }
5577              
5578 0         0 # $$foo
5579 0 0       0 elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) \z/oxms) {
5580 0         0 $char[$i] = e_capture($1);
5581             if ($ignorecase) {
5582             $char[$i] = '@{[Elatin7::ignorecase(' . $char[$i] . ')]}';
5583             }
5584             }
5585              
5586 0 50       0 # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Elatin7::PREMATCH()
5587 8         21 elsif ($char[$i] =~ /\A ( \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} ) \z/oxmsgc) {
5588             if ($ignorecase) {
5589             $char[$i] = '@{[Elatin7::ignorecase(Elatin7::PREMATCH())]}';
5590 0         0 }
5591             else {
5592             $char[$i] = '@{[Elatin7::PREMATCH()]}';
5593             }
5594             }
5595              
5596 8 50       23 # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Elatin7::MATCH()
5597 8         19 elsif ($char[$i] =~ /\A ( \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} ) \z/oxmsgc) {
5598             if ($ignorecase) {
5599             $char[$i] = '@{[Elatin7::ignorecase(Elatin7::MATCH())]}';
5600 0         0 }
5601             else {
5602             $char[$i] = '@{[Elatin7::MATCH()]}';
5603             }
5604             }
5605              
5606 8 50       23 # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Elatin7::POSTMATCH()
5607 6         15 elsif ($char[$i] =~ /\A ( \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} ) \z/oxmsgc) {
5608             if ($ignorecase) {
5609             $char[$i] = '@{[Elatin7::ignorecase(Elatin7::POSTMATCH())]}';
5610 0         0 }
5611             else {
5612             $char[$i] = '@{[Elatin7::POSTMATCH()]}';
5613             }
5614             }
5615              
5616 6 0       17 # ${ foo }
5617 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) {
5618             if ($ignorecase) {
5619             $char[$i] = '@{[Elatin7::ignorecase(' . $char[$i] . ')]}';
5620             }
5621             }
5622              
5623 0         0 # ${ ... }
5624 0 0       0 elsif ($char[$i] =~ /\A \$ (?>\s*) \{ ( .+ ) \} \z/oxms) {
5625 0         0 $char[$i] = e_capture($1);
5626             if ($ignorecase) {
5627             $char[$i] = '@{[Elatin7::ignorecase(' . $char[$i] . ')]}';
5628             }
5629             }
5630              
5631 0         0 # $scalar or @array
5632 21 100       48 elsif ($char[$i] =~ /\A [\$\@].+ /oxms) {
5633 21         53 $char[$i] = e_string($char[$i]);
5634             if ($ignorecase) {
5635             $char[$i] = '@{[Elatin7::ignorecase(' . $char[$i] . ')]}';
5636             }
5637             }
5638              
5639 11 100 33     35 # quote character before ? + * {
    50          
5640             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
5641             if ($char[$i-1] =~ /\A (?:[\x00-\xFF]|\\[0-7]{2,3}|\\x[0-9-A-Fa-f]{1,2}) \z/oxms) {
5642 138         926 }
5643 0 0       0 elsif (($ope =~ /\A m? \z/oxms) and ($delimiter eq '?')) {
5644 0         0 my $char = $char[$i-1];
5645             if ($char[$i] eq '{') {
5646             die __FILE__, qq{: "MULTIBYTE{n}" should be "(MULTIBYTE){n}" in m?? (and shift \$1,\$2,\$3,...) ($char){n}\n};
5647 0         0 }
5648             else {
5649             die __FILE__, qq{: "MULTIBYTE$char[$i]" should be "(MULTIBYTE)$char[$i]" in m?? (and shift \$1,\$2,\$3,...) ($char)$char[$i]\n};
5650             }
5651 0         0 }
5652             else {
5653             $char[$i-1] = '(?:' . $char[$i-1] . ')';
5654             }
5655             }
5656             }
5657 127         499  
5658 642 50       1098 # make regexp string
5659 642 0 0     1691 $modifier =~ tr/i//d;
5660 0         0 if ($left_e > $right_e) {
5661             if (($ope =~ /\A m? \z/oxms) and ($delimiter eq '?')) {
5662             return join '', $ope, $delimiter, $anchor, @char, '>]}' x ($left_e - $right_e), $matched, $end_delimiter, $modifier;
5663 0         0 }
5664             else {
5665             return join '', $ope, $delimiter, $anchor, '(?:', @char, '>]}' x ($left_e - $right_e), ')', $matched, $end_delimiter, $modifier;
5666 0 50 33     0 }
5667 642         3200 }
5668             if (($ope =~ /\A m? \z/oxms) and ($delimiter eq '?')) {
5669             return join '', $ope, $delimiter, $anchor, @char, $matched, $end_delimiter, $modifier;
5670 0         0 }
5671             else {
5672             return join '', $ope, $delimiter, $anchor, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
5673             }
5674             }
5675              
5676             #
5677             # double quote stuff
5678 642     180 0 4896 #
5679             sub qq_stuff {
5680             my($delimiter,$end_delimiter,$stuff) = @_;
5681 180 100       261  
5682 180         350 # scalar variable or array variable
5683             if ($stuff =~ /\A [\$\@] /oxms) {
5684             return $stuff;
5685             }
5686 100         314  
  80         170  
5687 80         240 # quote by delimiter
5688 80 50       185 my %octet = map {$_ => 1} ($stuff =~ /\G ([\x00-\xFF]) /oxmsg);
5689 80 50       125 for my $char (qw( ! " $ % & * + - . / : = ? @ ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
5690 80 50       109 next if $char eq $delimiter;
5691 80         126 next if $char eq $end_delimiter;
5692             if (not $octet{$char}) {
5693             return join '', 'qq', $char, $stuff, $char;
5694 80         345 }
5695             }
5696             return join '', 'qq', '<', $stuff, '>';
5697             }
5698              
5699             #
5700             # escape regexp (m'', qr'', and m''b, qr''b)
5701 0     10 0 0 #
5702 10   50     38 sub e_qr_q {
5703             my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
5704 10         37 $modifier ||= '';
5705 10 50       15  
5706 10         17 $modifier =~ tr/p//d;
5707 0         0 if ($modifier =~ /([adlu])/oxms) {
5708 0 0       0 my $line = 0;
5709 0         0 for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
5710 0         0 if ($filename ne __FILE__) {
5711             $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
5712             last;
5713 0         0 }
5714             }
5715             die qq{Unsupported modifier "$1" used at line $line.\n};
5716 0         0 }
5717              
5718             $slash = 'div';
5719 10 100       17  
    50          
5720 10         16 # literal null string pattern
5721 8         8 if ($string eq '') {
5722 8         9 $modifier =~ tr/bB//d;
5723             $modifier =~ tr/i//d;
5724             return join '', $ope, $delimiter, $end_delimiter, $modifier;
5725             }
5726              
5727 8         35 # with /b /B modifier
5728             elsif ($modifier =~ tr/bB//d) {
5729             return e_qr_qb($ope,$delimiter,$end_delimiter,$string,$modifier);
5730             }
5731              
5732 0         0 # without /b /B modifier
5733             else {
5734             return e_qr_qt($ope,$delimiter,$end_delimiter,$string,$modifier);
5735             }
5736             }
5737              
5738             #
5739             # escape regexp (m'', qr'')
5740 2     2 0 6 #
5741             sub e_qr_qt {
5742 2 50       6 my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
5743              
5744             my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
5745 2         6  
5746             # split regexp
5747             my @char = $string =~ /\G((?>
5748             [^\\\[\$\@\/] |
5749             [\x00-\xFF] |
5750             \[\^ |
5751             \[\: (?>[a-z]+) \:\] |
5752             \[\:\^ (?>[a-z]+) \:\] |
5753             [\$\@\/] |
5754             \\ (?:$q_char) |
5755             (?:$q_char)
5756             ))/oxmsg;
5757 2         58  
5758 2 50 33     10 # unescape character
    50 33        
    50 33        
    50          
    50          
    50          
5759             for (my $i=0; $i <= $#char; $i++) {
5760             if (0) {
5761             }
5762 2         15  
5763 0         0 # open character class [...]
5764 0 0       0 elsif ($char[$i] eq '[') {
5765 0         0 my $left = $i;
5766             if ($char[$i+1] eq ']') {
5767 0         0 $i++;
5768 0 0       0 }
5769 0         0 while (1) {
5770             if (++$i > $#char) {
5771 0 0       0 die __FILE__, ": Unmatched [] in regexp\n";
5772 0         0 }
5773             if ($char[$i] eq ']') {
5774             my $right = $i;
5775 0         0  
5776             # [...]
5777 0         0 splice @char, $left, $right-$left+1, Elatin7::charlist_qr(@char[$left+1..$right-1], $modifier);
5778 0         0  
5779             $i = $left;
5780             last;
5781             }
5782             }
5783             }
5784              
5785 0         0 # open character class [^...]
5786 0 0       0 elsif ($char[$i] eq '[^') {
5787 0         0 my $left = $i;
5788             if ($char[$i+1] eq ']') {
5789 0         0 $i++;
5790 0 0       0 }
5791 0         0 while (1) {
5792             if (++$i > $#char) {
5793 0 0       0 die __FILE__, ": Unmatched [] in regexp\n";
5794 0         0 }
5795             if ($char[$i] eq ']') {
5796             my $right = $i;
5797 0         0  
5798             # [^...]
5799 0         0 splice @char, $left, $right-$left+1, Elatin7::charlist_not_qr(@char[$left+1..$right-1], $modifier);
5800 0         0  
5801             $i = $left;
5802             last;
5803             }
5804             }
5805             }
5806              
5807 0         0 # escape $ @ / and \
5808             elsif ($char[$i] =~ /\A [\$\@\/\\] \z/oxms) {
5809             $char[$i] = '\\' . $char[$i];
5810             }
5811              
5812 0         0 # rewrite character class or escape character
5813             elsif (my $char = character_class($char[$i],$modifier)) {
5814             $char[$i] = $char;
5815             }
5816              
5817 0 0       0 # /i modifier
5818 0         0 elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Elatin7::uc($char[$i]) ne Elatin7::fc($char[$i]))) {
5819             if (CORE::length(Elatin7::fc($char[$i])) == 1) {
5820             $char[$i] = '[' . Elatin7::uc($char[$i]) . Elatin7::fc($char[$i]) . ']';
5821 0         0 }
5822             else {
5823             $char[$i] = '(?:' . Elatin7::uc($char[$i]) . '|' . Elatin7::fc($char[$i]) . ')';
5824             }
5825             }
5826              
5827 0 0       0 # quote character before ? + * {
5828             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
5829             if ($char[$i-1] =~ /\A [\x00-\xFF] \z/oxms) {
5830 0         0 }
5831             else {
5832             $char[$i-1] = '(?:' . $char[$i-1] . ')';
5833             }
5834             }
5835 0         0 }
5836 2         5  
5837             $delimiter = '/';
5838 2         3 $end_delimiter = '/';
5839 2         4  
5840             $modifier =~ tr/i//d;
5841             return join '', $ope, $delimiter, $anchor, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
5842             }
5843              
5844             #
5845             # escape regexp (m''b, qr''b)
5846 2     0 0 15 #
5847             sub e_qr_qb {
5848             my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
5849 0         0  
5850             # split regexp
5851             my @char = $string =~ /\G ((?>[^\\]|\\\\)) /oxmsg;
5852 0         0  
5853 0 0       0 # unescape character
    0          
5854             for (my $i=0; $i <= $#char; $i++) {
5855             if (0) {
5856             }
5857 0         0  
5858             # remain \\
5859             elsif ($char[$i] eq '\\\\') {
5860             }
5861              
5862 0         0 # escape $ @ / and \
5863             elsif ($char[$i] =~ /\A [\$\@\/\\] \z/oxms) {
5864             $char[$i] = '\\' . $char[$i];
5865             }
5866 0         0 }
5867 0         0  
5868 0         0 $delimiter = '/';
5869             $end_delimiter = '/';
5870             return join '', $ope, $delimiter, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
5871             }
5872              
5873             #
5874             # escape regexp (s/here//)
5875 0     76 0 0 #
5876 76   100     214 sub e_s1 {
5877             my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
5878 76         305 $modifier ||= '';
5879 76 50       113  
5880 76         173 $modifier =~ tr/p//d;
5881 0         0 if ($modifier =~ /([adlu])/oxms) {
5882 0 0       0 my $line = 0;
5883 0         0 for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
5884 0         0 if ($filename ne __FILE__) {
5885             $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
5886             last;
5887 0         0 }
5888             }
5889             die qq{Unsupported modifier "$1" used at line $line.\n};
5890 0         0 }
5891              
5892             $slash = 'div';
5893 76 100       127  
    50          
5894 76         239 # literal null string pattern
5895 8         20 if ($string eq '') {
5896 8         10 $modifier =~ tr/bB//d;
5897             $modifier =~ tr/i//d;
5898             return join '', $ope, $delimiter, $end_delimiter, $modifier;
5899             }
5900              
5901             # /b /B modifier
5902             elsif ($modifier =~ tr/bB//d) {
5903 8 0       44  
5904 0         0 # choice again delimiter
5905 0         0 if ($delimiter =~ / [\@:] /oxms) {
  0         0  
5906 0 0       0 my @char = $string =~ /\G ([\x00-\xFF]) /oxmsg;
    0          
    0          
    0          
5907 0         0 my %octet = map {$_ => 1} @char;
5908 0         0 if (not $octet{')'}) {
5909             $delimiter = '(';
5910             $end_delimiter = ')';
5911 0         0 }
5912 0         0 elsif (not $octet{'}'}) {
5913             $delimiter = '{';
5914             $end_delimiter = '}';
5915 0         0 }
5916 0         0 elsif (not $octet{']'}) {
5917             $delimiter = '[';
5918             $end_delimiter = ']';
5919 0         0 }
5920 0         0 elsif (not $octet{'>'}) {
5921             $delimiter = '<';
5922             $end_delimiter = '>';
5923 0         0 }
5924 0 0       0 else {
5925 0         0 for my $char (qw( ! " $ % & * + - . / = ? ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
5926 0         0 if (not $octet{$char}) {
5927 0         0 $delimiter = $char;
5928             $end_delimiter = $char;
5929             last;
5930             }
5931             }
5932             }
5933 0         0 }
5934 0         0  
5935             my $prematch = '';
5936             return join '', $ope, $delimiter, $prematch, '(?:', $string, ')', $matched, $end_delimiter, $modifier;
5937 0 100       0 }
5938 68         178  
5939             my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
5940             my $metachar = qr/[\@\\|[\]{^]/oxms;
5941 68         253  
5942             # split regexp
5943             my @char = $string =~ /\G((?>
5944             [^\\\$\@\[\(] |
5945             \\ (?>[1-9][0-9]*) |
5946             \\g (?>\s*) (?>[1-9][0-9]*) |
5947             \\g (?>\s*) \{ (?>\s*) (?>[1-9][0-9]*) (?>\s*) \} |
5948             \\g (?>\s*) \{ (?>\s*) - (?>\s*) (?>[1-9][0-9]*) (?>\s*) \} |
5949             \\x (?>[0-9A-Fa-f]{1,2}) |
5950             \\ (?>[0-7]{2,3}) |
5951             \\c [\x40-\x5F] |
5952             \\x\{ (?>[0-9A-Fa-f]+) \} |
5953             \\o\{ (?>[0-7]+) \} |
5954             \\[bBNpP]\{ (?>[^0-9\}][^\}]*) \} |
5955             \\ $q_char |
5956             \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} |
5957             \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} |
5958             \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} |
5959             [\$\@] $qq_variable |
5960             \$ (?>\s* [0-9]+) |
5961             \$ (?>\s*) \{ (?>\s* [0-9]+ \s*) \} |
5962             \$ \$ (?![\w\{]) |
5963             \$ (?>\s*) \$ (?>\s*) $qq_variable |
5964             \[\^ |
5965             \[\: (?>[a-z]+) :\] |
5966             \[\:\^ (?>[a-z]+) :\] |
5967             \(\? |
5968             $q_char
5969             ))/oxmsg;
5970 68 50       15636  
5971 68         436 # choice again delimiter
  0         0  
5972 0 0       0 if ($delimiter =~ / [\@:] /oxms) {
    0          
    0          
    0          
5973 0         0 my %octet = map {$_ => 1} @char;
5974 0         0 if (not $octet{')'}) {
5975             $delimiter = '(';
5976             $end_delimiter = ')';
5977 0         0 }
5978 0         0 elsif (not $octet{'}'}) {
5979             $delimiter = '{';
5980             $end_delimiter = '}';
5981 0         0 }
5982 0         0 elsif (not $octet{']'}) {
5983             $delimiter = '[';
5984             $end_delimiter = ']';
5985 0         0 }
5986 0         0 elsif (not $octet{'>'}) {
5987             $delimiter = '<';
5988             $end_delimiter = '>';
5989 0         0 }
5990 0 0       0 else {
5991 0         0 for my $char (qw( ! " $ % & * + - . / = ? ^ ` | ~ ), "\x00".."\x1F", "\x7F", "\xFF") {
5992 0         0 if (not $octet{$char}) {
5993 0         0 $delimiter = $char;
5994             $end_delimiter = $char;
5995             last;
5996             }
5997             }
5998             }
5999             }
6000 0         0  
  68         125  
6001             # count '('
6002 253         416 my $parens = grep { $_ eq '(' } @char;
6003 68         121  
6004 68         87 my $left_e = 0;
6005             my $right_e = 0;
6006             for (my $i=0; $i <= $#char; $i++) {
6007 68 50 33     192  
    50 33        
    100          
    100          
    50          
    50          
6008 195         1062 # "\L\u" --> "\u\L"
6009             if (($char[$i] eq '\L') and ($char[$i+1] eq '\u')) {
6010             @char[$i,$i+1] = @char[$i+1,$i];
6011             }
6012              
6013 0         0 # "\U\l" --> "\l\U"
6014             elsif (($char[$i] eq '\U') and ($char[$i+1] eq '\l')) {
6015             @char[$i,$i+1] = @char[$i+1,$i];
6016             }
6017              
6018 0         0 # octal escape sequence
6019             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
6020             $char[$i] = Elatin7::octchr($1);
6021             }
6022              
6023 1         2 # hexadecimal escape sequence
6024             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
6025             $char[$i] = Elatin7::hexchr($1);
6026             }
6027              
6028             # \b{...} --> b\{...}
6029             # \B{...} --> B\{...}
6030             # \N{CHARNAME} --> N\{CHARNAME}
6031             # \p{PROPERTY} --> p\{PROPERTY}
6032 1         5 # \P{PROPERTY} --> P\{PROPERTY}
6033             elsif ($char[$i] =~ /\A \\ ([bBNpP]) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
6034             $char[$i] = $1 . '\\' . $2;
6035             }
6036              
6037 0         0 # \p, \P, \X --> p, P, X
6038             elsif ($char[$i] =~ /\A \\ ( [pPX] ) \z/oxms) {
6039             $char[$i] = $1;
6040 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          
6041              
6042             if (0) {
6043             }
6044 195         769  
6045 0 0 0     0 # join separated multiple-octet
    0 0        
    0 0        
      0        
      0        
      0        
6046 0         0 elsif ($char[$i] =~ /\A (?: \\ [0-7]{2,3} | \\x [0-9A-Fa-f]{1,2}) \z/oxms) {
6047             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)) {
6048             $char[$i] .= join '', splice @char, $i+1, 3;
6049 0         0 }
6050             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)) {
6051             $char[$i] .= join '', splice @char, $i+1, 2;
6052 0         0 }
6053             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)) {
6054             $char[$i] .= join '', splice @char, $i+1, 1;
6055             }
6056             }
6057              
6058 0         0 # open character class [...]
6059 13 50       32 elsif ($char[$i] eq '[') {
6060 13         38 my $left = $i;
6061             if ($char[$i+1] eq ']') {
6062 0         0 $i++;
6063 13 50       18 }
6064 58         92 while (1) {
6065             if (++$i > $#char) {
6066 0 100       0 die __FILE__, ": Unmatched [] in regexp\n";
6067 58         109 }
6068             if ($char[$i] eq ']') {
6069             my $right = $i;
6070 13 50       21  
6071 13         73 # [...]
  0         0  
6072             if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
6073             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);
6074 0         0 }
6075             else {
6076             splice @char, $left, $right-$left+1, Elatin7::charlist_qr(@char[$left+1..$right-1], $modifier);
6077 13         55 }
6078 13         23  
6079             $i = $left;
6080             last;
6081             }
6082             }
6083             }
6084              
6085 13         36 # open character class [^...]
6086 0 0       0 elsif ($char[$i] eq '[^') {
6087 0         0 my $left = $i;
6088             if ($char[$i+1] eq ']') {
6089 0         0 $i++;
6090 0 0       0 }
6091 0         0 while (1) {
6092             if (++$i > $#char) {
6093 0 0       0 die __FILE__, ": Unmatched [] in regexp\n";
6094 0         0 }
6095             if ($char[$i] eq ']') {
6096             my $right = $i;
6097 0 0       0  
6098 0         0 # [^...]
  0         0  
6099             if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
6100             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);
6101 0         0 }
6102             else {
6103             splice @char, $left, $right-$left+1, Elatin7::charlist_not_qr(@char[$left+1..$right-1], $modifier);
6104 0         0 }
6105 0         0  
6106             $i = $left;
6107             last;
6108             }
6109             }
6110             }
6111              
6112 0         0 # rewrite character class or escape character
6113             elsif (my $char = character_class($char[$i],$modifier)) {
6114             $char[$i] = $char;
6115             }
6116              
6117 7 50       14 # /i modifier
6118 3         10 elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Elatin7::uc($char[$i]) ne Elatin7::fc($char[$i]))) {
6119             if (CORE::length(Elatin7::fc($char[$i])) == 1) {
6120             $char[$i] = '[' . Elatin7::uc($char[$i]) . Elatin7::fc($char[$i]) . ']';
6121 3         6 }
6122             else {
6123             $char[$i] = '(?:' . Elatin7::uc($char[$i]) . '|' . Elatin7::fc($char[$i]) . ')';
6124             }
6125             }
6126              
6127 0 0       0 # \u \l \U \L \F \Q \E
6128 0         0 elsif ($char[$i] =~ /\A [<>] \z/oxms) {
6129             if ($right_e < $left_e) {
6130             $char[$i] = '\\' . $char[$i];
6131             }
6132 0         0 }
6133 0         0 elsif ($char[$i] eq '\u') {
6134             $char[$i] = '@{[Elatin7::ucfirst qq<';
6135             $left_e++;
6136 0         0 }
6137 0         0 elsif ($char[$i] eq '\l') {
6138             $char[$i] = '@{[Elatin7::lcfirst qq<';
6139             $left_e++;
6140 0         0 }
6141 0         0 elsif ($char[$i] eq '\U') {
6142             $char[$i] = '@{[Elatin7::uc qq<';
6143             $left_e++;
6144 0         0 }
6145 0         0 elsif ($char[$i] eq '\L') {
6146             $char[$i] = '@{[Elatin7::lc qq<';
6147             $left_e++;
6148 0         0 }
6149 0         0 elsif ($char[$i] eq '\F') {
6150             $char[$i] = '@{[Elatin7::fc qq<';
6151             $left_e++;
6152 0         0 }
6153 0         0 elsif ($char[$i] eq '\Q') {
6154             $char[$i] = '@{[CORE::quotemeta qq<';
6155             $left_e++;
6156 0 0       0 }
6157 0         0 elsif ($char[$i] eq '\E') {
6158 0         0 if ($right_e < $left_e) {
6159             $char[$i] = '>]}';
6160             $right_e++;
6161 0         0 }
6162             else {
6163             $char[$i] = '';
6164             }
6165 0         0 }
6166 0 0       0 elsif ($char[$i] eq '\Q') {
6167 0         0 while (1) {
6168             if (++$i > $#char) {
6169 0 0       0 last;
6170 0         0 }
6171             if ($char[$i] eq '\E') {
6172             last;
6173             }
6174             }
6175             }
6176             elsif ($char[$i] eq '\E') {
6177             }
6178              
6179             # \0 --> \0
6180             elsif ($char[$i] =~ /\A \\ (?>\s*) 0 \z/oxms) {
6181             }
6182              
6183             # \g{N}, \g{-N}
6184              
6185             # P.108 Using Simple Patterns
6186             # in Chapter 7: In the World of Regular Expressions
6187             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
6188              
6189             # P.221 Capturing
6190             # in Chapter 5: Pattern Matching
6191             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
6192              
6193             # \g{-1}, \g{-2}, \g{-3} --> \g{-1}, \g{-2}, \g{-3}
6194             elsif ($char[$i] =~ /\A \\g (?>\s*) \{ (?>\s*) - (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} \z/oxms) {
6195             }
6196              
6197             # \g{1}, \g{2}, \g{3} --> \g{2}, \g{3}, \g{4} (only when multibyte anchoring is enable)
6198             elsif ($char[$i] =~ /\A \\g (?>\s*) \{ (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} \z/oxms) {
6199             }
6200              
6201             # \g1, \g2, \g3 --> \g2, \g3, \g4 (only when multibyte anchoring is enable)
6202             elsif ($char[$i] =~ /\A \\g (?>\s*) ((?>[1-9][0-9]*)) \z/oxms) {
6203             }
6204              
6205             # \1, \2, \3 --> \2, \3, \4 (only when multibyte anchoring is enable)
6206             elsif ($char[$i] =~ /\A \\ (?>\s*) ((?>[1-9][0-9]*)) \z/oxms) {
6207             }
6208              
6209 0 0       0 # $0 --> $0
6210 0         0 elsif ($char[$i] =~ /\A \$ 0 \z/oxms) {
6211             if ($ignorecase) {
6212             $char[$i] = '@{[Elatin7::ignorecase(' . $char[$i] . ')]}';
6213             }
6214 0 0       0 }
6215 0         0 elsif ($char[$i] =~ /\A \$ \{ (?>\s*) 0 (?>\s*) \} \z/oxms) {
6216             if ($ignorecase) {
6217             $char[$i] = '@{[Elatin7::ignorecase(' . $char[$i] . ')]}';
6218             }
6219             }
6220              
6221             # $$ --> $$
6222             elsif ($char[$i] =~ /\A \$\$ \z/oxms) {
6223             }
6224              
6225             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
6226 0         0 # $1, $2, $3 --> $1, $2, $3 otherwise
6227 0 0       0 elsif ($char[$i] =~ /\A \$ ((?>[1-9][0-9]*)) \z/oxms) {
6228 0         0 $char[$i] = e_capture($1);
6229             if ($ignorecase) {
6230             $char[$i] = '@{[Elatin7::ignorecase(' . $char[$i] . ')]}';
6231             }
6232 0         0 }
6233 0 0       0 elsif ($char[$i] =~ /\A \$ \{ (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} \z/oxms) {
6234 0         0 $char[$i] = e_capture($1);
6235             if ($ignorecase) {
6236             $char[$i] = '@{[Elatin7::ignorecase(' . $char[$i] . ')]}';
6237             }
6238             }
6239              
6240 0         0 # $$foo[ ... ] --> $ $foo->[ ... ]
6241 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) {
6242 0         0 $char[$i] = e_capture($1.'->'.$2);
6243             if ($ignorecase) {
6244             $char[$i] = '@{[Elatin7::ignorecase(' . $char[$i] . ')]}';
6245             }
6246             }
6247              
6248 0         0 # $$foo{ ... } --> $ $foo->{ ... }
6249 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) {
6250 0         0 $char[$i] = e_capture($1.'->'.$2);
6251             if ($ignorecase) {
6252             $char[$i] = '@{[Elatin7::ignorecase(' . $char[$i] . ')]}';
6253             }
6254             }
6255              
6256 0         0 # $$foo
6257 0 0       0 elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) \z/oxms) {
6258 0         0 $char[$i] = e_capture($1);
6259             if ($ignorecase) {
6260             $char[$i] = '@{[Elatin7::ignorecase(' . $char[$i] . ')]}';
6261             }
6262             }
6263              
6264 0 50       0 # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Elatin7::PREMATCH()
6265 4         16 elsif ($char[$i] =~ /\A ( \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} ) \z/oxmsgc) {
6266             if ($ignorecase) {
6267             $char[$i] = '@{[Elatin7::ignorecase(Elatin7::PREMATCH())]}';
6268 0         0 }
6269             else {
6270             $char[$i] = '@{[Elatin7::PREMATCH()]}';
6271             }
6272             }
6273              
6274 4 50       14 # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Elatin7::MATCH()
6275 4         12 elsif ($char[$i] =~ /\A ( \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} ) \z/oxmsgc) {
6276             if ($ignorecase) {
6277             $char[$i] = '@{[Elatin7::ignorecase(Elatin7::MATCH())]}';
6278 0         0 }
6279             else {
6280             $char[$i] = '@{[Elatin7::MATCH()]}';
6281             }
6282             }
6283              
6284 4 50       15 # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Elatin7::POSTMATCH()
6285 3         10 elsif ($char[$i] =~ /\A ( \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} ) \z/oxmsgc) {
6286             if ($ignorecase) {
6287             $char[$i] = '@{[Elatin7::ignorecase(Elatin7::POSTMATCH())]}';
6288 0         0 }
6289             else {
6290             $char[$i] = '@{[Elatin7::POSTMATCH()]}';
6291             }
6292             }
6293              
6294 3 0       11 # ${ foo }
6295 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) {
6296             if ($ignorecase) {
6297             $char[$i] = '@{[Elatin7::ignorecase(' . $char[$i] . ')]}';
6298             }
6299             }
6300              
6301 0         0 # ${ ... }
6302 0 0       0 elsif ($char[$i] =~ /\A \$ (?>\s*) \{ ( .+ ) \} \z/oxms) {
6303 0         0 $char[$i] = e_capture($1);
6304             if ($ignorecase) {
6305             $char[$i] = '@{[Elatin7::ignorecase(' . $char[$i] . ')]}';
6306             }
6307             }
6308              
6309 0         0 # $scalar or @array
6310 4 50       14 elsif ($char[$i] =~ /\A [\$\@].+ /oxms) {
6311 4         21 $char[$i] = e_string($char[$i]);
6312             if ($ignorecase) {
6313             $char[$i] = '@{[Elatin7::ignorecase(' . $char[$i] . ')]}';
6314             }
6315             }
6316              
6317 0 50       0 # quote character before ? + * {
6318             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
6319             if ($char[$i-1] =~ /\A (?:[\x00-\xFF]|\\[0-7]{2,3}|\\x[0-9-A-Fa-f]{1,2}) \z/oxms) {
6320 13         68 }
6321             else {
6322             $char[$i-1] = '(?:' . $char[$i-1] . ')';
6323             }
6324             }
6325             }
6326 13         61  
6327 68         146 # make regexp string
6328 68 50       108 my $prematch = '';
6329 68         192 $modifier =~ tr/i//d;
6330             if ($left_e > $right_e) {
6331 0         0 return join '', $ope, $delimiter, $prematch, '(?:', @char, '>]}' x ($left_e - $right_e), ')', $matched, $end_delimiter, $modifier;
6332             }
6333             return join '', $ope, $delimiter, $prematch, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
6334             }
6335              
6336             #
6337             # escape regexp (s'here'' or s'here''b)
6338 68     21 0 706 #
6339 21   100     40 sub e_s1_q {
6340             my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6341 21         65 $modifier ||= '';
6342 21 50       24  
6343 21         37 $modifier =~ tr/p//d;
6344 0         0 if ($modifier =~ /([adlu])/oxms) {
6345 0 0       0 my $line = 0;
6346 0         0 for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
6347 0         0 if ($filename ne __FILE__) {
6348             $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
6349             last;
6350 0         0 }
6351             }
6352             die qq{Unsupported modifier "$1" used at line $line.\n};
6353 0         0 }
6354              
6355             $slash = 'div';
6356 21 100       28  
    50          
6357 21         53 # literal null string pattern
6358 8         9 if ($string eq '') {
6359 8         34 $modifier =~ tr/bB//d;
6360             $modifier =~ tr/i//d;
6361             return join '', $ope, $delimiter, $end_delimiter, $modifier;
6362             }
6363              
6364 8         39 # with /b /B modifier
6365             elsif ($modifier =~ tr/bB//d) {
6366             return e_s1_qb($ope,$delimiter,$end_delimiter,$string,$modifier);
6367             }
6368              
6369 0         0 # without /b /B modifier
6370             else {
6371             return e_s1_qt($ope,$delimiter,$end_delimiter,$string,$modifier);
6372             }
6373             }
6374              
6375             #
6376             # escape regexp (s'here'')
6377 13     13 0 27 #
6378             sub e_s1_qt {
6379 13 50       27 my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6380              
6381             my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
6382 13         23  
6383             # split regexp
6384             my @char = $string =~ /\G((?>
6385             [^\\\[\$\@\/] |
6386             [\x00-\xFF] |
6387             \[\^ |
6388             \[\: (?>[a-z]+) \:\] |
6389             \[\:\^ (?>[a-z]+) \:\] |
6390             [\$\@\/] |
6391             \\ (?:$q_char) |
6392             (?:$q_char)
6393             ))/oxmsg;
6394 13         179  
6395 13 50 33     38 # unescape character
    50 33        
    50 66        
    100          
    50          
    50          
6396             for (my $i=0; $i <= $#char; $i++) {
6397             if (0) {
6398             }
6399 25         96  
6400 0         0 # open character class [...]
6401 0 0       0 elsif ($char[$i] eq '[') {
6402 0         0 my $left = $i;
6403             if ($char[$i+1] eq ']') {
6404 0         0 $i++;
6405 0 0       0 }
6406 0         0 while (1) {
6407             if (++$i > $#char) {
6408 0 0       0 die __FILE__, ": Unmatched [] in regexp\n";
6409 0         0 }
6410             if ($char[$i] eq ']') {
6411             my $right = $i;
6412 0         0  
6413             # [...]
6414 0         0 splice @char, $left, $right-$left+1, Elatin7::charlist_qr(@char[$left+1..$right-1], $modifier);
6415 0         0  
6416             $i = $left;
6417             last;
6418             }
6419             }
6420             }
6421              
6422 0         0 # open character class [^...]
6423 0 0       0 elsif ($char[$i] eq '[^') {
6424 0         0 my $left = $i;
6425             if ($char[$i+1] eq ']') {
6426 0         0 $i++;
6427 0 0       0 }
6428 0         0 while (1) {
6429             if (++$i > $#char) {
6430 0 0       0 die __FILE__, ": Unmatched [] in regexp\n";
6431 0         0 }
6432             if ($char[$i] eq ']') {
6433             my $right = $i;
6434 0         0  
6435             # [^...]
6436 0         0 splice @char, $left, $right-$left+1, Elatin7::charlist_not_qr(@char[$left+1..$right-1], $modifier);
6437 0         0  
6438             $i = $left;
6439             last;
6440             }
6441             }
6442             }
6443              
6444 0         0 # escape $ @ / and \
6445             elsif ($char[$i] =~ /\A [\$\@\/\\] \z/oxms) {
6446             $char[$i] = '\\' . $char[$i];
6447             }
6448              
6449 0         0 # rewrite character class or escape character
6450             elsif (my $char = character_class($char[$i],$modifier)) {
6451             $char[$i] = $char;
6452             }
6453              
6454 6 0       12 # /i modifier
6455 0         0 elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Elatin7::uc($char[$i]) ne Elatin7::fc($char[$i]))) {
6456             if (CORE::length(Elatin7::fc($char[$i])) == 1) {
6457             $char[$i] = '[' . Elatin7::uc($char[$i]) . Elatin7::fc($char[$i]) . ']';
6458 0         0 }
6459             else {
6460             $char[$i] = '(?:' . Elatin7::uc($char[$i]) . '|' . Elatin7::fc($char[$i]) . ')';
6461             }
6462             }
6463              
6464 0 0       0 # quote character before ? + * {
6465             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
6466             if ($char[$i-1] =~ /\A [\x00-\xFF] \z/oxms) {
6467 0         0 }
6468             else {
6469             $char[$i-1] = '(?:' . $char[$i-1] . ')';
6470             }
6471             }
6472 0         0 }
6473 13         23  
6474 13         21 $modifier =~ tr/i//d;
6475 13         15 $delimiter = '/';
6476 13         17 $end_delimiter = '/';
6477             my $prematch = '';
6478             return join '', $ope, $delimiter, $prematch, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
6479             }
6480              
6481             #
6482             # escape regexp (s'here''b)
6483 13     0 0 87 #
6484             sub e_s1_qb {
6485             my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6486 0         0  
6487             # split regexp
6488             my @char = $string =~ /\G (?>[^\\]|\\\\) /oxmsg;
6489 0         0  
6490 0 0       0 # unescape character
    0          
6491             for (my $i=0; $i <= $#char; $i++) {
6492             if (0) {
6493             }
6494 0         0  
6495             # remain \\
6496             elsif ($char[$i] eq '\\\\') {
6497             }
6498              
6499 0         0 # escape $ @ / and \
6500             elsif ($char[$i] =~ /\A [\$\@\/\\] \z/oxms) {
6501             $char[$i] = '\\' . $char[$i];
6502             }
6503 0         0 }
6504 0         0  
6505 0         0 $delimiter = '/';
6506 0         0 $end_delimiter = '/';
6507             my $prematch = '';
6508             return join '', $ope, $delimiter, $prematch, '(?:', @char, ')', $matched, $end_delimiter, $modifier;
6509             }
6510              
6511             #
6512             # escape regexp (s''here')
6513 0     16 0 0 #
6514             sub e_s2_q {
6515 16         31 my($ope,$delimiter,$end_delimiter,$string) = @_;
6516              
6517 16         17 $slash = 'div';
6518 16         92  
6519 16 100       43 my @char = $string =~ / \G (?>[^\\]|\\\\|$q_char) /oxmsg;
    100          
6520             for (my $i=0; $i <= $#char; $i++) {
6521             if (0) {
6522             }
6523 9         41  
6524             # not escape \\
6525             elsif ($char[$i] =~ /\A \\\\ \z/oxms) {
6526             }
6527              
6528 0         0 # escape $ @ / and \
6529             elsif ($char[$i] =~ /\A [\$\@\/\\] \z/oxms) {
6530             $char[$i] = '\\' . $char[$i];
6531             }
6532 5         15 }
6533              
6534             return join '', $ope, $delimiter, @char, $end_delimiter;
6535             }
6536              
6537             #
6538             # escape regexp (s/here/and here/modifier)
6539 16     97 0 47 #
6540 97   100     677 sub e_sub {
6541             my($variable,$delimiter1,$pattern,$end_delimiter1,$delimiter2,$replacement,$end_delimiter2,$modifier) = @_;
6542 97         391 $modifier ||= '';
6543 97 50       169  
6544 97         235 $modifier =~ tr/p//d;
6545 0         0 if ($modifier =~ /([adlu])/oxms) {
6546 0 0       0 my $line = 0;
6547 0         0 for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
6548 0         0 if ($filename ne __FILE__) {
6549             $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
6550             last;
6551 0         0 }
6552             }
6553             die qq{Unsupported modifier "$1" used at line $line.\n};
6554 0 100       0 }
6555 97         213  
6556 36         48 if ($variable eq '') {
6557             $variable = '$_';
6558             $bind_operator = ' =~ ';
6559 36         42 }
6560              
6561             $slash = 'div';
6562              
6563             # P.128 Start of match (or end of previous match): \G
6564             # P.130 Advanced Use of \G with Perl
6565             # in Chapter 3: Overview of Regular Expression Features and Flavors
6566             # P.312 Iterative Matching: Scalar Context, with /g
6567             # in Chapter 7: Perl
6568             # of ISBN 0-596-00289-0 Mastering Regular Expressions, Second edition
6569              
6570             # P.181 Where You Left Off: The \G Assertion
6571             # in Chapter 5: Pattern Matching
6572             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
6573              
6574             # P.220 Where You Left Off: The \G Assertion
6575             # in Chapter 5: Pattern Matching
6576 97         139 # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
6577 97         142  
6578             my $e_modifier = $modifier =~ tr/e//d;
6579 97         140 my $r_modifier = $modifier =~ tr/r//d;
6580 97 50       146  
6581 97         221 my $my = '';
6582 0         0 if ($variable =~ s/\A \( (?>\s*) ( (?>(?: local \b | my \b | our \b | state \b )?) .+ ) \) \z/$1/oxms) {
6583 0         0 $my = $variable;
6584             $variable =~ s/ (?: local \b | my \b | our \b | state \b ) (?>\s*) //oxms;
6585             $variable =~ s/ = .+ \z//oxms;
6586 0         0 }
6587 97         216  
6588             (my $variable_basename = $variable) =~ s/ [\[\{].* \z//oxms;
6589             $variable_basename =~ s/ \s+ \z//oxms;
6590 97         187  
6591 97 100       144 # quote replacement string
6592 97         205 my $e_replacement = '';
6593 17         33 if ($e_modifier >= 1) {
6594             $e_replacement = e_qq('', '', '', $replacement);
6595             $e_modifier--;
6596 17 100       20 }
6597 80         192 else {
6598             if ($delimiter2 eq "'") {
6599             $e_replacement = e_s2_q('qq', '/', '/', $replacement);
6600 16         26 }
6601             else {
6602             $e_replacement = e_qq ('qq', $delimiter2, $end_delimiter2, $replacement);
6603             }
6604 64         163 }
6605              
6606             my $sub = '';
6607 97 100       159  
6608 97 100       238 # with /r
6609             if ($r_modifier) {
6610             if (0) {
6611             }
6612 8         14  
6613 0 50       0 # s///gr without multibyte anchoring
6614             elsif ($modifier =~ /g/oxms) {
6615             $sub = sprintf(
6616             # 1 2 3 4 5
6617             q,
6618              
6619             $variable, # 1
6620             ($delimiter1 eq "'") ? # 2
6621             e_s1_q('m', $delimiter1, $end_delimiter1, $pattern, $modifier) : # :
6622             e_s1 ('m', $delimiter1, $end_delimiter1, $pattern, $modifier), # :
6623             $s_matched, # 3
6624             $e_replacement, # 4
6625             '$Elatin7::re_r=CORE::eval $Elatin7::re_r; ' x $e_modifier, # 5
6626             );
6627             }
6628              
6629             # s///r
6630 4         13 else {
6631              
6632 4 50       4 my $prematch = q{$`};
6633              
6634             $sub = sprintf(
6635             # 1 2 3 4 5 6 7
6636             q<(%s =~ %s) ? CORE::eval{%s local $^W=0; local $Elatin7::re_r=%s; %s"%s$Elatin7::re_r$'" } : %s>,
6637              
6638             $variable, # 1
6639             ($delimiter1 eq "'") ? # 2
6640             e_s1_q('m', $delimiter1, $end_delimiter1, $pattern, $modifier) : # :
6641             e_s1 ('m', $delimiter1, $end_delimiter1, $pattern, $modifier), # :
6642             $s_matched, # 3
6643             $e_replacement, # 4
6644             '$Elatin7::re_r=CORE::eval $Elatin7::re_r; ' x $e_modifier, # 5
6645             $prematch, # 6
6646             $variable, # 7
6647             );
6648             }
6649 4 50       10  
6650 8         22 # $var !~ s///r doesn't make sense
6651             if ($bind_operator =~ / !~ /oxms) {
6652             $sub = q{die("$0: Using !~ with s///r doesn't make sense"), } . $sub;
6653             }
6654             }
6655              
6656 0 100       0 # without /r
6657             else {
6658             if (0) {
6659             }
6660 89         213  
6661 0 100       0 # s///g without multibyte anchoring
    100          
6662             elsif ($modifier =~ /g/oxms) {
6663             $sub = sprintf(
6664             # 1 2 3 4 5 6 7 8
6665             q,
6666              
6667             $variable, # 1
6668             ($delimiter1 eq "'") ? # 2
6669             e_s1_q('m', $delimiter1, $end_delimiter1, $pattern, $modifier) : # :
6670             e_s1 ('m', $delimiter1, $end_delimiter1, $pattern, $modifier), # :
6671             $s_matched, # 3
6672             $e_replacement, # 4
6673             '$Elatin7::re_r=CORE::eval $Elatin7::re_r; ' x $e_modifier, # 5
6674             $variable, # 6
6675             $variable, # 7
6676             ($bind_operator =~ / !~ /oxms) ? '!' : '', # 8
6677             );
6678             }
6679              
6680             # s///
6681 22         79 else {
6682              
6683 67 100       105 my $prematch = q{$`};
    100          
6684              
6685             $sub = sprintf(
6686              
6687             ($bind_operator =~ / =~ /oxms) ?
6688              
6689             # 1 2 3 4 5 6 7 8
6690             q<(%s%s%s) ? CORE::eval{%s local $^W=0; local $Elatin7::re_r=%s; %s%s="%s$Elatin7::re_r$'"; 1 } : undef> :
6691              
6692             # 1 2 3 4 5 6 7 8
6693             q<(%s%s%s) ? 1 : CORE::eval{%s local $^W=0; local $Elatin7::re_r=%s; %s%s="%s$Elatin7::re_r$'"; undef }>,
6694              
6695             $variable, # 1
6696             $bind_operator, # 2
6697             ($delimiter1 eq "'") ? # 3
6698             e_s1_q('m', $delimiter1, $end_delimiter1, $pattern, $modifier) : # :
6699             e_s1 ('m', $delimiter1, $end_delimiter1, $pattern, $modifier), # :
6700             $s_matched, # 4
6701             $e_replacement, # 5
6702             '$Elatin7::re_r=CORE::eval $Elatin7::re_r; ' x $e_modifier, # 6
6703             $variable, # 7
6704             $prematch, # 8
6705             );
6706             }
6707             }
6708 67 50       341  
6709 97         270 # (my $foo = $bar) =~ s/// --> (my $foo = $bar, CORE::eval { ... })[1]
6710             if ($my ne '') {
6711             $sub = "($my, $sub)[1]";
6712             }
6713 0         0  
6714 97         138 # clear s/// variable
6715             $sub_variable = '';
6716 97         128 $bind_operator = '';
6717              
6718             return $sub;
6719             }
6720              
6721             #
6722             # escape regexp of split qr//
6723 97     74 0 666 #
6724 74   100     324 sub e_split {
6725             my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
6726 74         341 $modifier ||= '';
6727 74 50       124  
6728 74         307 $modifier =~ tr/p//d;
6729 0         0 if ($modifier =~ /([adlu])/oxms) {
6730 0 0       0 my $line = 0;
6731 0         0 for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
6732 0         0 if ($filename ne __FILE__) {
6733             $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
6734             last;
6735 0         0 }
6736             }
6737             die qq{Unsupported modifier "$1" used at line $line.\n};
6738 0         0 }
6739              
6740             $slash = 'div';
6741 74 50       127  
6742 74         180 # /b /B modifier
6743             if ($modifier =~ tr/bB//d) {
6744             return join '', 'split', $ope, $delimiter, $string, $end_delimiter, $modifier;
6745 0 50       0 }
6746 74         173  
6747             my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
6748             my $metachar = qr/[\@\\|[\]{^]/oxms;
6749 74         284  
6750             # split regexp
6751             my @char = $string =~ /\G((?>
6752             [^\\\$\@\[\(] |
6753             \\x (?>[0-9A-Fa-f]{1,2}) |
6754             \\ (?>[0-7]{2,3}) |
6755             \\c [\x40-\x5F] |
6756             \\x\{ (?>[0-9A-Fa-f]+) \} |
6757             \\o\{ (?>[0-7]+) \} |
6758             \\[bBNpP]\{ (?>[^0-9\}][^\}]*) \} |
6759             \\ $q_char |
6760             \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} |
6761             \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} |
6762             \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} |
6763             [\$\@] $qq_variable |
6764             \$ (?>\s* [0-9]+) |
6765             \$ (?>\s*) \{ (?>\s* [0-9]+ \s*) \} |
6766             \$ \$ (?![\w\{]) |
6767             \$ (?>\s*) \$ (?>\s*) $qq_variable |
6768             \[\^ |
6769             \[\: (?>[a-z]+) :\] |
6770             \[\:\^ (?>[a-z]+) :\] |
6771             \(\? |
6772             $q_char
6773 74         9032 ))/oxmsg;
6774 74         260  
6775 74         96 my $left_e = 0;
6776             my $right_e = 0;
6777             for (my $i=0; $i <= $#char; $i++) {
6778 74 50 33     363  
    50 33        
    100          
    100          
    50          
    50          
6779 249         1192 # "\L\u" --> "\u\L"
6780             if (($char[$i] eq '\L') and ($char[$i+1] eq '\u')) {
6781             @char[$i,$i+1] = @char[$i+1,$i];
6782             }
6783              
6784 0         0 # "\U\l" --> "\l\U"
6785             elsif (($char[$i] eq '\U') and ($char[$i+1] eq '\l')) {
6786             @char[$i,$i+1] = @char[$i+1,$i];
6787             }
6788              
6789 0         0 # octal escape sequence
6790             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
6791             $char[$i] = Elatin7::octchr($1);
6792             }
6793              
6794 1         4 # hexadecimal escape sequence
6795             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
6796             $char[$i] = Elatin7::hexchr($1);
6797             }
6798              
6799             # \b{...} --> b\{...}
6800             # \B{...} --> B\{...}
6801             # \N{CHARNAME} --> N\{CHARNAME}
6802             # \p{PROPERTY} --> p\{PROPERTY}
6803 1         4 # \P{PROPERTY} --> P\{PROPERTY}
6804             elsif ($char[$i] =~ /\A \\ ([bBNpP]) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
6805             $char[$i] = $1 . '\\' . $2;
6806             }
6807              
6808 0         0 # \p, \P, \X --> p, P, X
6809             elsif ($char[$i] =~ /\A \\ ( [pPX] ) \z/oxms) {
6810             $char[$i] = $1;
6811 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          
6812              
6813             if (0) {
6814             }
6815 249         740  
6816 0 0 0     0 # join separated multiple-octet
    0 0        
    0 0        
      0        
      0        
      0        
6817 0         0 elsif ($char[$i] =~ /\A (?: \\ [0-7]{2,3} | \\x [0-9A-Fa-f]{1,2}) \z/oxms) {
6818             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)) {
6819             $char[$i] .= join '', splice @char, $i+1, 3;
6820 0         0 }
6821             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)) {
6822             $char[$i] .= join '', splice @char, $i+1, 2;
6823 0         0 }
6824             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)) {
6825             $char[$i] .= join '', splice @char, $i+1, 1;
6826             }
6827             }
6828              
6829 0         0 # open character class [...]
6830 3 50       6 elsif ($char[$i] eq '[') {
6831 3         11 my $left = $i;
6832             if ($char[$i+1] eq ']') {
6833 0         0 $i++;
6834 3 50       5 }
6835 7         13 while (1) {
6836             if (++$i > $#char) {
6837 0 100       0 die __FILE__, ": Unmatched [] in regexp\n";
6838 7         16 }
6839             if ($char[$i] eq ']') {
6840             my $right = $i;
6841 3 50       4  
6842 3         28 # [...]
  0         0  
6843             if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
6844             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);
6845 0         0 }
6846             else {
6847             splice @char, $left, $right-$left+1, Elatin7::charlist_qr(@char[$left+1..$right-1], $modifier);
6848 3         19 }
6849 3         6  
6850             $i = $left;
6851             last;
6852             }
6853             }
6854             }
6855              
6856 3         11 # open character class [^...]
6857 0 0       0 elsif ($char[$i] eq '[^') {
6858 0         0 my $left = $i;
6859             if ($char[$i+1] eq ']') {
6860 0         0 $i++;
6861 0 0       0 }
6862 0         0 while (1) {
6863             if (++$i > $#char) {
6864 0 0       0 die __FILE__, ": Unmatched [] in regexp\n";
6865 0         0 }
6866             if ($char[$i] eq ']') {
6867             my $right = $i;
6868 0 0       0  
6869 0         0 # [^...]
  0         0  
6870             if (grep(/\A [\$\@]/oxms,@char[$left+1..$right-1]) >= 1) {
6871             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);
6872 0         0 }
6873             else {
6874             splice @char, $left, $right-$left+1, Elatin7::charlist_not_qr(@char[$left+1..$right-1], $modifier);
6875 0         0 }
6876 0         0  
6877             $i = $left;
6878             last;
6879             }
6880             }
6881             }
6882              
6883 0         0 # rewrite character class or escape character
6884             elsif (my $char = character_class($char[$i],$modifier)) {
6885             $char[$i] = $char;
6886             }
6887              
6888             # P.794 29.2.161. split
6889             # in Chapter 29: Functions
6890             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
6891              
6892             # P.951 split
6893             # in Chapter 27: Functions
6894             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
6895              
6896             # said "The //m modifier is assumed when you split on the pattern /^/",
6897             # but perl5.008 is not so. Therefore, this software adds //m.
6898             # (and so on)
6899              
6900 1         2 # split(m/^/) --> split(m/^/m)
6901             elsif (($char[$i] eq '^') and ($modifier !~ /m/oxms)) {
6902             $modifier .= 'm';
6903             }
6904              
6905 7 0       22 # /i modifier
6906 0         0 elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Elatin7::uc($char[$i]) ne Elatin7::fc($char[$i]))) {
6907             if (CORE::length(Elatin7::fc($char[$i])) == 1) {
6908             $char[$i] = '[' . Elatin7::uc($char[$i]) . Elatin7::fc($char[$i]) . ']';
6909 0         0 }
6910             else {
6911             $char[$i] = '(?:' . Elatin7::uc($char[$i]) . '|' . Elatin7::fc($char[$i]) . ')';
6912             }
6913             }
6914              
6915 0 0       0 # \u \l \U \L \F \Q \E
6916 0         0 elsif ($char[$i] =~ /\A ([<>]) \z/oxms) {
6917             if ($right_e < $left_e) {
6918             $char[$i] = '\\' . $char[$i];
6919             }
6920 0         0 }
6921 0         0 elsif ($char[$i] eq '\u') {
6922             $char[$i] = '@{[Elatin7::ucfirst qq<';
6923             $left_e++;
6924 0         0 }
6925 0         0 elsif ($char[$i] eq '\l') {
6926             $char[$i] = '@{[Elatin7::lcfirst qq<';
6927             $left_e++;
6928 0         0 }
6929 0         0 elsif ($char[$i] eq '\U') {
6930             $char[$i] = '@{[Elatin7::uc qq<';
6931             $left_e++;
6932 0         0 }
6933 0         0 elsif ($char[$i] eq '\L') {
6934             $char[$i] = '@{[Elatin7::lc qq<';
6935             $left_e++;
6936 0         0 }
6937 0         0 elsif ($char[$i] eq '\F') {
6938             $char[$i] = '@{[Elatin7::fc qq<';
6939             $left_e++;
6940 0         0 }
6941 0         0 elsif ($char[$i] eq '\Q') {
6942             $char[$i] = '@{[CORE::quotemeta qq<';
6943             $left_e++;
6944 0 0       0 }
6945 0         0 elsif ($char[$i] eq '\E') {
6946 0         0 if ($right_e < $left_e) {
6947             $char[$i] = '>]}';
6948             $right_e++;
6949 0         0 }
6950             else {
6951             $char[$i] = '';
6952             }
6953 0         0 }
6954 0 0       0 elsif ($char[$i] eq '\Q') {
6955 0         0 while (1) {
6956             if (++$i > $#char) {
6957 0 0       0 last;
6958 0         0 }
6959             if ($char[$i] eq '\E') {
6960             last;
6961             }
6962             }
6963             }
6964             elsif ($char[$i] eq '\E') {
6965             }
6966              
6967 0 0       0 # $0 --> $0
6968 0         0 elsif ($char[$i] =~ /\A \$ 0 \z/oxms) {
6969             if ($ignorecase) {
6970             $char[$i] = '@{[Elatin7::ignorecase(' . $char[$i] . ')]}';
6971             }
6972 0 0       0 }
6973 0         0 elsif ($char[$i] =~ /\A \$ \{ (?>\s*) 0 (?>\s*) \} \z/oxms) {
6974             if ($ignorecase) {
6975             $char[$i] = '@{[Elatin7::ignorecase(' . $char[$i] . ')]}';
6976             }
6977             }
6978              
6979             # $$ --> $$
6980             elsif ($char[$i] =~ /\A \$\$ \z/oxms) {
6981             }
6982              
6983             # $1, $2, $3 --> $2, $3, $4 after s/// with multibyte anchoring
6984 0         0 # $1, $2, $3 --> $1, $2, $3 otherwise
6985 0 0       0 elsif ($char[$i] =~ /\A \$ ((?>[1-9][0-9]*)) \z/oxms) {
6986 0         0 $char[$i] = e_capture($1);
6987             if ($ignorecase) {
6988             $char[$i] = '@{[Elatin7::ignorecase(' . $char[$i] . ')]}';
6989             }
6990 0         0 }
6991 0 0       0 elsif ($char[$i] =~ /\A \$ \{ (?>\s*) ((?>[1-9][0-9]*)) (?>\s*) \} \z/oxms) {
6992 0         0 $char[$i] = e_capture($1);
6993             if ($ignorecase) {
6994             $char[$i] = '@{[Elatin7::ignorecase(' . $char[$i] . ')]}';
6995             }
6996             }
6997              
6998 0         0 # $$foo[ ... ] --> $ $foo->[ ... ]
6999 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) {
7000 0         0 $char[$i] = e_capture($1.'->'.$2);
7001             if ($ignorecase) {
7002             $char[$i] = '@{[Elatin7::ignorecase(' . $char[$i] . ')]}';
7003             }
7004             }
7005              
7006 0         0 # $$foo{ ... } --> $ $foo->{ ... }
7007 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) {
7008 0         0 $char[$i] = e_capture($1.'->'.$2);
7009             if ($ignorecase) {
7010             $char[$i] = '@{[Elatin7::ignorecase(' . $char[$i] . ')]}';
7011             }
7012             }
7013              
7014 0         0 # $$foo
7015 0 0       0 elsif ($char[$i] =~ /\A \$ ((?> \$ [A-Za-z_][A-Za-z0-9_]*(?: ::[A-Za-z_][A-Za-z0-9_]*)* )) \z/oxms) {
7016 0         0 $char[$i] = e_capture($1);
7017             if ($ignorecase) {
7018             $char[$i] = '@{[Elatin7::ignorecase(' . $char[$i] . ')]}';
7019             }
7020             }
7021              
7022 0 50       0 # $`, ${`}, $PREMATCH, ${PREMATCH}, ${^PREMATCH} --> Elatin7::PREMATCH()
7023 12         41 elsif ($char[$i] =~ /\A ( \$` | \$\{`\} | \$ (?>\s*) PREMATCH | \$ (?>\s*) \{ (?>\s*) PREMATCH (?>\s*) \} | \$ (?>\s*) \{\^PREMATCH\} ) \z/oxmsgc) {
7024             if ($ignorecase) {
7025             $char[$i] = '@{[Elatin7::ignorecase(Elatin7::PREMATCH())]}';
7026 0         0 }
7027             else {
7028             $char[$i] = '@{[Elatin7::PREMATCH()]}';
7029             }
7030             }
7031              
7032 12 50       56 # $&, ${&}, $MATCH, ${MATCH}, ${^MATCH} --> Elatin7::MATCH()
7033 12         27 elsif ($char[$i] =~ /\A ( \$& | \$\{&\} | \$ (?>\s*) MATCH | \$ (?>\s*) \{ (?>\s*) MATCH (?>\s*) \} | \$ (?>\s*) \{\^MATCH\} ) \z/oxmsgc) {
7034             if ($ignorecase) {
7035             $char[$i] = '@{[Elatin7::ignorecase(Elatin7::MATCH())]}';
7036 0         0 }
7037             else {
7038             $char[$i] = '@{[Elatin7::MATCH()]}';
7039             }
7040             }
7041              
7042 12 50       53 # $POSTMATCH, ${POSTMATCH}, ${^POSTMATCH} --> Elatin7::POSTMATCH()
7043 9         22 elsif ($char[$i] =~ /\A ( \$ (?>\s*) POSTMATCH | \$ (?>\s*) \{ (?>\s*) POSTMATCH (?>\s*) \} | \$ (?>\s*) \{\^POSTMATCH\} ) \z/oxmsgc) {
7044             if ($ignorecase) {
7045             $char[$i] = '@{[Elatin7::ignorecase(Elatin7::POSTMATCH())]}';
7046 0         0 }
7047             else {
7048             $char[$i] = '@{[Elatin7::POSTMATCH()]}';
7049             }
7050             }
7051              
7052 9 0       35 # ${ foo }
7053 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) {
7054             if ($ignorecase) {
7055             $char[$i] = '@{[Elatin7::ignorecase(' . $1 . ')]}';
7056             }
7057             }
7058              
7059 0         0 # ${ ... }
7060 0 0       0 elsif ($char[$i] =~ /\A \$ (?>\s*) \{ ( .+ ) \} \z/oxms) {
7061 0         0 $char[$i] = e_capture($1);
7062             if ($ignorecase) {
7063             $char[$i] = '@{[Elatin7::ignorecase(' . $char[$i] . ')]}';
7064             }
7065             }
7066              
7067 0         0 # $scalar or @array
7068 3 50       11 elsif ($char[$i] =~ /\A [\$\@].+ /oxms) {
7069 3         15 $char[$i] = e_string($char[$i]);
7070             if ($ignorecase) {
7071             $char[$i] = '@{[Elatin7::ignorecase(' . $char[$i] . ')]}';
7072             }
7073             }
7074              
7075 0 50       0 # quote character before ? + * {
7076             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
7077             if ($char[$i-1] =~ /\A (?:[\x00-\xFF]|\\[0-7]{2,3}|\\x[0-9-A-Fa-f]{1,2}) \z/oxms) {
7078 1         7 }
7079             else {
7080             $char[$i-1] = '(?:' . $char[$i-1] . ')';
7081             }
7082             }
7083             }
7084 0         0  
7085 74 50       131 # make regexp string
7086 74         156 $modifier =~ tr/i//d;
7087             if ($left_e > $right_e) {
7088 0         0 return join '', 'Elatin7::split', $ope, $delimiter, @char, '>]}' x ($left_e - $right_e), $end_delimiter, $modifier;
7089             }
7090             return join '', 'Elatin7::split', $ope, $delimiter, @char, $end_delimiter, $modifier;
7091             }
7092              
7093             #
7094             # escape regexp of split qr''
7095 74     0 0 693 #
7096 0   0       sub e_split_q {
7097             my($ope,$delimiter,$end_delimiter,$string,$modifier) = @_;
7098 0           $modifier ||= '';
7099 0 0          
7100 0           $modifier =~ tr/p//d;
7101 0           if ($modifier =~ /([adlu])/oxms) {
7102 0 0         my $line = 0;
7103 0           for (my $i=0; my($package,$filename,$use_line,$subroutine) = caller($i); $i++) {
7104 0           if ($filename ne __FILE__) {
7105             $line = $use_line + (CORE::substr($_,0,pos($_)) =~ tr/\n//) + 1;
7106             last;
7107 0           }
7108             }
7109             die qq{Unsupported modifier "$1" used at line $line.\n};
7110 0           }
7111              
7112             $slash = 'div';
7113 0 0          
7114 0           # /b /B modifier
7115             if ($modifier =~ tr/bB//d) {
7116             return join '', 'split', $ope, $delimiter, $string, $end_delimiter, $modifier;
7117 0 0         }
7118              
7119             my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
7120 0            
7121             # split regexp
7122             my @char = $string =~ /\G((?>
7123             [^\\\[] |
7124             [\x00-\xFF] |
7125             \[\^ |
7126             \[\: (?>[a-z]+) \:\] |
7127             \[\:\^ (?>[a-z]+) \:\] |
7128             \\ (?:$q_char) |
7129             (?:$q_char)
7130             ))/oxmsg;
7131 0            
7132 0 0 0       # unescape character
    0 0        
    0 0        
    0 0        
    0          
    0          
7133             for (my $i=0; $i <= $#char; $i++) {
7134             if (0) {
7135             }
7136 0            
7137 0           # open character class [...]
7138 0 0         elsif ($char[$i] eq '[') {
7139 0           my $left = $i;
7140             if ($char[$i+1] eq ']') {
7141 0           $i++;
7142 0 0         }
7143 0           while (1) {
7144             if (++$i > $#char) {
7145 0 0         die __FILE__, ": Unmatched [] in regexp\n";
7146 0           }
7147             if ($char[$i] eq ']') {
7148             my $right = $i;
7149 0            
7150             # [...]
7151 0           splice @char, $left, $right-$left+1, Elatin7::charlist_qr(@char[$left+1..$right-1], $modifier);
7152 0            
7153             $i = $left;
7154             last;
7155             }
7156             }
7157             }
7158              
7159 0           # open character class [^...]
7160 0 0         elsif ($char[$i] eq '[^') {
7161 0           my $left = $i;
7162             if ($char[$i+1] eq ']') {
7163 0           $i++;
7164 0 0         }
7165 0           while (1) {
7166             if (++$i > $#char) {
7167 0 0         die __FILE__, ": Unmatched [] in regexp\n";
7168 0           }
7169             if ($char[$i] eq ']') {
7170             my $right = $i;
7171 0            
7172             # [^...]
7173 0           splice @char, $left, $right-$left+1, Elatin7::charlist_not_qr(@char[$left+1..$right-1], $modifier);
7174 0            
7175             $i = $left;
7176             last;
7177             }
7178             }
7179             }
7180              
7181 0           # rewrite character class or escape character
7182             elsif (my $char = character_class($char[$i],$modifier)) {
7183             $char[$i] = $char;
7184             }
7185              
7186 0           # split(m/^/) --> split(m/^/m)
7187             elsif (($char[$i] eq '^') and ($modifier !~ /m/oxms)) {
7188             $modifier .= 'm';
7189             }
7190              
7191 0 0         # /i modifier
7192 0           elsif ($ignorecase and ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) and (Elatin7::uc($char[$i]) ne Elatin7::fc($char[$i]))) {
7193             if (CORE::length(Elatin7::fc($char[$i])) == 1) {
7194             $char[$i] = '[' . Elatin7::uc($char[$i]) . Elatin7::fc($char[$i]) . ']';
7195 0           }
7196             else {
7197             $char[$i] = '(?:' . Elatin7::uc($char[$i]) . '|' . Elatin7::fc($char[$i]) . ')';
7198             }
7199             }
7200              
7201 0 0         # quote character before ? + * {
7202             elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
7203             if ($char[$i-1] =~ /\A [\x00-\xFF] \z/oxms) {
7204 0           }
7205             else {
7206             $char[$i-1] = '(?:' . $char[$i-1] . ')';
7207             }
7208             }
7209 0           }
7210 0            
7211             $modifier =~ tr/i//d;
7212             return join '', 'Elatin7::split', $ope, $delimiter, @char, $end_delimiter, $modifier;
7213             }
7214              
7215             #
7216             # instead of Carp::carp
7217 0     0 0   #
7218 0           sub carp {
7219             my($package,$filename,$line) = caller(1);
7220             print STDERR "@_ at $filename line $line.\n";
7221             }
7222              
7223             #
7224             # instead of Carp::croak
7225 0     0 0   #
7226 0           sub croak {
7227 0           my($package,$filename,$line) = caller(1);
7228             print STDERR "@_ at $filename line $line.\n";
7229             die "\n";
7230             }
7231              
7232             #
7233             # instead of Carp::cluck
7234 0     0 0   #
7235 0           sub cluck {
7236 0           my $i = 0;
7237 0           my @cluck = ();
7238 0           while (my($package,$filename,$line,$subroutine) = caller($i)) {
7239             push @cluck, "[$i] $filename($line) $package::$subroutine\n";
7240 0           $i++;
7241 0           }
7242 0           print STDERR CORE::reverse @cluck;
7243             print STDERR "\n";
7244             print STDERR @_;
7245             }
7246              
7247             #
7248             # instead of Carp::confess
7249 0     0 0   #
7250 0           sub confess {
7251 0           my $i = 0;
7252 0           my @confess = ();
7253 0           while (my($package,$filename,$line,$subroutine) = caller($i)) {
7254             push @confess, "[$i] $filename($line) $package::$subroutine\n";
7255 0           $i++;
7256 0           }
7257 0           print STDERR CORE::reverse @confess;
7258 0           print STDERR "\n";
7259             print STDERR @_;
7260             die "\n";
7261             }
7262              
7263             1;
7264              
7265             __END__