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/&/\&/g" -e "s/</\</g" -e "s/>/\>/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 " <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