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