home *** CD-ROM | disk | FTP | other *** search
- ############################################################################
- #
- # File: patchu.icn
- #
- # Subject: Program to implement UNIX-like patch
- #
- # Author: Rich Morin
- #
- # Date: June 18, 1990
- #
- ###########################################################################
- #
- # 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
-