File Coverage

blib/lib/Earabic.pm
Criterion Covered Total %
statement 896 2814 31.8
branch 884 2412 36.6
condition 97 355 27.3
subroutine 54 113 47.7
pod 7 74 9.4
total 1938 5768 33.6


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