File Coverage

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