File Coverage

Char/Elatin10.pm
Criterion Covered Total %
statement 51 954 5.3
branch 4 562 0.7
condition 1 180 0.5
subroutine 20 85 23.5
pod 7 50 14.0
total 83 1831 4.5


line stmt bran cond sub pod time code
1             #
2             # This file is *** FOR CPAN USE ONLY ***.
3             #
4             package Char::Elatin10;
5             ######################################################################
6             #
7             # Char::Elatin10 - Run-time routines for Char/Latin10.pm
8             #
9             # http://search.cpan.org/dist/Char-Latin10/
10             #
11             # Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014 INABA Hitoshi
12             ######################################################################
13              
14 177     177   17680 use 5.00503; # Galapagos Consensus 1998 for primetools
  177         11972  
  177         12865  
15             # use 5.008001; # Lancaster Consensus 2013 for toolchains
16              
17             # 12.3. Delaying use Until Runtime
18             # in Chapter 12. Packages, Libraries, and Modules
19             # of ISBN 0-596-00313-7 Perl Cookbook, 2nd Edition.
20             # (and so on)
21              
22 177     177   11510 BEGIN { eval q{ use vars qw($VERSION) } }
  177     177   1019  
  177         422  
  177         32864  
23             $VERSION = sprintf '%d.%02d', q$Revision: 1.01 $ =~ /(\d+)/xmsg;
24              
25             BEGIN {
26 177 50   177   1067 if ($^X =~ / jperl /oxmsi) {
27 0         0 die __FILE__, ": needs perl(not jperl) 5.00503 or later. (\$^X==$^X)";
28             }
29 177         304 if (CORE::ord('A') == 193) {
30             die __FILE__, ": is not US-ASCII script (may be EBCDIC or EBCDIK script).";
31             }
32 177         35758 if (CORE::ord('A') != 0x41) {
33             die __FILE__, ": is not US-ASCII script (must be US-ASCII script).";
34             }
35             }
36              
37             BEGIN {
38              
39             # instead of utf8.pm
40 177     177   12138 eval q{
  177     177   1122  
  177     56   331  
  177         41359  
  56         8511  
  64         10786  
  60         18041  
  56         9528  
  59         11645  
  59         9341  
41             no warnings qw(redefine);
42             *utf8::upgrade = sub { CORE::length $_[0] };
43             *utf8::downgrade = sub { 1 };
44             *utf8::encode = sub { };
45             *utf8::decode = sub { 1 };
46             *utf8::is_utf8 = sub { };
47             *utf8::valid = sub { 1 };
48             };
49 177 50       114009 if ($@) {
50 0         0 *utf8::upgrade = sub { CORE::length $_[0] };
  0         0  
51 0         0 *utf8::downgrade = sub { 1 };
  0         0  
52 0         0 *utf8::encode = sub { };
  0         0  
53 0         0 *utf8::decode = sub { 1 };
  0         0  
54 0         0 *utf8::is_utf8 = sub { };
  0         0  
55 0         0 *utf8::valid = sub { 1 };
  0         0  
56             }
57             }
58              
59             # instead of Symbol.pm
60             BEGIN {
61 177     177   435 my $genpkg = "Symbol::";
62 177         8584 my $genseq = 0;
63              
64             sub gensym () {
65 0     0 0 0 my $name = "GEN" . $genseq++;
66              
67             # here, no strict qw(refs); if strict.pm exists
68              
69 0         0 my $ref = \*{$genpkg . $name};
  0         0  
70 0         0 delete $$genpkg{$name};
71 0         0 return $ref;
72             }
73              
74             sub qualify ($;$) {
75 0     0 0 0 my ($name) = @_;
76 0 0 0     0 if (!ref($name) && (Char::Elatin10::index($name, '::') == -1) && (Char::Elatin10::index($name, "'") == -1)) {
      0        
77 0         0 my $pkg;
78 0         0 my %global = map {$_ => 1} qw(ARGV ARGVOUT ENV INC SIG STDERR STDIN STDOUT DATA);
  0         0  
79              
80             # Global names: special character, "^xyz", or other.
81 0 0 0     0 if ($name =~ /^(([^a-z])|(\^[a-z_]+))\z/i || $global{$name}) {
82             # RGS 2001-11-05 : translate leading ^X to control-char
83 0         0 $name =~ s/^\^([a-z_])/'qq(\c'.$1.')'/eei;
  0         0  
84 0         0 $pkg = "main";
85             }
86             else {
87 0 0       0 $pkg = (@_ > 1) ? $_[1] : caller;
88             }
89 0         0 $name = $pkg . "::" . $name;
90             }
91 0         0 return $name;
92             }
93              
94             sub qualify_to_ref ($;$) {
95              
96             # here, no strict qw(refs); if strict.pm exists
97              
98 0 0   0 0 0 return \*{ qualify $_[0], @_ > 1 ? $_[1] : caller };
  0         0  
99             }
100             }
101              
102             # Column: local $@
103             # in Chapter 9. Osaete okitai Perl no kiso
104             # of ISBN 10: 4798119172 | ISBN 13: 978-4798119175 MODAN Perl NYUMON
105             # (and so on)
106              
107             # use strict; if strict.pm exists
108             BEGIN {
109 177 50   177   477 if (eval { local $@; CORE::require strict }) {
  177         419  
  177         2014  
110 177         25186 strict::->import;
111             }
112             }
113              
114             # P.714 29.2.39. flock
115             # in Chapter 29: Functions
116             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
117              
118             # P.863 flock
119             # in Chapter 27: Functions
120             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
121              
122             sub LOCK_SH() {1}
123             sub LOCK_EX() {2}
124             sub LOCK_UN() {8}
125             sub LOCK_NB() {4}
126              
127             # instead of Carp.pm
128             sub carp;
129             sub croak;
130             sub cluck;
131             sub confess;
132              
133             my $your_char = q{[\x00-\xFF]};
134              
135             # regexp of character
136 177     177   11863 BEGIN { eval q{ use vars qw($q_char) } }
  177     177   1145  
  177         321  
  177         13098  
137             $q_char = qr/$your_char/oxms;
138              
139             #
140             # Latin-10 character range per length
141             #
142             my %range_tr = ();
143              
144             #
145             # alias of encoding name
146             #
147 177     177   11155 BEGIN { eval q{ use vars qw($encoding_alias) } }
  177     177   1571  
  177         377  
  177         490455  
