1#! /bin/sh 2# Copyright (C) 2004, 2005 Free Software Foundation, Inc. 3# Written by Mike Bianchi <MBianchi@Foveal.com <mailto:MBianchi@Foveal.com>> 4 5# This file is part of the gdiffmk utility, which is part of groff. 6 7# groff is free software; you can redistribute it and/or modify it 8# under the terms of the GNU General Public License as published by 9# the Free Software Foundation; either version 2, or (at your option) 10# any later version. 11 12# groff is distributed in the hope that it will be useful, but WITHOUT 13# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 14# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 15# License for more details. 16 17# You should have received a copy of the GNU General Public License 18# along with groff; see the files COPYING and LICENSE in the top 19# directory of the groff source. If not, write to the Free Software 20# Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. 21# This file is part of GNU gdiffmk. 22 23 24cmd=$( basename $0 ) 25 26function Usage { 27 if test "$#" -gt 0 28 then 29 echo >&2 "${cmd}: $@" 30 fi 31 echo >&2 "\ 32 33Usage: ${cmd} [ OPTIONS ] FILE1 FILE2 [ OUTPUT ] 34Place difference marks into the new version of a groff/nroff/troff document. 35FILE1 and FILE2 are compared, using \`diff', and FILE2 is output with 36groff \`.mc' requests added to indicate how it is different from FILE1. 37 38 FILE1 Previous version of the groff file. \`-' means standard input. 39 FILE2 Current version of the groff file. \`-' means standard input. 40 Either FILE1 or FILE2 can be standard input, but not both. 41 OUTPUT Copy of FILE2 with \`.mc' commands added. 42 \`-' means standard output (the default). 43 44OPTIONS: 45 -a ADDMARK Mark for added groff source lines. Default: \`+'. 46 -c CHANGEMARK Mark for changed groff source lines. Default: \`|'. 47 -d DELETEMARK Mark for deleted groff source lines. Default: \`*'. 48 49 -D Show the deleted portions from changed and deleted text. 50 Default delimiting marks: \`[[' .... \`]]'. 51 -B By default, the deleted texts marked by the \`-D' option end 52 with an added troff \`.br' command. This option prevents 53 the added \`.br'. 54 -M MARK1 MARK2 Change the delimiting marks for the \`-D' option. 55 56 -x DIFFCMD Use a different diff(1) command; 57 one that accepts the \`-Dname' option, such as GNU diff. 58 --version Print version information on the standard output and exit. 59 --help Print this message on the standard error. 60" 61 exit 255 62} 63 64 65function Exit { 66 exitcode=$1 67 shift 68 for arg 69 do 70 echo >&2 "${cmd}: $1" 71 shift 72 done 73 exit ${exitcode} 74} 75 76# Usage: FileRead exit_code filename 77# 78# Check for existence and readability of given file name. 79# If not found or not readable, print message and exit with EXIT_CODE. 80function FileRead { 81 case "$2" in 82 -) 83 return 84 ;; 85 esac 86 87 if test ! -e "$2" 88 then 89 Exit $1 "File \`$2' not found." 90 fi 91 if test ! -r "$2" 92 then 93 Exit $1 "File \`$2' not readable." 94 fi 95} 96 97 98# Usage: FileCreate exit_code filename 99# 100# Create the given filename if it doesn't exist. 101# If unable to create or write, print message and exit with EXIT_CODE. 102function FileCreate { 103 case "$2" in 104 -) 105 return 106 ;; 107 esac 108 109 if ! touch "$2" 2>/dev/null 110 then 111 if test ! -e "$2" 112 then 113 Exit $1 "File \`$2' not created; " \ 114 "Cannot write directory \`$( dirname "$2" )'." 115 fi 116 Exit $1 "File \`$2' not writeable." 117 fi 118} 119 120function WouldClobber { 121 case "$2" in 122 -) 123 return 124 ;; 125 esac 126 127 if test "$1" -ef "$3" 128 then 129 Exit 3 \ 130 "The $2 and OUTPUT arguments both point to the same file," \ 131 "\`$1', and it would be overwritten." 132 fi 133} 134 135ADDMARK='+' 136CHANGEMARK='|' 137DELETEMARK='*' 138MARK1='[[' 139MARK2=']]' 140 141function RequiresArgument { 142 # Process flags that take either concatenated or 143 # separated values. 144 case "$1" in 145 -??*) 146 expr "$1" : '-.\(.*\)' 147 return 1 148 ;; 149 esac 150 151 if test "$#" -lt 2 152 then 153 Exit 255 "Option \`$1' requires a value." 154 fi 155 156 echo "$2" 157 return 0 158} 159 160badoption= 161DIFFCMD=diff 162D_option= 163br=.br 164for OPTION 165do 166 case "${OPTION}" in 167 -a*) 168 ADDMARK=$( RequiresArgument "${OPTION}" $2 ) && 169 shift 170 ;; 171 -c*) 172 CHANGEMARK=$( RequiresArgument "${OPTION}" $2 ) && 173 shift 174 ;; 175 -d*) 176 DELETEMARK=$( RequiresArgument "${OPTION}" $2 ) && 177 shift 178 ;; 179 -D ) 180 D_option=D_option 181 ;; 182 -M* ) 183 MARK1=$( RequiresArgument "${OPTION}" $2 ) && 184 shift 185 if [ $# -lt 2 ] 186 then 187 Usage "Option \`-M' is missing the MARK2 value." 188 fi 189 MARK2=$2 190 shift 191 ;; 192 -B ) 193 br=. 194 ;; 195 -x* ) 196 DIFFCMD=$( RequiresArgument "${OPTION}" $2 ) && 197 shift 198 ;; 199 --version) 200 echo "GNU ${cmd} (groff) version @VERSION@" 201 exit 0 202 ;; 203 --help) 204 Usage 205 ;; 206 --) 207 # What follows -- are file arguments 208 shift 209 break 210 ;; 211 -) 212 break 213 ;; 214 -*) 215 badoption="${cmd}: invalid option \`$1'" 216 ;; 217 *) 218 break 219 ;; 220 esac 221 shift 222done 223 224${DIFFCMD} -Dx /dev/null /dev/null >/dev/null 2>&1 || 225 Usage "The \`${DIFFCMD}' program does not accept" \ 226 "the required \`-Dname' option. 227Use GNU diff instead. See the \`-x DIFFCMD' option." 228 229if test -n "${badoption}" 230then 231 Usage "${badoption}" 232fi 233 234if test "$#" -lt 2 -o "$#" -gt 3 235then 236 Usage "Incorrect number of arguments." 237fi 238 239if test "1$1" = 1- -a "2$2" = 2- 240then 241 Usage "Both FILE1 and FILE2 are \`-'." 242fi 243 244FILE1=$1 245FILE2=$2 246 247FileRead 1 "${FILE1}" 248FileRead 2 "${FILE2}" 249 250if test "$#" = 3 251then 252 case "$3" in 253 -) 254 # output goes to standard output 255 ;; 256 *) 257 # output goes to a file 258 WouldClobber "${FILE1}" FILE1 "$3" 259 WouldClobber "${FILE2}" FILE2 "$3" 260 261 FileCreate 3 "$3" 262 exec >$3 263 ;; 264 esac 265fi 266 267# To make a very unlikely label even more unlikely ... 268label=__diffmk_$$__ 269 270sed_script=' 271 /^#ifdef '"${label}"'/,/^#endif \/\* '"${label}"'/ { 272 /^#ifdef '"${label}"'/ s/.*/.mc '"${ADDMARK}"'/ 273 /^#endif \/\* '"${label}"'/ s/.*/.mc/ 274 p 275 d 276 } 277 /^#ifndef '"${label}"'/,/^#endif \/\* [!not ]*'"${label}"'/ { 278 /^#else \/\* '"${label}"'/,/^#endif \/\* '"${label}"'/ { 279 /^#else \/\* '"${label}"'/ s/.*/.mc '"${CHANGEMARK}"'/ 280 /^#endif \/\* '"${label}"'/ s/.*/.mc/ 281 p 282 d 283 } 284 /^#endif \/\* \(not\|!\) '"${label}"'/ { 285 s/.*/.mc '"${DELETEMARK}"'/p 286 a\ 287.mc 288 } 289 d 290 } 291 p 292 ' 293 294if [ ${D_option} ] 295then 296 sed_script=' 297 /^#ifdef '"${label}"'/,/^#endif \/\* '"${label}"'/ { 298 /^#ifdef '"${label}"'/ s/.*/.mc '"${ADDMARK}"'/ 299 /^#endif \/\* '"${label}"'/ s/.*/.mc/ 300 p 301 d 302 } 303 /^#ifndef '"${label}"'/,/^#endif \/\* [!not ]*'"${label}"'/ { 304 /^#ifndef '"${label}"'/ { 305 i\ 306'"${MARK1}"' 307 d 308 } 309 /^#else \/\* '"${label}"'/ ! { 310 /^#endif \/\* [!not ]*'"${label}"'/ ! { 311 p 312 d 313 } 314 } 315 /^#else \/\* '"${label}"'/,/^#endif \/\* '"${label}"'/ { 316 /^#else \/\* '"${label}"'/ { 317 i\ 318'"${MARK2}"'\ 319'"${br}"' 320 s/.*/.mc '"${CHANGEMARK}"'/ 321 a\ 322.mc '"${CHANGEMARK}"' 323 d 324 } 325 /^#endif \/\* '"${label}"'/ s/.*/.mc/ 326 p 327 d 328 } 329 /^#endif \/\* \(not\|!\) '"${label}"'/ { 330 i\ 331'"${MARK2}"'\ 332'"${br}"' 333 s/.*/.mc '"${DELETEMARK}"'/p 334 a\ 335.mc 336 } 337 d 338 } 339 p 340 ' 341fi 342 343diff -D"${label}" -- ${FILE1} ${FILE2} | 344 sed -n "${sed_script}" 345 346# EOF 347