xref: /titanic_52/usr/src/tools/scripts/webrev.sh (revision 14983201aedba8e8a440bf822addd2e3811e54cc)
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#
25daaffb31Sdp# Copyright 2006 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
58daaffb31SdpSTDHEAD='<meta http-equiv="cache-control" content="no-cache" />
59daaffb31Sdp<meta http-equiv="Pragma" content="no-cache" />
60daaffb31Sdp<meta http-equiv="Expires" content="-1" />
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{
178daaffb31Sdp	if [[ -z $Oflag ]]; then
179daaffb31Sdp	    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) {
210daaffb31Sdp				print "\n</pre><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	}
230daaffb31Sdp	END	{ if (c > (C * 2)) print "\n</pre><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
530daaffb31Sdp	    <script type="text/javascript" src="$RTOP/ancnav.js" />
5317c478bd9Sstevel@tonic-gate	    </head>
532daaffb31Sdp	    <body id="SUNWwebrev" onkeypress="keypress(event);">
533daaffb31Sdp	    <a name="0" />
534daaffb31Sdp	    <pre>$comments</pre><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%">
553daaffb31Sdp	      <frame src="$TNAME.lhs.html" scrolling="auto" name="lhs" />
554daaffb31Sdp	      <frame src="$TNAME.rhs.html" scrolling="auto" name="rhs" />
555daaffb31Sdp	    </frameset>
556daaffb31Sdp	  <frame src="$RTOP/ancnav.html" scrolling="no" marginwidth="0"
557daaffb31Sdp	   marginheight="0" name="nav" />
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
627*14983201Sdp	$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		# This should be able to be a singleton <a /> but that
652daaffb31Sdp		# seems to trigger a bug in firefox a:hover rule processing
653daaffb31Sdp		printf "<a name=\"%d\" id=\"anc%d\"></a>", anc, anc++;
6547c478bd9Sstevel@tonic-gate	}
655daaffb31Sdp
6567c478bd9Sstevel@tonic-gate	BEGIN {
657daaffb31Sdp		anc=1;
6587c478bd9Sstevel@tonic-gate		inblock=1;
659daaffb31Sdp		printf "<pre>\n";
6607c478bd9Sstevel@tonic-gate	}
661daaffb31Sdp	NF == 0 || /^<span class=/ {
6627c478bd9Sstevel@tonic-gate		if (inblock == 0) {
6637c478bd9Sstevel@tonic-gate			ia();
6647c478bd9Sstevel@tonic-gate			inblock=1;
6657c478bd9Sstevel@tonic-gate		}
6667c478bd9Sstevel@tonic-gate		print;
6677c478bd9Sstevel@tonic-gate		next;
6687c478bd9Sstevel@tonic-gate	}
6697c478bd9Sstevel@tonic-gate	{
6707c478bd9Sstevel@tonic-gate		inblock=0;
6717c478bd9Sstevel@tonic-gate		print;
6727c478bd9Sstevel@tonic-gate	}
6737c478bd9Sstevel@tonic-gate	END {
6747c478bd9Sstevel@tonic-gate		ia();
675daaffb31Sdp
676daaffb31Sdp		printf "<b style=\"font-size: large; color: red\">";
677daaffb31Sdp		printf "--- EOF ---</b>"
6787c478bd9Sstevel@tonic-gate        	for(i=0;i<8;i++) printf "\n\n\n\n\n\n\n\n\n\n";
679daaffb31Sdp		printf "</pre>"
680daaffb31Sdp		printf "<form name=\"eof\">";
681daaffb31Sdp		printf "<input name=\"value\" value=\"%d\" type=\"hidden\" />",
682daaffb31Sdp		    anc - 1;
683daaffb31Sdp		printf "</form>";
6847c478bd9Sstevel@tonic-gate	}
6857c478bd9Sstevel@tonic-gate	' $1
6867c478bd9Sstevel@tonic-gate}
6877c478bd9Sstevel@tonic-gate
6887c478bd9Sstevel@tonic-gate
689daaffb31Sdp#
690daaffb31Sdp# relative_dir
691daaffb31Sdp#
692daaffb31Sdp# Print a relative return path from $1 to $2.  For example if
693daaffb31Sdp# $1=/tmp/myreview/raw_files/usr/src/tools/scripts and $2=/tmp/myreview,
694daaffb31Sdp# this function would print "../../../../".
695daaffb31Sdp#
696daaffb31Sdp# In the event that $1 is not in $2 a warning is printed to stderr,
697daaffb31Sdp# and $2 is returned-- the result of this is that the resulting webrev
698daaffb31Sdp# is not relocatable.
699daaffb31Sdp#
700daaffb31Sdpfunction relative_dir
7017c478bd9Sstevel@tonic-gate{
702daaffb31Sdp	typeset cur="${1##$2?(/)}"
703daaffb31Sdp	typeset ret=""
704daaffb31Sdp	if [[ $2 == $cur ]]; then   # Should never happen.
705daaffb31Sdp		# Should never happen.
706*14983201Sdp		print -u2 "\nWARNING: relative_dir: \"$1\" not relative "
707daaffb31Sdp		print -u2 "to \"$2\".  Check input paths.  Framed webrev "
708daaffb31Sdp		print -u2 "will not be relocatable!"
709daaffb31Sdp		print $2
710daaffb31Sdp		return
711daaffb31Sdp	fi
712daaffb31Sdp
713daaffb31Sdp	while [[ -n ${cur} ]];
7147c478bd9Sstevel@tonic-gate	do
7157c478bd9Sstevel@tonic-gate		cur=${cur%%*(/)*([!/])}
716daaffb31Sdp		if [[ -z $ret ]]; then
717daaffb31Sdp			ret=".."
718daaffb31Sdp		else
7197c478bd9Sstevel@tonic-gate			ret="../$ret"
720daaffb31Sdp		fi
7217c478bd9Sstevel@tonic-gate	done
7227c478bd9Sstevel@tonic-gate	print $ret
7237c478bd9Sstevel@tonic-gate}
7247c478bd9Sstevel@tonic-gate
7257c478bd9Sstevel@tonic-gate
726daaffb31Sdp#
727daaffb31Sdp# frame_nav_js
728daaffb31Sdp#
729daaffb31Sdp# Emit javascript for frame navigation
730daaffb31Sdp#
731daaffb31Sdpfunction frame_nav_js
7327c478bd9Sstevel@tonic-gate{
7337c478bd9Sstevel@tonic-gatecat << \EOF
7347c478bd9Sstevel@tonic-gatevar myInt;
7357c478bd9Sstevel@tonic-gatevar scrolling=0;
736daaffb31Sdpvar sfactor = 3;
7377c478bd9Sstevel@tonic-gatevar scount=10;
7387c478bd9Sstevel@tonic-gate
7397c478bd9Sstevel@tonic-gatefunction scrollByPix() {
7407c478bd9Sstevel@tonic-gate	if (scount<=0) {
7417c478bd9Sstevel@tonic-gate		sfactor*=1.2;
7427c478bd9Sstevel@tonic-gate		scount=10;
7437c478bd9Sstevel@tonic-gate	}
7447c478bd9Sstevel@tonic-gate	parent.lhs.scrollBy(0,sfactor);
7457c478bd9Sstevel@tonic-gate	parent.rhs.scrollBy(0,sfactor);
7467c478bd9Sstevel@tonic-gate	scount--;
7477c478bd9Sstevel@tonic-gate}
7487c478bd9Sstevel@tonic-gate
749daaffb31Sdpfunction scrollToAnc(num) {
750daaffb31Sdp
751daaffb31Sdp	// Update the value of the anchor in the form which we use as
752daaffb31Sdp	// storage for this value.  setAncValue() will take care of
753daaffb31Sdp	// correcting for overflow and underflow of the value and return
754daaffb31Sdp	// us the new value.
755daaffb31Sdp	num = setAncValue(num);
756daaffb31Sdp
757daaffb31Sdp	// Set location and scroll back a little to expose previous
758daaffb31Sdp	// lines.
759daaffb31Sdp	//
760daaffb31Sdp	// Note that this could be improved: it is possible although
761daaffb31Sdp	// complex to compute the x and y position of an anchor, and to
762daaffb31Sdp	// scroll to that location directly.
763daaffb31Sdp	//
7647c478bd9Sstevel@tonic-gate	parent.lhs.location.replace(parent.lhs.location.pathname + "#" + num);
7657c478bd9Sstevel@tonic-gate	parent.rhs.location.replace(parent.rhs.location.pathname + "#" + num);
766daaffb31Sdp
7677c478bd9Sstevel@tonic-gate	parent.lhs.scrollBy(0,-30);
7687c478bd9Sstevel@tonic-gate	parent.rhs.scrollBy(0,-30);
7697c478bd9Sstevel@tonic-gate}
7707c478bd9Sstevel@tonic-gate
771daaffb31Sdpfunction getAncValue()
772daaffb31Sdp{
773daaffb31Sdp	return (parseInt(parent.nav.document.diff.real.value));
774daaffb31Sdp}
775daaffb31Sdp
776daaffb31Sdpfunction setAncValue(val)
777daaffb31Sdp{
778daaffb31Sdp	if (val <= 0) {
779daaffb31Sdp		val = 0;
780daaffb31Sdp		parent.nav.document.diff.real.value = val;
781daaffb31Sdp		parent.nav.document.diff.display.value = "BOF";
782daaffb31Sdp		return (val);
783daaffb31Sdp	}
784daaffb31Sdp
785daaffb31Sdp	//
786daaffb31Sdp	// The way we compute the max anchor value is to stash it
787daaffb31Sdp	// inline in the left and right hand side pages-- it's the same
788daaffb31Sdp	// on each side, so we pluck from the left.
789daaffb31Sdp	//
790daaffb31Sdp	maxval = parent.lhs.document.eof.value.value;
791daaffb31Sdp	if (val < maxval) {
792daaffb31Sdp		parent.nav.document.diff.real.value = val;
793daaffb31Sdp		parent.nav.document.diff.display.value = val.toString();
794daaffb31Sdp		return (val);
795daaffb31Sdp	}
796daaffb31Sdp
797daaffb31Sdp	// this must be: val >= maxval
798daaffb31Sdp	val = maxval;
799daaffb31Sdp	parent.nav.document.diff.real.value = val;
800daaffb31Sdp	parent.nav.document.diff.display.value = "EOF";
801daaffb31Sdp	return (val);
802daaffb31Sdp}
803daaffb31Sdp
8047c478bd9Sstevel@tonic-gatefunction stopScroll() {
8057c478bd9Sstevel@tonic-gate	if (scrolling==1) {
8067c478bd9Sstevel@tonic-gate		clearInterval(myInt);
8077c478bd9Sstevel@tonic-gate		scrolling=0;
8087c478bd9Sstevel@tonic-gate	}
8097c478bd9Sstevel@tonic-gate}
8107c478bd9Sstevel@tonic-gate
8117c478bd9Sstevel@tonic-gatefunction startScroll() {
8127c478bd9Sstevel@tonic-gate	stopScroll();
8137c478bd9Sstevel@tonic-gate	scrolling=1;
8147c478bd9Sstevel@tonic-gate	myInt=setInterval("scrollByPix()",10);
8157c478bd9Sstevel@tonic-gate}
8167c478bd9Sstevel@tonic-gate
8177c478bd9Sstevel@tonic-gatefunction handlePress(b) {
818daaffb31Sdp
8197c478bd9Sstevel@tonic-gate	switch (b) {
8207c478bd9Sstevel@tonic-gate	    case 1 :
821daaffb31Sdp		scrollToAnc(-1);
8227c478bd9Sstevel@tonic-gate		break;
8237c478bd9Sstevel@tonic-gate	    case 2 :
824daaffb31Sdp		scrollToAnc(getAncValue() - 1);
8257c478bd9Sstevel@tonic-gate		break;
8267c478bd9Sstevel@tonic-gate	    case 3 :
8277c478bd9Sstevel@tonic-gate		sfactor=-3;
8287c478bd9Sstevel@tonic-gate		startScroll();
8297c478bd9Sstevel@tonic-gate		break;
8307c478bd9Sstevel@tonic-gate	    case 4 :
8317c478bd9Sstevel@tonic-gate		sfactor=3;
8327c478bd9Sstevel@tonic-gate		startScroll();
8337c478bd9Sstevel@tonic-gate		break;
8347c478bd9Sstevel@tonic-gate	    case 5 :
835daaffb31Sdp		scrollToAnc(getAncValue() + 1);
8367c478bd9Sstevel@tonic-gate		break;
8377c478bd9Sstevel@tonic-gate	    case 6 :
838daaffb31Sdp		scrollToAnc(999999);
8397c478bd9Sstevel@tonic-gate		break;
8407c478bd9Sstevel@tonic-gate	}
8417c478bd9Sstevel@tonic-gate}
8427c478bd9Sstevel@tonic-gate
8437c478bd9Sstevel@tonic-gatefunction handleRelease(b) {
8447c478bd9Sstevel@tonic-gate	stopScroll();
8457c478bd9Sstevel@tonic-gate}
8467c478bd9Sstevel@tonic-gate
847daaffb31Sdpfunction keypress(ev) {
848daaffb31Sdp	var keynum;
849daaffb31Sdp	var keychar;
850daaffb31Sdp
851daaffb31Sdp	if (window.event) { // IE
852daaffb31Sdp		keynum = ev.keyCode;
853daaffb31Sdp	} else if (ev.which) { // non-IE
854daaffb31Sdp		keynum = ev.which;
855daaffb31Sdp	}
856daaffb31Sdp
857daaffb31Sdp	keychar = String.fromCharCode(keynum);
858daaffb31Sdp
859daaffb31Sdp	if (keychar == "k") {
860daaffb31Sdp		handlePress(2);
861daaffb31Sdp		return (0);
862daaffb31Sdp	} else if (keychar == "j" || keychar == " ") {
863daaffb31Sdp		handlePress(5);
864daaffb31Sdp		return (0);
865daaffb31Sdp	}
866daaffb31Sdp	return (1);
867daaffb31Sdp}
868daaffb31Sdp
8697c478bd9Sstevel@tonic-gatefunction ValidateDiffNum(){
870daaffb31Sdp	val = parent.nav.document.diff.display.value;
871daaffb31Sdp	if (val == "EOF") {
872daaffb31Sdp		scrollToAnc(999999);
873daaffb31Sdp		return;
874daaffb31Sdp	}
875daaffb31Sdp
876daaffb31Sdp	if (val == "BOF") {
877daaffb31Sdp		scrollToAnc(0);
878daaffb31Sdp		return;
879daaffb31Sdp	}
880daaffb31Sdp
881daaffb31Sdp        i=parseInt(val);
8827c478bd9Sstevel@tonic-gate        if (isNaN(i)) {
883daaffb31Sdp                parent.nav.document.diff.display.value = getAncValue();
8847c478bd9Sstevel@tonic-gate        } else {
885daaffb31Sdp                scrollToAnc(i);
8867c478bd9Sstevel@tonic-gate        }
8877c478bd9Sstevel@tonic-gate        return false;
8887c478bd9Sstevel@tonic-gate}
8897c478bd9Sstevel@tonic-gate
890daaffb31SdpEOF
891daaffb31Sdp}
892daaffb31Sdp
893daaffb31Sdp#
894daaffb31Sdp# frame_navigation
895daaffb31Sdp#
896daaffb31Sdp# Output anchor navigation file for framed sdiffs.
897daaffb31Sdp#
898daaffb31Sdpfunction frame_navigation
899daaffb31Sdp{
900daaffb31Sdp	print "$HTML<head>$STDHEAD"
901daaffb31Sdp
902daaffb31Sdp	cat << \EOF
903daaffb31Sdp<title>Anchor Navigation</title>
904daaffb31Sdp<meta http-equiv="Content-Script-Type" content="text/javascript">
905daaffb31Sdp<meta http-equiv="Content-Type" content="text/html">
906daaffb31Sdp
907daaffb31Sdp<style type="text/css">
908daaffb31Sdp    div.button td { padding-left: 5px; padding-right: 5px;
909daaffb31Sdp		    background-color: #eee; text-align: center;
910daaffb31Sdp		    border: 1px #444 outset; cursor: pointer; }
911daaffb31Sdp    div.button a { font-weight: bold; color: black }
912daaffb31Sdp    div.button td:hover { background: #ffcc99; }
913daaffb31Sdp</style>
914daaffb31SdpEOF
915daaffb31Sdp
916daaffb31Sdp	print "<script type=\"text/javascript\" src=\"ancnav.js\" />"
917daaffb31Sdp
918daaffb31Sdp	cat << \EOF
9197c478bd9Sstevel@tonic-gate</head>
920daaffb31Sdp<body id="SUNWwebrev" bgcolor="#eeeeee" onload="document.diff.real.focus();"
921daaffb31Sdp	onkeypress="keypress(event);">
9227c478bd9Sstevel@tonic-gate    <noscript lang="javascript">
9237c478bd9Sstevel@tonic-gate      <center>
924daaffb31Sdp	<p><big>Framed Navigation controls require Javascript</big><br />
9257c478bd9Sstevel@tonic-gate	Either this browser is incompatable or javascript is not enabled</p>
9267c478bd9Sstevel@tonic-gate      </center>
9277c478bd9Sstevel@tonic-gate    </noscript>
9287c478bd9Sstevel@tonic-gate    <table width="100%" border="0" align="center">
929daaffb31Sdp	<tr>
930daaffb31Sdp          <td valign="middle" width="25%">Diff navigation:
931daaffb31Sdp          Use 'j' and 'k' for next and previous diffs; or use buttons
932daaffb31Sdp          at right</td>
933daaffb31Sdp	  <td align="center" valign="top" width="50%">
9347c478bd9Sstevel@tonic-gate	    <div class="button">
935daaffb31Sdp	      <table border="0" align="center">
936daaffb31Sdp                  <tr>
937daaffb31Sdp		    <td>
9387c478bd9Sstevel@tonic-gate		      <a onMouseDown="handlePress(1);return true;"
9397c478bd9Sstevel@tonic-gate			 onMouseUp="handleRelease(1);return true;"
9407c478bd9Sstevel@tonic-gate			 onMouseOut="handleRelease(1);return true;"
9417c478bd9Sstevel@tonic-gate			 onClick="return false;"
9427c478bd9Sstevel@tonic-gate			 title="Go to Beginning Of file">BOF</a></td>
943daaffb31Sdp		    <td>
9447c478bd9Sstevel@tonic-gate		      <a onMouseDown="handlePress(3);return true;"
9457c478bd9Sstevel@tonic-gate			 onMouseUp="handleRelease(3);return true;"
9467c478bd9Sstevel@tonic-gate			 onMouseOut="handleRelease(3);return true;"
9477c478bd9Sstevel@tonic-gate			 title="Scroll Up: Press and Hold to accelerate"
948daaffb31Sdp			 onClick="return false;">Scroll Up</a></td>
949daaffb31Sdp		    <td>
9507c478bd9Sstevel@tonic-gate		      <a onMouseDown="handlePress(2);return true;"
9517c478bd9Sstevel@tonic-gate			 onMouseUp="handleRelease(2);return true;"
9527c478bd9Sstevel@tonic-gate			 onMouseOut="handleRelease(2);return true;"
9537c478bd9Sstevel@tonic-gate			 title="Go to previous Diff"
9547c478bd9Sstevel@tonic-gate			 onClick="return false;">Prev Diff</a>
9557c478bd9Sstevel@tonic-gate		    </td></tr>
956daaffb31Sdp
9577c478bd9Sstevel@tonic-gate		  <tr>
958daaffb31Sdp		    <td>
9597c478bd9Sstevel@tonic-gate		      <a onMouseDown="handlePress(6);return true;"
9607c478bd9Sstevel@tonic-gate			 onMouseUp="handleRelease(6);return true;"
9617c478bd9Sstevel@tonic-gate			 onMouseOut="handleRelease(6);return true;"
9627c478bd9Sstevel@tonic-gate			 onClick="return false;"
9637c478bd9Sstevel@tonic-gate			 title="Go to End Of File">EOF</a></td>
964daaffb31Sdp		    <td>
9657c478bd9Sstevel@tonic-gate		      <a onMouseDown="handlePress(4);return true;"
9667c478bd9Sstevel@tonic-gate			 onMouseUp="handleRelease(4);return true;"
9677c478bd9Sstevel@tonic-gate			 onMouseOut="handleRelease(4);return true;"
9687c478bd9Sstevel@tonic-gate			 title="Scroll Down: Press and Hold to accelerate"
969daaffb31Sdp			 onClick="return false;">Scroll Down</a></td>
970daaffb31Sdp		    <td>
9717c478bd9Sstevel@tonic-gate		      <a onMouseDown="handlePress(5);return true;"
9727c478bd9Sstevel@tonic-gate			 onMouseUp="handleRelease(5);return true;"
9737c478bd9Sstevel@tonic-gate			 onMouseOut="handleRelease(5);return true;"
9747c478bd9Sstevel@tonic-gate			 title="Go to next Diff"
9757c478bd9Sstevel@tonic-gate			 onClick="return false;">Next Diff</a></td>
976daaffb31Sdp		  </tr>
977daaffb31Sdp              </table>
978daaffb31Sdp	    </div>
979daaffb31Sdp	  </td>
9807c478bd9Sstevel@tonic-gate	  <th valign="middle" width="25%">
981daaffb31Sdp	    <form action="" name="diff" onsubmit="return ValidateDiffNum();">
982daaffb31Sdp		<input name="display" value="BOF" size="8" type="text" />
983daaffb31Sdp		<input name="real" value="0" size="8" type="hidden" />
9847c478bd9Sstevel@tonic-gate	    </form>
9857c478bd9Sstevel@tonic-gate	  </th>
986daaffb31Sdp	</tr>
9877c478bd9Sstevel@tonic-gate    </table>
9887c478bd9Sstevel@tonic-gate  </body>
9897c478bd9Sstevel@tonic-gate</html>
9907c478bd9Sstevel@tonic-gateEOF
9917c478bd9Sstevel@tonic-gate}
9927c478bd9Sstevel@tonic-gate
9937c478bd9Sstevel@tonic-gate
994daaffb31Sdp
995daaffb31Sdp#
996daaffb31Sdp# diff_to_html <filename> <filepath> { U | C } <comment>
997daaffb31Sdp#
998daaffb31Sdp# Processes the output of diff to produce an HTML file representing either
999daaffb31Sdp# context or unified diffs.
1000daaffb31Sdp#
10017c478bd9Sstevel@tonic-gatediff_to_html()
10027c478bd9Sstevel@tonic-gate{
10037c478bd9Sstevel@tonic-gate	TNAME=$1
1004daaffb31Sdp	TPATH=$2
1005daaffb31Sdp	DIFFTYPE=$3
1006daaffb31Sdp	COMMENT=$4
1007daaffb31Sdp
1008daaffb31Sdp	print "$HTML<head>$STDHEAD"
1009daaffb31Sdp	print "<title>$WNAME ${DIFFTYPE}diff $TPATH</title>"
1010daaffb31Sdp
1011daaffb31Sdp	if [[ $DIFFTYPE == "U" ]]; then
1012daaffb31Sdp		print "$UDIFFCSS"
1013daaffb31Sdp	fi
1014daaffb31Sdp
1015daaffb31Sdp	cat <<-EOF
1016daaffb31Sdp	</head>
1017daaffb31Sdp	<body id="SUNWwebrev">
1018daaffb31Sdp        <a class="print" href="javascript:print()">Print this page</a>
1019daaffb31Sdp	<pre>$COMMENT</pre>
1020daaffb31Sdp        <pre>
1021daaffb31Sdp	EOF
10227c478bd9Sstevel@tonic-gate
10237c478bd9Sstevel@tonic-gate	html_quote | nawk '
1024daaffb31Sdp	/^--- new/	{ next }
1025daaffb31Sdp	/^\+\+\+ new/	{ next }
1026daaffb31Sdp	/^--- old/	{ next }
1027daaffb31Sdp	/^\*\*\* old/	{ next }
1028daaffb31Sdp	/^\*\*\*\*/	{ next }
10297c478bd9Sstevel@tonic-gate	/^-------/	{ printf "<center><h1>%s</h1></center>\n", $0; next }
1030daaffb31Sdp	/^\@\@.*\@\@$/	{ printf "</pre><hr /><pre>\n";
1031daaffb31Sdp			  printf "<span class=\"newmarker\">%s</span>\n", $0;
1032daaffb31Sdp			  next}
1033daaffb31Sdp
1034daaffb31Sdp	/^\*\*\*/	{ printf "<hr /><span class=\"oldmarker\">%s</span>\n", $0;
1035daaffb31Sdp			  next}
1036daaffb31Sdp	/^---/		{ printf "<span class=\"newmarker\">%s</span>\n", $0;
1037daaffb31Sdp			  next}
1038daaffb31Sdp	/^\+/		{printf "<span class=\"new\">%s</span>\n", $0; next}
1039daaffb31Sdp	/^!/		{printf "<span class=\"changed\">%s</span>\n", $0; next}
1040daaffb31Sdp	/^-/		{printf "<span class=\"removed\">%s</span>\n", $0; next}
1041daaffb31Sdp			{printf "%s\n", $0; next}
10427c478bd9Sstevel@tonic-gate	'
1043daaffb31Sdp
1044daaffb31Sdp	print "</pre></body></html>\n"
10457c478bd9Sstevel@tonic-gate}
10467c478bd9Sstevel@tonic-gate
10477c478bd9Sstevel@tonic-gate
1048daaffb31Sdp#
1049daaffb31Sdp# source_to_html { new | old } <filename>
1050daaffb31Sdp#
1051daaffb31Sdp# Process a plain vanilla source file to transform it into an HTML file.
1052daaffb31Sdp#
10537c478bd9Sstevel@tonic-gatesource_to_html()
10547c478bd9Sstevel@tonic-gate{
10557c478bd9Sstevel@tonic-gate	WHICH=$1
10567c478bd9Sstevel@tonic-gate	TNAME=$2
10577c478bd9Sstevel@tonic-gate
1058daaffb31Sdp	print "$HTML<head>$STDHEAD"
1059daaffb31Sdp	print "<title>$WHICH $TNAME</title>"
1060daaffb31Sdp	print "<body id=\"SUNWwebrev\">"
1061daaffb31Sdp	print "<pre>"
1062daaffb31Sdp	html_quote | nawk '{line += 1 ; printf "%4d %s\n", line, $0 }'
1063daaffb31Sdp	print "</pre></body></html>"
10647c478bd9Sstevel@tonic-gate}
10657c478bd9Sstevel@tonic-gate
1066daaffb31Sdp#
1067daaffb31Sdp# teamwarecomments {text|html} parent-file child-file
1068daaffb31Sdp#
1069daaffb31Sdp# Find the first delta in the child that's not in the parent.  Get the
1070daaffb31Sdp# newest delta from the parent, get all deltas from the child starting
1071daaffb31Sdp# with that delta, and then get all info starting with the second oldest
1072daaffb31Sdp# delta in that list (the first delta unique to the child).
10737c478bd9Sstevel@tonic-gate#
10747c478bd9Sstevel@tonic-gate# This code adapted from Bill Shannon's "spc" script
1075daaffb31Sdp#
1076daaffb31Sdpcomments_from_teamware()
10777c478bd9Sstevel@tonic-gate{
1078daaffb31Sdp	fmt=$1
1079daaffb31Sdp	pfile=$PWS/$2
1080daaffb31Sdp	cfile=$CWS/$3
10817c478bd9Sstevel@tonic-gate
1082daaffb31Sdp	if [[ -f $pfile ]]; then
10837c478bd9Sstevel@tonic-gate		psid=$(sccs prs -d:I: $pfile 2>/dev/null)
10847c478bd9Sstevel@tonic-gate	else
10857c478bd9Sstevel@tonic-gate		psid=1.1
10867c478bd9Sstevel@tonic-gate	fi
10877c478bd9Sstevel@tonic-gate
10887c478bd9Sstevel@tonic-gate	set -A sids $(sccs prs -l -r$psid -d:I: $cfile 2>/dev/null)
10897c478bd9Sstevel@tonic-gate	N=${#sids[@]}
10907c478bd9Sstevel@tonic-gate
1091daaffb31Sdp	nawkprg='
1092daaffb31Sdp		/^COMMENTS:/	{p=1; continue}
1093daaffb31Sdp		/^D [0-9]+\.[0-9]+/ {printf "--- %s ---\n", $2; p=0; }
1094daaffb31Sdp		NF == 0u	{ continue }
1095daaffb31Sdp		{if (p==0) continue; print $0 }'
1096daaffb31Sdp
10977c478bd9Sstevel@tonic-gate	if [[ $N -ge 2 ]]; then
10987c478bd9Sstevel@tonic-gate		sid1=${sids[$((N-2))]}	# Gets 2nd to last sid
10997c478bd9Sstevel@tonic-gate
1100daaffb31Sdp		if [[ $fmt == "text" ]]; then
1101daaffb31Sdp			sccs prs -l -r$sid1 $cfile  2>/dev/null | \
1102daaffb31Sdp			    nawk "$nawkprg"
1103daaffb31Sdp			return
1104daaffb31Sdp		fi
1105daaffb31Sdp
1106daaffb31Sdp		sccs prs -l -r$sid1 $cfile  2>/dev/null | \
1107daaffb31Sdp		    html_quote | bug2url | sac2url | nawk "$nawkprg"
11087c478bd9Sstevel@tonic-gate	fi
11097c478bd9Sstevel@tonic-gate}
11107c478bd9Sstevel@tonic-gate
1111daaffb31Sdp#
1112daaffb31Sdp# wxcomments {text|html} filepath
1113daaffb31Sdp#
1114daaffb31Sdp# Given the pathname of a file, find its location in a "wx" active file
1115daaffb31Sdp# list and print the following sccs comment.  Output is either text or
1116daaffb31Sdp# HTML; if the latter, embedded bugids (sequence of 5 or more digits) are
1117daaffb31Sdp# turned into URLs.
1118daaffb31Sdp#
1119daaffb31Sdpcomments_from_wx()
11207c478bd9Sstevel@tonic-gate{
1121daaffb31Sdp	typeset fmt=$1
1122daaffb31Sdp	typeset p=$2
11237c478bd9Sstevel@tonic-gate
1124daaffb31Sdp	comm=`nawk '
1125daaffb31Sdp	$1 == "'$p'" {
11267c478bd9Sstevel@tonic-gate		do getline ; while (NF > 0)
11277c478bd9Sstevel@tonic-gate		getline
11287c478bd9Sstevel@tonic-gate		while (NF > 0) { print ; getline }
11297c478bd9Sstevel@tonic-gate		exit
1130daaffb31Sdp	}' < $wxfile`
1131daaffb31Sdp
1132daaffb31Sdp	if [[ $fmt == "text" ]]; then
1133daaffb31Sdp		print "$comm"
1134daaffb31Sdp		return
1135daaffb31Sdp	fi
1136daaffb31Sdp
1137daaffb31Sdp	print "$comm" | html_quote | bug2url | sac2url
11387c478bd9Sstevel@tonic-gate}
11397c478bd9Sstevel@tonic-gate
11407c478bd9Sstevel@tonic-gate#
1141daaffb31Sdp# getcomments {text|html} filepath parentpath
1142daaffb31Sdp#
1143daaffb31Sdp# Fetch the comments depending on what SCM mode we're in.
1144daaffb31Sdp#
1145daaffb31Sdpgetcomments()
1146daaffb31Sdp{
1147daaffb31Sdp	typeset fmt=$1
1148daaffb31Sdp	typeset p=$2
1149daaffb31Sdp	typeset pp=$3
11507c478bd9Sstevel@tonic-gate
1151daaffb31Sdp	if [[ -n $wxfile ]]; then
1152daaffb31Sdp		comments_from_wx $fmt $p
1153daaffb31Sdp	else
1154daaffb31Sdp		if [[ $SCM_MODE == "teamware" ]]; then
1155daaffb31Sdp			comments_from_teamware $fmt $pp $p
1156daaffb31Sdp		fi
1157daaffb31Sdp	fi
1158daaffb31Sdp}
1159daaffb31Sdp
1160daaffb31Sdp#
1161daaffb31Sdp# printCI <total-changed> <inserted> <deleted> <modified> <unchanged>
1162daaffb31Sdp#
1163daaffb31Sdp# Print out Code Inspection figures similar to sccs-prt(1) format.
1164daaffb31Sdp#
1165daaffb31Sdpfunction printCI
1166daaffb31Sdp{
1167daaffb31Sdp	integer tot=$1 ins=$2 del=$3 mod=$4 unc=$5
1168daaffb31Sdp	typeset str
1169daaffb31Sdp	if (( tot == 1 )); then
1170daaffb31Sdp		str="line"
1171daaffb31Sdp	else
1172daaffb31Sdp		str="lines"
1173daaffb31Sdp	fi
1174daaffb31Sdp	printf '%d %s changed: %d ins; %d del; %d mod; %d unchg\n' \
1175daaffb31Sdp	    $tot $str $ins $del $mod $unc
1176daaffb31Sdp}
1177daaffb31Sdp
1178daaffb31Sdp
1179daaffb31Sdp#
1180daaffb31Sdp# difflines <oldfile> <newfile>
1181daaffb31Sdp#
1182daaffb31Sdp# Calculate and emit number of added, removed, modified and unchanged lines,
1183daaffb31Sdp# and total lines changed, the sum of added + removed + modified.
1184daaffb31Sdp#
11857c478bd9Sstevel@tonic-gatefunction difflines
11867c478bd9Sstevel@tonic-gate{
1187daaffb31Sdp	integer tot mod del ins unc err
11887c478bd9Sstevel@tonic-gate	typeset filename
11897c478bd9Sstevel@tonic-gate
11907c478bd9Sstevel@tonic-gate	diff -e $1 $2 | eval $( nawk '
1191daaffb31Sdp	# Change range of lines: N,Nc
11927c478bd9Sstevel@tonic-gate	/^[0-9]*,[0-9]*c$/ {
11937c478bd9Sstevel@tonic-gate		n=split(substr($1,1,length($1)-1), counts, ",");
11947c478bd9Sstevel@tonic-gate		if (n != 2) {
11957c478bd9Sstevel@tonic-gate		    error=2
11967c478bd9Sstevel@tonic-gate		    exit;
11977c478bd9Sstevel@tonic-gate		}
1198daaffb31Sdp		#
1199daaffb31Sdp		# 3,5c means lines 3 , 4 and 5 are changed, a total of 3 lines.
1200daaffb31Sdp		# following would be 5 - 3 = 2! Hence +1 for correction.
1201daaffb31Sdp		#
12027c478bd9Sstevel@tonic-gate		r=(counts[2]-counts[1])+1;
1203daaffb31Sdp
1204daaffb31Sdp		#
1205daaffb31Sdp		# Now count replacement lines: each represents a change instead
1206daaffb31Sdp		# of a delete, so increment c and decrement r.
1207daaffb31Sdp		#
12087c478bd9Sstevel@tonic-gate		while (getline != /^\.$/) {
12097c478bd9Sstevel@tonic-gate			c++;
12107c478bd9Sstevel@tonic-gate			r--;
12117c478bd9Sstevel@tonic-gate		}
1212daaffb31Sdp		#
1213daaffb31Sdp		# If there were more replacement lines than original lines,
1214daaffb31Sdp		# then r will be negative; in this case there are no deletions,
1215daaffb31Sdp		# but there are r changes that should be counted as adds, and
1216daaffb31Sdp		# since r is negative, subtract it from a and add it to c.
1217daaffb31Sdp		#
12187c478bd9Sstevel@tonic-gate		if (r < 0) {
12197c478bd9Sstevel@tonic-gate			a-=r;
12207c478bd9Sstevel@tonic-gate			c+=r;
12217c478bd9Sstevel@tonic-gate		}
1222daaffb31Sdp
1223daaffb31Sdp		#
1224daaffb31Sdp		# If there were more original lines than replacement lines, then
1225daaffb31Sdp		# r will be positive; in this case, increment d by that much.
1226daaffb31Sdp		#
12277c478bd9Sstevel@tonic-gate		if (r > 0) {
12287c478bd9Sstevel@tonic-gate			d+=r;
12297c478bd9Sstevel@tonic-gate		}
12307c478bd9Sstevel@tonic-gate		next;
12317c478bd9Sstevel@tonic-gate	}
12327c478bd9Sstevel@tonic-gate
1233daaffb31Sdp	# Change lines: Nc
12347c478bd9Sstevel@tonic-gate	/^[0-9].*c$/ {
1235daaffb31Sdp		# The first line is a replacement; any more are additions.
12367c478bd9Sstevel@tonic-gate		if (getline != /^\.$/) {
12377c478bd9Sstevel@tonic-gate			c++;
12387c478bd9Sstevel@tonic-gate			while (getline != /^\.$/) a++;
12397c478bd9Sstevel@tonic-gate		}
12407c478bd9Sstevel@tonic-gate		next;
12417c478bd9Sstevel@tonic-gate	}
12427c478bd9Sstevel@tonic-gate
1243daaffb31Sdp	# Add lines: both Na and N,Na
12447c478bd9Sstevel@tonic-gate	/^[0-9].*a$/ {
12457c478bd9Sstevel@tonic-gate		while (getline != /^\.$/) a++;
12467c478bd9Sstevel@tonic-gate		next;
12477c478bd9Sstevel@tonic-gate	}
12487c478bd9Sstevel@tonic-gate
1249daaffb31Sdp	# Delete range of lines: N,Nd
12507c478bd9Sstevel@tonic-gate	/^[0-9]*,[0-9]*d$/ {
12517c478bd9Sstevel@tonic-gate		n=split(substr($1,1,length($1)-1), counts, ",");
12527c478bd9Sstevel@tonic-gate		if (n != 2) {
12537c478bd9Sstevel@tonic-gate			error=2
12547c478bd9Sstevel@tonic-gate			exit;
12557c478bd9Sstevel@tonic-gate		}
1256daaffb31Sdp		#
1257daaffb31Sdp		# 3,5d means lines 3 , 4 and 5 are deleted, a total of 3 lines.
1258daaffb31Sdp		# following would be 5 - 3 = 2! Hence +1 for correction.
1259daaffb31Sdp		#
12607c478bd9Sstevel@tonic-gate		r=(counts[2]-counts[1])+1;
12617c478bd9Sstevel@tonic-gate		d+=r;
12627c478bd9Sstevel@tonic-gate		next;
12637c478bd9Sstevel@tonic-gate	}
12647c478bd9Sstevel@tonic-gate
1265daaffb31Sdp	# Delete line: Nd.   For example 10d says line 10 is deleted.
12667c478bd9Sstevel@tonic-gate	/^[0-9]*d$/ {d++; next}
12677c478bd9Sstevel@tonic-gate
1268daaffb31Sdp	# Should not get here!
12697c478bd9Sstevel@tonic-gate	{
12707c478bd9Sstevel@tonic-gate		error=1;
12717c478bd9Sstevel@tonic-gate		exit;
12727c478bd9Sstevel@tonic-gate	}
12737c478bd9Sstevel@tonic-gate
1274daaffb31Sdp	# Finish off - print results
12757c478bd9Sstevel@tonic-gate	END {
1276daaffb31Sdp		printf("tot=%d;mod=%d;del=%d;ins=%d;err=%d\n",
12777c478bd9Sstevel@tonic-gate		    (c+d+a), c, d, a, error);
12787c478bd9Sstevel@tonic-gate	}' )
12797c478bd9Sstevel@tonic-gate
12807c478bd9Sstevel@tonic-gate	# End of nawk, Check to see if any trouble occurred.
12817c478bd9Sstevel@tonic-gate	if (( $? > 0 || err > 0 )); then
1282daaffb31Sdp		print "Unexpected Error occurred reading" \
1283daaffb31Sdp		    "\`diff -e $1 $2\`: \$?=$?, err=" $err
1284daaffb31Sdp		return
1285daaffb31Sdp	fi
1286daaffb31Sdp
12877c478bd9Sstevel@tonic-gate	# Accumulate totals
12887c478bd9Sstevel@tonic-gate	(( TOTL += tot ))
1289daaffb31Sdp	(( TMOD += mod ))
12907c478bd9Sstevel@tonic-gate	(( TDEL += del ))
12917c478bd9Sstevel@tonic-gate	(( TINS += ins ))
12927c478bd9Sstevel@tonic-gate	# Calculate unchanged lines
12937c478bd9Sstevel@tonic-gate	wc -l $1 | read unc filename
12947c478bd9Sstevel@tonic-gate	if (( unc > 0 )); then
1295daaffb31Sdp		(( unc -= del + mod ))
12967c478bd9Sstevel@tonic-gate		(( TUNC += unc ))
12977c478bd9Sstevel@tonic-gate	fi
12987c478bd9Sstevel@tonic-gate	# print summary
1299daaffb31Sdp	print "<span class=\"lineschanged\">"
1300daaffb31Sdp	printCI $tot $ins $del $mod $unc
1301daaffb31Sdp	print "</span>"
13027c478bd9Sstevel@tonic-gate}
13037c478bd9Sstevel@tonic-gate
1304daaffb31Sdp
13057c478bd9Sstevel@tonic-gate#
1306daaffb31Sdp# flist_from_wx
1307daaffb31Sdp#
1308daaffb31Sdp# Sets up webrev to source its information from a wx-formatted file.
1309daaffb31Sdp# Sets the global 'wxfile' variable.
1310daaffb31Sdp#
1311daaffb31Sdpfunction flist_from_wx
13127c478bd9Sstevel@tonic-gate{
1313daaffb31Sdp	typeset argfile=$1
1314daaffb31Sdp	if [[ -n ${argfile%%/*} ]]; then
1315daaffb31Sdp		#
1316daaffb31Sdp		# If the wx file pathname is relative then make it absolute
1317daaffb31Sdp		# because the webrev does a "cd" later on.
1318daaffb31Sdp		#
1319daaffb31Sdp		wxfile=$PWD/$argfile
13207c478bd9Sstevel@tonic-gate	else
1321daaffb31Sdp		wxfile=$argfile
13227c478bd9Sstevel@tonic-gate	fi
13237c478bd9Sstevel@tonic-gate
13247c478bd9Sstevel@tonic-gate	nawk '{ c = 1; print;
13257c478bd9Sstevel@tonic-gate	  while (getline) {
13267c478bd9Sstevel@tonic-gate		if (NF == 0) { c = -c; continue }
13277c478bd9Sstevel@tonic-gate		if (c > 0) print
13287c478bd9Sstevel@tonic-gate	  }
1329daaffb31Sdp	}' $wxfile > $FLIST
13307c478bd9Sstevel@tonic-gate
1331daaffb31Sdp	print " Done."
1332daaffb31Sdp}
13337c478bd9Sstevel@tonic-gate
1334daaffb31Sdp#
1335daaffb31Sdp# flist_from_teamware [ <args-to-putback-n> ]
1336daaffb31Sdp#
1337daaffb31Sdp# Generate the file list by extracting file names from a putback -n.  Some
1338daaffb31Sdp# names may come from the "update/create" messages and others from the
1339daaffb31Sdp# "currently checked out" warning.  Renames are detected here too.  Extract
1340daaffb31Sdp# values for CODEMGR_WS and CODEMGR_PARENT from the output of the putback
1341daaffb31Sdp# -n as well, but remove them if they are already defined.
1342daaffb31Sdp#
1343daaffb31Sdpfunction flist_from_teamware
1344daaffb31Sdp{
1345daaffb31Sdp	if [[ -n $codemgr_parent ]]; then
1346daaffb31Sdp		if [[ ! -d $codemgr_parent/Codemgr_wsdata ]]; then
1347daaffb31Sdp			print -u2 "parent $codemgr_parent doesn't look like a" \
1348daaffb31Sdp			    "valid teamware workspace"
13497c478bd9Sstevel@tonic-gate			exit 1
13507c478bd9Sstevel@tonic-gate		fi
1351daaffb31Sdp		parent_args="-p $codemgr_parent"
13527c478bd9Sstevel@tonic-gate	fi
13537c478bd9Sstevel@tonic-gate
1354daaffb31Sdp	print " File list from: 'putback -n $parent_args $*' ... \c"
13557c478bd9Sstevel@tonic-gate
1356daaffb31Sdp	putback -n $parent_args $* 2>&1 |
1357daaffb31Sdp	    nawk '
1358daaffb31Sdp		/^update:|^create:/	{print $2}
1359daaffb31Sdp		/^Parent workspace:/	{printf("CODEMGR_PARENT=%s\n",$3)}
1360daaffb31Sdp		/^Child workspace:/	{printf("CODEMGR_WS=%s\n",$3)}
1361daaffb31Sdp		/^The following files are currently checked out/ {p = 1; continue}
1362daaffb31Sdp		NF == 0			{p=0 ; continue}
1363daaffb31Sdp		/^rename/		{old=$3}
1364daaffb31Sdp		$1 == "to:"		{print $2, old}
1365daaffb31Sdp		/^"/			{continue}
1366daaffb31Sdp		p == 1			{print $1}' |
1367daaffb31Sdp	    sort -r -k 1,1 -u | sort > $FLIST
13687c478bd9Sstevel@tonic-gate
1369daaffb31Sdp	print " Done."
1370daaffb31Sdp}
1371daaffb31Sdp
1372daaffb31Sdpfunction env_from_flist
1373daaffb31Sdp{
1374daaffb31Sdp	[[ -r $FLIST ]] || return
1375daaffb31Sdp
1376daaffb31Sdp	#
1377daaffb31Sdp	# Use "eval" to set env variables that are listed in the file
1378daaffb31Sdp	# list.  Then copy those into our local versions of those
1379daaffb31Sdp	# variables if they have not been set already.
1380daaffb31Sdp	#
13817c478bd9Sstevel@tonic-gate	eval `sed -e "s/#.*$//" $FLIST | grep = `
13827c478bd9Sstevel@tonic-gate
1383daaffb31Sdp	[[ -z $codemgr_ws && -n $CODEMGR_WS ]] && codemgr_ws=$CODEMGR_WS
13847c478bd9Sstevel@tonic-gate
1385daaffb31Sdp	#
1386daaffb31Sdp	# Check to see if CODEMGR_PARENT is set in the flist file.
1387daaffb31Sdp	#
1388daaffb31Sdp	[[ -z $codemgr_parent && -n $CODEMGR_PARENT ]] && \
1389daaffb31Sdp	    codemgr_parent=$CODEMGR_PARENT
1390daaffb31Sdp}
1391daaffb31Sdp
1392daaffb31Sdp#
1393daaffb31Sdp# detect_scm
1394daaffb31Sdp#
1395daaffb31Sdp# We dynamically test the SCM type; this allows future extensions to
1396daaffb31Sdp# new SCM types
1397daaffb31Sdp#
1398daaffb31Sdpfunction detect_scm
1399daaffb31Sdp{
1400daaffb31Sdp	#
1401daaffb31Sdp	# If CODEMGR_WS is specified in the flist file, we assume teamware.
1402daaffb31Sdp	#
1403daaffb31Sdp	if [[ -r $FLIST ]]; then
1404daaffb31Sdp		egrep '^CODEMGR_WS=' $FLIST > /dev/null 2>&1
1405daaffb31Sdp		if [[ $? -eq 0 ]]; then
1406daaffb31Sdp			print "teamware"
1407daaffb31Sdp			return
1408daaffb31Sdp		fi
1409daaffb31Sdp	fi
1410daaffb31Sdp
1411daaffb31Sdp	#
1412daaffb31Sdp	# The presence of $CODEMGR_WS and a Codemgr_wsdata directory
1413daaffb31Sdp	# is our clue that this is a teamware workspace.
1414daaffb31Sdp	#
1415daaffb31Sdp	if [[ -n $CODEMGR_WS && -d "$CODEMGR_WS/Codemgr_wsdata" ]]; then
1416daaffb31Sdp		print "teamware"
1417daaffb31Sdp	else
1418daaffb31Sdp		print "unknown"
1419daaffb31Sdp	fi
1420daaffb31Sdp}
1421daaffb31Sdp
1422*14983201Sdpfunction look_for_prog
1423*14983201Sdp{
1424*14983201Sdp	typeset path
1425*14983201Sdp	typeset ppath
1426*14983201Sdp	typeset progname=$1
1427*14983201Sdp
1428*14983201Sdp	ppath=$PATH
1429*14983201Sdp	ppath=$ppath:/usr/sfw/bin:/usr/bin:/usr/sbin
1430*14983201Sdp	ppath=$ppath:/opt/teamware/bin:/opt/onbld/bin
1431*14983201Sdp	ppath=$ppath:/opt/onbld/bin/`/usr/bin/uname -p`
1432*14983201Sdp
1433*14983201Sdp	PATH=$ppath prog=`whence $progname`
1434*14983201Sdp	if [[ -n $prog ]]; then
1435*14983201Sdp		print $prog
1436*14983201Sdp	fi
1437*14983201Sdp}
1438*14983201Sdp
1439daaffb31Sdp#
1440daaffb31Sdp# Usage message.
1441daaffb31Sdp#
1442daaffb31Sdpfunction usage
1443daaffb31Sdp{
1444daaffb31Sdp	print 'Usage:\twebrev [common-options]
1445daaffb31Sdp	webrev [common-options] ( <file> | - )
1446daaffb31Sdp	webrev [common-options] -w <wx file>
1447daaffb31Sdp	webrev [common-options] -l [arguments to 'putback']
1448daaffb31Sdp
1449daaffb31SdpOptions:
1450daaffb31Sdp	-O: Print bugids/arc cases suitable for OpenSolaris.
1451daaffb31Sdp	-i <filename>: Include <filename> in the index.html file.
1452daaffb31Sdp	-o <outdir>: Output webrev to specified directory.
1453daaffb31Sdp	-p <compare-against>: Use specified parent wkspc or basis for comparison
1454daaffb31Sdp	-w <wxfile>: Use specified wx active file.
1455daaffb31Sdp
1456daaffb31SdpEnvironment:
1457daaffb31Sdp	WDIR: Control the output directory.
1458daaffb31Sdp	WEBREV_BUGURL: Control the URL prefix for bugids.
1459daaffb31Sdp	WEBREV_SACURL: Control the URL prefix for ARC cases.
1460daaffb31Sdp
1461daaffb31SdpSCM Environment:
1462daaffb31Sdp	Teamware: CODEMGR_WS: Workspace location.
1463daaffb31Sdp	Teamware: CODEMGR_PARENT: Parent workspace location.
1464daaffb31Sdp'
1465daaffb31Sdp
1466daaffb31Sdp	exit 2
1467daaffb31Sdp}
1468daaffb31Sdp
1469daaffb31Sdp#
1470daaffb31Sdp#
1471daaffb31Sdp# Main program starts here
1472daaffb31Sdp#
1473daaffb31Sdp#
1474daaffb31Sdp
1475daaffb31Sdptrap "rm -f /tmp/$$.* ; exit" 0 1 2 3 15
1476daaffb31Sdp
1477daaffb31Sdpset +o noclobber
1478daaffb31Sdp
1479*14983201Sdp[[ -z $WDIFF ]] && WDIFF=`look_for_prog wdiff`
1480*14983201Sdp[[ -z $WX ]] && WX=`look_for_prog wx`
1481*14983201Sdp[[ -z $CODEREVIEW ]] && CODEREVIEW=`look_for_prog codereview`
1482*14983201Sdp[[ -z $PS2PDF ]] && PS2PDF=`look_for_prog ps2pdf`
1483*14983201Sdp[[ -z $PERL ]] && PERL=`look_for_prog perl`
1484*14983201Sdp
1485*14983201Sdpif [[ ! -x $PERL ]]; then
1486*14983201Sdp	print -u2 "Error: No perl interpreter found.  Exiting."
1487*14983201Sdp	exit 1
1488daaffb31Sdpfi
1489*14983201Sdp
1490*14983201Sdp#
1491*14983201Sdp# These aren't fatal, but we want to note them to the user.
1492*14983201Sdp# We don't warn on the absence of 'wx' until later when we've
1493*14983201Sdp# determined that we actually need to try to invoke it.
1494*14983201Sdp#
1495*14983201Sdp[[ ! -x $CODEREVIEW ]] && print -u2 "WARNING: codereview(1) not found."
1496*14983201Sdp[[ ! -x $PS2PDF ]] && print -u2 "WARNING: ps2pdf(1) not found."
1497*14983201Sdp[[ ! -x $WDIFF ]] && print -u2 "WARNING: wdiff not found."
1498daaffb31Sdp
1499daaffb31Sdp# Declare global total counters.
1500daaffb31Sdpinteger TOTL TINS TDEL TMOD TUNC
1501daaffb31Sdp
1502*14983201Sdpflist_mode=
1503*14983201Sdpflist_file=
1504daaffb31Sdpiflag=
1505daaffb31Sdpoflag=
1506daaffb31Sdppflag=
1507daaffb31Sdplflag=
1508daaffb31Sdpwflag=
1509daaffb31SdpOflag=
1510daaffb31Sdpwhile getopts "i:o:p:lwO" opt
1511daaffb31Sdpdo
1512daaffb31Sdp	case $opt in
1513daaffb31Sdp	i)	iflag=1
1514daaffb31Sdp		INCLUDE_FILE=$OPTARG;;
1515daaffb31Sdp
1516daaffb31Sdp	o)	oflag=1
1517daaffb31Sdp		WDIR=$OPTARG;;
1518daaffb31Sdp
1519daaffb31Sdp	p)	pflag=1
1520daaffb31Sdp		codemgr_parent=$OPTARG;;
1521daaffb31Sdp
1522daaffb31Sdp	#
1523daaffb31Sdp	# If -l has been specified, we need to abort further options
1524daaffb31Sdp	# processing, because subsequent arguments are going to be
1525daaffb31Sdp	# arguments to 'putback -n'.
1526daaffb31Sdp	#
1527daaffb31Sdp	l)	lflag=1
1528daaffb31Sdp		break;;
1529daaffb31Sdp
1530daaffb31Sdp	w)	wflag=1;;
1531daaffb31Sdp
1532daaffb31Sdp	O)	Oflag=1;;
1533daaffb31Sdp
1534daaffb31Sdp	?)	usage;;
1535daaffb31Sdp	esac
1536daaffb31Sdpdone
1537daaffb31Sdp
1538daaffb31SdpFLIST=/tmp/$$.flist
1539daaffb31Sdp
1540daaffb31Sdpif [[ -n $wflag && -n $lflag ]]; then
1541daaffb31Sdp	usage
1542daaffb31Sdpfi
1543daaffb31Sdp
1544daaffb31Sdp#
1545daaffb31Sdp# If this manually set as the parent, and it appears to be an earlier webrev,
1546daaffb31Sdp# then note that fact and set the parent to the raw_files/new subdirectory.
1547daaffb31Sdp#
1548daaffb31Sdpif [[ -n $pflag && -d $codemgr_parent/raw_files/new ]]; then
1549daaffb31Sdp	parent_webrev="$codemgr_parent"
1550daaffb31Sdp	codemgr_parent="$codemgr_parent/raw_files/new"
1551daaffb31Sdpfi
1552daaffb31Sdp
1553daaffb31Sdpif [[ -z $wflag && -z $lflag ]]; then
1554daaffb31Sdp	shift $(($OPTIND - 1))
1555daaffb31Sdp
1556daaffb31Sdp	if [[ $1 == "-" ]]; then
1557daaffb31Sdp		cat > $FLIST
1558*14983201Sdp		flist_mode="stdin"
1559*14983201Sdp		flist_done=1
1560*14983201Sdp		shift
1561daaffb31Sdp	elif [[ -n $1 ]]; then
1562*14983201Sdp		if [[ ! -r $1 ]]; then
1563daaffb31Sdp			print -u2 "$1: no such file or not readable"
1564daaffb31Sdp			usage
1565daaffb31Sdp		fi
1566daaffb31Sdp		cat $1 > $FLIST
1567*14983201Sdp		flist_mode="file"
1568*14983201Sdp		flist_file=$1
1569*14983201Sdp		flist_done=1
1570*14983201Sdp		shift
1571daaffb31Sdp	else
1572*14983201Sdp		flist_mode="auto"
1573daaffb31Sdp	fi
1574daaffb31Sdpfi
1575daaffb31Sdp
1576daaffb31Sdp#
1577daaffb31Sdp# Before we go on to further consider -l and -w, work out which SCM we think
1578daaffb31Sdp# is in use.
1579daaffb31Sdp#
1580daaffb31SdpSCM_MODE=`detect_scm $FLIST`
1581daaffb31Sdpif [[ $SCM_MODE == "unknown" ]]; then
1582daaffb31Sdp	print -u2 "Unable to determine SCM type currently in use."
1583daaffb31Sdp	print -u2 "For teamware: webrev looks for \$CODEMGR_WS either in"
1584daaffb31Sdp	print -u2 "              the environment or in the file list."
15857c478bd9Sstevel@tonic-gate	exit 1
15867c478bd9Sstevel@tonic-gatefi
15877c478bd9Sstevel@tonic-gate
1588daaffb31Sdpprint -u2 "   SCM detected: $SCM_MODE"
1589daaffb31Sdp
1590daaffb31Sdpif [[ -n $lflag ]]; then
1591daaffb31Sdp	#
1592daaffb31Sdp	# If the -l flag is given instead of the name of a file list,
1593daaffb31Sdp	# then generate the file list by extracting file names from a
1594daaffb31Sdp	# putback -n.
1595daaffb31Sdp	#
1596daaffb31Sdp	shift $(($OPTIND - 1))
1597daaffb31Sdp	flist_from_teamware "$*"
1598daaffb31Sdp	flist_done=1
1599daaffb31Sdp	shift $#
1600daaffb31Sdp
1601daaffb31Sdpelif [[ -n $wflag ]]; then
1602daaffb31Sdp	#
1603daaffb31Sdp	# If the -w is given then assume the file list is in Bonwick's "wx"
1604daaffb31Sdp	# command format, i.e.  pathname lines alternating with SCCS comment
1605daaffb31Sdp	# lines with blank lines as separators.  Use the SCCS comments later
1606daaffb31Sdp	# in building the index.html file.
1607daaffb31Sdp	#
1608daaffb31Sdp	shift $(($OPTIND - 1))
1609daaffb31Sdp	wxfile=$1
1610daaffb31Sdp	if [[ -z $wxfile && -n $CODEMGR_WS ]]; then
1611daaffb31Sdp		if [[ -r $CODEMGR_WS/wx/active ]]; then
1612daaffb31Sdp			wxfile=$CODEMGR_WS/wx/active
1613daaffb31Sdp		fi
1614daaffb31Sdp	fi
1615daaffb31Sdp
1616daaffb31Sdp	[[ -z $wxfile ]] && print -u2 "wx file not specified, and could not " \
1617daaffb31Sdp	    "be auto-detected (check \$CODEMGR_WS)" && exit 1
1618daaffb31Sdp
1619daaffb31Sdp	print -u2 " File list from: wx 'active' file '$wxfile' ... \c"
1620daaffb31Sdp	flist_from_wx $wxfile
1621daaffb31Sdp	flist_done=1
1622daaffb31Sdp	if [[ -n "$*" ]]; then
1623daaffb31Sdp		shift
1624daaffb31Sdp	fi
1625*14983201Sdpelif [[ $flist_mode == "stdin" ]]; then
1626*14983201Sdp	print -u2 " File list from: standard input"
1627*14983201Sdpelif [[ $flist_mode == "file" ]]; then
1628*14983201Sdp	print -u2 " File list from: $flist_file"
1629daaffb31Sdpfi
1630daaffb31Sdp
1631daaffb31Sdpif [[ $# -gt 0 ]]; then
1632*14983201Sdp	print -u2 "WARNING: unused arguments: $*"
1633daaffb31Sdpfi
1634daaffb31Sdp
1635daaffb31Sdpif [[ $SCM_MODE == "teamware" ]]; then
1636daaffb31Sdp	#
1637daaffb31Sdp	# Parent (internally $codemgr_parent) and workspace ($codemgr_ws) can
1638daaffb31Sdp	# be set in a number of ways, in decreasing precedence:
1639daaffb31Sdp	#
1640daaffb31Sdp	#      1) on the command line (only for the parent)
1641daaffb31Sdp	#      2) in the user environment
1642daaffb31Sdp	#      3) in the flist
1643daaffb31Sdp	#      4) automatically based on the workspace (only for the parent)
1644daaffb31Sdp	#
1645daaffb31Sdp
1646daaffb31Sdp	#
1647daaffb31Sdp	# Here is case (2): the user environment
1648daaffb31Sdp	#
1649daaffb31Sdp	[[ -z $codemgr_ws && -n $CODEMGR_WS ]] && codemgr_ws=$CODEMGR_WS
1650daaffb31Sdp	if [[ -n $codemgr_ws && ! -d $codemgr_ws ]]; then
1651daaffb31Sdp		print -u2 "$codemgr_ws: no such workspace"
16527c478bd9Sstevel@tonic-gate		exit 1
16537c478bd9Sstevel@tonic-gate	fi
16547c478bd9Sstevel@tonic-gate
1655daaffb31Sdp	[[ -z $codemgr_parent && -n $CODEMGR_PARENT ]] && \
1656daaffb31Sdp	    codemgr_parent=$CODEMGR_PARENT
1657daaffb31Sdp	if [[ -n $codemgr_parent && ! -d $codemgr_parent ]]; then
1658daaffb31Sdp		print -u2 "$codemgr_parent: no such directory"
16597c478bd9Sstevel@tonic-gate		exit 1
16607c478bd9Sstevel@tonic-gate	fi
16617c478bd9Sstevel@tonic-gate
1662daaffb31Sdp	#
1663daaffb31Sdp	# If we're in auto-detect mode and we haven't already gotten the file
1664daaffb31Sdp	# list, then see if we can get it by probing for wx.
1665daaffb31Sdp	#
1666*14983201Sdp	if [[ -z $flist_done && $flist_mode == "auto" && -n $codemgr_ws ]]; then
1667*14983201Sdp		if [[ ! -x $WX ]]; then
1668*14983201Sdp			print -u2 "WARNING: wx not found!"
1669daaffb31Sdp		fi
16707c478bd9Sstevel@tonic-gate
1671daaffb31Sdp		#
1672daaffb31Sdp		# We need to use wx list -w so that we get renamed files, etc.
1673daaffb31Sdp		# but only if a wx active file exists-- otherwise wx will
1674daaffb31Sdp		# hang asking us to initialize our wx information.
1675daaffb31Sdp		#
1676*14983201Sdp		if [[ -x $WX && -f $codemgr_ws/wx/active ]]; then
1677daaffb31Sdp			print -u2 " File list from: 'wx list -w' ... \c"
1678daaffb31Sdp			$WX list -w > $FLIST
1679daaffb31Sdp			$WX comments > /tmp/$$.wx_comments
1680daaffb31Sdp			wxfile=/tmp/$$.wx_comments
1681daaffb31Sdp			print -u2 "done"
1682daaffb31Sdp			flist_done=1
1683daaffb31Sdp		fi
1684daaffb31Sdp	fi
1685daaffb31Sdp
1686daaffb31Sdp	#
1687daaffb31Sdp	# If by hook or by crook we've gotten a file list by now (perhaps
1688daaffb31Sdp	# from the command line), eval it to extract environment variables from
1689daaffb31Sdp	# it: This is step (3).
1690daaffb31Sdp	#
1691daaffb31Sdp	env_from_flist
1692daaffb31Sdp
1693daaffb31Sdp	#
1694daaffb31Sdp	# Continuing step (3): If we still have no file list, we'll try to get
1695daaffb31Sdp	# it from teamware.
1696daaffb31Sdp	#
1697daaffb31Sdp	if [[ -z $flist_done ]]; then
1698daaffb31Sdp		flist_from_teamware
1699daaffb31Sdp		env_from_flist
1700daaffb31Sdp	fi
1701daaffb31Sdp
1702daaffb31Sdp	#
1703daaffb31Sdp	# Observe true directory name of CODEMGR_WS, as used later in
1704daaffb31Sdp	# webrev title.
1705daaffb31Sdp	#
1706daaffb31Sdp	codemgr_ws=$(cd $codemgr_ws;print $PWD)
1707daaffb31Sdp
1708daaffb31Sdp	#
1709daaffb31Sdp	# (4) If we still don't have a value for codemgr_parent, get it
1710daaffb31Sdp	# from workspace.
1711daaffb31Sdp	#
1712daaffb31Sdp	[[ -z $codemgr_parent ]] && codemgr_parent=`workspace parent`
1713daaffb31Sdp	if [[ ! -d $codemgr_parent ]]; then
1714daaffb31Sdp		print -u2 "$CODEMGR_PARENT: no such parent workspace"
1715daaffb31Sdp		exit 1
1716daaffb31Sdp	fi
1717daaffb31Sdp
1718daaffb31Sdp	#
1719daaffb31Sdp	# Reset CODEMGR_WS to make sure teamware commands are happy.
1720daaffb31Sdp	#
1721daaffb31Sdp	CODEMGR_WS=$codemgr_ws
1722daaffb31Sdp	CWS=$codemgr_ws
1723daaffb31Sdp	PWS=$codemgr_parent
1724daaffb31Sdpfi
1725daaffb31Sdp
1726daaffb31Sdp#
1727daaffb31Sdp# If the user didn't specify a -i option, check to see if there is a
1728daaffb31Sdp# webrev-info file in the workspace directory.
1729daaffb31Sdp#
1730daaffb31Sdpif [[ -z $iflag && -r "$CWS/webrev-info" ]]; then
1731daaffb31Sdp	iflag=1
1732daaffb31Sdp	INCLUDE_FILE="$CWS/webrev-info"
1733daaffb31Sdpfi
1734daaffb31Sdp
1735daaffb31Sdpif [[ -n $iflag ]]; then
1736daaffb31Sdp	if [[ ! -r $INCLUDE_FILE ]]; then
1737daaffb31Sdp		print -u2 "include file '$INCLUDE_FILE' does not exist or is" \
1738daaffb31Sdp		    "not readable."
1739daaffb31Sdp		exit 1
1740daaffb31Sdp	else
1741daaffb31Sdp		#
1742daaffb31Sdp		# $INCLUDE_FILE may be a relative path, and the script alters
1743daaffb31Sdp		# PWD, so we just stash a copy in /tmp.
1744daaffb31Sdp		#
1745daaffb31Sdp		cp $INCLUDE_FILE /tmp/$$.include
1746daaffb31Sdp	fi
1747daaffb31Sdpfi
1748daaffb31Sdp
1749daaffb31Sdp#
1750daaffb31Sdp# Output directory.
1751daaffb31Sdp#
1752daaffb31SdpWDIR=${WDIR:-$CWS/webrev}
1753daaffb31Sdp
1754daaffb31Sdp#
1755daaffb31Sdp# Name of the webrev, derived from the workspace name; in the
1756daaffb31Sdp# future this could potentially be an option.
1757daaffb31Sdp#
1758daaffb31SdpWNAME=${CWS##*/}
1759daaffb31Sdp
17607c478bd9Sstevel@tonic-gateif [ ${WDIR%%/*} ]; then
17617c478bd9Sstevel@tonic-gate	WDIR=$PWD/$WDIR
17627c478bd9Sstevel@tonic-gatefi
1763daaffb31Sdp
1764daaffb31Sdpif [[ ! -d $WDIR ]]; then
1765daaffb31Sdp	mkdir -p $WDIR
1766daaffb31Sdp	[[ $? != 0 ]] && exit 1
17677c478bd9Sstevel@tonic-gatefi
17687c478bd9Sstevel@tonic-gate
1769daaffb31Sdp#
1770daaffb31Sdp# Summarize what we're going to do.
1771daaffb31Sdp#
1772daaffb31Sdpprint "      Workspace: $CWS"
1773daaffb31Sdpif [[ -n $parent_webrev ]]; then
1774daaffb31Sdp	print "Compare against: webrev at $parent_webrev"
1775daaffb31Sdpelse
1776daaffb31Sdp	print "Compare against: $PWS"
1777daaffb31Sdpfi
1778daaffb31Sdp
1779daaffb31Sdp[[ -n $INCLUDE_FILE ]] && print "      Including: $INCLUDE_FILE"
1780daaffb31Sdpprint "      Output to: $WDIR"
1781daaffb31Sdp
1782daaffb31Sdp#
17837c478bd9Sstevel@tonic-gate# Save the file list in the webrev dir
1784daaffb31Sdp#
1785daaffb31Sdp[[ ! $FLIST -ef $WDIR/file.list ]] && cp $FLIST $WDIR/file.list
17867c478bd9Sstevel@tonic-gate
1787daaffb31Sdp#
1788daaffb31Sdp#    Bug IDs will be replaced by a URL.  Order of precedence
1789daaffb31Sdp#    is: default location, $WEBREV_BUGURL, the -O flag.
1790daaffb31Sdp#
1791daaffb31SdpBUGURL='http://monaco.sfbay.sun.com/detail.jsp?cr='
1792daaffb31Sdp[[ -n $WEBREV_BUGURL ]] && BUGURL="$WEBREV_BUGURL"
1793daaffb31Sdp[[ -n "$Oflag" ]] && \
1794daaffb31Sdp    BUGURL='http://bugs.opensolaris.org/bugdatabase/view_bug.do?bug_id='
17957c478bd9Sstevel@tonic-gate
1796daaffb31Sdp#
1797daaffb31Sdp#    Likewise, ARC cases will be replaced by a URL.  Order of precedence
1798daaffb31Sdp#    is: default, $WEBREV_SACURL, the -O flag.
1799daaffb31Sdp#
1800daaffb31Sdp#    Note that -O also triggers different substitution behavior for
1801daaffb31Sdp#    SACURL.  See sac2url().
1802daaffb31Sdp#
1803daaffb31SdpSACURL='http://sac.eng.sun.com'
1804daaffb31Sdp[[ -n $WEBREV_SACURL ]] && SACURL="$WEBREV_SACURL"
1805daaffb31Sdp[[ -n $Oflag ]] && \
1806daaffb31Sdp    SACURL='http://www.opensolaris.org/os/community/arc/caselog'
18077c478bd9Sstevel@tonic-gate
1808daaffb31Sdprm -f $WDIR/$WNAME.patch
1809daaffb31Sdprm -f $WDIR/$WNAME.ps
1810daaffb31Sdprm -f $WDIR/$WNAME.pdf
18117c478bd9Sstevel@tonic-gate
1812daaffb31Sdptouch $WDIR/$WNAME.patch
18137c478bd9Sstevel@tonic-gate
1814daaffb31Sdpprint "   Output Files:"
1815daaffb31Sdp
1816daaffb31Sdp#
1817daaffb31Sdp# Clean up the file list: Remove comments, blank lines and env variables.
1818daaffb31Sdp#
1819daaffb31Sdpsed -e "s/#.*$//" -e "/=/d" -e "/^[   ]*$/d" $FLIST > /tmp/$$.flist.clean
1820daaffb31SdpFLIST=/tmp/$$.flist.clean
1821daaffb31Sdp
1822daaffb31Sdp#
1823daaffb31Sdp# First pass through the files: generate the per-file webrev HTML-files.
1824daaffb31Sdp#
1825daaffb31Sdpcat $FLIST | while read LINE
18267c478bd9Sstevel@tonic-gatedo
18277c478bd9Sstevel@tonic-gate	set - $LINE
18287c478bd9Sstevel@tonic-gate	P=$1
18297c478bd9Sstevel@tonic-gate
1830daaffb31Sdp	#
1831daaffb31Sdp	# Normally, each line in the file list is just a pathname of a
1832daaffb31Sdp	# file that has been modified or created in the child.  A file
1833daaffb31Sdp	# that is renamed in the child workspace has two names on the
1834daaffb31Sdp	# line: new name followed by the old name.
1835daaffb31Sdp	#
1836daaffb31Sdp	oldname=""
1837daaffb31Sdp	oldpath=""
1838daaffb31Sdp	rename=
1839daaffb31Sdp	if [[ $# -eq 2 ]]; then
18407c478bd9Sstevel@tonic-gate		PP=$2			# old filename
1841daaffb31Sdp		oldname=" (was $PP)"
1842daaffb31Sdp		oldpath="$PP"
1843daaffb31Sdp		rename=1
18447c478bd9Sstevel@tonic-gate        	PDIR=${PP%/*}
1845daaffb31Sdp        	if [[ $PDIR == $PP ]]; then
18467c478bd9Sstevel@tonic-gate			PDIR="."   # File at root of workspace
18477c478bd9Sstevel@tonic-gate		fi
18487c478bd9Sstevel@tonic-gate
18497c478bd9Sstevel@tonic-gate		PF=${PP##*/}
18507c478bd9Sstevel@tonic-gate
18517c478bd9Sstevel@tonic-gate	        DIR=${P%/*}
1852daaffb31Sdp	        if [[ $DIR == $P ]]; then
18537c478bd9Sstevel@tonic-gate			DIR="."   # File at root of workspace
18547c478bd9Sstevel@tonic-gate		fi
18557c478bd9Sstevel@tonic-gate
18567c478bd9Sstevel@tonic-gate		F=${P##*/}
1857daaffb31Sdp
18587c478bd9Sstevel@tonic-gate        else
18597c478bd9Sstevel@tonic-gate	        DIR=${P%/*}
1860daaffb31Sdp	        if [[ "$DIR" == "$P" ]]; then
18617c478bd9Sstevel@tonic-gate			DIR="."   # File at root of workspace
18627c478bd9Sstevel@tonic-gate		fi
18637c478bd9Sstevel@tonic-gate
18647c478bd9Sstevel@tonic-gate		F=${P##*/}
18657c478bd9Sstevel@tonic-gate
18667c478bd9Sstevel@tonic-gate		PP=$P
18677c478bd9Sstevel@tonic-gate		PDIR=$DIR
18687c478bd9Sstevel@tonic-gate		PF=$F
18697c478bd9Sstevel@tonic-gate	fi
18707c478bd9Sstevel@tonic-gate
1871daaffb31Sdp	COMM=`getcomments html $P $PP`
18727c478bd9Sstevel@tonic-gate
1873daaffb31Sdp	if [[ ! -d $CWS/$DIR ]]; then
1874daaffb31Sdp		print "  $CWS/$DIR: no such directory"
18757c478bd9Sstevel@tonic-gate		continue
18767c478bd9Sstevel@tonic-gate	fi
18777c478bd9Sstevel@tonic-gate
1878daaffb31Sdp	print "\t$P$oldname\n\t\t\c"
18797c478bd9Sstevel@tonic-gate
18807c478bd9Sstevel@tonic-gate	# Make the webrev mirror directory if necessary
18817c478bd9Sstevel@tonic-gate	mkdir -p $WDIR/$DIR
18827c478bd9Sstevel@tonic-gate
18837c478bd9Sstevel@tonic-gate	# cd to the directory so the names are short
18847c478bd9Sstevel@tonic-gate	cd $CWS/$DIR
18857c478bd9Sstevel@tonic-gate
1886daaffb31Sdp	#
1887daaffb31Sdp	# If we're in OpenSolaris mode, we enforce a minor policy:
1888daaffb31Sdp	# help to make sure the reviewer doesn't accidentally publish
1889daaffb31Sdp	# source which is in usr/closed/*
1890daaffb31Sdp	#
1891daaffb31Sdp	if [[ -n $Oflag ]]; then
1892daaffb31Sdp		pclosed=${P##usr/closed/}
1893daaffb31Sdp		if [[ $pclosed != $P ]]; then
1894daaffb31Sdp			print "*** Omitting closed source for OpenSolaris" \
1895daaffb31Sdp			    "mode review"
1896daaffb31Sdp			continue
1897daaffb31Sdp		fi
1898daaffb31Sdp	fi
1899daaffb31Sdp
1900daaffb31Sdp	#
1901daaffb31Sdp	# We stash old and new files into parallel directories in /tmp
1902daaffb31Sdp	# and do our diffs there.  This makes it possible to generate
1903daaffb31Sdp	# clean looking diffs which don't have absolute paths present.
1904daaffb31Sdp	#
1905daaffb31Sdp	olddir=$WDIR/raw_files/old
1906daaffb31Sdp	newdir=$WDIR/raw_files/new
1907daaffb31Sdp	mkdir -p $olddir
1908daaffb31Sdp	mkdir -p $newdir
1909daaffb31Sdp	mkdir -p $olddir/$PDIR
1910daaffb31Sdp	mkdir -p $newdir/$DIR
1911daaffb31Sdp
1912daaffb31Sdp	if [[ $SCM_MODE == "teamware" ]]; then
19137c478bd9Sstevel@tonic-gate		# If the child's version doesn't exist then
19147c478bd9Sstevel@tonic-gate		# get a readonly copy.
19157c478bd9Sstevel@tonic-gate
1916daaffb31Sdp		if [[ ! -f $F && -f SCCS/s.$F ]]; then
19177c478bd9Sstevel@tonic-gate			sccs get -s $F
19187c478bd9Sstevel@tonic-gate		fi
19197c478bd9Sstevel@tonic-gate
1920daaffb31Sdp		#
1921daaffb31Sdp		# Snag new version of file.
1922daaffb31Sdp		#
1923daaffb31Sdp		rm -f $newdir/$DIR/$F
1924daaffb31Sdp		cp $F $newdir/$DIR/$F
19257c478bd9Sstevel@tonic-gate
1926daaffb31Sdp		#
1927daaffb31Sdp		# Get the parent's version of the file. First see whether the
1928daaffb31Sdp		# child's version is checked out and get the parent's version
1929daaffb31Sdp		# with keywords expanded or unexpanded as appropriate.
1930daaffb31Sdp		#
1931daaffb31Sdp		if [ -f $PWS/$PDIR/SCCS/s.$PF -o \
1932daaffb31Sdp		    -f $PWS/$PDIR/SCCS/p.$PF ]; then
1933daaffb31Sdp			rm -f $olddir/$PDIR/$PF
19347c478bd9Sstevel@tonic-gate			if [ -f SCCS/p.$F ]; then
1935daaffb31Sdp				sccs get -s -p -k $PWS/$PDIR/$PF \
1936daaffb31Sdp				    > $olddir/$PDIR/$PF
19377c478bd9Sstevel@tonic-gate			else
1938daaffb31Sdp				sccs get -s -p    $PWS/$PDIR/$PF \
1939daaffb31Sdp				    > $olddir/$PDIR/$PF
19407c478bd9Sstevel@tonic-gate			fi
19417c478bd9Sstevel@tonic-gate		else
1942daaffb31Sdp			if [[ -f $PWS/$PDIR/$PF ]]; then
19437c478bd9Sstevel@tonic-gate				# Parent is not a real workspace, but just a raw
19447c478bd9Sstevel@tonic-gate				# directory tree - use the file that's there as
19457c478bd9Sstevel@tonic-gate				# the old file.
19467c478bd9Sstevel@tonic-gate
1947daaffb31Sdp				rm -f $olddir/$DIR/$F
1948daaffb31Sdp				cp $PWS/$PDIR/$PF $olddir/$DIR/$F
1949daaffb31Sdp			fi
19507c478bd9Sstevel@tonic-gate		fi
19517c478bd9Sstevel@tonic-gate	fi
19527c478bd9Sstevel@tonic-gate
1953daaffb31Sdp	if [[ ! -f $F && ! -f $olddir/$DIR/$F ]]; then
1954daaffb31Sdp		print "*** Error: file not in parent or child"
19557c478bd9Sstevel@tonic-gate		continue
19567c478bd9Sstevel@tonic-gate	fi
19577c478bd9Sstevel@tonic-gate
1958daaffb31Sdp	cd $WDIR/raw_files
1959daaffb31Sdp	ofile=old/$PDIR/$PF
1960daaffb31Sdp	nfile=new/$DIR/$F
19617c478bd9Sstevel@tonic-gate
1962daaffb31Sdp	mv_but_nodiff=
1963daaffb31Sdp	cmp $ofile $nfile > /dev/null 2>&1
1964daaffb31Sdp	if [[ $? == 0 && $rename == 1 ]]; then
1965daaffb31Sdp		mv_but_nodiff=1
1966daaffb31Sdp	fi
1967daaffb31Sdp
1968daaffb31Sdp	#
1969daaffb31Sdp	# If we have old and new versions of the file then run the appropriate
1970daaffb31Sdp	# diffs.  This is complicated by a couple of factors:
1971daaffb31Sdp	#
1972daaffb31Sdp	#	- renames must be handled specially: we emit a 'remove'
1973daaffb31Sdp	#	  diff and an 'add' diff
1974daaffb31Sdp	#	- new files and deleted files must be handled specially
1975daaffb31Sdp	#	- Solaris patch(1m) can't cope with file creation
1976daaffb31Sdp	#	  (and hence renames) as of this writing.
1977daaffb31Sdp	#       - To make matters worse, gnu patch doesn't interpret the
1978daaffb31Sdp	#	  output of Solaris diff properly when it comes to
1979daaffb31Sdp	#	  adds and deletes.  We need to do some "cleansing"
1980daaffb31Sdp	#         transformations:
1981daaffb31Sdp	# 	    [to add a file] @@ -1,0 +X,Y @@  -->  @@ -0,0 +X,Y @@
1982daaffb31Sdp	#	    [to del a file] @@ -X,Y +1,0 @@  -->  @@ -X,Y +0,0 @@
1983daaffb31Sdp	#
1984daaffb31Sdp	cleanse_rmfile="sed 's/^\(@@ [0-9+,-]*\) [0-9+,-]* @@$/\1 +0,0 @@/'"
1985daaffb31Sdp	cleanse_newfile="sed 's/^@@ [0-9+,-]* \([0-9+,-]* @@\)$/@@ -0,0 \1/'"
1986daaffb31Sdp
1987daaffb31Sdp	rm -f $WDIR/$DIR/$F.patch
1988daaffb31Sdp	if [[ -z $rename ]]; then
1989daaffb31Sdp		if [ ! -f $ofile ]; then
1990daaffb31Sdp			diff -u /dev/null $nfile | sh -c "$cleanse_newfile" \
1991daaffb31Sdp			    > $WDIR/$DIR/$F.patch
1992daaffb31Sdp		elif [ ! -f $nfile ]; then
1993daaffb31Sdp			diff -u $ofile /dev/null | sh -c "$cleanse_rmfile" \
1994daaffb31Sdp			    > $WDIR/$DIR/$F.patch
1995daaffb31Sdp		else
1996daaffb31Sdp			diff -u $ofile $nfile > $WDIR/$DIR/$F.patch
1997daaffb31Sdp		fi
1998daaffb31Sdp	else
1999daaffb31Sdp		diff -u $ofile /dev/null | sh -c "$cleanse_rmfile" \
2000daaffb31Sdp		    > $WDIR/$DIR/$F.patch
2001daaffb31Sdp
2002daaffb31Sdp		diff -u /dev/null $nfile | sh -c "$cleanse_newfile" \
2003daaffb31Sdp		    >> $WDIR/$DIR/$F.patch
2004daaffb31Sdp
2005daaffb31Sdp	fi
2006daaffb31Sdp
2007daaffb31Sdp	#
2008daaffb31Sdp	# Tack the patch we just made onto the accumulated patch for the
2009daaffb31Sdp	# whole wad.
2010daaffb31Sdp	#
2011daaffb31Sdp	cat $WDIR/$DIR/$F.patch >> $WDIR/$WNAME.patch
2012daaffb31Sdp
2013daaffb31Sdp	print " patch\c"
2014daaffb31Sdp
2015daaffb31Sdp	if [[ -f $ofile && -f $nfile && -z $mv_but_nodiff ]]; then
2016daaffb31Sdp
2017daaffb31Sdp		${CDIFFCMD:-diff -bt -C 5} $ofile $nfile > $WDIR/$DIR/$F.cdiff
2018daaffb31Sdp		diff_to_html $F $DIR/$F "C" "$COMM" < $WDIR/$DIR/$F.cdiff \
2019daaffb31Sdp		    > $WDIR/$DIR/$F.cdiff.html
20207c478bd9Sstevel@tonic-gate		print " cdiffs\c"
20217c478bd9Sstevel@tonic-gate
2022daaffb31Sdp		${UDIFFCMD:-diff -bt -U 5} $ofile $nfile > $WDIR/$DIR/$F.udiff
2023daaffb31Sdp		diff_to_html $F $DIR/$F "U" "$COMM" < $WDIR/$DIR/$F.udiff \
2024daaffb31Sdp		    > $WDIR/$DIR/$F.udiff.html
2025daaffb31Sdp
20267c478bd9Sstevel@tonic-gate		print " udiffs\c"
20277c478bd9Sstevel@tonic-gate
20287c478bd9Sstevel@tonic-gate		if [[ -x $WDIFF ]]; then
2029daaffb31Sdp			$WDIFF -c "$COMM" \
2030daaffb31Sdp			    -t "$WNAME Wdiff $DIR/$F" $ofile $nfile > \
2031daaffb31Sdp			    $WDIR/$DIR/$F.wdiff.html 2>/dev/null
2032daaffb31Sdp			if [[ $? -eq 0 ]]; then
20337c478bd9Sstevel@tonic-gate				print " wdiffs\c"
2034daaffb31Sdp			else
2035daaffb31Sdp				print " wdiffs[fail]\c"
2036daaffb31Sdp			fi
20377c478bd9Sstevel@tonic-gate		fi
20387c478bd9Sstevel@tonic-gate
2039daaffb31Sdp		sdiff_to_html $ofile $nfile $F $DIR "$COMM" \
2040daaffb31Sdp		    > $WDIR/$DIR/$F.sdiff.html
20417c478bd9Sstevel@tonic-gate		print " sdiffs\c"
20427c478bd9Sstevel@tonic-gate
20437c478bd9Sstevel@tonic-gate		print " frames\c"
20447c478bd9Sstevel@tonic-gate
20457c478bd9Sstevel@tonic-gate		rm -f $WDIR/$DIR/$F.cdiff $WDIR/$DIR/$F.udiff
20467c478bd9Sstevel@tonic-gate
2047daaffb31Sdp		difflines $ofile $nfile > $WDIR/$DIR/$F.count
2048daaffb31Sdp
2049daaffb31Sdp	elif [[ -f $ofile && -f $nfile && -n $mv_but_nodiff ]]; then
2050daaffb31Sdp		# renamed file: may also have differences
2051daaffb31Sdp		difflines $ofile $nfile > $WDIR/$DIR/$F.count
2052daaffb31Sdp	elif [[ -f $nfile ]]; then
20537c478bd9Sstevel@tonic-gate		# new file: count added lines
2054daaffb31Sdp		difflines /dev/null $nfile > $WDIR/$DIR/$F.count
2055daaffb31Sdp	elif [[ -f $ofile ]]; then
20567c478bd9Sstevel@tonic-gate		# old file: count deleted lines
2057daaffb31Sdp		difflines $ofile /dev/null > $WDIR/$DIR/$F.count
20587c478bd9Sstevel@tonic-gate	fi
20597c478bd9Sstevel@tonic-gate
2060daaffb31Sdp	#
2061daaffb31Sdp	# Now we generate the postscript for this file.  We generate diffs
2062daaffb31Sdp	# only in the event that there is delta, or the file is new (it seems
2063daaffb31Sdp	# tree-killing to print out the contents of deleted files).
2064daaffb31Sdp	#
2065daaffb31Sdp	if [[ -f $nfile ]]; then
2066daaffb31Sdp		ocr=$ofile
2067daaffb31Sdp		[[ ! -f $ofile ]] && ocr=/dev/null
2068daaffb31Sdp
2069daaffb31Sdp		if [[ -z $mv_but_nodiff ]]; then
2070daaffb31Sdp			textcomm=`getcomments text $P $PP`
2071*14983201Sdp			if [[ -x $CODEREVIEW ]]; then
2072*14983201Sdp				$CODEREVIEW -y "$textcomm" \
2073*14983201Sdp				    -e $ocr $nfile \
2074*14983201Sdp				    > /tmp/$$.psfile 2>/dev/null &&
2075*14983201Sdp				    cat /tmp/$$.psfile >> $WDIR/$WNAME.ps
2076daaffb31Sdp				if [[ $? -eq 0 ]]; then
2077daaffb31Sdp					print " ps\c"
2078daaffb31Sdp				else
2079daaffb31Sdp					print " ps[fail]\c"
2080daaffb31Sdp				fi
2081daaffb31Sdp			fi
2082daaffb31Sdp		fi
2083*14983201Sdp	fi
2084daaffb31Sdp
2085daaffb31Sdp	if [[ -f $ofile && -z $mv_but_nodiff ]]; then
2086daaffb31Sdp		source_to_html Old $P < $ofile > $WDIR/$DIR/$F-.html
20877c478bd9Sstevel@tonic-gate		print " old\c"
20887c478bd9Sstevel@tonic-gate	fi
20897c478bd9Sstevel@tonic-gate
2090daaffb31Sdp	if [[ -f $nfile ]]; then
2091daaffb31Sdp		source_to_html New $P < $nfile > $WDIR/$DIR/$F.html
20927c478bd9Sstevel@tonic-gate		print " new\c"
20937c478bd9Sstevel@tonic-gate	fi
20947c478bd9Sstevel@tonic-gate
2095daaffb31Sdp	print
20967c478bd9Sstevel@tonic-gatedone
20977c478bd9Sstevel@tonic-gate
2098daaffb31Sdpframe_nav_js > $WDIR/ancnav.js
20997c478bd9Sstevel@tonic-gateframe_navigation > $WDIR/ancnav.html
2100daaffb31Sdp
2101*14983201Sdpif [[ ! -f $WDIR/$WNAME.ps ]]; then
2102*14983201Sdp	print " Generating PDF: Skipped: no output available"
2103*14983201Sdpelif [[ -x $CODEREVIEW && -x $PS2PDF ]]; then
2104*14983201Sdp	print " Generating PDF: \c"
2105*14983201Sdp	fix_postscript $WDIR/$WNAME.ps | $PS2PDF - > $WDIR/$WNAME.pdf
2106daaffb31Sdp	rm -f $WDIR/$WNAME.ps
2107daaffb31Sdp	print "Done."
2108*14983201Sdpelse
2109*14983201Sdp	print " Generating PDF: Skipped: missing 'ps2pdf' or 'codereview'"
2110*14983201Sdpfi
21117c478bd9Sstevel@tonic-gate
21127c478bd9Sstevel@tonic-gate# Now build the index.html file that contains
21137c478bd9Sstevel@tonic-gate# links to the source files and their diffs.
21147c478bd9Sstevel@tonic-gate
21157c478bd9Sstevel@tonic-gatecd $CWS
21167c478bd9Sstevel@tonic-gate
21177c478bd9Sstevel@tonic-gate# Save total changed lines for Code Inspection.
2118daaffb31Sdpprint "$TOTL" > $WDIR/TotalChangedLines
21197c478bd9Sstevel@tonic-gate
2120daaffb31Sdpprint "     index.html: \c"
21217c478bd9Sstevel@tonic-gateINDEXFILE=$WDIR/index.html
21227c478bd9Sstevel@tonic-gateexec 3<&1			# duplicate stdout to FD3.
21237c478bd9Sstevel@tonic-gateexec 1<&-			# Close stdout.
21247c478bd9Sstevel@tonic-gateexec > $INDEXFILE		# Open stdout to index file.
21257c478bd9Sstevel@tonic-gate
2126daaffb31Sdpprint "$HTML<head>$STDHEAD"
2127daaffb31Sdpprint "<title>$WNAME</title>"
2128daaffb31Sdpprint "</head>"
2129daaffb31Sdpprint "<body id=\"SUNWwebrev\">"
2130daaffb31Sdpprint "<div class=\"summary\">"
2131daaffb31Sdpprint "<h2>Code Review for $WNAME</h2>"
21327c478bd9Sstevel@tonic-gate
2133daaffb31Sdpprint "<table>"
21347c478bd9Sstevel@tonic-gate
2135daaffb31Sdp#
2136daaffb31Sdp# Figure out the username and gcos name.  To maintain compatibility
2137daaffb31Sdp# with passwd(4), we must support '&' substitutions.
2138daaffb31Sdp#
2139daaffb31Sdpusername=`id | cut -d '(' -f 2 | cut -d ')' -f 1`
2140daaffb31Sdprealname=`getent passwd $username | cut -d':' -f 5`
2141*14983201Sdpuserupper=`$PERL -e "print ucfirst $username"`
2142daaffb31Sdprealname=`print $realname | sed s/\&/$userupper/`
2143daaffb31Sdpdate="on `date`"
21447c478bd9Sstevel@tonic-gate
2145daaffb31Sdpif [[ -n "$username" && -n "$realname" ]]; then
2146daaffb31Sdp	print "<tr><th>Prepared by:</th>"
2147daaffb31Sdp	print "<td>$realname ($username) $date</td></tr>"
2148daaffb31Sdpelif [[ -n "$username" ]]; then
2149daaffb31Sdp	print "<tr><th>Prepared by:</th><td>$username $date</td></tr>"
2150daaffb31Sdpfi
2151daaffb31Sdp
2152daaffb31Sdpprint "<tr><th>Workspace:</th><td>$CWS</td></tr>"
2153daaffb31Sdpprint "<tr><th>Compare against:</th><td>"
2154daaffb31Sdpif [[ -n $parent_webrev ]]; then
2155daaffb31Sdp	print "webrev at $parent_webrev"
2156daaffb31Sdpelse
2157daaffb31Sdp	print "$PWS"
2158daaffb31Sdpfi
2159daaffb31Sdpprint "</td></tr>"
2160daaffb31Sdpprint "<tr><th>Summary of changes:</th><td>"
2161daaffb31SdpprintCI $TOTL $TINS $TDEL $TMOD $TUNC
2162daaffb31Sdpprint "</td></tr>"
2163daaffb31Sdp
2164daaffb31Sdpif [[ -f $WDIR/$WNAME.patch ]]; then
2165daaffb31Sdp	print "<tr><th>Patch of changes:</th><td>"
2166daaffb31Sdp	print "<a href=\"$WNAME.patch\">$WNAME.patch</a></td></tr>"
2167daaffb31Sdpfi
2168daaffb31Sdpif [[ -f $WDIR/$WNAME.pdf ]]; then
2169daaffb31Sdp	print "<tr><th>Printable review:</th><td>"
2170daaffb31Sdp	print "<a href=\"$WNAME.pdf\">$WNAME.pdf</a></td></tr>"
2171daaffb31Sdpfi
2172daaffb31Sdp
2173daaffb31Sdpif [[ -n "$iflag" ]]; then
2174daaffb31Sdp	print "<tr><th>Author comments:</th><td><div>"
2175daaffb31Sdp	cat /tmp/$$.include
2176daaffb31Sdp	print "</div></td></tr>"
2177daaffb31Sdpfi
2178daaffb31Sdpprint "</table>"
2179daaffb31Sdpprint "</div>"
2180daaffb31Sdp
2181daaffb31Sdp
2182daaffb31Sdp#
2183daaffb31Sdp# Second pass through the files: generate the rest of the index file
2184daaffb31Sdp#
2185daaffb31Sdpcat $FLIST | while read LINE
21867c478bd9Sstevel@tonic-gatedo
21877c478bd9Sstevel@tonic-gate	set - $LINE
21887c478bd9Sstevel@tonic-gate	P=$1
21897c478bd9Sstevel@tonic-gate
2190daaffb31Sdp	if [[ $# == 2 ]]; then
21917c478bd9Sstevel@tonic-gate		PP=$2
2192daaffb31Sdp		oldname=" <i>(was $PP)</i>"
2193daaffb31Sdp
21947c478bd9Sstevel@tonic-gate	else
21957c478bd9Sstevel@tonic-gate		PP=$P
2196daaffb31Sdp		oldname=""
2197daaffb31Sdp	fi
2198daaffb31Sdp
2199daaffb31Sdp	DIR=${P%/*}
2200daaffb31Sdp	if [[ $DIR == $P ]]; then
2201daaffb31Sdp		DIR="."   # File at root of workspace
22027c478bd9Sstevel@tonic-gate	fi
22037c478bd9Sstevel@tonic-gate
22047c478bd9Sstevel@tonic-gate	# Avoid processing the same file twice.
22057c478bd9Sstevel@tonic-gate	# It's possible for renamed files to
22067c478bd9Sstevel@tonic-gate	# appear twice in the file list
22077c478bd9Sstevel@tonic-gate
22087c478bd9Sstevel@tonic-gate	F=$WDIR/$P
22097c478bd9Sstevel@tonic-gate
2210daaffb31Sdp	print "<p>"
22117c478bd9Sstevel@tonic-gate
22127c478bd9Sstevel@tonic-gate	# If there's a diffs file, make diffs links
22137c478bd9Sstevel@tonic-gate
2214daaffb31Sdp	if [[ -f $F.cdiff.html ]]; then
2215daaffb31Sdp		print "<a href=\"$P.cdiff.html\">Cdiffs</a>"
2216daaffb31Sdp		print "<a href=\"$P.udiff.html\">Udiffs</a>"
22177c478bd9Sstevel@tonic-gate
2218daaffb31Sdp		if [[ -f $F.wdiff.html && -x $WDIFF ]]; then
2219daaffb31Sdp			print "<a href=\"$P.wdiff.html\">Wdiffs</a>"
22207c478bd9Sstevel@tonic-gate		fi
22217c478bd9Sstevel@tonic-gate
2222daaffb31Sdp		print "<a href=\"$P.sdiff.html\">Sdiffs</a>"
22237c478bd9Sstevel@tonic-gate
22247c478bd9Sstevel@tonic-gate		print "<a href=\"$P.frames.html\">Frames</a>"
22257c478bd9Sstevel@tonic-gate	else
2226daaffb31Sdp		print " ------ ------ ------"
22277c478bd9Sstevel@tonic-gate
2228daaffb31Sdp		if [[ -x $WDIFF ]]; then
22297c478bd9Sstevel@tonic-gate			print " ------"
22307c478bd9Sstevel@tonic-gate		fi
2231daaffb31Sdp
2232daaffb31Sdp		print " ------"
22337c478bd9Sstevel@tonic-gate	fi
22347c478bd9Sstevel@tonic-gate
22357c478bd9Sstevel@tonic-gate	# If there's an old file, make the link
22367c478bd9Sstevel@tonic-gate
2237daaffb31Sdp	if [[ -f $F-.html ]]; then
2238daaffb31Sdp		print "<a href=\"$P-.html\">Old</a>"
22397c478bd9Sstevel@tonic-gate	else
2240daaffb31Sdp		print " ---"
22417c478bd9Sstevel@tonic-gate	fi
22427c478bd9Sstevel@tonic-gate
22437c478bd9Sstevel@tonic-gate	# If there's an new file, make the link
22447c478bd9Sstevel@tonic-gate
2245daaffb31Sdp	if [[ -f $F.html ]]; then
2246daaffb31Sdp		print "<a href=\"$P.html\">New</a>"
22477c478bd9Sstevel@tonic-gate	else
2248daaffb31Sdp		print " ---"
22497c478bd9Sstevel@tonic-gate	fi
22507c478bd9Sstevel@tonic-gate
2251daaffb31Sdp	if [[ -f $F.patch ]]; then
2252daaffb31Sdp		print "<a href=\"$P.patch\">Patch</a>"
2253daaffb31Sdp	else
2254daaffb31Sdp		print " -----"
2255daaffb31Sdp	fi
2256daaffb31Sdp
2257daaffb31Sdp	if [[ -f $WDIR/raw_files/new/$P ]]; then
2258daaffb31Sdp		print "<a href=\"raw_files/new/$P\">Raw</a>"
2259daaffb31Sdp	else
2260daaffb31Sdp		print " ---"
2261daaffb31Sdp	fi
2262daaffb31Sdp
2263daaffb31Sdp	print "<b>$P</b> $oldname"
2264daaffb31Sdp
2265daaffb31Sdp	#
2266daaffb31Sdp	# Check for usr/closed
2267daaffb31Sdp	#
2268daaffb31Sdp	if [ ! -z "$Oflag" ]; then
2269daaffb31Sdp		if [[ $P == usr/closed/* ]]; then
2270daaffb31Sdp			print "&nbsp;&nbsp;<i>Closed source: omitted from" \
2271daaffb31Sdp			    "this review</i>"
2272daaffb31Sdp		fi
2273daaffb31Sdp	fi
2274daaffb31Sdp
2275daaffb31Sdp	print "</p>"
22767c478bd9Sstevel@tonic-gate	# Insert delta comments
22777c478bd9Sstevel@tonic-gate
2278daaffb31Sdp	print "<blockquote><pre>"
2279daaffb31Sdp	getcomments html $P $PP
2280daaffb31Sdp	print "</pre>"
22817c478bd9Sstevel@tonic-gate
22827c478bd9Sstevel@tonic-gate	# Add additional comments comment
22837c478bd9Sstevel@tonic-gate
2284daaffb31Sdp	print "<!-- Add comments to explain changes in $P here -->"
22857c478bd9Sstevel@tonic-gate
22867c478bd9Sstevel@tonic-gate	# Add count of changes.
22877c478bd9Sstevel@tonic-gate
2288daaffb31Sdp	if [[ -f $F.count ]]; then
22897c478bd9Sstevel@tonic-gate	    cat $F.count
22907c478bd9Sstevel@tonic-gate	    rm $F.count
22917c478bd9Sstevel@tonic-gate	fi
2292daaffb31Sdp	print "</blockquote>"
22937c478bd9Sstevel@tonic-gatedone
22947c478bd9Sstevel@tonic-gate
2295daaffb31Sdpprint
2296daaffb31Sdpprint
2297daaffb31Sdpprint "<hr />"
2298daaffb31Sdpprint "<p style=\"font-size: small\">"
2299daaffb31Sdpprint "This code review page was prepared using <b>$0</b>"
2300daaffb31Sdpprint "(vers $WEBREV_UPDATED)."
2301daaffb31Sdpprint "Webrev is maintained by the <a href=\"http://www.opensolaris.org\">"
2302daaffb31Sdpprint "OpenSolaris</a> project.  The latest version may be obtained"
2303*14983201Sdpprint "<a href=\"http://src.opensolaris.org/source/xref/on/usr/src/tools/scripts/webrev.sh\">here</a>.</p>"
2304daaffb31Sdpprint "</body>"
2305daaffb31Sdpprint "</html>"
23067c478bd9Sstevel@tonic-gate
23077c478bd9Sstevel@tonic-gateexec 1<&-			# Close FD 1.
23087c478bd9Sstevel@tonic-gateexec 1<&3			# dup FD 3 to restore stdout.
23097c478bd9Sstevel@tonic-gateexec 3<&-			# close FD 3.
23107c478bd9Sstevel@tonic-gate
2311daaffb31Sdpprint "Done."
2312