| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Text::Patch; |
|
2
|
1
|
|
|
1
|
|
52871
|
use Exporter; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
65
|
|
|
3
|
|
|
|
|
|
|
our @ISA = qw( Exporter ); |
|
4
|
|
|
|
|
|
|
our @EXPORT = qw( patch ); |
|
5
|
|
|
|
|
|
|
our $VERSION = '1.8'; |
|
6
|
1
|
|
|
1
|
|
5
|
use strict; |
|
|
1
|
|
|
|
|
3
|
|
|
|
1
|
|
|
|
|
31
|
|
|
7
|
1
|
|
|
1
|
|
4
|
use warnings; |
|
|
1
|
|
|
|
|
5
|
|
|
|
1
|
|
|
|
|
33
|
|
|
8
|
1
|
|
|
1
|
|
4
|
use Carp; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
54
|
|
|
9
|
|
|
|
|
|
|
|
|
10
|
1
|
|
|
1
|
|
5
|
use constant NO_NEWLINE => '\\ No newline at end of file'; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
2230
|
|
|
11
|
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
sub patch |
|
13
|
|
|
|
|
|
|
{ |
|
14
|
0
|
|
|
0
|
1
|
|
my $text = shift; |
|
15
|
0
|
|
|
|
|
|
my $diff = shift; |
|
16
|
0
|
0
|
|
|
|
|
my %options = ref $_[0] eq 'HASH' ? %{ $_[0] } : @_; |
|
|
0
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
|
|
18
|
0
|
|
|
|
|
|
my %handler = ('unified' => \&patch_unified, |
|
19
|
|
|
|
|
|
|
'context' => \&patch_context, |
|
20
|
|
|
|
|
|
|
'oldstyle' => \&patch_oldstyle, |
|
21
|
|
|
|
|
|
|
); |
|
22
|
0
|
|
|
|
|
|
my $style = $options{STYLE}; |
|
23
|
0
|
0
|
|
|
|
|
croak "required STYLE option is missing" unless $style; |
|
24
|
0
|
0
|
|
|
|
|
croak "source required" unless defined $text; |
|
25
|
0
|
0
|
|
|
|
|
croak "diff required" unless defined $diff; |
|
26
|
0
|
|
0
|
|
|
|
my $code = $handler{lc($style)} || croak "unrecognised STYLE '$style'"; |
|
27
|
|
|
|
|
|
|
|
|
28
|
0
|
|
|
|
|
|
my @text = split /^/m, $text; |
|
29
|
0
|
|
|
|
|
|
my @diff = split /^/m, $diff; |
|
30
|
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
# analyse source/diff to determine line ending used. |
|
32
|
|
|
|
|
|
|
# (if source is only 1 line, can't use it to determine line endings) |
|
33
|
0
|
0
|
|
|
|
|
my $line1 = @text > 1 ? $text[0] : $diff[0]; |
|
34
|
0
|
|
|
|
|
|
my($line1c, $sep) = _chomp($line1); |
|
35
|
0
|
|
0
|
|
|
|
$sep ||= "\n"; # default to unix line ending |
|
36
|
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
# apply patch |
|
38
|
0
|
|
|
|
|
|
DUMP("got patch", \@diff); |
|
39
|
0
|
|
|
|
|
|
my $out = $code->(\@text, \@diff, $sep); |
|
40
|
|
|
|
|
|
|
|
|
41
|
0
|
|
|
|
|
|
my $lastline = _chomp($diff[-1], $sep); |
|
42
|
0
|
0
|
|
|
|
|
$out = _chomp($out, $sep) if $lastline eq NO_NEWLINE; |
|
43
|
0
|
|
|
|
|
|
return $out; |
|
44
|
|
|
|
|
|
|
} |
|
45
|
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
sub patch_unified |
|
47
|
|
|
|
|
|
|
{ |
|
48
|
0
|
|
|
0
|
0
|
|
my($text, $diff, $sep) = @_; |
|
49
|
0
|
|
|
|
|
|
my @hunks; |
|
50
|
|
|
|
|
|
|
my %hunk; |
|
51
|
|
|
|
|
|
|
|
|
52
|
0
|
|
|
|
|
|
for( @$diff ) |
|
53
|
|
|
|
|
|
|
{ |
|
54
|
|
|
|
|
|
|
#print STDERR ">>> ... [$_]"; |
|
55
|
0
|
0
|
|
|
|
|
if( /^\@\@\s*-([\d,]+)/ ) |
|
56
|
|
|
|
|
|
|
{ |
|
57
|
|
|
|
|
|
|
#print STDERR ">>> *** HUNK!\n"; |
|
58
|
0
|
|
|
|
|
|
my($pos1, $count1) = split /,/, $1; |
|
59
|
0
|
|
|
|
|
|
push @hunks, { %hunk }; |
|
60
|
0
|
|
|
|
|
|
%hunk = (); |
|
61
|
0
|
|
|
|
|
|
$hunk{ FROM } = $pos1 - 1; # diff is 1-based |
|
62
|
|
|
|
|
|
|
# Modification by Ben L., patches may have @@ -0,0 if the source is empty. |
|
63
|
0
|
0
|
|
|
|
|
$hunk{ FROM } = 0 if $hunk{ FROM } < 0; |
|
64
|
0
|
0
|
|
|
|
|
$hunk{ LEN } = defined $count1 ? $count1 : $pos1 == 0 ? 0 : 1; |
|
|
|
0
|
|
|
|
|
|
|
65
|
0
|
|
|
|
|
|
$hunk{ DATA } = []; |
|
66
|
|
|
|
|
|
|
} |
|
67
|
0
|
|
|
|
|
|
push @{ $hunk{ DATA } }, $_; |
|
|
0
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
} |
|
69
|
0
|
|
|
|
|
|
push @hunks, { %hunk }; # push last hunk |
|
70
|
0
|
|
|
|
|
|
shift @hunks; # first is always empty |
|
71
|
|
|
|
|
|
|
|
|
72
|
0
|
|
|
|
|
|
return _patch($text, \@hunks, $sep); |
|
73
|
|
|
|
|
|
|
} |
|
74
|
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
sub patch_oldstyle { |
|
76
|
0
|
|
|
0
|
0
|
|
my($text, $diff, $sep) = @_; |
|
77
|
0
|
|
|
|
|
|
my @hunks; |
|
78
|
0
|
|
|
|
|
|
my $i = 0; |
|
79
|
|
|
|
|
|
|
|
|
80
|
0
|
|
|
|
|
|
my $hunk_head = qr/^([\d,]+)([acd])([\d,]+)$/; |
|
81
|
0
|
|
|
|
|
|
while($i < @$diff) { |
|
82
|
0
|
|
|
|
|
|
my $l = $diff->[$i]; |
|
83
|
0
|
|
|
|
|
|
my($r1, $type, $r2) = $l =~ $hunk_head; |
|
84
|
0
|
0
|
0
|
|
|
|
die "Malformed patch at line ".($i + 1)."\n" |
|
|
|
|
0
|
|
|
|
|
|
85
|
|
|
|
|
|
|
unless defined $r1 && $type && defined $r2; |
|
86
|
0
|
|
|
|
|
|
my($pos1, $count1) = _range($r1); |
|
87
|
0
|
|
|
|
|
|
my($pos2, $count2) = _range($r2); |
|
88
|
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
# parse chunk data |
|
90
|
0
|
|
|
|
|
|
my @data; |
|
91
|
0
|
|
|
|
|
|
my $j = $i + 1; |
|
92
|
0
|
|
|
|
|
|
for(; $j < @$diff; $j++) { |
|
93
|
0
|
|
|
|
|
|
$l = $diff->[$j]; |
|
94
|
0
|
0
|
|
|
|
|
last if $l =~ $hunk_head; |
|
95
|
0
|
0
|
|
|
|
|
next if $l =~ /^---/; # separator |
|
96
|
0
|
|
|
|
|
|
push @data, $l; |
|
97
|
|
|
|
|
|
|
} |
|
98
|
0
|
|
|
|
|
|
my $datalen = $j - $i - 1; |
|
99
|
|
|
|
|
|
|
|
|
100
|
0
|
0
|
|
|
|
|
if($type eq 'a') { # add |
|
101
|
0
|
|
|
|
|
|
$count1 = 0; # don't remove any lines |
|
102
|
0
|
|
|
|
|
|
$pos1++; # add to line after pos1 |
|
103
|
|
|
|
|
|
|
} |
|
104
|
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
# convert data to a format _patch() will understand |
|
106
|
0
|
|
|
|
|
|
for(@data) { |
|
107
|
0
|
|
|
|
|
|
$_ =~ s/^< /-/; |
|
108
|
0
|
|
|
|
|
|
$_ =~ s/^> /+/; |
|
109
|
|
|
|
|
|
|
} |
|
110
|
|
|
|
|
|
|
|
|
111
|
0
|
|
|
|
|
|
push @hunks, { FROM => $pos1 - 1, |
|
112
|
|
|
|
|
|
|
LEN => $count1, |
|
113
|
|
|
|
|
|
|
DATA => \@data, |
|
114
|
|
|
|
|
|
|
}; |
|
115
|
0
|
|
|
|
|
|
$i += $datalen + 1; |
|
116
|
|
|
|
|
|
|
} |
|
117
|
0
|
|
|
|
|
|
return _patch($text, \@hunks, $sep); |
|
118
|
|
|
|
|
|
|
} |
|
119
|
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
# NB: this works by converting hunks into a kind of unified format |
|
121
|
|
|
|
|
|
|
sub patch_context { |
|
122
|
0
|
|
|
0
|
0
|
|
my($text, $diff, $sep) = @_; |
|
123
|
0
|
|
|
|
|
|
my $i = 0; |
|
124
|
0
|
|
|
|
|
|
my @hunks; |
|
125
|
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
# skip past header |
|
127
|
0
|
|
|
|
|
|
for(@$diff) { |
|
128
|
0
|
|
|
|
|
|
$i++; |
|
129
|
0
|
0
|
|
|
|
|
last if /^\Q***************\E$/; # end header marker |
|
130
|
|
|
|
|
|
|
} |
|
131
|
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
# this sub reads one half of a hunk (from/to part) |
|
133
|
|
|
|
|
|
|
my $read_part = sub { |
|
134
|
0
|
|
|
0
|
|
|
my $l = $diff->[$i++]; |
|
135
|
0
|
|
|
|
|
|
TRACE("got line: $l"); |
|
136
|
0
|
0
|
|
|
|
|
die "Malformed patch at line $i\n" |
|
137
|
|
|
|
|
|
|
unless $l =~ /^(?:\*\*\*|---)\s+([\d,]+)\s+(?:\*\*\*|---)/; |
|
138
|
0
|
|
|
|
|
|
my($pos, $count) = _range($1); |
|
139
|
0
|
|
|
|
|
|
my @part; |
|
140
|
0
|
|
|
|
|
|
while($i < @$diff) { |
|
141
|
0
|
|
|
|
|
|
my $l = $diff->[$i]; |
|
142
|
0
|
0
|
|
|
|
|
last if $l =~ /^(\*\*\*|---)/; |
|
143
|
0
|
|
|
|
|
|
push @part, $l; |
|
144
|
0
|
|
|
|
|
|
$i++; |
|
145
|
|
|
|
|
|
|
} |
|
146
|
0
|
|
|
|
|
|
DUMP("got part", \@part); |
|
147
|
0
|
|
|
|
|
|
return (\@part, $pos, $count); |
|
148
|
0
|
|
|
|
|
|
}; |
|
149
|
|
|
|
|
|
|
|
|
150
|
0
|
|
|
|
|
|
while($i < @$diff) { |
|
151
|
|
|
|
|
|
|
# read the from and to part of this hunk |
|
152
|
0
|
|
|
|
|
|
my($part1, $pos1, $count1) = $read_part->(); |
|
153
|
0
|
|
|
|
|
|
my($part2, $pos2, $count2) = $read_part->(); |
|
154
|
0
|
|
|
|
|
|
$i++; # skip chunk separator |
|
155
|
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
# convert operations to unified style ones |
|
157
|
0
|
|
|
|
|
|
$_ =~ s/^(.)\s/$1/ for @$part1, @$part2; |
|
158
|
0
|
|
|
|
|
|
$_ =~ s/^\!/-/ for @$part1; # remove |
|
159
|
0
|
|
|
|
|
|
$_ =~ s/^\!/+/ for @$part2; # add |
|
160
|
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
# merge the parts to create a unified style chunk |
|
162
|
0
|
|
|
|
|
|
my @data; |
|
163
|
0
|
|
|
|
|
|
for(;;) { |
|
164
|
0
|
|
|
|
|
|
my $c1 = $part1->[0]; |
|
165
|
0
|
|
|
|
|
|
my $c2 = $part2->[0]; |
|
166
|
0
|
0
|
0
|
|
|
|
last unless defined $c1 || defined $c2; |
|
167
|
|
|
|
|
|
|
|
|
168
|
0
|
0
|
0
|
|
|
|
if(defined $c1 && $c1 =~ /^-/) { |
|
|
|
0
|
0
|
|
|
|
|
|
169
|
0
|
|
|
|
|
|
push @data, shift @$part1; # remove line |
|
170
|
|
|
|
|
|
|
} elsif(defined $c2 && $c2 =~ /^\+/) { |
|
171
|
0
|
|
|
|
|
|
push @data, shift @$part2; # add line |
|
172
|
|
|
|
|
|
|
} else { # context |
|
173
|
0
|
|
|
|
|
|
my($x1, $x2) = (shift @$part1, shift @$part2); |
|
174
|
0
|
0
|
|
|
|
|
push @data, defined $x1 ? $x1 : $x2; |
|
175
|
|
|
|
|
|
|
} |
|
176
|
|
|
|
|
|
|
} |
|
177
|
0
|
|
|
|
|
|
push @hunks, { FROM => $pos1 - 1, |
|
178
|
|
|
|
|
|
|
LEN => $count1, |
|
179
|
|
|
|
|
|
|
DATA => \@data, |
|
180
|
|
|
|
|
|
|
}; |
|
181
|
0
|
|
|
|
|
|
DUMP("merged data", \@data); |
|
182
|
|
|
|
|
|
|
} |
|
183
|
0
|
|
|
|
|
|
return _patch($text, \@hunks, $sep); |
|
184
|
|
|
|
|
|
|
} |
|
185
|
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
###################################################################### |
|
187
|
|
|
|
|
|
|
# private |
|
188
|
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
# returns (start line, line count) |
|
190
|
|
|
|
|
|
|
sub _range { |
|
191
|
0
|
|
|
0
|
|
|
my($range) = @_; |
|
192
|
0
|
|
|
|
|
|
my($pos1, $pos2) = split /,/, $range; |
|
193
|
0
|
0
|
|
|
|
|
return ($pos1, defined $pos2 ? $pos2 - $pos1 + 1 : 1); |
|
194
|
|
|
|
|
|
|
} |
|
195
|
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
sub _patch { |
|
197
|
0
|
|
|
0
|
|
|
my($text, $hunks, $sep) = @_; |
|
198
|
0
|
|
|
|
|
|
my $hunknum = scalar @$hunks + 1; |
|
199
|
0
|
0
|
|
|
|
|
die "No hunks found\n" unless @$hunks; |
|
200
|
0
|
|
|
|
|
|
for my $hunk ( reverse @$hunks ) |
|
201
|
|
|
|
|
|
|
{ |
|
202
|
0
|
|
|
|
|
|
$hunknum--; |
|
203
|
0
|
|
|
|
|
|
DUMP("hunk", $hunk); |
|
204
|
0
|
|
|
|
|
|
my @pdata; |
|
205
|
0
|
|
|
|
|
|
my $num = $hunk->{FROM}; |
|
206
|
0
|
|
|
|
|
|
for( @{ $hunk->{ DATA } } ) |
|
|
0
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
{ |
|
208
|
0
|
0
|
|
|
|
|
next unless s/^([ \-\+])//; |
|
209
|
|
|
|
|
|
|
#print STDERR ">>> ($1) $_"; |
|
210
|
0
|
0
|
|
|
|
|
if($1 ne '+') { |
|
211
|
|
|
|
|
|
|
# not an addition, check line for match against existing text. |
|
212
|
|
|
|
|
|
|
# ignore line endings for comparison |
|
213
|
0
|
|
|
|
|
|
my $orig = _chomp($text->[$num++], $sep); # num 0 based here |
|
214
|
0
|
|
|
|
|
|
my $expect = _chomp($_, $sep); |
|
215
|
0
|
|
|
|
|
|
TRACE("checking >>$orig<<"); |
|
216
|
0
|
|
|
|
|
|
TRACE(" against >>$expect<<"); |
|
217
|
0
|
0
|
|
|
|
|
die "Hunk #$hunknum failed at line $num.\n" # actual line number |
|
218
|
|
|
|
|
|
|
unless $orig eq $expect; |
|
219
|
|
|
|
|
|
|
} |
|
220
|
0
|
0
|
|
|
|
|
next if $1 eq '-'; # removals |
|
221
|
0
|
|
|
|
|
|
push @pdata, $_; # add/replace line |
|
222
|
|
|
|
|
|
|
} |
|
223
|
0
|
|
|
|
|
|
splice @$text, $hunk->{ FROM }, $hunk->{ LEN }, @pdata; |
|
224
|
|
|
|
|
|
|
} |
|
225
|
|
|
|
|
|
|
|
|
226
|
0
|
|
|
|
|
|
return join '', @$text; |
|
227
|
|
|
|
|
|
|
} |
|
228
|
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
# chomp $sep from the end of line |
|
230
|
|
|
|
|
|
|
# if $sep is not given, chomp unix or dos line ending |
|
231
|
|
|
|
|
|
|
sub _chomp { |
|
232
|
0
|
|
|
0
|
|
|
my($text, $sep) = @_; |
|
233
|
0
|
0
|
|
|
|
|
if($sep) { |
|
234
|
0
|
|
|
|
|
|
$text =~ s/($sep)$//; |
|
235
|
|
|
|
|
|
|
} else { |
|
236
|
0
|
|
|
|
|
|
$text =~ s/(\r\n|\n)$//; |
|
237
|
|
|
|
|
|
|
} |
|
238
|
0
|
0
|
|
|
|
|
return wantarray ? ($text, $1) : $text; |
|
239
|
|
|
|
|
|
|
} |
|
240
|
|
|
|
|
|
|
|
|
241
|
0
|
|
|
0
|
0
|
|
sub DUMP {} |
|
242
|
0
|
|
|
0
|
0
|
|
sub TRACE {} |
|
243
|
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
#sub DUMP { |
|
245
|
|
|
|
|
|
|
#use Data::Dumper; |
|
246
|
|
|
|
|
|
|
#print STDERR Dumper(@_); |
|
247
|
|
|
|
|
|
|
#} |
|
248
|
|
|
|
|
|
|
#sub TRACE { |
|
249
|
|
|
|
|
|
|
#use Data::Dumper; |
|
250
|
|
|
|
|
|
|
#print STDERR Dumper(@_); |
|
251
|
|
|
|
|
|
|
#} |
|
252
|
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
=pod |
|
255
|
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
=head1 NAME |
|
257
|
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
Text::Patch - Patches text with given patch |
|
259
|
|
|
|
|
|
|
|
|
260
|
|
|
|
|
|
|
=head1 SYNOPSIS |
|
261
|
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
use Text::Patch; |
|
263
|
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
$output = patch( $source, $diff, STYLE => "Unified" ); |
|
265
|
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
use Text::Diff; |
|
267
|
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
$src = ... |
|
269
|
|
|
|
|
|
|
$dst = ... |
|
270
|
|
|
|
|
|
|
|
|
271
|
|
|
|
|
|
|
$diff = diff( \$src, \$dst, { STYLE => 'Unified' } ); |
|
272
|
|
|
|
|
|
|
|
|
273
|
|
|
|
|
|
|
$out = patch( $src, $diff, { STYLE => 'Unified' } ); |
|
274
|
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
print "Patch successful" if $out eq $dst; |
|
276
|
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
=head1 DESCRIPTION |
|
278
|
|
|
|
|
|
|
|
|
279
|
|
|
|
|
|
|
Text::Patch combines source text with given diff (difference) data. |
|
280
|
|
|
|
|
|
|
Diff data is produced by Text::Diff module or by the standard diff |
|
281
|
|
|
|
|
|
|
utility (man diff, see -u option). |
|
282
|
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
=over 4 |
|
284
|
|
|
|
|
|
|
|
|
285
|
|
|
|
|
|
|
=item patch( $source, $diff, options... ) |
|
286
|
|
|
|
|
|
|
|
|
287
|
|
|
|
|
|
|
First argument is source (original) text. Second is the diff data. |
|
288
|
|
|
|
|
|
|
Third argument can be either hash reference with options or all the |
|
289
|
|
|
|
|
|
|
rest arguments will be considered patch options: |
|
290
|
|
|
|
|
|
|
|
|
291
|
|
|
|
|
|
|
$output = patch( $source, $diff, STYLE => "Unified", ... ); |
|
292
|
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
$output = patch( $source, $diff, { STYLE => "Unified", ... } ); |
|
294
|
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
Options are: |
|
296
|
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
STYLE => 'Unified' |
|
298
|
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
STYLE can be "Unified", "Context" or "OldStyle". |
|
300
|
|
|
|
|
|
|
|
|
301
|
|
|
|
|
|
|
The 'Unified' diff format looks like this: |
|
302
|
|
|
|
|
|
|
|
|
303
|
|
|
|
|
|
|
@@ -1,7 +1,6 @@ |
|
304
|
|
|
|
|
|
|
-The Way that can be told of is not the eternal Way; |
|
305
|
|
|
|
|
|
|
-The name that can be named is not the eternal name. |
|
306
|
|
|
|
|
|
|
The Nameless is the origin of Heaven and Earth; |
|
307
|
|
|
|
|
|
|
-The Named is the mother of all things. |
|
308
|
|
|
|
|
|
|
+The named is the mother of all things. |
|
309
|
|
|
|
|
|
|
+ |
|
310
|
|
|
|
|
|
|
Therefore let there always be non-being, |
|
311
|
|
|
|
|
|
|
so we may see their subtlety, |
|
312
|
|
|
|
|
|
|
And let there always be being, |
|
313
|
|
|
|
|
|
|
@@ -9,3 +8,6 @@ |
|
314
|
|
|
|
|
|
|
The two are the same, |
|
315
|
|
|
|
|
|
|
But after they are produced, |
|
316
|
|
|
|
|
|
|
they have different names. |
|
317
|
|
|
|
|
|
|
+They both may be called deep and profound. |
|
318
|
|
|
|
|
|
|
+Deeper and more profound, |
|
319
|
|
|
|
|
|
|
+The door of all subtleties! |
|
320
|
|
|
|
|
|
|
|
|
321
|
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
=back |
|
323
|
|
|
|
|
|
|
|
|
324
|
|
|
|
|
|
|
=head1 TODO |
|
325
|
|
|
|
|
|
|
|
|
326
|
|
|
|
|
|
|
Interfaces with files, arrays, etc. |
|
327
|
|
|
|
|
|
|
|
|
328
|
|
|
|
|
|
|
=head1 AUTHOR |
|
329
|
|
|
|
|
|
|
|
|
330
|
|
|
|
|
|
|
Vladi Belperchinov-Shabanski "Cade" |
|
331
|
|
|
|
|
|
|
|
|
332
|
|
|
|
|
|
|
|
|
333
|
|
|
|
|
|
|
|
|
334
|
|
|
|
|
|
|
http://cade.datamax.bg |
|
335
|
|
|
|
|
|
|
|
|
336
|
|
|
|
|
|
|
=head1 VERSION |
|
337
|
|
|
|
|
|
|
|
|
338
|
|
|
|
|
|
|
$Id: Patch.pm,v 1.6 2007/04/07 19:57:41 cade Exp $ |
|
339
|
|
|
|
|
|
|
|
|
340
|
|
|
|
|
|
|
=cut |