File Coverage

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