1*7c478bd9Sstevel@tonic-gate#!/usr/bin/perl 2*7c478bd9Sstevel@tonic-gate# 3*7c478bd9Sstevel@tonic-gate# CDDL HEADER START 4*7c478bd9Sstevel@tonic-gate# 5*7c478bd9Sstevel@tonic-gate# The contents of this file are subject to the terms of the 6*7c478bd9Sstevel@tonic-gate# Common Development and Distribution License, Version 1.0 only 7*7c478bd9Sstevel@tonic-gate# (the "License"). You may not use this file except in compliance 8*7c478bd9Sstevel@tonic-gate# with the License. 9*7c478bd9Sstevel@tonic-gate# 10*7c478bd9Sstevel@tonic-gate# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 11*7c478bd9Sstevel@tonic-gate# or http://www.opensolaris.org/os/licensing. 12*7c478bd9Sstevel@tonic-gate# See the License for the specific language governing permissions 13*7c478bd9Sstevel@tonic-gate# and limitations under the License. 14*7c478bd9Sstevel@tonic-gate# 15*7c478bd9Sstevel@tonic-gate# When distributing Covered Code, include this CDDL HEADER in each 16*7c478bd9Sstevel@tonic-gate# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 17*7c478bd9Sstevel@tonic-gate# If applicable, add the following below this CDDL HEADER, with the 18*7c478bd9Sstevel@tonic-gate# fields enclosed by brackets "[]" replaced with your own identifying 19*7c478bd9Sstevel@tonic-gate# information: Portions Copyright [yyyy] [name of copyright owner] 20*7c478bd9Sstevel@tonic-gate# 21*7c478bd9Sstevel@tonic-gate# CDDL HEADER END 22*7c478bd9Sstevel@tonic-gate# 23*7c478bd9Sstevel@tonic-gate# 24*7c478bd9Sstevel@tonic-gate# ident "%Z%%M% %I% %E% SMI" 25*7c478bd9Sstevel@tonic-gate# 26*7c478bd9Sstevel@tonic-gate# Copyright 2004 Sun Microsystems, Inc. All rights reserved. 27*7c478bd9Sstevel@tonic-gate# Use is subject to license terms. 28*7c478bd9Sstevel@tonic-gate# 29*7c478bd9Sstevel@tonic-gate# Make a dynamic HTML page for the unified diffs between two (C) files. 30*7c478bd9Sstevel@tonic-gate# 31*7c478bd9Sstevel@tonic-gate 32*7c478bd9Sstevel@tonic-gateuse Getopt::Std; 33*7c478bd9Sstevel@tonic-gate 34*7c478bd9Sstevel@tonic-gate$diffword = "wdiff"; 35*7c478bd9Sstevel@tonic-gate$context = 10; 36*7c478bd9Sstevel@tonic-gate 37*7c478bd9Sstevel@tonic-gategetopt('t'); 38*7c478bd9Sstevel@tonic-gate 39*7c478bd9Sstevel@tonic-gateif ($#ARGV + 1 == 1) { 40*7c478bd9Sstevel@tonic-gate $diffword = $ARGV[0]; 41*7c478bd9Sstevel@tonic-gate open DIFF, "<&STDIN"; 42*7c478bd9Sstevel@tonic-gate $ARGV[0] = '-'; 43*7c478bd9Sstevel@tonic-gate $ARGV[1] = '-'; 44*7c478bd9Sstevel@tonic-gate} elsif ($#ARGV + 1 == 2) { 45*7c478bd9Sstevel@tonic-gate open DIFF, "diff -D $diffword $ARGV[0] $ARGV[1] | expand |"; 46*7c478bd9Sstevel@tonic-gate} else { 47*7c478bd9Sstevel@tonic-gate print "Usage: $0 [-t title] file1 file2\n"; 48*7c478bd9Sstevel@tonic-gate exit 2; 49*7c478bd9Sstevel@tonic-gate} 50*7c478bd9Sstevel@tonic-gate 51*7c478bd9Sstevel@tonic-gate$title = $opt_t ? $opt_t : "Differences between $ARGV[0] and $ARGV[1]"; 52*7c478bd9Sstevel@tonic-gate 53*7c478bd9Sstevel@tonic-gate$indiff = 0; 54*7c478bd9Sstevel@tonic-gate$line1 = 0; 55*7c478bd9Sstevel@tonic-gate$line2 = 0; 56*7c478bd9Sstevel@tonic-gate@pretext = (); # Speculative pretext buffer (code) 57*7c478bd9Sstevel@tonic-gate$posttext = 0; # Lines of posttext to print 58*7c478bd9Sstevel@tonic-gate$nelided = 0; # Number of elided chunks 59*7c478bd9Sstevel@tonic-gate$endfunc = 0; # Seen end of function? 60*7c478bd9Sstevel@tonic-gate$inelided = 0; # Elided section open? 61*7c478bd9Sstevel@tonic-gate$elided_lines = 0; 62*7c478bd9Sstevel@tonic-gate 63*7c478bd9Sstevel@tonic-gateprint <<END; 64*7c478bd9Sstevel@tonic-gate<html> 65*7c478bd9Sstevel@tonic-gate <head> 66*7c478bd9Sstevel@tonic-gate <title>$title</title> 67*7c478bd9Sstevel@tonic-gate <style type='text/css'> 68*7c478bd9Sstevel@tonic-gate pre { margin: 0; border: 2px solid white } 69*7c478bd9Sstevel@tonic-gate 70*7c478bd9Sstevel@tonic-gate .subtracted { color: red } 71*7c478bd9Sstevel@tonic-gate .added { color: blue } 72*7c478bd9Sstevel@tonic-gate 73*7c478bd9Sstevel@tonic-gate .elided { border: 2px solid; cursor: n-resize; padding: 1px } 74*7c478bd9Sstevel@tonic-gate 75*7c478bd9Sstevel@tonic-gate .hidebar { background-color: #cccccc; border: 1px solid black; 76*7c478bd9Sstevel@tonic-gate text-align: center; 77*7c478bd9Sstevel@tonic-gate border-collapse: separate; border-spacing: 0px; } 78*7c478bd9Sstevel@tonic-gate 79*7c478bd9Sstevel@tonic-gate .hidebar .active { border: 2px black outset; cursor: n-resize } 80*7c478bd9Sstevel@tonic-gate 81*7c478bd9Sstevel@tonic-gate .cmdbox { position: fixed; top: 0; right: 0; border: solid 1px black; 82*7c478bd9Sstevel@tonic-gate background-color: white; text-align: center } 83*7c478bd9Sstevel@tonic-gate 84*7c478bd9Sstevel@tonic-gate .cmdbox td { border: outset #808080; cursor: default; padding: 3px 4px; } 85*7c478bd9Sstevel@tonic-gate 86*7c478bd9Sstevel@tonic-gate </style> 87*7c478bd9Sstevel@tonic-gate <script> 88*7c478bd9Sstevel@tonic-gate function show_n_hide_dir(id_to_show, id_to_hide, dir) { 89*7c478bd9Sstevel@tonic-gate var elt_to_show = document.getElementById(id_to_show); 90*7c478bd9Sstevel@tonic-gate var elt_to_hide = document.getElementById(id_to_hide); 91*7c478bd9Sstevel@tonic-gate // When we're opening up, we need to make the bottoms of the 92*7c478bd9Sstevel@tonic-gate // elements appear to be the same. So our invariant should be 93*7c478bd9Sstevel@tonic-gate // elt.offsetBottom - window.scrollY. 94*7c478bd9Sstevel@tonic-gate var preinvar = elt_to_hide.offsetHeight - window.scrollY; 95*7c478bd9Sstevel@tonic-gate elt_to_show.style.setProperty('display', '', ''); 96*7c478bd9Sstevel@tonic-gate elt_to_hide.style.setProperty('display', 'none', ''); 97*7c478bd9Sstevel@tonic-gate if (dir == 'up') { 98*7c478bd9Sstevel@tonic-gate var postinvar = elt_to_show.offsetHeight - window.scrollY; 99*7c478bd9Sstevel@tonic-gate window.scrollBy(0, postinvar - preinvar); 100*7c478bd9Sstevel@tonic-gate } 101*7c478bd9Sstevel@tonic-gate } 102*7c478bd9Sstevel@tonic-gate 103*7c478bd9Sstevel@tonic-gate function handle_click(e) { 104*7c478bd9Sstevel@tonic-gate var eh = e.target; 105*7c478bd9Sstevel@tonic-gate var es = document.getElementById("hb-" + e.target.id); 106*7c478bd9Sstevel@tonic-gate eh.style.setProperty('display', 'none', ''); 107*7c478bd9Sstevel@tonic-gate es.style.setProperty('display', '', ''); 108*7c478bd9Sstevel@tonic-gate /* Scroll so new element is at cursor. */ 109*7c478bd9Sstevel@tonic-gate window.scroll(0, es.offsetTop + (es.offsetHeight / 2) 110*7c478bd9Sstevel@tonic-gate - e.clientY); 111*7c478bd9Sstevel@tonic-gate } 112*7c478bd9Sstevel@tonic-gate 113*7c478bd9Sstevel@tonic-gate function stripsearch(str) { 114*7c478bd9Sstevel@tonic-gate q = str.indexOf("?"); 115*7c478bd9Sstevel@tonic-gate if (q != -1) 116*7c478bd9Sstevel@tonic-gate str = str.substr(0, q); 117*7c478bd9Sstevel@tonic-gate return (str); 118*7c478bd9Sstevel@tonic-gate } 119*7c478bd9Sstevel@tonic-gate 120*7c478bd9Sstevel@tonic-gate function split() { 121*7c478bd9Sstevel@tonic-gate page = stripsearch(location.href); 122*7c478bd9Sstevel@tonic-gate halfway = window.scrollY + window.innerHeight / 2 - 5; 123*7c478bd9Sstevel@tonic-gate document.write('<frameset rows="50%,*">' + 124*7c478bd9Sstevel@tonic-gate '<frame src="' + page + "?" + window.scrollY + '" />' + 125*7c478bd9Sstevel@tonic-gate '<frame src="' + page + "?" + halfway + '" />' + 126*7c478bd9Sstevel@tonic-gate '</frameset>'); 127*7c478bd9Sstevel@tonic-gate document.close(); 128*7c478bd9Sstevel@tonic-gate } 129*7c478bd9Sstevel@tonic-gate 130*7c478bd9Sstevel@tonic-gate function closeframe() { 131*7c478bd9Sstevel@tonic-gate page = stripsearch(location.href); 132*7c478bd9Sstevel@tonic-gate 133*7c478bd9Sstevel@tonic-gate otherf = window.parent.frames[0]; 134*7c478bd9Sstevel@tonic-gate if (otherf == window) 135*7c478bd9Sstevel@tonic-gate otherf = window.parent.frames[1]; 136*7c478bd9Sstevel@tonic-gate 137*7c478bd9Sstevel@tonic-gate parent.location.href = page + "?" + otherf.scrollY; 138*7c478bd9Sstevel@tonic-gate } 139*7c478bd9Sstevel@tonic-gate 140*7c478bd9Sstevel@tonic-gate </script> 141*7c478bd9Sstevel@tonic-gate </head> 142*7c478bd9Sstevel@tonic-gate <body> 143*7c478bd9Sstevel@tonic-gate <table class='cmdbox'> 144*7c478bd9Sstevel@tonic-gate <tr> 145*7c478bd9Sstevel@tonic-gate <td onclick='split()'>Split</td> 146*7c478bd9Sstevel@tonic-gate <td id='close' onclick='closeframe()'>Close</td> 147*7c478bd9Sstevel@tonic-gate </tr> 148*7c478bd9Sstevel@tonic-gate <tr><td colspan=2 onclick='open_or_close_all(1)'>Expand all</td></tr> 149*7c478bd9Sstevel@tonic-gate <tr><td colspan=2 onclick='open_or_close_all(0)'>Collapse all</td></tr> 150*7c478bd9Sstevel@tonic-gate </table> 151*7c478bd9Sstevel@tonic-gate <script type='text/javascript'> 152*7c478bd9Sstevel@tonic-gate if (window == top) 153*7c478bd9Sstevel@tonic-gate document.getElementById('close').style.setProperty('display', 'none', ''); 154*7c478bd9Sstevel@tonic-gate </script> 155*7c478bd9Sstevel@tonic-gateEND 156*7c478bd9Sstevel@tonic-gate 157*7c478bd9Sstevel@tonic-gateprint "<pre><span class='subtracted'> --- $ARGV[0] 158*7c478bd9Sstevel@tonic-gate</span><span class='added'> +++ $ARGV[1] 159*7c478bd9Sstevel@tonic-gate</span>"; 160*7c478bd9Sstevel@tonic-gate 161*7c478bd9Sstevel@tonic-gatesub begin_elided { 162*7c478bd9Sstevel@tonic-gate ++$nelided; 163*7c478bd9Sstevel@tonic-gate # onclick handler assigned at bottom 164*7c478bd9Sstevel@tonic-gate print "<pre id='elided$nelided' class='elided' style='display: none'>"; 165*7c478bd9Sstevel@tonic-gate $inelided = 1; 166*7c478bd9Sstevel@tonic-gate $elided_lines = 0; 167*7c478bd9Sstevel@tonic-gate} 168*7c478bd9Sstevel@tonic-gate 169*7c478bd9Sstevel@tonic-gatesub end_elided { 170*7c478bd9Sstevel@tonic-gate print "</pre>\n"; 171*7c478bd9Sstevel@tonic-gate 172*7c478bd9Sstevel@tonic-gate print <<END; 173*7c478bd9Sstevel@tonic-gate<table id='hb-elided$nelided' class='hidebar'> 174*7c478bd9Sstevel@tonic-gate <tr> 175*7c478bd9Sstevel@tonic-gate <td class='active' onclick='show_n_hide_dir("elided$nelided", "hb-elided$nelided", "down")'> 176*7c478bd9Sstevel@tonic-gate Click to open down</td> 177*7c478bd9Sstevel@tonic-gate <td style='width: 5em'>$elided_lines lines</td> 178*7c478bd9Sstevel@tonic-gate <td class='active' onclick='show_n_hide_dir("elided$nelided", "hb-elided$nelided", "up")'> 179*7c478bd9Sstevel@tonic-gate Click to open up</td> 180*7c478bd9Sstevel@tonic-gate </tr> 181*7c478bd9Sstevel@tonic-gate<table> 182*7c478bd9Sstevel@tonic-gateEND 183*7c478bd9Sstevel@tonic-gate $inelided = 0; 184*7c478bd9Sstevel@tonic-gate} 185*7c478bd9Sstevel@tonic-gate 186*7c478bd9Sstevel@tonic-gatewhile (<DIFF>) { 187*7c478bd9Sstevel@tonic-gate chomp; 188*7c478bd9Sstevel@tonic-gate 189*7c478bd9Sstevel@tonic-gate # Change detection 190*7c478bd9Sstevel@tonic-gate $previndiff = $indiff; 191*7c478bd9Sstevel@tonic-gate 192*7c478bd9Sstevel@tonic-gate if (!$indiff) { 193*7c478bd9Sstevel@tonic-gate if (/^#ifdef $diffword$/) { 194*7c478bd9Sstevel@tonic-gate $indiff = 1; 195*7c478bd9Sstevel@tonic-gate } elsif (/^#ifndef $diffword$/) { 196*7c478bd9Sstevel@tonic-gate $indiff = -1; 197*7c478bd9Sstevel@tonic-gate } 198*7c478bd9Sstevel@tonic-gate } else { 199*7c478bd9Sstevel@tonic-gate if (/^#else \/\* $diffword \*\/$/) { 200*7c478bd9Sstevel@tonic-gate $indiff = -$indiff; 201*7c478bd9Sstevel@tonic-gate print "</span>"; 202*7c478bd9Sstevel@tonic-gate printf "<span class='%s'>", 203*7c478bd9Sstevel@tonic-gate ($indiff > 0 ? "added" : "subtracted"); 204*7c478bd9Sstevel@tonic-gate next; 205*7c478bd9Sstevel@tonic-gate } elsif (/^#endif \/\* (! )?$diffword \*\/$/) { 206*7c478bd9Sstevel@tonic-gate $indiff = 0; 207*7c478bd9Sstevel@tonic-gate $posttext = $context; 208*7c478bd9Sstevel@tonic-gate print "</span>"; 209*7c478bd9Sstevel@tonic-gate next; 210*7c478bd9Sstevel@tonic-gate } 211*7c478bd9Sstevel@tonic-gate } 212*7c478bd9Sstevel@tonic-gate 213*7c478bd9Sstevel@tonic-gate if (!$previndiff && $indiff) { 214*7c478bd9Sstevel@tonic-gate # Beginning of a change: If we have an elided section open, 215*7c478bd9Sstevel@tonic-gate # end it. Print the pretext and continue. 216*7c478bd9Sstevel@tonic-gate 217*7c478bd9Sstevel@tonic-gate if ($inelided) { 218*7c478bd9Sstevel@tonic-gate end_elided; 219*7c478bd9Sstevel@tonic-gate print "<pre>"; 220*7c478bd9Sstevel@tonic-gate } 221*7c478bd9Sstevel@tonic-gate 222*7c478bd9Sstevel@tonic-gate print @pretext; 223*7c478bd9Sstevel@tonic-gate @pretext = (); 224*7c478bd9Sstevel@tonic-gate $endfunc = 0; 225*7c478bd9Sstevel@tonic-gate $infunc = -1; 226*7c478bd9Sstevel@tonic-gate 227*7c478bd9Sstevel@tonic-gate printf "<span class='%s'>", 228*7c478bd9Sstevel@tonic-gate ($indiff > 0 ? "added" : "subtracted"); 229*7c478bd9Sstevel@tonic-gate next; 230*7c478bd9Sstevel@tonic-gate } 231*7c478bd9Sstevel@tonic-gate 232*7c478bd9Sstevel@tonic-gate # Line of code 233*7c478bd9Sstevel@tonic-gate 234*7c478bd9Sstevel@tonic-gate # Quote for HTML 235*7c478bd9Sstevel@tonic-gate s/&/&/g; 236*7c478bd9Sstevel@tonic-gate s/</</g; 237*7c478bd9Sstevel@tonic-gate s/>/>/g; 238*7c478bd9Sstevel@tonic-gate 239*7c478bd9Sstevel@tonic-gate # Format the line according to $indiff, and print it or put it into 240*7c478bd9Sstevel@tonic-gate # a buffer. 241*7c478bd9Sstevel@tonic-gate if ($indiff == -1) { 242*7c478bd9Sstevel@tonic-gate ++$line1; 243*7c478bd9Sstevel@tonic-gate printf "%4d %4s -%s\n", $line1, "", $_; 244*7c478bd9Sstevel@tonic-gate } elsif ($indiff == 0) { 245*7c478bd9Sstevel@tonic-gate ++$line1; 246*7c478bd9Sstevel@tonic-gate ++$line2; 247*7c478bd9Sstevel@tonic-gate 248*7c478bd9Sstevel@tonic-gate $str = sprintf "%4d %4d %s\n", $line1, $line2, $_; 249*7c478bd9Sstevel@tonic-gate 250*7c478bd9Sstevel@tonic-gate if ($posttext > 0) { 251*7c478bd9Sstevel@tonic-gate print $str; 252*7c478bd9Sstevel@tonic-gate --$posttext; 253*7c478bd9Sstevel@tonic-gate } else { 254*7c478bd9Sstevel@tonic-gate push @pretext, $str; 255*7c478bd9Sstevel@tonic-gate if ($#pretext + 1 > $context) { 256*7c478bd9Sstevel@tonic-gate $str = shift @pretext; 257*7c478bd9Sstevel@tonic-gate 258*7c478bd9Sstevel@tonic-gate if (!$inelided) { 259*7c478bd9Sstevel@tonic-gate print "</pre>\n"; 260*7c478bd9Sstevel@tonic-gate begin_elided; 261*7c478bd9Sstevel@tonic-gate } 262*7c478bd9Sstevel@tonic-gate 263*7c478bd9Sstevel@tonic-gate ++$elided_lines; 264*7c478bd9Sstevel@tonic-gate 265*7c478bd9Sstevel@tonic-gate print $str; 266*7c478bd9Sstevel@tonic-gate } 267*7c478bd9Sstevel@tonic-gate } 268*7c478bd9Sstevel@tonic-gate } elsif ($indiff == 1) { 269*7c478bd9Sstevel@tonic-gate ++$line2; 270*7c478bd9Sstevel@tonic-gate printf "%4s %4d +%s\n", "", $line2, $_; 271*7c478bd9Sstevel@tonic-gate } 272*7c478bd9Sstevel@tonic-gate} 273*7c478bd9Sstevel@tonic-gate 274*7c478bd9Sstevel@tonic-gateprint @pretext; 275*7c478bd9Sstevel@tonic-gate 276*7c478bd9Sstevel@tonic-gateif ($inelided) { 277*7c478bd9Sstevel@tonic-gate $elided_lines += @pretext; 278*7c478bd9Sstevel@tonic-gate end_elided; 279*7c478bd9Sstevel@tonic-gate} else { 280*7c478bd9Sstevel@tonic-gate print " </pre>\n"; 281*7c478bd9Sstevel@tonic-gate} 282*7c478bd9Sstevel@tonic-gate 283*7c478bd9Sstevel@tonic-gateprint "<pre id='linerefpre'><span id='lineref'>", ' ' x (4 + 1 + 4 + 2 + 80), 284*7c478bd9Sstevel@tonic-gate "</span></pre>\n"; 285*7c478bd9Sstevel@tonic-gate 286*7c478bd9Sstevel@tonic-gateprint <<END; 287*7c478bd9Sstevel@tonic-gate <script> 288*7c478bd9Sstevel@tonic-gate /* Assign event handlers and widths. */ 289*7c478bd9Sstevel@tonic-gate var w = document.getElementById('lineref').offsetWidth; 290*7c478bd9Sstevel@tonic-gate for (var i = 1; i <= $nelided; ++i) { 291*7c478bd9Sstevel@tonic-gate var e = document.getElementById("elided" + i); 292*7c478bd9Sstevel@tonic-gate e.onclick = handle_click; 293*7c478bd9Sstevel@tonic-gate e.style.setProperty('width', w, ''); 294*7c478bd9Sstevel@tonic-gate 295*7c478bd9Sstevel@tonic-gate e = document.getElementById("hb-elided" + i); 296*7c478bd9Sstevel@tonic-gate e.style.setProperty('width', w, ''); 297*7c478bd9Sstevel@tonic-gate } 298*7c478bd9Sstevel@tonic-gate 299*7c478bd9Sstevel@tonic-gate /* Hide our line size reference. */ 300*7c478bd9Sstevel@tonic-gate document.getElementById('linerefpre').style.setProperty('display', 'none', ''); 301*7c478bd9Sstevel@tonic-gate 302*7c478bd9Sstevel@tonic-gate /* Scroll as indicated. */ 303*7c478bd9Sstevel@tonic-gate str = location.search; 304*7c478bd9Sstevel@tonic-gate s = str.substring(1, str.length); 305*7c478bd9Sstevel@tonic-gate if (s > 0) 306*7c478bd9Sstevel@tonic-gate window.scroll(0, s); 307*7c478bd9Sstevel@tonic-gate 308*7c478bd9Sstevel@tonic-gate function open_or_close_all(open) { 309*7c478bd9Sstevel@tonic-gate for (var i = 1; i <= $nelided; ++i) { 310*7c478bd9Sstevel@tonic-gate var e = document.getElementById("hb-elided" + i); 311*7c478bd9Sstevel@tonic-gate e.style.setProperty("display", open ? "none" : "", ""); 312*7c478bd9Sstevel@tonic-gate 313*7c478bd9Sstevel@tonic-gate e = document.getElementById("elided" + i); 314*7c478bd9Sstevel@tonic-gate e.style.setProperty("display", open ? "" : "none", ""); 315*7c478bd9Sstevel@tonic-gate } 316*7c478bd9Sstevel@tonic-gate } 317*7c478bd9Sstevel@tonic-gate </script> 318*7c478bd9Sstevel@tonic-gate </body> 319*7c478bd9Sstevel@tonic-gate</html> 320*7c478bd9Sstevel@tonic-gateEND 321