* All affected files: Update postal address of FSF.
[s-roff.git] / contrib / gdiffmk / gdiffmk.sh
blobe55eb6962019d613fcc798469613e8873b03efb8
1 #! /bin/sh
2 # Copyright (C) 2004, 2005 Free Software Foundation, Inc.
3 # Written by Mike Bianchi <MBianchi@Foveal.com <mailto:MBianchi@Foveal.com>>
5 # This file is part of the gdiffmk utility, which is part of groff.
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.
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.
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.
24 cmd=$( basename $0 )
26 function Usage {
27 if test "$#" -gt 0
28 then
29 echo >&2 "${cmd}: $@"
31 echo >&2 "\
33 Usage: ${cmd} [ OPTIONS ] FILE1 FILE2 [ OUTPUT ]
34 Place difference marks into the new version of a groff/nroff/troff document.
35 FILE1 and FILE2 are compared, using \`diff', and FILE2 is output with
36 groff \`.mc' requests added to indicate how it is different from FILE1.
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).
44 OPTIONS:
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: \`*'.
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.
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.
61 exit 255
65 function Exit {
66 exitcode=$1
67 shift
68 for arg
70 echo >&2 "${cmd}: $1"
71 shift
72 done
73 exit ${exitcode}
76 # Usage: FileRead exit_code filename
78 # Check for existence and readability of given file name.
79 # If not found or not readable, print message and exit with EXIT_CODE.
80 function FileRead {
81 case "$2" in
83 return
85 esac
87 if test ! -e "$2"
88 then
89 Exit $1 "File \`$2' not found."
91 if test ! -r "$2"
92 then
93 Exit $1 "File \`$2' not readable."
98 # Usage: FileCreate exit_code filename
100 # Create the given filename if it doesn't exist.
101 # If unable to create or write, print message and exit with EXIT_CODE.
102 function FileCreate {
103 case "$2" in
105 return
107 esac
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" )'."
116 Exit $1 "File \`$2' not writeable."
120 function WouldClobber {
121 case "$2" in
123 return
125 esac
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."
135 ADDMARK='+'
136 CHANGEMARK='|'
137 DELETEMARK='*'
138 MARK1='[['
139 MARK2=']]'
141 function RequiresArgument {
142 # Process flags that take either concatenated or
143 # separated values.
144 case "$1" in
145 -??*)
146 expr "$1" : '-.\(.*\)'
147 return 1
149 esac
151 if test "$#" -lt 2
152 then
153 Exit 255 "Option \`$1' requires a value."
156 echo "$2"
157 return 0
160 badoption=
161 DIFFCMD=diff
162 D_option=
163 br=.br
164 for OPTION
166 case "${OPTION}" in
167 -a*)
168 ADDMARK=$( RequiresArgument "${OPTION}" $2 ) &&
169 shift
171 -c*)
172 CHANGEMARK=$( RequiresArgument "${OPTION}" $2 ) &&
173 shift
175 -d*)
176 DELETEMARK=$( RequiresArgument "${OPTION}" $2 ) &&
177 shift
179 -D )
180 D_option=D_option
182 -M* )
183 MARK1=$( RequiresArgument "${OPTION}" $2 ) &&
184 shift
185 if [ $# -lt 2 ]
186 then
187 Usage "Option \`-M' is missing the MARK2 value."
189 MARK2=$2
190 shift
192 -B )
193 br=.
195 -x* )
196 DIFFCMD=$( RequiresArgument "${OPTION}" $2 ) &&
197 shift
199 --version)
200 echo "GNU ${cmd} (groff) version @VERSION@"
201 exit 0
203 --help)
204 Usage
207 # What follows -- are file arguments
208 shift
209 break
212 break
215 badoption="${cmd}: invalid option \`$1'"
218 break
220 esac
221 shift
222 done
224 ${DIFFCMD} -Dx /dev/null /dev/null >/dev/null 2>&1 ||
225 Usage "The \`${DIFFCMD}' program does not accept" \
226 "the required \`-Dname' option.
227 Use GNU diff instead. See the \`-x DIFFCMD' option."
229 if test -n "${badoption}"
230 then
231 Usage "${badoption}"
234 if test "$#" -lt 2 -o "$#" -gt 3
235 then
236 Usage "Incorrect number of arguments."
239 if test "1$1" = 1- -a "2$2" = 2-
240 then
241 Usage "Both FILE1 and FILE2 are \`-'."
244 FILE1=$1
245 FILE2=$2
247 FileRead 1 "${FILE1}"
248 FileRead 2 "${FILE2}"
250 if test "$#" = 3
251 then
252 case "$3" in
254 # output goes to standard output
257 # output goes to a file
258 WouldClobber "${FILE1}" FILE1 "$3"
259 WouldClobber "${FILE2}" FILE2 "$3"
261 FileCreate 3 "$3"
262 exec >$3
264 esac
267 # To make a very unlikely label even more unlikely ...
268 label=__diffmk_$$__
270 sed_script='
271 /^#ifdef '"${label}"'/,/^#endif \/\* '"${label}"'/ {
272 /^#ifdef '"${label}"'/ s/.*/.mc '"${ADDMARK}"'/
273 /^#endif \/\* '"${label}"'/ s/.*/.mc/
277 /^#ifndef '"${label}"'/,/^#endif \/\* [!not ]*'"${label}"'/ {
278 /^#else \/\* '"${label}"'/,/^#endif \/\* '"${label}"'/ {
279 /^#else \/\* '"${label}"'/ s/.*/.mc '"${CHANGEMARK}"'/
280 /^#endif \/\* '"${label}"'/ s/.*/.mc/
284 /^#endif \/\* \(not\|!\) '"${label}"'/ {
285 s/.*/.mc '"${DELETEMARK}"'/p
294 if [ ${D_option} ]
295 then
296 sed_script='
297 /^#ifdef '"${label}"'/,/^#endif \/\* '"${label}"'/ {
298 /^#ifdef '"${label}"'/ s/.*/.mc '"${ADDMARK}"'/
299 /^#endif \/\* '"${label}"'/ s/.*/.mc/
303 /^#ifndef '"${label}"'/,/^#endif \/\* [!not ]*'"${label}"'/ {
304 /^#ifndef '"${label}"'/ {
306 '"${MARK1}"'
309 /^#else \/\* '"${label}"'/ ! {
310 /^#endif \/\* [!not ]*'"${label}"'/ ! {
315 /^#else \/\* '"${label}"'/,/^#endif \/\* '"${label}"'/ {
316 /^#else \/\* '"${label}"'/ {
318 '"${MARK2}"'\
319 '"${br}"'
320 s/.*/.mc '"${CHANGEMARK}"'/
322 .mc '"${CHANGEMARK}"'
325 /^#endif \/\* '"${label}"'/ s/.*/.mc/
329 /^#endif \/\* \(not\|!\) '"${label}"'/ {
331 '"${MARK2}"'\
332 '"${br}"'
333 s/.*/.mc '"${DELETEMARK}"'/p
343 diff -D"${label}" -- ${FILE1} ${FILE2} |
344 sed -n "${sed_script}"
346 # EOF