rfcdiff-1.45/0000755000175000017500000000000012676016065012401 5ustar henrikhenrikrfcdiff-1.45/Makefile.common0000644000175000017500000001251712462212375015331 0ustar henrikhenrik# ---------------------------------------------------------------------- # Generic # ---------------------------------------------------------------------- # tool should be set in the tool-specific Makefile, which should include this tool ?= $(shell basename $(PWD)) version := $(shell ./$(tool) --version | awk '{print $$2}' ) thisver := $(version) prevver := $(shell if [ -d ./archive ]; then ls -d ./archive/$(tool)* | grep -v ".tgz" | grep -v "$(version)" | tail -n 1 | sed 's/.*$(tool)-v//'; else echo "0.00"; fi ) language:= $(shell head -1 $(tool) | awk '{ sub("^.+/", "", $$1); print $$1; }') logentry := $(shell sed -n -r "/^$(tool) \($(version).*\)/,/^ -- /p" changelog | head -n -1 | sed -r 's/"/\\"/g' ) # Sources sources += $(tool) copyright control.in changelog todo template.shtml.pyht Makefile ../Makefile.common # Webpages webpages += index.shtml code.shtml copyright.shtml changelog.shtml # Additional scripts scripts += binaries += # Install directory prefix := /usr/local # ---------------------------------------------------------------------- # Set up for make in separate build directory VPATH = archive build # ---------------------------------------------------------------------- # This is what we want to make: all: setup manpage changelog package binaries # ---------------------------------------------------------------------- setup: build archive $(tool)-v0.00 build: [ -d build ] || mkdir build archive: [ -d archive ] || mkdir archive; $(tool)-v0.00: touch archive/$@ # ---------------------------------------------------------------------- manpage: $(tool).1.gz %.1: %.1.txt txt2man $< > $@ %.1: % ./$(tool) --help | txt2man -t "$(tool) 1" > $@ %.gz: % gzip -f $< -c > $@ # ---------------------------------------------------------------------- diff: build/$(tool)-$(version).diff.html build/$(tool)-$(thisver).diff.html: $(tool)-v$(prevver) $(tool) rfcdiff --width 82 $^ $@ # ---------------------------------------------------------------------- binaries: $(binaries) # ---------------------------------------------------------------------- test:: # Test suite # ---------------------------------------------------------------------- package: test archive archive/$(tool)-$(version).tgz archive/$(tool)-v$(version) archive/$(tool)-$(version).tgz: $(sources) control mkdir -p $(tool)-$(version) cp -p $^ $(tool)-$(version)/ tar czf $@ $(tool)-$(version) rm -rf $(tool)-$(version) archive/$(tool)-v$(version): $(tool) cp $< $@ control: control.in $(tool) changelog sed -r -e 's/^Version:.*/Version: $(version)/' -e "s/^Date:.*/Date: $$(date +'%Y-%m-%d %H:%M:%S')/" $< > $@ packagetest: archive/$(tool)-$(version).tgz cd archive && tar xzf archive/$(tool)-$(version).tgz cd archive/$(tool)-$(version)/ && make # ---------------------------------------------------------------------- webpages: $(webpages:%=build/%) build/%.shtml: ./%.shtml.frag control template.shtml.pyht pyht template.shtml.pyht view=$< > $@ build/%.shtml: %.shtml.frag control template.shtml.pyht pyht template.shtml.pyht view=$< > $@ build/%.shtml: build/%.html control template.shtml.pyht pyht template.shtml.pyht view=$< > $@ build/%.shtml: ../%.shtml cp -p $< $@ build/%.html: % rst2html $< > $@ build/code.html: $(tool) highlight --style-infile ../highlight.css --syntax $(language) --include-style --quiet $< > $@ build/about.html: $(tool).1.gz man -l $< | head -n -1 | tail -n +2 | rst2html > $@ build/index.html: $(tool).1.gz man2html -r $< | sed -n -r -e '/

NAME/,/
/p' > $@ build/changelog.html: changelog cat $< | sed -r -e 's!$(tool) *\(([0-9.-]+)\)!`\1 `_ (`diff-\1 `_)!' -e 's/^ --(.*)$$/ (\1)/' > $@.tmp rst2html $@.tmp > $@ # ---------------------------------------------------------------------- build/%.pyht: %.py.frag control template.shtml.pyht pyht template.shtml.pyht view=$< | sed -r -e 's//")\n\t?>/' > $@ # ---------------------------------------------------------------------- commit: diff @if [ ! "$(logentry)" ]; then echo "Missing changelog entry!"; exit 1; fi sed -r -i -e "1,/^ -- /s/([A-Za-z-]+ <[a-z0-9.-]+@[a-z0-9.-]+> ).*$$/\1$$(date +'%d %b %Y %H:%M:%S %z')/" changelog sv commit -m"$(logentry)" [ -d .svn ] && svn commit -m"$(logentry)" || true # ---------------------------------------------------------------------- distinfo: $(tool)-$(version).tgz diff [ -f $@ ] || touch $@ if grep "$<" $@; then echo "Version $(version) has already been uploaded"; exit 1; fi md5sum $< | awk '{ printf "MD5 (%s) = %s\n", $$2, $$1; }' >> $@ sha256sum $< | awk '{ printf "SHA256 (%s) = %s\n", $$2, $$1; }' >> $@ wc -c $< | awk '{ printf "SIZE (%s) = %s\n", $$2, $$1; }' >> $@ release:: $(tool) $(tool)-v$(version) $(tool)-$(version).tgz $(tool)-$(version).diff.html $(scripts) control distinfo echo "Made release $(version)" upload:: $(tool) $(tool)-v$(version) $(webpages) $(tool)-$(version).tgz $(tool)-$(version).diff.html $(scripts) control distinfo rsync -avuz --exclude /tmp/ $^ /www/tools.ietf.org/tools/$(tool)/ toolpush /www/tools.ietf.org/tools/$(tool)/ toolsfeed control changelog /www/tools.ietf.org/tools/atomfeed.xml toolpush /www/tools.ietf.org/tools/atomfeed.xml install:: $(tool) $(tool).1.gz install $(tool) $(prefix)/bin install -m 644 $(tool).1.gz /usr/share/man/man1/ rfcdiff-1.45/control.in0000644000175000017500000000063311203103501014364 0ustar henrikhenrikRepository: rfcdiff Version: 0.10 Section: text Priority: optional Maintainer: Henrik Levkowetz Package: rfcdiff Architecture: any Depends: Category: author Url: http://tools.ietf.org/rfcdiff Ietf: Description: Draft Diff Tool When looking at updated drafts, you want a diff with the previous draft which ignores changing page layout and moved page headers and footers. Get it here. rfcdiff-1.45/rfcdiff.pyht0000644000175000017500000003531512331675453014721 0ustar henrikhenrik 0: uploadsrc2 = form["filename2"].filename elif "url2" in args and type(args["url2"]) is str and len(args["url2"]) > 0: uploadsrc2 = args["url2"] if uploadsrc2.startswith("draft-"): rev_match = re.search("(.*-)([0-9][0-9])(.txt)?$", uploadsrc2) if not rev_match: name_match = re.search("^(.*?)(.txt)?$", uploadsrc2) if name_match: draft = name_match.group(1) try: attrs = attrib.readline("/www/tools.ietf.org/draft/%s/now" % draft) uploadsrc2 = "%s-%s" % (draft, attrs.docrev.string) except: pass uploadsrc2 = "http://tools.ietf.org/id/"+uploadsrc2; if not uploadsrc2.endswith(".txt"): uploadsrc2 += ".txt" else: match = re.search("^[rR][fF][cC] ?([0-9]+)", uploadsrc2) if match: uploadsrc2 = "http://tools.ietf.org/rfc/rfc"+match.group(1)+".txt" else: uploadmsg = "Upload failed - no source file name for file 2." if "filename1" in args or "url1" in args or uploadsrc2: if "filename1" in args and len(args["filename1"]) > 0: uploadsrc1 = form["filename1"].filename elif "url1" in args and type(args["url1"]) is str and len(args["url1"]) > 0: uploadsrc1 = args["url1"] if uploadsrc1.startswith("draft-"): uploadsrc1 = "http://tools.ietf.org/id/"+uploadsrc1; if not uploadsrc1.endswith(".txt"): uploadsrc1 += ".txt" if not uploadsrc2: match = re.match("(.*-)([0-9][0-9])(\..*)", uploadsrc1) if match: rev = int(match.group(2)) uploadsrc2= "%s%02d%s" % (match.group(1), rev+1, match.group(3)) uploadmsg = "" else: match = re.search("^[rR][fF][cC] ?([0-9]+)", uploadsrc1) if match: uploadsrc1 = "http://tools.ietf.org/rfc/rfc"+match.group(1)+".txt" elif uploadsrc2: try: match = re.match("(.*-)([0-9][0-9])(\..*)", uploadsrc2) if match: rev = int(match.group(2)) if rev > 0: uploadsrc1= "%s%02d%s" % (match.group(1), rev-1, match.group(3)) elif rev == 0: match = re.match(".*-(rfc)?([0-9][0-9][0-9]+)bis-.*", uploadsrc2) if match: rfcnum = match.group(2) uploadsrc1 = "http://tools.ietf.org/rfc/rfc%s.txt" % rfcnum else: # Check if this document is a draft which # replaces another... match = re.match(".*/(draft-[^.]*)(\.txt)?", uploadsrc2) if match: draft = match.group(1) if re.search("-[0-9][0-9]$", draft): draft = draft[:-3] try: attrs = attrib.readline("/www/tools.ietf.org/draft/%s/now" % draft) if "docreplaces" in attrs.__dict__: uploadsrc1= "http://tools.ietf.org/id/%s" % attrs.docreplaces except Exception, e: info = str(e) pass match = re.match(".*/([Rr][Ff][Cc])([0-9]+)(\..*)", uploadsrc2) if match: num = int(match.group(2)) if num > 0: try: attrs = attrib.readline("/www/tools.ietf.org/draft/rfc%s/now" % num) if "document" in attrs.__dict__: uploadsrc1= "http://tools.ietf.org/id/%s" % attrs.document except Exception, e: info = str(e) pass except Exception, e: info = str(e) pass if uploadsrc1: uploadname = basename(re.sub("\\\\","/", uploadsrc1)) if re.match("^[a-zA-Z0-9_.,-]*$", uploadname): if uploadsrc1.startswith("http://") or uploadsrc1.startswith("ftp://") or uploadsrc1.startswith("https://"): try: import httplib import urllib2 as urllib uploadfile = urllib.urlopen(uploadsrc1) except: uploadmsg = "Couldn't retrieve file 1 (%s) - please check the URL." % uploadsrc1 if uploadfile and re.search("-[0-9][0-9](\.txt)?$", uploadsrc1) and uploadsrc1 != uploadfile.geturl(): uploadmsg = "Couldn't retrieve file 1 (%s) - got a redirect to '%s' instead." % (uploadsrc1, uploadfile.geturl()) uploadfile = None elif "filename1" in args and form["filename1"].file: uploadfile = form["filename1"].file else: uploadmsg = "Couldn't retrieve file 1 (%s) - unknown URL format." % uploadsrc1 if uploadname and uploadfile: if not hasattr(uploadfile, "info") or uploadfile.info()["content-type"].startswith("text/plain"): uploadname = os.path.join("tmp/1", uploadname) outputfile = open(uploadname, "w") while linecount1 < 32000: # arbitrary number of lines line = uploadfile.readline() if not line: break # try to handle files with mac line endings well: for l in line.rstrip("\n\r").split("\r"): outputfile.write(l.rstrip("\n\r")) outputfile.write("\n") linecount1 += 1 outputfile.close() os.chmod(uploadname, 0666) filename1 = uploadname if not linecount1: uploadmsg = "File 1 seems to be empty" else: uploadmsg = "The mime-type of file 1 is '%s', but 'text/plain' was expected" % uploadfile.info()["content-type"] else: uploadmsg = "Upload aborted, got (%s) but a text file without odd characters in the name is expected here." % uploadname else: uploadmsg = "Upload failed - no source file name for file 1" if uploadsrc2: uploadname = basename(re.sub("\\\\","/", uploadsrc2)) if re.match("^[a-zA-Z0-9_.,-]*$", uploadname): if uploadsrc2.startswith("http://") or uploadsrc2.startswith("ftp://") or uploadsrc2.startswith("https://"): try: import httplib import urllib2 as urllib uploadfile = urllib.urlopen(uploadsrc2) except: uploadmsg = "Couldn't retrieve file 2 (%s) - please check the URL." % uploadsrc2 if uploadfile and re.search("-[0-9][0-9](\.txt)?$", uploadsrc2) and uploadsrc2 != uploadfile.geturl(): uploadmsg = "Couldn't retrieve file 2 (%s) - got a redirect to '%s'." % (uploadsrc2, uploadfile.geturl()) uploadfile = None if uploadsrc2.startswith("http://tools.ietf.org/id/draft-"): # Try to get the document from the master site, instead: uploadsrc2b = uploadsrc2.replace("http://tools.ietf.org/id/", "http://www.ietf.org/internet-drafts/") try: uploadfile = urllib.urlopen(uploadsrc2b) except: pass elif "filename2" in args and form["filename2"].file: uploadfile = form["filename2"].file else: uploadmsg = "Couldn't retrieve file 2 (%s) - unknown URL format." % uploadsrc2 if uploadname and uploadfile: if not hasattr(uploadfile, "info") or uploadfile.info()["content-type"].startswith("text/plain"): uploadname = os.path.join("tmp/2", uploadname) outputfile = open(uploadname, "w") while linecount2 < 32000: line = uploadfile.readline() if not line: break # try to handle files with mac line endings well: for l in line.rstrip("\n\r").split("\r"): outputfile.write(l.rstrip("\n\r")) outputfile.write("\n") linecount2 += 1 outputfile.close() if not linecount2: uploadmsg = "File 2 seems to be empty..." os.chmod(uploadname, 0666) filename2 = uploadname else: uploadmsg = "The mime-type of file 2 is '%s', but 'text/plain' was expected" % uploadfile.info()["content-type"] else: uploadmsg = "Upload aborted, got (%s) but a text file without odd characters in the name is expected here." % uploadname # argument cleaning if "--width" in args and args["--width"].isdigit(): width = "--width "+args["--width"] else: width="" colours = [ "aqua", "black", "blue", "fuchsia", "gray", "green", "lime", "maroon", "navy", "olive", "orange", "purple", "red", "silver", "teal", "white", "yellow"] if "--oldcolour" in args and args["--oldcolour"] in colours: oldcolour = "--oldcolour "+args["--oldcolour"] else: oldcolour = "" if "--newcolour" in args and args["--newcolour"] in colours: newcolour = "--newcolour "+args["--newcolour"] else: newcolour = "" difftypes = ["html", "chbars", "diff", "wdiff", "hwdiff", "abdiff" ] difftype = "" if "difftype" in args: if type(args["difftype"]) == type([]): args["difftype"] = args["difftype"][0] if args["difftype"].lstrip('-') in difftypes: difftype = args["difftype"] if "--larger" in args: larger = "--larger" else: larger = "" if debuginfo: out("\n\n" % (debuginfo.replace('"','\\"'))) if filename1 and filename2 and linecount1 and linecount2: uploadmsg = "Upload complete." if difftype in ("--abdiff", "--chbars"): print("Content-Type: text/plain\n\n") else: print("Content-Type: text/html\n\n") os.system("./rfcdiff --ignore-whitespace --stdout --links %s %s %s %s %s %s %s" % (width, difftype, oldcolour, newcolour, larger, filename1, filename2)) out("" % repr(args)) #os.unlink(uploadname) sys.exit(0) ?> <?python tool ?>

