home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.cs.arizona.edu
/
ftp.cs.arizona.edu.tar
/
ftp.cs.arizona.edu
/
icon
/
historic
/
v941.tgz
/
icon.v941src.tar
/
icon.v941src
/
ipl
/
progs
/
patchu.icn
< prev
next >
Wrap
Text File
|
2000-07-29
|
4KB
|
154 lines
############################################################################
#
# File: patchu.icn
#
# Subject: Program to implement UNIX-like patch
#
# Author: Rich Morin
#
# Date: June 18, 1990
#
############################################################################
#
# This file is in the public domain.
#
############################################################################
#
# This program reads a source file and a diff file, producing an
# updated file. The diff file may be generated by the UNIX diff(1)
# utility, or by diffu.icn, which uses dif.icn for the hard work.
#
# The original patch(1) utility, written by Larry Wall, is widely
# used in the UNIX community.
#
# The diff file contains edit lines, separators, and text lines.
# Edit lines may take the forms:
#
# #a#[,#] <- add lines
# #[,#]c#[,#] <- change lines
# #[,#]d# <- delete lines
#
# Change lines contain only the string "---". All other lines are
# text lines. See diff(1) in any UNIX manual for more details.
#
############################################################################
#
# Requires: co-expressions
#
############################################################################
#
# Links: options, patch
#
############################################################################
link options, patch
record diff_rec(pos, diffs)
global n1, n2, n3, n4
procedure main(arg)
local t, rev, source, dfile, diffs
t := options(arg, "r")
rev := t["r"]
if *arg ~= 2 then
zot("usage: patchu source diffs")
source := open(arg[1]) | zot("cannot open " || arg[1])
dfile := open(arg[2]) | zot("cannot open " || arg[2])
# every write(patch(source, get_diff(dfile))) # ? shouldn't need diffs ?
diffs := []
every put(diffs, get_diff(dfile))
every write(patch(source, diffs, rev))
end
procedure get_diff(dfile) # get diff record
local ef, i1, i2, l1, l2, i, line
repeat {
if ef := get_edit(dfile) then {
# write(">>> ",n1,", ",n2,", ",ef,", ",n3,", ",n4)
if ef == "a" then i1 := n1+1 else i1 := n1
if ef == "d" then i2 := n3+1 else i2 := n3
l1 := []
l2 := []
if ef == !"cd" then {
every i := n1 to n2 do {
line := !dfile | zot("unexpected end of edit data(1)")
if line[1:3] ~== "< " then
zot("bad edit data(1): " || line)
put(l1, line[3:0])
}
}
if ef == "c" then {
line := !dfile | zot("unexpected end of edit data(2)")
if line ~== "---" then
zot("bad edit data(2): " || line)
}
if ef == !"ac" then {
every i := n3 to n4 do {
line := !dfile | zot("unexpected end of edit data(3)")
if line[1:3] ~== "> " then
zot("bad edit data(3): " || line)
put(l2, line[3:0])
}
}
suspend [diff_rec(i1,l1), diff_rec(i2,l2)]
}
else
fail
}
end
procedure get_edit(dfile) # get edit parameters
local edit, i1, i2, ef, i3, i4
edit := !dfile | fail
i1 := i2 := many(&digits, edit) | zot("bad edit spec(1): " || edit)
n1 := n2 := edit[1:i1]
if edit[i1] == "," then {
i2 := many(&digits, edit, i1+1) | zot("bad edit spec(2): " || edit)
n2 := edit[i1+1:i2]
}
if edit[i2] == !"acd" then {
ef := edit[i2]
i3 := i4 := many(&digits, edit, i2+1) | zot("bad edit spec(3): " || edit)
n3 := n4 := edit[i2+1:i3]
if edit[i3] == "," then {
i4 := many(&digits, edit, i3+1) | zot("bad edit spec(4): " || edit)
n4 := edit[i3+1:i4]
}
}
else
zot("bad edit spec(5): " || edit)
if i4 ~= *edit+1 then
zot("bad edit spec(6): " || edit)
if not 0 <= n3 <= n4 then
zot("bad edit spec(7): " || edit)
if not 0 <= n1 <= n2 then
zot("bad edit spec(8): " || edit)
return ef
end
procedure zot(msg) # exit w/message
write(&errout, "patchu: " || msg)
exit(1)
end