#!/usr/bin/ksh -p # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # ident "%Z%%M% %I% %E% SMI" # # Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # This script takes a file list and a workspace and builds a set of html files # suitable for doing a code review of source changes via a web page. # Documentation is available via the manual page, webrev.1, or just # type 'webrev -h'. # # Acknowledgements to contributors to webrev are listed in the webrev(1) # man page. # # # The following variable is set to SCCS delta date 20YY/MM/DD. # Note this will have to be changed in 2100 or when SCCS has support for # 4 digit years; whichever is the sooner! # WEBREV_UPDATED=20%E% REMOVED_COLOR=brown CHANGED_COLOR=blue NEW_COLOR=blue HTML=' \n' FRAMEHTML=' \n' STDHEAD=' ' # # UDiffs need a slightly different CSS rule for 'new' items (we don't # want them to be bolded as we do in cdiffs or sdiffs). # UDIFFCSS=' ' # # input_cmd | html_quote | output_cmd # or # html_quote filename | output_cmd # # Make a piece of source code safe for display in an HTML
 block.
#
html_quote()
{
	sed -e "s/&/\&/g" -e "s//\>/g" "$@" | expand
}

#
# input_cmd | bug2url | output_cmd
#
# Scan for bugids and insert  links to the relevent bug database.
#
bug2url()
{
	sed -e 's|[0-9]\{5,\}|&|g'
}

#
# input_cmd | sac2url | output_cmd
#
# Scan for ARC cases and insert  links to the relevent SAC database.
# This is slightly complicated because inside the SWAN, SAC cases are
# grouped by ARC: PSARC/2006/123.  But on OpenSolaris.org, they are
# referenced as 2006/123 (without labelling the ARC).
#
sac2url()
{
	if [[ -z $Oflag ]]; then
	    sed -e 's|\([A-Z]\{1,2\}ARC\)[ /]\([0-9]\{4\}\)/\([0-9]\{3\}\)|\1 \2/\3|g'
	else
	    sed -e 's|\([A-Z]\{1,2\}ARC\)[ /]\([0-9]\{4\}\)/\([0-9]\{3\}\)|\1 \2/\3|g'
	fi
}