148              
149             #
150             # Latin-10 case conversion
151             #
152             my %lc = ();
153             @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)} =
154             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);
155             my %uc = ();
156             @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)} =
157             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);
158             my %fc = ();
159             @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)} =
160             qw(a b c d e f g h i j k l m n o p q r s t u v w x y z);
161              
162             if (0) {
163             }
164              
165             elsif (__PACKAGE__ =~ / \b Elatin10 \z/oxms) {
166             %range_tr = (
167             1 => [ [0x00..0xFF],
168             ],
169             );
170             $encoding_alias = qr/ \b (?: iso[-_ ]?8859-16 | iec[- ]?8859-16 | latin-?10 ) \b /oxmsi;
171              
172             %lc = (%lc,
173             "\xA1" => "\xA2", # LATIN LETTER A WITH OGONEK
174             "\xA3" => "\xB3", # LATIN LETTER L WITH STROKE
175             "\xA6" => "\xA8", # LATIN LETTER S WITH CARON
176             "\xAA" => "\xBA", # LATIN LETTER S WITH COMMA BELOW
177             "\xAC" => "\xAE", # LATIN LETTER Z WITH ACUTE
178             "\xAF" => "\xBF", # LATIN LETTER Z WITH DOT ABOVE
179             "\xB2" => "\xB9", # LATIN LETTER C WITH CARON
180             "\xB4" => "\xB8", # LATIN LETTER Z WITH CARON
181             "\xBC" => "\xBD", # LATIN LIGATURE OE
182             "\xBE" => "\xFF", # LATIN LETTER Y WITH DIAERESIS
183             "\xC0" => "\xE0", # LATIN LETTER A WITH GRAVE
184             "\xC1" => "\xE1", # LATIN LETTER A WITH ACUTE
185             "\xC2" => "\xE2", # LATIN LETTER A WITH CIRCUMFLEX
186             "\xC3" => "\xE3", # LATIN LETTER A WITH BREVE
187             "\xC4" => "\xE4", # LATIN LETTER A WITH DIAERESIS
188             "\xC5" => "\xE5", # LATIN LETTER C WITH ACUTE
189             "\xC6" => "\xE6", # LATIN LETTER AE
190             "\xC7" => "\xE7", # LATIN LETTER C WITH CEDILLA
191             "\xC8" => "\xE8", # LATIN LETTER E WITH GRAVE
192             "\xC9" => "\xE9", # LATIN LETTER E WITH ACUTE
193             "\xCA" => "\xEA", # LATIN LETTER E WITH CIRCUMFLEX
194             "\xCB" => "\xEB", # LATIN LETTER E WITH DIAERESIS
195             "\xCC" => "\xEC", # LATIN LETTER I WITH GRAVE
196             "\xCD" => "\xED", # LATIN LETTER I WITH ACUTE
197             "\xCE" => "\xEE", # LATIN LETTER I WITH CIRCUMFLEX
198             "\xCF" => "\xEF", # LATIN LETTER I WITH DIAERESIS
199             "\xD0" => "\xF0", # LATIN LETTER D WITH STROKE
200             "\xD1" => "\xF1", # LATIN LETTER N WITH ACUTE
201             "\xD2" => "\xF2", # LATIN LETTER O WITH GRAVE
202             "\xD3" => "\xF3", # LATIN LETTER O WITH ACUTE
203             "\xD4" => "\xF4", # LATIN LETTER O WITH CIRCUMFLEX
204             "\xD5" => "\xF5", # LATIN LETTER O WITH DOUBLE ACUTE
205             "\xD6" => "\xF6", # LATIN LETTER O WITH DIAERESIS
206             "\xD7" => "\xF7", # LATIN LETTER S WITH ACUTE
207             "\xD8" => "\xF8", # LATIN LETTER U WITH DOUBLE ACUTE
208             "\xD9" => "\xF9", # LATIN LETTER U WITH GRAVE
209             "\xDA" => "\xFA", # LATIN LETTER U WITH ACUTE
210             "\xDB" => "\xFB", # LATIN LETTER U WITH CIRCUMFLEX
211             "\xDC" => "\xFC", # LATIN LETTER U WITH DIAERESIS
212             "\xDD" => "\xFD", # LATIN LETTER E WITH OGONEK
213             "\xDE" => "\xFE", # LATIN LETTER T WITH COMMA BELOW
214             );
215              
216             %uc = (%uc,
217             "\xA2" => "\xA1", # LATIN LETTER A WITH OGONEK
218             "\xA8" => "\xA6", # LATIN LETTER S WITH CARON
219             "\xAE" => "\xAC", # LATIN LETTER Z WITH ACUTE
220             "\xB3" => "\xA3", # LATIN LETTER L WITH STROKE
221             "\xB8" => "\xB4", # LATIN LETTER Z WITH CARON
222             "\xB9" => "\xB2", # LATIN LETTER C WITH CARON
223             "\xBA" => "\xAA", # LATIN LETTER S WITH COMMA BELOW
224             "\xBD" => "\xBC", # LATIN LIGATURE OE
225             "\xBF" => "\xAF", # LATIN LETTER Z WITH DOT ABOVE
226             "\xE0" => "\xC0", # LATIN LETTER A WITH GRAVE
227             "\xE1" => "\xC1", # LATIN LETTER A WITH ACUTE
228             "\xE2" => "\xC2", # LATIN LETTER A WITH CIRCUMFLEX
229             "\xE3" => "\xC3", # LATIN LETTER A WITH BREVE
230             "\xE4" => "\xC4", # LATIN LETTER A WITH DIAERESIS
231             "\xE5" => "\xC5", # LATIN LETTER C WITH ACUTE
232             "\xE6" => "\xC6", # LATIN LETTER AE
233             "\xE7" => "\xC7", # LATIN LETTER C WITH CEDILLA
234             "\xE8" => "\xC8", # LATIN LETTER E WITH GRAVE
235             "\xE9" => "\xC9", # LATIN LETTER E WITH ACUTE
236             "\xEA" => "\xCA", # LATIN LETTER E WITH CIRCUMFLEX
237             "\xEB" => "\xCB", # LATIN LETTER E WITH DIAERESIS
238             "\xEC" => "\xCC", # LATIN LETTER I WITH GRAVE
239             "\xED" => "\xCD", # LATIN LETTER I WITH ACUTE
240             "\xEE" => "\xCE", # LATIN LETTER I WITH CIRCUMFLEX
241             "\xEF" => "\xCF", # LATIN LETTER I WITH DIAERESIS
242             "\xF0" => "\xD0", # LATIN LETTER D WITH STROKE
243             "\xF1" => "\xD1", # LATIN LETTER N WITH ACUTE
244             "\xF2" => "\xD2", # LATIN LETTER O WITH GRAVE
245             "\xF3" => "\xD3", # LATIN LETTER O WITH ACUTE
246             "\xF4" => "\xD4", # LATIN LETTER O WITH CIRCUMFLEX
247             "\xF5" => "\xD5", # LATIN LETTER O WITH DOUBLE ACUTE
248             "\xF6" => "\xD6", # LATIN LETTER O WITH DIAERESIS
249             "\xF7" => "\xD7", # LATIN LETTER S WITH ACUTE
250             "\xF8" => "\xD8", # LATIN LETTER U WITH DOUBLE ACUTE
251             "\xF9" => "\xD9", # LATIN LETTER U WITH GRAVE
252             "\xFA" => "\xDA", # LATIN LETTER U WITH ACUTE
253             "\xFB" => "\xDB", # LATIN LETTER U WITH CIRCUMFLEX
254             "\xFC" => "\xDC", # LATIN LETTER U WITH DIAERESIS
255             "\xFD" => "\xDD", # LATIN LETTER E WITH OGONEK
256             "\xFE" => "\xDE", # LATIN LETTER T WITH COMMA BELOW
257             "\xFF" => "\xBE", # LATIN LETTER Y WITH DIAERESIS
258             );
259              
260             %fc = (%fc,
261             "\xA1" => "\xA2", # LATIN CAPITAL LETTER A WITH OGONEK --> LATIN SMALL LETTER A WITH OGONEK
262             "\xA3" => "\xB3", # LATIN CAPITAL LETTER L WITH STROKE --> LATIN SMALL LETTER L WITH STROKE
263             "\xA6" => "\xA8", # LATIN CAPITAL LETTER S WITH CARON --> LATIN SMALL LETTER S WITH CARON
264             "\xAA" => "\xBA", # LATIN CAPITAL LETTER S WITH COMMA BELOW --> LATIN SMALL LETTER S WITH COMMA BELOW
265             "\xAC" => "\xAE", # LATIN CAPITAL LETTER Z WITH ACUTE --> LATIN SMALL LETTER Z WITH ACUTE
266             "\xAF" => "\xBF", # LATIN CAPITAL LETTER Z WITH DOT ABOVE --> LATIN SMALL LETTER Z WITH DOT ABOVE
267             "\xB2" => "\xB9", # LATIN CAPITAL LETTER C WITH CARON --> LATIN SMALL LETTER C WITH CARON
268             "\xB4" => "\xB8", # LATIN CAPITAL LETTER Z WITH CARON --> LATIN SMALL LETTER Z WITH CARON
269             "\xBC" => "\xBD", # LATIN CAPITAL LIGATURE OE --> LATIN SMALL LIGATURE OE
270             "\xBE" => "\xFF", # LATIN CAPITAL LETTER Y WITH DIAERESIS --> LATIN SMALL LETTER Y WITH DIAERESIS
271             "\xC0" => "\xE0", # LATIN CAPITAL LETTER A WITH GRAVE --> LATIN SMALL LETTER A WITH GRAVE
272             "\xC1" => "\xE1", # LATIN CAPITAL LETTER A WITH ACUTE --> LATIN SMALL LETTER A WITH ACUTE
273             "\xC2" => "\xE2", # LATIN CAPITAL LETTER A WITH CIRCUMFLEX --> LATIN SMALL LETTER A WITH CIRCUMFLEX
274             "\xC3" => "\xE3", # LATIN CAPITAL LETTER A WITH BREVE --> LATIN SMALL LETTER A WITH BREVE
275             "\xC4" => "\xE4", # LATIN CAPITAL LETTER A WITH DIAERESIS --> LATIN SMALL LETTER A WITH DIAERESIS
276             "\xC5" => "\xE5", # LATIN CAPITAL LETTER C WITH ACUTE --> LATIN SMALL LETTER C WITH ACUTE
277             "\xC6" => "\xE6", # LATIN CAPITAL LETTER AE --> LATIN SMALL LETTER AE
278             "\xC7" => "\xE7", # LATIN CAPITAL LETTER C WITH CEDILLA --> LATIN SMALL LETTER C WITH CEDILLA
279             "\xC8" => "\xE8", # LATIN CAPITAL LETTER E WITH GRAVE --> LATIN SMALL LETTER E WITH GRAVE
280             "\xC9" => "\xE9", # LATIN CAPITAL LETTER E WITH ACUTE --> LATIN SMALL LETTER E WITH ACUTE
281             "\xCA" => "\xEA", # LATIN CAPITAL LETTER E WITH CIRCUMFLEX --> LATIN SMALL LETTER E WITH CIRCUMFLEX
282             "\xCB" => "\xEB", # LATIN CAPITAL LETTER E WITH DIAERESIS --> LATIN SMALL LETTER E WITH DIAERESIS
283             "\xCC" => "\xEC", # LATIN CAPITAL LETTER I WITH GRAVE --> LATIN SMALL LETTER I WITH GRAVE
284             "\xCD" => "\xED", # LATIN CAPITAL LETTER I WITH ACUTE --> LATIN SMALL LETTER I WITH ACUTE
285             "\xCE" => "\xEE", # LATIN CAPITAL LETTER I WITH CIRCUMFLEX --> LATIN SMALL LETTER I WITH CIRCUMFLEX
286             "\xCF" => "\xEF", # LATIN CAPITAL LETTER I WITH DIAERESIS --> LATIN SMALL LETTER I WITH DIAERESIS
287             "\xD0" => "\xF0", # LATIN CAPITAL LETTER D WITH STROKE --> LATIN SMALL LETTER D WITH STROKE
288             "\xD1" => "\xF1", # LATIN CAPITAL LETTER N WITH ACUTE --> LATIN SMALL LETTER N WITH ACUTE
289             "\xD2" => "\xF2", # LATIN CAPITAL LETTER O WITH GRAVE --> LATIN SMALL LETTER O WITH GRAVE
290             "\xD3" => "\xF3", # LATIN CAPITAL LETTER O WITH ACUTE --> LATIN SMALL LETTER O WITH ACUTE
291             "\xD4" => "\xF4", # LATIN CAPITAL LETTER O WITH CIRCUMFLEX --> LATIN SMALL LETTER O WITH CIRCUMFLEX
292             "\xD5" => "\xF5", # LATIN CAPITAL LETTER O WITH DOUBLE ACUTE --> LATIN SMALL LETTER O WITH DOUBLE ACUTE
293             "\xD6" => "\xF6", # LATIN CAPITAL LETTER O WITH DIAERESIS --> LATIN SMALL LETTER O WITH DIAERESIS
294             "\xD7" => "\xF7", # LATIN CAPITAL LETTER S WITH ACUTE --> LATIN SMALL LETTER S WITH ACUTE
295             "\xD8" => "\xF8", # LATIN CAPITAL LETTER U WITH DOUBLE ACUTE --> LATIN SMALL LETTER U WITH DOUBLE ACUTE
296             "\xD9" => "\xF9", # LATIN CAPITAL LETTER U WITH GRAVE --> LATIN SMALL LETTER U WITH GRAVE
297             "\xDA" => "\xFA", # LATIN CAPITAL LETTER U WITH ACUTE --> LATIN SMALL LETTER U WITH ACUTE
298             "\xDB" => "\xFB", # LATIN CAPITAL LETTER U WITH CIRCUMFLEX --> LATIN SMALL LETTER U WITH CIRCUMFLEX
299             "\xDC" => "\xFC", # LATIN CAPITAL LETTER U WITH DIAERESIS --> LATIN SMALL LETTER U WITH DIAERESIS
300             "\xDD" => "\xFD", # LATIN CAPITAL LETTER E WITH OGONEK --> LATIN SMALL LETTER E WITH OGONEK
301             "\xDE" => "\xFE", # LATIN CAPITAL LETTER T WITH COMMA BELOW --> LATIN SMALL LETTER T WITH COMMA BELOW
302             "\xDF" => "\x73\x73", # LATIN SMALL LETTER SHARP S --> LATIN SMALL LETTER S, LATIN SMALL LETTER S
303             );
304             }
305              
306             else {
307             croak "Don't know my package name '@{[__PACKAGE__]}'";
308             }
309              
310             #
311             # @ARGV wildcard globbing
312             #
313             sub import {
314              
315 0 0   0   0 if ($^O =~ /\A (?: MSWin32 | NetWare | symbian | dos ) \z/oxms) {
316 0         0 my @argv = ();
317 0         0 for (@ARGV) {
318              
319             # has space
320 0 0       0 if (/\A (?:$q_char)*? [ ] /oxms) {
    0          
321 0 0       0 if (my @glob = Char::Elatin10::glob(qq{"$_"})) {
322 0         0 push @argv, @glob;
323             }
324             else {
325 0         0 push @argv, $_;
326             }
327             }
328              
329             # has wildcard metachar
330             elsif (/\A (?:$q_char)*? [*?] /oxms) {
331 0 0       0 if (my @glob = Char::Elatin10::glob($_)) {
332 0         0 push @argv, @glob;
333             }
334             else {
335 0         0 push @argv, $_;
336             }
337             }
338              
339             # no wildcard globbing
340             else {
341 0         0 push @argv, $_;
342             }
343             }
344 0         0 @ARGV = @argv;
345             }
346             }
347              
348             # P.230 Care with Prototypes
349             # in Chapter 6: Subroutines
350             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
351             #
352             # If you aren't careful, you can get yourself into trouble with prototypes.
353             # But if you are careful, you can do a lot of neat things with them. This is
354             # all very powerful, of course, and should only be used in moderation to make
355             # the world a better place.
356              
357             # P.332 Care with Prototypes
358             # in Chapter 7: Subroutines
359             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
360             #
361             # If you aren't careful, you can get yourself into trouble with prototypes.
362             # But if you are careful, you can do a lot of neat things with them. This is
363             # all very powerful, of course, and should only be used in moderation to make
364             # the world a better place.
365              
366             #
367             # Prototypes of subroutines
368             #
369 0     0   0 sub unimport {}
370             sub Char::Elatin10::split(;$$$);
371             sub Char::Elatin10::tr($$$$;$);
372             sub Char::Elatin10::chop(@);
373             sub Char::Elatin10::index($$;$);
374             sub Char::Elatin10::rindex($$;$);
375             sub Char::Elatin10::lcfirst(@);
376             sub Char::Elatin10::lcfirst_();
377             sub Char::Elatin10::lc(@);
378             sub Char::Elatin10::lc_();
379             sub Char::Elatin10::ucfirst(@);
380             sub Char::Elatin10::ucfirst_();
381             sub Char::Elatin10::uc(@);
382             sub Char::Elatin10::uc_();
383             sub Char::Elatin10::fc(@);
384             sub Char::Elatin10::fc_();
385             sub Char::Elatin10::ignorecase;
386             sub Char::Elatin10::classic_character_class;
387             sub Char::Elatin10::capture;
388             sub Char::Elatin10::chr(;$);
389             sub Char::Elatin10::chr_();
390             sub Char::Elatin10::glob($);
391             sub Char::Elatin10::glob_();
392              
393             sub Char::Latin10::ord(;$);
394             sub Char::Latin10::ord_();
395             sub Char::Latin10::reverse(@);
396             sub Char::Latin10::getc(;*@);
397             sub Char::Latin10::length(;$);
398             sub Char::Latin10::substr($$;$$);
399             sub Char::Latin10::index($$;$);
400             sub Char::Latin10::rindex($$;$);
401              
402             #
403             # Regexp work
404             #
405 177     177   17990 BEGIN { eval q{ use vars qw(
  177     177   1258  
  177         365  
  177         87018  
406             $Char::Latin10::re_a
407             $Char::Latin10::re_t
408             $Char::Latin10::re_n
409             $Char::Latin10::re_r
410             ) } }
411              
412             #
413             # Character class
414             #
415 177     177   14058 BEGIN { eval q{ use vars qw(
  177     177   2813  
  177         415  
  177         3250338  
416             $dot
417             $dot_s
418             $eD
419             $eS
420             $eW
421             $eH
422             $eV
423             $eR
424             $eN
425             $not_alnum
426             $not_alpha
427             $not_ascii
428             $not_blank
429             $not_cntrl
430             $not_digit
431             $not_graph
432             $not_lower
433             $not_lower_i
434             $not_print
435             $not_punct
436             $not_space
437             $not_upper
438             $not_upper_i
439             $not_word
440             $not_xdigit
441             $eb
442             $eB
443             ) } }
444              
445             ${Char::Elatin10::dot} = qr{(?:[^\x0A])};
446             ${Char::Elatin10::dot_s} = qr{(?:[\x00-\xFF])};
447             ${Char::Elatin10::eD} = qr{(?:[^0-9])};
448              
449             # Vertical tabs are now whitespace
450             # \s in a regex now matches a vertical tab in all circumstances.
451             # http://search.cpan.org/dist/perl-5.18.0/pod/perldelta.pod#Vertical_tabs_are_now_whitespace
452             # ${Char::Elatin10::eS} = qr{(?:[^\x09\x0A \x0C\x0D\x20])};
453             # ${Char::Elatin10::eS} = qr{(?:[^\x09\x0A\x0B\x0C\x0D\x20])};
454             ${Char::Elatin10::eS} = qr{(?:[^\s])};
455              
456             ${Char::Elatin10::eW} = qr{(?:[^0-9A-Z_a-z])};
457             ${Char::Elatin10::eH} = qr{(?:[^\x09\x20])};
458             ${Char::Elatin10::eV} = qr{(?:[^\x0A\x0B\x0C\x0D])};
459             ${Char::Elatin10::eR} = qr{(?:\x0D\x0A|[\x0A\x0D])};
460             ${Char::Elatin10::eN} = qr{(?:[^\x0A])};
461             ${Char::Elatin10::not_alnum} = qr{(?:[^\x30-\x39\x41-\x5A\x61-\x7A])};
462             ${Char::Elatin10::not_alpha} = qr{(?:[^\x41-\x5A\x61-\x7A])};
463             ${Char::Elatin10::not_ascii} = qr{(?:[^\x00-\x7F])};
464             ${Char::Elatin10::not_blank} = qr{(?:[^\x09\x20])};
465             ${Char::Elatin10::not_cntrl} = qr{(?:[^\x00-\x1F\x7F])};
466             ${Char::Elatin10::not_digit} = qr{(?:[^\x30-\x39])};
467             ${Char::Elatin10::not_graph} = qr{(?:[^\x21-\x7F])};
468             ${Char::Elatin10::not_lower} = qr{(?:[^\x61-\x7A])};
469             ${Char::Elatin10::not_lower_i} = qr{(?:[\x00-\xFF])};
470             ${Char::Elatin10::not_print} = qr{(?:[^\x20-\x7F])};
471             ${Char::Elatin10::not_punct} = qr{(?:[^\x21-\x2F\x3A-\x3F\x40\x5B-\x5F\x60\x7B-\x7E])};
472             ${Char::Elatin10::not_space} = qr{(?:[^\s\x0B])};
473             ${Char::Elatin10::not_upper} = qr{(?:[^\x41-\x5A])};
474             ${Char::Elatin10::not_upper_i} = qr{(?:[\x00-\xFF])};
475             ${Char::Elatin10::not_word} = qr{(?:[^\x30-\x39\x41-\x5A\x5F\x61-\x7A])};
476             ${Char::Elatin10::not_xdigit} = qr{(?:[^\x30-\x39\x41-\x46\x61-\x66])};
477             ${Char::Elatin10::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))};
478             ${Char::Elatin10::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]))};
479              
480             # avoid: Name "Char::Elatin10::foo" used only once: possible typo at here.
481             ${Char::Elatin10::dot} = ${Char::Elatin10::dot};
482             ${Char::Elatin10::dot_s} = ${Char::Elatin10::dot_s};
483             ${Char::Elatin10::eD} = ${Char::Elatin10::eD};
484             ${Char::Elatin10::eS} = ${Char::Elatin10::eS};
485             ${Char::Elatin10::eW} = ${Char::Elatin10::eW};
486             ${Char::Elatin10::eH} = ${Char::Elatin10::eH};
487             ${Char::Elatin10::eV} = ${Char::Elatin10::eV};
488             ${Char::Elatin10::eR} = ${Char::Elatin10::eR};
489             ${Char::Elatin10::eN} = ${Char::Elatin10::eN};
490             ${Char::Elatin10::not_alnum} = ${Char::Elatin10::not_alnum};
491             ${Char::Elatin10::not_alpha} = ${Char::Elatin10::not_alpha};
492             ${Char::Elatin10::not_ascii} = ${Char::Elatin10::not_ascii};
493             ${Char::Elatin10::not_blank} = ${Char::Elatin10::not_blank};
494             ${Char::Elatin10::not_cntrl} = ${Char::Elatin10::not_cntrl};
495             ${Char::Elatin10::not_digit} = ${Char::Elatin10::not_digit};
496             ${Char::Elatin10::not_graph} = ${Char::Elatin10::not_graph};
497             ${Char::Elatin10::not_lower} = ${Char::Elatin10::not_lower};
498             ${Char::Elatin10::not_lower_i} = ${Char::Elatin10::not_lower_i};
499             ${Char::Elatin10::not_print} = ${Char::Elatin10::not_print};
500             ${Char::Elatin10::not_punct} = ${Char::Elatin10::not_punct};
501             ${Char::Elatin10::not_space} = ${Char::Elatin10::not_space};
502             ${Char::Elatin10::not_upper} = ${Char::Elatin10::not_upper};
503             ${Char::Elatin10::not_upper_i} = ${Char::Elatin10::not_upper_i};
504             ${Char::Elatin10::not_word} = ${Char::Elatin10::not_word};
505             ${Char::Elatin10::not_xdigit} = ${Char::Elatin10::not_xdigit};
506             ${Char::Elatin10::eb} = ${Char::Elatin10::eb};
507             ${Char::Elatin10::eB} = ${Char::Elatin10::eB};
508              
509             #
510             # Latin-10 split
511             #
512             sub Char::Elatin10::split(;$$$) {
513              
514             # P.794 29.2.161. split
515             # in Chapter 29: Functions
516             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
517              
518             # P.951 split
519             # in Chapter 27: Functions
520             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
521              
522 0     0 0 0 my $pattern = $_[0];
523 0         0 my $string = $_[1];
524 0         0 my $limit = $_[2];
525              
526             # if $pattern is also omitted or is the literal space, " "
527 0 0       0 if (not defined $pattern) {
528 0         0 $pattern = ' ';
529             }
530              
531             # if $string is omitted, the function splits the $_ string
532 0 0       0 if (not defined $string) {
533 0 0       0 if (defined $_) {
534 0         0 $string = $_;
535             }
536             else {
537 0         0 $string = '';
538             }
539             }
540              
541 0         0 my @split = ();
542              
543             # when string is empty
544 0 0       0 if ($string eq '') {
    0          
545              
546             # resulting list value in list context
547 0 0       0 if (wantarray) {
548 0         0 return @split;
549             }
550              
551             # count of substrings in scalar context
552             else {
553 0 0       0 carp "Use of implicit split to \@_ is deprecated" if $^W;
554 0         0 @_ = @split;
555 0         0 return scalar @_;
556             }
557             }
558              
559             # split's first argument is more consistently interpreted
560             #
561             # After some changes earlier in v5.17, split's behavior has been simplified:
562             # if the PATTERN argument evaluates to a string containing one space, it is
563             # treated the way that a literal string containing one space once was.
564             # http://search.cpan.org/dist/perl-5.18.0/pod/perldelta.pod#split's_first_argument_is_more_consistently_interpreted
565              
566             # if $pattern is also omitted or is the literal space, " ", the function splits
567             # on whitespace, /\s+/, after skipping any leading whitespace
568             # (and so on)
569              
570             elsif ($pattern eq ' ') {
571 0 0       0 if (not defined $limit) {
572 0         0 return CORE::split(' ', $string);
573             }
574             else {
575 0         0 return CORE::split(' ', $string, $limit);
576             }
577             }
578              
579             # if $limit is negative, it is treated as if an arbitrarily large $limit has been specified
580 0 0 0     0 if ((not defined $limit) or ($limit <= 0)) {
    0          
581              
582             # a pattern capable of matching either the null string or something longer than the
583             # null string will split the value of $string into separate characters wherever it
584             # matches the null string between characters
585             # (and so on)
586              
587 0 0       0 if ('' =~ / \A $pattern \z /xms) {
588 0         0 my $last_subexpression_offsets = _last_subexpression_offsets($pattern);
589 0         0 my $limit = scalar(() = $string =~ /($pattern)/oxmsg);
590              
591             # P.1024 Appendix W.10 Multibyte Processing
592             # of ISBN 1-56592-224-7 CJKV Information Processing
593             # (and so on)
594              
595             # the //m modifier is assumed when you split on the pattern /^/
596             # (and so on)
597              
598             # V
599 0   0     0 while ((--$limit > 0) and ($string =~ s/\A((?:$q_char)+?)$pattern//m)) {
600              
601             # if the $pattern contains parentheses, then the substring matched by each pair of parentheses
602             # is included in the resulting list, interspersed with the fields that are ordinarily returned
603             # (and so on)
604              
605 0         0 local $@;
606 0         0 for (my $digit=1; $digit <= ($last_subexpression_offsets + 1); $digit++) {
607 0         0 push @split, eval('$' . $digit);
608             }
609             }
610             }
611              
612             else {
613 0         0 my $last_subexpression_offsets = _last_subexpression_offsets($pattern);
614              
615             # V
616 0         0 while ($string =~ s/\A((?:$q_char)*?)$pattern//m) {
617 0         0 local $@;
618 0         0 for (my $digit=1; $digit <= ($last_subexpression_offsets + 1); $digit++) {
619 0         0 push @split, eval('$' . $digit);
620             }
621             }
622             }
623             }
624              
625             elsif ($limit > 0) {
626 0 0       0 if ('' =~ / \A $pattern \z /xms) {
627 0         0 my $last_subexpression_offsets = _last_subexpression_offsets($pattern);
628 0   0     0 while ((--$limit > 0) and (CORE::length($string) > 0)) {
629              
630             # V
631 0 0       0 if ($string =~ s/\A((?:$q_char)+?)$pattern//m) {
632 0         0 local $@;
633 0         0 for (my $digit=1; $digit <= ($last_subexpression_offsets + 1); $digit++) {
634 0         0 push @split, eval('$' . $digit);
635             }
636             }
637             }
638             }
639             else {
640 0         0 my $last_subexpression_offsets = _last_subexpression_offsets($pattern);
641 0   0     0 while ((--$limit > 0) and (CORE::length($string) > 0)) {
642              
643             # V
644 0 0       0 if ($string =~ s/\A((?:$q_char)*?)$pattern//m) {
645 0         0 local $@;
646 0         0 for (my $digit=1; $digit <= ($last_subexpression_offsets + 1); $digit++) {
647 0         0 push @split, eval('$' . $digit);
648             }
649             }
650             }
651             }
652             }
653              
654 0 0       0 if (CORE::length($string) > 0) {
655 0         0 push @split, $string;
656             }
657              
658             # if $_[2] (NOT "$limit") is omitted or zero, trailing null fields are stripped from the result
659 0 0 0     0 if ((not defined $_[2]) or ($_[2] == 0)) {
660 0   0     0 while ((scalar(@split) >= 1) and ($split[-1] eq '')) {
661 0         0 pop @split;
662             }
663             }
664              
665             # resulting list value in list context
666 0 0       0 if (wantarray) {
667 0         0 return @split;
668             }
669              
670             # count of substrings in scalar context
671             else {
672 0 0       0 carp "Use of implicit split to \@_ is deprecated" if $^W;
673 0         0 @_ = @split;
674 0         0 return scalar @_;
675             }
676             }
677              
678             #
679             # get last subexpression offsets
680             #
681             sub _last_subexpression_offsets {
682 0     0   0 my $pattern = $_[0];
683              
684             # remove comment
685 0         0 $pattern =~ s/\(\?\# .*? \)//oxmsg;
686              
687 0         0 my $modifier = '';
688 0 0       0 if ($pattern =~ /\(\?\^? ([\-A-Za-z]+) :/oxms) {
689 0         0 $modifier = $1;
690 0         0 $modifier =~ s/-[A-Za-z]*//;
691             }
692              
693             # with /x modifier
694 0         0 my @char = ();
695 0 0       0 if ($modifier =~ /x/oxms) {
696 0         0 @char = $pattern =~ /\G(
697             \\ (?:$q_char) |
698             \# (?:$q_char)*? $ |
699             \[ (?: \\\] | (?:$q_char))+? \] |
700             \(\? |
701             (?:$q_char)
702             )/oxmsg;
703             }
704              
705             # without /x modifier
706             else {
707 0         0 @char = $pattern =~ /\G(
708             \\ (?:$q_char) |
709             \[ (?: \\\] | (?:$q_char))+? \] |
710             \(\? |
711             (?:$q_char)
712             )/oxmsg;
713             }
714              
715 0         0 return scalar grep { $_ eq '(' } @char;
  0         0  
716             }
717              
718             #
719             # Latin-10 transliteration (tr///)
720             #
721             sub Char::Elatin10::tr($$$$;$) {
722              
723 0     0 0 0 my $bind_operator = $_[1];
724 0         0 my $searchlist = $_[2];
725 0         0 my $replacementlist = $_[3];
726 0   0     0 my $modifier = $_[4] || '';
727              
728 0 0       0 if ($modifier =~ /r/oxms) {
729 0 0       0 if ($bind_operator =~ / !~ /oxms) {
730 0         0 croak "Using !~ with tr///r doesn't make sense";
731             }
732             }
733              
734 0         0 my @char = $_[0] =~ /\G ($q_char) /oxmsg;
735 0         0 my @searchlist = _charlist_tr($searchlist);
736 0         0 my @replacementlist = _charlist_tr($replacementlist);
737              
738 0         0 my %tr = ();
739 0         0 for (my $i=0; $i <= $#searchlist; $i++) {
740 0 0       0 if (not exists $tr{$searchlist[$i]}) {
741 0 0 0     0 if (defined $replacementlist[$i] and ($replacementlist[$i] ne '')) {
    0 0        
    0          
742 0         0 $tr{$searchlist[$i]} = $replacementlist[$i];
743             }
744             elsif ($modifier =~ /d/oxms) {
745 0         0 $tr{$searchlist[$i]} = '';
746             }
747             elsif (defined $replacementlist[-1] and ($replacementlist[-1] ne '')) {
748 0         0 $tr{$searchlist[$i]} = $replacementlist[-1];
749             }
750             else {
751 0         0 $tr{$searchlist[$i]} = $searchlist[$i];
752             }
753             }
754             }
755              
756 0         0 my $tr = 0;
757 0         0 my $replaced = '';
758 0 0       0 if ($modifier =~ /c/oxms) {
759 0         0 while (defined(my $char = shift @char)) {
760 0 0       0 if (not exists $tr{$char}) {
761 0 0       0 if (defined $replacementlist[0]) {
762 0         0 $replaced .= $replacementlist[0];
763             }
764 0         0 $tr++;
765 0 0       0 if ($modifier =~ /s/oxms) {
766 0   0     0 while (@char and (not exists $tr{$char[0]})) {
767 0         0 shift @char;
768 0         0 $tr++;
769             }
770             }
771             }
772             else {
773 0         0 $replaced .= $char;
774             }
775             }
776             }
777             else {
778 0         0 while (defined(my $char = shift @char)) {
779 0 0       0 if (exists $tr{$char}) {
780 0         0 $replaced .= $tr{$char};
781 0         0 $tr++;
782 0 0       0 if ($modifier =~ /s/oxms) {
783 0   0     0 while (@char and (exists $tr{$char[0]}) and ($tr{$char[0]} eq $tr{$char})) {
      0        
784 0         0 shift @char;
785 0         0 $tr++;
786             }
787             }
788             }
789             else {
790 0         0 $replaced .= $char;
791             }
792             }
793             }
794              
795 0 0       0 if ($modifier =~ /r/oxms) {
796 0         0 return $replaced;
797             }
798             else {
799 0         0 $_[0] = $replaced;
800 0 0       0 if ($bind_operator =~ / !~ /oxms) {
801 0         0 return not $tr;
802             }
803             else {
804 0         0 return $tr;
805             }
806             }
807             }
808              
809             #
810             # Latin-10 chop
811             #
812             sub Char::Elatin10::chop(@) {
813              
814 0     0 0 0 my $chop;
815 0 0       0 if (@_ == 0) {
816 0         0 my @char = /\G ($q_char) /oxmsg;
817 0         0 $chop = pop @char;
818 0         0 $_ = join '', @char;
819             }
820             else {
821 0         0 for (@_) {
822 0         0 my @char = /\G ($q_char) /oxmsg;
823 0         0 $chop = pop @char;
824 0         0 $_ = join '', @char;
825             }
826             }
827 0         0 return $chop;
828             }
829              
830             #
831             # Latin-10 index by octet
832             #
833             sub Char::Elatin10::index($$;$) {
834              
835 0     0 1 0 my($str,$substr,$position) = @_;
836 0   0     0 $position ||= 0;
837 0         0 my $pos = 0;
838              
839 0         0 while ($pos < CORE::length($str)) {
840 0 0       0 if (CORE::substr($str,$pos,CORE::length($substr)) eq $substr) {
841 0 0       0 if ($pos >= $position) {
842 0         0 return $pos;
843             }
844             }
845 0 0       0 if (CORE::substr($str,$pos) =~ /\A ($q_char) /oxms) {
846 0         0 $pos += CORE::length($1);
847             }
848             else {
849 0         0 $pos += 1;
850             }
851             }
852 0         0 return -1;
853             }
854              
855             #
856             # Latin-10 reverse index
857             #
858             sub Char::Elatin10::rindex($$;$) {
859              
860 0     0 0 0 my($str,$substr,$position) = @_;
861 0   0     0 $position ||= CORE::length($str) - 1;
862 0         0 my $pos = 0;
863 0         0 my $rindex = -1;
864              
865 0   0     0 while (($pos < CORE::length($str)) and ($pos <= $position)) {
866 0 0       0 if (CORE::substr($str,$pos,CORE::length($substr)) eq $substr) {
867 0         0 $rindex = $pos;
868             }
869 0 0       0 if (CORE::substr($str,$pos) =~ /\A ($q_char) /oxms) {
870 0         0 $pos += CORE::length($1);
871             }
872             else {
873 0         0 $pos += 1;
874             }
875             }
876 0         0 return $rindex;
877             }
878              
879             #
880             # Latin-10 lower case first with parameter
881             #
882             sub Char::Elatin10::lcfirst(@) {
883 0 0   0 0 0 if (@_) {
884 0         0 my $s = shift @_;
885 0 0 0     0 if (@_ and wantarray) {
886 0         0 return Char::Elatin10::lc(CORE::substr($s,0,1)) . CORE::substr($s,1), @_;
887             }
888             else {
889 0         0 return Char::Elatin10::lc(CORE::substr($s,0,1)) . CORE::substr($s,1);
890             }
891             }
892             else {
893 0         0 return Char::Elatin10::lc(CORE::substr($_,0,1)) . CORE::substr($_,1);
894             }
895             }
896              
897             #
898             # Latin-10 lower case first without parameter
899             #
900             sub Char::Elatin10::lcfirst_() {
901 0     0 0 0 return Char::Elatin10::lc(CORE::substr($_,0,1)) . CORE::substr($_,1);
902             }
903              
904             #
905             # Latin-10 lower case with parameter
906             #
907             sub Char::Elatin10::lc(@) {
908 0 0   0 0 0 if (@_) {
909 0         0 my $s = shift @_;
910 0 0 0     0 if (@_ and wantarray) {
911 0 0       0 return join('', map {defined($lc{$_}) ? $lc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg)), @_;
  0         0  
912             }
913             else {
914 0 0       0 return join('', map {defined($lc{$_}) ? $lc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg));
  0         0  
915             }
916             }
917             else {
918 0         0 return Char::Elatin10::lc_();
919             }
920             }
921              
922             #
923             # Latin-10 lower case without parameter
924             #
925             sub Char::Elatin10::lc_() {
926 0     0 0 0 my $s = $_;
927 0 0       0 return join '', map {defined($lc{$_}) ? $lc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg);
  0         0  
928             }
929              
930             #
931             # Latin-10 upper case first with parameter
932             #
933             sub Char::Elatin10::ucfirst(@) {
934 0 0   0 0 0 if (@_) {
935 0         0 my $s = shift @_;
936 0 0 0     0 if (@_ and wantarray) {
937 0         0 return Char::Elatin10::uc(CORE::substr($s,0,1)) . CORE::substr($s,1), @_;
938             }
939             else {
940 0         0 return Char::Elatin10::uc(CORE::substr($s,0,1)) . CORE::substr($s,1);
941             }
942             }
943             else {
944 0         0 return Char::Elatin10::uc(CORE::substr($_,0,1)) . CORE::substr($_,1);
945             }
946             }
947              
948             #
949             # Latin-10 upper case first without parameter
950             #
951             sub Char::Elatin10::ucfirst_() {
952 0     0 0 0 return Char::Elatin10::uc(CORE::substr($_,0,1)) . CORE::substr($_,1);
953             }
954              
955             #
956             # Latin-10 upper case with parameter
957             #
958             sub Char::Elatin10::uc(@) {
959 0 0   0 0 0 if (@_) {
960 0         0 my $s = shift @_;
961 0 0 0     0 if (@_ and wantarray) {
962 0 0       0 return join('', map {defined($uc{$_}) ? $uc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg)), @_;
  0         0  
963             }
964             else {
965 0 0       0 return join('', map {defined($uc{$_}) ? $uc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg));
  0         0  
966             }
967             }
968             else {
969 0         0 return Char::Elatin10::uc_();
970             }
971             }
972              
973             #
974             # Latin-10 upper case without parameter
975             #
976             sub Char::Elatin10::uc_() {
977 0     0 0 0 my $s = $_;
978 0 0       0 return join '', map {defined($uc{$_}) ? $uc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg);
  0         0  
979             }
980              
981             #
982             # Latin-10 fold case with parameter
983             #
984             sub Char::Elatin10::fc(@) {
985 0 0   0 0 0 if (@_) {
986 0         0 my $s = shift @_;
987 0 0 0     0 if (@_ and wantarray) {
988 0 0       0 return join('', map {defined($fc{$_}) ? $fc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg)), @_;
  0         0  
989             }
990             else {
991 0 0       0 return join('', map {defined($fc{$_}) ? $fc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg));
  0         0  
992             }
993             }
994             else {
995 0         0 return Char::Elatin10::fc_();
996             }
997             }
998              
999             #
1000             # Latin-10 fold case without parameter
1001             #
1002             sub Char::Elatin10::fc_() {
1003 0     0 0 0 my $s = $_;
1004 0 0       0 return join '', map {defined($fc{$_}) ? $fc{$_} : $_} ($s =~ /\G ($q_char) /oxmsg);
  0         0  
1005             }
1006              
1007             #
1008             # Latin-10 regexp capture
1009             #
1010             {
1011             sub Char::Elatin10::capture {
1012 0     0 1 0 return $_[0];
1013             }
1014             }
1015              
1016             #
1017             # Latin-10 regexp ignore case modifier
1018             #
1019             sub Char::Elatin10::ignorecase {
1020              
1021 0     0 0 0 my @string = @_;
1022 0         0 my $metachar = qr/[\@\\|[\]{]/oxms;
1023              
1024             # ignore case of $scalar or @array
1025 0         0 for my $string (@string) {
1026              
1027             # split regexp
1028 0         0 my @char = $string =~ /\G(
1029             \[\^ |
1030             \\? (?:$q_char)
1031             )/oxmsg;
1032              
1033             # unescape character
1034 0         0 for (my $i=0; $i <= $#char; $i++) {
1035 0 0       0 next if not defined $char[$i];
1036              
1037             # open character class [...]
1038 0 0       0 if ($char[$i] eq '[') {
    0          
    0          
    0          
1039 0         0 my $left = $i;
1040              
1041             # [] make die "unmatched [] in regexp ..."
1042              
1043 0 0       0 if ($char[$i+1] eq ']') {
1044 0         0 $i++;
1045             }
1046              
1047 0         0 while (1) {
1048 0 0       0 if (++$i > $#char) {
1049 0         0 croak "Unmatched [] in regexp";
1050             }
1051 0 0       0 if ($char[$i] eq ']') {
1052 0         0 my $right = $i;
1053 0         0 my @charlist = charlist_qr(@char[$left+1..$right-1], 'i');
1054              
1055             # escape character
1056 0         0 for my $char (@charlist) {
1057 0 0       0 if (0) {
1058             }
1059              
1060 0         0 elsif ($char =~ /\A [.|)] \z/oxms) {
1061 0         0 $char = $1 . '\\' . $char;
1062             }
1063             }
1064              
1065             # [...]
1066 0         0 splice @char, $left, $right-$left+1, '(?:' . join('|', @charlist) . ')';
1067              
1068 0         0 $i = $left;
1069 0         0 last;
1070             }
1071             }
1072             }
1073              
1074             # open character class [^...]
1075             elsif ($char[$i] eq '[^') {
1076 0         0 my $left = $i;
1077              
1078             # [^] make die "unmatched [] in regexp ..."
1079              
1080 0 0       0 if ($char[$i+1] eq ']') {
1081 0         0 $i++;
1082             }
1083              
1084 0         0 while (1) {
1085 0 0       0 if (++$i > $#char) {
1086 0         0 croak "Unmatched [] in regexp";
1087             }
1088 0 0       0 if ($char[$i] eq ']') {
1089 0         0 my $right = $i;
1090 0         0 my @charlist = charlist_not_qr(@char[$left+1..$right-1], 'i');
1091              
1092             # escape character
1093 0         0 for my $char (@charlist) {
1094 0 0       0 if (0) {
1095             }
1096              
1097 0         0 elsif ($char =~ /\A [.|)] \z/oxms) {
1098 0         0 $char = '\\' . $char;
1099             }
1100             }
1101              
1102             # [^...]
1103 0         0 splice @char, $left, $right-$left+1, '(?!' . join('|', @charlist) . ")(?:$your_char)";
1104              
1105 0         0 $i = $left;
1106 0         0 last;
1107             }
1108             }
1109             }
1110              
1111             # rewrite classic character class or escape character
1112             elsif (my $char = classic_character_class($char[$i])) {
1113 0         0 $char[$i] = $char;
1114             }
1115              
1116             # with /i modifier
1117             elsif ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) {
1118 0         0 my $uc = Char::Elatin10::uc($char[$i]);
1119 0         0 my $fc = Char::Elatin10::fc($char[$i]);
1120 0 0       0 if ($uc ne $fc) {
1121 0 0       0 if (CORE::length($fc) == 1) {
1122 0         0 $char[$i] = '[' . $uc . $fc . ']';
1123             }
1124             else {
1125 0         0 $char[$i] = '(?:' . $uc . '|' . $fc . ')';
1126             }
1127             }
1128             }
1129             }
1130              
1131             # characterize
1132 0         0 for (my $i=0; $i <= $#char; $i++) {
1133 0 0       0 next if not defined $char[$i];
1134              
1135 0 0       0 if (0) {
1136             }
1137              
1138             # quote character before ? + * {
1139 0 0       0 elsif (($i >= 1) and ($char[$i] =~ /\A [\?\+\*\{] \z/oxms)) {
1140 0 0       0 if ($char[$i-1] !~ /\A [\x00-\xFF] \z/oxms) {
1141 0         0 $char[$i-1] = '(?:' . $char[$i-1] . ')';
1142             }
1143             }
1144             }
1145              
1146 0         0 $string = join '', @char;
1147             }
1148              
1149             # make regexp string
1150 0         0 return @string;
1151             }
1152              
1153             #
1154             # classic character class ( \D \S \W \d \s \w \C \X \H \V \h \v \R \N \b \B )
1155             #
1156             sub Char::Elatin10::classic_character_class {
1157 0     0 0 0 my($char) = @_;
1158              
1159             return {
1160 0   0     0 '\D' => '${Char::Elatin10::eD}',
1161             '\S' => '${Char::Elatin10::eS}',
1162             '\W' => '${Char::Elatin10::eW}',
1163             '\d' => '[0-9]',
1164              
1165             # Before Perl 5.6, \s only matched the five whitespace characters
1166             # tab, newline, form-feed, carriage return, and the space character
1167             # itself, which, taken together, is the character class [\t\n\f\r ].
1168              
1169             # Vertical tabs are now whitespace
1170             # \s in a regex now matches a vertical tab in all circumstances.
1171             # http://search.cpan.org/dist/perl-5.18.0/pod/perldelta.pod#Vertical_tabs_are_now_whitespace
1172             # \t \n \v \f \r space
1173             # '\s' => '[\x09\x0A \x0C\x0D\x20]',
1174             # '\s' => '[\x09\x0A\x0B\x0C\x0D\x20]',
1175             '\s' => '\s',
1176              
1177             '\w' => '[0-9A-Z_a-z]',
1178             '\C' => '[\x00-\xFF]',
1179             '\X' => 'X',
1180              
1181             # \h \v \H \V
1182              
1183             # P.114 Character Class Shortcuts
1184             # in Chapter 7: In the World of Regular Expressions
1185             # of ISBN 978-0-596-52010-6 Learning Perl, Fifth Edition
1186              
1187             # P.357 13.2.3 Whitespace
1188             # in Chapter 13: perlrecharclass: Perl Regular Expression Character Classes
1189             # of ISBN-13: 978-1-906966-02-7 The Perl Language Reference Manual (for Perl version 5.12.1)
1190             #
1191             # 0x00009 CHARACTER TABULATION h s
1192             # 0x0000a LINE FEED (LF) vs
1193             # 0x0000b LINE TABULATION v
1194             # 0x0000c FORM FEED (FF) vs
1195             # 0x0000d CARRIAGE RETURN (CR) vs
1196             # 0x00020 SPACE h s
1197              
1198             # P.196 Table 5-9. Alphanumeric regex metasymbols
1199             # in Chapter 5. Pattern Matching
1200             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
1201              
1202             # (and so on)
1203              
1204             '\H' => '${Char::Elatin10::eH}',
1205             '\V' => '${Char::Elatin10::eV}',
1206             '\h' => '[\x09\x20]',
1207             '\v' => '[\x0A\x0B\x0C\x0D]',
1208             '\R' => '${Char::Elatin10::eR}',
1209              
1210             # \N
1211             #
1212             # http://perldoc.perl.org/perlre.html
1213             # Character Classes and other Special Escapes
1214             # Any character but \n (experimental). Not affected by /s modifier
1215              
1216             '\N' => '${Char::Elatin10::eN}',
1217              
1218             # \b \B
1219              
1220             # P.180 Boundaries: The \b and \B Assertions
1221             # in Chapter 5: Pattern Matching
1222             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
1223              
1224             # P.219 Boundaries: The \b and \B Assertions
1225             # in Chapter 5: Pattern Matching
1226             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
1227              
1228             # '\b' => '(?:(?<=\A|\W)(?=\w)|(?<=\w)(?=\W|\z))',
1229             '\b' => '${Char::Elatin10::eb}',
1230              
1231             # '\B' => '(?:(?<=\w)(?=\w)|(?<=\W)(?=\W))',
1232             '\B' => '${Char::Elatin10::eB}',
1233              
1234             }->{$char} || '';
1235             }
1236              
1237             #
1238             # prepare Latin-10 characters per length
1239             #
1240              
1241             # 1 octet characters
1242             my @chars1 = ();
1243             sub chars1 {
1244 0 0   0 0 0 if (@chars1) {
1245 0         0 return @chars1;
1246             }
1247 0 0       0 if (exists $range_tr{1}) {
1248 0         0 my @ranges = @{ $range_tr{1} };
  0         0  
1249 0         0 while (my @range = splice(@ranges,0,1)) {
1250 0         0 for my $oct0 (@{$range[0]}) {
  0         0  
1251 0         0 push @chars1, pack 'C', $oct0;
1252             }
1253             }
1254             }
1255 0         0 return @chars1;
1256             }
1257              
1258             # 2 octets characters
1259             my @chars2 = ();
1260             sub chars2 {
1261 0 0   0 0 0 if (@chars2) {
1262 0         0 return @chars2;
1263             }
1264 0 0       0 if (exists $range_tr{2}) {
1265 0         0 my @ranges = @{ $range_tr{2} };
  0         0  
1266 0         0 while (my @range = splice(@ranges,0,2)) {
1267 0         0 for my $oct0 (@{$range[0]}) {
  0         0  
1268 0         0 for my $oct1 (@{$range[1]}) {
  0         0  
1269 0         0 push @chars2, pack 'CC', $oct0,$oct1;
1270             }
1271             }
1272             }
1273             }
1274 0         0 return @chars2;
1275             }
1276              
1277             # 3 octets characters
1278             my @chars3 = ();
1279             sub chars3 {
1280 0 0   0 0 0 if (@chars3) {
1281 0         0 return @chars3;
1282             }
1283 0 0       0 if (exists $range_tr{3}) {
1284 0         0 my @ranges = @{ $range_tr{3} };
  0         0  
1285 0         0 while (my @range = splice(@ranges,0,3)) {
1286 0         0 for my $oct0 (@{$range[0]}) {
  0         0  
1287 0         0 for my $oct1 (@{$range[1]}) {
  0         0  
1288 0         0 for my $oct2 (@{$range[2]}) {
  0         0  
1289 0         0 push @chars3, pack 'CCC', $oct0,$oct1,$oct2;
1290             }
1291             }
1292             }
1293             }
1294             }
1295 0         0 return @chars3;
1296             }
1297              
1298             # 4 octets characters
1299             my @chars4 = ();
1300             sub chars4 {
1301 0 0   0 0 0 if (@chars4) {
1302 0         0 return @chars4;
1303             }
1304 0 0       0 if (exists $range_tr{4}) {
1305 0         0 my @ranges = @{ $range_tr{4} };
  0         0  
1306 0         0 while (my @range = splice(@ranges,0,4)) {
1307 0         0 for my $oct0 (@{$range[0]}) {
  0         0  
1308 0         0 for my $oct1 (@{$range[1]}) {
  0         0  
1309 0         0 for my $oct2 (@{$range[2]}) {
  0         0  
1310 0         0 for my $oct3 (@{$range[3]}) {
  0         0  
1311 0         0 push @chars4, pack 'CCCC', $oct0,$oct1,$oct2,$oct3;
1312             }
1313             }
1314             }
1315             }
1316             }
1317             }
1318 0         0 return @chars4;
1319             }
1320              
1321             #
1322             # Latin-10 open character list for tr
1323             #
1324             sub _charlist_tr {
1325              
1326 0     0   0 local $_ = shift @_;
1327              
1328             # unescape character
1329 0         0 my @char = ();
1330 0         0 while (not /\G \z/oxmsgc) {
1331 0 0       0 if (/\G (\\0?55|\\x2[Dd]|\\-) /oxmsgc) {
    0          
    0          
    0          
    0          
    0          
    0          
1332 0         0 push @char, '\-';
1333             }
1334             elsif (/\G \\ ([0-7]{2,3}) /oxmsgc) {
1335 0         0 push @char, CORE::chr(oct $1);
1336             }
1337             elsif (/\G \\x ([0-9A-Fa-f]{1,2}) /oxmsgc) {
1338 0         0 push @char, CORE::chr(hex $1);
1339             }
1340             elsif (/\G \\c ([\x40-\x5F]) /oxmsgc) {
1341 0         0 push @char, CORE::chr(CORE::ord($1) & 0x1F);
1342             }
1343             elsif (/\G (\\ [0nrtfbae]) /oxmsgc) {
1344 0         0 push @char, {
1345             '\0' => "\0",
1346             '\n' => "\n",
1347             '\r' => "\r",
1348             '\t' => "\t",
1349             '\f' => "\f",
1350             '\b' => "\x08", # \b means backspace in character class
1351             '\a' => "\a",
1352             '\e' => "\e",
1353             }->{$1};
1354             }
1355             elsif (/\G \\ ($q_char) /oxmsgc) {
1356 0         0 push @char, $1;
1357             }
1358             elsif (/\G ($q_char) /oxmsgc) {
1359 0         0 push @char, $1;
1360             }
1361             }
1362              
1363             # join separated multiple-octet
1364 0         0 @char = join('',@char) =~ /\G (\\-|$q_char) /oxmsg;
1365              
1366             # unescape '-'
1367 0         0 my @i = ();
1368 0         0 for my $i (0 .. $#char) {
1369 0 0       0 if ($char[$i] eq '\-') {
    0          
1370 0         0 $char[$i] = '-';
1371             }
1372             elsif ($char[$i] eq '-') {
1373 0 0 0     0 if ((0 < $i) and ($i < $#char)) {
1374 0         0 push @i, $i;
1375             }
1376             }
1377             }
1378              
1379             # open character list (reverse for splice)
1380 0         0 for my $i (CORE::reverse @i) {
1381 0         0 my @range = ();
1382              
1383             # range error
1384 0 0 0     0 if ((CORE::length($char[$i-1]) > CORE::length($char[$i+1])) or ($char[$i-1] gt $char[$i+1])) {
1385 0         0 croak "Invalid tr/// range \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1386             }
1387              
1388             # range of multiple-octet code
1389 0 0       0 if (CORE::length($char[$i-1]) == 1) {
    0          
    0          
    0          
1390 0 0       0 if (CORE::length($char[$i+1]) == 1) {
    0          
    0          
    0          
1391 0 0       0 push @range, grep {($char[$i-1] le $_) and ($_ le $char[$i+1])} chars1();
  0         0  
1392             }
1393             elsif (CORE::length($char[$i+1]) == 2) {
1394 0         0 push @range, grep {$char[$i-1] le $_} chars1();
  0         0  
1395 0         0 push @range, grep {$_ le $char[$i+1]} chars2();
  0         0  
1396             }
1397             elsif (CORE::length($char[$i+1]) == 3) {
1398 0         0 push @range, grep {$char[$i-1] le $_} chars1();
  0         0  
1399 0         0 push @range, chars2();
1400 0         0 push @range, grep {$_ le $char[$i+1]} chars3();
  0         0  
1401             }
1402             elsif (CORE::length($char[$i+1]) == 4) {
1403 0         0 push @range, grep {$char[$i-1] le $_} chars1();
  0         0  
1404 0         0 push @range, chars2();
1405 0         0 push @range, chars3();
1406 0         0 push @range, grep {$_ le $char[$i+1]} chars4();
  0         0  
1407             }
1408             else {
1409 0         0 croak "Invalid tr/// range (over 4octets) \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1410             }
1411             }
1412             elsif (CORE::length($char[$i-1]) == 2) {
1413 0 0       0 if (CORE::length($char[$i+1]) == 2) {
    0          
    0          
1414 0 0       0 push @range, grep {($char[$i-1] le $_) and ($_ le $char[$i+1])} chars2();
  0         0  
1415             }
1416             elsif (CORE::length($char[$i+1]) == 3) {
1417 0         0 push @range, grep {$char[$i-1] le $_} chars2();
  0         0  
1418 0         0 push @range, grep {$_ le $char[$i+1]} chars3();
  0         0  
1419             }
1420             elsif (CORE::length($char[$i+1]) == 4) {
1421 0         0 push @range, grep {$char[$i-1] le $_} chars2();
  0         0  
1422 0         0 push @range, chars3();
1423 0         0 push @range, grep {$_ le $char[$i+1]} chars4();
  0         0  
1424             }
1425             else {
1426 0         0 croak "Invalid tr/// range (over 4octets) \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1427             }
1428             }
1429             elsif (CORE::length($char[$i-1]) == 3) {
1430 0 0       0 if (CORE::length($char[$i+1]) == 3) {
    0          
1431 0 0       0 push @range, grep {($char[$i-1] le $_) and ($_ le $char[$i+1])} chars3();
  0         0  
1432             }
1433             elsif (CORE::length($char[$i+1]) == 4) {
1434 0         0 push @range, grep {$char[$i-1] le $_} chars3();
  0         0  
1435 0         0 push @range, grep {$_ le $char[$i+1]} chars4();
  0         0  
1436             }
1437             else {
1438 0         0 croak "Invalid tr/// range (over 4octets) \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1439             }
1440             }
1441             elsif (CORE::length($char[$i-1]) == 4) {
1442 0 0       0 if (CORE::length($char[$i+1]) == 4) {
1443 0 0       0 push @range, grep {($char[$i-1] le $_) and ($_ le $char[$i+1])} chars4();
  0         0  
1444             }
1445             else {
1446 0         0 croak "Invalid tr/// range (over 4octets) \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1447             }
1448             }
1449             else {
1450 0         0 croak "Invalid tr/// range (over 4octets) \"\\x" . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]) . '"';
1451             }
1452              
1453 0         0 splice @char, $i-1, 3, @range;
1454             }
1455              
1456 0         0 return @char;
1457             }
1458              
1459             #
1460             # Latin-10 open character class
1461             #
1462             sub _cc {
1463 0 0   0   0 if (scalar(@_) == 0) {
    0          
    0          
1464 0         0 die __FILE__, ": subroutine cc got no parameter.";
1465             }
1466             elsif (scalar(@_) == 1) {
1467 0         0 return sprintf('\x%02X',$_[0]);
1468             }
1469             elsif (scalar(@_) == 2) {
1470 0 0       0 if ($_[0] > $_[1]) {
    0          
    0          
1471 0         0 die __FILE__, ": subroutine cc got \$_[0] > \$_[1] parameters).";
1472             }
1473             elsif ($_[0] == $_[1]) {
1474 0         0 return sprintf('\x%02X',$_[0]);
1475             }
1476             elsif (($_[0]+1) == $_[1]) {
1477 0         0 return sprintf('[\\x%02X\\x%02X]',$_[0],$_[1]);
1478             }
1479             else {
1480 0         0 return sprintf('[\\x%02X-\\x%02X]',$_[0],$_[1]);
1481             }
1482             }
1483             else {
1484 0         0 die __FILE__, ": subroutine cc got 3 or more parameters (@{[scalar(@_)]} parameters).";
  0         0  
1485             }
1486             }
1487              
1488             #
1489             # Latin-10 octet range
1490             #
1491             sub _octets {
1492 0     0   0 my $length = shift @_;
1493              
1494 0 0       0 if ($length == 1) {
1495 0         0 my($a1) = unpack 'C', $_[0];
1496 0         0 my($z1) = unpack 'C', $_[1];
1497              
1498 0 0       0 if ($a1 > $z1) {
1499 0         0 croak 'Invalid [] range in regexp (CORE::ord(A) > CORE::ord(B)) ' . '\x' . unpack('H*',$a1) . '-\x' . unpack('H*',$z1);
1500             }
1501              
1502 0 0       0 if ($a1 == $z1) {
    0          
1503 0         0 return sprintf('\x%02X',$a1);
1504             }
1505             elsif (($a1+1) == $z1) {
1506 0         0 return sprintf('\x%02X\x%02X',$a1,$z1);
1507             }
1508             else {
1509 0         0 return sprintf('\x%02X-\x%02X',$a1,$z1);
1510             }
1511             }
1512             else {
1513 0         0 die __FILE__, ": subroutine _octets got invalid length ($length).";
1514             }
1515             }
1516              
1517             #
1518             # Latin-10 range regexp
1519             #
1520             sub _range_regexp {
1521 0     0   0 my($length,$first,$last) = @_;
1522              
1523 0         0 my @range_regexp = ();
1524 0 0       0 if (not exists $range_tr{$length}) {
1525 0         0 return @range_regexp;
1526             }
1527              
1528 0         0 my @ranges = @{ $range_tr{$length} };
  0         0  
1529 0         0 while (my @range = splice(@ranges,0,$length)) {
1530 0         0 my $min = '';
1531 0         0 my $max = '';
1532 0         0 for (my $i=0; $i < $length; $i++) {
1533 0         0 $min .= pack 'C', $range[$i][0];
1534 0         0 $max .= pack 'C', $range[$i][-1];
1535             }
1536              
1537             # min___max
1538             # FIRST_____________LAST
1539             # (nothing)
1540              
1541 0 0 0     0 if ($max lt $first) {
    0 0        
    0 0        
    0 0        
    0 0        
    0 0        
    0 0        
1542             }
1543              
1544             # **********
1545             # min_________max
1546             # FIRST_____________LAST
1547             # **********
1548              
1549             elsif (($min le $first) and ($first le $max) and ($max le $last)) {
1550 0         0 push @range_regexp, _octets($length,$first,$max,$min,$max);
1551             }
1552              
1553             # **********************
1554             # min________________max
1555             # FIRST_____________LAST
1556             # **********************
1557              
1558             elsif (($min eq $first) and ($max eq $last)) {
1559 0         0 push @range_regexp, _octets($length,$first,$last,$min,$max);
1560             }
1561              
1562             # *********
1563             # min___max
1564             # FIRST_____________LAST
1565             # *********
1566              
1567             elsif (($first le $min) and ($max le $last)) {
1568 0         0 push @range_regexp, _octets($length,$min,$max,$min,$max);
1569             }
1570              
1571             # **********************
1572             # min__________________________max
1573             # FIRST_____________LAST
1574             # **********************
1575              
1576             elsif (($min le $first) and ($last le $max)) {
1577 0         0 push @range_regexp, _octets($length,$first,$last,$min,$max);
1578             }
1579              
1580             # *********
1581             # min________max
1582             # FIRST_____________LAST
1583             # *********
1584              
1585             elsif (($first le $min) and ($min le $last) and ($last le $max)) {
1586 0         0 push @range_regexp, _octets($length,$min,$last,$min,$max);
1587             }
1588              
1589             # min___max
1590             # FIRST_____________LAST
1591             # (nothing)
1592              
1593             elsif ($last lt $min) {
1594             }
1595              
1596             else {
1597 0         0 die __FILE__, ": subroutine _range_regexp panic.";
1598             }
1599             }
1600              
1601 0         0 return @range_regexp;
1602             }
1603              
1604             #
1605             # Latin-10 open character list for qr and not qr
1606             #
1607             sub _charlist {
1608              
1609 0     0   0 my $modifier = pop @_;
1610 0         0 my @char = @_;
1611              
1612 0 0       0 my $ignorecase = ($modifier =~ /i/oxms) ? 1 : 0;
1613              
1614             # unescape character
1615 0         0 for (my $i=0; $i <= $#char; $i++) {
1616              
1617             # escape - to ...
1618 0 0 0     0 if ($char[$i] eq '-') {
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
1619 0 0 0     0 if ((0 < $i) and ($i < $#char)) {
1620 0         0 $char[$i] = '...';
1621             }
1622             }
1623              
1624             # octal escape sequence
1625             elsif ($char[$i] =~ /\A \\o \{ ([0-7]+) \} \z/oxms) {
1626 0         0 $char[$i] = octchr($1);
1627             }
1628              
1629             # hexadecimal escape sequence
1630             elsif ($char[$i] =~ /\A \\x \{ ([0-9A-Fa-f]+) \} \z/oxms) {
1631 0         0 $char[$i] = hexchr($1);
1632             }
1633              
1634             # \N{CHARNAME} --> N\{CHARNAME}
1635             elsif ($char[$i] =~ /\A \\ (N) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
1636 0         0 $char[$i] = $1 . '\\' . $2;
1637             }
1638              
1639             # \p{PROPERTY} --> p\{PROPERTY}
1640             elsif ($char[$i] =~ /\A \\ (p) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
1641 0         0 $char[$i] = $1 . '\\' . $2;
1642             }
1643              
1644             # \P{PROPERTY} --> P\{PROPERTY}
1645             elsif ($char[$i] =~ /\A \\ (P) ( \{ ([^0-9\}][^\}]*) \} ) \z/oxms) {
1646 0         0 $char[$i] = $1 . '\\' . $2;
1647             }
1648              
1649             # \p, \P, \X --> p, P, X
1650             elsif ($char[$i] =~ /\A \\ ( [pPX] ) \z/oxms) {
1651 0         0 $char[$i] = $1;
1652             }
1653              
1654             elsif ($char[$i] =~ /\A \\ ([0-7]{2,3}) \z/oxms) {
1655 0         0 $char[$i] = CORE::chr oct $1;
1656             }
1657             elsif ($char[$i] =~ /\A \\x ([0-9A-Fa-f]{1,2}) \z/oxms) {
1658 0         0 $char[$i] = CORE::chr hex $1;
1659             }
1660             elsif ($char[$i] =~ /\A \\c ([\x40-\x5F]) \z/oxms) {
1661 0         0 $char[$i] = CORE::chr(CORE::ord($1) & 0x1F);
1662             }
1663             elsif ($char[$i] =~ /\A (\\ [0nrtfbaedswDSWHVhvR]) \z/oxms) {
1664 0         0 $char[$i] = {
1665             '\0' => "\0",
1666             '\n' => "\n",
1667             '\r' => "\r",
1668             '\t' => "\t",
1669             '\f' => "\f",
1670             '\b' => "\x08", # \b means backspace in character class
1671             '\a' => "\a",
1672             '\e' => "\e",
1673             '\d' => '[0-9]',
1674              
1675             # Vertical tabs are now whitespace
1676             # \s in a regex now matches a vertical tab in all circumstances.
1677             # http://search.cpan.org/dist/perl-5.18.0/pod/perldelta.pod#Vertical_tabs_are_now_whitespace
1678             # \t \n \v \f \r space
1679             # '\s' => '[\x09\x0A \x0C\x0D\x20]',
1680             # '\s' => '[\x09\x0A\x0B\x0C\x0D\x20]',
1681             '\s' => '\s',
1682              
1683             '\w' => '[0-9A-Z_a-z]',
1684             '\D' => '${Char::Elatin10::eD}',
1685             '\S' => '${Char::Elatin10::eS}',
1686             '\W' => '${Char::Elatin10::eW}',
1687              
1688             '\H' => '${Char::Elatin10::eH}',
1689             '\V' => '${Char::Elatin10::eV}',
1690             '\h' => '[\x09\x20]',
1691             '\v' => '[\x0A\x0B\x0C\x0D]',
1692             '\R' => '${Char::Elatin10::eR}',
1693              
1694             }->{$1};
1695             }
1696              
1697             # POSIX-style character classes
1698             elsif ($ignorecase and ($char[$i] =~ /\A ( \[\: \^? (?:lower|upper) :\] ) \z/oxms)) {
1699 0         0 $char[$i] = {
1700              
1701             '[:lower:]' => '[\x41-\x5A\x61-\x7A]',
1702             '[:upper:]' => '[\x41-\x5A\x61-\x7A]',
1703             '[:^lower:]' => '${Char::Elatin10::not_lower_i}',
1704             '[:^upper:]' => '${Char::Elatin10::not_upper_i}',
1705              
1706             }->{$1};
1707             }
1708             elsif ($char[$i] =~ /\A ( \[\: \^? (?:alnum|alpha|ascii|blank|cntrl|digit|graph|lower|print|punct|space|upper|word|xdigit) :\] ) \z/oxms) {
1709 0         0 $char[$i] = {
1710              
1711             '[:alnum:]' => '[\x30-\x39\x41-\x5A\x61-\x7A]',
1712             '[:alpha:]' => '[\x41-\x5A\x61-\x7A]',
1713             '[:ascii:]' => '[\x00-\x7F]',
1714             '[:blank:]' => '[\x09\x20]',
1715             '[:cntrl:]' => '[\x00-\x1F\x7F]',
1716             '[:digit:]' => '[\x30-\x39]',
1717             '[:graph:]' => '[\x21-\x7F]',
1718             '[:lower:]' => '[\x61-\x7A]',
1719             '[:print:]' => '[\x20-\x7F]',
1720             '[:punct:]' => '[\x21-\x2F\x3A-\x3F\x40\x5B-\x5F\x60\x7B-\x7E]',
1721              
1722             # P.174 POSIX-Style Character Classes
1723             # in Chapter 5: Pattern Matching
1724             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
1725              
1726             # P.311 11.2.4 Character Classes and other Special Escapes
1727             # in Chapter 11: perlre: Perl regular expressions
1728             # of ISBN-13: 978-1-906966-02-7 The Perl Language Reference Manual (for Perl version 5.12.1)
1729              
1730             # P.210 POSIX-Style Character Classes
1731             # in Chapter 5: Pattern Matching
1732             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
1733              
1734             '[:space:]' => '[\s\x0B]', # "\s" plus vertical tab ("\cK")
1735              
1736             '[:upper:]' => '[\x41-\x5A]',
1737             '[:word:]' => '[\x30-\x39\x41-\x5A\x5F\x61-\x7A]',
1738             '[:xdigit:]' => '[\x30-\x39\x41-\x46\x61-\x66]',
1739             '[:^alnum:]' => '${Char::Elatin10::not_alnum}',
1740             '[:^alpha:]' => '${Char::Elatin10::not_alpha}',
1741             '[:^ascii:]' => '${Char::Elatin10::not_ascii}',
1742             '[:^blank:]' => '${Char::Elatin10::not_blank}',
1743             '[:^cntrl:]' => '${Char::Elatin10::not_cntrl}',
1744             '[:^digit:]' => '${Char::Elatin10::not_digit}',
1745             '[:^graph:]' => '${Char::Elatin10::not_graph}',
1746             '[:^lower:]' => '${Char::Elatin10::not_lower}',
1747             '[:^print:]' => '${Char::Elatin10::not_print}',
1748             '[:^punct:]' => '${Char::Elatin10::not_punct}',
1749             '[:^space:]' => '${Char::Elatin10::not_space}',
1750             '[:^upper:]' => '${Char::Elatin10::not_upper}',
1751             '[:^word:]' => '${Char::Elatin10::not_word}',
1752             '[:^xdigit:]' => '${Char::Elatin10::not_xdigit}',
1753              
1754             }->{$1};
1755             }
1756             elsif ($char[$i] =~ /\A \\ ($q_char) \z/oxms) {
1757 0         0 $char[$i] = $1;
1758             }
1759             }
1760              
1761             # open character list
1762 0         0 my @singleoctet = ();
1763 0         0 my @multipleoctet = ();
1764 0         0 for (my $i=0; $i <= $#char; ) {
1765              
1766             # escaped -
1767 0 0 0     0 if (defined($char[$i+1]) and ($char[$i+1] eq '...')) {
    0          
    0          
    0          
    0          
    0          
1768 0         0 $i += 1;
1769 0         0 next;
1770             }
1771              
1772             # make range regexp
1773             elsif ($char[$i] eq '...') {
1774              
1775             # range error
1776 0 0       0 if (CORE::length($char[$i-1]) > CORE::length($char[$i+1])) {
    0          
1777 0         0 croak 'Invalid [] range in regexp (length(A) > length(B)) ' . '\x' . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]);
1778             }
1779             elsif (CORE::length($char[$i-1]) == CORE::length($char[$i+1])) {
1780 0 0       0 if ($char[$i-1] gt $char[$i+1]) {
1781 0         0 croak 'Invalid [] range in regexp (CORE::ord(A) > CORE::ord(B)) ' . '\x' . unpack('H*',$char[$i-1]) . '-\x' . unpack('H*',$char[$i+1]);
1782             }
1783             }
1784              
1785             # make range regexp per length
1786 0         0 for my $length (CORE::length($char[$i-1]) .. CORE::length($char[$i+1])) {
1787 0         0 my @regexp = ();
1788              
1789             # is first and last
1790 0 0 0     0 if (($length == CORE::length($char[$i-1])) and ($length == CORE::length($char[$i+1]))) {
    0 0        
    0          
    0          
1791 0         0 push @regexp, _range_regexp($length, $char[$i-1], $char[$i+1]);
1792             }
1793              
1794             # is first
1795             elsif ($length == CORE::length($char[$i-1])) {
1796 0         0 push @regexp, _range_regexp($length, $char[$i-1], "\xFF" x $length);
1797             }
1798              
1799             # is inside in first and last
1800             elsif ((CORE::length($char[$i-1]) < $length) and ($length < CORE::length($char[$i+1]))) {
1801 0         0 push @regexp, _range_regexp($length, "\x00" x $length, "\xFF" x $length);
1802             }
1803              
1804             # is last
1805             elsif ($length == CORE::length($char[$i+1])) {
1806 0         0 push @regexp, _range_regexp($length, "\x00" x $length, $char[$i+1]);
1807             }
1808              
1809             else {
1810 0         0 die __FILE__, ": subroutine make_regexp panic.";
1811             }
1812              
1813 0 0       0 if ($length == 1) {
1814 0         0 push @singleoctet, @regexp;
1815             }
1816             else {
1817 0         0 push @multipleoctet, @regexp;
1818             }
1819             }
1820              
1821 0         0 $i += 2;
1822             }
1823              
1824             # with /i modifier
1825             elsif ($char[$i] =~ /\A [\x00-\xFF] \z/oxms) {
1826 0 0       0 if ($modifier =~ /i/oxms) {
1827 0         0 my $uc = Char::Elatin10::uc($char[$i]);
1828 0         0 my $fc = Char::Elatin10::fc($char[$i]);
1829 0 0       0 if ($uc ne $fc) {
1830 0 0       0 if (CORE::length($fc) == 1) {
1831 0         0 push @singleoctet, $uc, $fc;
1832             }
1833             else {
1834 0         0 push @singleoctet, $uc;
1835 0         0 push @multipleoctet, $fc;
1836             }
1837             }
1838             else {
1839 0         0 push @singleoctet, $char[$i];
1840             }
1841             }
1842             else {
1843 0         0 push @singleoctet, $char[$i];
1844             }
1845 0         0 $i += 1;
1846             }
1847              
1848             # single character of single octet code
1849             elsif ($char[$i] =~ /\A (?: \\h ) \z/oxms) {
1850 0         0 push @singleoctet, "\t", "\x20";
1851 0         0 $i += 1;
1852             }
1853             elsif ($char[$i] =~ /\A (?: \\v ) \z/oxms) {
1854 0         0 push @singleoctet, "\x0A", "\x0B", "\x0C", "\x0D";
1855 0         0 $i += 1;
1856             }
1857             elsif ($char[$i] =~ /\A (?: \\d | \\s | \\w ) \z/oxms) {
1858 0         0 push @singleoctet, $char[$i];
1859 0         0 $i += 1;
1860             }
1861              
1862             # single character of multiple-octet code
1863             else {
1864 0         0 push @multipleoctet, $char[$i];
1865 0         0 $i += 1;
1866             }
1867             }
1868              
1869             # quote metachar
1870 0         0 for (@singleoctet) {
1871 0 0       0 if ($_ eq '...') {
    0          
    0          
    0          
    0          
1872 0         0 $_ = '-';
1873             }
1874             elsif (/\A \n \z/oxms) {
1875 0         0 $_ = '\n';
1876             }
1877             elsif (/\A \r \z/oxms) {
1878 0         0 $_ = '\r';
1879             }
1880             elsif (/\A ([\x00-\x20\x7F-\xFF]) \z/oxms) {
1881 0         0 $_ = sprintf('\x%02X', CORE::ord $1);
1882             }
1883             elsif (/\A [\x00-\xFF] \z/oxms) {
1884 0         0 $_ = quotemeta $_;
1885             }
1886             }
1887              
1888             # return character list
1889 0         0 return \@singleoctet, \@multipleoctet;
1890             }
1891              
1892             #
1893             # Latin-10 octal escape sequence
1894             #
1895             sub octchr {
1896 0     0 0 0 my($octdigit) = @_;
1897              
1898 0         0 my @binary = ();
1899 0         0 for my $octal (split(//,$octdigit)) {
1900 0         0 push @binary, {
1901             '0' => '000',
1902             '1' => '001',
1903             '2' => '010',
1904             '3' => '011',
1905             '4' => '100',
1906             '5' => '101',
1907             '6' => '110',
1908             '7' => '111',
1909             }->{$octal};
1910             }
1911 0         0 my $binary = join '', @binary;
1912              
1913 0         0 my $octchr = {
1914             # 1234567
1915             1 => pack('B*', "0000000$binary"),
1916             2 => pack('B*', "000000$binary"),
1917             3 => pack('B*', "00000$binary"),
1918             4 => pack('B*', "0000$binary"),
1919             5 => pack('B*', "000$binary"),
1920             6 => pack('B*', "00$binary"),
1921             7 => pack('B*', "0$binary"),
1922             0 => pack('B*', "$binary"),
1923              
1924             }->{CORE::length($binary) % 8};
1925              
1926 0         0 return $octchr;
1927             }
1928              
1929             #
1930             # Latin-10 hexadecimal escape sequence
1931             #
1932             sub hexchr {
1933 0     0 0 0 my($hexdigit) = @_;
1934              
1935 0         0 my $hexchr = {
1936             1 => pack('H*', "0$hexdigit"),
1937             0 => pack('H*', "$hexdigit"),
1938              
1939             }->{CORE::length($_[0]) % 2};
1940              
1941 0         0 return $hexchr;
1942             }
1943              
1944             #
1945             # Latin-10 open character list for qr
1946             #
1947             sub charlist_qr {
1948              
1949 0     0 0 0 my $modifier = pop @_;
1950 0         0 my @char = @_;
1951              
1952 0         0 my($singleoctet, $multipleoctet) = _charlist(@char, $modifier);
1953 0         0 my @singleoctet = @$singleoctet;
1954 0         0 my @multipleoctet = @$multipleoctet;
1955              
1956             # return character list
1957 0 0       0 if (scalar(@singleoctet) >= 1) {
1958              
1959             # with /i modifier
1960 0 0       0 if ($modifier =~ m/i/oxms) {
1961 0         0 my %singleoctet_ignorecase = ();
1962 0         0 for (@singleoctet) {
1963 0   0     0 while (s/ \A \\x(..) - \\x(..) //oxms or s/ \A \\x((..)) //oxms) {
1964 0         0 for my $ord (hex($1) .. hex($2)) {
1965 0         0 my $char = CORE::chr($ord);
1966 0         0 my $uc = Char::Elatin10::uc($char);
1967 0         0 my $fc = Char::Elatin10::fc($char);
1968 0 0       0 if ($uc eq $fc) {
1969 0         0 $singleoctet_ignorecase{unpack 'C*', $char} = 1;
1970             }
1971             else {
1972 0 0       0 if (CORE::length($fc) == 1) {
1973 0         0 $singleoctet_ignorecase{unpack 'C*', $uc} = 1;
1974 0         0 $singleoctet_ignorecase{unpack 'C*', $fc} = 1;
1975             }
1976             else {
1977 0         0 $singleoctet_ignorecase{unpack 'C*', $uc} = 1;
1978 0         0 push @multipleoctet, join '', map {sprintf('\x%02X',$_)} unpack 'C*', $fc;
  0         0  
1979             }
1980             }
1981             }
1982             }
1983 0 0       0 if ($_ ne '') {
1984 0         0 $singleoctet_ignorecase{unpack 'C*', $_} = 1;
1985             }
1986             }
1987 0         0 my $i = 0;
1988 0         0 my @singleoctet_ignorecase = ();
1989 0         0 for my $ord (0 .. 255) {
1990 0 0       0 if (exists $singleoctet_ignorecase{$ord}) {
1991 0         0 push @{$singleoctet_ignorecase[$i]}, $ord;
  0         0  
1992             }
1993             else {
1994 0         0 $i++;
1995             }
1996             }
1997 0         0 @singleoctet = ();
1998 0         0 for my $range (@singleoctet_ignorecase) {
1999 0 0       0 if (ref $range) {
2000 0 0       0 if (scalar(@{$range}) == 1) {
  0 0       0  
  0         0  
2001 0         0 push @singleoctet, sprintf('\x%02X', @{$range}[0]);
  0         0  
2002             }
2003             elsif (scalar(@{$range}) == 2) {
2004 0         0 push @singleoctet, sprintf('\x%02X\x%02X', @{$range}[0], @{$range}[-1]);
  0         0  
  0         0  
2005             }
2006             else {
2007 0         0 push @singleoctet, sprintf('\x%02X-\x%02X', @{$range}[0], @{$range}[-1]);
  0         0  
  0         0  
2008             }
2009             }
2010             }
2011             }
2012              
2013 0         0 my $not_anchor = '';
2014              
2015 0         0 push @multipleoctet, join('', $not_anchor, '[', @singleoctet, ']' );
2016             }
2017 0 0       0 if (scalar(@multipleoctet) >= 2) {
2018 0         0 return '(?:' . join('|', @multipleoctet) . ')';
2019             }
2020             else {
2021 0         0 return $multipleoctet[0];
2022             }
2023             }
2024              
2025             #
2026             # Latin-10 open character list for not qr
2027             #
2028             sub charlist_not_qr {
2029              
2030 0     0 0 0 my $modifier = pop @_;
2031 0         0 my @char = @_;
2032              
2033 0         0 my($singleoctet, $multipleoctet) = _charlist(@char, $modifier);
2034 0         0 my @singleoctet = @$singleoctet;
2035 0         0 my @multipleoctet = @$multipleoctet;
2036              
2037             # with /i modifier
2038 0 0       0 if ($modifier =~ m/i/oxms) {
2039 0         0 my %singleoctet_ignorecase = ();
2040 0         0 for (@singleoctet) {
2041 0   0     0 while (s/ \A \\x(..) - \\x(..) //oxms or s/ \A \\x((..)) //oxms) {
2042 0         0 for my $ord (hex($1) .. hex($2)) {
2043 0         0 my $char = CORE::chr($ord);
2044 0         0 my $uc = Char::Elatin10::uc($char);
2045 0         0 my $fc = Char::Elatin10::fc($char);
2046 0 0       0 if ($uc eq $fc) {
2047 0         0 $singleoctet_ignorecase{unpack 'C*', $char} = 1;
2048             }
2049             else {
2050 0 0       0 if (CORE::length($fc) == 1) {
2051 0         0 $singleoctet_ignorecase{unpack 'C*', $uc} = 1;
2052 0         0 $singleoctet_ignorecase{unpack 'C*', $fc} = 1;
2053             }
2054             else {
2055 0         0 $singleoctet_ignorecase{unpack 'C*', $uc} = 1;
2056 0         0 push @multipleoctet, join '', map {sprintf('\x%02X',$_)} unpack 'C*', $fc;
  0         0  
2057             }
2058             }
2059             }
2060             }
2061 0 0       0 if ($_ ne '') {
2062 0         0 $singleoctet_ignorecase{unpack 'C*', $_} = 1;
2063             }
2064             }
2065 0         0 my $i = 0;
2066 0         0 my @singleoctet_ignorecase = ();
2067 0         0 for my $ord (0 .. 255) {
2068 0 0       0 if (exists $singleoctet_ignorecase{$ord}) {
2069 0         0 push @{$singleoctet_ignorecase[$i]}, $ord;
  0         0  
2070             }
2071             else {
2072 0         0 $i++;
2073             }
2074             }
2075 0         0 @singleoctet = ();
2076 0         0 for my $range (@singleoctet_ignorecase) {
2077 0 0       0 if (ref $range) {
2078 0 0       0 if (scalar(@{$range}) == 1) {
  0 0       0  
  0         0  
2079 0         0 push @singleoctet, sprintf('\x%02X', @{$range}[0]);
  0         0  
2080             }
2081             elsif (scalar(@{$range}) == 2) {
2082 0         0 push @singleoctet, sprintf('\x%02X\x%02X', @{$range}[0], @{$range}[-1]);
  0         0  
  0         0  
2083             }
2084             else {
2085 0         0 push @singleoctet, sprintf('\x%02X-\x%02X', @{$range}[0], @{$range}[-1]);
  0         0  
  0         0  
2086             }
2087             }
2088             }
2089             }
2090              
2091             # return character list
2092 0 0       0 if (scalar(@multipleoctet) >= 1) {
2093 0 0       0 if (scalar(@singleoctet) >= 1) {
2094              
2095             # any character other than multiple-octet and single octet character class
2096 0         0 return '(?!' . join('|', @multipleoctet) . ')(?:[^' . join('', @singleoctet) . '])';
2097             }
2098             else {
2099              
2100             # any character other than multiple-octet character class
2101 0         0 return '(?!' . join('|', @multipleoctet) . ")(?:$your_char)";
2102             }
2103             }
2104             else {
2105 0 0       0 if (scalar(@singleoctet) >= 1) {
2106              
2107             # any character other than single octet character class
2108 0         0 return '(?:[^' . join('', @singleoctet) . '])';
2109             }
2110             else {
2111              
2112             # any character
2113 0         0 return "(?:$your_char)";
2114             }
2115             }
2116             }
2117              
2118             #
2119             # open file in read mode
2120             #
2121             sub _open_r {
2122 177     177   602 my(undef,$file) = @_;
2123 177         897 $file =~ s#\A (\s) #./$1#oxms;
2124 177   33     17208 return eval(q{open($_[0],'<',$_[1])}) ||
2125             open($_[0],"< $file\0");
2126             }
2127              
2128             #
2129             # open file in write mode
2130             #
2131             sub _open_w {
2132 0     0   0 my(undef,$file) = @_;
2133 0         0 $file =~ s#\A (\s) #./$1#oxms;
2134 0   0     0 return eval(q{open($_[0],'>',$_[1])}) ||
2135             open($_[0],"> $file\0");
2136             }
2137              
2138             #
2139             # open file in append mode
2140             #
2141             sub _open_a {
2142 0     0   0 my(undef,$file) = @_;
2143 0         0 $file =~ s#\A (\s) #./$1#oxms;
2144 0   0     0 return eval(q{open($_[0],'>>',$_[1])}) ||
2145             open($_[0],">> $file\0");
2146             }
2147              
2148             #
2149             # safe system
2150             #
2151             sub _systemx {
2152              
2153             # P.707 29.2.33. exec
2154             # in Chapter 29: Functions
2155             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
2156             #
2157             # Be aware that in older releases of Perl, exec (and system) did not flush
2158             # your output buffer, so you needed to enable command buffering by setting $|
2159             # on one or more filehandles to avoid lost output in the case of exec, or
2160             # misordererd output in the case of system. This situation was largely remedied
2161             # in the 5.6 release of Perl. (So, 5.005 release not yet.)
2162              
2163             # P.855 exec
2164             # in Chapter 27: Functions
2165             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
2166             #
2167             # In very old release of Perl (before v5.6), exec (and system) did not flush
2168             # your output buffer, so you needed to enable command buffering by setting $|
2169             # on one or more filehandles to avoid lost output with exec or misordered
2170             # output with system.
2171              
2172 177     177   730 $| = 1;
2173              
2174             # P.565 23.1.2. Cleaning Up Your Environment
2175             # in Chapter 23: Security
2176             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
2177              
2178             # P.656 Cleaning Up Your Environment
2179             # in Chapter 20: Security
2180             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
2181              
2182             # local $ENV{'PATH'} = '.';
2183 177         1889 local @ENV{qw(IFS CDPATH ENV BASH_ENV)}; # Make %ENV safer
2184              
2185             # P.707 29.2.33. exec
2186             # in Chapter 29: Functions
2187             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
2188             #
2189             # As we mentioned earlier, exec treats a discrete list of arguments as an
2190             # indication that it should bypass shell processing. However, there is one
2191             # place where you might still get tripped up. The exec call (and system, too)
2192             # will not distinguish between a single scalar argument and an array containing
2193             # only one element.
2194             #
2195             # @args = ("echo surprise"); # just one element in list
2196             # exec @args # still subject to shell escapes
2197             # or die "exec: $!"; # because @args == 1
2198             #
2199             # To avoid this, you can use the PATHNAME syntax, explicitly duplicating the
2200             # first argument as the pathname, which forces the rest of the arguments to be
2201             # interpreted as a list, even if there is only one of them:
2202             #
2203             # exec { $args[0] } @args # safe even with one-argument list
2204             # or die "can't exec @args: $!";
2205              
2206             # P.855 exec
2207             # in Chapter 27: Functions
2208             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
2209             #
2210             # As we mentioned earlier, exec treats a discrete list of arguments as a
2211             # directive to bypass shell processing. However, there is one place where
2212             # you might still get tripped up. The exec call (and system, too) cannot
2213             # distinguish between a single scalar argument and an array containing
2214             # only one element.
2215             #
2216             # @args = ("echo surprise"); # just one element in list
2217             # exec @args # still subject to shell escapes
2218             # || die "exec: $!"; # because @args == 1
2219             #
2220             # To avoid this, use the PATHNAME syntax, explicitly duplicating the first
2221             # argument as the pathname, which forces the rest of the arguments to be
2222             # interpreted as a list, even if there is only one of them:
2223             #
2224             # exec { $args[0] } @args # safe even with one-argument list
2225             # || die "can't exec @args: $!";
2226              
2227 177         432 return CORE::system { $_[0] } @_; # safe even with one-argument list
  177         11933601  
2228             }
2229              
2230             #
2231             # Latin-10 order to character (with parameter)
2232             #
2233             sub Char::Elatin10::chr(;$) {
2234              
2235 0 0   0 0   my $c = @_ ? $_[0] : $_;
2236              
2237 0 0         if ($c == 0x00) {
2238 0           return "\x00";
2239             }
2240             else {
2241 0           my @chr = ();
2242 0           while ($c > 0) {
2243 0           unshift @chr, ($c % 0x100);
2244 0           $c = int($c / 0x100);
2245             }
2246 0           return pack 'C*', @chr;
2247             }
2248             }
2249              
2250             #
2251             # Latin-10 order to character (without parameter)
2252             #
2253             sub Char::Elatin10::chr_() {
2254              
2255 0     0 0   my $c = $_;
2256              
2257 0 0         if ($c == 0x00) {
2258 0           return "\x00";
2259             }
2260             else {
2261 0           my @chr = ();
2262 0           while ($c > 0) {
2263 0           unshift @chr, ($c % 0x100);
2264 0           $c = int($c / 0x100);
2265             }
2266 0           return pack 'C*', @chr;
2267             }
2268             }
2269              
2270             #
2271             # Latin-10 path globbing (with parameter)
2272             #
2273             sub Char::Elatin10::glob($) {
2274              
2275 0 0   0 0   if (wantarray) {
2276 0           my @glob = _DOS_like_glob(@_);
2277 0           for my $glob (@glob) {
2278 0           $glob =~ s{ \A (?:\./)+ }{}oxms;
2279             }
2280 0           return @glob;
2281             }
2282             else {
2283 0           my $glob = _DOS_like_glob(@_);
2284 0           $glob =~ s{ \A (?:\./)+ }{}oxms;
2285 0           return $glob;
2286             }
2287             }
2288              
2289             #
2290             # Latin-10 path globbing (without parameter)
2291             #
2292             sub Char::Elatin10::glob_() {
2293              
2294 0 0   0 0   if (wantarray) {
2295 0           my @glob = _DOS_like_glob();
2296 0           for my $glob (@glob) {
2297 0           $glob =~ s{ \A (?:\./)+ }{}oxms;
2298             }
2299 0           return @glob;
2300             }
2301             else {
2302 0           my $glob = _DOS_like_glob();
2303 0           $glob =~ s{ \A (?:\./)+ }{}oxms;
2304 0           return $glob;
2305             }
2306             }
2307              
2308             #
2309             # Latin-10 path globbing via File::DosGlob 1.10
2310             #
2311             # Often I confuse "_dosglob" and "_doglob".
2312             # So, I renamed "_dosglob" to "_DOS_like_glob".
2313             #
2314             my %iter;
2315             my %entries;
2316             sub _DOS_like_glob {
2317              
2318             # context (keyed by second cxix argument provided by core)
2319 0     0     my($expr,$cxix) = @_;
2320              
2321             # glob without args defaults to $_
2322 0 0         $expr = $_ if not defined $expr;
2323              
2324             # represents the current user's home directory
2325             #
2326             # 7.3. Expanding Tildes in Filenames
2327             # in Chapter 7. File Access
2328             # of ISBN 0-596-00313-7 Perl Cookbook, 2nd Edition.
2329             #
2330             # and File::HomeDir, File::HomeDir::Windows module
2331              
2332             # DOS-like system
2333 0 0         if ($^O =~ /\A (?: MSWin32 | NetWare | symbian | dos ) \z/oxms) {
2334 0           $expr =~ s{ \A ~ (?= [^/\\] ) }
2335 0           { my_home_MSWin32() }oxmse;
2336             }
2337              
2338             # UNIX-like system
2339             else {
2340 0           $expr =~ s{ \A ~ ( (?:[^/])* ) }
2341 0 0 0       { $1 ? (eval(q{(getpwnam($1))[7]})||my_home()) : my_home() }oxmse;
2342             }
2343              
2344             # assume global context if not provided one
2345 0 0         $cxix = '_G_' if not defined $cxix;
2346 0 0         $iter{$cxix} = 0 if not exists $iter{$cxix};
2347              
2348             # if we're just beginning, do it all first
2349 0 0         if ($iter{$cxix} == 0) {
2350 0           $entries{$cxix} = [ _do_glob(1, _parse_line($expr)) ];
2351             }
2352              
2353             # chuck it all out, quick or slow
2354 0 0         if (wantarray) {
2355 0           delete $iter{$cxix};
2356 0           return @{delete $entries{$cxix}};
  0            
2357             }
2358             else {
2359 0 0         if ($iter{$cxix} = scalar @{$entries{$cxix}}) {
  0            
2360 0           return shift @{$entries{$cxix}};
  0            
2361             }
2362             else {
2363             # return undef for EOL
2364 0           delete $iter{$cxix};
2365 0           delete $entries{$cxix};
2366 0           return undef;
2367             }
2368             }
2369             }
2370              
2371             #
2372             # Latin-10 path globbing subroutine
2373             #
2374             sub _do_glob {
2375              
2376 0     0     my($cond,@expr) = @_;
2377 0           my @glob = ();
2378 0           my $fix_drive_relative_paths = 0;
2379              
2380             OUTER:
2381 0           for my $expr (@expr) {
2382 0 0         next OUTER if not defined $expr;
2383 0 0         next OUTER if $expr eq '';
2384              
2385 0           my @matched = ();
2386 0           my @globdir = ();
2387 0           my $head = '.';
2388 0           my $pathsep = '/';
2389 0           my $tail;
2390              
2391             # if argument is within quotes strip em and do no globbing
2392 0 0         if ($expr =~ /\A " ((?:$q_char)*) " \z/oxms) {
2393 0           $expr = $1;
2394 0 0         if ($cond eq 'd') {
2395 0 0         if (-d $expr) {
2396 0           push @glob, $expr;
2397             }
2398             }
2399             else {
2400 0 0         if (-e $expr) {
2401 0           push @glob, $expr;
2402             }
2403             }
2404 0           next OUTER;
2405             }
2406              
2407             # wildcards with a drive prefix such as h:*.pm must be changed
2408             # to h:./*.pm to expand correctly
2409 0 0         if ($^O =~ /\A (?: MSWin32 | NetWare | symbian | dos ) \z/oxms) {
2410 0 0         if ($expr =~ s# \A ((?:[A-Za-z]:)?) ([^/\\]) #$1./$2#oxms) {
2411 0           $fix_drive_relative_paths = 1;
2412             }
2413             }
2414              
2415 0 0         if (($head, $tail) = _parse_path($expr,$pathsep)) {
2416 0 0         if ($tail eq '') {
2417 0           push @glob, $expr;
2418 0           next OUTER;
2419             }
2420 0 0         if ($head =~ / \A (?:$q_char)*? [*?] /oxms) {
2421 0 0         if (@globdir = _do_glob('d', $head)) {
2422 0           push @glob, _do_glob($cond, map {"$_$pathsep$tail"} @globdir);
  0            
2423 0           next OUTER;
2424             }
2425             }
2426 0 0 0       if ($head eq '' or $head =~ /\A [A-Za-z]: \z/oxms) {
2427 0           $head .= $pathsep;
2428             }
2429 0           $expr = $tail;
2430             }
2431              
2432             # If file component has no wildcards, we can avoid opendir
2433 0 0         if ($expr !~ / \A (?:$q_char)*? [*?] /oxms) {
2434 0 0         if ($head eq '.') {
2435 0           $head = '';
2436             }
2437 0 0 0       if ($head ne '' and ($head =~ / \G ($q_char) /oxmsg)[-1] ne $pathsep) {
2438 0           $head .= $pathsep;
2439             }
2440 0           $head .= $expr;
2441 0 0         if ($cond eq 'd') {
2442 0 0         if (-d $head) {
2443 0           push @glob, $head;
2444             }
2445             }
2446             else {
2447 0 0         if (-e $head) {
2448 0           push @glob, $head;
2449             }
2450             }
2451 0           next OUTER;
2452             }
2453 0 0         opendir(*DIR, $head) or next OUTER;
2454 0           my @leaf = readdir DIR;
2455 0           closedir DIR;
2456              
2457 0 0         if ($head eq '.') {
2458 0           $head = '';
2459             }
2460 0 0 0       if ($head ne '' and ($head =~ / \G ($q_char) /oxmsg)[-1] ne $pathsep) {
2461 0           $head .= $pathsep;
2462             }
2463              
2464 0           my $pattern = '';
2465 0           while ($expr =~ / \G ($q_char) /oxgc) {
2466 0           my $char = $1;
2467              
2468             # 6.9. Matching Shell Globs as Regular Expressions
2469             # in Chapter 6. Pattern Matching
2470             # of ISBN 0-596-00313-7 Perl Cookbook, 2nd Edition.
2471             # (and so on)
2472              
2473 0 0         if ($char eq '*') {
    0          
    0          
2474 0           $pattern .= "(?:$your_char)*",
2475             }
2476             elsif ($char eq '?') {
2477 0           $pattern .= "(?:$your_char)?", # DOS style
2478             # $pattern .= "(?:$your_char)", # UNIX style
2479             }
2480             elsif ((my $fc = Char::Elatin10::fc($char)) ne $char) {
2481 0           $pattern .= $fc;
2482             }
2483             else {
2484 0           $pattern .= quotemeta $char;
2485             }
2486             }
2487 0     0     my $matchsub = sub { Char::Elatin10::fc($_[0]) =~ /\A $pattern \z/xms };
  0            
2488              
2489             # if ($@) {
2490             # print STDERR "$0: $@\n";
2491             # next OUTER;
2492             # }
2493              
2494             INNER:
2495 0           for my $leaf (@leaf) {
2496 0 0 0       if ($leaf eq '.' or $leaf eq '..') {
2497 0           next INNER;
2498             }
2499 0 0 0       if ($cond eq 'd' and not -d "$head$leaf") {
2500 0           next INNER;
2501             }
2502              
2503 0 0         if (&$matchsub($leaf)) {
2504 0           push @matched, "$head$leaf";
2505 0           next INNER;
2506             }
2507              
2508             # [DOS compatibility special case]
2509             # Failed, add a trailing dot and try again, but only...
2510              
2511 0 0 0       if (Char::Elatin10::index($leaf,'.') == -1 and # if name does not have a dot in it *and*
      0        
2512             CORE::length($leaf) <= 8 and # name is shorter than or equal to 8 chars *and*
2513             Char::Elatin10::index($pattern,'\\.') != -1 # pattern has a dot.
2514             ) {
2515 0 0         if (&$matchsub("$leaf.")) {
2516 0           push @matched, "$head$leaf";
2517 0           next INNER;
2518             }
2519             }
2520             }
2521 0 0         if (@matched) {
2522 0           push @glob, @matched;
2523             }
2524             }
2525 0 0         if ($fix_drive_relative_paths) {
2526 0           for my $glob (@glob) {
2527 0           $glob =~ s# \A ([A-Za-z]:) \./ #$1#oxms;
2528             }
2529             }
2530 0           return @glob;
2531             }
2532              
2533             #
2534             # Latin-10 parse line
2535             #
2536             sub _parse_line {
2537              
2538 0     0     my($line) = @_;
2539              
2540 0           $line .= ' ';
2541 0           my @piece = ();
2542 0           while ($line =~ /
2543             " ( (?: [^"] )* ) " \s+ |
2544             ( (?: [^"\s] )* ) \s+
2545             /oxmsg
2546             ) {
2547 0 0         push @piece, defined($1) ? $1 : $2;
2548             }
2549 0           return @piece;
2550             }
2551              
2552             #
2553             # Latin-10 parse path
2554             #
2555             sub _parse_path {
2556              
2557 0     0     my($path,$pathsep) = @_;
2558              
2559 0           $path .= '/';
2560 0           my @subpath = ();
2561 0           while ($path =~ /
2562             ((?: [^\/\\] )+?) [\/\\]
2563             /oxmsg
2564             ) {
2565 0           push @subpath, $1;
2566             }
2567              
2568 0           my $tail = pop @subpath;
2569 0           my $head = join $pathsep, @subpath;
2570 0           return $head, $tail;
2571             }
2572              
2573             #
2574             # via File::HomeDir::Windows 1.00
2575             #
2576             sub my_home_MSWin32 {
2577              
2578             # A lot of unix people and unix-derived tools rely on
2579             # the ability to overload HOME. We will support it too
2580             # so that they can replace raw HOME calls with File::HomeDir.
2581 0 0 0 0 0   if (exists $ENV{'HOME'} and $ENV{'HOME'}) {
    0 0        
    0 0        
      0        
      0        
2582 0           return $ENV{'HOME'};
2583             }
2584              
2585             # Do we have a user profile?
2586             elsif (exists $ENV{'USERPROFILE'} and $ENV{'USERPROFILE'}) {
2587 0           return $ENV{'USERPROFILE'};
2588             }
2589              
2590             # Some Windows use something like $ENV{'HOME'}
2591             elsif (exists $ENV{'HOMEDRIVE'} and exists $ENV{'HOMEPATH'} and $ENV{'HOMEDRIVE'} and $ENV{'HOMEPATH'}) {
2592 0           return join '', $ENV{'HOMEDRIVE'}, $ENV{'HOMEPATH'};
2593             }
2594              
2595 0           return undef;
2596             }
2597              
2598             #
2599             # via File::HomeDir::Unix 1.00
2600             #
2601             sub my_home {
2602 0     0 0   my $home;
2603              
2604 0 0 0       if (exists $ENV{'HOME'} and defined $ENV{'HOME'}) {
    0 0        
2605 0           $home = $ENV{'HOME'};
2606             }
2607              
2608             # This is from the original code, but I'm guessing
2609             # it means "login directory" and exists on some Unixes.
2610             elsif (exists $ENV{'LOGDIR'} and $ENV{'LOGDIR'}) {
2611 0           $home = $ENV{'LOGDIR'};
2612             }
2613              
2614             ### More-desperate methods
2615              
2616             # Light desperation on any (Unixish) platform
2617             else {
2618 0           $home = eval q{ (getpwuid($<))[7] };
2619             }
2620              
2621             # On Unix in general, a non-existant home means "no home"
2622             # For example, "nobody"-like users might use /nonexistant
2623 0 0 0       if (defined $home and ! -d($home)) {
2624 0           $home = undef;
2625             }
2626 0           return $home;
2627             }
2628              
2629             #
2630             # ${^PREMATCH}, $PREMATCH, $` the string preceding what was matched
2631             #
2632             sub Char::Elatin10::PREMATCH {
2633 0     0 0   return $`;
2634             }
2635              
2636             #
2637             # ${^MATCH}, $MATCH, $& the string that matched
2638             #
2639             sub Char::Elatin10::MATCH {
2640 0     0 0   return $&;
2641             }
2642              
2643             #
2644             # ${^POSTMATCH}, $POSTMATCH, $' the string following what was matched
2645             #
2646             sub Char::Elatin10::POSTMATCH {
2647 0     0 0   return $';
2648             }
2649              
2650             #
2651             # Latin-10 character to order (with parameter)
2652             #
2653             sub Char::Latin10::ord(;$) {
2654              
2655 0 0   0 1   local $_ = shift if @_;
2656              
2657 0 0         if (/\A ($q_char) /oxms) {
2658 0           my @ord = unpack 'C*', $1;
2659 0           my $ord = 0;
2660 0           while (my $o = shift @ord) {
2661 0           $ord = $ord * 0x100 + $o;
2662             }
2663 0           return $ord;
2664             }
2665             else {
2666 0           return CORE::ord $_;
2667             }
2668             }
2669              
2670             #
2671             # Latin-10 character to order (without parameter)
2672             #
2673             sub Char::Latin10::ord_() {
2674              
2675 0 0   0 0   if (/\A ($q_char) /oxms) {
2676 0           my @ord = unpack 'C*', $1;
2677 0           my $ord = 0;
2678 0           while (my $o = shift @ord) {
2679 0           $ord = $ord * 0x100 + $o;
2680             }
2681 0           return $ord;
2682             }
2683             else {
2684 0           return CORE::ord $_;
2685             }
2686             }
2687              
2688             #
2689             # Latin-10 reverse
2690             #
2691             sub Char::Latin10::reverse(@) {
2692              
2693 0 0   0 0   if (wantarray) {
2694 0           return CORE::reverse @_;
2695             }
2696             else {
2697              
2698             # One of us once cornered Larry in an elevator and asked him what
2699             # problem he was solving with this, but he looked as far off into
2700             # the distance as he could in an elevator and said, "It seemed like
2701             # a good idea at the time."
2702              
2703 0           return join '', CORE::reverse(join('',@_) =~ /\G ($q_char) /oxmsg);
2704             }
2705             }
2706              
2707             #
2708             # Latin-10 getc (with parameter, without parameter)
2709             #
2710             sub Char::Latin10::getc(;*@) {
2711              
2712 0     0 0   my($package) = caller;
2713 0 0         my $fh = @_ ? qualify_to_ref(shift,$package) : \*STDIN;
2714 0 0 0       croak 'Too many arguments for Char::Latin10::getc' if @_ and not wantarray;
2715              
2716 0           my @length = sort { $a <=> $b } keys %range_tr;
  0            
2717 0           my $getc = '';
2718 0           for my $length ($length[0] .. $length[-1]) {
2719 0           $getc .= CORE::getc($fh);
2720 0 0         if (exists $range_tr{CORE::length($getc)}) {
2721 0 0         if ($getc =~ /\A ${Char::Elatin10::dot_s} \z/oxms) {
2722 0 0         return wantarray ? ($getc,@_) : $getc;
2723             }
2724             }
2725             }
2726 0 0         return wantarray ? ($getc,@_) : $getc;
2727             }
2728              
2729             #
2730             # Latin-10 length by character
2731             #
2732             sub Char::Latin10::length(;$) {
2733              
2734 0 0   0 1   local $_ = shift if @_;
2735              
2736 0           local @_ = /\G ($q_char) /oxmsg;
2737 0           return scalar @_;
2738             }
2739              
2740             #
2741             # Latin-10 substr by character
2742             #
2743             BEGIN {
2744              
2745             # P.232 The lvalue Attribute
2746             # in Chapter 6: Subroutines
2747             # of ISBN 0-596-00027-8 Programming Perl Third Edition.
2748              
2749             # P.336 The lvalue Attribute
2750             # in Chapter 7: Subroutines
2751             # of ISBN 978-0-596-00492-7 Programming Perl 4th Edition.
2752              
2753             # P.144 8.4 Lvalue subroutines
2754             # in Chapter 8: perlsub: Perl subroutines
2755             # of ISBN-13: 978-1-906966-02-7 The Perl Language Reference Manual (for Perl version 5.12.1)
2756              
2757 177 50 0 177 1 314139 eval sprintf(<<'END', ($] >= 5.014000) ? ':lvalue' : '');
  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            
2758             # vv----------------*******
2759             sub Char::Latin10::substr($$;$$) %s {
2760              
2761             my @char = $_[0] =~ /\G ($q_char) /oxmsg;
2762              
2763             # If the substring is beyond either end of the string, substr() returns the undefined
2764             # value and produces a warning. When used as an lvalue, specifying a substring that
2765             # is entirely outside the string raises an exception.
2766             # http://perldoc.perl.org/functions/substr.html
2767              
2768             # A return with no argument returns the scalar value undef in scalar context,
2769             # an empty list () in list context, and (naturally) nothing at all in void
2770             # context.
2771              
2772             my $offset = $_[1];
2773             if (($offset > scalar(@char)) or ($offset < (-1 * scalar(@char)))) {
2774             return;
2775             }
2776              
2777             # substr($string,$offset,$length,$replacement)
2778             if (@_ == 4) {
2779             my(undef,undef,$length,$replacement) = @_;
2780             my $substr = join '', splice(@char, $offset, $length, $replacement);
2781             $_[0] = join '', @char;
2782              
2783             # return $substr; this doesn't work, don't say "return"
2784             $substr;
2785             }
2786              
2787             # substr($string,$offset,$length)
2788             elsif (@_ == 3) {
2789             my(undef,undef,$length) = @_;
2790             my $octet_offset = 0;
2791             my $octet_length = 0;
2792             if ($offset == 0) {
2793             $octet_offset = 0;
2794             }
2795             elsif ($offset > 0) {
2796             $octet_offset = CORE::length(join '', @char[0..$offset-1]);
2797             }
2798             else {
2799             $octet_offset = -1 * CORE::length(join '', @char[$#char+$offset+1..$#char]);
2800             }
2801             if ($length == 0) {
2802             $octet_length = 0;
2803             }
2804             elsif ($length > 0) {
2805             $octet_length = CORE::length(join '', @char[$offset..$offset+$length-1]);
2806             }
2807             else {
2808             $octet_length = -1 * CORE::length(join '', @char[$#char+$length+1..$#char]);
2809             }
2810             CORE::substr($_[0], $octet_offset, $octet_length);
2811             }
2812              
2813             # substr($string,$offset)
2814             else {
2815             my $octet_offset = 0;
2816             if ($offset == 0) {
2817             $octet_offset = 0;
2818             }
2819             elsif ($offset > 0) {
2820             $octet_offset = CORE::length(join '', @char[0..$offset-1]);
2821             }
2822             else {
2823             $octet_offset = -1 * CORE::length(join '', @char[$#char+$offset+1..$#char]);
2824             }
2825             CORE::substr($_[0], $octet_offset);
2826             }
2827             }
2828             END
2829             }
2830              
2831             #
2832             # Latin-10 index by character
2833             #
2834             sub Char::Latin10::index($$;$) {
2835              
2836 0     0 1   my $index;
2837 0 0         if (@_ == 3) {
2838 0           $index = Char::Elatin10::index($_[0], $_[1], CORE::length(Char::Latin10::substr($_[0], 0, $_[2])));
2839             }
2840             else {
2841 0           $index = Char::Elatin10::index($_[0], $_[1]);
2842             }
2843              
2844 0 0         if ($index == -1) {
2845 0           return -1;
2846             }
2847             else {
2848 0           return Char::Latin10::length(CORE::substr $_[0], 0, $index);
2849             }
2850             }
2851              
2852             #
2853             # Latin-10 rindex by character
2854             #
2855             sub Char::Latin10::rindex($$;$) {
2856              
2857 0     0 1   my $rindex;
2858 0 0         if (@_ == 3) {
2859 0           $rindex = Char::Elatin10::rindex($_[0], $_[1], CORE::length(Char::Latin10::substr($_[0], 0, $_[2])));
2860             }
2861             else {
2862 0           $rindex = Char::Elatin10::rindex($_[0], $_[1]);
2863             }
2864              
2865 0 0         if ($rindex == -1) {
2866 0           return -1;
2867             }
2868             else {
2869 0           return Char::Latin10::length(CORE::substr $_[0], 0, $rindex);
2870             }
2871             }
2872              
2873             #
2874             # instead of Carp::carp
2875             #
2876             sub carp {
2877 0     0 0   my($package,$filename,$line) = caller(1);
2878 0           print STDERR "@_ at $filename line $line.\n";
2879             }
2880              
2881             #
2882             # instead of Carp::croak
2883             #
2884             sub croak {
2885 0     0 0   my($package,$filename,$line) = caller(1);
2886 0           print STDERR "@_ at $filename line $line.\n";
2887 0           die "\n";
2888             }
2889              
2890             #
2891             # instead of Carp::cluck
2892             #
2893             sub cluck {
2894 0     0 0   my $i = 0;
2895 0           my @cluck = ();
2896 0           while (my($package,$filename,$line,$subroutine) = caller($i)) {
2897 0           push @cluck, "[$i] $filename($line) $package::$subroutine\n";
2898 0           $i++;
2899             }
2900 0           print STDERR CORE::reverse @cluck;
2901 0           print STDERR "\n";
2902 0           carp @_;
2903             }
2904              
2905             #
2906             # instead of Carp::confess
2907             #
2908             sub confess {
2909 0     0 0   my $i = 0;
2910 0           my @confess = ();
2911 0           while (my($package,$filename,$line,$subroutine) = caller($i)) {
2912 0           push @confess, "[$i] $filename($line) $package::$subroutine\n";
2913 0           $i++;
2914             }
2915 0           print STDERR CORE::reverse @confess;
2916 0           print STDERR "\n";
2917 0           croak @_;
2918             }
2919              
2920             1;
2921              
2922             __END__