]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/groff/contrib/gdiffmk/gdiffmk.sh
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / groff / contrib / gdiffmk / gdiffmk.sh
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
24 cmd=$( basename $0 )
25
26 function Usage {
27         if test "$#" -gt 0
28         then
29                 echo >&2 "${cmd}:  $@"
30         fi
31         echo >&2 "\
32
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.
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
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: \`*'.
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
65 function 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.
80 function 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.
102 function 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
120 function 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
135 ADDMARK='+'
136 CHANGEMARK='|'
137 DELETEMARK='*'
138 MARK1='[['
139 MARK2=']]'
140
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
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
160 badoption=
161 DIFFCMD=diff
162 D_option=
163 br=.br
164 for OPTION
165 do
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
222 done
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.
227 Use GNU diff instead.  See the \`-x DIFFCMD' option."
228
229 if test -n "${badoption}"
230 then
231         Usage "${badoption}"
232 fi
233
234 if test "$#" -lt 2  -o  "$#" -gt 3
235 then
236         Usage "Incorrect number of arguments."
237 fi
238
239 if test "1$1" = 1-  -a  "2$2" = 2-
240 then
241         Usage "Both FILE1 and FILE2 are \`-'."
242 fi
243
244 FILE1=$1
245 FILE2=$2
246
247 FileRead 1 "${FILE1}"
248 FileRead 2 "${FILE2}"
249
250 if test "$#" = 3
251 then
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
265 fi
266
267 #       To make a very unlikely label even more unlikely ...
268 label=__diffmk_$$__
269
270 sed_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
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/
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         '
341 fi
342
343 diff -D"${label}" -- ${FILE1} ${FILE2}  |
344         sed -n "${sed_script}"
345
346 # EOF