/contrib/groff/contrib/gdiffmk/gdiffmk.sh

https://bitbucket.org/freebsd/freebsd-head/ · Shell · 346 lines · 295 code · 23 blank · 28 comment · 12 complexity · f2d6d3cc74578d57a176c46db50b6fac MD5 · raw file

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