1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
|
############################################################################
#
# File: patch.icn
#
# Subject: Procedures for UNIX-like patch(1)
#
# Author: Rich Morin
#
# Date: June 18, 1990
#
############################################################################
#
# This file is in the public domain.
#
############################################################################
#
# This procedure produces a sequence of edited items, reading a source
# stream (from) and a stream of difference records (diffs), as generated
# by dif.icn.
#
# An optional parameter (rev) causes the edits to be made in reverse.
# This allows an old stream to be regenerated from a new stream and an
# appropriate stream of difference records.
#
# The original patch(1) utility was written by Larry Wall, and is used
# widely in the UNIX community. See also diffu.icn and patchu.icn, the
# utility program versions of dif.icn and patch.icn.
#
# Usage: patch(old, diff) # patch old to new via diff
# patch(new, diff, rev) # patch new to old via diff
#
############################################################################
#
# Requires: co-expressions
#
############################################################################
procedure patch(from, diff, rev)
local c_diff, c_from, cnte, cnti, i, item, ldr, o
initial {
i := 1
o := 2
if \rev then
i :=: o
c_diff := create !diff
c_from := create !from
cnti := item := 0
ldr := @c_diff
cnte := ldr[i].pos
}
repeat {
while /ldr | cnti < cnte-1 do { # copy old items
cnti +:= 1
if item := @c_from then
suspend item
else {
item := &null
break
}
}
if \ldr then { # still have edits
every 1 to *ldr[i].diffs do { # discard items
cnti +:= 1
@c_from | zot_patch("unexpected end of stream")
}
if *ldr[o].diffs > 0 then # copy new items
suspend !ldr[o].diffs
if ldr := @c_diff then # get next edit
cnte := ldr[i].pos
else
ldr := &null
}
if /item & /ldr then
fail
}
end
procedure zot_patch(msg) # exit w/ message
write(&errout, "patch: ", msg)
exit(1)
end
|