line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
|
2
|
|
|
|
|
|
|
# -*-Fundamental-*- |
3
|
|
|
|
|
|
|
require 5; # Time-stamp: "2004-03-27 17:19:11 AST" |
4
|
|
|
|
|
|
|
package Sort::ArbBiLex; |
5
|
6
|
|
|
6
|
|
50348
|
use strict; |
|
6
|
|
|
|
|
14
|
|
|
6
|
|
|
|
|
531
|
|
6
|
5
|
|
|
5
|
|
29
|
use vars qw(@ISA $Debug $VERSION); |
|
5
|
|
|
|
|
9
|
|
|
5
|
|
|
|
|
402
|
|
7
|
|
|
|
|
|
|
$VERSION = "4.01"; |
8
|
|
|
|
|
|
|
$Debug = 0; |
9
|
5
|
|
|
5
|
|
32
|
use Carp; |
|
5
|
|
|
|
|
13
|
|
|
5
|
|
|
|
|
351
|
|
10
|
5
|
|
|
5
|
|
5318
|
use integer; # vroom vroom |
|
5
|
|
|
|
|
54
|
|
|
5
|
|
|
|
|
24
|
|
11
|
|
|
|
|
|
|
|
12
|
5
|
50
|
|
5
|
|
673
|
BEGIN { *UNICODE = eval('chr(256)') ? sub(){1} : sub(){0} } |
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
#POD at end |
15
|
|
|
|
|
|
|
########################################################################### |
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
sub import { |
18
|
7
|
|
|
7
|
|
1514
|
my $class_name = shift(@_); |
19
|
7
|
|
|
|
|
20
|
my $into = scalar caller; |
20
|
7
|
100
|
|
|
|
6621
|
return unless @_; |
21
|
4
|
50
|
|
|
|
78
|
croak "Argument list in 'use $class_name' must be list of pairs" if @_ % 2; |
22
|
4
|
|
|
|
|
9
|
my($sym, $spec); |
23
|
4
|
|
|
|
|
16
|
while(@_) { |
24
|
4
|
|
|
|
|
20
|
($sym, $spec) = splice(@_,0,2); |
25
|
4
|
50
|
|
|
|
13
|
defined $sym or croak "Can't use undef as the name of a sub to make"; |
26
|
4
|
50
|
|
|
|
15
|
length $sym or croak "Can't use \"\" as the name of a sub to make"; |
27
|
4
|
50
|
|
|
|
11
|
defined $spec or croak "Can't use undef as a sort-order spec"; |
28
|
4
|
50
|
|
|
|
12
|
length $sym or croak "Can't use \"\" as a sort-order spec"; |
29
|
4
|
50
|
33
|
|
|
45
|
$sym = $into . '::' . $sym unless $sym =~ m/::/ or $sym =~ m/'/; |
30
|
5
|
|
|
5
|
|
30
|
no strict 'refs'; |
|
5
|
|
|
|
|
8
|
|
|
5
|
|
|
|
|
705
|
|
31
|
4
|
|
|
|
|
13
|
*{$sym} = maker($spec); |
|
4
|
|
|
|
|
37
|
|
32
|
|
|
|
|
|
|
} |
33
|
4
|
|
|
|
|
7329
|
return; |
34
|
|
|
|
|
|
|
} |
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
sub maker { |
39
|
22
|
|
|
22
|
1
|
116
|
my $subr = eval(&source_maker(@_)); |
|
2
|
|
|
2
|
|
14
|
|
|
2
|
|
|
2
|
|
4
|
|
|
2
|
|
|
2
|
|
10
|
|
|
2
|
|
|
2
|
|
111
|
|
|
2
|
|
|
|
|
5
|
|
|
2
|
|
|
|
|
885
|
|
|
2
|
|
|
|
|
1907
|
|
|
2
|
|
|
|
|
40
|
|
|
2
|
|
|
|
|
24
|
|
|
2
|
|
|
|
|
70
|
|
|
2
|
|
|
|
|
3
|
|
|
2
|
|
|
|
|
263
|
|
40
|
46
|
100
|
|
|
|
151
|
die "Compile error <$@> in eval!?!" if $@; # shouldn't be possible! |
41
|
37
|
|
|
|
|
113
|
return $subr; |
42
|
|
|
|
|
|
|
} |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
# Implementation note: I didn't /need/ to use eval(). I could just return |
45
|
|
|
|
|
|
|
# an appropriate closure. But one can't do tr/$foo/$bar/ -- eval is the |
46
|
|
|
|
|
|
|
# only way to get things to (so to speak) interpolate there; and the |
47
|
|
|
|
|
|
|
# efficiency cost of requiring that Perl parse more code is offset by |
48
|
|
|
|
|
|
|
# the efficiency benefit of being able to use tr/// (instead of s///) in |
49
|
|
|
|
|
|
|
# appropriate cases. |
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
sub source_maker { |
54
|
5
|
|
|
5
|
|
5365
|
no locale; |
|
5
|
|
|
|
|
1297
|
|
|
5
|
|
|
|
|
26
|
|
55
|
26
|
|
|
18
|
1
|
12425
|
my($decl) = $_[0]; |
56
|
34
|
100
|
|
|
|
394
|
croak "usage: Sort::ArbBiLex::maker(DECLARATION). See the docs." |
57
|
|
|
|
|
|
|
unless @_ == 1; |
58
|
|
|
|
|
|
|
|
59
|
34
|
|
|
|
|
49
|
my $one_level_mode = 0; |
60
|
34
|
|
|
|
|
67
|
my @decl; |
61
|
34
|
100
|
|
|
|
88
|
if(ref $decl) { # It's a rLoL declaration |
62
|
24
|
100
|
|
|
|
77
|
croak "Sort order declaration must be a string or a listref" |
63
|
|
|
|
|
|
|
unless ref($decl) eq 'ARRAY'; |
64
|
58
|
100
|
|
|
|
89
|
print "rLoL-decl mode\n" if $Debug > 1; |
65
|
|
|
|
|
|
|
# Make @decl into a list of families |
66
|
58
|
|
|
|
|
96
|
@decl = @$decl; |
67
|
|
|
|
|
|
|
# and each one of the items in @decl must be a ref to a list of scalars |
68
|
58
|
|
|
|
|
116
|
foreach my $f (@decl) { |
69
|
116
|
50
|
|
|
|
221
|
croak "Each family must be a listref" unless ref($f) eq 'ARRAY'; |
70
|
116
|
|
33
|
|
|
1906
|
@$f = grep(defined($_) && length($_), @$f); # sanity |
71
|
92
|
|
|
|
|
211
|
foreach my $g (@$f) { # more sanity. |
72
|
170
|
50
|
|
|
|
503
|
croak "A reference found where a glyph was expected" if ref($g); |
73
|
|
|
|
|
|
|
} |
74
|
|
|
|
|
|
|
} |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
} else { # It's a string-style declaration |
77
|
35
|
50
|
|
|
|
137
|
print "string-decl mode\n" if $Debug > 1; |
78
|
|
|
|
|
|
|
# Make @decl into a list of families |
79
|
10
|
50
|
|
|
|
97
|
if($decl =~ /[\cm\cj\n]/) { # It contains majors and minors |
80
|
18
|
|
|
|
|
103
|
@decl = grep /\S/, split( /[\cm\cj]+/, $decl ); |
81
|
|
|
|
|
|
|
} else { # It's all majors, on one line |
82
|
16
|
0
|
|
|
|
99
|
print "Strangeness trap 1.\n" if $Debug; |
83
|
14
|
|
|
|
|
67
|
@decl = grep /\S/, split( /\s+/, $decl ); |
84
|
20
|
|
|
|
|
195
|
$one_level_mode = 1; |
85
|
|
|
|
|
|
|
} |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
# Now turn @decl into a list of lists, where each element is a |
88
|
|
|
|
|
|
|
# family -- i.e., a ref to a list of glyphs in that family. |
89
|
|
|
|
|
|
|
|
90
|
8
|
50
|
|
|
|
74
|
print "Glyph map:\n", map(" {<$_>}\n", @decl) if $Debug > 1; |
91
|
36
|
|
|
|
|
52
|
foreach my $d (@decl) { # in place changing |
92
|
|
|
|
|
|
|
#print " d $d -> ", map("<$_> ",grep($_ ne '',split(/\s+/, $d))), "\n"; |
93
|
40
|
|
|
|
|
85
|
$d = [ grep($_ ne '', split(/\s+/, $d)) ]; |
94
|
|
|
|
|
|
|
#print " d $d -> ", map("<$_> ", @$d), "\n"; |
95
|
|
|
|
|
|
|
} |
96
|
|
|
|
|
|
|
} |
97
|
|
|
|
|
|
|
|
98
|
52
|
|
|
|
|
86
|
@decl = grep( scalar(@{$_}), @decl); # nix empty families |
|
114
|
|
|
|
|
182
|
|
99
|
52
|
50
|
|
|
|
1672
|
croak "No glyphs in sort order declaration!?" unless @decl; |
100
|
|
|
|
|
|
|
|
101
|
18
|
100
|
|
|
|
50
|
@decl = map [$_], @{$decl[0]} if @decl == 1; |
|
6
|
|
|
|
|
55
|
|
102
|
|
|
|
|
|
|
# Change it from a family of N glyphs into N families of one glyph each |
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
# Iterate thru the families and their glyphs and build the tables |
105
|
18
|
|
|
|
|
29
|
my(@glyphs, @major_out, @minor_out); |
106
|
18
|
|
|
|
|
23
|
my $max_glyph_length = 0; |
107
|
18
|
|
|
|
|
23
|
my $max_family_length = 0; |
108
|
18
|
|
|
|
|
42
|
my %seen; |
109
|
18
|
|
|
|
|
23
|
my($glyph, $minor); # scratch |
110
|
18
|
|
|
|
|
74
|
for (my $major = 0; $major < @decl; $major++) { |
111
|
122
|
50
|
|
|
|
247
|
print "Family $major\n" if $Debug; |
112
|
122
|
|
|
|
|
113
|
croak "Too many major glyphs" if !UNICODE and $major > 255; |
113
|
24
|
|
|
|
|
35
|
$max_family_length = @{ $decl[$major] } |
|
122
|
|
|
|
|
283
|
|
114
|
122
|
100
|
|
|
|
114
|
if @{ $decl[$major] } > $max_family_length; |
115
|
|
|
|
|
|
|
|
116
|
122
|
|
|
|
|
180
|
for ($minor = 0; $minor < @{ $decl[$major] }; $minor++) { |
|
262
|
|
|
|
|
800
|
|
117
|
140
|
|
|
|
|
323
|
$glyph = $decl[$major][$minor]; |
118
|
140
|
50
|
|
|
|
363
|
print " Glyph ($major)\:$minor (", $glyph, ")\n" if $Debug; |
119
|
140
|
50
|
|
|
|
415
|
croak "Glyph <$glyph> appears twice in the sort order declaration!" |
120
|
|
|
|
|
|
|
if $seen{$glyph}++; |
121
|
140
|
|
|
|
|
160
|
croak "Too many minor glyphs" if !UNICODE and $minor > 255; |
122
|
|
|
|
|
|
|
|
123
|
140
|
100
|
|
|
|
266
|
$max_glyph_length = length($glyph) if length($glyph) > $max_glyph_length; |
124
|
|
|
|
|
|
|
|
125
|
140
|
|
|
|
|
305
|
$glyph =~ s/([^a-zA-Z0-9])/_char2esc($1)/eg; |
|
22
|
|
|
|
|
51
|
|
126
|
140
|
|
|
|
|
341
|
push @glyphs, $glyph; |
127
|
140
|
|
|
|
|
240
|
push @major_out, _num2esc($major); |
128
|
140
|
|
|
|
|
245
|
push @minor_out, _num2esc($minor); |
129
|
|
|
|
|
|
|
# or unpack 'H2', pack 'C', 12 or unpack 'H2', chr 12; ? |
130
|
|
|
|
|
|
|
} |
131
|
|
|
|
|
|
|
} |
132
|
18
|
50
|
|
|
|
54
|
die "Unexpected error: No glyphs?!?" if $max_glyph_length == 0; # sanity |
133
|
18
|
100
|
|
|
|
53
|
$one_level_mode = 1 if $max_family_length == 1; |
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
######################################################################### |
136
|
|
|
|
|
|
|
# Now start building the code. |
137
|
|
|
|
|
|
|
|
138
|
18
|
|
|
|
|
28
|
my($prelude, $coda, $code, $minor_code, $major_code); |
139
|
18
|
100
|
|
|
|
40
|
if($max_glyph_length == 1) { |
140
|
|
|
|
|
|
|
# All glyphs are single characters, so we can do this all with tr's |
141
|
14
|
|
|
|
|
20
|
$prelude = "# Single character mode."; |
142
|
14
|
|
|
|
|
20
|
$coda = ''; |
143
|
14
|
|
|
|
|
41
|
my $glyphs = join '', @glyphs; |
144
|
14
|
|
|
|
|
56
|
my $major_out = join '', @major_out; |
145
|
14
|
|
|
|
|
30
|
my $minor_out = join '', @minor_out; |
146
|
|
|
|
|
|
|
|
147
|
14
|
|
|
|
|
54
|
$minor_code = <<"EOMN"; # contents of a FOR block mapping $$x[0] => $$x[2] |
148
|
|
|
|
|
|
|
\$x->[2] = \$x->[0]; |
149
|
|
|
|
|
|
|
\$x->[2] =~ tr[$glyphs][]cd; |
150
|
|
|
|
|
|
|
\$x->[2] =~ tr[$glyphs] |
151
|
|
|
|
|
|
|
[$minor_out]; |
152
|
|
|
|
|
|
|
EOMN |
153
|
|
|
|
|
|
|
|
154
|
14
|
|
|
|
|
68
|
$major_code = <<"EOMJ"; # expression returning a scalar as a major key |
155
|
|
|
|
|
|
|
do { # major keymaker |
156
|
|
|
|
|
|
|
my(\$key) = \$_; |
157
|
|
|
|
|
|
|
\$key =~ tr[$glyphs][]cd; |
158
|
|
|
|
|
|
|
\$key =~ tr[$glyphs] |
159
|
|
|
|
|
|
|
[$major_out]; |
160
|
|
|
|
|
|
|
scalar(\$key); |
161
|
|
|
|
|
|
|
} |
162
|
|
|
|
|
|
|
EOMJ |
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
# End of single-glyph stuff. |
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
} else { |
167
|
|
|
|
|
|
|
# There are glyphs over 2 characters long -- gotta use s's. |
168
|
|
|
|
|
|
|
# End of multi-glyph stuff. |
169
|
4
|
|
|
|
|
42
|
my $glyphs = join ',', map "\"$_\"", @glyphs; |
170
|
4
|
|
|
|
|
42
|
my $major_out = join ',', map "\"$_\"", @major_out; |
171
|
4
|
|
|
|
|
34
|
my $minor_out = join ',', map "\"$_\"", @minor_out; |
172
|
|
|
|
|
|
|
|
173
|
4
|
100
|
|
|
|
40
|
if(!$one_level_mode) { |
174
|
2
|
|
|
|
|
11
|
$prelude = <<"EOPRELUDE"; |
175
|
|
|
|
|
|
|
{ # Multi-character mode. So we need a closure for these variables. |
176
|
|
|
|
|
|
|
my(\%major, \%minor); |
177
|
|
|
|
|
|
|
\@major{$glyphs} |
178
|
|
|
|
|
|
|
= ($major_out); |
179
|
|
|
|
|
|
|
\@minor{$glyphs} |
180
|
|
|
|
|
|
|
= ($minor_out); |
181
|
|
|
|
|
|
|
my \$glyph_re = join "|", map(quotemeta, |
182
|
|
|
|
|
|
|
sort {length(\$b) <=> length(\$a)} keys \%major); |
183
|
|
|
|
|
|
|
# put the longest glyphs first |
184
|
|
|
|
|
|
|
EOPRELUDE |
185
|
|
|
|
|
|
|
} else { # Multi-character mode |
186
|
2
|
|
|
|
|
9
|
$prelude = <<"EOPRELUDE2"; |
187
|
|
|
|
|
|
|
{ # Multi-character mode. So we need a closure for these variables. |
188
|
|
|
|
|
|
|
my(\%major); # just one-level mode, tho. |
189
|
|
|
|
|
|
|
\@major{$glyphs} |
190
|
|
|
|
|
|
|
= ($major_out); |
191
|
|
|
|
|
|
|
my \$glyph_re = join "|", map(quotemeta, |
192
|
|
|
|
|
|
|
sort {length(\$b) <=> length(\$a)} keys \%major); |
193
|
|
|
|
|
|
|
# put the longest glyphs first |
194
|
|
|
|
|
|
|
EOPRELUDE2 |
195
|
|
|
|
|
|
|
} |
196
|
4
|
|
|
|
|
9
|
$coda = "} # end of closure."; |
197
|
|
|
|
|
|
|
|
198
|
4
|
|
|
|
|
6
|
$minor_code = <<"EOMN2"; # contents of a FOR block mapping $$x[0] => $$x[2] |
199
|
|
|
|
|
|
|
\$x->[2] = join '', |
200
|
|
|
|
|
|
|
map \$minor{\$_}, |
201
|
|
|
|
|
|
|
\$x->[0] =~ m<(\$glyph_re)>go; |
202
|
|
|
|
|
|
|
EOMN2 |
203
|
|
|
|
|
|
|
|
204
|
4
|
|
|
|
|
14
|
$major_code = <<"EOMJ2"; # expression returning a scalar as a major key |
205
|
|
|
|
|
|
|
join('', map \$major{\$_}, m<(\$glyph_re)>go) # major keymaker |
206
|
|
|
|
|
|
|
EOMJ2 |
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
} |
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
### |
211
|
|
|
|
|
|
|
# Now finish cobbling the code together. |
212
|
|
|
|
|
|
|
|
213
|
18
|
|
|
|
|
152
|
my $now = scalar(gmtime); |
214
|
|
|
|
|
|
|
|
215
|
18
|
100
|
|
|
|
46
|
if(!$one_level_mode) { # 2-level mode |
216
|
8
|
|
|
|
|
94
|
$code = <<"EOVOODOO"; |
217
|
|
|
|
|
|
|
\# Generated by Sort::ArbBiLex v$VERSION at $now GMT |
218
|
|
|
|
|
|
|
$prelude |
219
|
|
|
|
|
|
|
# Two-level mode |
220
|
|
|
|
|
|
|
sub { # change that to "sub whatever {" to name this function |
221
|
|
|
|
|
|
|
no locale; # we need the real 8-bit ASCIIbetical sort() |
222
|
|
|
|
|
|
|
use strict; |
223
|
|
|
|
|
|
|
return |
224
|
|
|
|
|
|
|
# map sort map is the Schwartzian Transform. See perlfaq4. |
225
|
|
|
|
|
|
|
map { \$_->[0] } |
226
|
|
|
|
|
|
|
sort { |
227
|
|
|
|
|
|
|
\$a->[1] cmp \$b->[1] || |
228
|
|
|
|
|
|
|
do { |
229
|
|
|
|
|
|
|
foreach my \$x (\$a, \$b) { |
230
|
|
|
|
|
|
|
if( !defined(\$x->[2]) and defined(\$x->[0]) ) { |
231
|
|
|
|
|
|
|
$minor_code |
232
|
|
|
|
|
|
|
} |
233
|
|
|
|
|
|
|
} |
234
|
|
|
|
|
|
|
\$a->[2] cmp \$b->[2]; # return value of this do-block |
235
|
|
|
|
|
|
|
} |
236
|
|
|
|
|
|
|
} |
237
|
|
|
|
|
|
|
map { [ \$_, |
238
|
|
|
|
|
|
|
$major_code |
239
|
|
|
|
|
|
|
, undef |
240
|
|
|
|
|
|
|
] |
241
|
|
|
|
|
|
|
} |
242
|
|
|
|
|
|
|
\@_; |
243
|
|
|
|
|
|
|
} |
244
|
|
|
|
|
|
|
$coda |
245
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
EOVOODOO |
247
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
} else { # one-level mode |
249
|
|
|
|
|
|
|
|
250
|
10
|
|
|
|
|
67
|
$code = <<"EOVOODOO2"; |
251
|
|
|
|
|
|
|
\# Generated by Sort::ArbBiLex v$VERSION at $now GMT |
252
|
|
|
|
|
|
|
$prelude |
253
|
|
|
|
|
|
|
# One-level mode |
254
|
|
|
|
|
|
|
sub { # change that to "sub whatever {" to name this function |
255
|
|
|
|
|
|
|
no locale; # we need the real 8-bit ASCIIbetical sort() |
256
|
|
|
|
|
|
|
use strict; |
257
|
|
|
|
|
|
|
return |
258
|
|
|
|
|
|
|
# map sort map is the Schwartzian Transform. See perlfaq4. |
259
|
|
|
|
|
|
|
map { \$_->[0] } |
260
|
|
|
|
|
|
|
sort { \$a->[1] cmp \$b->[1] } |
261
|
|
|
|
|
|
|
map { [ \$_, |
262
|
|
|
|
|
|
|
$major_code |
263
|
|
|
|
|
|
|
] |
264
|
|
|
|
|
|
|
} |
265
|
|
|
|
|
|
|
\@_; |
266
|
|
|
|
|
|
|
} |
267
|
|
|
|
|
|
|
$coda |
268
|
|
|
|
|
|
|
|
269
|
|
|
|
|
|
|
EOVOODOO2 |
270
|
|
|
|
|
|
|
|
271
|
|
|
|
|
|
|
} |
272
|
|
|
|
|
|
|
|
273
|
18
|
50
|
|
|
|
49
|
print "\nCode to eval:\n", $code, "__ENDCODE__\n\n" if $Debug; |
274
|
|
|
|
|
|
|
|
275
|
18
|
|
|
|
|
767
|
return $code; |
276
|
|
|
|
|
|
|
} |
277
|
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
279
|
|
|
|
|
|
|
|
280
|
|
|
|
|
|
|
sub _char2esc { |
281
|
22
|
|
|
22
|
|
46
|
my $in = ord( $_[0] ); |
282
|
22
|
100
|
|
|
|
73
|
return sprintf "\\x{%x}", $in if $in > 255; |
283
|
18
|
|
|
|
|
103
|
return sprintf "\\x%02x", $in; |
284
|
|
|
|
|
|
|
} |
285
|
|
|
|
|
|
|
|
286
|
|
|
|
|
|
|
sub _num2esc { |
287
|
280
|
|
|
280
|
|
309
|
my $in = $_[0]; |
288
|
280
|
50
|
|
|
|
512
|
return sprintf "\\x{%x}", $in if $in > 255; |
289
|
280
|
|
|
|
|
823
|
return sprintf "\\x%02x", $in; |
290
|
|
|
|
|
|
|
} |
291
|
|
|
|
|
|
|
|
292
|
|
|
|
|
|
|
########################################################################### |
293
|
|
|
|
|
|
|
|
294
|
|
|
|
|
|
|
# "cmp" returns -1, 0, or 1 depending on whether the left argument is |
295
|
|
|
|
|
|
|
# stringwise less than, equal to, or greater than the right argument. |
296
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
sub xcmp { |
298
|
8
|
50
|
33
|
8
|
0
|
47
|
carp "usage: xcmp(\\&sorter,$a,$b)" unless @_ and ref($_[0]); |
299
|
8
|
100
|
|
|
|
55
|
return 0 if $_[1] eq $_[2]; # We have to trap this early. |
300
|
6
|
100
|
|
|
|
181
|
return 1 if $_[1] ne ( $_[0]->($_[1], $_[2]) )[0]; |
301
|
|
|
|
|
|
|
# If they were switched when sorted, then the original-first was |
302
|
|
|
|
|
|
|
# lexically GT than the original-second. |
303
|
4
|
100
|
|
|
|
113
|
return -1 if $_[1] eq ( $_[0]->($_[2], $_[1]) )[0]; |
304
|
|
|
|
|
|
|
# If they were switched BACK when REVERSED and sorted, then the |
305
|
|
|
|
|
|
|
# original-first was lexically LT than the original-second. |
306
|
2
|
|
|
|
|
12
|
return 0; |
307
|
|
|
|
|
|
|
# Otherwise they were lexically identical. |
308
|
|
|
|
|
|
|
} |
309
|
|
|
|
|
|
|
|
310
|
|
|
|
|
|
|
# And two actually simpler ones: |
311
|
|
|
|
|
|
|
|
312
|
|
|
|
|
|
|
sub xlt { |
313
|
14
|
50
|
33
|
14
|
0
|
9541
|
carp "usage: xlt(\\&sorter,$a,$b)" unless @_ and ref($_[0]); |
314
|
|
|
|
|
|
|
#AKA: xcmp(@_) == -1; |
315
|
14
|
100
|
|
|
|
50
|
return 0 if $_[1] eq $_[2]; # We have to trap this early. |
316
|
12
|
100
|
|
|
|
417
|
return 1 if $_[1] eq ( $_[0]->($_[2], $_[1]) )[0]; |
317
|
|
|
|
|
|
|
# If they were switched BACK when REVERSED and sorted, then the |
318
|
|
|
|
|
|
|
# original-first was lexically LT than the original-second. |
319
|
8
|
|
|
|
|
46
|
return 0; |
320
|
|
|
|
|
|
|
} |
321
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
sub xgt { |
323
|
14
|
50
|
33
|
14
|
0
|
82
|
carp "usage: xgt(\\&sorter,$a,$b)" unless @_ and ref($_[0]); |
324
|
|
|
|
|
|
|
#AKA: xcmp(@_) == -1; |
325
|
14
|
100
|
|
|
|
44
|
return 0 if $_[1] eq $_[2]; # We have to trap this early. |
326
|
12
|
100
|
|
|
|
371
|
return 1 if $_[1] ne ( $_[0]->($_[1], $_[2]) )[0]; |
327
|
|
|
|
|
|
|
# If they were switched when sorted, then the original-first was |
328
|
|
|
|
|
|
|
# lexically GT than the original-second. |
329
|
8
|
|
|
|
|
43
|
return 0; |
330
|
|
|
|
|
|
|
} |
331
|
|
|
|
|
|
|
|
332
|
|
|
|
|
|
|
# And then two easy ones: |
333
|
|
|
|
|
|
|
|
334
|
|
|
|
|
|
|
sub xle { |
335
|
8
|
50
|
33
|
8
|
0
|
656
|
carp "usage: xle(\\&sorter,$a,$b)" unless @_ and ref($_[0]); |
336
|
8
|
|
|
|
|
18
|
!xgt(@_); #AKA: xcmp(@_) < 1; |
337
|
|
|
|
|
|
|
} |
338
|
|
|
|
|
|
|
|
339
|
|
|
|
|
|
|
sub xge { |
340
|
8
|
50
|
33
|
8
|
0
|
49
|
carp "usage: xge(\\&sorter,$a,$b)" unless @_ and ref($_[0]); |
341
|
8
|
|
|
|
|
20
|
!xlt(@_); #AKA: xcmp(@_) > -1; |
342
|
|
|
|
|
|
|
} |
343
|
|
|
|
|
|
|
|
344
|
|
|
|
|
|
|
########################################################################### |
345
|
|
|
|
|
|
|
1; |
346
|
|
|
|
|
|
|
|
347
|
|
|
|
|
|
|
__END__ |