xref: /titanic_52/usr/src/tools/scripts/webrev.sh (revision daaffb314aae330855b7faea7a653244767ed744)
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
6*daaffb31Sdp# Common Development and Distribution License (the "License").
7*daaffb31Sdp# You may not use this file except in compliance with the License.
87c478bd9Sstevel@tonic-gate#
97c478bd9Sstevel@tonic-gate# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate# or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate# See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate# and limitations under the License.
137c478bd9Sstevel@tonic-gate#
147c478bd9Sstevel@tonic-gate# When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate# If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate# fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate# information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate#
207c478bd9Sstevel@tonic-gate# CDDL HEADER END
217c478bd9Sstevel@tonic-gate#
227c478bd9Sstevel@tonic-gate#
237c478bd9Sstevel@tonic-gate# ident	"%Z%%M%	%I%	%E% SMI"
247c478bd9Sstevel@tonic-gate#
25*daaffb31Sdp# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
267c478bd9Sstevel@tonic-gate# Use is subject to license terms.
277c478bd9Sstevel@tonic-gate#
28*daaffb31Sdp# This script takes a file list and a workspace and builds a set of html files
29*daaffb31Sdp# suitable for doing a code review of source changes via a web page.
30*daaffb31Sdp# Documentation is available via the manual page, webrev.1, or just
31*daaffb31Sdp# type 'webrev -h'.
327c478bd9Sstevel@tonic-gate#
33*daaffb31Sdp# Acknowledgements to contributors to webrev are listed in the webrev(1)
34*daaffb31Sdp# man page.
357c478bd9Sstevel@tonic-gate#
36*daaffb31Sdp
377c478bd9Sstevel@tonic-gate#
38*daaffb31Sdp# 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
48*daaffb31SdpHTML='<?xml version="1.0"?>
49*daaffb31Sdp<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
50*daaffb31Sdp    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
51*daaffb31Sdp<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">\n'
52*daaffb31Sdp
53*daaffb31SdpFRAMEHTML='<?xml version="1.0"?>
54*daaffb31Sdp<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"
55*daaffb31Sdp    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
56*daaffb31Sdp<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">\n'
57*daaffb31Sdp
58*daaffb31SdpSTDHEAD='<meta http-equiv="cache-control" content="no-cache" />
59*daaffb31Sdp<meta http-equiv="Pragma" content="no-cache" />
60*daaffb31Sdp<meta http-equiv="Expires" content="-1" />
61*daaffb31Sdp<!--
62*daaffb31Sdp   Note to customizers: the body of the webrev is IDed as SUNWwebrev
63*daaffb31Sdp   to allow easy overriding by users of webrev via the userContent.css
64*daaffb31Sdp   mechanism available in some browsers.
65*daaffb31Sdp
66*daaffb31Sdp   For example, to have all "removed" information be red instead of
67*daaffb31Sdp   brown, set a rule in your userContent.css file like:
68*daaffb31Sdp
69*daaffb31Sdp       body#SUNWwebrev span.removed { color: red ! important; }
70*daaffb31Sdp-->
71*daaffb31Sdp<style type="text/css" media="screen">
72*daaffb31Sdpbody {
73*daaffb31Sdp    background-color: #eeeeee;
74*daaffb31Sdp}
75*daaffb31Sdphr {
76*daaffb31Sdp    border: none 0;
77*daaffb31Sdp    border-top: 1px solid #aaa;
78*daaffb31Sdp    height: 1px;
79*daaffb31Sdp}
80*daaffb31Sdpdiv.summary {
81*daaffb31Sdp    font-size: .8em;
82*daaffb31Sdp    border-bottom: 1px solid #aaa;
83*daaffb31Sdp    padding-left: 1em;
84*daaffb31Sdp    padding-right: 1em;
85*daaffb31Sdp}
86*daaffb31Sdpdiv.summary h2 {
87*daaffb31Sdp    margin-bottom: 0.3em;
88*daaffb31Sdp}
89*daaffb31Sdpdiv.summary table th {
90*daaffb31Sdp    text-align: right;
91*daaffb31Sdp    vertical-align: top;
92*daaffb31Sdp    white-space: nowrap;
93*daaffb31Sdp}
94*daaffb31Sdpspan.lineschanged {
95*daaffb31Sdp    font-size: 0.7em;
96*daaffb31Sdp}
97*daaffb31Sdpspan.oldmarker {
98*daaffb31Sdp    color: red;
99*daaffb31Sdp    font-size: large;
100*daaffb31Sdp    font-weight: bold;
101*daaffb31Sdp}
102*daaffb31Sdpspan.newmarker {
103*daaffb31Sdp    color: green;
104*daaffb31Sdp    font-size: large;
105*daaffb31Sdp    font-weight: bold;
106*daaffb31Sdp}
107*daaffb31Sdpspan.removed {
108*daaffb31Sdp    color: brown;
109*daaffb31Sdp}
110*daaffb31Sdpspan.changed {
111*daaffb31Sdp    color: blue;
112*daaffb31Sdp}
113*daaffb31Sdpspan.new {
114*daaffb31Sdp    color: blue;
115*daaffb31Sdp    font-weight: bold;
116*daaffb31Sdp}
117*daaffb31Sdpa.print { font-size: x-small; }
118*daaffb31Sdpa:hover { background-color: #ffcc99; }
119*daaffb31Sdp</style>
120*daaffb31Sdp
121*daaffb31Sdp<style type="text/css" media="print">
122*daaffb31Sdppre { font-size: 0.8em; font-family: courier, monospace; }
123*daaffb31Sdpspan.removed { color: #444; font-style: italic }
124*daaffb31Sdpspan.changed { font-weight: bold; }
125*daaffb31Sdpspan.new { font-weight: bold; }
126*daaffb31Sdpspan.newmarker { font-size: 1.2em; font-weight: bold; }
127*daaffb31Sdpspan.oldmarker { font-size: 1.2em; font-weight: bold; }
128*daaffb31Sdpa.print {display: none}
129*daaffb31Sdphr { border: none 0; border-top: 1px solid #aaa; height: 1px; }
130*daaffb31Sdp</style>
131*daaffb31Sdp'
132*daaffb31Sdp
133*daaffb31Sdp#
134*daaffb31Sdp# UDiffs need a slightly different CSS rule for 'new' items (we don't
135*daaffb31Sdp# want them to be bolded as we do in cdiffs or sdiffs).
136*daaffb31Sdp#
137*daaffb31SdpUDIFFCSS='
138*daaffb31Sdp<style type="text/css" media="screen">
139*daaffb31Sdpspan.new {
140*daaffb31Sdp    color: blue;
141*daaffb31Sdp    font-weight: normal;
142*daaffb31Sdp}
143*daaffb31Sdp</style>
144*daaffb31Sdp'
145*daaffb31Sdp
146*daaffb31Sdp#
147*daaffb31Sdp# input_cmd | html_quote | output_cmd
148*daaffb31Sdp# or
149*daaffb31Sdp# 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
158*daaffb31Sdp#
159*daaffb31Sdp# input_cmd | bug2url | output_cmd
160*daaffb31Sdp#
161*daaffb31Sdp# Scan for bugids and insert <a> links to the relevent bug database.
162*daaffb31Sdp#
163*daaffb31Sdpbug2url()
1647c478bd9Sstevel@tonic-gate{
165*daaffb31Sdp	sed -e 's|[0-9]\{5,\}|<a href=\"'$BUGURL'&\">&</a>|g'
166*daaffb31Sdp}
167*daaffb31Sdp
1687c478bd9Sstevel@tonic-gate#
169*daaffb31Sdp# input_cmd | sac2url | output_cmd
1707c478bd9Sstevel@tonic-gate#
171*daaffb31Sdp# Scan for ARC cases and insert <a> links to the relevent SAC database.
172*daaffb31Sdp# This is slightly complicated because inside the SWAN, SAC cases are
173*daaffb31Sdp# grouped by ARC: PSARC/2006/123.  But on OpenSolaris.org, they are
174*daaffb31Sdp# referenced as 2006/123 (without labelling the ARC).
1757c478bd9Sstevel@tonic-gate#
176*daaffb31Sdpsac2url()
177*daaffb31Sdp{
178*daaffb31Sdp	if [[ -z $Oflag ]]; then
179*daaffb31Sdp	    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'
180*daaffb31Sdp	else
181*daaffb31Sdp	    sed -e 's|\([A-Z]\{1,2\}ARC\)[ /]\([0-9]\{4\}\)/\([0-9]\{3\}\)|<a href=\"'$SACURL'/\2/\3\">\1 \2/\3</a>|g'
182*daaffb31Sdp	fi
183*daaffb31Sdp}
184*daaffb31Sdp
1857c478bd9Sstevel@tonic-gate#
186*daaffb31Sdp# strip_unchanged <infile> | output_cmd
1877c478bd9Sstevel@tonic-gate#
188*daaffb31Sdp# Removes chunks of sdiff documents that have not changed. This makes it
189*daaffb31Sdp# easier for a code reviewer to find the bits that have changed.
1907c478bd9Sstevel@tonic-gate#
191*daaffb31Sdp# Deleted lines of text are replaced by a horizontal rule. Some
192*daaffb31Sdp# identical lines are retained before and after the changed lines to
193*daaffb31Sdp# provide some context.  The number of these lines is controlled by the
194*daaffb31Sdp# variable C in the nawk script below.
195*daaffb31Sdp#
196*daaffb31Sdp# The script detects changed lines as any line that has a "<span class="
197*daaffb31Sdp# string embedded (unchanged lines have no particular class and are not
198*daaffb31Sdp# part of a <span>).  Blank lines (without a sequence number) are also
199*daaffb31Sdp# detected since they flag lines that have been inserted or deleted.
200*daaffb31Sdp#
201*daaffb31Sdpstrip_unchanged()
202*daaffb31Sdp{
203*daaffb31Sdp	nawk '
204*daaffb31Sdp	BEGIN	{ C = c = 20 }
205*daaffb31Sdp	NF == 0 || /span class=/ {
206*daaffb31Sdp		if (c > C) {
207*daaffb31Sdp			c -= C
208*daaffb31Sdp			inx = 0
209*daaffb31Sdp			if (c > C) {
210*daaffb31Sdp				print "\n</pre><hr /><pre>"
211*daaffb31Sdp				inx = c % C
212*daaffb31Sdp				c = C
213*daaffb31Sdp			}
214*daaffb31Sdp
215*daaffb31Sdp			for (i = 0; i < c; i++)
216*daaffb31Sdp				print ln[(inx + i) % C]
217*daaffb31Sdp		}
218*daaffb31Sdp		c = 0;
219*daaffb31Sdp		print
220*daaffb31Sdp		next
221*daaffb31Sdp	}
222*daaffb31Sdp	{	if (c >= C) {
223*daaffb31Sdp			ln[c % C] = $0
224*daaffb31Sdp			c++;
225*daaffb31Sdp			next;
226*daaffb31Sdp		}
227*daaffb31Sdp		c++;
228*daaffb31Sdp		print
229*daaffb31Sdp	}
230*daaffb31Sdp	END	{ if (c > (C * 2)) print "\n</pre><hr />" }
231*daaffb31Sdp
232*daaffb31Sdp	' $1
233*daaffb31Sdp}
234*daaffb31Sdp
235*daaffb31Sdp#
236*daaffb31Sdp# sdiff_to_html
237*daaffb31Sdp#
238*daaffb31Sdp# This function takes two files as arguments, obtains their diff, and
239*daaffb31Sdp# processes the diff output to present the files as an HTML document with
240*daaffb31Sdp# the files displayed side-by-side, differences shown in color.  It also
241*daaffb31Sdp# takes a delta comment, rendered as an HTML snippet, as the third
242*daaffb31Sdp# argument.  The function takes two files as arguments, then the name of
243*daaffb31Sdp# file, the path, and the comment.  The HTML will be delivered on stdout,
244*daaffb31Sdp# e.g.
245*daaffb31Sdp#
246*daaffb31Sdp#   $ sdiff_to_html old/usr/src/tools/scripts/webrev.sh \
247*daaffb31Sdp#         new/usr/src/tools/scripts/webrev.sh \
248*daaffb31Sdp#         webrev.sh usr/src/tools/scripts \
249*daaffb31Sdp#         '<a href="http://monaco.sfbay.sun.com/detail.jsp?cr=1234567">
250*daaffb31Sdp#          1234567</a> my bugid' > <file>.html
251*daaffb31Sdp#
252*daaffb31Sdp# framed_sdiff() is then called which creates $2.frames.html
253*daaffb31Sdp# in the webrev tree.
254*daaffb31Sdp#
255*daaffb31Sdp# FYI: This function is rather unusual in its use of awk.  The initial
256*daaffb31Sdp# diff run produces conventional diff output showing changed lines mixed
257*daaffb31Sdp# with editing codes.  The changed lines are ignored - we're interested in
258*daaffb31Sdp# 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#
267*daaffb31Sdp#  These editing codes are parsed by the awk script and used to generate
268*daaffb31Sdp#  another awk script that generates HTML, e.g the above lines would turn
269*daaffb31Sdp#  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"}
273*daaffb31Sdp#      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#
280*daaffb31Sdp#  This script is then run on the original source file to generate the
281*daaffb31Sdp#  HTML that corresponds to the source file.
2827c478bd9Sstevel@tonic-gate#
283*daaffb31Sdp#  The two HTML files are then combined into a single piece of HTML that
284*daaffb31Sdp#  uses an HTML table construct to present the files side by side.  You'll
285*daaffb31Sdp#  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#
292*daaffb31Sdp#  Blank lines are inserted in each file to keep unchanged lines in sync
293*daaffb31Sdp#  (side-by-side).  This format is familiar to users of sdiff(1) or
294*daaffb31Sdp#  Teamware's filemerge tool.
295*daaffb31Sdp#
296*daaffb31Sdpsdiff_to_html()
297*daaffb31Sdp{
2987c478bd9Sstevel@tonic-gate	diff -b $1 $2 > /tmp/$$.diffs
2997c478bd9Sstevel@tonic-gate
300*daaffb31Sdp	TNAME=$3
301*daaffb31Sdp	TPATH=$4
302*daaffb31Sdp	COMMENT=$5
303*daaffb31Sdp
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"
310*daaffb31Sdp		printf "function removed() "
311*daaffb31Sdp		printf "{printf \"<span class=\\\"removed\\\">%%4d %%s</span>\\n\", NR, $0}\n"
312*daaffb31Sdp		printf "function changed() "
313*daaffb31Sdp		printf "{printf \"<span class=\\\"changed\\\">%%4d %%s</span>\\n\", NR, $0}\n"
314*daaffb31Sdp		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}
319*daaffb31Sdp
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)
350*daaffb31Sdp			printf "NR==%s\t\t{removed(); next}\n" , n1
3517c478bd9Sstevel@tonic-gate		else
352*daaffb31Sdp			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)
362*daaffb31Sdp			printf "NR==%s\t\t{changed();" , n1
3637c478bd9Sstevel@tonic-gate		else {
3647c478bd9Sstevel@tonic-gate			d1 = n2 - n1
365*daaffb31Sdp			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
383*daaffb31Sdp	END	{ printf "{printf \"%%4d %%s\\n\", NR, $0 }\n" }
384*daaffb31Sdp	' /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"
392*daaffb31Sdp		printf "function new() "
393*daaffb31Sdp		printf "{printf \"<span class=\\\"new\\\">%%4d %%s</span>\\n\", NR, $0}\n"
394*daaffb31Sdp		printf "function changed() "
395*daaffb31Sdp		printf "{printf \"<span class=\\\"changed\\\">%%4d %%s</span>\\n\", NR, $0}\n"
396*daaffb31Sdp		printf "function bl() {printf \"%%4d %%s\\n\", NR, $0}\n"
3977c478bd9Sstevel@tonic-gate	}
398*daaffb31Sdp
3997c478bd9Sstevel@tonic-gate	/^</	{next}
4007c478bd9Sstevel@tonic-gate	/^>/	{next}
4017c478bd9Sstevel@tonic-gate	/^---/	{next}
402*daaffb31Sdp
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)
433*daaffb31Sdp			printf "NR==%s\t\t{new() ; next}\n" , n1
4347c478bd9Sstevel@tonic-gate		else
435*daaffb31Sdp			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
446*daaffb31Sdp			printf "NR==%s\t\t{changed();" , n1
4477c478bd9Sstevel@tonic-gate		} else {
4487c478bd9Sstevel@tonic-gate			d2 = n2 - n1
449*daaffb31Sdp			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	}
465*daaffb31Sdp	END	{ printf "{printf \"%%4d %%s\\n\", NR, $0 }\n" }
4667c478bd9Sstevel@tonic-gate	' /tmp/$$.diffs > /tmp/$$.file2
4677c478bd9Sstevel@tonic-gate
468*daaffb31Sdp	#
469*daaffb31Sdp	# Post-process the HTML files by running them back through nawk
470*daaffb31Sdp	#
471*daaffb31Sdp	html_quote < $1 | nawk -f /tmp/$$.file1 > /tmp/$$.file1.html
4727c478bd9Sstevel@tonic-gate
473*daaffb31Sdp	html_quote < $2 | nawk -f /tmp/$$.file2 > /tmp/$$.file2.html
4747c478bd9Sstevel@tonic-gate
475*daaffb31Sdp	#
476*daaffb31Sdp	# Now combine into a valid HTML file and side-by-side into a table
477*daaffb31Sdp	#
478*daaffb31Sdp	print "$HTML<head>$STDHEAD"
479*daaffb31Sdp	print "<title>$WNAME Sdiff $TPATH </title>"
480*daaffb31Sdp	print "</head><body id=\"SUNWwebrev\">"
481*daaffb31Sdp        print "<a class=\"print\" href=\"javascript:print()\">Print this page</a>"
482*daaffb31Sdp	print "<pre>$COMMENT</pre>\n"
483*daaffb31Sdp	print "<table><tr valign=\"top\">"
484*daaffb31Sdp	print "<td><pre>"
4857c478bd9Sstevel@tonic-gate
4867c478bd9Sstevel@tonic-gate	strip_unchanged /tmp/$$.file1.html
4877c478bd9Sstevel@tonic-gate
488*daaffb31Sdp	print "</pre></td><td><pre>"
4897c478bd9Sstevel@tonic-gate
4907c478bd9Sstevel@tonic-gate	strip_unchanged /tmp/$$.file2.html
4917c478bd9Sstevel@tonic-gate
492*daaffb31Sdp	print "</pre></td>"
493*daaffb31Sdp	print "</tr></table>"
494*daaffb31Sdp	print "</body></html>"
4957c478bd9Sstevel@tonic-gate
496*daaffb31Sdp	framed_sdiff $TNAME $TPATH /tmp/$$.file1.html /tmp/$$.file2.html \
497*daaffb31Sdp	    "$COMMENT"
4987c478bd9Sstevel@tonic-gate}
4997c478bd9Sstevel@tonic-gate
5007c478bd9Sstevel@tonic-gate
501*daaffb31Sdp#
502*daaffb31Sdp# framed_sdiff <filename> <filepath> <lhsfile> <rhsfile> <comment>
503*daaffb31Sdp#
504*daaffb31Sdp# Expects lefthand and righthand side html files created by sdiff_to_html.
505*daaffb31Sdp# We use insert_anchors() to augment those with HTML navigation anchors,
506*daaffb31Sdp# and then emit the main frame.  Content is placed into:
507*daaffb31Sdp#
508*daaffb31Sdp#    $WDIR/DIR/$TNAME.lhs.html
509*daaffb31Sdp#    $WDIR/DIR/$TNAME.rhs.html
510*daaffb31Sdp#    $WDIR/DIR/$TNAME.frames.html
511*daaffb31Sdp#
512*daaffb31Sdp# NOTE: We rely on standard usage of $WDIR and $DIR.
513*daaffb31Sdp#
5147c478bd9Sstevel@tonic-gatefunction framed_sdiff
5157c478bd9Sstevel@tonic-gate{
5167c478bd9Sstevel@tonic-gate	typeset TNAME=$1
517*daaffb31Sdp	typeset TPATH=$2
518*daaffb31Sdp	typeset lhsfile=$3
519*daaffb31Sdp	typeset rhsfile=$4
520*daaffb31Sdp	typeset comments=$5
5217c478bd9Sstevel@tonic-gate	typeset RTOP
522*daaffb31Sdp
5237c478bd9Sstevel@tonic-gate	# Enable html files to access WDIR via a relative path.
524*daaffb31Sdp	RTOP=$(relative_dir $TPATH $WDIR)
525*daaffb31Sdp
526*daaffb31Sdp	# Make the rhs/lhs files and output the frameset file.
527*daaffb31Sdp	print "$HTML<head>$STDHEAD" > $WDIR/$DIR/$TNAME.lhs.html
528*daaffb31Sdp
529*daaffb31Sdp	cat >> $WDIR/$DIR/$TNAME.lhs.html <<-EOF
530*daaffb31Sdp	    <script type="text/javascript" src="$RTOP/ancnav.js" />
5317c478bd9Sstevel@tonic-gate	    </head>
532*daaffb31Sdp	    <body id="SUNWwebrev" onkeypress="keypress(event);">
533*daaffb31Sdp	    <a name="0" />
534*daaffb31Sdp	    <pre>$comments</pre><hr />
535*daaffb31Sdp	EOF
536*daaffb31Sdp
537*daaffb31Sdp	cp $WDIR/$DIR/$TNAME.lhs.html $WDIR/$DIR/$TNAME.rhs.html
538*daaffb31Sdp
539*daaffb31Sdp	insert_anchors $lhsfile >> $WDIR/$DIR/$TNAME.lhs.html
540*daaffb31Sdp	insert_anchors $rhsfile >> $WDIR/$DIR/$TNAME.rhs.html
541*daaffb31Sdp
542*daaffb31Sdp	close='</body></html>'
543*daaffb31Sdp
544*daaffb31Sdp	print $close >> $WDIR/$DIR/$TNAME.lhs.html
545*daaffb31Sdp	print $close >> $WDIR/$DIR/$TNAME.rhs.html
546*daaffb31Sdp
547*daaffb31Sdp	print "$FRAMEHTML<head>$STDHEAD" > $WDIR/$DIR/$TNAME.frames.html
548*daaffb31Sdp	print "<title>$WNAME Framed-Sdiff " \
549*daaffb31Sdp	    "$TPATH/$TNAME</title> </head>" >> $WDIR/$DIR/$TNAME.frames.html
550*daaffb31Sdp	cat >> $WDIR/$DIR/$TNAME.frames.html <<-EOF
551*daaffb31Sdp	  <frameset rows="*,60">
552*daaffb31Sdp	    <frameset cols="50%,50%">
553*daaffb31Sdp	      <frame src="$TNAME.lhs.html" scrolling="auto" name="lhs" />
554*daaffb31Sdp	      <frame src="$TNAME.rhs.html" scrolling="auto" name="rhs" />
555*daaffb31Sdp	    </frameset>
556*daaffb31Sdp	  <frame src="$RTOP/ancnav.html" scrolling="no" marginwidth="0"
557*daaffb31Sdp	   marginheight="0" name="nav" />
558*daaffb31Sdp	  <noframes>
559*daaffb31Sdp            <body id="SUNWwebrev">
560*daaffb31Sdp	      Alas 'frames' webrev requires that your browser supports frames
5617c478bd9Sstevel@tonic-gate	      and has the feature enabled.
562*daaffb31Sdp            </body>
563*daaffb31Sdp	  </noframes>
564*daaffb31Sdp	  </frameset>
5657c478bd9Sstevel@tonic-gate	</html>
5667c478bd9Sstevel@tonic-gate	EOF
5677c478bd9Sstevel@tonic-gate}
5687c478bd9Sstevel@tonic-gate
5697c478bd9Sstevel@tonic-gate
570*daaffb31Sdp#
571*daaffb31Sdp# fix_postscript
572*daaffb31Sdp#
573*daaffb31Sdp# Merge codereview output files to a single conforming postscript file, by:
574*daaffb31Sdp# 	- removing all extraneous headers/trailers
575*daaffb31Sdp#	- making the page numbers right
576*daaffb31Sdp#	- removing pages devoid of contents which confuse some
577*daaffb31Sdp#	  postscript readers.
578*daaffb31Sdp#
579*daaffb31Sdp# From Casper.
580*daaffb31Sdp#
581*daaffb31Sdpfunction fix_postscript
5827c478bd9Sstevel@tonic-gate{
583*daaffb31Sdp	infile=$1
5847c478bd9Sstevel@tonic-gate
585*daaffb31Sdp	cat > /tmp/$$.crmerge.pl << \EOF
5867c478bd9Sstevel@tonic-gate
587*daaffb31Sdp	print scalar(<>);		# %!PS-Adobe---
588*daaffb31Sdp	print "%%Orientation: Landscape\n";
5897c478bd9Sstevel@tonic-gate
590*daaffb31Sdp	$pno = 0;
591*daaffb31Sdp	$doprint = 1;
592*daaffb31Sdp
593*daaffb31Sdp	$page = "";
594*daaffb31Sdp
595*daaffb31Sdp	while (<>) {
596*daaffb31Sdp		next if (/^%%Pages:\s*\d+/);
597*daaffb31Sdp
598*daaffb31Sdp		if (/^%%Page:/) {
599*daaffb31Sdp			if ($pno == 0 || $page =~ /\)S/) {
600*daaffb31Sdp				# Header or single page containing text
601*daaffb31Sdp				print "%%Page: ? $pno\n" if ($pno > 0);
602*daaffb31Sdp				print $page;
603*daaffb31Sdp				$pno++;
604*daaffb31Sdp			} else {
605*daaffb31Sdp				# Empty page, skip it.
6067c478bd9Sstevel@tonic-gate			}
607*daaffb31Sdp			$page = "";
608*daaffb31Sdp			$doprint = 1;
6097c478bd9Sstevel@tonic-gate			next;
6107c478bd9Sstevel@tonic-gate		}
6117c478bd9Sstevel@tonic-gate
612*daaffb31Sdp		# Skip from %%Trailer of one document to Endprolog
613*daaffb31Sdp		# %%Page of the next
614*daaffb31Sdp		$doprint = 0 if (/^%%Trailer/);
615*daaffb31Sdp		$page .= $_ if ($doprint);
6167c478bd9Sstevel@tonic-gate	}
6177c478bd9Sstevel@tonic-gate
618*daaffb31Sdp	if ($page =~ /\)S/) {
619*daaffb31Sdp		print "%%Page: ? $pno\n";
620*daaffb31Sdp		print $page;
621*daaffb31Sdp	} else {
622*daaffb31Sdp		$pno--;
623*daaffb31Sdp	}
624*daaffb31Sdp	print "%%Trailer\n%%Pages: $pno\n";
625*daaffb31SdpEOF
626*daaffb31Sdp
627*daaffb31Sdp	perl /tmp/$$.crmerge.pl < $infile
628*daaffb31Sdp}
629*daaffb31Sdp
630*daaffb31Sdp
631*daaffb31Sdp#
632*daaffb31Sdp# input_cmd | insert_anchors | output_cmd
633*daaffb31Sdp#
6347c478bd9Sstevel@tonic-gate# Flag blocks of difference with sequentially numbered invisible
635*daaffb31Sdp# 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#
641*daaffb31Sdp# The script detects changed lines as any line that has a "<span
642*daaffb31Sdp# class=" string embedded (unchanged lines have no class set and are
643*daaffb31Sdp# 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#
647*daaffb31Sdpfunction insert_anchors
648*daaffb31Sdp{
6497c478bd9Sstevel@tonic-gate	nawk '
6507c478bd9Sstevel@tonic-gate	function ia() {
651*daaffb31Sdp		# This should be able to be a singleton <a /> but that
652*daaffb31Sdp		# seems to trigger a bug in firefox a:hover rule processing
653*daaffb31Sdp		printf "<a name=\"%d\" id=\"anc%d\"></a>", anc, anc++;
6547c478bd9Sstevel@tonic-gate	}
655*daaffb31Sdp
6567c478bd9Sstevel@tonic-gate	BEGIN {
657*daaffb31Sdp		anc=1;
6587c478bd9Sstevel@tonic-gate		inblock=1;
659*daaffb31Sdp		printf "<pre>\n";
6607c478bd9Sstevel@tonic-gate	}
661*daaffb31Sdp	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();
675*daaffb31Sdp
676*daaffb31Sdp		printf "<b style=\"font-size: large; color: red\">";
677*daaffb31Sdp		printf "--- EOF ---</b>"
6787c478bd9Sstevel@tonic-gate        	for(i=0;i<8;i++) printf "\n\n\n\n\n\n\n\n\n\n";
679*daaffb31Sdp		printf "</pre>"
680*daaffb31Sdp		printf "<form name=\"eof\">";
681*daaffb31Sdp		printf "<input name=\"value\" value=\"%d\" type=\"hidden\" />",
682*daaffb31Sdp		    anc - 1;
683*daaffb31Sdp		printf "</form>";
6847c478bd9Sstevel@tonic-gate	}
6857c478bd9Sstevel@tonic-gate	' $1
6867c478bd9Sstevel@tonic-gate}
6877c478bd9Sstevel@tonic-gate
6887c478bd9Sstevel@tonic-gate
689*daaffb31Sdp#
690*daaffb31Sdp# relative_dir
691*daaffb31Sdp#
692*daaffb31Sdp# Print a relative return path from $1 to $2.  For example if
693*daaffb31Sdp# $1=/tmp/myreview/raw_files/usr/src/tools/scripts and $2=/tmp/myreview,
694*daaffb31Sdp# this function would print "../../../../".
695*daaffb31Sdp#
696*daaffb31Sdp# In the event that $1 is not in $2 a warning is printed to stderr,
697*daaffb31Sdp# and $2 is returned-- the result of this is that the resulting webrev
698*daaffb31Sdp# is not relocatable.
699*daaffb31Sdp#
700*daaffb31Sdpfunction relative_dir
7017c478bd9Sstevel@tonic-gate{
702*daaffb31Sdp	typeset cur="${1##$2?(/)}"
703*daaffb31Sdp	typeset ret=""
704*daaffb31Sdp	if [[ $2 == $cur ]]; then   # Should never happen.
705*daaffb31Sdp		# Should never happen.
706*daaffb31Sdp		print -u2 "\nWarning: relative_dir: \"$1\" not relative "
707*daaffb31Sdp		print -u2 "to \"$2\".  Check input paths.  Framed webrev "
708*daaffb31Sdp		print -u2 "will not be relocatable!"
709*daaffb31Sdp		print $2
710*daaffb31Sdp		return
711*daaffb31Sdp	fi
712*daaffb31Sdp
713*daaffb31Sdp	while [[ -n ${cur} ]];
7147c478bd9Sstevel@tonic-gate	do
7157c478bd9Sstevel@tonic-gate		cur=${cur%%*(/)*([!/])}
716*daaffb31Sdp		if [[ -z $ret ]]; then
717*daaffb31Sdp			ret=".."
718*daaffb31Sdp		else
7197c478bd9Sstevel@tonic-gate			ret="../$ret"
720*daaffb31Sdp		fi
7217c478bd9Sstevel@tonic-gate	done
7227c478bd9Sstevel@tonic-gate	print $ret
7237c478bd9Sstevel@tonic-gate}
7247c478bd9Sstevel@tonic-gate
7257c478bd9Sstevel@tonic-gate
726*daaffb31Sdp#
727*daaffb31Sdp# frame_nav_js
728*daaffb31Sdp#
729*daaffb31Sdp# Emit javascript for frame navigation
730*daaffb31Sdp#
731*daaffb31Sdpfunction frame_nav_js
7327c478bd9Sstevel@tonic-gate{
7337c478bd9Sstevel@tonic-gatecat << \EOF
7347c478bd9Sstevel@tonic-gatevar myInt;
7357c478bd9Sstevel@tonic-gatevar scrolling=0;
736*daaffb31Sdpvar 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
749*daaffb31Sdpfunction scrollToAnc(num) {
750*daaffb31Sdp
751*daaffb31Sdp	// Update the value of the anchor in the form which we use as
752*daaffb31Sdp	// storage for this value.  setAncValue() will take care of
753*daaffb31Sdp	// correcting for overflow and underflow of the value and return
754*daaffb31Sdp	// us the new value.
755*daaffb31Sdp	num = setAncValue(num);
756*daaffb31Sdp
757*daaffb31Sdp	// Set location and scroll back a little to expose previous
758*daaffb31Sdp	// lines.
759*daaffb31Sdp	//
760*daaffb31Sdp	// Note that this could be improved: it is possible although
761*daaffb31Sdp	// complex to compute the x and y position of an anchor, and to
762*daaffb31Sdp	// scroll to that location directly.
763*daaffb31Sdp	//
7647c478bd9Sstevel@tonic-gate	parent.lhs.location.replace(parent.lhs.location.pathname + "#" + num);
7657c478bd9Sstevel@tonic-gate	parent.rhs.location.replace(parent.rhs.location.pathname + "#" + num);
766*daaffb31Sdp
7677c478bd9Sstevel@tonic-gate	parent.lhs.scrollBy(0,-30);
7687c478bd9Sstevel@tonic-gate	parent.rhs.scrollBy(0,-30);
7697c478bd9Sstevel@tonic-gate}
7707c478bd9Sstevel@tonic-gate
771*daaffb31Sdpfunction getAncValue()
772*daaffb31Sdp{
773*daaffb31Sdp	return (parseInt(parent.nav.document.diff.real.value));
774*daaffb31Sdp}
775*daaffb31Sdp
776*daaffb31Sdpfunction setAncValue(val)
777*daaffb31Sdp{
778*daaffb31Sdp	if (val <= 0) {
779*daaffb31Sdp		val = 0;
780*daaffb31Sdp		parent.nav.document.diff.real.value = val;
781*daaffb31Sdp		parent.nav.document.diff.display.value = "BOF";
782*daaffb31Sdp		return (val);
783*daaffb31Sdp	}
784*daaffb31Sdp
785*daaffb31Sdp	//
786*daaffb31Sdp	// The way we compute the max anchor value is to stash it
787*daaffb31Sdp	// inline in the left and right hand side pages-- it's the same
788*daaffb31Sdp	// on each side, so we pluck from the left.
789*daaffb31Sdp	//
790*daaffb31Sdp	maxval = parent.lhs.document.eof.value.value;
791*daaffb31Sdp	if (val < maxval) {
792*daaffb31Sdp		parent.nav.document.diff.real.value = val;
793*daaffb31Sdp		parent.nav.document.diff.display.value = val.toString();
794*daaffb31Sdp		return (val);
795*daaffb31Sdp	}
796*daaffb31Sdp
797*daaffb31Sdp	// this must be: val >= maxval
798*daaffb31Sdp	val = maxval;
799*daaffb31Sdp	parent.nav.document.diff.real.value = val;
800*daaffb31Sdp	parent.nav.document.diff.display.value = "EOF";
801*daaffb31Sdp	return (val);
802*daaffb31Sdp}
803*daaffb31Sdp
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) {
818*daaffb31Sdp
8197c478bd9Sstevel@tonic-gate	switch (b) {
8207c478bd9Sstevel@tonic-gate	    case 1 :
821*daaffb31Sdp		scrollToAnc(-1);
8227c478bd9Sstevel@tonic-gate		break;
8237c478bd9Sstevel@tonic-gate	    case 2 :
824*daaffb31Sdp		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 :
835*daaffb31Sdp		scrollToAnc(getAncValue() + 1);
8367c478bd9Sstevel@tonic-gate		break;
8377c478bd9Sstevel@tonic-gate	    case 6 :
838*daaffb31Sdp		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
847*daaffb31Sdpfunction keypress(ev) {
848*daaffb31Sdp	var keynum;
849*daaffb31Sdp	var keychar;
850*daaffb31Sdp
851*daaffb31Sdp	if (window.event) { // IE
852*daaffb31Sdp		keynum = ev.keyCode;
853*daaffb31Sdp	} else if (ev.which) { // non-IE
854*daaffb31Sdp		keynum = ev.which;
855*daaffb31Sdp	}
856*daaffb31Sdp
857*daaffb31Sdp	keychar = String.fromCharCode(keynum);
858*daaffb31Sdp
859*daaffb31Sdp	if (keychar == "k") {
860*daaffb31Sdp		handlePress(2);
861*daaffb31Sdp		return (0);
862*daaffb31Sdp	} else if (keychar == "j" || keychar == " ") {
863*daaffb31Sdp		handlePress(5);
864*daaffb31Sdp		return (0);
865*daaffb31Sdp	}
866*daaffb31Sdp	return (1);
867*daaffb31Sdp}
868*daaffb31Sdp
8697c478bd9Sstevel@tonic-gatefunction ValidateDiffNum(){
870*daaffb31Sdp	val = parent.nav.document.diff.display.value;
871*daaffb31Sdp	if (val == "EOF") {
872*daaffb31Sdp		scrollToAnc(999999);
873*daaffb31Sdp		return;
874*daaffb31Sdp	}
875*daaffb31Sdp
876*daaffb31Sdp	if (val == "BOF") {
877*daaffb31Sdp		scrollToAnc(0);
878*daaffb31Sdp		return;
879*daaffb31Sdp	}
880*daaffb31Sdp
881*daaffb31Sdp        i=parseInt(val);
8827c478bd9Sstevel@tonic-gate        if (isNaN(i)) {
883*daaffb31Sdp                parent.nav.document.diff.display.value = getAncValue();
8847c478bd9Sstevel@tonic-gate        } else {
885*daaffb31Sdp                scrollToAnc(i);
8867c478bd9Sstevel@tonic-gate        }
8877c478bd9Sstevel@tonic-gate        return false;
8887c478bd9Sstevel@tonic-gate}
8897c478bd9Sstevel@tonic-gate
890*daaffb31SdpEOF
891*daaffb31Sdp}
892*daaffb31Sdp
893*daaffb31Sdp#
894*daaffb31Sdp# frame_navigation
895*daaffb31Sdp#
896*daaffb31Sdp# Output anchor navigation file for framed sdiffs.
897*daaffb31Sdp#
898*daaffb31Sdpfunction frame_navigation
899*daaffb31Sdp{
900*daaffb31Sdp	print "$HTML<head>$STDHEAD"
901*daaffb31Sdp
902*daaffb31Sdp	cat << \EOF
903*daaffb31Sdp<title>Anchor Navigation</title>
904*daaffb31Sdp<meta http-equiv="Content-Script-Type" content="text/javascript">
905*daaffb31Sdp<meta http-equiv="Content-Type" content="text/html">
906*daaffb31Sdp
907*daaffb31Sdp<style type="text/css">
908*daaffb31Sdp    div.button td { padding-left: 5px; padding-right: 5px;
909*daaffb31Sdp		    background-color: #eee; text-align: center;
910*daaffb31Sdp		    border: 1px #444 outset; cursor: pointer; }
911*daaffb31Sdp    div.button a { font-weight: bold; color: black }
912*daaffb31Sdp    div.button td:hover { background: #ffcc99; }
913*daaffb31Sdp</style>
914*daaffb31SdpEOF
915*daaffb31Sdp
916*daaffb31Sdp	print "<script type=\"text/javascript\" src=\"ancnav.js\" />"
917*daaffb31Sdp
918*daaffb31Sdp	cat << \EOF
9197c478bd9Sstevel@tonic-gate</head>
920*daaffb31Sdp<body id="SUNWwebrev" bgcolor="#eeeeee" onload="document.diff.real.focus();"
921*daaffb31Sdp	onkeypress="keypress(event);">
9227c478bd9Sstevel@tonic-gate    <noscript lang="javascript">
9237c478bd9Sstevel@tonic-gate      <center>
924*daaffb31Sdp	<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">
929*daaffb31Sdp	<tr>
930*daaffb31Sdp          <td valign="middle" width="25%">Diff navigation:
931*daaffb31Sdp          Use 'j' and 'k' for next and previous diffs; or use buttons
932*daaffb31Sdp          at right</td>
933*daaffb31Sdp	  <td align="center" valign="top" width="50%">
9347c478bd9Sstevel@tonic-gate	    <div class="button">
935*daaffb31Sdp	      <table border="0" align="center">
936*daaffb31Sdp                  <tr>
937*daaffb31Sdp		    <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>
943*daaffb31Sdp		    <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"
948*daaffb31Sdp			 onClick="return false;">Scroll Up</a></td>
949*daaffb31Sdp		    <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>
956*daaffb31Sdp
9577c478bd9Sstevel@tonic-gate		  <tr>
958*daaffb31Sdp		    <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>
964*daaffb31Sdp		    <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"
969*daaffb31Sdp			 onClick="return false;">Scroll Down</a></td>
970*daaffb31Sdp		    <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>
976*daaffb31Sdp		  </tr>
977*daaffb31Sdp              </table>
978*daaffb31Sdp	    </div>
979*daaffb31Sdp	  </td>
9807c478bd9Sstevel@tonic-gate	  <th valign="middle" width="25%">
981*daaffb31Sdp	    <form action="" name="diff" onsubmit="return ValidateDiffNum();">
982*daaffb31Sdp		<input name="display" value="BOF" size="8" type="text" />
983*daaffb31Sdp		<input name="real" value="0" size="8" type="hidden" />
9847c478bd9Sstevel@tonic-gate	    </form>
9857c478bd9Sstevel@tonic-gate	  </th>
986*daaffb31Sdp	</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
994*daaffb31Sdp
995*daaffb31Sdp#
996*daaffb31Sdp# diff_to_html <filename> <filepath> { U | C } <comment>
997*daaffb31Sdp#
998*daaffb31Sdp# Processes the output of diff to produce an HTML file representing either
999*daaffb31Sdp# context or unified diffs.
1000*daaffb31Sdp#
10017c478bd9Sstevel@tonic-gatediff_to_html()
10027c478bd9Sstevel@tonic-gate{
10037c478bd9Sstevel@tonic-gate	TNAME=$1
1004*daaffb31Sdp	TPATH=$2
1005*daaffb31Sdp	DIFFTYPE=$3
1006*daaffb31Sdp	COMMENT=$4
1007*daaffb31Sdp
1008*daaffb31Sdp	print "$HTML<head>$STDHEAD"
1009*daaffb31Sdp	print "<title>$WNAME ${DIFFTYPE}diff $TPATH</title>"
1010*daaffb31Sdp
1011*daaffb31Sdp	if [[ $DIFFTYPE == "U" ]]; then
1012*daaffb31Sdp		print "$UDIFFCSS"
1013*daaffb31Sdp	fi
1014*daaffb31Sdp
1015*daaffb31Sdp	cat <<-EOF
1016*daaffb31Sdp	</head>
1017*daaffb31Sdp	<body id="SUNWwebrev">
1018*daaffb31Sdp        <a class="print" href="javascript:print()">Print this page</a>
1019*daaffb31Sdp	<pre>$COMMENT</pre>
1020*daaffb31Sdp        <pre>
1021*daaffb31Sdp	EOF
10227c478bd9Sstevel@tonic-gate
10237c478bd9Sstevel@tonic-gate	html_quote | nawk '
1024*daaffb31Sdp	/^--- new/	{ next }
1025*daaffb31Sdp	/^\+\+\+ new/	{ next }
1026*daaffb31Sdp	/^--- old/	{ next }
1027*daaffb31Sdp	/^\*\*\* old/	{ next }
1028*daaffb31Sdp	/^\*\*\*\*/	{ next }
10297c478bd9Sstevel@tonic-gate	/^-------/	{ printf "<center><h1>%s</h1></center>\n", $0; next }
1030*daaffb31Sdp	/^\@\@.*\@\@$/	{ printf "</pre><hr /><pre>\n";
1031*daaffb31Sdp			  printf "<span class=\"newmarker\">%s</span>\n", $0;
1032*daaffb31Sdp			  next}
1033*daaffb31Sdp
1034*daaffb31Sdp	/^\*\*\*/	{ printf "<hr /><span class=\"oldmarker\">%s</span>\n", $0;
1035*daaffb31Sdp			  next}
1036*daaffb31Sdp	/^---/		{ printf "<span class=\"newmarker\">%s</span>\n", $0;
1037*daaffb31Sdp			  next}
1038*daaffb31Sdp	/^\+/		{printf "<span class=\"new\">%s</span>\n", $0; next}
1039*daaffb31Sdp	/^!/		{printf "<span class=\"changed\">%s</span>\n", $0; next}
1040*daaffb31Sdp	/^-/		{printf "<span class=\"removed\">%s</span>\n", $0; next}
1041*daaffb31Sdp			{printf "%s\n", $0; next}
10427c478bd9Sstevel@tonic-gate	'
1043*daaffb31Sdp
1044*daaffb31Sdp	print "</pre></body></html>\n"
10457c478bd9Sstevel@tonic-gate}
10467c478bd9Sstevel@tonic-gate
10477c478bd9Sstevel@tonic-gate
1048*daaffb31Sdp#
1049*daaffb31Sdp# source_to_html { new | old } <filename>
1050*daaffb31Sdp#
1051*daaffb31Sdp# Process a plain vanilla source file to transform it into an HTML file.
1052*daaffb31Sdp#
10537c478bd9Sstevel@tonic-gatesource_to_html()
10547c478bd9Sstevel@tonic-gate{
10557c478bd9Sstevel@tonic-gate	WHICH=$1
10567c478bd9Sstevel@tonic-gate	TNAME=$2
10577c478bd9Sstevel@tonic-gate
1058*daaffb31Sdp	print "$HTML<head>$STDHEAD"
1059*daaffb31Sdp	print "<title>$WHICH $TNAME</title>"
1060*daaffb31Sdp	print "<body id=\"SUNWwebrev\">"
1061*daaffb31Sdp	print "<pre>"
1062*daaffb31Sdp	html_quote | nawk '{line += 1 ; printf "%4d %s\n", line, $0 }'
1063*daaffb31Sdp	print "</pre></body></html>"
10647c478bd9Sstevel@tonic-gate}
10657c478bd9Sstevel@tonic-gate
1066*daaffb31Sdp#
1067*daaffb31Sdp# teamwarecomments {text|html} parent-file child-file
1068*daaffb31Sdp#
1069*daaffb31Sdp# Find the first delta in the child that's not in the parent.  Get the
1070*daaffb31Sdp# newest delta from the parent, get all deltas from the child starting
1071*daaffb31Sdp# with that delta, and then get all info starting with the second oldest
1072*daaffb31Sdp# 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
1075*daaffb31Sdp#
1076*daaffb31Sdpcomments_from_teamware()
10777c478bd9Sstevel@tonic-gate{
1078*daaffb31Sdp	fmt=$1
1079*daaffb31Sdp	pfile=$PWS/$2
1080*daaffb31Sdp	cfile=$CWS/$3
10817c478bd9Sstevel@tonic-gate
1082*daaffb31Sdp	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
1091*daaffb31Sdp	nawkprg='
1092*daaffb31Sdp		/^COMMENTS:/	{p=1; continue}
1093*daaffb31Sdp		/^D [0-9]+\.[0-9]+/ {printf "--- %s ---\n", $2; p=0; }
1094*daaffb31Sdp		NF == 0u	{ continue }
1095*daaffb31Sdp		{if (p==0) continue; print $0 }'
1096*daaffb31Sdp
10977c478bd9Sstevel@tonic-gate	if [[ $N -ge 2 ]]; then
10987c478bd9Sstevel@tonic-gate		sid1=${sids[$((N-2))]}	# Gets 2nd to last sid
10997c478bd9Sstevel@tonic-gate
1100*daaffb31Sdp		if [[ $fmt == "text" ]]; then
1101*daaffb31Sdp			sccs prs -l -r$sid1 $cfile  2>/dev/null | \
1102*daaffb31Sdp			    nawk "$nawkprg"
1103*daaffb31Sdp			return
1104*daaffb31Sdp		fi
1105*daaffb31Sdp
1106*daaffb31Sdp		sccs prs -l -r$sid1 $cfile  2>/dev/null | \
1107*daaffb31Sdp		    html_quote | bug2url | sac2url | nawk "$nawkprg"
11087c478bd9Sstevel@tonic-gate	fi
11097c478bd9Sstevel@tonic-gate}
11107c478bd9Sstevel@tonic-gate
1111*daaffb31Sdp#
1112*daaffb31Sdp# wxcomments {text|html} filepath
1113*daaffb31Sdp#
1114*daaffb31Sdp# Given the pathname of a file, find its location in a "wx" active file
1115*daaffb31Sdp# list and print the following sccs comment.  Output is either text or
1116*daaffb31Sdp# HTML; if the latter, embedded bugids (sequence of 5 or more digits) are
1117*daaffb31Sdp# turned into URLs.
1118*daaffb31Sdp#
1119*daaffb31Sdpcomments_from_wx()
11207c478bd9Sstevel@tonic-gate{
1121*daaffb31Sdp	typeset fmt=$1
1122*daaffb31Sdp	typeset p=$2
11237c478bd9Sstevel@tonic-gate
1124*daaffb31Sdp	comm=`nawk '
1125*daaffb31Sdp	$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
1130*daaffb31Sdp	}' < $wxfile`
1131*daaffb31Sdp
1132*daaffb31Sdp	if [[ $fmt == "text" ]]; then
1133*daaffb31Sdp		print "$comm"
1134*daaffb31Sdp		return
1135*daaffb31Sdp	fi
1136*daaffb31Sdp
1137*daaffb31Sdp	print "$comm" | html_quote | bug2url | sac2url
11387c478bd9Sstevel@tonic-gate}
11397c478bd9Sstevel@tonic-gate
11407c478bd9Sstevel@tonic-gate#
1141*daaffb31Sdp# getcomments {text|html} filepath parentpath
1142*daaffb31Sdp#
1143*daaffb31Sdp# Fetch the comments depending on what SCM mode we're in.
1144*daaffb31Sdp#
1145*daaffb31Sdpgetcomments()
1146*daaffb31Sdp{
1147*daaffb31Sdp	typeset fmt=$1
1148*daaffb31Sdp	typeset p=$2
1149*daaffb31Sdp	typeset pp=$3
11507c478bd9Sstevel@tonic-gate
1151*daaffb31Sdp	if [[ -n $wxfile ]]; then
1152*daaffb31Sdp		comments_from_wx $fmt $p
1153*daaffb31Sdp	else
1154*daaffb31Sdp		if [[ $SCM_MODE == "teamware" ]]; then
1155*daaffb31Sdp			comments_from_teamware $fmt $pp $p
1156*daaffb31Sdp		fi
1157*daaffb31Sdp	fi
1158*daaffb31Sdp}
1159*daaffb31Sdp
1160*daaffb31Sdp#
1161*daaffb31Sdp# printCI <total-changed> <inserted> <deleted> <modified> <unchanged>
1162*daaffb31Sdp#
1163*daaffb31Sdp# Print out Code Inspection figures similar to sccs-prt(1) format.
1164*daaffb31Sdp#
1165*daaffb31Sdpfunction printCI
1166*daaffb31Sdp{
1167*daaffb31Sdp	integer tot=$1 ins=$2 del=$3 mod=$4 unc=$5
1168*daaffb31Sdp	typeset str
1169*daaffb31Sdp	if (( tot == 1 )); then
1170*daaffb31Sdp		str="line"
1171*daaffb31Sdp	else
1172*daaffb31Sdp		str="lines"
1173*daaffb31Sdp	fi
1174*daaffb31Sdp	printf '%d %s changed: %d ins; %d del; %d mod; %d unchg\n' \
1175*daaffb31Sdp	    $tot $str $ins $del $mod $unc
1176*daaffb31Sdp}
1177*daaffb31Sdp
1178*daaffb31Sdp
1179*daaffb31Sdp#
1180*daaffb31Sdp# difflines <oldfile> <newfile>
1181*daaffb31Sdp#
1182*daaffb31Sdp# Calculate and emit number of added, removed, modified and unchanged lines,
1183*daaffb31Sdp# and total lines changed, the sum of added + removed + modified.
1184*daaffb31Sdp#
11857c478bd9Sstevel@tonic-gatefunction difflines
11867c478bd9Sstevel@tonic-gate{
1187*daaffb31Sdp	integer tot mod del ins unc err
11887c478bd9Sstevel@tonic-gate	typeset filename
11897c478bd9Sstevel@tonic-gate
11907c478bd9Sstevel@tonic-gate	diff -e $1 $2 | eval $( nawk '
1191*daaffb31Sdp	# 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		}
1198*daaffb31Sdp		#
1199*daaffb31Sdp		# 3,5c means lines 3 , 4 and 5 are changed, a total of 3 lines.
1200*daaffb31Sdp		# following would be 5 - 3 = 2! Hence +1 for correction.
1201*daaffb31Sdp		#
12027c478bd9Sstevel@tonic-gate		r=(counts[2]-counts[1])+1;
1203*daaffb31Sdp
1204*daaffb31Sdp		#
1205*daaffb31Sdp		# Now count replacement lines: each represents a change instead
1206*daaffb31Sdp		# of a delete, so increment c and decrement r.
1207*daaffb31Sdp		#
12087c478bd9Sstevel@tonic-gate		while (getline != /^\.$/) {
12097c478bd9Sstevel@tonic-gate			c++;
12107c478bd9Sstevel@tonic-gate			r--;
12117c478bd9Sstevel@tonic-gate		}
1212*daaffb31Sdp		#
1213*daaffb31Sdp		# If there were more replacement lines than original lines,
1214*daaffb31Sdp		# then r will be negative; in this case there are no deletions,
1215*daaffb31Sdp		# but there are r changes that should be counted as adds, and
1216*daaffb31Sdp		# since r is negative, subtract it from a and add it to c.
1217*daaffb31Sdp		#
12187c478bd9Sstevel@tonic-gate		if (r < 0) {
12197c478bd9Sstevel@tonic-gate			a-=r;
12207c478bd9Sstevel@tonic-gate			c+=r;
12217c478bd9Sstevel@tonic-gate		}
1222*daaffb31Sdp
1223*daaffb31Sdp		#
1224*daaffb31Sdp		# If there were more original lines than replacement lines, then
1225*daaffb31Sdp		# r will be positive; in this case, increment d by that much.
1226*daaffb31Sdp		#
12277c478bd9Sstevel@tonic-gate		if (r > 0) {
12287c478bd9Sstevel@tonic-gate			d+=r;
12297c478bd9Sstevel@tonic-gate		}
12307c478bd9Sstevel@tonic-gate		next;
12317c478bd9Sstevel@tonic-gate	}
12327c478bd9Sstevel@tonic-gate
1233*daaffb31Sdp	# Change lines: Nc
12347c478bd9Sstevel@tonic-gate	/^[0-9].*c$/ {
1235*daaffb31Sdp		# 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
1243*daaffb31Sdp	# 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
1249*daaffb31Sdp	# 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		}
1256*daaffb31Sdp		#
1257*daaffb31Sdp		# 3,5d means lines 3 , 4 and 5 are deleted, a total of 3 lines.
1258*daaffb31Sdp		# following would be 5 - 3 = 2! Hence +1 for correction.
1259*daaffb31Sdp		#
12607c478bd9Sstevel@tonic-gate		r=(counts[2]-counts[1])+1;
12617c478bd9Sstevel@tonic-gate		d+=r;
12627c478bd9Sstevel@tonic-gate		next;
12637c478bd9Sstevel@tonic-gate	}
12647c478bd9Sstevel@tonic-gate
1265*daaffb31Sdp	# Delete line: Nd.   For example 10d says line 10 is deleted.
12667c478bd9Sstevel@tonic-gate	/^[0-9]*d$/ {d++; next}
12677c478bd9Sstevel@tonic-gate
1268*daaffb31Sdp	# Should not get here!
12697c478bd9Sstevel@tonic-gate	{
12707c478bd9Sstevel@tonic-gate		error=1;
12717c478bd9Sstevel@tonic-gate		exit;
12727c478bd9Sstevel@tonic-gate	}
12737c478bd9Sstevel@tonic-gate
1274*daaffb31Sdp	# Finish off - print results
12757c478bd9Sstevel@tonic-gate	END {
1276*daaffb31Sdp		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
1282*daaffb31Sdp		print "Unexpected Error occurred reading" \
1283*daaffb31Sdp		    "\`diff -e $1 $2\`: \$?=$?, err=" $err
1284*daaffb31Sdp		return
1285*daaffb31Sdp	fi
1286*daaffb31Sdp
12877c478bd9Sstevel@tonic-gate	# Accumulate totals
12887c478bd9Sstevel@tonic-gate	(( TOTL += tot ))
1289*daaffb31Sdp	(( 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
1295*daaffb31Sdp		(( unc -= del + mod ))
12967c478bd9Sstevel@tonic-gate		(( TUNC += unc ))
12977c478bd9Sstevel@tonic-gate	fi
12987c478bd9Sstevel@tonic-gate	# print summary
1299*daaffb31Sdp	print "<span class=\"lineschanged\">"
1300*daaffb31Sdp	printCI $tot $ins $del $mod $unc
1301*daaffb31Sdp	print "</span>"
13027c478bd9Sstevel@tonic-gate}
13037c478bd9Sstevel@tonic-gate
1304*daaffb31Sdp
13057c478bd9Sstevel@tonic-gate#
1306*daaffb31Sdp# flist_from_wx
1307*daaffb31Sdp#
1308*daaffb31Sdp# Sets up webrev to source its information from a wx-formatted file.
1309*daaffb31Sdp# Sets the global 'wxfile' variable.
1310*daaffb31Sdp#
1311*daaffb31Sdpfunction flist_from_wx
13127c478bd9Sstevel@tonic-gate{
1313*daaffb31Sdp	typeset argfile=$1
1314*daaffb31Sdp	if [[ -n ${argfile%%/*} ]]; then
1315*daaffb31Sdp		#
1316*daaffb31Sdp		# If the wx file pathname is relative then make it absolute
1317*daaffb31Sdp		# because the webrev does a "cd" later on.
1318*daaffb31Sdp		#
1319*daaffb31Sdp		wxfile=$PWD/$argfile
13207c478bd9Sstevel@tonic-gate	else
1321*daaffb31Sdp		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	  }
1329*daaffb31Sdp	}' $wxfile > $FLIST
13307c478bd9Sstevel@tonic-gate
1331*daaffb31Sdp	print " Done."
1332*daaffb31Sdp}
13337c478bd9Sstevel@tonic-gate
1334*daaffb31Sdp#
1335*daaffb31Sdp# flist_from_teamware [ <args-to-putback-n> ]
1336*daaffb31Sdp#
1337*daaffb31Sdp# Generate the file list by extracting file names from a putback -n.  Some
1338*daaffb31Sdp# names may come from the "update/create" messages and others from the
1339*daaffb31Sdp# "currently checked out" warning.  Renames are detected here too.  Extract
1340*daaffb31Sdp# values for CODEMGR_WS and CODEMGR_PARENT from the output of the putback
1341*daaffb31Sdp# -n as well, but remove them if they are already defined.
1342*daaffb31Sdp#
1343*daaffb31Sdpfunction flist_from_teamware
1344*daaffb31Sdp{
1345*daaffb31Sdp	if [[ -n $codemgr_parent ]]; then
1346*daaffb31Sdp		if [[ ! -d $codemgr_parent/Codemgr_wsdata ]]; then
1347*daaffb31Sdp			print -u2 "parent $codemgr_parent doesn't look like a" \
1348*daaffb31Sdp			    "valid teamware workspace"
13497c478bd9Sstevel@tonic-gate			exit 1
13507c478bd9Sstevel@tonic-gate		fi
1351*daaffb31Sdp		parent_args="-p $codemgr_parent"
13527c478bd9Sstevel@tonic-gate	fi
13537c478bd9Sstevel@tonic-gate
1354*daaffb31Sdp	print " File list from: 'putback -n $parent_args $*' ... \c"
13557c478bd9Sstevel@tonic-gate
1356*daaffb31Sdp	putback -n $parent_args $* 2>&1 |
1357*daaffb31Sdp	    nawk '
1358*daaffb31Sdp		/^update:|^create:/	{print $2}
1359*daaffb31Sdp		/^Parent workspace:/	{printf("CODEMGR_PARENT=%s\n",$3)}
1360*daaffb31Sdp		/^Child workspace:/	{printf("CODEMGR_WS=%s\n",$3)}
1361*daaffb31Sdp		/^The following files are currently checked out/ {p = 1; continue}
1362*daaffb31Sdp		NF == 0			{p=0 ; continue}
1363*daaffb31Sdp		/^rename/		{old=$3}
1364*daaffb31Sdp		$1 == "to:"		{print $2, old}
1365*daaffb31Sdp		/^"/			{continue}
1366*daaffb31Sdp		p == 1			{print $1}' |
1367*daaffb31Sdp	    sort -r -k 1,1 -u | sort > $FLIST
13687c478bd9Sstevel@tonic-gate
1369*daaffb31Sdp	print " Done."
1370*daaffb31Sdp}
1371*daaffb31Sdp
1372*daaffb31Sdpfunction env_from_flist
1373*daaffb31Sdp{
1374*daaffb31Sdp	[[ -r $FLIST ]] || return
1375*daaffb31Sdp
1376*daaffb31Sdp	#
1377*daaffb31Sdp	# Use "eval" to set env variables that are listed in the file
1378*daaffb31Sdp	# list.  Then copy those into our local versions of those
1379*daaffb31Sdp	# variables if they have not been set already.
1380*daaffb31Sdp	#
13817c478bd9Sstevel@tonic-gate	eval `sed -e "s/#.*$//" $FLIST | grep = `
13827c478bd9Sstevel@tonic-gate
1383*daaffb31Sdp	[[ -z $codemgr_ws && -n $CODEMGR_WS ]] && codemgr_ws=$CODEMGR_WS
13847c478bd9Sstevel@tonic-gate
1385*daaffb31Sdp	#
1386*daaffb31Sdp	# Check to see if CODEMGR_PARENT is set in the flist file.
1387*daaffb31Sdp	#
1388*daaffb31Sdp	[[ -z $codemgr_parent && -n $CODEMGR_PARENT ]] && \
1389*daaffb31Sdp	    codemgr_parent=$CODEMGR_PARENT
1390*daaffb31Sdp}
1391*daaffb31Sdp
1392*daaffb31Sdp#
1393*daaffb31Sdp# detect_scm
1394*daaffb31Sdp#
1395*daaffb31Sdp# We dynamically test the SCM type; this allows future extensions to
1396*daaffb31Sdp# new SCM types
1397*daaffb31Sdp#
1398*daaffb31Sdpfunction detect_scm
1399*daaffb31Sdp{
1400*daaffb31Sdp	#
1401*daaffb31Sdp	# If CODEMGR_WS is specified in the flist file, we assume teamware.
1402*daaffb31Sdp	#
1403*daaffb31Sdp	if [[ -r $FLIST ]]; then
1404*daaffb31Sdp		egrep '^CODEMGR_WS=' $FLIST > /dev/null 2>&1
1405*daaffb31Sdp		if [[ $? -eq 0 ]]; then
1406*daaffb31Sdp			print "teamware"
1407*daaffb31Sdp			return
1408*daaffb31Sdp		fi
1409*daaffb31Sdp	fi
1410*daaffb31Sdp
1411*daaffb31Sdp	#
1412*daaffb31Sdp	# The presence of $CODEMGR_WS and a Codemgr_wsdata directory
1413*daaffb31Sdp	# is our clue that this is a teamware workspace.
1414*daaffb31Sdp	#
1415*daaffb31Sdp	if [[ -n $CODEMGR_WS && -d "$CODEMGR_WS/Codemgr_wsdata" ]]; then
1416*daaffb31Sdp		print "teamware"
1417*daaffb31Sdp	else
1418*daaffb31Sdp		print "unknown"
1419*daaffb31Sdp	fi
1420*daaffb31Sdp}
1421*daaffb31Sdp
1422*daaffb31Sdp#
1423*daaffb31Sdp# Usage message.
1424*daaffb31Sdp#
1425*daaffb31Sdpfunction usage
1426*daaffb31Sdp{
1427*daaffb31Sdp	print 'Usage:\twebrev [common-options]
1428*daaffb31Sdp	webrev [common-options] ( <file> | - )
1429*daaffb31Sdp	webrev [common-options] -w <wx file>
1430*daaffb31Sdp	webrev [common-options] -l [arguments to 'putback']
1431*daaffb31Sdp
1432*daaffb31SdpOptions:
1433*daaffb31Sdp	-O: Print bugids/arc cases suitable for OpenSolaris.
1434*daaffb31Sdp	-i <filename>: Include <filename> in the index.html file.
1435*daaffb31Sdp	-o <outdir>: Output webrev to specified directory.
1436*daaffb31Sdp	-p <compare-against>: Use specified parent wkspc or basis for comparison
1437*daaffb31Sdp	-w <wxfile>: Use specified wx active file.
1438*daaffb31Sdp
1439*daaffb31SdpEnvironment:
1440*daaffb31Sdp	WDIR: Control the output directory.
1441*daaffb31Sdp	WEBREV_BUGURL: Control the URL prefix for bugids.
1442*daaffb31Sdp	WEBREV_SACURL: Control the URL prefix for ARC cases.
1443*daaffb31Sdp
1444*daaffb31SdpSCM Environment:
1445*daaffb31Sdp	Teamware: CODEMGR_WS: Workspace location.
1446*daaffb31Sdp	Teamware: CODEMGR_PARENT: Parent workspace location.
1447*daaffb31Sdp'
1448*daaffb31Sdp
1449*daaffb31Sdp	exit 2
1450*daaffb31Sdp}
1451*daaffb31Sdp
1452*daaffb31Sdp#
1453*daaffb31Sdp#
1454*daaffb31Sdp# Main program starts here
1455*daaffb31Sdp#
1456*daaffb31Sdp#
1457*daaffb31Sdp
1458*daaffb31Sdptrap "rm -f /tmp/$$.* ; exit" 0 1 2 3 15
1459*daaffb31Sdp
1460*daaffb31Sdpset +o noclobber
1461*daaffb31Sdp
1462*daaffb31Sdpif [[ -z $WDIFF ]]; then
1463*daaffb31Sdp	WDIFF=`whence wdiff`
1464*daaffb31Sdp	if [[ -z $WDIFF ]]; then
1465*daaffb31Sdp		if [[ -x /opt/onbld/bin/wdiff ]]; then
1466*daaffb31Sdp			WDIFF=/opt/onbld/bin/wdiff
1467*daaffb31Sdp		elif [[ -x /ws/onnv-gate/public/bin/wdiff ]]; then
1468*daaffb31Sdp			WDIFF=/ws/onnv-gate/public/bin/wdiff
1469*daaffb31Sdp		else
1470*daaffb31Sdp			print -u2 "Warning: wdiff not found!"
1471*daaffb31Sdp		fi
1472*daaffb31Sdp	fi
1473*daaffb31Sdpfi
1474*daaffb31Sdp
1475*daaffb31Sdp# Declare global total counters.
1476*daaffb31Sdpinteger TOTL TINS TDEL TMOD TUNC
1477*daaffb31Sdp
1478*daaffb31Sdpflist_autodetect=
1479*daaffb31Sdpiflag=
1480*daaffb31Sdpoflag=
1481*daaffb31Sdppflag=
1482*daaffb31Sdplflag=
1483*daaffb31Sdpwflag=
1484*daaffb31SdpOflag=
1485*daaffb31Sdpwhile getopts "i:o:p:lwO" opt
1486*daaffb31Sdpdo
1487*daaffb31Sdp	case $opt in
1488*daaffb31Sdp	i)	iflag=1
1489*daaffb31Sdp		INCLUDE_FILE=$OPTARG;;
1490*daaffb31Sdp
1491*daaffb31Sdp	o)	oflag=1
1492*daaffb31Sdp		WDIR=$OPTARG;;
1493*daaffb31Sdp
1494*daaffb31Sdp	p)	pflag=1
1495*daaffb31Sdp		codemgr_parent=$OPTARG;;
1496*daaffb31Sdp
1497*daaffb31Sdp	#
1498*daaffb31Sdp	# If -l has been specified, we need to abort further options
1499*daaffb31Sdp	# processing, because subsequent arguments are going to be
1500*daaffb31Sdp	# arguments to 'putback -n'.
1501*daaffb31Sdp	#
1502*daaffb31Sdp	l)	lflag=1
1503*daaffb31Sdp		break;;
1504*daaffb31Sdp
1505*daaffb31Sdp	w)	wflag=1;;
1506*daaffb31Sdp
1507*daaffb31Sdp	O)	Oflag=1;;
1508*daaffb31Sdp
1509*daaffb31Sdp	?)	usage;;
1510*daaffb31Sdp	esac
1511*daaffb31Sdpdone
1512*daaffb31Sdp
1513*daaffb31SdpFLIST=/tmp/$$.flist
1514*daaffb31Sdp
1515*daaffb31Sdpif [[ -n $wflag && -n $lflag ]]; then
1516*daaffb31Sdp	usage
1517*daaffb31Sdpfi
1518*daaffb31Sdp
1519*daaffb31Sdp#
1520*daaffb31Sdp# If this manually set as the parent, and it appears to be an earlier webrev,
1521*daaffb31Sdp# then note that fact and set the parent to the raw_files/new subdirectory.
1522*daaffb31Sdp#
1523*daaffb31Sdpif [[ -n $pflag && -d $codemgr_parent/raw_files/new ]]; then
1524*daaffb31Sdp	parent_webrev="$codemgr_parent"
1525*daaffb31Sdp	codemgr_parent="$codemgr_parent/raw_files/new"
1526*daaffb31Sdpfi
1527*daaffb31Sdp
1528*daaffb31Sdpif [[ -z $wflag && -z $lflag ]]; then
1529*daaffb31Sdp	shift $(($OPTIND - 1))
1530*daaffb31Sdp
1531*daaffb31Sdp	if [[ $1 == "-" ]]; then
1532*daaffb31Sdp		cat > $FLIST
1533*daaffb31Sdp	elif [[ -n $1 ]]; then
1534*daaffb31Sdp		if [[ -r $1 ]]; then
1535*daaffb31Sdp			print -u2 "$1: no such file or not readable"
1536*daaffb31Sdp			usage
1537*daaffb31Sdp		fi
1538*daaffb31Sdp		cat $1 > $FLIST
1539*daaffb31Sdp	else
1540*daaffb31Sdp		flist_autodetect=1
1541*daaffb31Sdp	fi
1542*daaffb31Sdpfi
1543*daaffb31Sdp
1544*daaffb31Sdp#
1545*daaffb31Sdp# Before we go on to further consider -l and -w, work out which SCM we think
1546*daaffb31Sdp# is in use.
1547*daaffb31Sdp#
1548*daaffb31SdpSCM_MODE=`detect_scm $FLIST`
1549*daaffb31Sdpif [[ $SCM_MODE == "unknown" ]]; then
1550*daaffb31Sdp	print -u2 "Unable to determine SCM type currently in use."
1551*daaffb31Sdp	print -u2 "For teamware: webrev looks for \$CODEMGR_WS either in"
1552*daaffb31Sdp	print -u2 "              the environment or in the file list."
15537c478bd9Sstevel@tonic-gate	exit 1
15547c478bd9Sstevel@tonic-gatefi
15557c478bd9Sstevel@tonic-gate
1556*daaffb31Sdpprint -u2 "   SCM detected: $SCM_MODE"
1557*daaffb31Sdp
1558*daaffb31Sdpif [[ -n $lflag ]]; then
1559*daaffb31Sdp	#
1560*daaffb31Sdp	# If the -l flag is given instead of the name of a file list,
1561*daaffb31Sdp	# then generate the file list by extracting file names from a
1562*daaffb31Sdp	# putback -n.
1563*daaffb31Sdp	#
1564*daaffb31Sdp	shift $(($OPTIND - 1))
1565*daaffb31Sdp	flist_from_teamware "$*"
1566*daaffb31Sdp	flist_done=1
1567*daaffb31Sdp	shift $#
1568*daaffb31Sdp
1569*daaffb31Sdpelif [[ -n $wflag ]]; then
1570*daaffb31Sdp	#
1571*daaffb31Sdp	# If the -w is given then assume the file list is in Bonwick's "wx"
1572*daaffb31Sdp	# command format, i.e.  pathname lines alternating with SCCS comment
1573*daaffb31Sdp	# lines with blank lines as separators.  Use the SCCS comments later
1574*daaffb31Sdp	# in building the index.html file.
1575*daaffb31Sdp	#
1576*daaffb31Sdp	shift $(($OPTIND - 1))
1577*daaffb31Sdp	wxfile=$1
1578*daaffb31Sdp	if [[ -z $wxfile && -n $CODEMGR_WS ]]; then
1579*daaffb31Sdp		if [[ -r $CODEMGR_WS/wx/active ]]; then
1580*daaffb31Sdp			wxfile=$CODEMGR_WS/wx/active
1581*daaffb31Sdp		fi
1582*daaffb31Sdp	fi
1583*daaffb31Sdp
1584*daaffb31Sdp	[[ -z $wxfile ]] && print -u2 "wx file not specified, and could not " \
1585*daaffb31Sdp	    "be auto-detected (check \$CODEMGR_WS)" && exit 1
1586*daaffb31Sdp
1587*daaffb31Sdp	print -u2 " File list from: wx 'active' file '$wxfile' ... \c"
1588*daaffb31Sdp	flist_from_wx $wxfile
1589*daaffb31Sdp	flist_done=1
1590*daaffb31Sdp	if [[ -n "$*" ]]; then
1591*daaffb31Sdp		shift
1592*daaffb31Sdp	fi
1593*daaffb31Sdpfi
1594*daaffb31Sdp
1595*daaffb31Sdpif [[ $# -gt 0 ]]; then
1596*daaffb31Sdp	print -u2 "Warning: unused arguments: $*"
1597*daaffb31Sdpfi
1598*daaffb31Sdp
1599*daaffb31Sdpif [[ $SCM_MODE == "teamware" ]]; then
1600*daaffb31Sdp	#
1601*daaffb31Sdp	# Parent (internally $codemgr_parent) and workspace ($codemgr_ws) can
1602*daaffb31Sdp	# be set in a number of ways, in decreasing precedence:
1603*daaffb31Sdp	#
1604*daaffb31Sdp	#      1) on the command line (only for the parent)
1605*daaffb31Sdp	#      2) in the user environment
1606*daaffb31Sdp	#      3) in the flist
1607*daaffb31Sdp	#      4) automatically based on the workspace (only for the parent)
1608*daaffb31Sdp	#
1609*daaffb31Sdp
1610*daaffb31Sdp	#
1611*daaffb31Sdp	# Here is case (2): the user environment
1612*daaffb31Sdp	#
1613*daaffb31Sdp	[[ -z $codemgr_ws && -n $CODEMGR_WS ]] && codemgr_ws=$CODEMGR_WS
1614*daaffb31Sdp	if [[ -n $codemgr_ws && ! -d $codemgr_ws ]]; then
1615*daaffb31Sdp		print -u2 "$codemgr_ws: no such workspace"
16167c478bd9Sstevel@tonic-gate		exit 1
16177c478bd9Sstevel@tonic-gate	fi
16187c478bd9Sstevel@tonic-gate
1619*daaffb31Sdp	[[ -z $codemgr_parent && -n $CODEMGR_PARENT ]] && \
1620*daaffb31Sdp	    codemgr_parent=$CODEMGR_PARENT
1621*daaffb31Sdp	if [[ -n $codemgr_parent && ! -d $codemgr_parent ]]; then
1622*daaffb31Sdp		print -u2 "$codemgr_parent: no such directory"
16237c478bd9Sstevel@tonic-gate		exit 1
16247c478bd9Sstevel@tonic-gate	fi
16257c478bd9Sstevel@tonic-gate
1626*daaffb31Sdp	#
1627*daaffb31Sdp	# If we're in auto-detect mode and we haven't already gotten the file
1628*daaffb31Sdp	# list, then see if we can get it by probing for wx.
1629*daaffb31Sdp	#
1630*daaffb31Sdp	if [[ -z $flist_done && -n $flist_autodetect && -n $codemgr_ws ]]; then
1631*daaffb31Sdp		if [[ -z $WX ]]; then
1632*daaffb31Sdp			WX=`whence wx`
1633*daaffb31Sdp			if [[ -z $WX ]]; then
1634*daaffb31Sdp				if [[ -x /opt/onbld/bin/wx ]]; then
1635*daaffb31Sdp					WDIFF=/opt/onbld/bin/wx
1636*daaffb31Sdp				elif [[ -x /ws/onnv-gate/public/bin/wx ]]; then
1637*daaffb31Sdp					WDIFF=/ws/onnv-gate/public/bin/wx
1638*daaffb31Sdp				else
1639*daaffb31Sdp					print -u2 "Warning: wx not found!"
1640*daaffb31Sdp				fi
1641*daaffb31Sdp			fi
1642*daaffb31Sdp		fi
16437c478bd9Sstevel@tonic-gate
1644*daaffb31Sdp		#
1645*daaffb31Sdp		# We need to use wx list -w so that we get renamed files, etc.
1646*daaffb31Sdp		# but only if a wx active file exists-- otherwise wx will
1647*daaffb31Sdp		# hang asking us to initialize our wx information.
1648*daaffb31Sdp		#
1649*daaffb31Sdp		if [[ -n $WX && -f $codemgr_ws/wx/active ]]; then
1650*daaffb31Sdp			print -u2 " File list from: 'wx list -w' ... \c"
1651*daaffb31Sdp			$WX list -w > $FLIST
1652*daaffb31Sdp			$WX comments > /tmp/$$.wx_comments
1653*daaffb31Sdp			wxfile=/tmp/$$.wx_comments
1654*daaffb31Sdp			print -u2 "done"
1655*daaffb31Sdp			flist_done=1
1656*daaffb31Sdp		fi
1657*daaffb31Sdp	fi
1658*daaffb31Sdp
1659*daaffb31Sdp	#
1660*daaffb31Sdp	# If by hook or by crook we've gotten a file list by now (perhaps
1661*daaffb31Sdp	# from the command line), eval it to extract environment variables from
1662*daaffb31Sdp	# it: This is step (3).
1663*daaffb31Sdp	#
1664*daaffb31Sdp	env_from_flist
1665*daaffb31Sdp
1666*daaffb31Sdp	#
1667*daaffb31Sdp	# Continuing step (3): If we still have no file list, we'll try to get
1668*daaffb31Sdp	# it from teamware.
1669*daaffb31Sdp	#
1670*daaffb31Sdp	if [[ -z $flist_done ]]; then
1671*daaffb31Sdp		flist_from_teamware
1672*daaffb31Sdp		env_from_flist
1673*daaffb31Sdp	fi
1674*daaffb31Sdp
1675*daaffb31Sdp	#
1676*daaffb31Sdp	# Observe true directory name of CODEMGR_WS, as used later in
1677*daaffb31Sdp	# webrev title.
1678*daaffb31Sdp	#
1679*daaffb31Sdp	codemgr_ws=$(cd $codemgr_ws;print $PWD)
1680*daaffb31Sdp
1681*daaffb31Sdp	#
1682*daaffb31Sdp	# (4) If we still don't have a value for codemgr_parent, get it
1683*daaffb31Sdp	# from workspace.
1684*daaffb31Sdp	#
1685*daaffb31Sdp	[[ -z $codemgr_parent ]] && codemgr_parent=`workspace parent`
1686*daaffb31Sdp	if [[ ! -d $codemgr_parent ]]; then
1687*daaffb31Sdp		print -u2 "$CODEMGR_PARENT: no such parent workspace"
1688*daaffb31Sdp		exit 1
1689*daaffb31Sdp	fi
1690*daaffb31Sdp
1691*daaffb31Sdp	#
1692*daaffb31Sdp	# Reset CODEMGR_WS to make sure teamware commands are happy.
1693*daaffb31Sdp	#
1694*daaffb31Sdp	CODEMGR_WS=$codemgr_ws
1695*daaffb31Sdp	CWS=$codemgr_ws
1696*daaffb31Sdp	PWS=$codemgr_parent
1697*daaffb31Sdpfi
1698*daaffb31Sdp
1699*daaffb31Sdp#
1700*daaffb31Sdp# If the user didn't specify a -i option, check to see if there is a
1701*daaffb31Sdp# webrev-info file in the workspace directory.
1702*daaffb31Sdp#
1703*daaffb31Sdpif [[ -z $iflag && -r "$CWS/webrev-info" ]]; then
1704*daaffb31Sdp	iflag=1
1705*daaffb31Sdp	INCLUDE_FILE="$CWS/webrev-info"
1706*daaffb31Sdpfi
1707*daaffb31Sdp
1708*daaffb31Sdpif [[ -n $iflag ]]; then
1709*daaffb31Sdp	if [[ ! -r $INCLUDE_FILE ]]; then
1710*daaffb31Sdp		print -u2 "include file '$INCLUDE_FILE' does not exist or is" \
1711*daaffb31Sdp		    "not readable."
1712*daaffb31Sdp		exit 1
1713*daaffb31Sdp	else
1714*daaffb31Sdp		#
1715*daaffb31Sdp		# $INCLUDE_FILE may be a relative path, and the script alters
1716*daaffb31Sdp		# PWD, so we just stash a copy in /tmp.
1717*daaffb31Sdp		#
1718*daaffb31Sdp		cp $INCLUDE_FILE /tmp/$$.include
1719*daaffb31Sdp	fi
1720*daaffb31Sdpfi
1721*daaffb31Sdp
1722*daaffb31Sdp#
1723*daaffb31Sdp# Output directory.
1724*daaffb31Sdp#
1725*daaffb31SdpWDIR=${WDIR:-$CWS/webrev}
1726*daaffb31Sdp
1727*daaffb31Sdp#
1728*daaffb31Sdp# Name of the webrev, derived from the workspace name; in the
1729*daaffb31Sdp# future this could potentially be an option.
1730*daaffb31Sdp#
1731*daaffb31SdpWNAME=${CWS##*/}
1732*daaffb31Sdp
17337c478bd9Sstevel@tonic-gateif [ ${WDIR%%/*} ]; then
17347c478bd9Sstevel@tonic-gate	WDIR=$PWD/$WDIR
17357c478bd9Sstevel@tonic-gatefi
1736*daaffb31Sdp
1737*daaffb31Sdpif [[ ! -d $WDIR ]]; then
1738*daaffb31Sdp	mkdir -p $WDIR
1739*daaffb31Sdp	[[ $? != 0 ]] && exit 1
17407c478bd9Sstevel@tonic-gatefi
17417c478bd9Sstevel@tonic-gate
1742*daaffb31Sdp#
1743*daaffb31Sdp# Summarize what we're going to do.
1744*daaffb31Sdp#
1745*daaffb31Sdpprint "      Workspace: $CWS"
1746*daaffb31Sdpif [[ -n $parent_webrev ]]; then
1747*daaffb31Sdp	print "Compare against: webrev at $parent_webrev"
1748*daaffb31Sdpelse
1749*daaffb31Sdp	print "Compare against: $PWS"
1750*daaffb31Sdpfi
1751*daaffb31Sdp
1752*daaffb31Sdp[[ -n $INCLUDE_FILE ]] && print "      Including: $INCLUDE_FILE"
1753*daaffb31Sdpprint "      Output to: $WDIR"
1754*daaffb31Sdp
1755*daaffb31Sdp#
17567c478bd9Sstevel@tonic-gate# Save the file list in the webrev dir
1757*daaffb31Sdp#
1758*daaffb31Sdp[[ ! $FLIST -ef $WDIR/file.list ]] && cp $FLIST $WDIR/file.list
17597c478bd9Sstevel@tonic-gate
1760*daaffb31Sdp#
1761*daaffb31Sdp#    Bug IDs will be replaced by a URL.  Order of precedence
1762*daaffb31Sdp#    is: default location, $WEBREV_BUGURL, the -O flag.
1763*daaffb31Sdp#
1764*daaffb31SdpBUGURL='http://monaco.sfbay.sun.com/detail.jsp?cr='
1765*daaffb31Sdp[[ -n $WEBREV_BUGURL ]] && BUGURL="$WEBREV_BUGURL"
1766*daaffb31Sdp[[ -n "$Oflag" ]] && \
1767*daaffb31Sdp    BUGURL='http://bugs.opensolaris.org/bugdatabase/view_bug.do?bug_id='
17687c478bd9Sstevel@tonic-gate
1769*daaffb31Sdp#
1770*daaffb31Sdp#    Likewise, ARC cases will be replaced by a URL.  Order of precedence
1771*daaffb31Sdp#    is: default, $WEBREV_SACURL, the -O flag.
1772*daaffb31Sdp#
1773*daaffb31Sdp#    Note that -O also triggers different substitution behavior for
1774*daaffb31Sdp#    SACURL.  See sac2url().
1775*daaffb31Sdp#
1776*daaffb31SdpSACURL='http://sac.eng.sun.com'
1777*daaffb31Sdp[[ -n $WEBREV_SACURL ]] && SACURL="$WEBREV_SACURL"
1778*daaffb31Sdp[[ -n $Oflag ]] && \
1779*daaffb31Sdp    SACURL='http://www.opensolaris.org/os/community/arc/caselog'
17807c478bd9Sstevel@tonic-gate
1781*daaffb31Sdprm -f $WDIR/$WNAME.patch
1782*daaffb31Sdprm -f $WDIR/$WNAME.ps
1783*daaffb31Sdprm -f $WDIR/$WNAME.pdf
17847c478bd9Sstevel@tonic-gate
1785*daaffb31Sdptouch $WDIR/$WNAME.patch
1786*daaffb31Sdptouch $WDIR/$WNAME.ps
17877c478bd9Sstevel@tonic-gate
1788*daaffb31Sdpprint "   Output Files:"
1789*daaffb31Sdp
1790*daaffb31Sdp#
1791*daaffb31Sdp# Clean up the file list: Remove comments, blank lines and env variables.
1792*daaffb31Sdp#
1793*daaffb31Sdpsed -e "s/#.*$//" -e "/=/d" -e "/^[   ]*$/d" $FLIST > /tmp/$$.flist.clean
1794*daaffb31SdpFLIST=/tmp/$$.flist.clean
1795*daaffb31Sdp
1796*daaffb31Sdp#
1797*daaffb31Sdp# First pass through the files: generate the per-file webrev HTML-files.
1798*daaffb31Sdp#
1799*daaffb31Sdpcat $FLIST | while read LINE
18007c478bd9Sstevel@tonic-gatedo
18017c478bd9Sstevel@tonic-gate	set - $LINE
18027c478bd9Sstevel@tonic-gate	P=$1
18037c478bd9Sstevel@tonic-gate
1804*daaffb31Sdp	#
1805*daaffb31Sdp	# Normally, each line in the file list is just a pathname of a
1806*daaffb31Sdp	# file that has been modified or created in the child.  A file
1807*daaffb31Sdp	# that is renamed in the child workspace has two names on the
1808*daaffb31Sdp	# line: new name followed by the old name.
1809*daaffb31Sdp	#
1810*daaffb31Sdp	oldname=""
1811*daaffb31Sdp	oldpath=""
1812*daaffb31Sdp	rename=
1813*daaffb31Sdp	if [[ $# -eq 2 ]]; then
18147c478bd9Sstevel@tonic-gate		PP=$2			# old filename
1815*daaffb31Sdp		oldname=" (was $PP)"
1816*daaffb31Sdp		oldpath="$PP"
1817*daaffb31Sdp		rename=1
18187c478bd9Sstevel@tonic-gate        	PDIR=${PP%/*}
1819*daaffb31Sdp        	if [[ $PDIR == $PP ]]; then
18207c478bd9Sstevel@tonic-gate			PDIR="."   # File at root of workspace
18217c478bd9Sstevel@tonic-gate		fi
18227c478bd9Sstevel@tonic-gate
18237c478bd9Sstevel@tonic-gate		PF=${PP##*/}
18247c478bd9Sstevel@tonic-gate
18257c478bd9Sstevel@tonic-gate	        DIR=${P%/*}
1826*daaffb31Sdp	        if [[ $DIR == $P ]]; then
18277c478bd9Sstevel@tonic-gate			DIR="."   # File at root of workspace
18287c478bd9Sstevel@tonic-gate		fi
18297c478bd9Sstevel@tonic-gate
18307c478bd9Sstevel@tonic-gate		F=${P##*/}
1831*daaffb31Sdp
18327c478bd9Sstevel@tonic-gate        else
18337c478bd9Sstevel@tonic-gate	        DIR=${P%/*}
1834*daaffb31Sdp	        if [[ "$DIR" == "$P" ]]; then
18357c478bd9Sstevel@tonic-gate			DIR="."   # File at root of workspace
18367c478bd9Sstevel@tonic-gate		fi
18377c478bd9Sstevel@tonic-gate
18387c478bd9Sstevel@tonic-gate		F=${P##*/}
18397c478bd9Sstevel@tonic-gate
18407c478bd9Sstevel@tonic-gate		PP=$P
18417c478bd9Sstevel@tonic-gate		PDIR=$DIR
18427c478bd9Sstevel@tonic-gate		PF=$F
18437c478bd9Sstevel@tonic-gate	fi
18447c478bd9Sstevel@tonic-gate
1845*daaffb31Sdp	COMM=`getcomments html $P $PP`
18467c478bd9Sstevel@tonic-gate
1847*daaffb31Sdp	if [[ ! -d $CWS/$DIR ]]; then
1848*daaffb31Sdp		print "  $CWS/$DIR: no such directory"
18497c478bd9Sstevel@tonic-gate		continue
18507c478bd9Sstevel@tonic-gate	fi
18517c478bd9Sstevel@tonic-gate
1852*daaffb31Sdp	print "\t$P$oldname\n\t\t\c"
18537c478bd9Sstevel@tonic-gate
18547c478bd9Sstevel@tonic-gate	# Make the webrev mirror directory if necessary
18557c478bd9Sstevel@tonic-gate	mkdir -p $WDIR/$DIR
18567c478bd9Sstevel@tonic-gate
18577c478bd9Sstevel@tonic-gate	# cd to the directory so the names are short
18587c478bd9Sstevel@tonic-gate	cd $CWS/$DIR
18597c478bd9Sstevel@tonic-gate
1860*daaffb31Sdp	#
1861*daaffb31Sdp	# If we're in OpenSolaris mode, we enforce a minor policy:
1862*daaffb31Sdp	# help to make sure the reviewer doesn't accidentally publish
1863*daaffb31Sdp	# source which is in usr/closed/*
1864*daaffb31Sdp	#
1865*daaffb31Sdp	if [[ -n $Oflag ]]; then
1866*daaffb31Sdp		pclosed=${P##usr/closed/}
1867*daaffb31Sdp		if [[ $pclosed != $P ]]; then
1868*daaffb31Sdp			print "*** Omitting closed source for OpenSolaris" \
1869*daaffb31Sdp			    "mode review"
1870*daaffb31Sdp			continue
1871*daaffb31Sdp		fi
1872*daaffb31Sdp	fi
1873*daaffb31Sdp
1874*daaffb31Sdp	#
1875*daaffb31Sdp	# We stash old and new files into parallel directories in /tmp
1876*daaffb31Sdp	# and do our diffs there.  This makes it possible to generate
1877*daaffb31Sdp	# clean looking diffs which don't have absolute paths present.
1878*daaffb31Sdp	#
1879*daaffb31Sdp	olddir=$WDIR/raw_files/old
1880*daaffb31Sdp	newdir=$WDIR/raw_files/new
1881*daaffb31Sdp	mkdir -p $olddir
1882*daaffb31Sdp	mkdir -p $newdir
1883*daaffb31Sdp	mkdir -p $olddir/$PDIR
1884*daaffb31Sdp	mkdir -p $newdir/$DIR
1885*daaffb31Sdp
1886*daaffb31Sdp	if [[ $SCM_MODE == "teamware" ]]; then
18877c478bd9Sstevel@tonic-gate		# If the child's version doesn't exist then
18887c478bd9Sstevel@tonic-gate		# get a readonly copy.
18897c478bd9Sstevel@tonic-gate
1890*daaffb31Sdp		if [[ ! -f $F && -f SCCS/s.$F ]]; then
18917c478bd9Sstevel@tonic-gate			sccs get -s $F
18927c478bd9Sstevel@tonic-gate		fi
18937c478bd9Sstevel@tonic-gate
1894*daaffb31Sdp		#
1895*daaffb31Sdp		# Snag new version of file.
1896*daaffb31Sdp		#
1897*daaffb31Sdp		rm -f $newdir/$DIR/$F
1898*daaffb31Sdp		cp $F $newdir/$DIR/$F
18997c478bd9Sstevel@tonic-gate
1900*daaffb31Sdp		#
1901*daaffb31Sdp		# Get the parent's version of the file. First see whether the
1902*daaffb31Sdp		# child's version is checked out and get the parent's version
1903*daaffb31Sdp		# with keywords expanded or unexpanded as appropriate.
1904*daaffb31Sdp		#
1905*daaffb31Sdp		if [ -f $PWS/$PDIR/SCCS/s.$PF -o \
1906*daaffb31Sdp		    -f $PWS/$PDIR/SCCS/p.$PF ]; then
1907*daaffb31Sdp			rm -f $olddir/$PDIR/$PF
19087c478bd9Sstevel@tonic-gate			if [ -f SCCS/p.$F ]; then
1909*daaffb31Sdp				sccs get -s -p -k $PWS/$PDIR/$PF \
1910*daaffb31Sdp				    > $olddir/$PDIR/$PF
19117c478bd9Sstevel@tonic-gate			else
1912*daaffb31Sdp				sccs get -s -p    $PWS/$PDIR/$PF \
1913*daaffb31Sdp				    > $olddir/$PDIR/$PF
19147c478bd9Sstevel@tonic-gate			fi
19157c478bd9Sstevel@tonic-gate		else
1916*daaffb31Sdp			if [[ -f $PWS/$PDIR/$PF ]]; then
19177c478bd9Sstevel@tonic-gate				# Parent is not a real workspace, but just a raw
19187c478bd9Sstevel@tonic-gate				# directory tree - use the file that's there as
19197c478bd9Sstevel@tonic-gate				# the old file.
19207c478bd9Sstevel@tonic-gate
1921*daaffb31Sdp				rm -f $olddir/$DIR/$F
1922*daaffb31Sdp				cp $PWS/$PDIR/$PF $olddir/$DIR/$F
1923*daaffb31Sdp			fi
19247c478bd9Sstevel@tonic-gate		fi
19257c478bd9Sstevel@tonic-gate	fi
19267c478bd9Sstevel@tonic-gate
1927*daaffb31Sdp	if [[ ! -f $F && ! -f $olddir/$DIR/$F ]]; then
1928*daaffb31Sdp		print "*** Error: file not in parent or child"
19297c478bd9Sstevel@tonic-gate		continue
19307c478bd9Sstevel@tonic-gate	fi
19317c478bd9Sstevel@tonic-gate
1932*daaffb31Sdp	cd $WDIR/raw_files
1933*daaffb31Sdp	ofile=old/$PDIR/$PF
1934*daaffb31Sdp	nfile=new/$DIR/$F
19357c478bd9Sstevel@tonic-gate
1936*daaffb31Sdp	mv_but_nodiff=
1937*daaffb31Sdp	cmp $ofile $nfile > /dev/null 2>&1
1938*daaffb31Sdp	if [[ $? == 0 && $rename == 1 ]]; then
1939*daaffb31Sdp		mv_but_nodiff=1
1940*daaffb31Sdp	fi
1941*daaffb31Sdp
1942*daaffb31Sdp	#
1943*daaffb31Sdp	# If we have old and new versions of the file then run the appropriate
1944*daaffb31Sdp	# diffs.  This is complicated by a couple of factors:
1945*daaffb31Sdp	#
1946*daaffb31Sdp	#	- renames must be handled specially: we emit a 'remove'
1947*daaffb31Sdp	#	  diff and an 'add' diff
1948*daaffb31Sdp	#	- new files and deleted files must be handled specially
1949*daaffb31Sdp	#	- Solaris patch(1m) can't cope with file creation
1950*daaffb31Sdp	#	  (and hence renames) as of this writing.
1951*daaffb31Sdp	#       - To make matters worse, gnu patch doesn't interpret the
1952*daaffb31Sdp	#	  output of Solaris diff properly when it comes to
1953*daaffb31Sdp	#	  adds and deletes.  We need to do some "cleansing"
1954*daaffb31Sdp	#         transformations:
1955*daaffb31Sdp	# 	    [to add a file] @@ -1,0 +X,Y @@  -->  @@ -0,0 +X,Y @@
1956*daaffb31Sdp	#	    [to del a file] @@ -X,Y +1,0 @@  -->  @@ -X,Y +0,0 @@
1957*daaffb31Sdp	#
1958*daaffb31Sdp	cleanse_rmfile="sed 's/^\(@@ [0-9+,-]*\) [0-9+,-]* @@$/\1 +0,0 @@/'"
1959*daaffb31Sdp	cleanse_newfile="sed 's/^@@ [0-9+,-]* \([0-9+,-]* @@\)$/@@ -0,0 \1/'"
1960*daaffb31Sdp
1961*daaffb31Sdp	rm -f $WDIR/$DIR/$F.patch
1962*daaffb31Sdp	if [[ -z $rename ]]; then
1963*daaffb31Sdp		if [ ! -f $ofile ]; then
1964*daaffb31Sdp			diff -u /dev/null $nfile | sh -c "$cleanse_newfile" \
1965*daaffb31Sdp			    > $WDIR/$DIR/$F.patch
1966*daaffb31Sdp		elif [ ! -f $nfile ]; then
1967*daaffb31Sdp			diff -u $ofile /dev/null | sh -c "$cleanse_rmfile" \
1968*daaffb31Sdp			    > $WDIR/$DIR/$F.patch
1969*daaffb31Sdp		else
1970*daaffb31Sdp			diff -u $ofile $nfile > $WDIR/$DIR/$F.patch
1971*daaffb31Sdp		fi
1972*daaffb31Sdp	else
1973*daaffb31Sdp		diff -u $ofile /dev/null | sh -c "$cleanse_rmfile" \
1974*daaffb31Sdp		    > $WDIR/$DIR/$F.patch
1975*daaffb31Sdp
1976*daaffb31Sdp		diff -u /dev/null $nfile | sh -c "$cleanse_newfile" \
1977*daaffb31Sdp		    >> $WDIR/$DIR/$F.patch
1978*daaffb31Sdp
1979*daaffb31Sdp	fi
1980*daaffb31Sdp
1981*daaffb31Sdp	#
1982*daaffb31Sdp	# Tack the patch we just made onto the accumulated patch for the
1983*daaffb31Sdp	# whole wad.
1984*daaffb31Sdp	#
1985*daaffb31Sdp	cat $WDIR/$DIR/$F.patch >> $WDIR/$WNAME.patch
1986*daaffb31Sdp
1987*daaffb31Sdp	print " patch\c"
1988*daaffb31Sdp
1989*daaffb31Sdp	if [[ -f $ofile && -f $nfile && -z $mv_but_nodiff ]]; then
1990*daaffb31Sdp
1991*daaffb31Sdp		${CDIFFCMD:-diff -bt -C 5} $ofile $nfile > $WDIR/$DIR/$F.cdiff
1992*daaffb31Sdp		diff_to_html $F $DIR/$F "C" "$COMM" < $WDIR/$DIR/$F.cdiff \
1993*daaffb31Sdp		    > $WDIR/$DIR/$F.cdiff.html
19947c478bd9Sstevel@tonic-gate		print " cdiffs\c"
19957c478bd9Sstevel@tonic-gate
1996*daaffb31Sdp		${UDIFFCMD:-diff -bt -U 5} $ofile $nfile > $WDIR/$DIR/$F.udiff
1997*daaffb31Sdp		diff_to_html $F $DIR/$F "U" "$COMM" < $WDIR/$DIR/$F.udiff \
1998*daaffb31Sdp		    > $WDIR/$DIR/$F.udiff.html
1999*daaffb31Sdp
20007c478bd9Sstevel@tonic-gate		print " udiffs\c"
20017c478bd9Sstevel@tonic-gate
20027c478bd9Sstevel@tonic-gate		if [[ -x $WDIFF ]]; then
2003*daaffb31Sdp			$WDIFF -c "$COMM" \
2004*daaffb31Sdp			    -t "$WNAME Wdiff $DIR/$F" $ofile $nfile > \
2005*daaffb31Sdp			    $WDIR/$DIR/$F.wdiff.html 2>/dev/null
2006*daaffb31Sdp			if [[ $? -eq 0 ]]; then
20077c478bd9Sstevel@tonic-gate				print " wdiffs\c"
2008*daaffb31Sdp			else
2009*daaffb31Sdp				print " wdiffs[fail]\c"
2010*daaffb31Sdp			fi
20117c478bd9Sstevel@tonic-gate		fi
20127c478bd9Sstevel@tonic-gate
2013*daaffb31Sdp		sdiff_to_html $ofile $nfile $F $DIR "$COMM" \
2014*daaffb31Sdp		    > $WDIR/$DIR/$F.sdiff.html
20157c478bd9Sstevel@tonic-gate		print " sdiffs\c"
20167c478bd9Sstevel@tonic-gate
20177c478bd9Sstevel@tonic-gate		print " frames\c"
20187c478bd9Sstevel@tonic-gate
20197c478bd9Sstevel@tonic-gate		rm -f $WDIR/$DIR/$F.cdiff $WDIR/$DIR/$F.udiff
20207c478bd9Sstevel@tonic-gate
2021*daaffb31Sdp		difflines $ofile $nfile > $WDIR/$DIR/$F.count
2022*daaffb31Sdp
2023*daaffb31Sdp	elif [[ -f $ofile && -f $nfile && -n $mv_but_nodiff ]]; then
2024*daaffb31Sdp		# renamed file: may also have differences
2025*daaffb31Sdp		difflines $ofile $nfile > $WDIR/$DIR/$F.count
2026*daaffb31Sdp	elif [[ -f $nfile ]]; then
20277c478bd9Sstevel@tonic-gate		# new file: count added lines
2028*daaffb31Sdp		difflines /dev/null $nfile > $WDIR/$DIR/$F.count
2029*daaffb31Sdp	elif [[ -f $ofile ]]; then
20307c478bd9Sstevel@tonic-gate		# old file: count deleted lines
2031*daaffb31Sdp		difflines $ofile /dev/null > $WDIR/$DIR/$F.count
20327c478bd9Sstevel@tonic-gate	fi
20337c478bd9Sstevel@tonic-gate
2034*daaffb31Sdp	#
2035*daaffb31Sdp	# Now we generate the postscript for this file.  We generate diffs
2036*daaffb31Sdp	# only in the event that there is delta, or the file is new (it seems
2037*daaffb31Sdp	# tree-killing to print out the contents of deleted files).
2038*daaffb31Sdp	#
2039*daaffb31Sdp	if [[ -f $nfile ]]; then
2040*daaffb31Sdp		ocr=$ofile
2041*daaffb31Sdp		[[ ! -f $ofile ]] && ocr=/dev/null
2042*daaffb31Sdp
2043*daaffb31Sdp		if [[ -z $mv_but_nodiff ]]; then
2044*daaffb31Sdp			textcomm=`getcomments text $P $PP`
2045*daaffb31Sdp			codereview -y "$textcomm" \
2046*daaffb31Sdp			    -e $ocr $nfile >> $WDIR/$WNAME.ps  # 2>/dev/null
2047*daaffb31Sdp			if [[ $? -eq 0 ]]; then
2048*daaffb31Sdp				print " ps\c"
2049*daaffb31Sdp			else
2050*daaffb31Sdp				print " ps[fail]\c"
2051*daaffb31Sdp			fi
2052*daaffb31Sdp		fi
2053*daaffb31Sdp	fi
2054*daaffb31Sdp
2055*daaffb31Sdp	if [[ -f $ofile && -z $mv_but_nodiff ]]; then
2056*daaffb31Sdp		source_to_html Old $P < $ofile > $WDIR/$DIR/$F-.html
20577c478bd9Sstevel@tonic-gate		print " old\c"
20587c478bd9Sstevel@tonic-gate	fi
20597c478bd9Sstevel@tonic-gate
2060*daaffb31Sdp	if [[ -f $nfile ]]; then
2061*daaffb31Sdp		source_to_html New $P < $nfile > $WDIR/$DIR/$F.html
20627c478bd9Sstevel@tonic-gate		print " new\c"
20637c478bd9Sstevel@tonic-gate	fi
20647c478bd9Sstevel@tonic-gate
2065*daaffb31Sdp	print
20667c478bd9Sstevel@tonic-gatedone
20677c478bd9Sstevel@tonic-gate
2068*daaffb31Sdpframe_nav_js > $WDIR/ancnav.js
20697c478bd9Sstevel@tonic-gateframe_navigation > $WDIR/ancnav.html
2070*daaffb31Sdp
2071*daaffb31Sdpprint " ${B}Generating PDF: ${NB}\c"
2072*daaffb31Sdpfix_postscript $WDIR/$WNAME.ps | ps2pdf - > $WDIR/$WNAME.pdf
2073*daaffb31Sdprm -f $WDIR/$WNAME.ps
2074*daaffb31Sdpprint "Done."
20757c478bd9Sstevel@tonic-gate
20767c478bd9Sstevel@tonic-gate# Now build the index.html file that contains
20777c478bd9Sstevel@tonic-gate# links to the source files and their diffs.
20787c478bd9Sstevel@tonic-gate
20797c478bd9Sstevel@tonic-gatecd $CWS
20807c478bd9Sstevel@tonic-gate
20817c478bd9Sstevel@tonic-gate# Save total changed lines for Code Inspection.
2082*daaffb31Sdpprint "$TOTL" > $WDIR/TotalChangedLines
20837c478bd9Sstevel@tonic-gate
2084*daaffb31Sdpprint "     index.html: \c"
20857c478bd9Sstevel@tonic-gateINDEXFILE=$WDIR/index.html
20867c478bd9Sstevel@tonic-gateexec 3<&1			# duplicate stdout to FD3.
20877c478bd9Sstevel@tonic-gateexec 1<&-			# Close stdout.
20887c478bd9Sstevel@tonic-gateexec > $INDEXFILE		# Open stdout to index file.
20897c478bd9Sstevel@tonic-gate
2090*daaffb31Sdpprint "$HTML<head>$STDHEAD"
2091*daaffb31Sdpprint "<title>$WNAME</title>"
2092*daaffb31Sdpprint "</head>"
2093*daaffb31Sdpprint "<body id=\"SUNWwebrev\">"
2094*daaffb31Sdpprint "<div class=\"summary\">"
2095*daaffb31Sdpprint "<h2>Code Review for $WNAME</h2>"
20967c478bd9Sstevel@tonic-gate
2097*daaffb31Sdpprint "<table>"
20987c478bd9Sstevel@tonic-gate
2099*daaffb31Sdp#
2100*daaffb31Sdp# Figure out the username and gcos name.  To maintain compatibility
2101*daaffb31Sdp# with passwd(4), we must support '&' substitutions.
2102*daaffb31Sdp#
2103*daaffb31Sdpusername=`id | cut -d '(' -f 2 | cut -d ')' -f 1`
2104*daaffb31Sdprealname=`getent passwd $username | cut -d':' -f 5`
2105*daaffb31Sdpuserupper=`perl -e "print ucfirst $username"`
2106*daaffb31Sdprealname=`print $realname | sed s/\&/$userupper/`
2107*daaffb31Sdpdate="on `date`"
21087c478bd9Sstevel@tonic-gate
2109*daaffb31Sdpif [[ -n "$username" && -n "$realname" ]]; then
2110*daaffb31Sdp	print "<tr><th>Prepared by:</th>"
2111*daaffb31Sdp	print "<td>$realname ($username) $date</td></tr>"
2112*daaffb31Sdpelif [[ -n "$username" ]]; then
2113*daaffb31Sdp	print "<tr><th>Prepared by:</th><td>$username $date</td></tr>"
2114*daaffb31Sdpfi
2115*daaffb31Sdp
2116*daaffb31Sdpprint "<tr><th>Workspace:</th><td>$CWS</td></tr>"
2117*daaffb31Sdpprint "<tr><th>Compare against:</th><td>"
2118*daaffb31Sdpif [[ -n $parent_webrev ]]; then
2119*daaffb31Sdp	print "webrev at $parent_webrev"
2120*daaffb31Sdpelse
2121*daaffb31Sdp	print "$PWS"
2122*daaffb31Sdpfi
2123*daaffb31Sdpprint "</td></tr>"
2124*daaffb31Sdpprint "<tr><th>Summary of changes:</th><td>"
2125*daaffb31SdpprintCI $TOTL $TINS $TDEL $TMOD $TUNC
2126*daaffb31Sdpprint "</td></tr>"
2127*daaffb31Sdp
2128*daaffb31Sdpif [[ -f $WDIR/$WNAME.patch ]]; then
2129*daaffb31Sdp	print "<tr><th>Patch of changes:</th><td>"
2130*daaffb31Sdp	print "<a href=\"$WNAME.patch\">$WNAME.patch</a></td></tr>"
2131*daaffb31Sdpfi
2132*daaffb31Sdpif [[ -f $WDIR/$WNAME.pdf ]]; then
2133*daaffb31Sdp	print "<tr><th>Printable review:</th><td>"
2134*daaffb31Sdp	print "<a href=\"$WNAME.pdf\">$WNAME.pdf</a></td></tr>"
2135*daaffb31Sdpfi
2136*daaffb31Sdp
2137*daaffb31Sdpif [[ -n "$iflag" ]]; then
2138*daaffb31Sdp	print "<tr><th>Author comments:</th><td><div>"
2139*daaffb31Sdp	cat /tmp/$$.include
2140*daaffb31Sdp	print "</div></td></tr>"
2141*daaffb31Sdpfi
2142*daaffb31Sdpprint "</table>"
2143*daaffb31Sdpprint "</div>"
2144*daaffb31Sdp
2145*daaffb31Sdp
2146*daaffb31Sdp#
2147*daaffb31Sdp# Second pass through the files: generate the rest of the index file
2148*daaffb31Sdp#
2149*daaffb31Sdpcat $FLIST | while read LINE
21507c478bd9Sstevel@tonic-gatedo
21517c478bd9Sstevel@tonic-gate	set - $LINE
21527c478bd9Sstevel@tonic-gate	P=$1
21537c478bd9Sstevel@tonic-gate
2154*daaffb31Sdp	if [[ $# == 2 ]]; then
21557c478bd9Sstevel@tonic-gate		PP=$2
2156*daaffb31Sdp		oldname=" <i>(was $PP)</i>"
2157*daaffb31Sdp
21587c478bd9Sstevel@tonic-gate	else
21597c478bd9Sstevel@tonic-gate		PP=$P
2160*daaffb31Sdp		oldname=""
2161*daaffb31Sdp	fi
2162*daaffb31Sdp
2163*daaffb31Sdp	DIR=${P%/*}
2164*daaffb31Sdp	if [[ $DIR == $P ]]; then
2165*daaffb31Sdp		DIR="."   # File at root of workspace
21667c478bd9Sstevel@tonic-gate	fi
21677c478bd9Sstevel@tonic-gate
21687c478bd9Sstevel@tonic-gate	# Avoid processing the same file twice.
21697c478bd9Sstevel@tonic-gate	# It's possible for renamed files to
21707c478bd9Sstevel@tonic-gate	# appear twice in the file list
21717c478bd9Sstevel@tonic-gate
21727c478bd9Sstevel@tonic-gate	F=$WDIR/$P
21737c478bd9Sstevel@tonic-gate
2174*daaffb31Sdp	print "<p>"
21757c478bd9Sstevel@tonic-gate
21767c478bd9Sstevel@tonic-gate	# If there's a diffs file, make diffs links
21777c478bd9Sstevel@tonic-gate
2178*daaffb31Sdp	if [[ -f $F.cdiff.html ]]; then
2179*daaffb31Sdp		print "<a href=\"$P.cdiff.html\">Cdiffs</a>"
2180*daaffb31Sdp		print "<a href=\"$P.udiff.html\">Udiffs</a>"
21817c478bd9Sstevel@tonic-gate
2182*daaffb31Sdp		if [[ -f $F.wdiff.html && -x $WDIFF ]]; then
2183*daaffb31Sdp			print "<a href=\"$P.wdiff.html\">Wdiffs</a>"
21847c478bd9Sstevel@tonic-gate		fi
21857c478bd9Sstevel@tonic-gate
2186*daaffb31Sdp		print "<a href=\"$P.sdiff.html\">Sdiffs</a>"
21877c478bd9Sstevel@tonic-gate
21887c478bd9Sstevel@tonic-gate		print "<a href=\"$P.frames.html\">Frames</a>"
21897c478bd9Sstevel@tonic-gate	else
2190*daaffb31Sdp		print " ------ ------ ------"
21917c478bd9Sstevel@tonic-gate
2192*daaffb31Sdp		if [[ -x $WDIFF ]]; then
21937c478bd9Sstevel@tonic-gate			print " ------"
21947c478bd9Sstevel@tonic-gate		fi
2195*daaffb31Sdp
2196*daaffb31Sdp		print " ------"
21977c478bd9Sstevel@tonic-gate	fi
21987c478bd9Sstevel@tonic-gate
21997c478bd9Sstevel@tonic-gate	# If there's an old file, make the link
22007c478bd9Sstevel@tonic-gate
2201*daaffb31Sdp	if [[ -f $F-.html ]]; then
2202*daaffb31Sdp		print "<a href=\"$P-.html\">Old</a>"
22037c478bd9Sstevel@tonic-gate	else
2204*daaffb31Sdp		print " ---"
22057c478bd9Sstevel@tonic-gate	fi
22067c478bd9Sstevel@tonic-gate
22077c478bd9Sstevel@tonic-gate	# If there's an new file, make the link
22087c478bd9Sstevel@tonic-gate
2209*daaffb31Sdp	if [[ -f $F.html ]]; then
2210*daaffb31Sdp		print "<a href=\"$P.html\">New</a>"
22117c478bd9Sstevel@tonic-gate	else
2212*daaffb31Sdp		print " ---"
22137c478bd9Sstevel@tonic-gate	fi
22147c478bd9Sstevel@tonic-gate
2215*daaffb31Sdp	if [[ -f $F.patch ]]; then
2216*daaffb31Sdp		print "<a href=\"$P.patch\">Patch</a>"
2217*daaffb31Sdp	else
2218*daaffb31Sdp		print " -----"
2219*daaffb31Sdp	fi
2220*daaffb31Sdp
2221*daaffb31Sdp	if [[ -f $WDIR/raw_files/new/$P ]]; then
2222*daaffb31Sdp		print "<a href=\"raw_files/new/$P\">Raw</a>"
2223*daaffb31Sdp	else
2224*daaffb31Sdp		print " ---"
2225*daaffb31Sdp	fi
2226*daaffb31Sdp
2227*daaffb31Sdp	print "<b>$P</b> $oldname"
2228*daaffb31Sdp
2229*daaffb31Sdp	#
2230*daaffb31Sdp	# Check for usr/closed
2231*daaffb31Sdp	#
2232*daaffb31Sdp	if [ ! -z "$Oflag" ]; then
2233*daaffb31Sdp		if [[ $P == usr/closed/* ]]; then
2234*daaffb31Sdp			print "&nbsp;&nbsp;<i>Closed source: omitted from" \
2235*daaffb31Sdp			    "this review</i>"
2236*daaffb31Sdp		fi
2237*daaffb31Sdp	fi
2238*daaffb31Sdp
2239*daaffb31Sdp	print "</p>"
22407c478bd9Sstevel@tonic-gate	# Insert delta comments
22417c478bd9Sstevel@tonic-gate
2242*daaffb31Sdp	print "<blockquote><pre>"
2243*daaffb31Sdp	getcomments html $P $PP
2244*daaffb31Sdp	print "</pre>"
22457c478bd9Sstevel@tonic-gate
22467c478bd9Sstevel@tonic-gate	# Add additional comments comment
22477c478bd9Sstevel@tonic-gate
2248*daaffb31Sdp	print "<!-- Add comments to explain changes in $P here -->"
22497c478bd9Sstevel@tonic-gate
22507c478bd9Sstevel@tonic-gate	# Add count of changes.
22517c478bd9Sstevel@tonic-gate
2252*daaffb31Sdp	if [[ -f $F.count ]]; then
22537c478bd9Sstevel@tonic-gate	    cat $F.count
22547c478bd9Sstevel@tonic-gate	    rm $F.count
22557c478bd9Sstevel@tonic-gate	fi
2256*daaffb31Sdp	print "</blockquote>"
22577c478bd9Sstevel@tonic-gatedone
22587c478bd9Sstevel@tonic-gate
2259*daaffb31Sdpprint
2260*daaffb31Sdpprint
2261*daaffb31Sdpprint "<hr />"
2262*daaffb31Sdpprint "<p style=\"font-size: small\">"
2263*daaffb31Sdpprint "This code review page was prepared using <b>$0</b>"
2264*daaffb31Sdpprint "(vers $WEBREV_UPDATED)."
2265*daaffb31Sdpprint "Webrev is maintained by the <a href=\"http://www.opensolaris.org\">"
2266*daaffb31Sdpprint "OpenSolaris</a> project.  The latest version may be obtained"
2267*daaffb31Sdpprint "<a href=\"http://cvs.opensolaris.org/source/xref/on/usr/src/tools/scripts/webrev.sh\">here</a>.</p>"
2268*daaffb31Sdpprint "</body>"
2269*daaffb31Sdpprint "</html>"
22707c478bd9Sstevel@tonic-gate
22717c478bd9Sstevel@tonic-gateexec 1<&-			# Close FD 1.
22727c478bd9Sstevel@tonic-gateexec 1<&3			# dup FD 3 to restore stdout.
22737c478bd9Sstevel@tonic-gateexec 3<&-			# close FD 3.
22747c478bd9Sstevel@tonic-gate
2275*daaffb31Sdpprint "Done."
2276