Rfcdiff Tool

Version: 0.11
Author:

Rfcdiff Web Service

File 1 -   Upload file:  
or enter URL or draft name:  
 
File 2 -   Upload file:  
or enter URL or draft name:  
 
Output format: Side-by-side diff
Before-after diff
Changebars
Html wdiff
Html Wdiff Options:
Colour of old text:
Colour of new text:
Larger diff text:
Column width:

You can also use this web-service with an URL query-string of the form:

?url1=http-url-to-doc-1&url2=http-url-to-doc-2

which makes it possible to send around links to diffs between document versions withouth actually generating the diff yourself, as long as the two document versions are available by http.

Example (yes, it is long - no way to get around that... - but you could use tinyurl.com to get a short alias to one of these):

?
  url1=http://tools.ietf.org/id/draft-ietf-atompub-format-10.txt
  &url2=http://tools.ietf.org/id/draft-ietf-atompub-format-11.txt




Generated from PyHt script Latest update: -
alert(\"%s\");" % (uploadmsg+". "+info).replace('"','\\"')) ?>
rfcdiff-1.45/template.shtml.pyht0000644000175000017500000000663011254145052016243 0ustar henrikhenrik <?python Tool ?> Tool

Tool

Version:
Author: -1: email = word.strip("<>").split("@") else: author = author + word + " " out('\n' % (email[0], email[1], author)) ?>
Home | %s | """ % (page, Page)) pages += [ page ] archive = "%s-%s.tgz" % (tool, meta["version"]) if isfile(archive) or isfile("archive/"+archive): out("""Download | """ % archive ) if isfile("distinfo"): out("""Checksums | """ ) ?> | Copyright

filetime(contentfile): content = filetext(contentfile+".html") else: content = filetext(contentfile) if not (re.search("<.*>", content) and re.search("", content)): content = "

%s
" % content else: content = re.sub("(?i)<(!DOCTYPE|/?html|/?body)[^>]*>\n*", "", content) content = re.sub("(?si).*\n*", "", content) ?>

rfcdiff-1.45/changelog0000644000175000017500000003255412676015054014261 0ustar henrikhenrikrfcdiff (1.45) * Added javascript support for moving to next and previous diff chunk with the 'n' and 'p' keys, provided by ekr@rtfm.com. See repository at https://github.com/ekr/rfcdiff . * Applied 2 patches from dev@spiessknafl.at, which fixed a typo and updated the FSF address. -- Henrik Levkowetz 25 Mar 2016 15:37:55 +0100 rfcdiff (1.44) Applied 4 patches from julian.reschke@greenbytes.de, which: * Added stripping of Byte Order Marks (BOMs) * Changed many instances of to instead use id attributes on page content elements * Added fragment links from the page/line position text at the start of each diff block -- Henrik Levkowetz 5 Mar 2016 22:43:00 +0100 rfcdiff (1.43) * Changed the output charset from ISO-8859-1 to UTF-8 -- Henrik Levkowetz 3 Mar 2016 12:02:00 +0100 rfcdiff (1.42) * Removed sudo from the recipe for the Makefile install target * Added a release target and sending of a release mail to the Makefile upload target. * Changed the generation of index.html to use man2html * Changes in rfcdiff.pyht, for the web interface: - Forced links to htmlized documents on tools.ietf.org to use https - Don't refer to (unavailable) python package raw2event in rfcdiff.pyht - Refined code in rfcdiff.pyht to find the latest rev of a draft - Recognize https URL arguments, not just http and ftp - Changed to use urllib2 instead of urllib - Added handling for different line end conventions in rfcdiff.pyht - Improved argument cleaning - Changed default rfcdiff invocation from rfcdiff.pyht to ignore whitespace changes -- Henrik Levkowetz 28 Jan 2015 9:00:27 +0200 rfcdiff (1.41) * Under OS X 10.6.6 (at least), if gawk and nawk are unavailable, earlier versions fails silently. Fail with a meaningful error message instead. -- Henrik Levkowetz 23 Feb 2011 12:40:56 +0200 rfcdiff (1.40) * Changed the rfcdiff.pyht upload script to handle upload files with Mac line-endings (\r). -- Henrik Levkowetz 16 Sep 2010 14:24:00 +0200 rfcdiff (1.39) * New options for diff colours and diff text size for hwdiff, from paul.hoffman@vpnc.org -- Henrik Levkowetz 16 Sep 2010 14:24:00 +0200 rfcdiff (1.38) * Special handling for draft diffs: Make the draft name in the header a link to the text version, and add angle brackets linking to the previous and next diffs. The next diff link is simpleminded; there is no check to see if a later revision actually exists. -- Henrik Levkowetz 02 Feb 2010 17:03:11 +0100 rfcdiff (1.37) * Moved the changelog out of source file and into a proper changelog file. * Refined the regexp identifying RFC page header lines * Use diff -Bd instead of diff -Bwd (don't ignore as much whitespace), important to see differences in ascii figures. * Fixed a problem where < and > strings could be broken up by inserted delete or insert tags. -- Henrik Levkowetz 20 Jan 2010 14:33:24 +0100 rfcdiff (1.36) * The header and footer stripping code in idnits is better than the one used in 1.35. Incorporating that here instead. -- Henrik Levkowetz 04 Jan 2010 14:51:13 +0100 rfcdiff (1.35) * 'tail' doesn't accept a plain '+3' for instance any more. Change to using 'tail -n +3'. -- Henrik Levkowetz 2009-09-12 20:18:51 +0100 rfcdiff (1.34) * Added quotes around file names to be able to handle filenames containing whitespace, and some other changes associated with files containing whitespace and running on *BSD. -- Henrik Levkowetz 2007-07-18 18:39:18 +0100 rfcdiff (1.32) * Changed 'para.' to 'paragraph' in abdiff. Added new regexps for page headers in strip. -- Henrik Levkowetz 2006-06-01 22:54:18 +0100 rfcdiff (1.31) * Fixed a bug where the last diff in --abdiff mode would not be output. Tweaked the regexp which recognizes section headers in abdiff(). -- Henrik Levkowetz 2006-05-12 15:51:03 +0100 rfcdiff (1.30) * Changed -U to -U to work on Macs -- Henrik Levkowetz 2006-05-05 02:24:38 +0100 rfcdiff (1.29) * Added --hwdiff switch, to give single- columnt html output, as in Bill Fenner's htmlwdiff -- Henrik Levkowetz 20 Dec 2005 00:00:00 +0100 rfcdiff (1.28) * Changed font-size units from pt to em. Made white-space ignoring somewhat less aggressive. -- Henrik Levkowetz 20 Dec 2005 00:00:00 +0100 rfcdiff (1.27) * Added -f option to some mv commands to handle read-only input files. Added statistics output. -- Henrik Levkowetz 04 Aug 2005 00:00:00 +0100 rfcdiff (1.26) * Removed spurious empty output line. Added guard against files beginning with "-" for mv. -- Henrik Levkowetz 29 Jul 2005 00:00:00 +0100 rfcdiff (1.25) * Tweaked the regexps for --bodystrip and recognition of wdiff version, both thanks to Bruce Lilly. Tweak to handle directory names with whitespace, thanks to Thomas Morin. -- Henrik Levkowetz 11 Jul 2005 00:00:00 +0100 rfcdiff (1.24) * Changed to use uppercase "-U" option to diff, for MacOS X compatibility. (Thanks to Lars Eggert.) -- Henrik Levkowetz 16 Jun 2005 00:00:00 +0100 rfcdiff (1.23) * Fixed a bug where html entity codes was broken up by diff markup. -- Henrik Levkowetz 24 Jan 2005 00:00:00 +0100 rfcdiff (1.22) * Tweaked a style setting -- Henrik Levkowetz 06 Jan 2005 00:00:00 +0100 rfcdiff (1.21) * Added anchor for each diff, in order for it to be possible to create URLs referring to individual diffs. -- Henrik Levkowetz 10 Dec 2004 00:00:00 +0100 rfcdiff (1.20) * Fixed the same bug again, a bit better this time :-) -- Henrik Levkowetz 09 Dec 2004 00:00:00 +0100 rfcdiff (1.19) * Fixed a bug introduced in v1.18, where lines of diffs with linebreaks would not be shown when using the --width option. -- Henrik Levkowetz 06 Dec 2004 00:00:00 +0100 rfcdiff (1.18) * On some systems, awk is the original Aho, Weinberger, Kernighan awk. We need gawk or at least nawk, so now we look for those. If not found, we try to run with awk anyway, but that will probably not work... Nawk won't accept continuation lines inside strings, so all multiline strings broken up. Also changed the linebreaking and page formatting somewhat. -- Henrik Levkowetz 02 Dec 2004 00:00:00 +0100 rfcdiff (1.17) * Minor bugfix for cygwin - "cd -" was reported not to work; working around that. -- Henrik Levkowetz 16 Nov 2004 00:00:00 +0100 rfcdiff (1.16) * Minor bugfix - properly removing temp outfile when using --stdout -- Henrik Levkowetz 10 Nov 2004 00:00:00 +0100 rfcdiff (1.15) * Improved the page header/footer stripping to handle more cases of paragraphs split over page breaks, and a greater variety of whitespace in the page break. Added some diagnostic information to the generated html diff, in comments. Added --stdout option. -- Henrik Levkowetz 20 Sep 2004 00:00:00 +0100 rfcdiff (1.14) * Cleaned up html in a few places so it's now clean again. -- Henrik Levkowetz 04 Sep 2004 00:00:00 +0100 rfcdiff (1.13) * Tweaked the regexp to match section numbers slightly. Added -wd option to diff also for the ab (rfc-editor before/after) diff. -- Henrik Levkowetz 11 Jun 2004 00:00:00 +0100 rfcdiff (1.12) * Added --abdiff option, to produce OLD/NEW output suitable for the RFC-Editor -- Henrik Levkowetz 07 Jun 2004 00:00:00 +0100 rfcdiff (1.11) * Added --nostrip option. Fixed a bug where a diff on the very first line would not be shown. -- Henrik Levkowetz 03 Apr 2004 00:00:00 +0100 rfcdiff (1.10) * Minor tweaks to handle malformed drafts better. Added firefox to browser list. -- Henrik Levkowetz 17 Mar 2004 00:00:00 +0100 rfcdiff (1.09) * Started work on an Old/New diff mode, suitable for diff summaries to mailing lists, issue trackers, reviewers & rfc-editor. Not complete yet. -- Henrik Levkowetz 23 Feb 2004 00:00:00 +0100 rfcdiff (1.08) * Added --body option to exclude boilerplate and table of contents changes. -- Henrik Levkowetz 22 Feb 2004 00:00:00 +0100 rfcdiff (1.07) * Added diagnostic message when wdiff not found or wdiff version not recognised -- Henrik Levkowetz 21 Feb 2004 00:00:00 +0100 rfcdiff (1.06) * Added --linenum option to provide line numbers on each line. Simplified linebreaking markup. Some mild refactoring. -- Henrik Levkowetz 01 Feb 2004 00:00:00 +0100 rfcdiff (1.05) * Now providing page and line numbers for both old and new document versions at the start of each change section. The line-breaking code is still buggy... -- Henrik Levkowetz 29 Jan 2004 00:00:00 +0100 rfcdiff (1.04) * Added line numbers for the case when no page numbers are available -- Henrik Levkowetz 25 Jan 2004 00:00:00 +0100 rfcdiff (1.03) * Fixed a line coloring bug introduced in v1.02 -- Henrik Levkowetz 24 Jan 2004 00:00:00 +0100 rfcdiff (1.02) * Added line-breaking functionality through the --width option. Experimental -- may be buggy. -- Henrik Levkowetz 22 Jan 2004 00:00:00 +0100 rfcdiff (1.01) * Fixed a bug where diffs with no text occurring after the last change would be shown without the last change. Added some debug functionality to be able to track this one down. -- Henrik Levkowetz 17 Dec 2003 00:00:00 +0100 rfcdiff (1.00) * Bumped version number to 1.00 -- Henrik Levkowetz 14 Dec 2003 00:00:00 +0100 rfcdiff (0.42) * Added html diff output for the identical files case. -- Henrik Levkowetz 6 Dec 2003 00:00:00 +0100 rfcdiff (0.41) * Added --info option -- Henrik Levkowetz 5 Dec 2003 00:00:00 +0100 rfcdiff (0.40) * Added the use of wget (if available) to pull down remote source files (http: or ftp:) -- Henrik Levkowetz 25 Nov 2003 00:00:00 +0100 rfcdiff (0.39) * Added 'End of changes' line at the end of html diff. Added a test on wdiff producing reasonable output with --version option, to avoid old broken wdiff versions. -- Henrik Levkowetz 20 Nov 2003 00:00:00 +0100 rfcdiff (0.38) * Added --keep option, to keep temporary files. -- Henrik Levkowetz 20 Nov 2003 00:00:00 +0100 rfcdiff (0.37) * Added --nowdiff option, to make --html *not* use wdiff even if it is available. -- Henrik Levkowetz 20 Nov 2003 00:00:00 +0100 rfcdiff (0.36) * Added --browse option, to optionally start a browser to show html diff output. Refined how we look for a wdiff binary. -- Henrik Levkowetz 20 Nov 2003 00:00:00 +0100 rfcdiff (0.35) * Minor tweaks to header/footer stripping regexps. Changed color marking of differences. Other minor tweaks and comment updates. -- Henrik Levkowetz 18 Nov 2003 00:00:00 +0100 rfcdiff (0.34) * Removed listing of environment when no files were given on the command line. Added help text. Added the possibility of using wdiff to get the changed words in a change block highlighted. -- Henrik Levkowetz 16 Nov 2003 00:00:00 +0100 rfcdiff (0.33) * Using different dir's for the stripped files, to be able to diff files with the same basename. -- Henrik Levkowetz 23 Oct 2003 00:00:00 +0100 rfcdiff (0.32) * Fixed spurious error message when using --wdiff option -- Henrik Levkowetz 2 Sep 2003 00:00:00 +0100 rfcdiff (0.31) * Not touching the original files, using temporary directory for work files. -- Henrik Levkowetz 1 Sep 2003 00:00:00 +0100 rfcdiff (0.30) * Removed explicit font size for output. Changed regexp for page start (now accepting space in "Internet Draft". -- Henrik Levkowetz 29 Aug 2003 00:00:00 +0100 rfcdiff (0.29) * Added wdiff support -- Henrik Levkowetz 16 Apr 2003 00:00:00 +0100 rfcdiff (0.28) * Added --html, --chbars and --diff switches -- Henrik Levkowetz 6 Mar 2003 00:00:00 +0100 rfcdiff (0.27) * Changed page regexp to accept lowercase 'p'. -- Henrik Levkowetz 3 Mar 2003 00:00:00 +0100 rfcdiff (0.26) * Expanded to provide side-by-side html diff, in addition to changebars in .txt files -- Henrik Levkowetz 2 Feb 2003 00:00:00 +0100 rfcdiff-1.45/control0000644000175000017500000000063312676016065014006 0ustar henrikhenrikRepository: rfcdiff Version: 1.45 Section: text Priority: optional Maintainer: Henrik Levkowetz Package: rfcdiff Architecture: any Depends: Category: author Url: http://tools.ietf.org/rfcdiff Ietf: Description: Draft Diff Tool When looking at updated drafts, you want a diff with the previous draft which ignores changing page layout and moved page headers and footers. Get it here. rfcdiff-1.45/copyright0000644000175000017500000000165612674006773014347 0ustar henrikhenrikrfcdiff is Copyright 2006 Henrik Levkowetz License: This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. On Debian systems, the complete text of the GNU General Public License can be found in '/usr/share/common-licenses/GPL'. rfcdiff-1.45/Makefile0000644000175000017500000000150212676015745014043 0ustar henrikhenrik tool := rfcdiff sources += rfcdiff.pyht rfcdiff.base rfcdiff.js include Makefile.common mlchanges := $(shell sed -n "/^$(tool) ($(version).*)/,/^ -- /p" changelog | awk '{ if (line) print line "\\n"; line=$$0 }' ) # Inline the javascript code from ekr in the distribution binary $(tool): $(tool).base python ekr/merge.py $(tool).base $(tool).js $(tool) upload:: echo -e "\n\ Hi,\n\ \n\ This is an automatic notification about a new $(tool) version, v$(version),\n\ generated when doing 'make upload' for $(tool).\n\ \n\ Release notes:\n\ \n\ $(mlchanges)\n\ \n\ The new version is available for download here:\n\ http://$$(hostname).tools.ietf.org/tools/$(tool)/$(tool)-v$(version)\n\ \n\ Regards,\n\ \n\ Henrik\n\ " | mail -s "New $(tool) release: v$(version)" henrik@levkowetz.com -c hobbes1069@gmail.com rfcdiff-1.45/todo0000644000175000017500000000000011254145026013246 0ustar henrikhenrikrfcdiff-1.45/rfcdiff0000755000175000017500000010644412676016065013743 0ustar henrikhenrik#!/bin/bash # # Synopsis: # Show changes between 2 internet-drafts using changebars or html # side-by-side diff. # # Usage: # rfcdiff [options] file1 file2 # # rfcdiff takes two RFCs or Internet-Drafts in text form as input, and # produces output which indicates the differences found in one of various # forms, controlled by the options listed below. In all cases, page # headers and page footers are stripped before looking for changes. # # --html Produce side-by-side .html diff (default) # # --chbars Produce changebar marked .txt output # # --diff Produce a regular diff output # # --wdiff Produce paged wdiff output # # --hwdiff Produce html-wrapped coloured wdiff output # # --oldcolour COLOURNAME Colour for new file in hwdiff (default is "green") # --oldcolor COLORNAME Color for old file in hwdiff (default is "red") # # --newcolour COLOURNAME Colour for new file in hwdiff (default is "green") # --newcolor COLORNAME Color for new file in hwdiff (default is "green") # # --larger Make difference text in hwdiff slightly larger # # --browse Show html output in browser # # --keep Don't delete temporary workfiles # # --version Show version # # --help Show this help # # --info "Synopsis|Usage|Copyright|Description|Log" # Show various info # # --width N Set a maximum width of N characters for the # display of each half of the old/new html diff # # --linenum Show linenumbers for each line, not only at the # start of each change section # # --body Strip document preamble (title, boilerplate and # table of contents) and postamble (Intellectual # Property Statement, Disclaimer etc) # # --nostrip Don't strip headers and footers (or body) # # --ab-diff Before/After diff, suitable for rfc-editor # --abdiff # # --stdout Send output to stdout instead to a file # # # Copyright: # ----------------------------------------------------------------- # # Copyright 2002 Henrik Levkowetz # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # ----------------------------------------------------------------- # # Description: # # The purpose of this program is to compare two versions of an # internet-draft, and as output produce a diff in one of several # formats: # # - side-by-side html diff # - paged wdiff output in a text terminal # - a text file with changebars in the left margin # - a simple unified diff output # # In all cases, internet-draft headers and footers are stripped before # generating the diff, to produce a cleaner diff. # # It is called as # # rfcdiff first-file second-file # # The latest version is available from # http://tools.ietf.org/tools/rfcdiff/ # export version="1.45" export progdate="" export prelines="10" export basename=$(basename $0) export workdir="/tmp/$basename-$$" export pagecache1="$workdir/pagecache1" export pagecache2="$workdir/pagecache2" # ---------------------------------------------------------------------- # Utility to find an executable # ---------------------------------------------------------------------- lookfor() { for b in "$@"; do found=$(which "$b" 2>/dev/null) if [ -n "$found" ]; then if [ -x "$found" ]; then echo "$found" return fi fi done } AWK=$(lookfor gawk nawk awk) # ---------------------------------------------------------------------- # Strip headers footers and formfeeds from infile to stdout # ---------------------------------------------------------------------- stripbom() { $AWK ' NR==1 { sub(/^\xef\xbb\xbf/,""); } { print ; } ' "$1" } # ---------------------------------------------------------------------- # Strip headers footers and formfeeds from infile to stdout # ---------------------------------------------------------------------- strip() { $AWK ' { gsub(/\r/, ""); } { gsub(/[ \t]+$/, ""); } { pagelength++; } /\[?[Pp]age [0-9ivx]+\]?[ \t\f]*$/ { match($0, /[Pp]age [0-9ivx]+/); num = substr($0, RSTART+5, RLENGTH-5); print num, outline > ENVIRON["pagecache" ENVIRON["which"]] pagelength = 0; } /\f/ { newpage=1; pagelength=1; } /\f$/ { # a form feed followed by a \n does not contribute to the # line count. (But a \f followed by something else does.) pagelength--; } /\f/ { next; } /\[?[Pp]age [0-9ivx]+\]?[ \t\f]*$/ { preindent = indent; next; } /^ *Internet.Draft.+[12][0-9][0-9][0-9] *$/ && (FNR > 15) { newpage=1; next; } /^ *INTERNET.DRAFT.+[12][0-9][0-9][0-9] *$/ && (FNR > 15) { newpage=1; next; } /^ *Draft.+( +)[12][0-9][0-9][0-9] *$/ && (FNR > 15) { newpage=1; next; } /^RFC[ -]?[0-9]+.*( +).* [12][0-9][0-9][0-9]$/ && (FNR > 15) { newpage=1; next; } /^draft-[-a-z0-9_.]+.*[0-9][0-9][0-9][0-9]$/ && (FNR > 15) { newpage=1; next; } /(Jan|Feb|Mar|March|Apr|April|May|Jun|June|Jul|July|Aug|Sep|Oct|Nov|Dec) (19[89][0-9]|20[0-9][0-9]) *$/ && pagelength < 3 { newpage=1; next; } newpage && $0 ~ /^ *draft-[-a-z0-9_.]+ *$/ { newpage=1; next; } /^[ \t]+\[/ { sentence=1; } /[^ \t]/ { indent = match($0, /[^ ]/); if (indent < preindent) { sentence = 1; } if (newpage) { if (sentence) { outline++; print ""; } } else { if (haveblank) { outline++; print ""; } } haveblank=0; sentence=0; newpage=0; line = $0; sub(/^ *\t/, " ", line); thiscolumn = match(line, /[^ ]/); } /[.:][ \t]*$/ { sentence=1; } /\(http:\/\/trustee\.ietf\.org\/license-info\)\./ { sentence=0; } /^[ \t]*$/ { haveblank=1; next; } { outline++; print; } ' "$1" } # ---------------------------------------------------------------------- # Strip preamble (title, boilerplate and table of contents) and # postamble (Intellectual Property Statement, Disclaimer etc) # ---------------------------------------------------------------------- bodystrip() { $AWK ' /^[ \t]*Acknowledgment/ { inbody = 0; } /^(Full )*Copyright Statement$/ { inbody = 0; } /^[ \t]*Disclaimer of Validid/ { inbody = 0; } /^[ \t]*Intellectual Property/ { inbody = 0; } /^Abstract$/ { inbody = 0; } /^Table of Contents$/ { inbody = 0; } /^1.[ \t]*Introduction$/ { inbody = 1; } inbody { print; } ' "$1" } # ---------------------------------------------------------------------- # From two words, find common prefix and differing part, join descriptively # ---------------------------------------------------------------------- worddiff() { $AWK ' BEGIN { w1 = ARGV[1] w2 = ARGV[2] format = ARGV[3] do { if (substr(w1,1,1) == substr(w2,1,1)) { w1 = substr(w1,2) w2 = substr(w2,2) } else { break; } prefixlen++; } while (length(w1) && length(w2)) prefix = substr(ARGV[1],1,prefixlen); do { l1 = length(w1); l2 = length(w2); if (substr(w1,l1,1) == substr(w2,l2,1)) { w1 = substr(w1,1,l1-1) w2 = substr(w2,1,l2-1) } else { break; } } while (l1 && l2) suffix = substr(ARGV[1], prefixlen+length(w1)) printf format, prefix, w1, w2, suffix; } ' "$1" "$2" "$3" } # ---------------------------------------------------------------------- # Generate a html page with side-by-side diff from a unified diff # ---------------------------------------------------------------------- htmldiff() { $AWK ' BEGIN { FS = "[ \t,]"; # Read pagecache1 maxpage[1] = 1 pageend[1,0] = 2; while ( getline < ENVIRON["pagecache1"] > 0) { pageend[1,$1] = $2; if ($1+0 > maxpage[1]) maxpage[1] = $1+0; } # Read pagecache2 maxpage[2] = 1 pageend[2,0] = 2; while ( getline < ENVIRON["pagecache2"] > 0) { pageend[2,$1] = $2; if ($1+0 > maxpage[2]) maxpage[2] = $1+0; } wdiff = ENVIRON["wdiffbin"] base1 = ENVIRON["base1"] base2 = ENVIRON["base2"] optwidth = ENVIRON["optwidth"] optnums = ENVIRON["optnums"] optlinks = ENVIRON["optlinks"] cmdline = ENVIRON["cmdline"] gsub("--", "- -", cmdline) ENVIRON["cmdline"] = cmdline header(base1, base2) difflines1 = 0 difflines2 = 0 } function header(file1, file2) { url1 = file1; url2 = file2; if (optlinks) { if (file1 ~ /^draft-/) { url1 = sprintf("%s", file1, file1); } if (file1 ~ /^draft-/) { prev = sprintf("<", file1); } if (file2 ~ /^draft-/) { url2 = sprintf("%s", file2, file2); } if (file2 ~ /^draft-/) { nxt = sprintf(">", file2) } } printf "" \ " \n" \ " \n" \ "\n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " Diff: %s - %s \n" \ " \n" \ " %s \n" \ " \n" \ " \n" \ " \n" \ " \n" \ "", ENVIRON["version"], ENVIRON["cmdline"], ENVIRON["uname"], ENVIRON["awkbin"], ENVIRON["awkver"], ENVIRON["diffbin"], ENVIRON["diffver"], ENVIRON["wdiffbin"], ENVIRON["wdiffver"], file1, file2, ENVIRON["jsinc"], prev, url1, url2, nxt; } function worddiff(w1, w2) { prefixlen = 0; word1 = w1; do { if (substr(w1,1,1) == substr(w2,1,1)) { w1 = substr(w1,2); w2 = substr(w2,2); } else { break; } prefixlen++; } while (length(w1) && length(w2)); prefix = substr(word1,1,prefixlen); do { l1 = length(w1); l2 = length(w2); if (substr(w1,l1,1) == substr(w2,l2,1)) { w1 = substr(w1,1,l1-1); w2 = substr(w2,1,l2-1); } else { break; } } while (l1 && l2); suffix = substr(word1, prefixlen+length(w1)+1); wordpart[0] = prefix; wordpart[1] = w1; wordpart[2] = w2; wordpart[3] = suffix; } function numdisplay(which, line) { if (optnums && (line != prevline[which])) { prevline[which] = line; return line-1; } return ""; } function fixesc(line) { # Making this a no-op for now -- the change in line-breaking # "
" => "\n" should make this less necessary. # line = gensub(/&(<[^>]*>)/, "\\1\\&", "g", line); # We still have to handle cases where we have a broken up "<" / ">" gsub(/&l<\/span>t;/, "\\<", line); gsub(/&g<\/span>t;/, "\\>", line); gsub(/&amp;/, "\\&", line) gsub(/&amp;/, "\\&", line) gsub(/&lt;/, "\\<", line); gsub(/&gt;/, "\\>", line); gsub(/&lt;/, "\\<", line); gsub(/&gt;/, "\\>", line); gsub(/&l<\/span>t;/, "\\<", line); gsub(/&g<\/span>t;/, "\\>", line); gsub(/&l<\/span>t;/, "\\<", line); gsub(/&g<\/span>t;/, "\\>", line); return line; } function chunkdiff(chunk) { if (difflines1 == 0 && difflines2 == 0) return; chunkfile1= sprintf("1/chunk%04d", chunk); chunkfile2= sprintf("2/chunk%04d", chunk); printf "" > chunkfile1; printf "" > chunkfile2; for (l = 0; l < difflines1; l++) { print stack1[l] >> chunkfile1; } for (l = 0; l < difflines2; l++) { print stack2[l] >> chunkfile2; } close(chunkfile1); close(chunkfile2); cmd1 = sprintf("%s -n -2 -w \"\" -x \"\" %s %s", wdiff, chunkfile1, chunkfile2); cmd2 = sprintf("%s -n -1 -y \"\" -z \"\" %s %s", wdiff, chunkfile1, chunkfile2); l=0; while (cmd1 | getline > 0) { stack1[l] = fixesc($0); l++; } difflines1 = l; l=0; while (cmd2 | getline > 0) { stack2[l] = fixesc($0); l++; } difflines2 = l; close(cmd1); close(cmd2); } function flush() { if (difflines1 || difflines2) { difftag++; multiline = (difflines1 > 1) || (difflines2 > 1); if (multiline && (wdiff != "")) chunkdiff(difftag); printf " \n", difftag; for (l = 0; l < difflines1 || l < difflines2; l++) { if (l in stack1) { line1 = stack1[l]; delete stack1[l]; linenum1++ if (line1 == "") if (optwidth > 0) { line1 = substr(" ",0,optwidth); } else { line1 = " "; } } else { line1 = ""; } if (l in stack2) { line2 = stack2[l]; delete stack2[l]; linenum2++; if (line2 == "") if (optwidth > 0) { line2 = substr(" ",0,optwidth); } else { line2 = " "; } } else { line2 = ""; } if (!multiline || (wdiff == "")) { worddiff(line1, line2); line1 = fixesc(sprintf("%s%s%s", wordpart[0], wordpart[1], wordpart[3])); line2 = fixesc(sprintf("%s%s%s", wordpart[0], wordpart[2], wordpart[3])); # Clean up; remove empty spans sub(/<\/span>/,"", line1); sub(/<\/span>/,"", line2); } left = sprintf("", numdisplay(1, linenum1), line1); right = sprintf("", line2, numdisplay(2, linenum2)); printf " %s%s\n", left, right; } } } function getpage(which, line) { line = line + ENVIRON["prelines"]; page = "?"; for (p=1; p <= maxpage[which]; p++) { if (pageend[which,p] == 0) continue; if (line <= pageend[which,p]) { page = p; break; } } return page; } function getpageline(which, line, page) { if (page == "?") { return line + ENVIRON["prelines"]; } else { if (pageend[which,page-1]+0 != 0) { return line + ENVIRON["prelines"] - pageend[which,page-1] + 3; # numbers of header lines stripped } else { return "?"; } } } function htmlesc(line) { gsub("&", "\\&", line); gsub("<", "\\<", line); gsub(">", "\\>", line); return line; } function expandtabs(line) { spaces = " "; while (pos = index(line, "\t")) { sub("\t", substr(spaces, 0, (8-pos%8)), line); } return line; } function maybebreakline(line, width) { width = optwidth; new = ""; if (width > 0) { line = expandtabs(line); while (length(line) > width) { new = new htmlesc(substr(line, 1, width)) "\n"; line = substr(line, width+1); } } line = new htmlesc(line) ; return line; } /^@@/ { linenum1 = 0 - $2; linenum2 = 0 + $4; diffnum ++; if (linenum1 > 1) { printf " \n"; page1 = getpage(1,linenum1); page2 = getpage(2,linenum2); difflabel = sprintf("part-%s", diffnum); if (page1 == "?") { posinfo1 = sprintf("skipping to change at line %s", difflabel, getpageline(1, linenum1, page1)); } else { posinfo1 = sprintf("skipping to change at page %s, line %s", difflabel, page1, getpageline(1, linenum1, page1)); } if (page2 == "?") { posinfo2 = sprintf("skipping to change at line %s", difflabel, getpageline(2, linenum2, page2)); } else { posinfo2 = sprintf("skipping to change at page %s, line %s", difflabel, page2, getpageline(2, linenum2, page2)); } printf " \n", difflabel, posinfo1, posinfo2; } } /^---/ { next; } /^[+][+][+]/ { next; } /^[ ]/ { line = substr($0, 2); line = maybebreakline(line); flush(); linenum1++; linenum2++; printf " ", numdisplay(1, linenum1), line; printf "\n", line, numdisplay(2, linenum2); diffcount1 += difflines1 difflines1 = 0 diffcount2 += difflines2 difflines2 = 0 } /^-/ { line = substr($0, 2); line = maybebreakline(line); stack1[difflines1] = line; difflines1++; } /^[+]/ { line = substr($0, 2); line = maybebreakline(line); stack2[difflines2] = line; difflines2++; } END { flush(); printf("\n" \ " \n" \ " \n" \ " \n" \ " \n" \ "
%s %s   %s %s
%s%s%s%s
%s %s
%s%s %s%s
 %s. %s change blocks. 
%s lines changed or deleted %s lines changed or added

This html diff was produced by rfcdiff %s. The latest version is available from http://tools.ietf.org/tools/rfcdiff/
\n" \ " \n" \ " \n", diffnum?"End of changes":"No changes", difftag, diffcount1, diffcount2, ENVIRON["version"]); } ' "$1" } # ---------------------------------------------------------------------- # Generate before/after text output from a context diff # ---------------------------------------------------------------------- abdiff() { $AWK ' BEGIN { # Read pagecache1 maxpage[1] = 1 pageend[1,0] = 2; while ( getline < ENVIRON["pagecache1"] > 0) { pageend[1,$1] = $2; if ($1+0 > maxpage[1]) maxpage[1] = $1+0; } # Read pagecache2 maxpage[2] = 1 pageend[2,0] = 2; while ( getline < ENVIRON["pagecache2"] > 0) { pageend[2,$1] = $2; if ($1+0 > maxpage[2]) maxpage[2] = $1+0; } base1 = ENVIRON["base1"] base2 = ENVIRON["base2"] section = "INTRODUCTION"; para = 0; } /^\+\+/ { next; } /^\-\-/ { next; } /^ Appendix ./ { section = $1 " " $2; para = 0; } /^ ? ? ?[0-9]+(\.[0-9]+)*\.? / { section = "Section " $1; para = 0; } /^ ?$/ { if (inpara) { printf "\n%s, paragraph %s:\n", section, para; print "OLD:\n" print oldpara print "NEW:\n" print newpara } oldpara = ""; newpara = ""; para ++; inpara = 0 } /^ ./ { oldpara = oldpara $0 "\n" newpara = newpara $0 "\n" } /^\-/ { sub(/^./, " "); oldpara = oldpara $0 "\n" inpara++; } /^\+/ { sub(/^./, " "); newpara = newpara $0 "\n" inpara++; } END { if (inpara) { printf "\n%s, paragraph %s:\n", section, para; print "OLD:\n" print oldpara print "NEW:\n" print newpara } } ' } # ---------------------------------------------------------------------- # Utility to extract keyword info # ---------------------------------------------------------------------- extract() { $AWK -v keyword="$1" ' BEGIN { # print "Keyword", keyword; } /^# [A-Z]/ { # print "New key", $2; if ($2 == keyword ":" ) { output=1; } else { output=0; } # print "Output", output; } /^#\t/ { # print "Content", output, $0; if ( output ) { sub(/^#/,""); print; } } { next; } ' "$2" } # ---------------------------------------------------------------------- # Utility to start a browser # ---------------------------------------------------------------------- browse() { if [ "$(uname)" = "Darwin" ]; then open "$@" else browser=$(lookfor firefox phoenix MozillaFirebird mozilla opera Netscape netscape dillo) if [ -z "$browser" ]; then echo "Couldn't find any browser, can't display $*." exit 1 fi # make sure file name is absolute if [ "${1#/}" = "$1" ]; then # not absolute path, add pwd arg="file://$PWD/$1" else arg="file://$1" fi # see if a browser is running, act accordingly $browser -remote "ping()" >/dev/null 2>&1 if [ $? -eq 0 ]; then # use running instance $browser -raise -remote "openurl($arg, new-tab)" else # error exit: no running instance echo "Starting web browser." $browser "$arg" >/dev/null 2>&1 & fi fi } # ---------------------------------------------------------------------- # Utility for error exit # ---------------------------------------------------------------------- die() { echo $*; exit 1; } # ---------------------------------------------------------------------- # Process options # ---------------------------------------------------------------------- # Default values opthtml=1; optdiff=0; optchbars=0; optwdiff=0; optshow=0; optnowdiff=0; optkeep=0; optinfo=0; optwidth=0; optnums=0; optbody=0; optabdiff=0; optstrip=1; opthwdiff=0; optlinks=0; optoldcolour="red"; optnewcolour="green"; optlarger="" optstdout=0; while [ $# -gt 0 ]; do case "$1" in --html) opthtml=1; optdiff=0; optchbars=0; optwdiff=0; opthwdiff=0; optabdiff=0;; --diff) opthtml=0; optdiff=1; optchbars=0; optwdiff=0; opthwdiff=0; optabdiff=0;; --chbars) opthtml=0; optdiff=0; optchbars=1; optwdiff=0; opthwdiff=0; optabdiff=0;; --wdiff) opthtml=0; optdiff=0; optchbars=0; optwdiff=1; opthwdiff=0; optabdiff=0;; --hwdiff) opthtml=0; optdiff=0; optchbars=0; optwdiff=0; opthwdiff=1; optabdiff=0;; --changes)opthtml=0; optdiff=0; optchbars=0; optwdiff=0; opthwdiff=0; optabdiff=1;; --abdiff) opthtml=0; optdiff=0; optchbars=0; optwdiff=0; opthwdiff=0; optabdiff=1;; --ab-diff)opthtml=0; optdiff=0; optchbars=0; optwdiff=0; opthwdiff=0; optabdiff=1;; --rfc-editor-diff)opthtml=0; optdiff=0; optchbars=0; optwdiff=0; opthwdiff=0; optabdiff=1;; --version)echo -e "$basename\t$version\t$progdate"; exit 0;; --browse) optshow=1;; --nowdiff)optnowdiff=1;; --keep) optkeep=1;; --info) optinfo=1; keyword=$2; shift;; --help) optinfo=1; keyword="Usage";; --width) optwidth=$2; shift;; --oldcolor) optoldcolour=$2; shift;; --oldcolour) optoldcolour=$2; shift;; --newcolor) optnewcolour=$2; shift;; --newcolour) optnewcolour=$2; shift;; --larger) optlarger='size="+1"';; --linenum)optnums=1;; --body) optbody=1;; --nostrip)optstrip=0; optbody=0;; --stdout) optstdout=1;; --links) optlinks=1;; --no-space-changes) optnospacechange=1;; --ignore-whitespace) optignorewhite=1;; --wdiff-args) optwdiffargs=$2; shift;; --) shift; break;; -v) echo "$basename $version"; exit 0;; -*) echo "Unrecognized option: $1"; exit 1;; *) break;; esac shift done export optwidth export optnums export optlinks # ---------------------------------------------------------------------- # Determine output file name. Maybe output usage and exit. # ---------------------------------------------------------------------- #set -x if [ $optinfo -gt 0 ]; then extract $keyword $0 exit fi if [ $# -ge 2 ]; then if [ "$1" = "$2" ]; then echo "The files are the same file" exit fi export base1=$(basename "$1") export base2=$(basename "$2") outbase=$(worddiff "$base2" "$base1" "%s%s-from-%s") else extract Usage $0 exit 1 fi # ---------------------------------------------------------------------- # create working directory. # ---------------------------------------------------------------------- mkdir $workdir || die "$0: Error: Failed to create temporary directory '$workdir'." mkdir $workdir/1 || die "$0: Error: Failed to create temporary directory '$workdir/1'." mkdir $workdir/2 || die "$0: Error: Failed to create temporary directory '$workdir/2'." # ---------------------------------------------------------------------- # If any of the files is an http or ftp URL we download it, else copy it # ---------------------------------------------------------------------- wgetbin=$(lookfor wget) dowgetarg1=0 dowgetarg2=0 if [ -n "$wgetbin" ]; then if [ "${1#http://}" != "$1" ]; then dowgetarg1=1; fi if [ "${1#ftp://}" != "$1" ]; then dowgetarg1=1; fi if [ "${2#http://}" != "$2" ]; then dowgetarg2=1; fi if [ "${2#ftp://}" != "$2" ]; then dowgetarg2=1; fi fi if [ $dowgetarg1 -gt 0 ]; then $wgetbin -nv "$1" -O $workdir/1/"$base1" else cp "$1" $workdir/1/"$base1" fi if [ $dowgetarg2 -gt 0 ]; then $wgetbin -nv "$2" -O $workdir/2/"$base2" else cp "$2" $workdir/2/"$base2" fi # ---------------------------------------------------------------------- # Remove UTF-8 BOMs # ---------------------------------------------------------------------- stripbom $workdir/1/"$base1" > $workdir/1/"$base1".nobom mv -f $workdir/1/"$base1".nobom $workdir/1/"$base1" stripbom $workdir/2/"$base2" > $workdir/2/"$base2".nobom mv -f $workdir/2/"$base2".nobom $workdir/2/"$base2" # ---------------------------------------------------------------------- # Maybe strip headers/footers from both files # ---------------------------------------------------------------------- if [ $optstrip -gt 0 ]; then export which=1 strip $workdir/1/"$base1" > $workdir/1/"$base1".stripped mv -f $workdir/1/"$base1".stripped $workdir/1/"$base1" export which=2 strip $workdir/2/"$base2" > $workdir/2/"$base2".stripped mv -f $workdir/2/"$base2".stripped $workdir/2/"$base2" fi # ---------------------------------------------------------------------- # Maybe do html quoting # ---------------------------------------------------------------------- if [ $opthwdiff -gt 0 ]; then sed -e 's/&/&/g' -e 's//\>/g' $workdir/1/"$base1" > $workdir/1/"$base1".quoted mv -f $workdir/1/"$base1".quoted $workdir/1/"$base1" sed -e 's/&/&/g' -e 's//\>/g' $workdir/2/"$base2" > $workdir/2/"$base2".quoted mv -f $workdir/2/"$base2".quoted $workdir/2/"$base2" fi # ---------------------------------------------------------------------- # Maybe strip preamble (title, boilerplate and table of contents) and # postamble (Intellectual Property Statement, Disclaimer etc) # ---------------------------------------------------------------------- if [ $optbody -gt 0 ]; then bodystrip $workdir/1/"$base1" > $workdir/1/"$base1".stripped mv $workdir/1/"$base1".stripped $workdir/1/"$base1" bodystrip $workdir/2/"$base2" > $workdir/2/"$base2".stripped mv $workdir/2/"$base2".stripped $workdir/2/"$base2" fi # ---------------------------------------------------------------------- # Get output file name # ---------------------------------------------------------------------- if [ "$3" ]; then outfile="$3" else if [ $opthtml -gt 0 ]; then outfile=./"$outbase".diff.html fi if [ $optchbars -gt 0 ]; then outfile=./"$outbase".chbar fi if [ $optdiff -gt 0 ]; then outfile=./"$outbase".diff fi if [ $optabdiff -gt 0 ]; then outfile=./"$outbase".changes fi if [ $opthwdiff -gt 0 ]; then outfile=./"$outbase".wdiff.html fi fi if [ "$outfile" ]; then tempout=./$(basename "$outfile") fi # ---------------------------------------------------------------------- # Check if we can use wdiff for block diffs # ---------------------------------------------------------------------- if [ $optnowdiff -eq 0 ]; then wdiffbin=$(lookfor wdiff) if [ -n "$wdiffbin" ]; then wdiffver=$($wdiffbin --version 2>/dev/null | egrep "(wdiff|GNU).+[0-9]\.[0-9]") if [ -z "$wdiffver" ]; then wdiffbin=""; echo -en "\n Found wdiff, but it reported no recognisable version." fi else echo -en "\n Couldn't find wdiff." fi if [ -z "$wdiffbin" ]; then echo " Falling back to builtin diff colouring..."; fi export wdiffbin export wdiffver #echo "Found wdiff at $wdiffbin" fi # ---------------------------------------------------------------------- # Get some misc. info # ---------------------------------------------------------------------- uname=$(uname -a) export uname awkbin=$AWK export awkbin awkver=$( { $AWK --version 2>/dev/null || $AWK -V 2>/dev/null; } | head -n 1) export awkver diffbin=$(lookfor diff) export diffbin diffver=$(diff --version | head -n 1) export diffver # ---------------------------------------------------------------------- # Set up the JS code to page through chunks. # ---------------------------------------------------------------------- # If there's a rfcdiff.js script in the current directory, include that # in the output html, otherwise use the inline script expansion below. if [ -e rfcdiff.js ]; then jsinc=" " else jsinc=$(cat <<'ENDOFSCRIPT' ENDOFSCRIPT ) fi export jsinc # ---------------------------------------------------------------------- # Check that we don't have a broken awk # ---------------------------------------------------------------------- if [ $opthtml -gt 0 -a "${uname%% *}" == "Darwin" -a "$awkver" == "awk version 20070501" ]; then echo -e "\n Oops. Awk version 20070501 on OS X doesn't work with rfcdiff's html mode.\n To make rfcdiff work, you could install Gnu Awk (gawk), for instance using\n MacPorts, http://www.macports.org/." exit 1 fi # ---------------------------------------------------------------------- # Do diff # ---------------------------------------------------------------------- origdir=$PWD cd $workdir if cmp 1/"$base1" 2/"$base2" >/dev/null; then echo "" echo "The files are identical." fi if [ $opthtml -gt 0 ]; then diff -Bd ${optnospacechange:+-b} ${optignorewhite:+-w} -U $prelines 1/"$base1" 2/"$base2" | tee $workdir/diff | htmldiff > "$tempout" fi if [ $optchbars -gt 0 ]; then diff -Bwd -U 10000 1/"$base1" 2/"$base2" | tee $workdir/diff | grep -v "^-" | tail -n +3 | sed 's/^+/|/' > "$tempout" fi if [ $optdiff -gt 0 ]; then diff -Bwd -U $prelines 1/"$base1" 2/"$base2" | tee $workdir/diff > "$tempout" fi if [ $optabdiff -gt 0 ]; then diff -wd -U 1000 1/"$base1" 2/"$base2" | tee $workdir/diff | abdiff fi if [ $optwdiff -gt 0 ]; then wdiff -a $optwdiffargs 1/"$base1" 2/"$base2" fi if [ $opthwdiff -gt 0 ]; then echo "wdiff "$base1" "$base2"" > "$tempout" echo "
"								>> "$tempout"
    wdiff -w "" -x ""	\
          -y "" -z ""	\
	  1/"$base1" 2/"$base2"							>> "$tempout"
    echo "
" >> "$tempout" echo "" >> "$tempout" fi if [ $optstdout -gt 0 ]; then cat "$tempout" rm "$tempout" else cd "$origdir"; if [ -f $workdir/"$tempout" ]; then mv $workdir/"$tempout" "$outfile"; fi fi if [ $optshow -gt 0 ]; then browse "$outfile" fi if [ $optkeep -eq 0 ]; then if [ -f $pagecache1 ]; then rm $pagecache1; fi if [ -f $pagecache2 ]; then rm $pagecache2; fi rm -fr $workdir/1 rm -fr $workdir/2 if [ -f $workdir/diff ]; then rm $workdir/diff fi rmdir $workdir else cd /tmp tar czf $basename-$$.tgz $basename-$$ echo " Temporary workfiles have been left in $workdir/, and packed up in $workdir.tgz" fi rfcdiff-1.45/rfcdiff.base0000644000175000017500000010457212676016063014647 0ustar henrikhenrik#!/bin/bash # # Synopsis: # Show changes between 2 internet-drafts using changebars or html # side-by-side diff. # # Usage: # rfcdiff [options] file1 file2 # # rfcdiff takes two RFCs or Internet-Drafts in text form as input, and # produces output which indicates the differences found in one of various # forms, controlled by the options listed below. In all cases, page # headers and page footers are stripped before looking for changes. # # --html Produce side-by-side .html diff (default) # # --chbars Produce changebar marked .txt output # # --diff Produce a regular diff output # # --wdiff Produce paged wdiff output # # --hwdiff Produce html-wrapped coloured wdiff output # # --oldcolour COLOURNAME Colour for new file in hwdiff (default is "green") # --oldcolor COLORNAME Color for old file in hwdiff (default is "red") # # --newcolour COLOURNAME Colour for new file in hwdiff (default is "green") # --newcolor COLORNAME Color for new file in hwdiff (default is "green") # # --larger Make difference text in hwdiff slightly larger # # --browse Show html output in browser # # --keep Don't delete temporary workfiles # # --version Show version # # --help Show this help # # --info "Synopsis|Usage|Copyright|Description|Log" # Show various info # # --width N Set a maximum width of N characters for the # display of each half of the old/new html diff # # --linenum Show linenumbers for each line, not only at the # start of each change section # # --body Strip document preamble (title, boilerplate and # table of contents) and postamble (Intellectual # Property Statement, Disclaimer etc) # # --nostrip Don't strip headers and footers (or body) # # --ab-diff Before/After diff, suitable for rfc-editor # --abdiff # # --stdout Send output to stdout instead to a file # # # Copyright: # ----------------------------------------------------------------- # # Copyright 2002 Henrik Levkowetz # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # ----------------------------------------------------------------- # # Description: # # The purpose of this program is to compare two versions of an # internet-draft, and as output produce a diff in one of several # formats: # # - side-by-side html diff # - paged wdiff output in a text terminal # - a text file with changebars in the left margin # - a simple unified diff output # # In all cases, internet-draft headers and footers are stripped before # generating the diff, to produce a cleaner diff. # # It is called as # # rfcdiff first-file second-file # # The latest version is available from # http://tools.ietf.org/tools/rfcdiff/ # export version="1.45" export progdate="" export prelines="10" export basename=$(basename $0) export workdir="/tmp/$basename-$$" export pagecache1="$workdir/pagecache1" export pagecache2="$workdir/pagecache2" # ---------------------------------------------------------------------- # Utility to find an executable # ---------------------------------------------------------------------- lookfor() { for b in "$@"; do found=$(which "$b" 2>/dev/null) if [ -n "$found" ]; then if [ -x "$found" ]; then echo "$found" return fi fi done } AWK=$(lookfor gawk nawk awk) # ---------------------------------------------------------------------- # Strip headers footers and formfeeds from infile to stdout # ---------------------------------------------------------------------- stripbom() { $AWK ' NR==1 { sub(/^\xef\xbb\xbf/,""); } { print ; } ' "$1" } # ---------------------------------------------------------------------- # Strip headers footers and formfeeds from infile to stdout # ---------------------------------------------------------------------- strip() { $AWK ' { gsub(/\r/, ""); } { gsub(/[ \t]+$/, ""); } { pagelength++; } /\[?[Pp]age [0-9ivx]+\]?[ \t\f]*$/ { match($0, /[Pp]age [0-9ivx]+/); num = substr($0, RSTART+5, RLENGTH-5); print num, outline > ENVIRON["pagecache" ENVIRON["which"]] pagelength = 0; } /\f/ { newpage=1; pagelength=1; } /\f$/ { # a form feed followed by a \n does not contribute to the # line count. (But a \f followed by something else does.) pagelength--; } /\f/ { next; } /\[?[Pp]age [0-9ivx]+\]?[ \t\f]*$/ { preindent = indent; next; } /^ *Internet.Draft.+[12][0-9][0-9][0-9] *$/ && (FNR > 15) { newpage=1; next; } /^ *INTERNET.DRAFT.+[12][0-9][0-9][0-9] *$/ && (FNR > 15) { newpage=1; next; } /^ *Draft.+( +)[12][0-9][0-9][0-9] *$/ && (FNR > 15) { newpage=1; next; } /^RFC[ -]?[0-9]+.*( +).* [12][0-9][0-9][0-9]$/ && (FNR > 15) { newpage=1; next; } /^draft-[-a-z0-9_.]+.*[0-9][0-9][0-9][0-9]$/ && (FNR > 15) { newpage=1; next; } /(Jan|Feb|Mar|March|Apr|April|May|Jun|June|Jul|July|Aug|Sep|Oct|Nov|Dec) (19[89][0-9]|20[0-9][0-9]) *$/ && pagelength < 3 { newpage=1; next; } newpage && $0 ~ /^ *draft-[-a-z0-9_.]+ *$/ { newpage=1; next; } /^[ \t]+\[/ { sentence=1; } /[^ \t]/ { indent = match($0, /[^ ]/); if (indent < preindent) { sentence = 1; } if (newpage) { if (sentence) { outline++; print ""; } } else { if (haveblank) { outline++; print ""; } } haveblank=0; sentence=0; newpage=0; line = $0; sub(/^ *\t/, " ", line); thiscolumn = match(line, /[^ ]/); } /[.:][ \t]*$/ { sentence=1; } /\(http:\/\/trustee\.ietf\.org\/license-info\)\./ { sentence=0; } /^[ \t]*$/ { haveblank=1; next; } { outline++; print; } ' "$1" } # ---------------------------------------------------------------------- # Strip preamble (title, boilerplate and table of contents) and # postamble (Intellectual Property Statement, Disclaimer etc) # ---------------------------------------------------------------------- bodystrip() { $AWK ' /^[ \t]*Acknowledgment/ { inbody = 0; } /^(Full )*Copyright Statement$/ { inbody = 0; } /^[ \t]*Disclaimer of Validid/ { inbody = 0; } /^[ \t]*Intellectual Property/ { inbody = 0; } /^Abstract$/ { inbody = 0; } /^Table of Contents$/ { inbody = 0; } /^1.[ \t]*Introduction$/ { inbody = 1; } inbody { print; } ' "$1" } # ---------------------------------------------------------------------- # From two words, find common prefix and differing part, join descriptively # ---------------------------------------------------------------------- worddiff() { $AWK ' BEGIN { w1 = ARGV[1] w2 = ARGV[2] format = ARGV[3] do { if (substr(w1,1,1) == substr(w2,1,1)) { w1 = substr(w1,2) w2 = substr(w2,2) } else { break; } prefixlen++; } while (length(w1) && length(w2)) prefix = substr(ARGV[1],1,prefixlen); do { l1 = length(w1); l2 = length(w2); if (substr(w1,l1,1) == substr(w2,l2,1)) { w1 = substr(w1,1,l1-1) w2 = substr(w2,1,l2-1) } else { break; } } while (l1 && l2) suffix = substr(ARGV[1], prefixlen+length(w1)) printf format, prefix, w1, w2, suffix; } ' "$1" "$2" "$3" } # ---------------------------------------------------------------------- # Generate a html page with side-by-side diff from a unified diff # ---------------------------------------------------------------------- htmldiff() { $AWK ' BEGIN { FS = "[ \t,]"; # Read pagecache1 maxpage[1] = 1 pageend[1,0] = 2; while ( getline < ENVIRON["pagecache1"] > 0) { pageend[1,$1] = $2; if ($1+0 > maxpage[1]) maxpage[1] = $1+0; } # Read pagecache2 maxpage[2] = 1 pageend[2,0] = 2; while ( getline < ENVIRON["pagecache2"] > 0) { pageend[2,$1] = $2; if ($1+0 > maxpage[2]) maxpage[2] = $1+0; } wdiff = ENVIRON["wdiffbin"] base1 = ENVIRON["base1"] base2 = ENVIRON["base2"] optwidth = ENVIRON["optwidth"] optnums = ENVIRON["optnums"] optlinks = ENVIRON["optlinks"] cmdline = ENVIRON["cmdline"] gsub("--", "- -", cmdline) ENVIRON["cmdline"] = cmdline header(base1, base2) difflines1 = 0 difflines2 = 0 } function header(file1, file2) { url1 = file1; url2 = file2; if (optlinks) { if (file1 ~ /^draft-/) { url1 = sprintf("%s", file1, file1); } if (file1 ~ /^draft-/) { prev = sprintf("<", file1); } if (file2 ~ /^draft-/) { url2 = sprintf("%s", file2, file2); } if (file2 ~ /^draft-/) { nxt = sprintf(">", file2) } } printf "" \ " \n" \ " \n" \ "\n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " Diff: %s - %s \n" \ " \n" \ " %s \n" \ " \n" \ " \n" \ " \n" \ " \n" \ "", ENVIRON["version"], ENVIRON["cmdline"], ENVIRON["uname"], ENVIRON["awkbin"], ENVIRON["awkver"], ENVIRON["diffbin"], ENVIRON["diffver"], ENVIRON["wdiffbin"], ENVIRON["wdiffver"], file1, file2, ENVIRON["jsinc"], prev, url1, url2, nxt; } function worddiff(w1, w2) { prefixlen = 0; word1 = w1; do { if (substr(w1,1,1) == substr(w2,1,1)) { w1 = substr(w1,2); w2 = substr(w2,2); } else { break; } prefixlen++; } while (length(w1) && length(w2)); prefix = substr(word1,1,prefixlen); do { l1 = length(w1); l2 = length(w2); if (substr(w1,l1,1) == substr(w2,l2,1)) { w1 = substr(w1,1,l1-1); w2 = substr(w2,1,l2-1); } else { break; } } while (l1 && l2); suffix = substr(word1, prefixlen+length(w1)+1); wordpart[0] = prefix; wordpart[1] = w1; wordpart[2] = w2; wordpart[3] = suffix; } function numdisplay(which, line) { if (optnums && (line != prevline[which])) { prevline[which] = line; return line-1; } return ""; } function fixesc(line) { # Making this a no-op for now -- the change in line-breaking # "
" => "\n" should make this less necessary. # line = gensub(/&(<[^>]*>)/, "\\1\\&", "g", line); # We still have to handle cases where we have a broken up "<" / ">" gsub(/&l<\/span>t;/, "\\<", line); gsub(/&g<\/span>t;/, "\\>", line); gsub(/&amp;/, "\\&", line) gsub(/&amp;/, "\\&", line) gsub(/&lt;/, "\\<", line); gsub(/&gt;/, "\\>", line); gsub(/&lt;/, "\\<", line); gsub(/&gt;/, "\\>", line); gsub(/&l<\/span>t;/, "\\<", line); gsub(/&g<\/span>t;/, "\\>", line); gsub(/&l<\/span>t;/, "\\<", line); gsub(/&g<\/span>t;/, "\\>", line); return line; } function chunkdiff(chunk) { if (difflines1 == 0 && difflines2 == 0) return; chunkfile1= sprintf("1/chunk%04d", chunk); chunkfile2= sprintf("2/chunk%04d", chunk); printf "" > chunkfile1; printf "" > chunkfile2; for (l = 0; l < difflines1; l++) { print stack1[l] >> chunkfile1; } for (l = 0; l < difflines2; l++) { print stack2[l] >> chunkfile2; } close(chunkfile1); close(chunkfile2); cmd1 = sprintf("%s -n -2 -w \"\" -x \"\" %s %s", wdiff, chunkfile1, chunkfile2); cmd2 = sprintf("%s -n -1 -y \"\" -z \"\" %s %s", wdiff, chunkfile1, chunkfile2); l=0; while (cmd1 | getline > 0) { stack1[l] = fixesc($0); l++; } difflines1 = l; l=0; while (cmd2 | getline > 0) { stack2[l] = fixesc($0); l++; } difflines2 = l; close(cmd1); close(cmd2); } function flush() { if (difflines1 || difflines2) { difftag++; multiline = (difflines1 > 1) || (difflines2 > 1); if (multiline && (wdiff != "")) chunkdiff(difftag); printf " \n", difftag; for (l = 0; l < difflines1 || l < difflines2; l++) { if (l in stack1) { line1 = stack1[l]; delete stack1[l]; linenum1++ if (line1 == "") if (optwidth > 0) { line1 = substr(" ",0,optwidth); } else { line1 = " "; } } else { line1 = ""; } if (l in stack2) { line2 = stack2[l]; delete stack2[l]; linenum2++; if (line2 == "") if (optwidth > 0) { line2 = substr(" ",0,optwidth); } else { line2 = " "; } } else { line2 = ""; } if (!multiline || (wdiff == "")) { worddiff(line1, line2); line1 = fixesc(sprintf("%s%s%s", wordpart[0], wordpart[1], wordpart[3])); line2 = fixesc(sprintf("%s%s%s", wordpart[0], wordpart[2], wordpart[3])); # Clean up; remove empty spans sub(/<\/span>/,"", line1); sub(/<\/span>/,"", line2); } left = sprintf("", numdisplay(1, linenum1), line1); right = sprintf("", line2, numdisplay(2, linenum2)); printf " %s%s\n", left, right; } } } function getpage(which, line) { line = line + ENVIRON["prelines"]; page = "?"; for (p=1; p <= maxpage[which]; p++) { if (pageend[which,p] == 0) continue; if (line <= pageend[which,p]) { page = p; break; } } return page; } function getpageline(which, line, page) { if (page == "?") { return line + ENVIRON["prelines"]; } else { if (pageend[which,page-1]+0 != 0) { return line + ENVIRON["prelines"] - pageend[which,page-1] + 3; # numbers of header lines stripped } else { return "?"; } } } function htmlesc(line) { gsub("&", "\\&", line); gsub("<", "\\<", line); gsub(">", "\\>", line); return line; } function expandtabs(line) { spaces = " "; while (pos = index(line, "\t")) { sub("\t", substr(spaces, 0, (8-pos%8)), line); } return line; } function maybebreakline(line, width) { width = optwidth; new = ""; if (width > 0) { line = expandtabs(line); while (length(line) > width) { new = new htmlesc(substr(line, 1, width)) "\n"; line = substr(line, width+1); } } line = new htmlesc(line) ; return line; } /^@@/ { linenum1 = 0 - $2; linenum2 = 0 + $4; diffnum ++; if (linenum1 > 1) { printf " \n"; page1 = getpage(1,linenum1); page2 = getpage(2,linenum2); difflabel = sprintf("part-%s", diffnum); if (page1 == "?") { posinfo1 = sprintf("skipping to change at line %s", difflabel, getpageline(1, linenum1, page1)); } else { posinfo1 = sprintf("skipping to change at page %s, line %s", difflabel, page1, getpageline(1, linenum1, page1)); } if (page2 == "?") { posinfo2 = sprintf("skipping to change at line %s", difflabel, getpageline(2, linenum2, page2)); } else { posinfo2 = sprintf("skipping to change at page %s, line %s", difflabel, page2, getpageline(2, linenum2, page2)); } printf " \n", difflabel, posinfo1, posinfo2; } } /^---/ { next; } /^[+][+][+]/ { next; } /^[ ]/ { line = substr($0, 2); line = maybebreakline(line); flush(); linenum1++; linenum2++; printf " ", numdisplay(1, linenum1), line; printf "\n", line, numdisplay(2, linenum2); diffcount1 += difflines1 difflines1 = 0 diffcount2 += difflines2 difflines2 = 0 } /^-/ { line = substr($0, 2); line = maybebreakline(line); stack1[difflines1] = line; difflines1++; } /^[+]/ { line = substr($0, 2); line = maybebreakline(line); stack2[difflines2] = line; difflines2++; } END { flush(); printf("\n" \ " \n" \ " \n" \ " \n" \ " \n" \ "
%s %s   %s %s
%s%s%s%s
%s %s
%s%s %s%s
 %s. %s change blocks. 
%s lines changed or deleted %s lines changed or added

This html diff was produced by rfcdiff %s. The latest version is available from http://tools.ietf.org/tools/rfcdiff/
\n" \ " \n" \ " \n", diffnum?"End of changes":"No changes", difftag, diffcount1, diffcount2, ENVIRON["version"]); } ' "$1" } # ---------------------------------------------------------------------- # Generate before/after text output from a context diff # ---------------------------------------------------------------------- abdiff() { $AWK ' BEGIN { # Read pagecache1 maxpage[1] = 1 pageend[1,0] = 2; while ( getline < ENVIRON["pagecache1"] > 0) { pageend[1,$1] = $2; if ($1+0 > maxpage[1]) maxpage[1] = $1+0; } # Read pagecache2 maxpage[2] = 1 pageend[2,0] = 2; while ( getline < ENVIRON["pagecache2"] > 0) { pageend[2,$1] = $2; if ($1+0 > maxpage[2]) maxpage[2] = $1+0; } base1 = ENVIRON["base1"] base2 = ENVIRON["base2"] section = "INTRODUCTION"; para = 0; } /^\+\+/ { next; } /^\-\-/ { next; } /^ Appendix ./ { section = $1 " " $2; para = 0; } /^ ? ? ?[0-9]+(\.[0-9]+)*\.? / { section = "Section " $1; para = 0; } /^ ?$/ { if (inpara) { printf "\n%s, paragraph %s:\n", section, para; print "OLD:\n" print oldpara print "NEW:\n" print newpara } oldpara = ""; newpara = ""; para ++; inpara = 0 } /^ ./ { oldpara = oldpara $0 "\n" newpara = newpara $0 "\n" } /^\-/ { sub(/^./, " "); oldpara = oldpara $0 "\n" inpara++; } /^\+/ { sub(/^./, " "); newpara = newpara $0 "\n" inpara++; } END { if (inpara) { printf "\n%s, paragraph %s:\n", section, para; print "OLD:\n" print oldpara print "NEW:\n" print newpara } } ' } # ---------------------------------------------------------------------- # Utility to extract keyword info # ---------------------------------------------------------------------- extract() { $AWK -v keyword="$1" ' BEGIN { # print "Keyword", keyword; } /^# [A-Z]/ { # print "New key", $2; if ($2 == keyword ":" ) { output=1; } else { output=0; } # print "Output", output; } /^#\t/ { # print "Content", output, $0; if ( output ) { sub(/^#/,""); print; } } { next; } ' "$2" } # ---------------------------------------------------------------------- # Utility to start a browser # ---------------------------------------------------------------------- browse() { if [ "$(uname)" = "Darwin" ]; then open "$@" else browser=$(lookfor firefox phoenix MozillaFirebird mozilla opera Netscape netscape dillo) if [ -z "$browser" ]; then echo "Couldn't find any browser, can't display $*." exit 1 fi # make sure file name is absolute if [ "${1#/}" = "$1" ]; then # not absolute path, add pwd arg="file://$PWD/$1" else arg="file://$1" fi # see if a browser is running, act accordingly $browser -remote "ping()" >/dev/null 2>&1 if [ $? -eq 0 ]; then # use running instance $browser -raise -remote "openurl($arg, new-tab)" else # error exit: no running instance echo "Starting web browser." $browser "$arg" >/dev/null 2>&1 & fi fi } # ---------------------------------------------------------------------- # Utility for error exit # ---------------------------------------------------------------------- die() { echo $*; exit 1; } # ---------------------------------------------------------------------- # Process options # ---------------------------------------------------------------------- # Default values opthtml=1; optdiff=0; optchbars=0; optwdiff=0; optshow=0; optnowdiff=0; optkeep=0; optinfo=0; optwidth=0; optnums=0; optbody=0; optabdiff=0; optstrip=1; opthwdiff=0; optlinks=0; optoldcolour="red"; optnewcolour="green"; optlarger="" optstdout=0; while [ $# -gt 0 ]; do case "$1" in --html) opthtml=1; optdiff=0; optchbars=0; optwdiff=0; opthwdiff=0; optabdiff=0;; --diff) opthtml=0; optdiff=1; optchbars=0; optwdiff=0; opthwdiff=0; optabdiff=0;; --chbars) opthtml=0; optdiff=0; optchbars=1; optwdiff=0; opthwdiff=0; optabdiff=0;; --wdiff) opthtml=0; optdiff=0; optchbars=0; optwdiff=1; opthwdiff=0; optabdiff=0;; --hwdiff) opthtml=0; optdiff=0; optchbars=0; optwdiff=0; opthwdiff=1; optabdiff=0;; --changes)opthtml=0; optdiff=0; optchbars=0; optwdiff=0; opthwdiff=0; optabdiff=1;; --abdiff) opthtml=0; optdiff=0; optchbars=0; optwdiff=0; opthwdiff=0; optabdiff=1;; --ab-diff)opthtml=0; optdiff=0; optchbars=0; optwdiff=0; opthwdiff=0; optabdiff=1;; --rfc-editor-diff)opthtml=0; optdiff=0; optchbars=0; optwdiff=0; opthwdiff=0; optabdiff=1;; --version)echo -e "$basename\t$version\t$progdate"; exit 0;; --browse) optshow=1;; --nowdiff)optnowdiff=1;; --keep) optkeep=1;; --info) optinfo=1; keyword=$2; shift;; --help) optinfo=1; keyword="Usage";; --width) optwidth=$2; shift;; --oldcolor) optoldcolour=$2; shift;; --oldcolour) optoldcolour=$2; shift;; --newcolor) optnewcolour=$2; shift;; --newcolour) optnewcolour=$2; shift;; --larger) optlarger='size="+1"';; --linenum)optnums=1;; --body) optbody=1;; --nostrip)optstrip=0; optbody=0;; --stdout) optstdout=1;; --links) optlinks=1;; --no-space-changes) optnospacechange=1;; --ignore-whitespace) optignorewhite=1;; --wdiff-args) optwdiffargs=$2; shift;; --) shift; break;; -v) echo "$basename $version"; exit 0;; -*) echo "Unrecognized option: $1"; exit 1;; *) break;; esac shift done export optwidth export optnums export optlinks # ---------------------------------------------------------------------- # Determine output file name. Maybe output usage and exit. # ---------------------------------------------------------------------- #set -x if [ $optinfo -gt 0 ]; then extract $keyword $0 exit fi if [ $# -ge 2 ]; then if [ "$1" = "$2" ]; then echo "The files are the same file" exit fi export base1=$(basename "$1") export base2=$(basename "$2") outbase=$(worddiff "$base2" "$base1" "%s%s-from-%s") else extract Usage $0 exit 1 fi # ---------------------------------------------------------------------- # create working directory. # ---------------------------------------------------------------------- mkdir $workdir || die "$0: Error: Failed to create temporary directory '$workdir'." mkdir $workdir/1 || die "$0: Error: Failed to create temporary directory '$workdir/1'." mkdir $workdir/2 || die "$0: Error: Failed to create temporary directory '$workdir/2'." # ---------------------------------------------------------------------- # If any of the files is an http or ftp URL we download it, else copy it # ---------------------------------------------------------------------- wgetbin=$(lookfor wget) dowgetarg1=0 dowgetarg2=0 if [ -n "$wgetbin" ]; then if [ "${1#http://}" != "$1" ]; then dowgetarg1=1; fi if [ "${1#ftp://}" != "$1" ]; then dowgetarg1=1; fi if [ "${2#http://}" != "$2" ]; then dowgetarg2=1; fi if [ "${2#ftp://}" != "$2" ]; then dowgetarg2=1; fi fi if [ $dowgetarg1 -gt 0 ]; then $wgetbin -nv "$1" -O $workdir/1/"$base1" else cp "$1" $workdir/1/"$base1" fi if [ $dowgetarg2 -gt 0 ]; then $wgetbin -nv "$2" -O $workdir/2/"$base2" else cp "$2" $workdir/2/"$base2" fi # ---------------------------------------------------------------------- # Remove UTF-8 BOMs # ---------------------------------------------------------------------- stripbom $workdir/1/"$base1" > $workdir/1/"$base1".nobom mv -f $workdir/1/"$base1".nobom $workdir/1/"$base1" stripbom $workdir/2/"$base2" > $workdir/2/"$base2".nobom mv -f $workdir/2/"$base2".nobom $workdir/2/"$base2" # ---------------------------------------------------------------------- # Maybe strip headers/footers from both files # ---------------------------------------------------------------------- if [ $optstrip -gt 0 ]; then export which=1 strip $workdir/1/"$base1" > $workdir/1/"$base1".stripped mv -f $workdir/1/"$base1".stripped $workdir/1/"$base1" export which=2 strip $workdir/2/"$base2" > $workdir/2/"$base2".stripped mv -f $workdir/2/"$base2".stripped $workdir/2/"$base2" fi # ---------------------------------------------------------------------- # Maybe do html quoting # ---------------------------------------------------------------------- if [ $opthwdiff -gt 0 ]; then sed -e 's/&/&/g' -e 's//\>/g' $workdir/1/"$base1" > $workdir/1/"$base1".quoted mv -f $workdir/1/"$base1".quoted $workdir/1/"$base1" sed -e 's/&/&/g' -e 's//\>/g' $workdir/2/"$base2" > $workdir/2/"$base2".quoted mv -f $workdir/2/"$base2".quoted $workdir/2/"$base2" fi # ---------------------------------------------------------------------- # Maybe strip preamble (title, boilerplate and table of contents) and # postamble (Intellectual Property Statement, Disclaimer etc) # ---------------------------------------------------------------------- if [ $optbody -gt 0 ]; then bodystrip $workdir/1/"$base1" > $workdir/1/"$base1".stripped mv $workdir/1/"$base1".stripped $workdir/1/"$base1" bodystrip $workdir/2/"$base2" > $workdir/2/"$base2".stripped mv $workdir/2/"$base2".stripped $workdir/2/"$base2" fi # ---------------------------------------------------------------------- # Get output file name # ---------------------------------------------------------------------- if [ "$3" ]; then outfile="$3" else if [ $opthtml -gt 0 ]; then outfile=./"$outbase".diff.html fi if [ $optchbars -gt 0 ]; then outfile=./"$outbase".chbar fi if [ $optdiff -gt 0 ]; then outfile=./"$outbase".diff fi if [ $optabdiff -gt 0 ]; then outfile=./"$outbase".changes fi if [ $opthwdiff -gt 0 ]; then outfile=./"$outbase".wdiff.html fi fi if [ "$outfile" ]; then tempout=./$(basename "$outfile") fi # ---------------------------------------------------------------------- # Check if we can use wdiff for block diffs # ---------------------------------------------------------------------- if [ $optnowdiff -eq 0 ]; then wdiffbin=$(lookfor wdiff) if [ -n "$wdiffbin" ]; then wdiffver=$($wdiffbin --version 2>/dev/null | egrep "(wdiff|GNU).+[0-9]\.[0-9]") if [ -z "$wdiffver" ]; then wdiffbin=""; echo -en "\n Found wdiff, but it reported no recognisable version." fi else echo -en "\n Couldn't find wdiff." fi if [ -z "$wdiffbin" ]; then echo " Falling back to builtin diff colouring..."; fi export wdiffbin export wdiffver #echo "Found wdiff at $wdiffbin" fi # ---------------------------------------------------------------------- # Get some misc. info # ---------------------------------------------------------------------- uname=$(uname -a) export uname awkbin=$AWK export awkbin awkver=$( { $AWK --version 2>/dev/null || $AWK -V 2>/dev/null; } | head -n 1) export awkver diffbin=$(lookfor diff) export diffbin diffver=$(diff --version | head -n 1) export diffver # ---------------------------------------------------------------------- # Set up the JS code to page through chunks. # ---------------------------------------------------------------------- # If there's a rfcdiff.js script in the current directory, include that # in the output html, otherwise use the inline script expansion below. if [ -e rfcdiff.js ]; then jsinc=" " else jsinc=$(cat <<'ENDOFSCRIPT' ENDOFSCRIPT ) fi export jsinc # ---------------------------------------------------------------------- # Check that we don't have a broken awk # ---------------------------------------------------------------------- if [ $opthtml -gt 0 -a "${uname%% *}" == "Darwin" -a "$awkver" == "awk version 20070501" ]; then echo -e "\n Oops. Awk version 20070501 on OS X doesn't work with rfcdiff's html mode.\n To make rfcdiff work, you could install Gnu Awk (gawk), for instance using\n MacPorts, http://www.macports.org/." exit 1 fi # ---------------------------------------------------------------------- # Do diff # ---------------------------------------------------------------------- origdir=$PWD cd $workdir if cmp 1/"$base1" 2/"$base2" >/dev/null; then echo "" echo "The files are identical." fi if [ $opthtml -gt 0 ]; then diff -Bd ${optnospacechange:+-b} ${optignorewhite:+-w} -U $prelines 1/"$base1" 2/"$base2" | tee $workdir/diff | htmldiff > "$tempout" fi if [ $optchbars -gt 0 ]; then diff -Bwd -U 10000 1/"$base1" 2/"$base2" | tee $workdir/diff | grep -v "^-" | tail -n +3 | sed 's/^+/|/' > "$tempout" fi if [ $optdiff -gt 0 ]; then diff -Bwd -U $prelines 1/"$base1" 2/"$base2" | tee $workdir/diff > "$tempout" fi if [ $optabdiff -gt 0 ]; then diff -wd -U 1000 1/"$base1" 2/"$base2" | tee $workdir/diff | abdiff fi if [ $optwdiff -gt 0 ]; then wdiff -a $optwdiffargs 1/"$base1" 2/"$base2" fi if [ $opthwdiff -gt 0 ]; then echo "wdiff "$base1" "$base2"" > "$tempout" echo "
"								>> "$tempout"
    wdiff -w "" -x ""	\
          -y "" -z ""	\
	  1/"$base1" 2/"$base2"							>> "$tempout"
    echo "
" >> "$tempout" echo "" >> "$tempout" fi if [ $optstdout -gt 0 ]; then cat "$tempout" rm "$tempout" else cd "$origdir"; if [ -f $workdir/"$tempout" ]; then mv $workdir/"$tempout" "$outfile"; fi fi if [ $optshow -gt 0 ]; then browse "$outfile" fi if [ $optkeep -eq 0 ]; then if [ -f $pagecache1 ]; then rm $pagecache1; fi if [ -f $pagecache2 ]; then rm $pagecache2; fi rm -fr $workdir/1 rm -fr $workdir/2 if [ -f $workdir/diff ]; then rm $workdir/diff fi rmdir $workdir else cd /tmp tar czf $basename-$$.tgz $basename-$$ echo " Temporary workfiles have been left in $workdir/, and packed up in $workdir.tgz" fi rfcdiff-1.45/rfcdiff.js0000644000175000017500000000166412676012572014350 0ustar henrikhenrikvar chunk_index = 0; var old_chunk = null; function format_chunk(index) { var prefix = "diff"; var str = index.toString(); for (x=0; x<(4-str.length); ++x) { prefix+='0'; } return prefix + str; } function find_chunk(n){ return document.querySelector('tr[id$="' + n + '"]'); } function change_chunk(offset) { var index = chunk_index + offset; var new_str; var new_chunk; new_str = format_chunk(index); new_chunk = find_chunk(new_str); if (!new_chunk) { return; } if (old_chunk) { old_chunk.style.outline = ""; } old_chunk = new_chunk; old_chunk.style.outline = "1px solid red"; window.location.hash = "#" + new_str; window.scrollBy(0,-100); chunk_index = index; } document.onkeydown = function(e) { switch (e.keyCode) { case 78: change_chunk(1); break; case 80: change_chunk(-1); break; } };