xref: /titanic_52/usr/src/tools/scripts/webrev.sh (revision cac38512af2b196c3d8b0bf4ab71e6a49bff1c22)
17c478bd9Sstevel@tonic-gate#!/usr/bin/ksh -p
27c478bd9Sstevel@tonic-gate#
37c478bd9Sstevel@tonic-gate# CDDL HEADER START
47c478bd9Sstevel@tonic-gate#
57c478bd9Sstevel@tonic-gate# The contents of this file are subject to the terms of the
6daaffb31Sdp# Common Development and Distribution License (the "License").
7daaffb31Sdp# You may not use this file except in compliance with the License.
87c478bd9Sstevel@tonic-gate#
97c478bd9Sstevel@tonic-gate# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate# or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate# See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate# and limitations under the License.
137c478bd9Sstevel@tonic-gate#
147c478bd9Sstevel@tonic-gate# When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate# If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate# fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate# information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate#
207c478bd9Sstevel@tonic-gate# CDDL HEADER END
217c478bd9Sstevel@tonic-gate#
227c478bd9Sstevel@tonic-gate#
237c478bd9Sstevel@tonic-gate# ident	"%Z%%M%	%I%	%E% SMI"
247c478bd9Sstevel@tonic-gate#
25*cac38512Smjnelson# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
267c478bd9Sstevel@tonic-gate# Use is subject to license terms.
277c478bd9Sstevel@tonic-gate#
28daaffb31Sdp# This script takes a file list and a workspace and builds a set of html files
29daaffb31Sdp# suitable for doing a code review of source changes via a web page.
30daaffb31Sdp# Documentation is available via the manual page, webrev.1, or just
31daaffb31Sdp# type 'webrev -h'.
327c478bd9Sstevel@tonic-gate#
33daaffb31Sdp# Acknowledgements to contributors to webrev are listed in the webrev(1)
34daaffb31Sdp# man page.
357c478bd9Sstevel@tonic-gate#
36daaffb31Sdp
377c478bd9Sstevel@tonic-gate#
38daaffb31Sdp# The following variable is set to SCCS delta date 20YY/MM/DD.
397c478bd9Sstevel@tonic-gate# Note this will have to be changed in 2100 or when SCCS has support for
407c478bd9Sstevel@tonic-gate# 4 digit years; whichever is the sooner!
417c478bd9Sstevel@tonic-gate#
427c478bd9Sstevel@tonic-gateWEBREV_UPDATED=20%E%
437c478bd9Sstevel@tonic-gate
447c478bd9Sstevel@tonic-gateREMOVED_COLOR=brown
457c478bd9Sstevel@tonic-gateCHANGED_COLOR=blue
467c478bd9Sstevel@tonic-gateNEW_COLOR=blue
477c478bd9Sstevel@tonic-gate
48daaffb31SdpHTML='<?xml version="1.0"?>
49daaffb31Sdp<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
50daaffb31Sdp    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
51daaffb31Sdp<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">\n'
52daaffb31Sdp
53daaffb31SdpFRAMEHTML='<?xml version="1.0"?>
54daaffb31Sdp<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"
55daaffb31Sdp    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
56daaffb31Sdp<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">\n'
57daaffb31Sdp
58*cac38512SmjnelsonSTDHEAD='<meta http-equiv="cache-control" content="no-cache"></meta>
59*cac38512Smjnelson<meta http-equiv="Pragma" content="no-cache"></meta>
60*cac38512Smjnelson<meta http-equiv="Expires" content="-1"></meta>
61daaffb31Sdp<!--
62daaffb31Sdp   Note to customizers: the body of the webrev is IDed as SUNWwebrev
63daaffb31Sdp   to allow easy overriding by users of webrev via the userContent.css
64daaffb31Sdp   mechanism available in some browsers.
65daaffb31Sdp
66daaffb31Sdp   For example, to have all "removed" information be red instead of
67daaffb31Sdp   brown, set a rule in your userContent.css file like:
68daaffb31Sdp
69daaffb31Sdp       body#SUNWwebrev span.removed { color: red ! important; }
70daaffb31Sdp-->
71daaffb31Sdp<style type="text/css" media="screen">
72daaffb31Sdpbody {
73daaffb31Sdp    background-color: #eeeeee;
74daaffb31Sdp}
75daaffb31Sdphr {
76daaffb31Sdp    border: none 0;
77daaffb31Sdp    border-top: 1px solid #aaa;
78daaffb31Sdp    height: 1px;
79daaffb31Sdp}
80daaffb31Sdpdiv.summary {
81daaffb31Sdp    font-size: .8em;
82daaffb31Sdp    border-bottom: 1px solid #aaa;
83daaffb31Sdp    padding-left: 1em;
84daaffb31Sdp    padding-right: 1em;
85daaffb31Sdp}
86daaffb31Sdpdiv.summary h2 {
87daaffb31Sdp    margin-bottom: 0.3em;
88daaffb31Sdp}
89daaffb31Sdpdiv.summary table th {
90daaffb31Sdp    text-align: right;
91daaffb31Sdp    vertical-align: top;
92daaffb31Sdp    white-space: nowrap;
93daaffb31Sdp}
94daaffb31Sdpspan.lineschanged {
95daaffb31Sdp    font-size: 0.7em;
96daaffb31Sdp}
97daaffb31Sdpspan.oldmarker {
98daaffb31Sdp    color: red;
99daaffb31Sdp    font-size: large;
100daaffb31Sdp    font-weight: bold;
101daaffb31Sdp}
102daaffb31Sdpspan.newmarker {
103daaffb31Sdp    color: green;
104daaffb31Sdp    font-size: large;
105daaffb31Sdp    font-weight: bold;
106daaffb31Sdp}
107daaffb31Sdpspan.removed {
108daaffb31Sdp    color: brown;
109daaffb31Sdp}
110daaffb31Sdpspan.changed {
111daaffb31Sdp    color: blue;
112daaffb31Sdp}
113daaffb31Sdpspan.new {
114daaffb31Sdp    color: blue;
115daaffb31Sdp    font-weight: bold;
116daaffb31Sdp}
117daaffb31Sdpa.print { font-size: x-small; }
118daaffb31Sdpa:hover { background-color: #ffcc99; }
119daaffb31Sdp</style>
120daaffb31Sdp
121daaffb31Sdp<style type="text/css" media="print">
122daaffb31Sdppre { font-size: 0.8em; font-family: courier, monospace; }
123daaffb31Sdpspan.removed { color: #444; font-style: italic }
124daaffb31Sdpspan.changed { font-weight: bold; }
125daaffb31Sdpspan.new { font-weight: bold; }
126daaffb31Sdpspan.newmarker { font-size: 1.2em; font-weight: bold; }
127daaffb31Sdpspan.oldmarker { font-size: 1.2em; font-weight: bold; }
128daaffb31Sdpa.print {display: none}
129daaffb31Sdphr { border: none 0; border-top: 1px solid #aaa; height: 1px; }
130daaffb31Sdp</style>
131daaffb31Sdp'
132daaffb31Sdp
133daaffb31Sdp#
134daaffb31Sdp# UDiffs need a slightly different CSS rule for 'new' items (we don't
135daaffb31Sdp# want them to be bolded as we do in cdiffs or sdiffs).
136daaffb31Sdp#
137daaffb31SdpUDIFFCSS='
138daaffb31Sdp<style type="text/css" media="screen">
139daaffb31Sdpspan.new {
140daaffb31Sdp    color: blue;
141daaffb31Sdp    font-weight: normal;
142daaffb31Sdp}
143daaffb31Sdp</style>
144daaffb31Sdp'
145daaffb31Sdp
146daaffb31Sdp#
147daaffb31Sdp# input_cmd | html_quote | output_cmd
148daaffb31Sdp# or
149daaffb31Sdp# html_quote filename | output_cmd
1507c478bd9Sstevel@tonic-gate#
1517c478bd9Sstevel@tonic-gate# Make a piece of source code safe for display in an HTML <pre> block.
1527c478bd9Sstevel@tonic-gate#
1537c478bd9Sstevel@tonic-gatehtml_quote()
1547c478bd9Sstevel@tonic-gate{
1557c478bd9Sstevel@tonic-gate	sed -e "s/&/\&amp;/g" -e "s/</\&lt;/g" -e "s/>/\&gt;/g" "$@" | expand
1567c478bd9Sstevel@tonic-gate}
1577c478bd9Sstevel@tonic-gate
158daaffb31Sdp#
159daaffb31Sdp# input_cmd | bug2url | output_cmd
160daaffb31Sdp#
161daaffb31Sdp# Scan for bugids and insert <a> links to the relevent bug database.
162daaffb31Sdp#
163daaffb31Sdpbug2url()
1647c478bd9Sstevel@tonic-gate{
165daaffb31Sdp	sed -e 's|[0-9]\{5,\}|<a href=\"'$BUGURL'&\">&</a>|g'
166daaffb31Sdp}
167daaffb31Sdp
1687c478bd9Sstevel@tonic-gate#
169daaffb31Sdp# input_cmd | sac2url | output_cmd
1707c478bd9Sstevel@tonic-gate#
171daaffb31Sdp# Scan for ARC cases and insert <a> links to the relevent SAC database.
172daaffb31Sdp# This is slightly complicated because inside the SWAN, SAC cases are
173daaffb31Sdp# grouped by ARC: PSARC/2006/123.  But on OpenSolaris.org, they are
174daaffb31Sdp# referenced as 2006/123 (without labelling the ARC).
1757c478bd9Sstevel@tonic-gate#
176daaffb31Sdpsac2url()
177daaffb31Sdp{
178e0e0293aSjmcp	if [[ -z "$Oflag" ]]; then
1790a30ef2cSstevel	    sed -e 's|\([A-Z]\{1,2\}ARC\)[ /]\([0-9]\{4\}\)/\([0-9]\{3\}\)|<a href=\"'$SACURL'/\1/\2/\3\">\1 \2/\3</a>|g'
180daaffb31Sdp	else
181daaffb31Sdp	    sed -e 's|\([A-Z]\{1,2\}ARC\)[ /]\([0-9]\{4\}\)/\([0-9]\{3\}\)|<a href=\"'$SACURL'/\2/\3\">\1 \2/\3</a>|g'
182daaffb31Sdp	fi
183daaffb31Sdp}
184daaffb31Sdp
1857c478bd9Sstevel@tonic-gate#
186daaffb31Sdp# strip_unchanged <infile> | output_cmd
1877c478bd9Sstevel@tonic-gate#
188daaffb31Sdp# Removes chunks of sdiff documents that have not changed. This makes it
189daaffb31Sdp# easier for a code reviewer to find the bits that have changed.
1907c478bd9Sstevel@tonic-gate#
191daaffb31Sdp# Deleted lines of text are replaced by a horizontal rule. Some
192daaffb31Sdp# identical lines are retained before and after the changed lines to
193daaffb31Sdp# provide some context.  The number of these lines is controlled by the
194daaffb31Sdp# variable C in the nawk script below.
195daaffb31Sdp#
196daaffb31Sdp# The script detects changed lines as any line that has a "<span class="
197daaffb31Sdp# string embedded (unchanged lines have no particular class and are not
198daaffb31Sdp# part of a <span>).  Blank lines (without a sequence number) are also
199daaffb31Sdp# detected since they flag lines that have been inserted or deleted.
200daaffb31Sdp#
201daaffb31Sdpstrip_unchanged()
202daaffb31Sdp{
203daaffb31Sdp	nawk '
204daaffb31Sdp	BEGIN	{ C = c = 20 }
205daaffb31Sdp	NF == 0 || /span class=/ {
206daaffb31Sdp		if (c > C) {
207daaffb31Sdp			c -= C
208daaffb31Sdp			inx = 0
209daaffb31Sdp			if (c > C) {
210*cac38512Smjnelson				print "\n</pre><hr></hr><pre>"
211daaffb31Sdp				inx = c % C
212daaffb31Sdp				c = C
213daaffb31Sdp			}
214daaffb31Sdp
215daaffb31Sdp			for (i = 0; i < c; i++)
216daaffb31Sdp				print ln[(inx + i) % C]
217daaffb31Sdp		}
218daaffb31Sdp		c = 0;
219daaffb31Sdp		print
220daaffb31Sdp		next
221daaffb31Sdp	}
222daaffb31Sdp	{	if (c >= C) {
223daaffb31Sdp			ln[c % C] = $0
224daaffb31Sdp			c++;
225daaffb31Sdp			next;
226daaffb31Sdp		}
227daaffb31Sdp		c++;
228daaffb31Sdp		print
229daaffb31Sdp	}
230*cac38512Smjnelson	END	{ if (c > (C * 2)) print "\n</pre><hr></hr>" }
231daaffb31Sdp
232daaffb31Sdp	' $1
233daaffb31Sdp}
234daaffb31Sdp
235daaffb31Sdp#
236daaffb31Sdp# sdiff_to_html
237daaffb31Sdp#
238daaffb31Sdp# This function takes two files as arguments, obtains their diff, and
239daaffb31Sdp# processes the diff output to present the files as an HTML document with
240daaffb31Sdp# the files displayed side-by-side, differences shown in color.  It also
241daaffb31Sdp# takes a delta comment, rendered as an HTML snippet, as the third
242daaffb31Sdp# argument.  The function takes two files as arguments, then the name of
243daaffb31Sdp# file, the path, and the comment.  The HTML will be delivered on stdout,
244daaffb31Sdp# e.g.
245daaffb31Sdp#
246daaffb31Sdp#   $ sdiff_to_html old/usr/src/tools/scripts/webrev.sh \
247daaffb31Sdp#         new/usr/src/tools/scripts/webrev.sh \
248daaffb31Sdp#         webrev.sh usr/src/tools/scripts \
249daaffb31Sdp#         '<a href="http://monaco.sfbay.sun.com/detail.jsp?cr=1234567">
250daaffb31Sdp#          1234567</a> my bugid' > <file>.html
251daaffb31Sdp#
252daaffb31Sdp# framed_sdiff() is then called which creates $2.frames.html
253daaffb31Sdp# in the webrev tree.
254daaffb31Sdp#
255daaffb31Sdp# FYI: This function is rather unusual in its use of awk.  The initial
256daaffb31Sdp# diff run produces conventional diff output showing changed lines mixed
257daaffb31Sdp# with editing codes.  The changed lines are ignored - we're interested in
258daaffb31Sdp# the editing codes, e.g.
2597c478bd9Sstevel@tonic-gate#
2607c478bd9Sstevel@tonic-gate#      8c8
2617c478bd9Sstevel@tonic-gate#      57a61
2627c478bd9Sstevel@tonic-gate#      63c66,76
2637c478bd9Sstevel@tonic-gate#      68,93d80
2647c478bd9Sstevel@tonic-gate#      106d90
2657c478bd9Sstevel@tonic-gate#      108,110d91
2667c478bd9Sstevel@tonic-gate#
267daaffb31Sdp#  These editing codes are parsed by the awk script and used to generate
268daaffb31Sdp#  another awk script that generates HTML, e.g the above lines would turn
269daaffb31Sdp#  into something like this:
2707c478bd9Sstevel@tonic-gate#
2717c478bd9Sstevel@tonic-gate#      BEGIN { printf "<pre>\n" }
2727c478bd9Sstevel@tonic-gate#      function sp(n) {for (i=0;i<n;i++)printf "\n"}
273daaffb31Sdp#      function wl(n) {printf "<font color=%s>%4d %s </font>\n", n, NR, $0}
2747c478bd9Sstevel@tonic-gate#      NR==8           {wl("#7A7ADD");next}
2757c478bd9Sstevel@tonic-gate#      NR==54          {wl("#7A7ADD");sp(3);next}
2767c478bd9Sstevel@tonic-gate#      NR==56          {wl("#7A7ADD");next}
2777c478bd9Sstevel@tonic-gate#      NR==57          {wl("black");printf "\n"; next}
2787c478bd9Sstevel@tonic-gate#        :               :
2797c478bd9Sstevel@tonic-gate#
280daaffb31Sdp#  This script is then run on the original source file to generate the
281daaffb31Sdp#  HTML that corresponds to the source file.
2827c478bd9Sstevel@tonic-gate#
283daaffb31Sdp#  The two HTML files are then combined into a single piece of HTML that
284daaffb31Sdp#  uses an HTML table construct to present the files side by side.  You'll
285daaffb31Sdp#  notice that the changes are color-coded:
2867c478bd9Sstevel@tonic-gate#
2877c478bd9Sstevel@tonic-gate#   black     - unchanged lines
2887c478bd9Sstevel@tonic-gate#   blue      - changed lines
2897c478bd9Sstevel@tonic-gate#   bold blue - new lines
2907c478bd9Sstevel@tonic-gate#   brown     - deleted lines
2917c478bd9Sstevel@tonic-gate#
292daaffb31Sdp#  Blank lines are inserted in each file to keep unchanged lines in sync
293daaffb31Sdp#  (side-by-side).  This format is familiar to users of sdiff(1) or
294daaffb31Sdp#  Teamware's filemerge tool.
295daaffb31Sdp#
296daaffb31Sdpsdiff_to_html()
297daaffb31Sdp{
2987c478bd9Sstevel@tonic-gate	diff -b $1 $2 > /tmp/$$.diffs
2997c478bd9Sstevel@tonic-gate
300daaffb31Sdp	TNAME=$3
301daaffb31Sdp	TPATH=$4
302daaffb31Sdp	COMMENT=$5
303daaffb31Sdp
3047c478bd9Sstevel@tonic-gate	#
3057c478bd9Sstevel@tonic-gate	#  Now we have the diffs, generate the HTML for the old file.
3067c478bd9Sstevel@tonic-gate	#
3077c478bd9Sstevel@tonic-gate	nawk '
3087c478bd9Sstevel@tonic-gate	BEGIN	{
3097c478bd9Sstevel@tonic-gate		printf "function sp(n) {for (i=0;i<n;i++)printf \"\\n\"}\n"
310daaffb31Sdp		printf "function removed() "
311daaffb31Sdp		printf "{printf \"<span class=\\\"removed\\\">%%4d %%s</span>\\n\", NR, $0}\n"
312daaffb31Sdp		printf "function changed() "
313daaffb31Sdp		printf "{printf \"<span class=\\\"changed\\\">%%4d %%s</span>\\n\", NR, $0}\n"
314daaffb31Sdp		printf "function bl() {printf \"%%4d %%s\\n\", NR, $0}\n"
3157c478bd9Sstevel@tonic-gate}
3167c478bd9Sstevel@tonic-gate	/^</	{next}
3177c478bd9Sstevel@tonic-gate	/^>/	{next}
3187c478bd9Sstevel@tonic-gate	/^---/	{next}
319daaffb31Sdp
3207c478bd9Sstevel@tonic-gate	{
3217c478bd9Sstevel@tonic-gate	split($1, a, /[cad]/) ;
3227c478bd9Sstevel@tonic-gate	if (index($1, "a")) {
3237c478bd9Sstevel@tonic-gate		if (a[1] == 0) {
3247c478bd9Sstevel@tonic-gate			n = split(a[2], r, /,/);
3257c478bd9Sstevel@tonic-gate			if (n == 1)
3267c478bd9Sstevel@tonic-gate				printf "BEGIN\t\t{sp(1)}\n"
3277c478bd9Sstevel@tonic-gate			else
3287c478bd9Sstevel@tonic-gate				printf "BEGIN\t\t{sp(%d)}\n",\
3297c478bd9Sstevel@tonic-gate				(r[2] - r[1]) + 1
3307c478bd9Sstevel@tonic-gate			next
3317c478bd9Sstevel@tonic-gate		}
3327c478bd9Sstevel@tonic-gate
3337c478bd9Sstevel@tonic-gate		printf "NR==%s\t\t{", a[1]
3347c478bd9Sstevel@tonic-gate		n = split(a[2], r, /,/);
3357c478bd9Sstevel@tonic-gate		s = r[1];
3367c478bd9Sstevel@tonic-gate		if (n == 1)
3377c478bd9Sstevel@tonic-gate			printf "bl();printf \"\\n\"; next}\n"
3387c478bd9Sstevel@tonic-gate		else {
3397c478bd9Sstevel@tonic-gate			n = r[2] - r[1]
3407c478bd9Sstevel@tonic-gate			printf "bl();sp(%d);next}\n",\
3417c478bd9Sstevel@tonic-gate			(r[2] - r[1]) + 1
3427c478bd9Sstevel@tonic-gate		}
3437c478bd9Sstevel@tonic-gate		next
3447c478bd9Sstevel@tonic-gate	}
3457c478bd9Sstevel@tonic-gate	if (index($1, "d")) {
3467c478bd9Sstevel@tonic-gate		n = split(a[1], r, /,/);
3477c478bd9Sstevel@tonic-gate		n1 = r[1]
3487c478bd9Sstevel@tonic-gate		n2 = r[2]
3497c478bd9Sstevel@tonic-gate		if (n == 1)
350daaffb31Sdp			printf "NR==%s\t\t{removed(); next}\n" , n1
3517c478bd9Sstevel@tonic-gate		else
352daaffb31Sdp			printf "NR==%s,NR==%s\t{removed(); next}\n" , n1, n2
3537c478bd9Sstevel@tonic-gate		next
3547c478bd9Sstevel@tonic-gate	}
3557c478bd9Sstevel@tonic-gate	if (index($1, "c")) {
3567c478bd9Sstevel@tonic-gate		n = split(a[1], r, /,/);
3577c478bd9Sstevel@tonic-gate		n1 = r[1]
3587c478bd9Sstevel@tonic-gate		n2 = r[2]
3597c478bd9Sstevel@tonic-gate		final = n2
3607c478bd9Sstevel@tonic-gate		d1 = 0
3617c478bd9Sstevel@tonic-gate		if (n == 1)
362daaffb31Sdp			printf "NR==%s\t\t{changed();" , n1
3637c478bd9Sstevel@tonic-gate		else {
3647c478bd9Sstevel@tonic-gate			d1 = n2 - n1
365daaffb31Sdp			printf "NR==%s,NR==%s\t{changed();" , n1, n2
3667c478bd9Sstevel@tonic-gate		}
3677c478bd9Sstevel@tonic-gate		m = split(a[2], r, /,/);
3687c478bd9Sstevel@tonic-gate		n1 = r[1]
3697c478bd9Sstevel@tonic-gate		n2 = r[2]
3707c478bd9Sstevel@tonic-gate		if (m > 1) {
3717c478bd9Sstevel@tonic-gate			d2  = n2 - n1
3727c478bd9Sstevel@tonic-gate			if (d2 > d1) {
3737c478bd9Sstevel@tonic-gate				if (n > 1) printf "if (NR==%d)", final
3747c478bd9Sstevel@tonic-gate				printf "sp(%d);", d2 - d1
3757c478bd9Sstevel@tonic-gate			}
3767c478bd9Sstevel@tonic-gate		}
3777c478bd9Sstevel@tonic-gate		printf "next}\n" ;
3787c478bd9Sstevel@tonic-gate
3797c478bd9Sstevel@tonic-gate		next
3807c478bd9Sstevel@tonic-gate	}
3817c478bd9Sstevel@tonic-gate	}
3827c478bd9Sstevel@tonic-gate
383daaffb31Sdp	END	{ printf "{printf \"%%4d %%s\\n\", NR, $0 }\n" }
384daaffb31Sdp	' /tmp/$$.diffs > /tmp/$$.file1
3857c478bd9Sstevel@tonic-gate
3867c478bd9Sstevel@tonic-gate	#
3877c478bd9Sstevel@tonic-gate	#  Now generate the HTML for the new file
3887c478bd9Sstevel@tonic-gate	#
3897c478bd9Sstevel@tonic-gate	nawk '
3907c478bd9Sstevel@tonic-gate	BEGIN	{
3917c478bd9Sstevel@tonic-gate		printf "function sp(n) {for (i=0;i<n;i++)printf \"\\n\"}\n"
392daaffb31Sdp		printf "function new() "
393daaffb31Sdp		printf "{printf \"<span class=\\\"new\\\">%%4d %%s</span>\\n\", NR, $0}\n"
394daaffb31Sdp		printf "function changed() "
395daaffb31Sdp		printf "{printf \"<span class=\\\"changed\\\">%%4d %%s</span>\\n\", NR, $0}\n"
396daaffb31Sdp		printf "function bl() {printf \"%%4d %%s\\n\", NR, $0}\n"
3977c478bd9Sstevel@tonic-gate	}
398daaffb31Sdp
3997c478bd9Sstevel@tonic-gate	/^</	{next}
4007c478bd9Sstevel@tonic-gate	/^>/	{next}
4017c478bd9Sstevel@tonic-gate	/^---/	{next}
402daaffb31Sdp
4037c478bd9Sstevel@tonic-gate	{
4047c478bd9Sstevel@tonic-gate	split($1, a, /[cad]/) ;
4057c478bd9Sstevel@tonic-gate	if (index($1, "d")) {
4067c478bd9Sstevel@tonic-gate		if (a[2] == 0) {
4077c478bd9Sstevel@tonic-gate			n = split(a[1], r, /,/);
4087c478bd9Sstevel@tonic-gate			if (n == 1)
4097c478bd9Sstevel@tonic-gate				printf "BEGIN\t\t{sp(1)}\n"
4107c478bd9Sstevel@tonic-gate			else
4117c478bd9Sstevel@tonic-gate				printf "BEGIN\t\t{sp(%d)}\n",\
4127c478bd9Sstevel@tonic-gate				(r[2] - r[1]) + 1
4137c478bd9Sstevel@tonic-gate			next
4147c478bd9Sstevel@tonic-gate		}
4157c478bd9Sstevel@tonic-gate
4167c478bd9Sstevel@tonic-gate		printf "NR==%s\t\t{", a[2]
4177c478bd9Sstevel@tonic-gate		n = split(a[1], r, /,/);
4187c478bd9Sstevel@tonic-gate		s = r[1];
4197c478bd9Sstevel@tonic-gate		if (n == 1)
4207c478bd9Sstevel@tonic-gate			printf "bl();printf \"\\n\"; next}\n"
4217c478bd9Sstevel@tonic-gate		else {
4227c478bd9Sstevel@tonic-gate			n = r[2] - r[1]
4237c478bd9Sstevel@tonic-gate			printf "bl();sp(%d);next}\n",\
4247c478bd9Sstevel@tonic-gate			(r[2] - r[1]) + 1
4257c478bd9Sstevel@tonic-gate		}
4267c478bd9Sstevel@tonic-gate		next
4277c478bd9Sstevel@tonic-gate	}
4287c478bd9Sstevel@tonic-gate	if (index($1, "a")) {
4297c478bd9Sstevel@tonic-gate		n = split(a[2], r, /,/);
4307c478bd9Sstevel@tonic-gate		n1 = r[1]
4317c478bd9Sstevel@tonic-gate		n2 = r[2]
4327c478bd9Sstevel@tonic-gate		if (n == 1)
433daaffb31Sdp			printf "NR==%s\t\t{new() ; next}\n" , n1
4347c478bd9Sstevel@tonic-gate		else
435daaffb31Sdp			printf "NR==%s,NR==%s\t{new() ; next}\n" , n1, n2
4367c478bd9Sstevel@tonic-gate		next
4377c478bd9Sstevel@tonic-gate	}
4387c478bd9Sstevel@tonic-gate	if (index($1, "c")) {
4397c478bd9Sstevel@tonic-gate		n = split(a[2], r, /,/);
4407c478bd9Sstevel@tonic-gate		n1 = r[1]
4417c478bd9Sstevel@tonic-gate		n2 = r[2]
4427c478bd9Sstevel@tonic-gate		final = n2
4437c478bd9Sstevel@tonic-gate		d2 = 0;
4447c478bd9Sstevel@tonic-gate		if (n == 1) {
4457c478bd9Sstevel@tonic-gate			final = n1
446daaffb31Sdp			printf "NR==%s\t\t{changed();" , n1
4477c478bd9Sstevel@tonic-gate		} else {
4487c478bd9Sstevel@tonic-gate			d2 = n2 - n1
449daaffb31Sdp			printf "NR==%s,NR==%s\t{changed();" , n1, n2
4507c478bd9Sstevel@tonic-gate		}
4517c478bd9Sstevel@tonic-gate		m = split(a[1], r, /,/);
4527c478bd9Sstevel@tonic-gate		n1 = r[1]
4537c478bd9Sstevel@tonic-gate		n2 = r[2]
4547c478bd9Sstevel@tonic-gate		if (m > 1) {
4557c478bd9Sstevel@tonic-gate			d1  = n2 - n1
4567c478bd9Sstevel@tonic-gate			if (d1 > d2) {
4577c478bd9Sstevel@tonic-gate				if (n > 1) printf "if (NR==%d)", final
4587c478bd9Sstevel@tonic-gate				printf "sp(%d);", d1 - d2
4597c478bd9Sstevel@tonic-gate			}
4607c478bd9Sstevel@tonic-gate		}
4617c478bd9Sstevel@tonic-gate		printf "next}\n" ;
4627c478bd9Sstevel@tonic-gate		next
4637c478bd9Sstevel@tonic-gate	}
4647c478bd9Sstevel@tonic-gate	}
465daaffb31Sdp	END	{ printf "{printf \"%%4d %%s\\n\", NR, $0 }\n" }
4667c478bd9Sstevel@tonic-gate	' /tmp/$$.diffs > /tmp/$$.file2
4677c478bd9Sstevel@tonic-gate
468daaffb31Sdp	#
469daaffb31Sdp	# Post-process the HTML files by running them back through nawk
470daaffb31Sdp	#
471daaffb31Sdp	html_quote < $1 | nawk -f /tmp/$$.file1 > /tmp/$$.file1.html
4727c478bd9Sstevel@tonic-gate
473daaffb31Sdp	html_quote < $2 | nawk -f /tmp/$$.file2 > /tmp/$$.file2.html
4747c478bd9Sstevel@tonic-gate
475daaffb31Sdp	#
476daaffb31Sdp	# Now combine into a valid HTML file and side-by-side into a table
477daaffb31Sdp	#
478daaffb31Sdp	print "$HTML<head>$STDHEAD"
479daaffb31Sdp	print "<title>$WNAME Sdiff $TPATH </title>"
480daaffb31Sdp	print "</head><body id=\"SUNWwebrev\">"
481daaffb31Sdp        print "<a class=\"print\" href=\"javascript:print()\">Print this page</a>"
482daaffb31Sdp	print "<pre>$COMMENT</pre>\n"
483daaffb31Sdp	print "<table><tr valign=\"top\">"
484daaffb31Sdp	print "<td><pre>"
4857c478bd9Sstevel@tonic-gate
4867c478bd9Sstevel@tonic-gate	strip_unchanged /tmp/$$.file1.html
4877c478bd9Sstevel@tonic-gate
488daaffb31Sdp	print "</pre></td><td><pre>"
4897c478bd9Sstevel@tonic-gate
4907c478bd9Sstevel@tonic-gate	strip_unchanged /tmp/$$.file2.html
4917c478bd9Sstevel@tonic-gate
492daaffb31Sdp	print "</pre></td>"
493daaffb31Sdp	print "</tr></table>"
494daaffb31Sdp	print "</body></html>"
4957c478bd9Sstevel@tonic-gate
496daaffb31Sdp	framed_sdiff $TNAME $TPATH /tmp/$$.file1.html /tmp/$$.file2.html \
497daaffb31Sdp	    "$COMMENT"
4987c478bd9Sstevel@tonic-gate}
4997c478bd9Sstevel@tonic-gate
5007c478bd9Sstevel@tonic-gate
501daaffb31Sdp#
502daaffb31Sdp# framed_sdiff <filename> <filepath> <lhsfile> <rhsfile> <comment>
503daaffb31Sdp#
504daaffb31Sdp# Expects lefthand and righthand side html files created by sdiff_to_html.
505daaffb31Sdp# We use insert_anchors() to augment those with HTML navigation anchors,
506daaffb31Sdp# and then emit the main frame.  Content is placed into:
507daaffb31Sdp#
508daaffb31Sdp#    $WDIR/DIR/$TNAME.lhs.html
509daaffb31Sdp#    $WDIR/DIR/$TNAME.rhs.html
510daaffb31Sdp#    $WDIR/DIR/$TNAME.frames.html
511daaffb31Sdp#
512daaffb31Sdp# NOTE: We rely on standard usage of $WDIR and $DIR.
513daaffb31Sdp#
5147c478bd9Sstevel@tonic-gatefunction framed_sdiff
5157c478bd9Sstevel@tonic-gate{
5167c478bd9Sstevel@tonic-gate	typeset TNAME=$1
517daaffb31Sdp	typeset TPATH=$2
518daaffb31Sdp	typeset lhsfile=$3
519daaffb31Sdp	typeset rhsfile=$4
520daaffb31Sdp	typeset comments=$5
5217c478bd9Sstevel@tonic-gate	typeset RTOP
522daaffb31Sdp
5237c478bd9Sstevel@tonic-gate	# Enable html files to access WDIR via a relative path.
524daaffb31Sdp	RTOP=$(relative_dir $TPATH $WDIR)
525daaffb31Sdp
526daaffb31Sdp	# Make the rhs/lhs files and output the frameset file.
527daaffb31Sdp	print "$HTML<head>$STDHEAD" > $WDIR/$DIR/$TNAME.lhs.html
528daaffb31Sdp
529daaffb31Sdp	cat >> $WDIR/$DIR/$TNAME.lhs.html <<-EOF
530*cac38512Smjnelson	    <script type="text/javascript" src="$RTOP/ancnav.js"></script>
5317c478bd9Sstevel@tonic-gate	    </head>
532daaffb31Sdp	    <body id="SUNWwebrev" onkeypress="keypress(event);">
533*cac38512Smjnelson	    <a name="0"></a>
534*cac38512Smjnelson	    <pre>$comments</pre><hr></hr>
535daaffb31Sdp	EOF
536daaffb31Sdp
537daaffb31Sdp	cp $WDIR/$DIR/$TNAME.lhs.html $WDIR/$DIR/$TNAME.rhs.html
538daaffb31Sdp
539daaffb31Sdp	insert_anchors $lhsfile >> $WDIR/$DIR/$TNAME.lhs.html
540daaffb31Sdp	insert_anchors $rhsfile >> $WDIR/$DIR/$TNAME.rhs.html
541daaffb31Sdp
542daaffb31Sdp	close='</body></html>'
543daaffb31Sdp
544daaffb31Sdp	print $close >> $WDIR/$DIR/$TNAME.lhs.html
545daaffb31Sdp	print $close >> $WDIR/$DIR/$TNAME.rhs.html
546daaffb31Sdp
547daaffb31Sdp	print "$FRAMEHTML<head>$STDHEAD" > $WDIR/$DIR/$TNAME.frames.html
548daaffb31Sdp	print "<title>$WNAME Framed-Sdiff " \
549daaffb31Sdp	    "$TPATH/$TNAME</title> </head>" >> $WDIR/$DIR/$TNAME.frames.html
550daaffb31Sdp	cat >> $WDIR/$DIR/$TNAME.frames.html <<-EOF
551daaffb31Sdp	  <frameset rows="*,60">
552daaffb31Sdp	    <frameset cols="50%,50%">
553*cac38512Smjnelson	      <frame src="$TNAME.lhs.html" scrolling="auto" name="lhs"></frame>
554*cac38512Smjnelson	      <frame src="$TNAME.rhs.html" scrolling="auto" name="rhs"></frame>
555daaffb31Sdp	    </frameset>
556daaffb31Sdp	  <frame src="$RTOP/ancnav.html" scrolling="no" marginwidth="0"
557*cac38512Smjnelson	   marginheight="0" name="nav"></frame>
558daaffb31Sdp	  <noframes>
559daaffb31Sdp            <body id="SUNWwebrev">
560daaffb31Sdp	      Alas 'frames' webrev requires that your browser supports frames
5617c478bd9Sstevel@tonic-gate	      and has the feature enabled.
562daaffb31Sdp            </body>
563daaffb31Sdp	  </noframes>
564daaffb31Sdp	  </frameset>
5657c478bd9Sstevel@tonic-gate	</html>
5667c478bd9Sstevel@tonic-gate	EOF
5677c478bd9Sstevel@tonic-gate}
5687c478bd9Sstevel@tonic-gate
5697c478bd9Sstevel@tonic-gate
570daaffb31Sdp#
571daaffb31Sdp# fix_postscript
572daaffb31Sdp#
573daaffb31Sdp# Merge codereview output files to a single conforming postscript file, by:
574daaffb31Sdp# 	- removing all extraneous headers/trailers
575daaffb31Sdp#	- making the page numbers right
576daaffb31Sdp#	- removing pages devoid of contents which confuse some
577daaffb31Sdp#	  postscript readers.
578daaffb31Sdp#
579daaffb31Sdp# From Casper.
580daaffb31Sdp#
581daaffb31Sdpfunction fix_postscript
5827c478bd9Sstevel@tonic-gate{
583daaffb31Sdp	infile=$1
5847c478bd9Sstevel@tonic-gate
585daaffb31Sdp	cat > /tmp/$$.crmerge.pl << \EOF
5867c478bd9Sstevel@tonic-gate
587daaffb31Sdp	print scalar(<>);		# %!PS-Adobe---
588daaffb31Sdp	print "%%Orientation: Landscape\n";
5897c478bd9Sstevel@tonic-gate
590daaffb31Sdp	$pno = 0;
591daaffb31Sdp	$doprint = 1;
592daaffb31Sdp
593daaffb31Sdp	$page = "";
594daaffb31Sdp
595daaffb31Sdp	while (<>) {
596daaffb31Sdp		next if (/^%%Pages:\s*\d+/);
597daaffb31Sdp
598daaffb31Sdp		if (/^%%Page:/) {
599daaffb31Sdp			if ($pno == 0 || $page =~ /\)S/) {
600daaffb31Sdp				# Header or single page containing text
601daaffb31Sdp				print "%%Page: ? $pno\n" if ($pno > 0);
602daaffb31Sdp				print $page;
603daaffb31Sdp				$pno++;
604daaffb31Sdp			} else {
605daaffb31Sdp				# Empty page, skip it.
6067c478bd9Sstevel@tonic-gate			}
607daaffb31Sdp			$page = "";
608daaffb31Sdp			$doprint = 1;
6097c478bd9Sstevel@tonic-gate			next;
6107c478bd9Sstevel@tonic-gate		}
6117c478bd9Sstevel@tonic-gate
612daaffb31Sdp		# Skip from %%Trailer of one document to Endprolog
613daaffb31Sdp		# %%Page of the next
614daaffb31Sdp		$doprint = 0 if (/^%%Trailer/);
615daaffb31Sdp		$page .= $_ if ($doprint);
6167c478bd9Sstevel@tonic-gate	}
6177c478bd9Sstevel@tonic-gate
618daaffb31Sdp	if ($page =~ /\)S/) {
619daaffb31Sdp		print "%%Page: ? $pno\n";
620daaffb31Sdp		print $page;
621daaffb31Sdp	} else {
622daaffb31Sdp		$pno--;
623daaffb31Sdp	}
624daaffb31Sdp	print "%%Trailer\n%%Pages: $pno\n";
625daaffb31SdpEOF
626daaffb31Sdp
62714983201Sdp	$PERL /tmp/$$.crmerge.pl < $infile
628daaffb31Sdp}
629daaffb31Sdp
630daaffb31Sdp
631daaffb31Sdp#
632daaffb31Sdp# input_cmd | insert_anchors | output_cmd
633daaffb31Sdp#
6347c478bd9Sstevel@tonic-gate# Flag blocks of difference with sequentially numbered invisible
635daaffb31Sdp# anchors.  These are used to drive the frames version of the
6367c478bd9Sstevel@tonic-gate# sdiffs output.
6377c478bd9Sstevel@tonic-gate#
6387c478bd9Sstevel@tonic-gate# NOTE: Anchor zero flags the top of the file irrespective of changes,
6397c478bd9Sstevel@tonic-gate# an additional anchor is also appended to flag the bottom.
6407c478bd9Sstevel@tonic-gate#
641daaffb31Sdp# The script detects changed lines as any line that has a "<span
642daaffb31Sdp# class=" string embedded (unchanged lines have no class set and are
643daaffb31Sdp# not part of a <span>.  Blank lines (without a sequence number)
6447c478bd9Sstevel@tonic-gate# are also detected since they flag lines that have been inserted or
6457c478bd9Sstevel@tonic-gate# deleted.
6467c478bd9Sstevel@tonic-gate#
647daaffb31Sdpfunction insert_anchors
648daaffb31Sdp{
6497c478bd9Sstevel@tonic-gate	nawk '
6507c478bd9Sstevel@tonic-gate	function ia() {
651daaffb31Sdp		printf "<a name=\"%d\" id=\"anc%d\"></a>", anc, anc++;
6527c478bd9Sstevel@tonic-gate	}
653daaffb31Sdp
6547c478bd9Sstevel@tonic-gate	BEGIN {
655daaffb31Sdp		anc=1;
6567c478bd9Sstevel@tonic-gate		inblock=1;
657daaffb31Sdp		printf "<pre>\n";
6587c478bd9Sstevel@tonic-gate	}
659daaffb31Sdp	NF == 0 || /^<span class=/ {
6607c478bd9Sstevel@tonic-gate		if (inblock == 0) {
6617c478bd9Sstevel@tonic-gate			ia();
6627c478bd9Sstevel@tonic-gate			inblock=1;
6637c478bd9Sstevel@tonic-gate		}
6647c478bd9Sstevel@tonic-gate		print;
6657c478bd9Sstevel@tonic-gate		next;
6667c478bd9Sstevel@tonic-gate	}
6677c478bd9Sstevel@tonic-gate	{
6687c478bd9Sstevel@tonic-gate		inblock=0;
6697c478bd9Sstevel@tonic-gate		print;
6707c478bd9Sstevel@tonic-gate	}
6717c478bd9Sstevel@tonic-gate	END {
6727c478bd9Sstevel@tonic-gate		ia();
673daaffb31Sdp
674daaffb31Sdp		printf "<b style=\"font-size: large; color: red\">";
675daaffb31Sdp		printf "--- EOF ---</b>"
6767c478bd9Sstevel@tonic-gate        	for(i=0;i<8;i++) printf "\n\n\n\n\n\n\n\n\n\n";
677daaffb31Sdp		printf "</pre>"
678daaffb31Sdp		printf "<form name=\"eof\">";
679*cac38512Smjnelson		printf "<input name=\"value\" value=\"%d\" " \
680*cac38512Smjnelson		    "type=\"hidden\"></input>", anc - 1;
681daaffb31Sdp		printf "</form>";
6827c478bd9Sstevel@tonic-gate	}
6837c478bd9Sstevel@tonic-gate	' $1
6847c478bd9Sstevel@tonic-gate}
6857c478bd9Sstevel@tonic-gate
6867c478bd9Sstevel@tonic-gate
687daaffb31Sdp#
688daaffb31Sdp# relative_dir
689daaffb31Sdp#
690daaffb31Sdp# Print a relative return path from $1 to $2.  For example if
691daaffb31Sdp# $1=/tmp/myreview/raw_files/usr/src/tools/scripts and $2=/tmp/myreview,
692daaffb31Sdp# this function would print "../../../../".
693daaffb31Sdp#
694daaffb31Sdp# In the event that $1 is not in $2 a warning is printed to stderr,
695daaffb31Sdp# and $2 is returned-- the result of this is that the resulting webrev
696daaffb31Sdp# is not relocatable.
697daaffb31Sdp#
698daaffb31Sdpfunction relative_dir
6997c478bd9Sstevel@tonic-gate{
700daaffb31Sdp	typeset cur="${1##$2?(/)}"
701daaffb31Sdp	typeset ret=""
702daaffb31Sdp	if [[ $2 == $cur ]]; then   # Should never happen.
703daaffb31Sdp		# Should never happen.
70414983201Sdp		print -u2 "\nWARNING: relative_dir: \"$1\" not relative "
705daaffb31Sdp		print -u2 "to \"$2\".  Check input paths.  Framed webrev "
706daaffb31Sdp		print -u2 "will not be relocatable!"
707daaffb31Sdp		print $2
708daaffb31Sdp		return
709daaffb31Sdp	fi
710daaffb31Sdp
711daaffb31Sdp	while [[ -n ${cur} ]];
7127c478bd9Sstevel@tonic-gate	do
7137c478bd9Sstevel@tonic-gate		cur=${cur%%*(/)*([!/])}
714daaffb31Sdp		if [[ -z $ret ]]; then
715daaffb31Sdp			ret=".."
716daaffb31Sdp		else
7177c478bd9Sstevel@tonic-gate			ret="../$ret"
718daaffb31Sdp		fi
7197c478bd9Sstevel@tonic-gate	done
7207c478bd9Sstevel@tonic-gate	print $ret
7217c478bd9Sstevel@tonic-gate}
7227c478bd9Sstevel@tonic-gate
7237c478bd9Sstevel@tonic-gate
724daaffb31Sdp#
725daaffb31Sdp# frame_nav_js
726daaffb31Sdp#
727daaffb31Sdp# Emit javascript for frame navigation
728daaffb31Sdp#
729daaffb31Sdpfunction frame_nav_js
7307c478bd9Sstevel@tonic-gate{
7317c478bd9Sstevel@tonic-gatecat << \EOF
7327c478bd9Sstevel@tonic-gatevar myInt;
7337c478bd9Sstevel@tonic-gatevar scrolling=0;
734daaffb31Sdpvar sfactor = 3;
7357c478bd9Sstevel@tonic-gatevar scount=10;
7367c478bd9Sstevel@tonic-gate
7377c478bd9Sstevel@tonic-gatefunction scrollByPix() {
7387c478bd9Sstevel@tonic-gate	if (scount<=0) {
7397c478bd9Sstevel@tonic-gate		sfactor*=1.2;
7407c478bd9Sstevel@tonic-gate		scount=10;
7417c478bd9Sstevel@tonic-gate	}
7427c478bd9Sstevel@tonic-gate	parent.lhs.scrollBy(0,sfactor);
7437c478bd9Sstevel@tonic-gate	parent.rhs.scrollBy(0,sfactor);
7447c478bd9Sstevel@tonic-gate	scount--;
7457c478bd9Sstevel@tonic-gate}
7467c478bd9Sstevel@tonic-gate
747daaffb31Sdpfunction scrollToAnc(num) {
748daaffb31Sdp
749daaffb31Sdp	// Update the value of the anchor in the form which we use as
750daaffb31Sdp	// storage for this value.  setAncValue() will take care of
751daaffb31Sdp	// correcting for overflow and underflow of the value and return
752daaffb31Sdp	// us the new value.
753daaffb31Sdp	num = setAncValue(num);
754daaffb31Sdp
755daaffb31Sdp	// Set location and scroll back a little to expose previous
756daaffb31Sdp	// lines.
757daaffb31Sdp	//
758daaffb31Sdp	// Note that this could be improved: it is possible although
759daaffb31Sdp	// complex to compute the x and y position of an anchor, and to
760daaffb31Sdp	// scroll to that location directly.
761daaffb31Sdp	//
7627c478bd9Sstevel@tonic-gate	parent.lhs.location.replace(parent.lhs.location.pathname + "#" + num);
7637c478bd9Sstevel@tonic-gate	parent.rhs.location.replace(parent.rhs.location.pathname + "#" + num);
764daaffb31Sdp
7657c478bd9Sstevel@tonic-gate	parent.lhs.scrollBy(0,-30);
7667c478bd9Sstevel@tonic-gate	parent.rhs.scrollBy(0,-30);
7677c478bd9Sstevel@tonic-gate}
7687c478bd9Sstevel@tonic-gate
769daaffb31Sdpfunction getAncValue()
770daaffb31Sdp{
771daaffb31Sdp	return (parseInt(parent.nav.document.diff.real.value));
772daaffb31Sdp}
773daaffb31Sdp
774daaffb31Sdpfunction setAncValue(val)
775daaffb31Sdp{
776daaffb31Sdp	if (val <= 0) {
777daaffb31Sdp		val = 0;
778daaffb31Sdp		parent.nav.document.diff.real.value = val;
779daaffb31Sdp		parent.nav.document.diff.display.value = "BOF";
780daaffb31Sdp		return (val);
781daaffb31Sdp	}
782daaffb31Sdp
783daaffb31Sdp	//
784daaffb31Sdp	// The way we compute the max anchor value is to stash it
785daaffb31Sdp	// inline in the left and right hand side pages-- it's the same
786daaffb31Sdp	// on each side, so we pluck from the left.
787daaffb31Sdp	//
788daaffb31Sdp	maxval = parent.lhs.document.eof.value.value;
789daaffb31Sdp	if (val < maxval) {
790daaffb31Sdp		parent.nav.document.diff.real.value = val;
791daaffb31Sdp		parent.nav.document.diff.display.value = val.toString();
792daaffb31Sdp		return (val);
793daaffb31Sdp	}
794daaffb31Sdp
795daaffb31Sdp	// this must be: val >= maxval
796daaffb31Sdp	val = maxval;
797daaffb31Sdp	parent.nav.document.diff.real.value = val;
798daaffb31Sdp	parent.nav.document.diff.display.value = "EOF";
799daaffb31Sdp	return (val);
800daaffb31Sdp}
801daaffb31Sdp
8027c478bd9Sstevel@tonic-gatefunction stopScroll() {
8037c478bd9Sstevel@tonic-gate	if (scrolling==1) {
8047c478bd9Sstevel@tonic-gate		clearInterval(myInt);
8057c478bd9Sstevel@tonic-gate		scrolling=0;
8067c478bd9Sstevel@tonic-gate	}
8077c478bd9Sstevel@tonic-gate}
8087c478bd9Sstevel@tonic-gate
8097c478bd9Sstevel@tonic-gatefunction startScroll() {
8107c478bd9Sstevel@tonic-gate	stopScroll();
8117c478bd9Sstevel@tonic-gate	scrolling=1;
8127c478bd9Sstevel@tonic-gate	myInt=setInterval("scrollByPix()",10);
8137c478bd9Sstevel@tonic-gate}
8147c478bd9Sstevel@tonic-gate
8157c478bd9Sstevel@tonic-gatefunction handlePress(b) {
816daaffb31Sdp
8177c478bd9Sstevel@tonic-gate	switch (b) {
8187c478bd9Sstevel@tonic-gate	    case 1 :
819daaffb31Sdp		scrollToAnc(-1);
8207c478bd9Sstevel@tonic-gate		break;
8217c478bd9Sstevel@tonic-gate	    case 2 :
822daaffb31Sdp		scrollToAnc(getAncValue() - 1);
8237c478bd9Sstevel@tonic-gate		break;
8247c478bd9Sstevel@tonic-gate	    case 3 :
8257c478bd9Sstevel@tonic-gate		sfactor=-3;
8267c478bd9Sstevel@tonic-gate		startScroll();
8277c478bd9Sstevel@tonic-gate		break;
8287c478bd9Sstevel@tonic-gate	    case 4 :
8297c478bd9Sstevel@tonic-gate		sfactor=3;
8307c478bd9Sstevel@tonic-gate		startScroll();
8317c478bd9Sstevel@tonic-gate		break;
8327c478bd9Sstevel@tonic-gate	    case 5 :
833daaffb31Sdp		scrollToAnc(getAncValue() + 1);
8347c478bd9Sstevel@tonic-gate		break;
8357c478bd9Sstevel@tonic-gate	    case 6 :
836daaffb31Sdp		scrollToAnc(999999);
8377c478bd9Sstevel@tonic-gate		break;
8387c478bd9Sstevel@tonic-gate	}
8397c478bd9Sstevel@tonic-gate}
8407c478bd9Sstevel@tonic-gate
8417c478bd9Sstevel@tonic-gatefunction handleRelease(b) {
8427c478bd9Sstevel@tonic-gate	stopScroll();
8437c478bd9Sstevel@tonic-gate}
8447c478bd9Sstevel@tonic-gate
845daaffb31Sdpfunction keypress(ev) {
846daaffb31Sdp	var keynum;
847daaffb31Sdp	var keychar;
848daaffb31Sdp
849daaffb31Sdp	if (window.event) { // IE
850daaffb31Sdp		keynum = ev.keyCode;
851daaffb31Sdp	} else if (ev.which) { // non-IE
852daaffb31Sdp		keynum = ev.which;
853daaffb31Sdp	}
854daaffb31Sdp
855daaffb31Sdp	keychar = String.fromCharCode(keynum);
856daaffb31Sdp
857daaffb31Sdp	if (keychar == "k") {
858daaffb31Sdp		handlePress(2);
859daaffb31Sdp		return (0);
860daaffb31Sdp	} else if (keychar == "j" || keychar == " ") {
861daaffb31Sdp		handlePress(5);
862daaffb31Sdp		return (0);
863daaffb31Sdp	}
864daaffb31Sdp	return (1);
865daaffb31Sdp}
866daaffb31Sdp
8677c478bd9Sstevel@tonic-gatefunction ValidateDiffNum(){
868daaffb31Sdp	val = parent.nav.document.diff.display.value;
869daaffb31Sdp	if (val == "EOF") {
870daaffb31Sdp		scrollToAnc(999999);
871daaffb31Sdp		return;
872daaffb31Sdp	}
873daaffb31Sdp
874daaffb31Sdp	if (val == "BOF") {
875daaffb31Sdp		scrollToAnc(0);
876daaffb31Sdp		return;
877daaffb31Sdp	}
878daaffb31Sdp
879daaffb31Sdp        i=parseInt(val);
8807c478bd9Sstevel@tonic-gate        if (isNaN(i)) {
881daaffb31Sdp                parent.nav.document.diff.display.value = getAncValue();
8827c478bd9Sstevel@tonic-gate        } else {
883daaffb31Sdp                scrollToAnc(i);
8847c478bd9Sstevel@tonic-gate        }
8857c478bd9Sstevel@tonic-gate        return false;
8867c478bd9Sstevel@tonic-gate}
8877c478bd9Sstevel@tonic-gate
888daaffb31SdpEOF
889daaffb31Sdp}
890daaffb31Sdp
891daaffb31Sdp#
892daaffb31Sdp# frame_navigation
893daaffb31Sdp#
894daaffb31Sdp# Output anchor navigation file for framed sdiffs.
895daaffb31Sdp#
896daaffb31Sdpfunction frame_navigation
897daaffb31Sdp{
898daaffb31Sdp	print "$HTML<head>$STDHEAD"
899daaffb31Sdp
900daaffb31Sdp	cat << \EOF
901daaffb31Sdp<title>Anchor Navigation</title>
902daaffb31Sdp<meta http-equiv="Content-Script-Type" content="text/javascript">
903daaffb31Sdp<meta http-equiv="Content-Type" content="text/html">
904daaffb31Sdp
905daaffb31Sdp<style type="text/css">
906daaffb31Sdp    div.button td { padding-left: 5px; padding-right: 5px;
907daaffb31Sdp		    background-color: #eee; text-align: center;
908daaffb31Sdp		    border: 1px #444 outset; cursor: pointer; }
909daaffb31Sdp    div.button a { font-weight: bold; color: black }
910daaffb31Sdp    div.button td:hover { background: #ffcc99; }
911daaffb31Sdp</style>
912daaffb31SdpEOF
913daaffb31Sdp
914*cac38512Smjnelson	print "<script type=\"text/javascript\" src=\"ancnav.js\"></script>"
915daaffb31Sdp
916daaffb31Sdp	cat << \EOF
9177c478bd9Sstevel@tonic-gate</head>
918daaffb31Sdp<body id="SUNWwebrev" bgcolor="#eeeeee" onload="document.diff.real.focus();"
919daaffb31Sdp	onkeypress="keypress(event);">
9207c478bd9Sstevel@tonic-gate    <noscript lang="javascript">
9217c478bd9Sstevel@tonic-gate      <center>
922*cac38512Smjnelson	<p><big>Framed Navigation controls require Javascript</big><br></br>
9237c478bd9Sstevel@tonic-gate	Either this browser is incompatable or javascript is not enabled</p>
9247c478bd9Sstevel@tonic-gate      </center>
9257c478bd9Sstevel@tonic-gate    </noscript>
9267c478bd9Sstevel@tonic-gate    <table width="100%" border="0" align="center">
927daaffb31Sdp	<tr>
928daaffb31Sdp          <td valign="middle" width="25%">Diff navigation:
929daaffb31Sdp          Use 'j' and 'k' for next and previous diffs; or use buttons
930daaffb31Sdp          at right</td>
931daaffb31Sdp	  <td align="center" valign="top" width="50%">
9327c478bd9Sstevel@tonic-gate	    <div class="button">
933daaffb31Sdp	      <table border="0" align="center">
934daaffb31Sdp                  <tr>
935daaffb31Sdp		    <td>
9367c478bd9Sstevel@tonic-gate		      <a onMouseDown="handlePress(1);return true;"
9377c478bd9Sstevel@tonic-gate			 onMouseUp="handleRelease(1);return true;"
9387c478bd9Sstevel@tonic-gate			 onMouseOut="handleRelease(1);return true;"
9397c478bd9Sstevel@tonic-gate			 onClick="return false;"
9407c478bd9Sstevel@tonic-gate			 title="Go to Beginning Of file">BOF</a></td>
941daaffb31Sdp		    <td>
9427c478bd9Sstevel@tonic-gate		      <a onMouseDown="handlePress(3);return true;"
9437c478bd9Sstevel@tonic-gate			 onMouseUp="handleRelease(3);return true;"
9447c478bd9Sstevel@tonic-gate			 onMouseOut="handleRelease(3);return true;"
9457c478bd9Sstevel@tonic-gate			 title="Scroll Up: Press and Hold to accelerate"
946daaffb31Sdp			 onClick="return false;">Scroll Up</a></td>
947daaffb31Sdp		    <td>
9487c478bd9Sstevel@tonic-gate		      <a onMouseDown="handlePress(2);return true;"
9497c478bd9Sstevel@tonic-gate			 onMouseUp="handleRelease(2);return true;"
9507c478bd9Sstevel@tonic-gate			 onMouseOut="handleRelease(2);return true;"
9517c478bd9Sstevel@tonic-gate			 title="Go to previous Diff"
9527c478bd9Sstevel@tonic-gate			 onClick="return false;">Prev Diff</a>
9537c478bd9Sstevel@tonic-gate		    </td></tr>
954daaffb31Sdp
9557c478bd9Sstevel@tonic-gate		  <tr>
956daaffb31Sdp		    <td>
9577c478bd9Sstevel@tonic-gate		      <a onMouseDown="handlePress(6);return true;"
9587c478bd9Sstevel@tonic-gate			 onMouseUp="handleRelease(6);return true;"
9597c478bd9Sstevel@tonic-gate			 onMouseOut="handleRelease(6);return true;"
9607c478bd9Sstevel@tonic-gate			 onClick="return false;"
9617c478bd9Sstevel@tonic-gate			 title="Go to End Of File">EOF</a></td>
962daaffb31Sdp		    <td>
9637c478bd9Sstevel@tonic-gate		      <a onMouseDown="handlePress(4);return true;"
9647c478bd9Sstevel@tonic-gate			 onMouseUp="handleRelease(4);return true;"
9657c478bd9Sstevel@tonic-gate			 onMouseOut="handleRelease(4);return true;"
9667c478bd9Sstevel@tonic-gate			 title="Scroll Down: Press and Hold to accelerate"
967daaffb31Sdp			 onClick="return false;">Scroll Down</a></td>
968daaffb31Sdp		    <td>
9697c478bd9Sstevel@tonic-gate		      <a onMouseDown="handlePress(5);return true;"
9707c478bd9Sstevel@tonic-gate			 onMouseUp="handleRelease(5);return true;"
9717c478bd9Sstevel@tonic-gate			 onMouseOut="handleRelease(5);return true;"
9727c478bd9Sstevel@tonic-gate			 title="Go to next Diff"
9737c478bd9Sstevel@tonic-gate			 onClick="return false;">Next Diff</a></td>
974daaffb31Sdp		  </tr>
975daaffb31Sdp              </table>
976daaffb31Sdp	    </div>
977daaffb31Sdp	  </td>
9787c478bd9Sstevel@tonic-gate	  <th valign="middle" width="25%">
979daaffb31Sdp	    <form action="" name="diff" onsubmit="return ValidateDiffNum();">
980*cac38512Smjnelson		<input name="display" value="BOF" size="8" type="text"></input>
981*cac38512Smjnelson		<input name="real" value="0" size="8" type="hidden"></input>
9827c478bd9Sstevel@tonic-gate	    </form>
9837c478bd9Sstevel@tonic-gate	  </th>
984daaffb31Sdp	</tr>
9857c478bd9Sstevel@tonic-gate    </table>
9867c478bd9Sstevel@tonic-gate  </body>
9877c478bd9Sstevel@tonic-gate</html>
9887c478bd9Sstevel@tonic-gateEOF
9897c478bd9Sstevel@tonic-gate}
9907c478bd9Sstevel@tonic-gate
9917c478bd9Sstevel@tonic-gate
992daaffb31Sdp
993daaffb31Sdp#
994daaffb31Sdp# diff_to_html <filename> <filepath> { U | C } <comment>
995daaffb31Sdp#
996daaffb31Sdp# Processes the output of diff to produce an HTML file representing either
997daaffb31Sdp# context or unified diffs.
998daaffb31Sdp#
9997c478bd9Sstevel@tonic-gatediff_to_html()
10007c478bd9Sstevel@tonic-gate{
10017c478bd9Sstevel@tonic-gate	TNAME=$1
1002daaffb31Sdp	TPATH=$2
1003daaffb31Sdp	DIFFTYPE=$3
1004daaffb31Sdp	COMMENT=$4
1005daaffb31Sdp
1006daaffb31Sdp	print "$HTML<head>$STDHEAD"
1007daaffb31Sdp	print "<title>$WNAME ${DIFFTYPE}diff $TPATH</title>"
1008daaffb31Sdp
1009daaffb31Sdp	if [[ $DIFFTYPE == "U" ]]; then
1010daaffb31Sdp		print "$UDIFFCSS"
1011daaffb31Sdp	fi
1012daaffb31Sdp
1013daaffb31Sdp	cat <<-EOF
1014daaffb31Sdp	</head>
1015daaffb31Sdp	<body id="SUNWwebrev">
1016daaffb31Sdp        <a class="print" href="javascript:print()">Print this page</a>
1017daaffb31Sdp	<pre>$COMMENT</pre>
1018daaffb31Sdp        <pre>
1019daaffb31Sdp	EOF
10207c478bd9Sstevel@tonic-gate
10217c478bd9Sstevel@tonic-gate	html_quote | nawk '
1022daaffb31Sdp	/^--- new/	{ next }
1023daaffb31Sdp	/^\+\+\+ new/	{ next }
1024daaffb31Sdp	/^--- old/	{ next }
1025daaffb31Sdp	/^\*\*\* old/	{ next }
1026daaffb31Sdp	/^\*\*\*\*/	{ next }
10277c478bd9Sstevel@tonic-gate	/^-------/	{ printf "<center><h1>%s</h1></center>\n", $0; next }
1028*cac38512Smjnelson	/^\@\@.*\@\@$/	{ printf "</pre><hr></hr><pre>\n";
1029daaffb31Sdp			  printf "<span class=\"newmarker\">%s</span>\n", $0;
1030daaffb31Sdp			  next}
1031daaffb31Sdp
1032*cac38512Smjnelson	/^\*\*\*/	{ printf "<hr></hr><span class=\"oldmarker\">%s</span>\n", $0;
1033daaffb31Sdp			  next}
1034daaffb31Sdp	/^---/		{ printf "<span class=\"newmarker\">%s</span>\n", $0;
1035daaffb31Sdp			  next}
1036daaffb31Sdp	/^\+/		{printf "<span class=\"new\">%s</span>\n", $0; next}
1037daaffb31Sdp	/^!/		{printf "<span class=\"changed\">%s</span>\n", $0; next}
1038daaffb31Sdp	/^-/		{printf "<span class=\"removed\">%s</span>\n", $0; next}
1039daaffb31Sdp			{printf "%s\n", $0; next}
10407c478bd9Sstevel@tonic-gate	'
1041daaffb31Sdp
1042daaffb31Sdp	print "</pre></body></html>\n"
10437c478bd9Sstevel@tonic-gate}
10447c478bd9Sstevel@tonic-gate
10457c478bd9Sstevel@tonic-gate
1046daaffb31Sdp#
1047daaffb31Sdp# source_to_html { new | old } <filename>
1048daaffb31Sdp#
1049daaffb31Sdp# Process a plain vanilla source file to transform it into an HTML file.
1050daaffb31Sdp#
10517c478bd9Sstevel@tonic-gatesource_to_html()
10527c478bd9Sstevel@tonic-gate{
10537c478bd9Sstevel@tonic-gate	WHICH=$1
10547c478bd9Sstevel@tonic-gate	TNAME=$2
10557c478bd9Sstevel@tonic-gate
1056daaffb31Sdp	print "$HTML<head>$STDHEAD"
1057daaffb31Sdp	print "<title>$WHICH $TNAME</title>"
1058daaffb31Sdp	print "<body id=\"SUNWwebrev\">"
1059daaffb31Sdp	print "<pre>"
1060daaffb31Sdp	html_quote | nawk '{line += 1 ; printf "%4d %s\n", line, $0 }'
1061daaffb31Sdp	print "</pre></body></html>"
10627c478bd9Sstevel@tonic-gate}
10637c478bd9Sstevel@tonic-gate
1064daaffb31Sdp#
1065daaffb31Sdp# teamwarecomments {text|html} parent-file child-file
1066daaffb31Sdp#
1067daaffb31Sdp# Find the first delta in the child that's not in the parent.  Get the
1068daaffb31Sdp# newest delta from the parent, get all deltas from the child starting
1069daaffb31Sdp# with that delta, and then get all info starting with the second oldest
1070daaffb31Sdp# delta in that list (the first delta unique to the child).
10717c478bd9Sstevel@tonic-gate#
10727c478bd9Sstevel@tonic-gate# This code adapted from Bill Shannon's "spc" script
1073daaffb31Sdp#
1074daaffb31Sdpcomments_from_teamware()
10757c478bd9Sstevel@tonic-gate{
1076daaffb31Sdp	fmt=$1
1077daaffb31Sdp	pfile=$PWS/$2
1078daaffb31Sdp	cfile=$CWS/$3
10797c478bd9Sstevel@tonic-gate
1080daaffb31Sdp	if [[ -f $pfile ]]; then
10817c478bd9Sstevel@tonic-gate		psid=$(sccs prs -d:I: $pfile 2>/dev/null)
10827c478bd9Sstevel@tonic-gate	else
10837c478bd9Sstevel@tonic-gate		psid=1.1
10847c478bd9Sstevel@tonic-gate	fi
10857c478bd9Sstevel@tonic-gate
10867c478bd9Sstevel@tonic-gate	set -A sids $(sccs prs -l -r$psid -d:I: $cfile 2>/dev/null)
10877c478bd9Sstevel@tonic-gate	N=${#sids[@]}
10887c478bd9Sstevel@tonic-gate
1089daaffb31Sdp	nawkprg='
1090daaffb31Sdp		/^COMMENTS:/	{p=1; continue}
1091daaffb31Sdp		/^D [0-9]+\.[0-9]+/ {printf "--- %s ---\n", $2; p=0; }
1092daaffb31Sdp		NF == 0u	{ continue }
1093daaffb31Sdp		{if (p==0) continue; print $0 }'
1094daaffb31Sdp
10957c478bd9Sstevel@tonic-gate	if [[ $N -ge 2 ]]; then
10967c478bd9Sstevel@tonic-gate		sid1=${sids[$((N-2))]}	# Gets 2nd to last sid
10977c478bd9Sstevel@tonic-gate
1098daaffb31Sdp		if [[ $fmt == "text" ]]; then
1099daaffb31Sdp			sccs prs -l -r$sid1 $cfile  2>/dev/null | \
1100daaffb31Sdp			    nawk "$nawkprg"
1101daaffb31Sdp			return
1102daaffb31Sdp		fi
1103daaffb31Sdp
1104daaffb31Sdp		sccs prs -l -r$sid1 $cfile  2>/dev/null | \
1105daaffb31Sdp		    html_quote | bug2url | sac2url | nawk "$nawkprg"
11067c478bd9Sstevel@tonic-gate	fi
11077c478bd9Sstevel@tonic-gate}
11087c478bd9Sstevel@tonic-gate
1109daaffb31Sdp#
1110daaffb31Sdp# wxcomments {text|html} filepath
1111daaffb31Sdp#
1112daaffb31Sdp# Given the pathname of a file, find its location in a "wx" active file
1113daaffb31Sdp# list and print the following sccs comment.  Output is either text or
1114daaffb31Sdp# HTML; if the latter, embedded bugids (sequence of 5 or more digits) are
1115daaffb31Sdp# turned into URLs.
1116daaffb31Sdp#
1117daaffb31Sdpcomments_from_wx()
11187c478bd9Sstevel@tonic-gate{
1119daaffb31Sdp	typeset fmt=$1
1120daaffb31Sdp	typeset p=$2
11217c478bd9Sstevel@tonic-gate
1122daaffb31Sdp	comm=`nawk '
1123daaffb31Sdp	$1 == "'$p'" {
11247c478bd9Sstevel@tonic-gate		do getline ; while (NF > 0)
11257c478bd9Sstevel@tonic-gate		getline
11267c478bd9Sstevel@tonic-gate		while (NF > 0) { print ; getline }
11277c478bd9Sstevel@tonic-gate		exit
1128daaffb31Sdp	}' < $wxfile`
1129daaffb31Sdp
1130daaffb31Sdp	if [[ $fmt == "text" ]]; then
1131daaffb31Sdp		print "$comm"
1132daaffb31Sdp		return
1133daaffb31Sdp	fi
1134daaffb31Sdp
1135daaffb31Sdp	print "$comm" | html_quote | bug2url | sac2url
11367c478bd9Sstevel@tonic-gate}
11377c478bd9Sstevel@tonic-gate
11387c478bd9Sstevel@tonic-gate#
1139daaffb31Sdp# getcomments {text|html} filepath parentpath
1140daaffb31Sdp#
1141daaffb31Sdp# Fetch the comments depending on what SCM mode we're in.
1142daaffb31Sdp#
1143daaffb31Sdpgetcomments()
1144daaffb31Sdp{
1145daaffb31Sdp	typeset fmt=$1
1146daaffb31Sdp	typeset p=$2
1147daaffb31Sdp	typeset pp=$3
11487c478bd9Sstevel@tonic-gate
1149daaffb31Sdp	if [[ -n $wxfile ]]; then
1150daaffb31Sdp		comments_from_wx $fmt $p
1151daaffb31Sdp	else
1152daaffb31Sdp		if [[ $SCM_MODE == "teamware" ]]; then
1153daaffb31Sdp			comments_from_teamware $fmt $pp $p
1154daaffb31Sdp		fi
1155daaffb31Sdp	fi
1156daaffb31Sdp}
1157daaffb31Sdp
1158daaffb31Sdp#
1159daaffb31Sdp# printCI <total-changed> <inserted> <deleted> <modified> <unchanged>
1160daaffb31Sdp#
1161daaffb31Sdp# Print out Code Inspection figures similar to sccs-prt(1) format.
1162daaffb31Sdp#
1163daaffb31Sdpfunction printCI
1164daaffb31Sdp{
1165daaffb31Sdp	integer tot=$1 ins=$2 del=$3 mod=$4 unc=$5
1166daaffb31Sdp	typeset str
1167daaffb31Sdp	if (( tot == 1 )); then
1168daaffb31Sdp		str="line"
1169daaffb31Sdp	else
1170daaffb31Sdp		str="lines"
1171daaffb31Sdp	fi
1172daaffb31Sdp	printf '%d %s changed: %d ins; %d del; %d mod; %d unchg\n' \
1173daaffb31Sdp	    $tot $str $ins $del $mod $unc
1174daaffb31Sdp}
1175daaffb31Sdp
1176daaffb31Sdp
1177daaffb31Sdp#
1178daaffb31Sdp# difflines <oldfile> <newfile>
1179daaffb31Sdp#
1180daaffb31Sdp# Calculate and emit number of added, removed, modified and unchanged lines,
1181daaffb31Sdp# and total lines changed, the sum of added + removed + modified.
1182daaffb31Sdp#
11837c478bd9Sstevel@tonic-gatefunction difflines
11847c478bd9Sstevel@tonic-gate{
1185daaffb31Sdp	integer tot mod del ins unc err
11867c478bd9Sstevel@tonic-gate	typeset filename
11877c478bd9Sstevel@tonic-gate
11887c478bd9Sstevel@tonic-gate	diff -e $1 $2 | eval $( nawk '
1189daaffb31Sdp	# Change range of lines: N,Nc
11907c478bd9Sstevel@tonic-gate	/^[0-9]*,[0-9]*c$/ {
11917c478bd9Sstevel@tonic-gate		n=split(substr($1,1,length($1)-1), counts, ",");
11927c478bd9Sstevel@tonic-gate		if (n != 2) {
11937c478bd9Sstevel@tonic-gate		    error=2
11947c478bd9Sstevel@tonic-gate		    exit;
11957c478bd9Sstevel@tonic-gate		}
1196daaffb31Sdp		#
1197daaffb31Sdp		# 3,5c means lines 3 , 4 and 5 are changed, a total of 3 lines.
1198daaffb31Sdp		# following would be 5 - 3 = 2! Hence +1 for correction.
1199daaffb31Sdp		#
12007c478bd9Sstevel@tonic-gate		r=(counts[2]-counts[1])+1;
1201daaffb31Sdp
1202daaffb31Sdp		#
1203daaffb31Sdp		# Now count replacement lines: each represents a change instead
1204daaffb31Sdp		# of a delete, so increment c and decrement r.
1205daaffb31Sdp		#
12067c478bd9Sstevel@tonic-gate		while (getline != /^\.$/) {
12077c478bd9Sstevel@tonic-gate			c++;
12087c478bd9Sstevel@tonic-gate			r--;
12097c478bd9Sstevel@tonic-gate		}
1210daaffb31Sdp		#
1211daaffb31Sdp		# If there were more replacement lines than original lines,
1212daaffb31Sdp		# then r will be negative; in this case there are no deletions,
1213daaffb31Sdp		# but there are r changes that should be counted as adds, and
1214daaffb31Sdp		# since r is negative, subtract it from a and add it to c.
1215daaffb31Sdp		#
12167c478bd9Sstevel@tonic-gate		if (r < 0) {
12177c478bd9Sstevel@tonic-gate			a-=r;
12187c478bd9Sstevel@tonic-gate			c+=r;
12197c478bd9Sstevel@tonic-gate		}
1220daaffb31Sdp
1221daaffb31Sdp		#
1222daaffb31Sdp		# If there were more original lines than replacement lines, then
1223daaffb31Sdp		# r will be positive; in this case, increment d by that much.
1224daaffb31Sdp		#
12257c478bd9Sstevel@tonic-gate		if (r > 0) {
12267c478bd9Sstevel@tonic-gate			d+=r;
12277c478bd9Sstevel@tonic-gate		}
12287c478bd9Sstevel@tonic-gate		next;
12297c478bd9Sstevel@tonic-gate	}
12307c478bd9Sstevel@tonic-gate
1231daaffb31Sdp	# Change lines: Nc
12327c478bd9Sstevel@tonic-gate	/^[0-9].*c$/ {
1233daaffb31Sdp		# The first line is a replacement; any more are additions.
12347c478bd9Sstevel@tonic-gate		if (getline != /^\.$/) {
12357c478bd9Sstevel@tonic-gate			c++;
12367c478bd9Sstevel@tonic-gate			while (getline != /^\.$/) a++;
12377c478bd9Sstevel@tonic-gate		}
12387c478bd9Sstevel@tonic-gate		next;
12397c478bd9Sstevel@tonic-gate	}
12407c478bd9Sstevel@tonic-gate
1241daaffb31Sdp	# Add lines: both Na and N,Na
12427c478bd9Sstevel@tonic-gate	/^[0-9].*a$/ {
12437c478bd9Sstevel@tonic-gate		while (getline != /^\.$/) a++;
12447c478bd9Sstevel@tonic-gate		next;
12457c478bd9Sstevel@tonic-gate	}
12467c478bd9Sstevel@tonic-gate
1247daaffb31Sdp	# Delete range of lines: N,Nd
12487c478bd9Sstevel@tonic-gate	/^[0-9]*,[0-9]*d$/ {
12497c478bd9Sstevel@tonic-gate		n=split(substr($1,1,length($1)-1), counts, ",");
12507c478bd9Sstevel@tonic-gate		if (n != 2) {
12517c478bd9Sstevel@tonic-gate			error=2
12527c478bd9Sstevel@tonic-gate			exit;
12537c478bd9Sstevel@tonic-gate		}
1254daaffb31Sdp		#
1255daaffb31Sdp		# 3,5d means lines 3 , 4 and 5 are deleted, a total of 3 lines.
1256daaffb31Sdp		# following would be 5 - 3 = 2! Hence +1 for correction.
1257daaffb31Sdp		#
12587c478bd9Sstevel@tonic-gate		r=(counts[2]-counts[1])+1;
12597c478bd9Sstevel@tonic-gate		d+=r;
12607c478bd9Sstevel@tonic-gate		next;
12617c478bd9Sstevel@tonic-gate	}
12627c478bd9Sstevel@tonic-gate
1263daaffb31Sdp	# Delete line: Nd.   For example 10d says line 10 is deleted.
12647c478bd9Sstevel@tonic-gate	/^[0-9]*d$/ {d++; next}
12657c478bd9Sstevel@tonic-gate
1266daaffb31Sdp	# Should not get here!
12677c478bd9Sstevel@tonic-gate	{
12687c478bd9Sstevel@tonic-gate		error=1;
12697c478bd9Sstevel@tonic-gate		exit;
12707c478bd9Sstevel@tonic-gate	}
12717c478bd9Sstevel@tonic-gate
1272daaffb31Sdp	# Finish off - print results
12737c478bd9Sstevel@tonic-gate	END {
1274daaffb31Sdp		printf("tot=%d;mod=%d;del=%d;ins=%d;err=%d\n",
12757c478bd9Sstevel@tonic-gate		    (c+d+a), c, d, a, error);
12767c478bd9Sstevel@tonic-gate	}' )
12777c478bd9Sstevel@tonic-gate
12787c478bd9Sstevel@tonic-gate	# End of nawk, Check to see if any trouble occurred.
12797c478bd9Sstevel@tonic-gate	if (( $? > 0 || err > 0 )); then
1280daaffb31Sdp		print "Unexpected Error occurred reading" \
1281daaffb31Sdp		    "\`diff -e $1 $2\`: \$?=$?, err=" $err
1282daaffb31Sdp		return
1283daaffb31Sdp	fi
1284daaffb31Sdp
12857c478bd9Sstevel@tonic-gate	# Accumulate totals
12867c478bd9Sstevel@tonic-gate	(( TOTL += tot ))
1287daaffb31Sdp	(( TMOD += mod ))
12887c478bd9Sstevel@tonic-gate	(( TDEL += del ))
12897c478bd9Sstevel@tonic-gate	(( TINS += ins ))
12907c478bd9Sstevel@tonic-gate	# Calculate unchanged lines
12917c478bd9Sstevel@tonic-gate	wc -l $1 | read unc filename
12927c478bd9Sstevel@tonic-gate	if (( unc > 0 )); then
1293daaffb31Sdp		(( unc -= del + mod ))
12947c478bd9Sstevel@tonic-gate		(( TUNC += unc ))
12957c478bd9Sstevel@tonic-gate	fi
12967c478bd9Sstevel@tonic-gate	# print summary
1297daaffb31Sdp	print "<span class=\"lineschanged\">"
1298daaffb31Sdp	printCI $tot $ins $del $mod $unc
1299daaffb31Sdp	print "</span>"
13007c478bd9Sstevel@tonic-gate}
13017c478bd9Sstevel@tonic-gate
1302daaffb31Sdp
13037c478bd9Sstevel@tonic-gate#
1304daaffb31Sdp# flist_from_wx
1305daaffb31Sdp#
1306daaffb31Sdp# Sets up webrev to source its information from a wx-formatted file.
1307daaffb31Sdp# Sets the global 'wxfile' variable.
1308daaffb31Sdp#
1309daaffb31Sdpfunction flist_from_wx
13107c478bd9Sstevel@tonic-gate{
1311daaffb31Sdp	typeset argfile=$1
1312daaffb31Sdp	if [[ -n ${argfile%%/*} ]]; then
1313daaffb31Sdp		#
1314daaffb31Sdp		# If the wx file pathname is relative then make it absolute
1315daaffb31Sdp		# because the webrev does a "cd" later on.
1316daaffb31Sdp		#
1317daaffb31Sdp		wxfile=$PWD/$argfile
13187c478bd9Sstevel@tonic-gate	else
1319daaffb31Sdp		wxfile=$argfile
13207c478bd9Sstevel@tonic-gate	fi
13217c478bd9Sstevel@tonic-gate
13227c478bd9Sstevel@tonic-gate	nawk '{ c = 1; print;
13237c478bd9Sstevel@tonic-gate	  while (getline) {
13247c478bd9Sstevel@tonic-gate		if (NF == 0) { c = -c; continue }
13257c478bd9Sstevel@tonic-gate		if (c > 0) print
13267c478bd9Sstevel@tonic-gate	  }
1327daaffb31Sdp	}' $wxfile > $FLIST
13287c478bd9Sstevel@tonic-gate
1329daaffb31Sdp	print " Done."
1330daaffb31Sdp}
13317c478bd9Sstevel@tonic-gate
1332daaffb31Sdp#
1333daaffb31Sdp# flist_from_teamware [ <args-to-putback-n> ]
1334daaffb31Sdp#
1335daaffb31Sdp# Generate the file list by extracting file names from a putback -n.  Some
1336daaffb31Sdp# names may come from the "update/create" messages and others from the
1337daaffb31Sdp# "currently checked out" warning.  Renames are detected here too.  Extract
1338daaffb31Sdp# values for CODEMGR_WS and CODEMGR_PARENT from the output of the putback
1339daaffb31Sdp# -n as well, but remove them if they are already defined.
1340daaffb31Sdp#
1341daaffb31Sdpfunction flist_from_teamware
1342daaffb31Sdp{
1343daaffb31Sdp	if [[ -n $codemgr_parent ]]; then
1344daaffb31Sdp		if [[ ! -d $codemgr_parent/Codemgr_wsdata ]]; then
1345daaffb31Sdp			print -u2 "parent $codemgr_parent doesn't look like a" \
1346daaffb31Sdp			    "valid teamware workspace"
13477c478bd9Sstevel@tonic-gate			exit 1
13487c478bd9Sstevel@tonic-gate		fi
1349daaffb31Sdp		parent_args="-p $codemgr_parent"
13507c478bd9Sstevel@tonic-gate	fi
13517c478bd9Sstevel@tonic-gate
1352daaffb31Sdp	print " File list from: 'putback -n $parent_args $*' ... \c"
13537c478bd9Sstevel@tonic-gate
1354daaffb31Sdp	putback -n $parent_args $* 2>&1 |
1355daaffb31Sdp	    nawk '
1356daaffb31Sdp		/^update:|^create:/	{print $2}
1357daaffb31Sdp		/^Parent workspace:/	{printf("CODEMGR_PARENT=%s\n",$3)}
1358daaffb31Sdp		/^Child workspace:/	{printf("CODEMGR_WS=%s\n",$3)}
1359daaffb31Sdp		/^The following files are currently checked out/ {p = 1; continue}
1360daaffb31Sdp		NF == 0			{p=0 ; continue}
1361daaffb31Sdp		/^rename/		{old=$3}
1362daaffb31Sdp		$1 == "to:"		{print $2, old}
1363daaffb31Sdp		/^"/			{continue}
1364daaffb31Sdp		p == 1			{print $1}' |
1365daaffb31Sdp	    sort -r -k 1,1 -u | sort > $FLIST
13667c478bd9Sstevel@tonic-gate
1367daaffb31Sdp	print " Done."
1368daaffb31Sdp}
1369daaffb31Sdp
1370daaffb31Sdpfunction env_from_flist
1371daaffb31Sdp{
1372daaffb31Sdp	[[ -r $FLIST ]] || return
1373daaffb31Sdp
1374daaffb31Sdp	#
1375daaffb31Sdp	# Use "eval" to set env variables that are listed in the file
1376daaffb31Sdp	# list.  Then copy those into our local versions of those
1377daaffb31Sdp	# variables if they have not been set already.
1378daaffb31Sdp	#
13797c478bd9Sstevel@tonic-gate	eval `sed -e "s/#.*$//" $FLIST | grep = `
13807c478bd9Sstevel@tonic-gate
1381daaffb31Sdp	[[ -z $codemgr_ws && -n $CODEMGR_WS ]] && codemgr_ws=$CODEMGR_WS
13827c478bd9Sstevel@tonic-gate
1383daaffb31Sdp	#
1384daaffb31Sdp	# Check to see if CODEMGR_PARENT is set in the flist file.
1385daaffb31Sdp	#
1386daaffb31Sdp	[[ -z $codemgr_parent && -n $CODEMGR_PARENT ]] && \
1387daaffb31Sdp	    codemgr_parent=$CODEMGR_PARENT
1388daaffb31Sdp}
1389daaffb31Sdp
1390daaffb31Sdp#
1391daaffb31Sdp# detect_scm
1392daaffb31Sdp#
1393daaffb31Sdp# We dynamically test the SCM type; this allows future extensions to
1394daaffb31Sdp# new SCM types
1395daaffb31Sdp#
1396daaffb31Sdpfunction detect_scm
1397daaffb31Sdp{
1398daaffb31Sdp	#
1399daaffb31Sdp	# If CODEMGR_WS is specified in the flist file, we assume teamware.
1400daaffb31Sdp	#
1401daaffb31Sdp	if [[ -r $FLIST ]]; then
1402daaffb31Sdp		egrep '^CODEMGR_WS=' $FLIST > /dev/null 2>&1
1403daaffb31Sdp		if [[ $? -eq 0 ]]; then
1404daaffb31Sdp			print "teamware"
1405daaffb31Sdp			return
1406daaffb31Sdp		fi
1407daaffb31Sdp	fi
1408daaffb31Sdp
1409daaffb31Sdp	#
1410daaffb31Sdp	# The presence of $CODEMGR_WS and a Codemgr_wsdata directory
1411daaffb31Sdp	# is our clue that this is a teamware workspace.
1412daaffb31Sdp	#
1413daaffb31Sdp	if [[ -n $CODEMGR_WS && -d "$CODEMGR_WS/Codemgr_wsdata" ]]; then
1414daaffb31Sdp		print "teamware"
1415daaffb31Sdp	else
1416daaffb31Sdp		print "unknown"
1417daaffb31Sdp	fi
1418daaffb31Sdp}
1419daaffb31Sdp
142014983201Sdpfunction look_for_prog
142114983201Sdp{
142214983201Sdp	typeset path
142314983201Sdp	typeset ppath
142414983201Sdp	typeset progname=$1
142514983201Sdp
142614983201Sdp	ppath=$PATH
142714983201Sdp	ppath=$ppath:/usr/sfw/bin:/usr/bin:/usr/sbin
142814983201Sdp	ppath=$ppath:/opt/teamware/bin:/opt/onbld/bin
142914983201Sdp	ppath=$ppath:/opt/onbld/bin/`/usr/bin/uname -p`
143014983201Sdp
143114983201Sdp	PATH=$ppath prog=`whence $progname`
143214983201Sdp	if [[ -n $prog ]]; then
143314983201Sdp		print $prog
143414983201Sdp	fi
143514983201Sdp}
143614983201Sdp
1437daaffb31Sdp#
1438daaffb31Sdp# Usage message.
1439daaffb31Sdp#
1440daaffb31Sdpfunction usage
1441daaffb31Sdp{
1442daaffb31Sdp	print 'Usage:\twebrev [common-options]
1443daaffb31Sdp	webrev [common-options] ( <file> | - )
1444daaffb31Sdp	webrev [common-options] -w <wx file>
1445daaffb31Sdp	webrev [common-options] -l [arguments to 'putback']
1446daaffb31Sdp
1447daaffb31SdpOptions:
1448daaffb31Sdp	-O: Print bugids/arc cases suitable for OpenSolaris.
1449daaffb31Sdp	-i <filename>: Include <filename> in the index.html file.
1450daaffb31Sdp	-o <outdir>: Output webrev to specified directory.
1451daaffb31Sdp	-p <compare-against>: Use specified parent wkspc or basis for comparison
1452daaffb31Sdp	-w <wxfile>: Use specified wx active file.
1453daaffb31Sdp
1454daaffb31SdpEnvironment:
1455daaffb31Sdp	WDIR: Control the output directory.
1456daaffb31Sdp	WEBREV_BUGURL: Control the URL prefix for bugids.
1457daaffb31Sdp	WEBREV_SACURL: Control the URL prefix for ARC cases.
1458daaffb31Sdp
1459daaffb31SdpSCM Environment:
1460daaffb31Sdp	Teamware: CODEMGR_WS: Workspace location.
1461daaffb31Sdp	Teamware: CODEMGR_PARENT: Parent workspace location.
1462daaffb31Sdp'
1463daaffb31Sdp
1464daaffb31Sdp	exit 2
1465daaffb31Sdp}
1466daaffb31Sdp
1467daaffb31Sdp#
1468daaffb31Sdp#
1469daaffb31Sdp# Main program starts here
1470daaffb31Sdp#
1471daaffb31Sdp#
1472daaffb31Sdp
1473daaffb31Sdptrap "rm -f /tmp/$$.* ; exit" 0 1 2 3 15
1474daaffb31Sdp
1475daaffb31Sdpset +o noclobber
1476daaffb31Sdp
147714983201Sdp[[ -z $WDIFF ]] && WDIFF=`look_for_prog wdiff`
147814983201Sdp[[ -z $WX ]] && WX=`look_for_prog wx`
147914983201Sdp[[ -z $CODEREVIEW ]] && CODEREVIEW=`look_for_prog codereview`
148014983201Sdp[[ -z $PS2PDF ]] && PS2PDF=`look_for_prog ps2pdf`
148114983201Sdp[[ -z $PERL ]] && PERL=`look_for_prog perl`
148214983201Sdp
148314983201Sdpif [[ ! -x $PERL ]]; then
148414983201Sdp	print -u2 "Error: No perl interpreter found.  Exiting."
148514983201Sdp	exit 1
1486daaffb31Sdpfi
148714983201Sdp
148814983201Sdp#
148914983201Sdp# These aren't fatal, but we want to note them to the user.
149014983201Sdp# We don't warn on the absence of 'wx' until later when we've
149114983201Sdp# determined that we actually need to try to invoke it.
149214983201Sdp#
149314983201Sdp[[ ! -x $CODEREVIEW ]] && print -u2 "WARNING: codereview(1) not found."
149414983201Sdp[[ ! -x $PS2PDF ]] && print -u2 "WARNING: ps2pdf(1) not found."
149514983201Sdp[[ ! -x $WDIFF ]] && print -u2 "WARNING: wdiff not found."
1496daaffb31Sdp
1497daaffb31Sdp# Declare global total counters.
1498daaffb31Sdpinteger TOTL TINS TDEL TMOD TUNC
1499daaffb31Sdp
150014983201Sdpflist_mode=
150114983201Sdpflist_file=
1502daaffb31Sdpiflag=
1503daaffb31Sdpoflag=
1504daaffb31Sdppflag=
1505daaffb31Sdplflag=
1506daaffb31Sdpwflag=
1507daaffb31SdpOflag=
1508daaffb31Sdpwhile getopts "i:o:p:lwO" opt
1509daaffb31Sdpdo
1510daaffb31Sdp	case $opt in
1511daaffb31Sdp	i)	iflag=1
1512daaffb31Sdp		INCLUDE_FILE=$OPTARG;;
1513daaffb31Sdp
1514daaffb31Sdp	o)	oflag=1
1515daaffb31Sdp		WDIR=$OPTARG;;
1516daaffb31Sdp
1517daaffb31Sdp	p)	pflag=1
1518daaffb31Sdp		codemgr_parent=$OPTARG;;
1519daaffb31Sdp
1520daaffb31Sdp	#
1521daaffb31Sdp	# If -l has been specified, we need to abort further options
1522daaffb31Sdp	# processing, because subsequent arguments are going to be
1523daaffb31Sdp	# arguments to 'putback -n'.
1524daaffb31Sdp	#
1525daaffb31Sdp	l)	lflag=1
1526daaffb31Sdp		break;;
1527daaffb31Sdp
1528daaffb31Sdp	w)	wflag=1;;
1529daaffb31Sdp
1530daaffb31Sdp	O)	Oflag=1;;
1531daaffb31Sdp
1532daaffb31Sdp	?)	usage;;
1533daaffb31Sdp	esac
1534daaffb31Sdpdone
1535daaffb31Sdp
1536daaffb31SdpFLIST=/tmp/$$.flist
1537daaffb31Sdp
1538daaffb31Sdpif [[ -n $wflag && -n $lflag ]]; then
1539daaffb31Sdp	usage
1540daaffb31Sdpfi
1541daaffb31Sdp
1542daaffb31Sdp#
1543daaffb31Sdp# If this manually set as the parent, and it appears to be an earlier webrev,
1544daaffb31Sdp# then note that fact and set the parent to the raw_files/new subdirectory.
1545daaffb31Sdp#
1546daaffb31Sdpif [[ -n $pflag && -d $codemgr_parent/raw_files/new ]]; then
1547daaffb31Sdp	parent_webrev="$codemgr_parent"
1548daaffb31Sdp	codemgr_parent="$codemgr_parent/raw_files/new"
1549daaffb31Sdpfi
1550daaffb31Sdp
1551daaffb31Sdpif [[ -z $wflag && -z $lflag ]]; then
1552daaffb31Sdp	shift $(($OPTIND - 1))
1553daaffb31Sdp
1554daaffb31Sdp	if [[ $1 == "-" ]]; then
1555daaffb31Sdp		cat > $FLIST
155614983201Sdp		flist_mode="stdin"
155714983201Sdp		flist_done=1
155814983201Sdp		shift
1559daaffb31Sdp	elif [[ -n $1 ]]; then
156014983201Sdp		if [[ ! -r $1 ]]; then
1561daaffb31Sdp			print -u2 "$1: no such file or not readable"
1562daaffb31Sdp			usage
1563daaffb31Sdp		fi
1564daaffb31Sdp		cat $1 > $FLIST
156514983201Sdp		flist_mode="file"
156614983201Sdp		flist_file=$1
156714983201Sdp		flist_done=1
156814983201Sdp		shift
1569daaffb31Sdp	else
157014983201Sdp		flist_mode="auto"
1571daaffb31Sdp	fi
1572daaffb31Sdpfi
1573daaffb31Sdp
1574daaffb31Sdp#
1575daaffb31Sdp# Before we go on to further consider -l and -w, work out which SCM we think
1576daaffb31Sdp# is in use.
1577daaffb31Sdp#
1578daaffb31SdpSCM_MODE=`detect_scm $FLIST`
1579daaffb31Sdpif [[ $SCM_MODE == "unknown" ]]; then
1580daaffb31Sdp	print -u2 "Unable to determine SCM type currently in use."
1581daaffb31Sdp	print -u2 "For teamware: webrev looks for \$CODEMGR_WS either in"
1582daaffb31Sdp	print -u2 "              the environment or in the file list."
15837c478bd9Sstevel@tonic-gate	exit 1
15847c478bd9Sstevel@tonic-gatefi
15857c478bd9Sstevel@tonic-gate
1586daaffb31Sdpprint -u2 "   SCM detected: $SCM_MODE"
1587daaffb31Sdp
1588daaffb31Sdpif [[ -n $lflag ]]; then
1589daaffb31Sdp	#
1590daaffb31Sdp	# If the -l flag is given instead of the name of a file list,
1591daaffb31Sdp	# then generate the file list by extracting file names from a
1592daaffb31Sdp	# putback -n.
1593daaffb31Sdp	#
1594daaffb31Sdp	shift $(($OPTIND - 1))
1595daaffb31Sdp	flist_from_teamware "$*"
1596daaffb31Sdp	flist_done=1
1597daaffb31Sdp	shift $#
1598daaffb31Sdp
1599daaffb31Sdpelif [[ -n $wflag ]]; then
1600daaffb31Sdp	#
1601daaffb31Sdp	# If the -w is given then assume the file list is in Bonwick's "wx"
1602daaffb31Sdp	# command format, i.e.  pathname lines alternating with SCCS comment
1603daaffb31Sdp	# lines with blank lines as separators.  Use the SCCS comments later
1604daaffb31Sdp	# in building the index.html file.
1605daaffb31Sdp	#
1606daaffb31Sdp	shift $(($OPTIND - 1))
1607daaffb31Sdp	wxfile=$1
1608daaffb31Sdp	if [[ -z $wxfile && -n $CODEMGR_WS ]]; then
1609daaffb31Sdp		if [[ -r $CODEMGR_WS/wx/active ]]; then
1610daaffb31Sdp			wxfile=$CODEMGR_WS/wx/active
1611daaffb31Sdp		fi
1612daaffb31Sdp	fi
1613daaffb31Sdp
1614daaffb31Sdp	[[ -z $wxfile ]] && print -u2 "wx file not specified, and could not " \
1615daaffb31Sdp	    "be auto-detected (check \$CODEMGR_WS)" && exit 1
1616daaffb31Sdp
1617daaffb31Sdp	print -u2 " File list from: wx 'active' file '$wxfile' ... \c"
1618daaffb31Sdp	flist_from_wx $wxfile
1619daaffb31Sdp	flist_done=1
1620daaffb31Sdp	if [[ -n "$*" ]]; then
1621daaffb31Sdp		shift
1622daaffb31Sdp	fi
162314983201Sdpelif [[ $flist_mode == "stdin" ]]; then
162414983201Sdp	print -u2 " File list from: standard input"
162514983201Sdpelif [[ $flist_mode == "file" ]]; then
162614983201Sdp	print -u2 " File list from: $flist_file"
1627daaffb31Sdpfi
1628daaffb31Sdp
1629daaffb31Sdpif [[ $# -gt 0 ]]; then
163014983201Sdp	print -u2 "WARNING: unused arguments: $*"
1631daaffb31Sdpfi
1632daaffb31Sdp
1633daaffb31Sdpif [[ $SCM_MODE == "teamware" ]]; then
1634daaffb31Sdp	#
1635daaffb31Sdp	# Parent (internally $codemgr_parent) and workspace ($codemgr_ws) can
1636daaffb31Sdp	# be set in a number of ways, in decreasing precedence:
1637daaffb31Sdp	#
1638daaffb31Sdp	#      1) on the command line (only for the parent)
1639daaffb31Sdp	#      2) in the user environment
1640daaffb31Sdp	#      3) in the flist
1641daaffb31Sdp	#      4) automatically based on the workspace (only for the parent)
1642daaffb31Sdp	#
1643daaffb31Sdp
1644daaffb31Sdp	#
1645daaffb31Sdp	# Here is case (2): the user environment
1646daaffb31Sdp	#
1647daaffb31Sdp	[[ -z $codemgr_ws && -n $CODEMGR_WS ]] && codemgr_ws=$CODEMGR_WS
1648daaffb31Sdp	if [[ -n $codemgr_ws && ! -d $codemgr_ws ]]; then
1649daaffb31Sdp		print -u2 "$codemgr_ws: no such workspace"
16507c478bd9Sstevel@tonic-gate		exit 1
16517c478bd9Sstevel@tonic-gate	fi
16527c478bd9Sstevel@tonic-gate
1653daaffb31Sdp	[[ -z $codemgr_parent && -n $CODEMGR_PARENT ]] && \
1654daaffb31Sdp	    codemgr_parent=$CODEMGR_PARENT
1655daaffb31Sdp	if [[ -n $codemgr_parent && ! -d $codemgr_parent ]]; then
1656daaffb31Sdp		print -u2 "$codemgr_parent: no such directory"
16577c478bd9Sstevel@tonic-gate		exit 1
16587c478bd9Sstevel@tonic-gate	fi
16597c478bd9Sstevel@tonic-gate
1660daaffb31Sdp	#
1661daaffb31Sdp	# If we're in auto-detect mode and we haven't already gotten the file
1662daaffb31Sdp	# list, then see if we can get it by probing for wx.
1663daaffb31Sdp	#
166414983201Sdp	if [[ -z $flist_done && $flist_mode == "auto" && -n $codemgr_ws ]]; then
166514983201Sdp		if [[ ! -x $WX ]]; then
166614983201Sdp			print -u2 "WARNING: wx not found!"
1667daaffb31Sdp		fi
16687c478bd9Sstevel@tonic-gate
1669daaffb31Sdp		#
1670daaffb31Sdp		# We need to use wx list -w so that we get renamed files, etc.
1671daaffb31Sdp		# but only if a wx active file exists-- otherwise wx will
1672daaffb31Sdp		# hang asking us to initialize our wx information.
1673daaffb31Sdp		#
167414983201Sdp		if [[ -x $WX && -f $codemgr_ws/wx/active ]]; then
1675daaffb31Sdp			print -u2 " File list from: 'wx list -w' ... \c"
1676daaffb31Sdp			$WX list -w > $FLIST
1677daaffb31Sdp			$WX comments > /tmp/$$.wx_comments
1678daaffb31Sdp			wxfile=/tmp/$$.wx_comments
1679daaffb31Sdp			print -u2 "done"
1680daaffb31Sdp			flist_done=1
1681daaffb31Sdp		fi
1682daaffb31Sdp	fi
1683daaffb31Sdp
1684daaffb31Sdp	#
1685daaffb31Sdp	# If by hook or by crook we've gotten a file list by now (perhaps
1686daaffb31Sdp	# from the command line), eval it to extract environment variables from
1687daaffb31Sdp	# it: This is step (3).
1688daaffb31Sdp	#
1689daaffb31Sdp	env_from_flist
1690daaffb31Sdp
1691daaffb31Sdp	#
1692daaffb31Sdp	# Continuing step (3): If we still have no file list, we'll try to get
1693daaffb31Sdp	# it from teamware.
1694daaffb31Sdp	#
1695daaffb31Sdp	if [[ -z $flist_done ]]; then
1696daaffb31Sdp		flist_from_teamware
1697daaffb31Sdp		env_from_flist
1698daaffb31Sdp	fi
1699daaffb31Sdp
1700daaffb31Sdp	#
1701daaffb31Sdp	# Observe true directory name of CODEMGR_WS, as used later in
1702daaffb31Sdp	# webrev title.
1703daaffb31Sdp	#
1704daaffb31Sdp	codemgr_ws=$(cd $codemgr_ws;print $PWD)
1705daaffb31Sdp
1706daaffb31Sdp	#
1707daaffb31Sdp	# (4) If we still don't have a value for codemgr_parent, get it
1708daaffb31Sdp	# from workspace.
1709daaffb31Sdp	#
1710daaffb31Sdp	[[ -z $codemgr_parent ]] && codemgr_parent=`workspace parent`
1711daaffb31Sdp	if [[ ! -d $codemgr_parent ]]; then
1712daaffb31Sdp		print -u2 "$CODEMGR_PARENT: no such parent workspace"
1713daaffb31Sdp		exit 1
1714daaffb31Sdp	fi
1715daaffb31Sdp
1716daaffb31Sdp	#
1717daaffb31Sdp	# Reset CODEMGR_WS to make sure teamware commands are happy.
1718daaffb31Sdp	#
1719daaffb31Sdp	CODEMGR_WS=$codemgr_ws
1720daaffb31Sdp	CWS=$codemgr_ws
1721daaffb31Sdp	PWS=$codemgr_parent
1722daaffb31Sdpfi
1723daaffb31Sdp
1724daaffb31Sdp#
1725daaffb31Sdp# If the user didn't specify a -i option, check to see if there is a
1726daaffb31Sdp# webrev-info file in the workspace directory.
1727daaffb31Sdp#
1728daaffb31Sdpif [[ -z $iflag && -r "$CWS/webrev-info" ]]; then
1729daaffb31Sdp	iflag=1
1730daaffb31Sdp	INCLUDE_FILE="$CWS/webrev-info"
1731daaffb31Sdpfi
1732daaffb31Sdp
1733daaffb31Sdpif [[ -n $iflag ]]; then
1734daaffb31Sdp	if [[ ! -r $INCLUDE_FILE ]]; then
1735daaffb31Sdp		print -u2 "include file '$INCLUDE_FILE' does not exist or is" \
1736daaffb31Sdp		    "not readable."
1737daaffb31Sdp		exit 1
1738daaffb31Sdp	else
1739daaffb31Sdp		#
1740daaffb31Sdp		# $INCLUDE_FILE may be a relative path, and the script alters
1741daaffb31Sdp		# PWD, so we just stash a copy in /tmp.
1742daaffb31Sdp		#
1743daaffb31Sdp		cp $INCLUDE_FILE /tmp/$$.include
1744daaffb31Sdp	fi
1745daaffb31Sdpfi
1746daaffb31Sdp
1747daaffb31Sdp#
1748daaffb31Sdp# Output directory.
1749daaffb31Sdp#
1750daaffb31SdpWDIR=${WDIR:-$CWS/webrev}
1751daaffb31Sdp
1752daaffb31Sdp#
1753daaffb31Sdp# Name of the webrev, derived from the workspace name; in the
1754daaffb31Sdp# future this could potentially be an option.
1755daaffb31Sdp#
1756daaffb31SdpWNAME=${CWS##*/}
1757daaffb31Sdp
1758e0e0293aSjmcpif [ "${WDIR%%/*}" ]; then
17597c478bd9Sstevel@tonic-gate	WDIR=$PWD/$WDIR
17607c478bd9Sstevel@tonic-gatefi
1761daaffb31Sdp
1762daaffb31Sdpif [[ ! -d $WDIR ]]; then
1763daaffb31Sdp	mkdir -p $WDIR
1764daaffb31Sdp	[[ $? != 0 ]] && exit 1
17657c478bd9Sstevel@tonic-gatefi
17667c478bd9Sstevel@tonic-gate
1767daaffb31Sdp#
1768daaffb31Sdp# Summarize what we're going to do.
1769daaffb31Sdp#
1770daaffb31Sdpprint "      Workspace: $CWS"
1771daaffb31Sdpif [[ -n $parent_webrev ]]; then
1772daaffb31Sdp	print "Compare against: webrev at $parent_webrev"
1773daaffb31Sdpelse
1774daaffb31Sdp	print "Compare against: $PWS"
1775daaffb31Sdpfi
1776daaffb31Sdp
1777daaffb31Sdp[[ -n $INCLUDE_FILE ]] && print "      Including: $INCLUDE_FILE"
1778daaffb31Sdpprint "      Output to: $WDIR"
1779daaffb31Sdp
1780daaffb31Sdp#
17817c478bd9Sstevel@tonic-gate# Save the file list in the webrev dir
1782daaffb31Sdp#
1783daaffb31Sdp[[ ! $FLIST -ef $WDIR/file.list ]] && cp $FLIST $WDIR/file.list
17847c478bd9Sstevel@tonic-gate
1785daaffb31Sdp#
1786daaffb31Sdp#    Bug IDs will be replaced by a URL.  Order of precedence
1787daaffb31Sdp#    is: default location, $WEBREV_BUGURL, the -O flag.
1788daaffb31Sdp#
1789daaffb31SdpBUGURL='http://monaco.sfbay.sun.com/detail.jsp?cr='
1790daaffb31Sdp[[ -n $WEBREV_BUGURL ]] && BUGURL="$WEBREV_BUGURL"
1791daaffb31Sdp[[ -n "$Oflag" ]] && \
1792daaffb31Sdp    BUGURL='http://bugs.opensolaris.org/bugdatabase/view_bug.do?bug_id='
17937c478bd9Sstevel@tonic-gate
1794daaffb31Sdp#
1795daaffb31Sdp#    Likewise, ARC cases will be replaced by a URL.  Order of precedence
1796daaffb31Sdp#    is: default, $WEBREV_SACURL, the -O flag.
1797daaffb31Sdp#
1798daaffb31Sdp#    Note that -O also triggers different substitution behavior for
1799daaffb31Sdp#    SACURL.  See sac2url().
1800daaffb31Sdp#
1801daaffb31SdpSACURL='http://sac.eng.sun.com'
1802daaffb31Sdp[[ -n $WEBREV_SACURL ]] && SACURL="$WEBREV_SACURL"
1803e0e0293aSjmcp[[ -n "$Oflag" ]] && \
1804daaffb31Sdp    SACURL='http://www.opensolaris.org/os/community/arc/caselog'
18057c478bd9Sstevel@tonic-gate
1806daaffb31Sdprm -f $WDIR/$WNAME.patch
1807daaffb31Sdprm -f $WDIR/$WNAME.ps
1808daaffb31Sdprm -f $WDIR/$WNAME.pdf
18097c478bd9Sstevel@tonic-gate
1810daaffb31Sdptouch $WDIR/$WNAME.patch
18117c478bd9Sstevel@tonic-gate
1812daaffb31Sdpprint "   Output Files:"
1813daaffb31Sdp
1814daaffb31Sdp#
1815daaffb31Sdp# Clean up the file list: Remove comments, blank lines and env variables.
1816daaffb31Sdp#
1817daaffb31Sdpsed -e "s/#.*$//" -e "/=/d" -e "/^[   ]*$/d" $FLIST > /tmp/$$.flist.clean
1818daaffb31SdpFLIST=/tmp/$$.flist.clean
1819daaffb31Sdp
1820daaffb31Sdp#
1821daaffb31Sdp# First pass through the files: generate the per-file webrev HTML-files.
1822daaffb31Sdp#
1823daaffb31Sdpcat $FLIST | while read LINE
18247c478bd9Sstevel@tonic-gatedo
18257c478bd9Sstevel@tonic-gate	set - $LINE
18267c478bd9Sstevel@tonic-gate	P=$1
18277c478bd9Sstevel@tonic-gate
1828daaffb31Sdp	#
1829daaffb31Sdp	# Normally, each line in the file list is just a pathname of a
1830daaffb31Sdp	# file that has been modified or created in the child.  A file
1831daaffb31Sdp	# that is renamed in the child workspace has two names on the
1832daaffb31Sdp	# line: new name followed by the old name.
1833daaffb31Sdp	#
1834daaffb31Sdp	oldname=""
1835daaffb31Sdp	oldpath=""
1836daaffb31Sdp	rename=
1837daaffb31Sdp	if [[ $# -eq 2 ]]; then
18387c478bd9Sstevel@tonic-gate		PP=$2			# old filename
1839daaffb31Sdp		oldname=" (was $PP)"
1840daaffb31Sdp		oldpath="$PP"
1841daaffb31Sdp		rename=1
18427c478bd9Sstevel@tonic-gate        	PDIR=${PP%/*}
1843daaffb31Sdp        	if [[ $PDIR == $PP ]]; then
18447c478bd9Sstevel@tonic-gate			PDIR="."   # File at root of workspace
18457c478bd9Sstevel@tonic-gate		fi
18467c478bd9Sstevel@tonic-gate
18477c478bd9Sstevel@tonic-gate		PF=${PP##*/}
18487c478bd9Sstevel@tonic-gate
18497c478bd9Sstevel@tonic-gate	        DIR=${P%/*}
1850daaffb31Sdp	        if [[ $DIR == $P ]]; then
18517c478bd9Sstevel@tonic-gate			DIR="."   # File at root of workspace
18527c478bd9Sstevel@tonic-gate		fi
18537c478bd9Sstevel@tonic-gate
18547c478bd9Sstevel@tonic-gate		F=${P##*/}
1855daaffb31Sdp
18567c478bd9Sstevel@tonic-gate        else
18577c478bd9Sstevel@tonic-gate	        DIR=${P%/*}
1858daaffb31Sdp	        if [[ "$DIR" == "$P" ]]; then
18597c478bd9Sstevel@tonic-gate			DIR="."   # File at root of workspace
18607c478bd9Sstevel@tonic-gate		fi
18617c478bd9Sstevel@tonic-gate
18627c478bd9Sstevel@tonic-gate		F=${P##*/}
18637c478bd9Sstevel@tonic-gate
18647c478bd9Sstevel@tonic-gate		PP=$P
18657c478bd9Sstevel@tonic-gate		PDIR=$DIR
18667c478bd9Sstevel@tonic-gate		PF=$F
18677c478bd9Sstevel@tonic-gate	fi
18687c478bd9Sstevel@tonic-gate
1869daaffb31Sdp	COMM=`getcomments html $P $PP`
18707c478bd9Sstevel@tonic-gate
1871daaffb31Sdp	if [[ ! -d $CWS/$DIR ]]; then
1872daaffb31Sdp		print "  $CWS/$DIR: no such directory"
18737c478bd9Sstevel@tonic-gate		continue
18747c478bd9Sstevel@tonic-gate	fi
18757c478bd9Sstevel@tonic-gate
1876daaffb31Sdp	print "\t$P$oldname\n\t\t\c"
18777c478bd9Sstevel@tonic-gate
18787c478bd9Sstevel@tonic-gate	# Make the webrev mirror directory if necessary
18797c478bd9Sstevel@tonic-gate	mkdir -p $WDIR/$DIR
18807c478bd9Sstevel@tonic-gate
18817c478bd9Sstevel@tonic-gate	# cd to the directory so the names are short
18827c478bd9Sstevel@tonic-gate	cd $CWS/$DIR
18837c478bd9Sstevel@tonic-gate
1884daaffb31Sdp	#
1885daaffb31Sdp	# If we're in OpenSolaris mode, we enforce a minor policy:
1886daaffb31Sdp	# help to make sure the reviewer doesn't accidentally publish
1887e0e0293aSjmcp	# source which is in usr/closed/* or deleted_files/usr/closed/*
1888daaffb31Sdp	#
1889e0e0293aSjmcp	if [[ -n "$Oflag" ]]; then
1890daaffb31Sdp		pclosed=${P##usr/closed/}
1891e0e0293aSjmcp		pdeleted=${P##deleted_files/usr/closed/}
1892e0e0293aSjmcp		if [[ "$pclosed" != "$P" || "$pdeleted" != "$P" ]]; then
1893daaffb31Sdp			print "*** Omitting closed source for OpenSolaris" \
1894daaffb31Sdp			    "mode review"
1895daaffb31Sdp			continue
1896daaffb31Sdp		fi
1897daaffb31Sdp	fi
1898daaffb31Sdp
1899daaffb31Sdp	#
1900daaffb31Sdp	# We stash old and new files into parallel directories in /tmp
1901daaffb31Sdp	# and do our diffs there.  This makes it possible to generate
1902daaffb31Sdp	# clean looking diffs which don't have absolute paths present.
1903daaffb31Sdp	#
1904daaffb31Sdp	olddir=$WDIR/raw_files/old
1905daaffb31Sdp	newdir=$WDIR/raw_files/new
1906daaffb31Sdp	mkdir -p $olddir
1907daaffb31Sdp	mkdir -p $newdir
1908daaffb31Sdp	mkdir -p $olddir/$PDIR
1909daaffb31Sdp	mkdir -p $newdir/$DIR
1910daaffb31Sdp
1911daaffb31Sdp	if [[ $SCM_MODE == "teamware" ]]; then
19127c478bd9Sstevel@tonic-gate		# If the child's version doesn't exist then
19137c478bd9Sstevel@tonic-gate		# get a readonly copy.
19147c478bd9Sstevel@tonic-gate
1915daaffb31Sdp		if [[ ! -f $F && -f SCCS/s.$F ]]; then
19167c478bd9Sstevel@tonic-gate			sccs get -s $F
19177c478bd9Sstevel@tonic-gate		fi
19187c478bd9Sstevel@tonic-gate
1919daaffb31Sdp		#
1920daaffb31Sdp		# Snag new version of file.
1921daaffb31Sdp		#
1922daaffb31Sdp		rm -f $newdir/$DIR/$F
1923daaffb31Sdp		cp $F $newdir/$DIR/$F
19247c478bd9Sstevel@tonic-gate
1925daaffb31Sdp		#
1926daaffb31Sdp		# Get the parent's version of the file. First see whether the
1927daaffb31Sdp		# child's version is checked out and get the parent's version
1928daaffb31Sdp		# with keywords expanded or unexpanded as appropriate.
1929daaffb31Sdp		#
1930e0e0293aSjmcp		if [ -f "$PWS/$PDIR/SCCS/s.$PF" -o \
1931e0e0293aSjmcp		    -f "$PWS/$PDIR/SCCS/p.$PF" ]; then
1932daaffb31Sdp			rm -f $olddir/$PDIR/$PF
1933e0e0293aSjmcp			if [ -f "SCCS/p.$F" ]; then
1934daaffb31Sdp				sccs get -s -p -k $PWS/$PDIR/$PF \
1935daaffb31Sdp				    > $olddir/$PDIR/$PF
19367c478bd9Sstevel@tonic-gate			else
1937daaffb31Sdp				sccs get -s -p    $PWS/$PDIR/$PF \
1938daaffb31Sdp				    > $olddir/$PDIR/$PF
19397c478bd9Sstevel@tonic-gate			fi
19407c478bd9Sstevel@tonic-gate		else
1941daaffb31Sdp			if [[ -f $PWS/$PDIR/$PF ]]; then
19427c478bd9Sstevel@tonic-gate				# Parent is not a real workspace, but just a raw
19437c478bd9Sstevel@tonic-gate				# directory tree - use the file that's there as
19447c478bd9Sstevel@tonic-gate				# the old file.
19457c478bd9Sstevel@tonic-gate
1946daaffb31Sdp				rm -f $olddir/$DIR/$F
1947daaffb31Sdp				cp $PWS/$PDIR/$PF $olddir/$DIR/$F
1948daaffb31Sdp			fi
19497c478bd9Sstevel@tonic-gate		fi
19507c478bd9Sstevel@tonic-gate	fi
19517c478bd9Sstevel@tonic-gate
1952daaffb31Sdp	if [[ ! -f $F && ! -f $olddir/$DIR/$F ]]; then
1953daaffb31Sdp		print "*** Error: file not in parent or child"
19547c478bd9Sstevel@tonic-gate		continue
19557c478bd9Sstevel@tonic-gate	fi
19567c478bd9Sstevel@tonic-gate
1957daaffb31Sdp	cd $WDIR/raw_files
1958daaffb31Sdp	ofile=old/$PDIR/$PF
1959daaffb31Sdp	nfile=new/$DIR/$F
19607c478bd9Sstevel@tonic-gate
1961daaffb31Sdp	mv_but_nodiff=
1962daaffb31Sdp	cmp $ofile $nfile > /dev/null 2>&1
1963daaffb31Sdp	if [[ $? == 0 && $rename == 1 ]]; then
1964daaffb31Sdp		mv_but_nodiff=1
1965daaffb31Sdp	fi
1966daaffb31Sdp
1967daaffb31Sdp	#
1968daaffb31Sdp	# If we have old and new versions of the file then run the appropriate
1969daaffb31Sdp	# diffs.  This is complicated by a couple of factors:
1970daaffb31Sdp	#
1971daaffb31Sdp	#	- renames must be handled specially: we emit a 'remove'
1972daaffb31Sdp	#	  diff and an 'add' diff
1973daaffb31Sdp	#	- new files and deleted files must be handled specially
1974daaffb31Sdp	#	- Solaris patch(1m) can't cope with file creation
1975daaffb31Sdp	#	  (and hence renames) as of this writing.
1976daaffb31Sdp	#       - To make matters worse, gnu patch doesn't interpret the
1977daaffb31Sdp	#	  output of Solaris diff properly when it comes to
1978daaffb31Sdp	#	  adds and deletes.  We need to do some "cleansing"
1979daaffb31Sdp	#         transformations:
1980daaffb31Sdp	# 	    [to add a file] @@ -1,0 +X,Y @@  -->  @@ -0,0 +X,Y @@
1981daaffb31Sdp	#	    [to del a file] @@ -X,Y +1,0 @@  -->  @@ -X,Y +0,0 @@
1982daaffb31Sdp	#
1983daaffb31Sdp	cleanse_rmfile="sed 's/^\(@@ [0-9+,-]*\) [0-9+,-]* @@$/\1 +0,0 @@/'"
1984daaffb31Sdp	cleanse_newfile="sed 's/^@@ [0-9+,-]* \([0-9+,-]* @@\)$/@@ -0,0 \1/'"
1985daaffb31Sdp
1986daaffb31Sdp	rm -f $WDIR/$DIR/$F.patch
1987daaffb31Sdp	if [[ -z $rename ]]; then
1988e0e0293aSjmcp		if [ ! -f "$ofile" ]; then
1989daaffb31Sdp			diff -u /dev/null $nfile | sh -c "$cleanse_newfile" \
1990daaffb31Sdp			    > $WDIR/$DIR/$F.patch
1991e0e0293aSjmcp		elif [ ! -f "$nfile" ]; then
1992daaffb31Sdp			diff -u $ofile /dev/null | sh -c "$cleanse_rmfile" \
1993daaffb31Sdp			    > $WDIR/$DIR/$F.patch
1994daaffb31Sdp		else
1995daaffb31Sdp			diff -u $ofile $nfile > $WDIR/$DIR/$F.patch
1996daaffb31Sdp		fi
1997daaffb31Sdp	else
1998daaffb31Sdp		diff -u $ofile /dev/null | sh -c "$cleanse_rmfile" \
1999daaffb31Sdp		    > $WDIR/$DIR/$F.patch
2000daaffb31Sdp
2001daaffb31Sdp		diff -u /dev/null $nfile | sh -c "$cleanse_newfile" \
2002daaffb31Sdp		    >> $WDIR/$DIR/$F.patch
2003daaffb31Sdp
2004daaffb31Sdp	fi
2005daaffb31Sdp
2006daaffb31Sdp	#
2007daaffb31Sdp	# Tack the patch we just made onto the accumulated patch for the
2008daaffb31Sdp	# whole wad.
2009daaffb31Sdp	#
2010daaffb31Sdp	cat $WDIR/$DIR/$F.patch >> $WDIR/$WNAME.patch
2011daaffb31Sdp
2012daaffb31Sdp	print " patch\c"
2013daaffb31Sdp
2014daaffb31Sdp	if [[ -f $ofile && -f $nfile && -z $mv_but_nodiff ]]; then
2015daaffb31Sdp
2016daaffb31Sdp		${CDIFFCMD:-diff -bt -C 5} $ofile $nfile > $WDIR/$DIR/$F.cdiff
2017daaffb31Sdp		diff_to_html $F $DIR/$F "C" "$COMM" < $WDIR/$DIR/$F.cdiff \
2018daaffb31Sdp		    > $WDIR/$DIR/$F.cdiff.html
20197c478bd9Sstevel@tonic-gate		print " cdiffs\c"
20207c478bd9Sstevel@tonic-gate
2021daaffb31Sdp		${UDIFFCMD:-diff -bt -U 5} $ofile $nfile > $WDIR/$DIR/$F.udiff
2022daaffb31Sdp		diff_to_html $F $DIR/$F "U" "$COMM" < $WDIR/$DIR/$F.udiff \
2023daaffb31Sdp		    > $WDIR/$DIR/$F.udiff.html
2024daaffb31Sdp
20257c478bd9Sstevel@tonic-gate		print " udiffs\c"
20267c478bd9Sstevel@tonic-gate
20277c478bd9Sstevel@tonic-gate		if [[ -x $WDIFF ]]; then
2028daaffb31Sdp			$WDIFF -c "$COMM" \
2029daaffb31Sdp			    -t "$WNAME Wdiff $DIR/$F" $ofile $nfile > \
2030daaffb31Sdp			    $WDIR/$DIR/$F.wdiff.html 2>/dev/null
2031daaffb31Sdp			if [[ $? -eq 0 ]]; then
20327c478bd9Sstevel@tonic-gate				print " wdiffs\c"
2033daaffb31Sdp			else
2034daaffb31Sdp				print " wdiffs[fail]\c"
2035daaffb31Sdp			fi
20367c478bd9Sstevel@tonic-gate		fi
20377c478bd9Sstevel@tonic-gate
2038daaffb31Sdp		sdiff_to_html $ofile $nfile $F $DIR "$COMM" \
2039daaffb31Sdp		    > $WDIR/$DIR/$F.sdiff.html
20407c478bd9Sstevel@tonic-gate		print " sdiffs\c"
20417c478bd9Sstevel@tonic-gate
20427c478bd9Sstevel@tonic-gate		print " frames\c"
20437c478bd9Sstevel@tonic-gate
20447c478bd9Sstevel@tonic-gate		rm -f $WDIR/$DIR/$F.cdiff $WDIR/$DIR/$F.udiff
20457c478bd9Sstevel@tonic-gate
2046daaffb31Sdp		difflines $ofile $nfile > $WDIR/$DIR/$F.count
2047daaffb31Sdp
2048daaffb31Sdp	elif [[ -f $ofile && -f $nfile && -n $mv_but_nodiff ]]; then
2049daaffb31Sdp		# renamed file: may also have differences
2050daaffb31Sdp		difflines $ofile $nfile > $WDIR/$DIR/$F.count
2051daaffb31Sdp	elif [[ -f $nfile ]]; then
20527c478bd9Sstevel@tonic-gate		# new file: count added lines
2053daaffb31Sdp		difflines /dev/null $nfile > $WDIR/$DIR/$F.count
2054daaffb31Sdp	elif [[ -f $ofile ]]; then
20557c478bd9Sstevel@tonic-gate		# old file: count deleted lines
2056daaffb31Sdp		difflines $ofile /dev/null > $WDIR/$DIR/$F.count
20577c478bd9Sstevel@tonic-gate	fi
20587c478bd9Sstevel@tonic-gate
2059daaffb31Sdp	#
2060daaffb31Sdp	# Now we generate the postscript for this file.  We generate diffs
2061daaffb31Sdp	# only in the event that there is delta, or the file is new (it seems
2062daaffb31Sdp	# tree-killing to print out the contents of deleted files).
2063daaffb31Sdp	#
2064daaffb31Sdp	if [[ -f $nfile ]]; then
2065daaffb31Sdp		ocr=$ofile
2066daaffb31Sdp		[[ ! -f $ofile ]] && ocr=/dev/null
2067daaffb31Sdp
2068daaffb31Sdp		if [[ -z $mv_but_nodiff ]]; then
2069daaffb31Sdp			textcomm=`getcomments text $P $PP`
207014983201Sdp			if [[ -x $CODEREVIEW ]]; then
207114983201Sdp				$CODEREVIEW -y "$textcomm" \
207214983201Sdp				    -e $ocr $nfile \
207314983201Sdp				    > /tmp/$$.psfile 2>/dev/null &&
207414983201Sdp				    cat /tmp/$$.psfile >> $WDIR/$WNAME.ps
2075daaffb31Sdp				if [[ $? -eq 0 ]]; then
2076daaffb31Sdp					print " ps\c"
2077daaffb31Sdp				else
2078daaffb31Sdp					print " ps[fail]\c"
2079daaffb31Sdp				fi
2080daaffb31Sdp			fi
2081daaffb31Sdp		fi
208214983201Sdp	fi
2083daaffb31Sdp
2084daaffb31Sdp	if [[ -f $ofile && -z $mv_but_nodiff ]]; then
2085daaffb31Sdp		source_to_html Old $P < $ofile > $WDIR/$DIR/$F-.html
20867c478bd9Sstevel@tonic-gate		print " old\c"
20877c478bd9Sstevel@tonic-gate	fi
20887c478bd9Sstevel@tonic-gate
2089daaffb31Sdp	if [[ -f $nfile ]]; then
2090daaffb31Sdp		source_to_html New $P < $nfile > $WDIR/$DIR/$F.html
20917c478bd9Sstevel@tonic-gate		print " new\c"
20927c478bd9Sstevel@tonic-gate	fi
20937c478bd9Sstevel@tonic-gate
2094daaffb31Sdp	print
20957c478bd9Sstevel@tonic-gatedone
20967c478bd9Sstevel@tonic-gate
2097daaffb31Sdpframe_nav_js > $WDIR/ancnav.js
20987c478bd9Sstevel@tonic-gateframe_navigation > $WDIR/ancnav.html
2099daaffb31Sdp
210014983201Sdpif [[ ! -f $WDIR/$WNAME.ps ]]; then
210114983201Sdp	print " Generating PDF: Skipped: no output available"
210214983201Sdpelif [[ -x $CODEREVIEW && -x $PS2PDF ]]; then
210314983201Sdp	print " Generating PDF: \c"
210414983201Sdp	fix_postscript $WDIR/$WNAME.ps | $PS2PDF - > $WDIR/$WNAME.pdf
2105daaffb31Sdp	rm -f $WDIR/$WNAME.ps
2106daaffb31Sdp	print "Done."
210714983201Sdpelse
210814983201Sdp	print " Generating PDF: Skipped: missing 'ps2pdf' or 'codereview'"
210914983201Sdpfi
21107c478bd9Sstevel@tonic-gate
2111e0e0293aSjmcp# If we're in OpenSolaris mode and there's a closed dir under $WDIR,
2112e0e0293aSjmcp# delete it - prevent accidental publishing of closed source
2113e0e0293aSjmcp
2114e0e0293aSjmcpif [[ -n "$Oflag" ]]; then
2115e0e0293aSjmcp	/usr/bin/find $WDIR -type d -name closed -exec /bin/rm -rf {} \;
2116e0e0293aSjmcpfi
2117e0e0293aSjmcp
21187c478bd9Sstevel@tonic-gate# Now build the index.html file that contains
21197c478bd9Sstevel@tonic-gate# links to the source files and their diffs.
21207c478bd9Sstevel@tonic-gate
21217c478bd9Sstevel@tonic-gatecd $CWS
21227c478bd9Sstevel@tonic-gate
21237c478bd9Sstevel@tonic-gate# Save total changed lines for Code Inspection.
2124daaffb31Sdpprint "$TOTL" > $WDIR/TotalChangedLines
21257c478bd9Sstevel@tonic-gate
2126daaffb31Sdpprint "     index.html: \c"
21277c478bd9Sstevel@tonic-gateINDEXFILE=$WDIR/index.html
21287c478bd9Sstevel@tonic-gateexec 3<&1			# duplicate stdout to FD3.
21297c478bd9Sstevel@tonic-gateexec 1<&-			# Close stdout.
21307c478bd9Sstevel@tonic-gateexec > $INDEXFILE		# Open stdout to index file.
21317c478bd9Sstevel@tonic-gate
2132daaffb31Sdpprint "$HTML<head>$STDHEAD"
2133daaffb31Sdpprint "<title>$WNAME</title>"
2134daaffb31Sdpprint "</head>"
2135daaffb31Sdpprint "<body id=\"SUNWwebrev\">"
2136daaffb31Sdpprint "<div class=\"summary\">"
2137daaffb31Sdpprint "<h2>Code Review for $WNAME</h2>"
21387c478bd9Sstevel@tonic-gate
2139daaffb31Sdpprint "<table>"
21407c478bd9Sstevel@tonic-gate
2141daaffb31Sdp#
2142daaffb31Sdp# Figure out the username and gcos name.  To maintain compatibility
2143daaffb31Sdp# with passwd(4), we must support '&' substitutions.
2144daaffb31Sdp#
2145daaffb31Sdpusername=`id | cut -d '(' -f 2 | cut -d ')' -f 1`
2146daaffb31Sdprealname=`getent passwd $username | cut -d':' -f 5`
214714983201Sdpuserupper=`$PERL -e "print ucfirst $username"`
2148daaffb31Sdprealname=`print $realname | sed s/\&/$userupper/`
2149daaffb31Sdpdate="on `date`"
21507c478bd9Sstevel@tonic-gate
2151daaffb31Sdpif [[ -n "$username" && -n "$realname" ]]; then
2152daaffb31Sdp	print "<tr><th>Prepared by:</th>"
2153daaffb31Sdp	print "<td>$realname ($username) $date</td></tr>"
2154daaffb31Sdpelif [[ -n "$username" ]]; then
2155daaffb31Sdp	print "<tr><th>Prepared by:</th><td>$username $date</td></tr>"
2156daaffb31Sdpfi
2157daaffb31Sdp
2158daaffb31Sdpprint "<tr><th>Workspace:</th><td>$CWS</td></tr>"
2159daaffb31Sdpprint "<tr><th>Compare against:</th><td>"
2160daaffb31Sdpif [[ -n $parent_webrev ]]; then
2161daaffb31Sdp	print "webrev at $parent_webrev"
2162daaffb31Sdpelse
2163daaffb31Sdp	print "$PWS"
2164daaffb31Sdpfi
2165daaffb31Sdpprint "</td></tr>"
2166daaffb31Sdpprint "<tr><th>Summary of changes:</th><td>"
2167daaffb31SdpprintCI $TOTL $TINS $TDEL $TMOD $TUNC
2168daaffb31Sdpprint "</td></tr>"
2169daaffb31Sdp
2170daaffb31Sdpif [[ -f $WDIR/$WNAME.patch ]]; then
2171daaffb31Sdp	print "<tr><th>Patch of changes:</th><td>"
2172daaffb31Sdp	print "<a href=\"$WNAME.patch\">$WNAME.patch</a></td></tr>"
2173daaffb31Sdpfi
2174daaffb31Sdpif [[ -f $WDIR/$WNAME.pdf ]]; then
2175daaffb31Sdp	print "<tr><th>Printable review:</th><td>"
2176daaffb31Sdp	print "<a href=\"$WNAME.pdf\">$WNAME.pdf</a></td></tr>"
2177daaffb31Sdpfi
2178daaffb31Sdp
2179daaffb31Sdpif [[ -n "$iflag" ]]; then
2180daaffb31Sdp	print "<tr><th>Author comments:</th><td><div>"
2181daaffb31Sdp	cat /tmp/$$.include
2182daaffb31Sdp	print "</div></td></tr>"
2183daaffb31Sdpfi
2184daaffb31Sdpprint "</table>"
2185daaffb31Sdpprint "</div>"
2186daaffb31Sdp
2187daaffb31Sdp
2188daaffb31Sdp#
2189daaffb31Sdp# Second pass through the files: generate the rest of the index file
2190daaffb31Sdp#
2191daaffb31Sdpcat $FLIST | while read LINE
21927c478bd9Sstevel@tonic-gatedo
21937c478bd9Sstevel@tonic-gate	set - $LINE
21947c478bd9Sstevel@tonic-gate	P=$1
21957c478bd9Sstevel@tonic-gate
2196daaffb31Sdp	if [[ $# == 2 ]]; then
21977c478bd9Sstevel@tonic-gate		PP=$2
2198daaffb31Sdp		oldname=" <i>(was $PP)</i>"
2199daaffb31Sdp
22007c478bd9Sstevel@tonic-gate	else
22017c478bd9Sstevel@tonic-gate		PP=$P
2202daaffb31Sdp		oldname=""
2203daaffb31Sdp	fi
2204daaffb31Sdp
2205daaffb31Sdp	DIR=${P%/*}
2206daaffb31Sdp	if [[ $DIR == $P ]]; then
2207daaffb31Sdp		DIR="."   # File at root of workspace
22087c478bd9Sstevel@tonic-gate	fi
22097c478bd9Sstevel@tonic-gate
22107c478bd9Sstevel@tonic-gate	# Avoid processing the same file twice.
22117c478bd9Sstevel@tonic-gate	# It's possible for renamed files to
22127c478bd9Sstevel@tonic-gate	# appear twice in the file list
22137c478bd9Sstevel@tonic-gate
22147c478bd9Sstevel@tonic-gate	F=$WDIR/$P
22157c478bd9Sstevel@tonic-gate
2216daaffb31Sdp	print "<p>"
22177c478bd9Sstevel@tonic-gate
22187c478bd9Sstevel@tonic-gate	# If there's a diffs file, make diffs links
22197c478bd9Sstevel@tonic-gate
2220daaffb31Sdp	if [[ -f $F.cdiff.html ]]; then
2221daaffb31Sdp		print "<a href=\"$P.cdiff.html\">Cdiffs</a>"
2222daaffb31Sdp		print "<a href=\"$P.udiff.html\">Udiffs</a>"
22237c478bd9Sstevel@tonic-gate
2224daaffb31Sdp		if [[ -f $F.wdiff.html && -x $WDIFF ]]; then
2225daaffb31Sdp			print "<a href=\"$P.wdiff.html\">Wdiffs</a>"
22267c478bd9Sstevel@tonic-gate		fi
22277c478bd9Sstevel@tonic-gate
2228daaffb31Sdp		print "<a href=\"$P.sdiff.html\">Sdiffs</a>"
22297c478bd9Sstevel@tonic-gate
22307c478bd9Sstevel@tonic-gate		print "<a href=\"$P.frames.html\">Frames</a>"
22317c478bd9Sstevel@tonic-gate	else
2232daaffb31Sdp		print " ------ ------ ------"
22337c478bd9Sstevel@tonic-gate
2234daaffb31Sdp		if [[ -x $WDIFF ]]; then
22357c478bd9Sstevel@tonic-gate			print " ------"
22367c478bd9Sstevel@tonic-gate		fi
2237daaffb31Sdp
2238daaffb31Sdp		print " ------"
22397c478bd9Sstevel@tonic-gate	fi
22407c478bd9Sstevel@tonic-gate
22417c478bd9Sstevel@tonic-gate	# If there's an old file, make the link
22427c478bd9Sstevel@tonic-gate
2243daaffb31Sdp	if [[ -f $F-.html ]]; then
2244daaffb31Sdp		print "<a href=\"$P-.html\">Old</a>"
22457c478bd9Sstevel@tonic-gate	else
2246daaffb31Sdp		print " ---"
22477c478bd9Sstevel@tonic-gate	fi
22487c478bd9Sstevel@tonic-gate
22497c478bd9Sstevel@tonic-gate	# If there's an new file, make the link
22507c478bd9Sstevel@tonic-gate
2251daaffb31Sdp	if [[ -f $F.html ]]; then
2252daaffb31Sdp		print "<a href=\"$P.html\">New</a>"
22537c478bd9Sstevel@tonic-gate	else
2254daaffb31Sdp		print " ---"
22557c478bd9Sstevel@tonic-gate	fi
22567c478bd9Sstevel@tonic-gate
2257daaffb31Sdp	if [[ -f $F.patch ]]; then
2258daaffb31Sdp		print "<a href=\"$P.patch\">Patch</a>"
2259daaffb31Sdp	else
2260daaffb31Sdp		print " -----"
2261daaffb31Sdp	fi
2262daaffb31Sdp
2263daaffb31Sdp	if [[ -f $WDIR/raw_files/new/$P ]]; then
2264daaffb31Sdp		print "<a href=\"raw_files/new/$P\">Raw</a>"
2265daaffb31Sdp	else
2266daaffb31Sdp		print " ---"
2267daaffb31Sdp	fi
2268daaffb31Sdp
2269daaffb31Sdp	print "<b>$P</b> $oldname"
2270daaffb31Sdp
2271daaffb31Sdp	#
2272e0e0293aSjmcp	# Check for usr/closed and deleted_files/usr/closed
2273daaffb31Sdp	#
2274daaffb31Sdp	if [ ! -z "$Oflag" ]; then
2275e0e0293aSjmcp		if [[ $P == usr/closed/* || \
2276e0e0293aSjmcp		    $P == deleted_files/usr/closed/* ]]; then
2277daaffb31Sdp			print "&nbsp;&nbsp;<i>Closed source: omitted from" \
2278daaffb31Sdp			    "this review</i>"
2279daaffb31Sdp		fi
2280daaffb31Sdp	fi
2281daaffb31Sdp
2282daaffb31Sdp	print "</p>"
22837c478bd9Sstevel@tonic-gate	# Insert delta comments
22847c478bd9Sstevel@tonic-gate
2285daaffb31Sdp	print "<blockquote><pre>"
2286daaffb31Sdp	getcomments html $P $PP
2287daaffb31Sdp	print "</pre>"
22887c478bd9Sstevel@tonic-gate
22897c478bd9Sstevel@tonic-gate	# Add additional comments comment
22907c478bd9Sstevel@tonic-gate
2291daaffb31Sdp	print "<!-- Add comments to explain changes in $P here -->"
22927c478bd9Sstevel@tonic-gate
22937c478bd9Sstevel@tonic-gate	# Add count of changes.
22947c478bd9Sstevel@tonic-gate
2295daaffb31Sdp	if [[ -f $F.count ]]; then
22967c478bd9Sstevel@tonic-gate	    cat $F.count
22977c478bd9Sstevel@tonic-gate	    rm $F.count
22987c478bd9Sstevel@tonic-gate	fi
2299daaffb31Sdp	print "</blockquote>"
23007c478bd9Sstevel@tonic-gatedone
23017c478bd9Sstevel@tonic-gate
2302daaffb31Sdpprint
2303daaffb31Sdpprint
2304*cac38512Smjnelsonprint "<hr></hr>"
2305daaffb31Sdpprint "<p style=\"font-size: small\">"
2306daaffb31Sdpprint "This code review page was prepared using <b>$0</b>"
2307daaffb31Sdpprint "(vers $WEBREV_UPDATED)."
2308daaffb31Sdpprint "Webrev is maintained by the <a href=\"http://www.opensolaris.org\">"
2309daaffb31Sdpprint "OpenSolaris</a> project.  The latest version may be obtained"
2310e9e2cfb2Sfr80241print "<a href=\"http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/tools/scripts/webrev.sh\">here</a>.</p>"
2311daaffb31Sdpprint "</body>"
2312daaffb31Sdpprint "</html>"
23137c478bd9Sstevel@tonic-gate
23147c478bd9Sstevel@tonic-gateexec 1<&-			# Close FD 1.
23157c478bd9Sstevel@tonic-gateexec 1<&3			# dup FD 3 to restore stdout.
23167c478bd9Sstevel@tonic-gateexec 3<&-			# close FD 3.
23177c478bd9Sstevel@tonic-gate
2318daaffb31Sdpprint "Done."
2319