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