#
# strip_unchanged  | output_cmd
#
# Removes chunks of sdiff documents that have not changed. This makes it
# easier for a code reviewer to find the bits that have changed.
#
# Deleted lines of text are replaced by a horizontal rule. Some
# identical lines are retained before and after the changed lines to
# provide some context.  The number of these lines is controlled by the
# variable C in the nawk script below.
#
# The script detects changed lines as any line that has a "
"
				inx = c % C
				c = C
			}

			for (i = 0; i < c; i++)
				print ln[(inx + i) % C]
		}
		c = 0;
		print
		next
	}
	{	if (c >= C) {
			ln[c % C] = $0
			c++;
			next;
		}
		c++;
		print
	}
	END	{ if (c > (C * 2)) print "\n

" } ' $1 } # # sdiff_to_html # # This function takes two files as arguments, obtains their diff, and # processes the diff output to present the files as an HTML document with # the files displayed side-by-side, differences shown in color. It also # takes a delta comment, rendered as an HTML snippet, as the third # argument. The function takes two files as arguments, then the name of # file, the path, and the comment. The HTML will be delivered on stdout, # e.g. # # $ sdiff_to_html old/usr/src/tools/scripts/webrev.sh \ # new/usr/src/tools/scripts/webrev.sh \ # webrev.sh usr/src/tools/scripts \ # ' # 1234567 my bugid' > .html # # framed_sdiff() is then called which creates $2.frames.html # in the webrev tree. # # FYI: This function is rather unusual in its use of awk. The initial # diff run produces conventional diff output showing changed lines mixed # with editing codes. The changed lines are ignored - we're interested in # the editing codes, e.g. # # 8c8 # 57a61 # 63c66,76 # 68,93d80 # 106d90 # 108,110d91 # # These editing codes are parsed by the awk script and used to generate # another awk script that generates HTML, e.g the above lines would turn # into something like this: # # BEGIN { printf "
\n" }
#      function sp(n) {for (i=0;i%4d %s \n", n, NR, $0}
#      NR==8           {wl("#7A7ADD");next}
#      NR==54          {wl("#7A7ADD");sp(3);next}
#      NR==56          {wl("#7A7ADD");next}
#      NR==57          {wl("black");printf "\n"; next}
#        :               :
#
#  This script is then run on the original source file to generate the
#  HTML that corresponds to the source file.
#
#  The two HTML files are then combined into a single piece of HTML that
#  uses an HTML table construct to present the files side by side.  You'll
#  notice that the changes are color-coded:
#
#   black     - unchanged lines
#   blue      - changed lines
#   bold blue - new lines
#   brown     - deleted lines
#
#  Blank lines are inserted in each file to keep unchanged lines in sync
#  (side-by-side).  This format is familiar to users of sdiff(1) or
#  Teamware's filemerge tool.
#
sdiff_to_html()
{
	diff -b $1 $2 > /tmp/$$.diffs

	TNAME=$3
	TPATH=$4
	COMMENT=$5

	#
	#  Now we have the diffs, generate the HTML for the old file.
	#
	nawk '
	BEGIN	{
		printf "function sp(n) {for (i=0;i%%4d %%s\\n\", NR, $0}\n"
		printf "function changed() "
		printf "{printf \"%%4d %%s\\n\", NR, $0}\n"
		printf "function bl() {printf \"%%4d %%s\\n\", NR, $0}\n"
}
	/^/	{next}
	/^---/	{next}

	{
	split($1, a, /[cad]/) ;
	if (index($1, "a")) {
		if (a[1] == 0) {
			n = split(a[2], r, /,/);
			if (n == 1)
				printf "BEGIN\t\t{sp(1)}\n"
			else
				printf "BEGIN\t\t{sp(%d)}\n",\
				(r[2] - r[1]) + 1
			next
		}

		printf "NR==%s\t\t{", a[1]
		n = split(a[2], r, /,/);
		s = r[1];
		if (n == 1)
			printf "bl();printf \"\\n\"; next}\n"
		else {
			n = r[2] - r[1]
			printf "bl();sp(%d);next}\n",\
			(r[2] - r[1]) + 1
		}
		next
	}
	if (index($1, "d")) {
		n = split(a[1], r, /,/);
		n1 = r[1]
		n2 = r[2]
		if (n == 1)
			printf "NR==%s\t\t{removed(); next}\n" , n1
		else
			printf "NR==%s,NR==%s\t{removed(); next}\n" , n1, n2
		next
	}
	if (index($1, "c")) {
		n = split(a[1], r, /,/);
		n1 = r[1]
		n2 = r[2]
		final = n2
		d1 = 0
		if (n == 1)
			printf "NR==%s\t\t{changed();" , n1
		else {
			d1 = n2 - n1
			printf "NR==%s,NR==%s\t{changed();" , n1, n2
		}
		m = split(a[2], r, /,/);
		n1 = r[1]
		n2 = r[2]
		if (m > 1) {
			d2  = n2 - n1
			if (d2 > d1) {
				if (n > 1) printf "if (NR==%d)", final
				printf "sp(%d);", d2 - d1
			}
		}
		printf "next}\n" ;

		next
	}
	}

	END	{ printf "{printf \"%%4d %%s\\n\", NR, $0 }\n" }
	' /tmp/$$.diffs > /tmp/$$.file1

	#
	#  Now generate the HTML for the new file
	#
	nawk '
	BEGIN	{
		printf "function sp(n) {for (i=0;i%%4d %%s\\n\", NR, $0}\n"
		printf "function changed() "
		printf "{printf \"%%4d %%s\\n\", NR, $0}\n"
		printf "function bl() {printf \"%%4d %%s\\n\", NR, $0}\n"
	}

	/^/	{next}
	/^---/	{next}

	{
	split($1, a, /[cad]/) ;
	if (index($1, "d")) {
		if (a[2] == 0) {
			n = split(a[1], r, /,/);
			if (n == 1)
				printf "BEGIN\t\t{sp(1)}\n"
			else
				printf "BEGIN\t\t{sp(%d)}\n",\
				(r[2] - r[1]) + 1
			next
		}

		printf "NR==%s\t\t{", a[2]
		n = split(a[1], r, /,/);
		s = r[1];
		if (n == 1)
			printf "bl();printf \"\\n\"; next}\n"
		else {
			n = r[2] - r[1]
			printf "bl();sp(%d);next}\n",\
			(r[2] - r[1]) + 1
		}
		next
	}
	if (index($1, "a")) {
		n = split(a[2], r, /,/);
		n1 = r[1]
		n2 = r[2]
		if (n == 1)
			printf "NR==%s\t\t{new() ; next}\n" , n1
		else
			printf "NR==%s,NR==%s\t{new() ; next}\n" , n1, n2
		next
	}
	if (index($1, "c")) {
		n = split(a[2], r, /,/);
		n1 = r[1]
		n2 = r[2]
		final = n2
		d2 = 0;
		if (n == 1) {
			final = n1
			printf "NR==%s\t\t{changed();" , n1
		} else {
			d2 = n2 - n1
			printf "NR==%s,NR==%s\t{changed();" , n1, n2
		}
		m = split(a[1], r, /,/);
		n1 = r[1]
		n2 = r[2]
		if (m > 1) {
			d1  = n2 - n1
			if (d1 > d2) {
				if (n > 1) printf "if (NR==%d)", final
				printf "sp(%d);", d1 - d2
			}
		}
		printf "next}\n" ;
		next
	}
	}
	END	{ printf "{printf \"%%4d %%s\\n\", NR, $0 }\n" }
	' /tmp/$$.diffs > /tmp/$$.file2

	#
	# Post-process the HTML files by running them back through nawk
	#
	html_quote < $1 | nawk -f /tmp/$$.file1 > /tmp/$$.file1.html

	html_quote < $2 | nawk -f /tmp/$$.file2 > /tmp/$$.file2.html

	#
	# Now combine into a valid HTML file and side-by-side into a table
	#
	print "$HTML$STDHEAD"
	print "$WNAME Sdiff $TPATH "
	print ""
        print "Print this page"
	print "
$COMMENT
\n" print "" print "" print "
"

	strip_unchanged /tmp/$$.file1.html

	print "
"

	strip_unchanged /tmp/$$.file2.html

	print "
" print "" framed_sdiff $TNAME $TPATH /tmp/$$.file1.html /tmp/$$.file2.html \ "$COMMENT" } # # framed_sdiff # # Expects lefthand and righthand side html files created by sdiff_to_html. # We use insert_anchors() to augment those with HTML navigation anchors, # and then emit the main frame. Content is placed into: # # $WDIR/DIR/$TNAME.lhs.html # $WDIR/DIR/$TNAME.rhs.html # $WDIR/DIR/$TNAME.frames.html # # NOTE: We rely on standard usage of $WDIR and $DIR. # function framed_sdiff { typeset TNAME=$1 typeset TPATH=$2 typeset lhsfile=$3 typeset rhsfile=$4 typeset comments=$5 typeset RTOP # Enable html files to access WDIR via a relative path. RTOP=$(relative_dir $TPATH $WDIR) # Make the rhs/lhs files and output the frameset file. print "$HTML$STDHEAD" > $WDIR/$DIR/$TNAME.lhs.html cat >> $WDIR/$DIR/$TNAME.lhs.html <<-EOF