Subject: bug#37844: [PATCH] cmp -x/--verbose-hex

From: "[email-masked]" <[email-masked]>
Date: Sun, 20 Oct 2019 16:32:20 -0400

This adds a `-x`/`--verbose-hex` option to `cmp`, similar to what FreeBSD has in
its own `cmp`. From `doc/diffutils.texi`:

'-x'
'--verbose-hex'
     Like '--verbose', but with hexadecimal numbers, and byte numbers
     starting at 0.

A few assorted points:
* `cmp -x` always displays a minimum of eight hex digits, just like FreeBSD's
implementation.
* `offtostr` only does decimal, so it was removed in a few places where
hexadecimal was called for.
* Some of the format strings had `%s` replaced with `%"PRIuMAX"`, in part
because of GCC's new `-Wformat-overflow` feature. These strings are translated,
and because it was a simple fix, I updated the `.po` files.
* For `-x`, I replaced "EOF on FILE after byte 511" to "EOF on FILE at byte
0x200". I think it's a bit more useful this way.
* I believe the Malay (`ms.po`) translation needs a bit of attention at this
spot regarding the printf format string:
```
#: src/cmp.c:592
#, fuzzy, c-format
#| msgid "cmp: EOF on %s\n"
msgid "cmp: EOF on %s after byte %s\n"
msgstr "%s: EOF tidak dijangka selepas membaca %d/%d bins\n"
```

This is a bit more than the 15-or-so lines of code that are "not legally
significant for copyright", so let me know if there's paperwork that needs to be
filled out.

Dave Odell

--- a/bg.po
+++ b/bg.po
@@ -654,18 +654,18 @@ msgstr "cmp: „EOF“ в празния „%s“\n"
 
 #: src/cmp.c:585
 #, c-format
-msgid "cmp: EOF on %s after byte %s, line %s\n"
-msgstr "cmp: „EOF“ в „%s“ след байт %s, ред %s\n"
+msgid "cmp: EOF on %s after byte %<PRIuMAX>, line %<PRIuMAX>\n"
+msgstr "cmp: „EOF“ в „%s“ след байт %<PRIuMAX>, ред %<PRIuMAX>\n"
 
 #: src/cmp.c:586
 #, c-format
-msgid "cmp: EOF on %s after byte %s, in line %s\n"
-msgstr "cmp: „EOF“ в „%s“ след байт %s, на ред %s\n"
+msgid "cmp: EOF on %s after byte %<PRIuMAX>, in line %<PRIuMAX>\n"
+msgstr "cmp: „EOF“ в „%s“ след байт %<PRIuMAX>, на ред %<PRIuMAX>\n"
 
 #: src/cmp.c:592
 #, c-format
-msgid "cmp: EOF on %s after byte %s\n"
-msgstr "cmp: „EOF“ в „%s“ след байт %s\n"
+msgid "cmp: EOF on %s after byte %<PRIuMAX>\n"
+msgstr "cmp: „EOF“ в „%s“ след байт %<PRIuMAX>\n"
 
 #. This is a proper name. See the gettext manual, section Names.
 #: src/diff.c:50
--- a/cs.po
+++ b/cs.po
@@ -649,18 +649,18 @@ msgstr "cmp: konec souboru v %s, který je prázdný\n"
 
 #: src/cmp.c:585
 #, c-format
-msgid "cmp: EOF on %s after byte %s, line %s\n"
-msgstr "cmp: konec souboru v %s po bajtu %s, řádek %s\n"
+msgid "cmp: EOF on %s after byte %<PRIuMAX>, line %<PRIuMAX>\n"
+msgstr "cmp: konec souboru v %s po bajtu %<PRIuMAX>, řádek %<PRIuMAX>\n"
 
 #: src/cmp.c:586
 #, c-format
-msgid "cmp: EOF on %s after byte %s, in line %s\n"
-msgstr "cmp: konec souboru v %s po bajtu %s na řádku %s\n"
+msgid "cmp: EOF on %s after byte %<PRIuMAX>, in line %<PRIuMAX>\n"
+msgstr "cmp: konec souboru v %s po bajtu %<PRIuMAX> na řádku %<PRIuMAX>\n"
 
 #: src/cmp.c:592
 #, c-format
-msgid "cmp: EOF on %s after byte %s\n"
-msgstr "cmp: konec souboru v %s po bajtu %s\n"
+msgid "cmp: EOF on %s after byte %<PRIuMAX>\n"
+msgstr "cmp: konec souboru v %s po bajtu %<PRIuMAX>\n"
 
 #. This is a proper name. See the gettext manual, section Names.
 #: src/diff.c:50
--- a/da.po
+++ b/da.po
@@ -650,18 +650,18 @@ msgstr "cmp: filafslutning på %s som er tom\n"
 
 #: src/cmp.c:585
 #, c-format
-msgid "cmp: EOF on %s after byte %s, line %s\n"
-msgstr "cmp: filafslutning på %s efter byte %s, linje %s\n"
+msgid "cmp: EOF on %s after byte %<PRIuMAX>, line %<PRIuMAX>\n"
+msgstr "cmp: filafslutning på %s efter byte %<PRIuMAX>, linje %<PRIuMAX>\n"
 
 #: src/cmp.c:586
 #, c-format
-msgid "cmp: EOF on %s after byte %s, in line %s\n"
-msgstr "cmp: filafslutning på %s efter byte %s i linje %s\n"
+msgid "cmp: EOF on %s after byte %<PRIuMAX>, in line %<PRIuMAX>\n"
+msgstr "cmp: filafslutning på %s efter byte %<PRIuMAX> i linje %<PRIuMAX>\n"
 
 #: src/cmp.c:592
 #, c-format
-msgid "cmp: EOF on %s after byte %s\n"
-msgstr "cmp: filafslutning på %s efter byte %s\n"
+msgid "cmp: EOF on %s after byte %<PRIuMAX>\n"
+msgstr "cmp: filafslutning på %s efter byte %<PRIuMAX>\n"
 
 #. This is a proper name. See the gettext manual, section Names.
 #: src/diff.c:50
--- a/de.po
+++ b/de.po
@@ -658,18 +658,18 @@ msgstr "cmp: Dateiende in %s, welche leer ist.\n"
 
 #: src/cmp.c:585
 #, c-format
-msgid "cmp: EOF on %s after byte %s, line %s\n"
-msgstr "cmp: Dateiende in %s nach Byte %s, Zeile %s\n"
+msgid "cmp: EOF on %s after byte %<PRIuMAX>, line %<PRIuMAX>\n"
+msgstr "cmp: Dateiende in %s nach Byte %<PRIuMAX>, Zeile %<PRIuMAX>\n"
 
 #: src/cmp.c:586
 #, c-format
-msgid "cmp: EOF on %s after byte %s, in line %s\n"
-msgstr "cmp: Dateiende in %s nach Byte %s, Zeile %s\n"
+msgid "cmp: EOF on %s after byte %<PRIuMAX>, in line %<PRIuMAX>\n"
+msgstr "cmp: Dateiende in %s nach Byte %<PRIuMAX>, Zeile %<PRIuMAX>\n"
 
 #: src/cmp.c:592
 #, c-format
-msgid "cmp: EOF on %s after byte %s\n"
-msgstr "cmp: Dateiende in %s nach Byte %s\n"
+msgid "cmp: EOF on %s after byte %<PRIuMAX>\n"
+msgstr "cmp: Dateiende in %s nach Byte %<PRIuMAX>\n"
 
 #. This is a proper name. See the gettext manual, section Names.
 #: src/diff.c:50
--- a/el.po
+++ b/el.po
@@ -651,18 +651,18 @@ msgstr "cmp: EOF στο %s που είναι κενό\n"
 
 #: src/cmp.c:585
 #, c-format
-msgid "cmp: EOF on %s after byte %s, line %s\n"
-msgstr "cmp: EOF στο %s μετά το byte %s, γραμμή %s\n"
+msgid "cmp: EOF on %s after byte %<PRIuMAX>, line %<PRIuMAX>\n"
+msgstr "cmp: EOF στο %s μετά το byte %<PRIuMAX>, γραμμή %<PRIuMAX>\n"
 
 #: src/cmp.c:586
 #, c-format
-msgid "cmp: EOF on %s after byte %s, in line %s\n"
-msgstr "cmp: EOF στο %s μετά το byte %s, στη γραμμή %s\n"
+msgid "cmp: EOF on %s after byte %<PRIuMAX>, in line %<PRIuMAX>\n"
+msgstr "cmp: EOF στο %s μετά το byte %<PRIuMAX>, στη γραμμή %<PRIuMAX>\n"
 
 #: src/cmp.c:592
 #, c-format
-msgid "cmp: EOF on %s after byte %s\n"
-msgstr "cmp: EOF στο %s μετά το byte %s\n"
+msgid "cmp: EOF on %s after byte %<PRIuMAX>\n"
+msgstr "cmp: EOF στο %s μετά το byte %<PRIuMAX>\n"
 
 #. This is a proper name. See the gettext manual, section Names.
 #: src/diff.c:50
--- a/eo.po
+++ b/eo.po
@@ -648,18 +648,18 @@ msgstr "cmp: EOF ĉe %s, kiu malplenas\n"
 
 #: src/cmp.c:585
 #, c-format
-msgid "cmp: EOF on %s after byte %s, line %s\n"
-msgstr "cmp: EOF ĉe %s post bajto %s, linio %s\n"
+msgid "cmp: EOF on %s after byte %<PRIuMAX>, line %<PRIuMAX>\n"
+msgstr "cmp: EOF ĉe %s post bajto %<PRIuMAX>, linio %<PRIuMAX>\n"
 
 #: src/cmp.c:586
 #, c-format
-msgid "cmp: EOF on %s after byte %s, in line %s\n"
-msgstr "cmp: EOF ĉe %s post bajto %s, en linio %s\n"
+msgid "cmp: EOF on %s after byte %<PRIuMAX>, in line %<PRIuMAX>\n"
+msgstr "cmp: EOF ĉe %s post bajto %<PRIuMAX>, en linio %<PRIuMAX>\n"
 
 #: src/cmp.c:592
 #, c-format
-msgid "cmp: EOF on %s after byte %s\n"
-msgstr "cmp: EOF ĉe %s post bajto %s\n"
+msgid "cmp: EOF on %s after byte %<PRIuMAX>\n"
+msgstr "cmp: EOF ĉe %s post bajto %<PRIuMAX>\n"
 
 #. This is a proper name. See the gettext manual, section Names.
 #: src/diff.c:50
--- a/fr.po
+++ b/fr.po
@@ -646,18 +646,18 @@ msgstr "cmp: Fin-de-fichier (EOF) sur %s qui est vide\n"
 
 #: src/cmp.c:585
 #, c-format
-msgid "cmp: EOF on %s after byte %s, line %s\n"
-msgstr "cmp: Fin-de-fichier (EOF) sur %s après l'octet %s, ligne %s\n"
+msgid "cmp: EOF on %s after byte %<PRIuMAX>, line %<PRIuMAX>\n"
+msgstr "cmp: Fin-de-fichier (EOF) sur %s après l'octet %<PRIuMAX>, ligne %<PRIuMAX>\n"
 
 #: src/cmp.c:586
 #, c-format
-msgid "cmp: EOF on %s after byte %s, in line %s\n"
-msgstr "cmp: Fin-de-fichier (EOF) sur %s après l'octet %s, ligne %s\n"
+msgid "cmp: EOF on %s after byte %<PRIuMAX>, in line %<PRIuMAX>\n"
+msgstr "cmp: Fin-de-fichier (EOF) sur %s après l'octet %<PRIuMAX>, ligne %<PRIuMAX>\n"
 
 #: src/cmp.c:592
 #, c-format
-msgid "cmp: EOF on %s after byte %s\n"
-msgstr "cmp: Fin-de-fichier (EOF) sur %s après l'octet %s\n"
+msgid "cmp: EOF on %s after byte %<PRIuMAX>\n"
+msgstr "cmp: Fin-de-fichier (EOF) sur %s après l'octet %<PRIuMAX>\n"
 
 #. This is a proper name. See the gettext manual, section Names.
 #: src/diff.c:50
--- a/hr.po
+++ b/hr.po
@@ -648,18 +648,18 @@ msgstr "cmp: kraj datoteke (EOF) u %s koji je prazan\n"
 
 #: src/cmp.c:585
 #, c-format
-msgid "cmp: EOF on %s after byte %s, line %s\n"
-msgstr "cmp: kraj datoteke (EOF) u %s iza bajta %s, redak %s\n"
+msgid "cmp: EOF on %s after byte %<PRIuMAX>, line %<PRIuMAX>\n"
+msgstr "cmp: kraj datoteke (EOF) u %s iza bajta %<PRIuMAX>, redak %<PRIuMAX>\n"
 
 #: src/cmp.c:586
 #, c-format
-msgid "cmp: EOF on %s after byte %s, in line %s\n"
-msgstr "cmp: kraj datoteke (EOF) u %s iza bajta %s, u retku %s\n"
+msgid "cmp: EOF on %s after byte %<PRIuMAX>, in line %<PRIuMAX>\n"
+msgstr "cmp: kraj datoteke (EOF) u %s iza bajta %<PRIuMAX>, u retku %<PRIuMAX>\n"
 
 #: src/cmp.c:592
 #, c-format
-msgid "cmp: EOF on %s after byte %s\n"
-msgstr "cmp: kraj datoteke (EOF) u %s iza bajta %s\n"
+msgid "cmp: EOF on %s after byte %<PRIuMAX>\n"
+msgstr "cmp: kraj datoteke (EOF) u %s iza bajta %<PRIuMAX>\n"
 
 #. This is a proper name. See the gettext manual, section Names.
 #: src/diff.c:50
--- a/hu.po
+++ b/hu.po
@@ -647,18 +647,18 @@ msgstr "cmp: EOF ennél: %s, amely üres\n"
 
 #: src/cmp.c:585
 #, c-format
-msgid "cmp: EOF on %s after byte %s, line %s\n"
-msgstr "cmp: EOF ennél: %s, %s bájt és %s sor után\n"
+msgid "cmp: EOF on %s after byte %<PRIuMAX>, line %<PRIuMAX>\n"
+msgstr "cmp: EOF ennél: %s, %<PRIuMAX> bájt és %<PRIuMAX> sor után\n"
 
 #: src/cmp.c:586
 #, c-format
-msgid "cmp: EOF on %s after byte %s, in line %s\n"
-msgstr "cmp: EOF ennél: %s, %s bájt után a(z) %s. sorban\n"
+msgid "cmp: EOF on %s after byte %<PRIuMAX>, in line %<PRIuMAX>\n"
+msgstr "cmp: EOF ennél: %s, %<PRIuMAX> bájt után a(z) %<PRIuMAX>. sorban\n"
 
 #: src/cmp.c:592
 #, c-format
-msgid "cmp: EOF on %s after byte %s\n"
-msgstr "cmp: EOF ennél: %s, %s bájt után\n"
+msgid "cmp: EOF on %s after byte %<PRIuMAX>\n"
+msgstr "cmp: EOF ennél: %s, %<PRIuMAX> bájt után\n"
 
 #. This is a proper name. See the gettext manual, section Names.
 #: src/diff.c:50
--- a/ms.po
+++ b/ms.po
@@ -677,14 +677,14 @@ msgstr "cmp: EOF pada %s\n"
 #: src/cmp.c:585
 #, fuzzy, c-format
 #| msgid "%s %s differ: byte %s, line %s\n"
-msgid "cmp: EOF on %s after byte %s, line %s\n"
-msgstr "%s %s berbeza: byte %s, baris %s\n"
+msgid "cmp: EOF on %s after byte %<PRIuMAX>, line %<PRIuMAX>\n"
+msgstr "%s %s berbeza: byte %<PRIuMAX>, baris %<PRIuMAX>\n"
 
 #: src/cmp.c:586
 #, fuzzy, c-format
 #| msgid "%s %s differ: byte %s, line %s\n"
-msgid "cmp: EOF on %s after byte %s, in line %s\n"
-msgstr "%s %s berbeza: byte %s, baris %s\n"
+msgid "cmp: EOF on %s after byte %<PRIuMAX>, in line %<PRIuMAX>\n"
+msgstr "%s %s berbeza: byte %<PRIuMAX>, baris %<PRIuMAX>\n"
 
 #: src/cmp.c:592
 #, fuzzy, c-format
--- a/nb.po
+++ b/nb.po
@@ -646,18 +646,18 @@ msgstr "cmp: EOF på %s, som er tom\n"
 
 #: src/cmp.c:585
 #, c-format
-msgid "cmp: EOF on %s after byte %s, line %s\n"
-msgstr "cmp: EOF på %s etter byte %s, linje %s\n"
+msgid "cmp: EOF on %s after byte %<PRIuMAX>, line %<PRIuMAX>\n"
+msgstr "cmp: EOF på %s etter byte %<PRIuMAX>, linje %<PRIuMAX>\n"
 
 #: src/cmp.c:586
 #, c-format
-msgid "cmp: EOF on %s after byte %s, in line %s\n"
-msgstr "cmp: EOF på %s etter byte %s, på linje %s\n"
+msgid "cmp: EOF on %s after byte %<PRIuMAX>, in line %<PRIuMAX>\n"
+msgstr "cmp: EOF på %s etter byte %<PRIuMAX>, på linje %<PRIuMAX>\n"
 
 #: src/cmp.c:592
 #, c-format
-msgid "cmp: EOF on %s after byte %s\n"
-msgstr "cmp: EOF på %s etter byte %s\n"
+msgid "cmp: EOF on %s after byte %<PRIuMAX>\n"
+msgstr "cmp: EOF på %s etter byte %<PRIuMAX>\n"
 
 #. This is a proper name. See the gettext manual, section Names.
 #: src/diff.c:50
--- a/nl.po
+++ b/nl.po
@@ -661,18 +661,18 @@ msgstr "cmp: einde-van-bestand in %s dat leeg is\n"
 
 #: src/cmp.c:585
 #, c-format
-msgid "cmp: EOF on %s after byte %s, line %s\n"
-msgstr "cmp: einde-van-bestand in %s na byte %s, regel %s\n"
+msgid "cmp: EOF on %s after byte %<PRIuMAX>, line %<PRIuMAX>\n"
+msgstr "cmp: einde-van-bestand in %s na byte %<PRIuMAX>, regel %<PRIuMAX>\n"
 
 #: src/cmp.c:586
 #, c-format
-msgid "cmp: EOF on %s after byte %s, in line %s\n"
-msgstr "cmp: einde-van-bestand in %s na byte %s, in regel %s\n"
+msgid "cmp: EOF on %s after byte %<PRIuMAX>, in line %<PRIuMAX>\n"
+msgstr "cmp: einde-van-bestand in %s na byte %<PRIuMAX>, in regel %<PRIuMAX>\n"
 
 #: src/cmp.c:592
 #, c-format
-msgid "cmp: EOF on %s after byte %s\n"
-msgstr "cmp: einde-van-bestand in %s na byte %s\n"
+msgid "cmp: EOF on %s after byte %<PRIuMAX>\n"
+msgstr "cmp: einde-van-bestand in %s na byte %<PRIuMAX>\n"
 
 #. This is a proper name. See the gettext manual, section Names.
 #: src/diff.c:50
--- a/pl.po
+++ b/pl.po
@@ -649,18 +649,18 @@ msgstr "cmp: EOF w %s, który jest pusty\n"
 
 #: src/cmp.c:585
 #, c-format
-msgid "cmp: EOF on %s after byte %s, line %s\n"
-msgstr "cmp: EOF w %s, po bajcie %s, linii %s\n"
+msgid "cmp: EOF on %s after byte %<PRIuMAX>, line %<PRIuMAX>\n"
+msgstr "cmp: EOF w %s, po bajcie %<PRIuMAX>, linii %<PRIuMAX>\n"
 
 #: src/cmp.c:586
 #, c-format
-msgid "cmp: EOF on %s after byte %s, in line %s\n"
-msgstr "cmp: EOF w %s, po bajcie %s, w linii %s\n"
+msgid "cmp: EOF on %s after byte %<PRIuMAX>, in line %<PRIuMAX>\n"
+msgstr "cmp: EOF w %s, po bajcie %<PRIuMAX>, w linii %<PRIuMAX>\n"
 
 #: src/cmp.c:592
 #, c-format
-msgid "cmp: EOF on %s after byte %s\n"
-msgstr "cmp: EOF w %s, po bajcie %s\n"
+msgid "cmp: EOF on %s after byte %<PRIuMAX>\n"
+msgstr "cmp: EOF w %s, po bajcie %<PRIuMAX>\n"
 
 #. This is a proper name. See the gettext manual, section Names.
 #: src/diff.c:50
--- a/pt.po
+++ b/pt.po
@@ -645,18 +645,18 @@ msgstr "cmp: EOF em %s que está vazio\n"
 
 #: src/cmp.c:585
 #, c-format
-msgid "cmp: EOF on %s after byte %s, line %s\n"
-msgstr "cmp: EOF em %s após o byte %s, linha %s\n"
+msgid "cmp: EOF on %s after byte %<PRIuMAX>, line %<PRIuMAX>\n"
+msgstr "cmp: EOF em %s após o byte %<PRIuMAX>, linha %<PRIuMAX>\n"
 
 #: src/cmp.c:586
 #, c-format
-msgid "cmp: EOF on %s after byte %s, in line %s\n"
-msgstr "cmp: EOF em %s após o byte %s, na linha %s\n"
+msgid "cmp: EOF on %s after byte %<PRIuMAX>, in line %<PRIuMAX>\n"
+msgstr "cmp: EOF em %s após o byte %<PRIuMAX>, na linha %<PRIuMAX>\n"
 
 #: src/cmp.c:592
 #, c-format
-msgid "cmp: EOF on %s after byte %s\n"
-msgstr "cmp: EOF em %s após o byte %s\n"
+msgid "cmp: EOF on %s after byte %<PRIuMAX>\n"
+msgstr "cmp: EOF em %s após o byte %<PRIuMAX>\n"
 
 #. This is a proper name. See the gettext manual, section Names.
 #: src/diff.c:50
--- a/pt_BR.po
+++ b/pt_BR.po
@@ -651,18 +651,18 @@ msgstr "cmp: Fim de arquivo (EOF) em %s que está vazio\n"
 
 #: src/cmp.c:585
 #, c-format
-msgid "cmp: EOF on %s after byte %s, line %s\n"
-msgstr "cmp: Fim de arquivo (EOF) em %s após byte %s, linha %s\n"
+msgid "cmp: EOF on %s after byte %<PRIuMAX>, line %<PRIuMAX>\n"
+msgstr "cmp: Fim de arquivo (EOF) em %s após byte %<PRIuMAX>, linha %<PRIuMAX>\n"
 
 #: src/cmp.c:586
 #, c-format
-msgid "cmp: EOF on %s after byte %s, in line %s\n"
-msgstr "cmp: Fim de arquivo (EOF) em %s após byte %s, na linha %s\n"
+msgid "cmp: EOF on %s after byte %<PRIuMAX>, in line %<PRIuMAX>\n"
+msgstr "cmp: Fim de arquivo (EOF) em %s após byte %<PRIuMAX>, na linha %<PRIuMAX>\n"
 
 #: src/cmp.c:592
 #, c-format
-msgid "cmp: EOF on %s after byte %s\n"
-msgstr "cmp: Fim de arquivo (EOF) em %s após byte %s\n"
+msgid "cmp: EOF on %s after byte %<PRIuMAX>\n"
+msgstr "cmp: Fim de arquivo (EOF) em %s após byte %<PRIuMAX>\n"
 
 #. This is a proper name. See the gettext manual, section Names.
 #: src/diff.c:50
--- a/ru.po
+++ b/ru.po
@@ -649,18 +649,18 @@ msgstr "cmp: EOF в %s, который пуст\n"
 
 #: src/cmp.c:585
 #, c-format
-msgid "cmp: EOF on %s after byte %s, line %s\n"
-msgstr "cmp: EOF в %s после байта %s, строка %s\n"
+msgid "cmp: EOF on %s after byte %<PRIuMAX>, line %<PRIuMAX>\n"
+msgstr "cmp: EOF в %s после байта %<PRIuMAX>, строка %<PRIuMAX>\n"
 
 #: src/cmp.c:586
 #, c-format
-msgid "cmp: EOF on %s after byte %s, in line %s\n"
-msgstr "cmp: EOF в %s после байта %s в строке %s\n"
+msgid "cmp: EOF on %s after byte %<PRIuMAX>, in line %<PRIuMAX>\n"
+msgstr "cmp: EOF в %s после байта %<PRIuMAX> в строке %<PRIuMAX>\n"
 
 #: src/cmp.c:592
 #, c-format
-msgid "cmp: EOF on %s after byte %s\n"
-msgstr "cmp: EOF в %s после байта %s\n"
+msgid "cmp: EOF on %s after byte %<PRIuMAX>\n"
+msgstr "cmp: EOF в %s после байта %<PRIuMAX>\n"
 
 #. This is a proper name. See the gettext manual, section Names.
 #: src/diff.c:50
--- a/sr.po
+++ b/sr.po
@@ -642,18 +642,18 @@ msgstr "cmp: крај датотеке на %s које је празно\n"
 
 #: src/cmp.c:585
 #, c-format
-msgid "cmp: EOF on %s after byte %s, line %s\n"
-msgstr "cmp: крај датотеке на %s након бајта %s, %s. ред\n"
+msgid "cmp: EOF on %s after byte %<PRIuMAX>, line %<PRIuMAX>\n"
+msgstr "cmp: крај датотеке на %s након бајта %<PRIuMAX>, %<PRIuMAX>. ред\n"
 
 #: src/cmp.c:586
 #, c-format
-msgid "cmp: EOF on %s after byte %s, in line %s\n"
-msgstr "cmp: крај датотеке на %s након бајта %s, у %s. реду\n"
+msgid "cmp: EOF on %s after byte %<PRIuMAX>, in line %<PRIuMAX>\n"
+msgstr "cmp: крај датотеке на %s након бајта %<PRIuMAX>, у %<PRIuMAX>. реду\n"
 
 #: src/cmp.c:592
 #, c-format
-msgid "cmp: EOF on %s after byte %s\n"
-msgstr "cmp: крај датотеке на %s након бајта %s\n"
+msgid "cmp: EOF on %s after byte %<PRIuMAX>\n"
+msgstr "cmp: крај датотеке на %s након бајта %<PRIuMAX>\n"
 
 #. This is a proper name. See the gettext manual, section Names.
 #: src/diff.c:50
--- a/sv.po
+++ b/sv.po
@@ -646,18 +646,18 @@ msgstr "cmp: EOF i %s som är tom\n"
 
 #: src/cmp.c:585
 #, c-format
-msgid "cmp: EOF on %s after byte %s, line %s\n"
-msgstr "cmp: EOF i %s efter byte %s, rad %s\n"
+msgid "cmp: EOF on %s after byte %<PRIuMAX>, line %<PRIuMAX>\n"
+msgstr "cmp: EOF i %s efter byte %<PRIuMAX>, rad %<PRIuMAX>\n"
 
 #: src/cmp.c:586
 #, c-format
-msgid "cmp: EOF on %s after byte %s, in line %s\n"
-msgstr "cmp: EOF i %s efter byte %s, på rad %s\n"
+msgid "cmp: EOF on %s after byte %<PRIuMAX>, in line %<PRIuMAX>\n"
+msgstr "cmp: EOF i %s efter byte %<PRIuMAX>, på rad %<PRIuMAX>\n"
 
 #: src/cmp.c:592
 #, c-format
-msgid "cmp: EOF on %s after byte %s\n"
-msgstr "cmp: EOF i %s efter byte %s\n"
+msgid "cmp: EOF on %s after byte %<PRIuMAX>\n"
+msgstr "cmp: EOF i %s efter byte %<PRIuMAX>\n"
 
 #. This is a proper name. See the gettext manual, section Names.
 #: src/diff.c:50
--- a/tr.po
+++ b/tr.po
@@ -674,18 +674,18 @@ msgstr "cmp: %s'da EOF (dosya sonu) boş\n"
 
 #: src/cmp.c:585
 #, c-format
-msgid "cmp: EOF on %s after byte %s, line %s\n"
-msgstr "cmp: EOF üzerinde %s sonrası byte %s, satır %s\n"
+msgid "cmp: EOF on %s after byte %<PRIuMAX>, line %<PRIuMAX>\n"
+msgstr "cmp: EOF üzerinde %s sonrası byte %<PRIuMAX>, satır %<PRIuMAX>\n"
 
 #: src/cmp.c:586
 #, c-format
-msgid "cmp: EOF on %s after byte %s, in line %s\n"
-msgstr "cmp: EOF üzerinde %s sonrası byte %s, satır %s\n"
+msgid "cmp: EOF on %s after byte %<PRIuMAX>, in line %<PRIuMAX>\n"
+msgstr "cmp: EOF üzerinde %s sonrası byte %<PRIuMAX>, satır %<PRIuMAX>\n"
 
 #: src/cmp.c:592
 #, c-format
-msgid "cmp: EOF on %s after byte %s\n"
-msgstr "cmp: EOF üzerinde %s sonrası byte %s\n"
+msgid "cmp: EOF on %s after byte %<PRIuMAX>\n"
+msgstr "cmp: EOF üzerinde %s sonrası byte %<PRIuMAX>\n"
 
 #. This is a proper name. See the gettext manual, section Names.
 #: src/diff.c:50
--- a/uk.po
+++ b/uk.po
@@ -647,17 +647,17 @@ msgstr "cmp: кінець файла у %s, який є порожнім\n"
 
 #: src/cmp.c:585
 #, c-format
-msgid "cmp: EOF on %s after byte %s, line %s\n"
-msgstr "cmp: кінець файла у %s після байта %s, рядок %s\n"
+msgid "cmp: EOF on %s after byte %<PRIuMAX>, line %<PRIuMAX>\n"
+msgstr "cmp: кінець файла у %s після байта %<PRIuMAX>, рядок %<PRIuMAX>\n"
 
 #: src/cmp.c:586
 #, c-format
-msgid "cmp: EOF on %s after byte %s, in line %s\n"
-msgstr "cmp: кінець файла у %s після байта %s, у рядку %s\n"
+msgid "cmp: EOF on %s after byte %<PRIuMAX>, in line %<PRIuMAX>\n"
+msgstr "cmp: кінець файла у %s після байта %<PRIuMAX>, у рядку %<PRIuMAX>\n"
 
 #: src/cmp.c:592
 #, c-format
-msgid "cmp: EOF on %s after byte %s\n"
+msgid "cmp: EOF on %s after byte %<PRIuMAX>\n"
 msgstr "cmp: кінець файла у %s після байта %s\n"
 
 #. This is a proper name. See the gettext manual, section Names.
--- a/vi.po
+++ b/vi.po
@@ -652,18 +652,18 @@ msgstr "cmp: gặp kết thức tập tin trên %s cái mà trống rỗng\n"
 
 #: src/cmp.c:585
 #, c-format
-msgid "cmp: EOF on %s after byte %s, line %s\n"
-msgstr "cmp: gặp kết thức tập tin trên %s sau byte %s, dòng %s\n"
+msgid "cmp: EOF on %s after byte %<PRIuMAX>, line %<PRIuMAX>\n"
+msgstr "cmp: gặp kết thức tập tin trên %s sau byte %<PRIuMAX>, dòng %<PRIuMAX>\n"
 
 #: src/cmp.c:586
 #, c-format
-msgid "cmp: EOF on %s after byte %s, in line %s\n"
-msgstr "cmp: gặp kết thức tập tin trên %s sau byte %s, ở dòng %s\n"
+msgid "cmp: EOF on %s after byte %<PRIuMAX>, in line %<PRIuMAX>\n"
+msgstr "cmp: gặp kết thức tập tin trên %s sau byte %<PRIuMAX>, ở dòng %<PRIuMAX>\n"
 
 #: src/cmp.c:592
 #, c-format
-msgid "cmp: EOF on %s after byte %s\n"
-msgstr "cmp: gặp kết thức tập tin trên %s sau byte %s\n"
+msgid "cmp: EOF on %s after byte %<PRIuMAX>\n"
+msgstr "cmp: gặp kết thức tập tin trên %s sau byte %<PRIuMAX>\n"
 
 # Tên họ
 #. This is a proper name. See the gettext manual, section Names.
--- a/zh_CN.po
+++ b/zh_CN.po
@@ -648,18 +648,18 @@ msgstr "cmp：%s 已结束且为空\n"
 
 #: src/cmp.c:585
 #, c-format
-msgid "cmp: EOF on %s after byte %s, line %s\n"
-msgstr "cmp：%s 在 %s 字节 %s 行后结束\n"
+msgid "cmp: EOF on %s after byte %<PRIuMAX>, line %<PRIuMAX>\n"
+msgstr "cmp：%s 在 %<PRIuMAX> 字节 %<PRIuMAX> 行后结束\n"
 
 #: src/cmp.c:586
 #, c-format
-msgid "cmp: EOF on %s after byte %s, in line %s\n"
-msgstr "cmp：%s 在 %s 字节 %s 行中结束\n"
+msgid "cmp: EOF on %s after byte %<PRIuMAX>, in line %<PRIuMAX>\n"
+msgstr "cmp：%s 在 %<PRIuMAX> 字节 %<PRIuMAX> 行中结束\n"
 
 #: src/cmp.c:592
 #, c-format
-msgid "cmp: EOF on %s after byte %s\n"
-msgstr "cmp：%s 在 %s 字节后结束\n"
+msgid "cmp: EOF on %s after byte %<PRIuMAX>\n"
+msgstr "cmp：%s 在 %<PRIuMAX> 字节后结束\n"
 
 #. This is a proper name. See the gettext manual, section Names.
 #: src/diff.c:50
diff --git a/NEWS b/NEWS
index 3ecd111..423c0ee 100644
--- a/NEWS
+++ b/NEWS
@@ -23,6 +23,9 @@ GNU diffutils NEWS                                    -*- outline -*-
   option-arguments as if they were large positive numbers.
   [bug#35256 introduced in 2.8]
 
+** Improvements
+
+  New cmp option: -x or --verbose-hex.
 
 * Noteworthy changes in release 3.7 (2018-12-31) [stable]
 
diff --git a/doc/diffutils.texi b/doc/diffutils.texi
index 3a780db..c5ef984 100644
--- a/doc/diffutils.texi
+++ b/doc/diffutils.texi
@@ -3581,6 +3581,11 @@ the files differ.
 @item -v
 @itemx --version
 Output version information and then exit.
+
+@item -x
+@itemx --verbose-hex
+Like @option{--verbose}, but with hexadecimal numbers, and byte numbers
+starting at 0.
 @end table
 
 In the above table, operands that are byte counts are normally
diff --git a/src/cmp.c b/src/cmp.c
index 5152ca0..555665c 100644
--- a/src/cmp.c
+++ b/src/cmp.c
@@ -90,6 +90,9 @@ static enum comparison_type
 /* If nonzero, print values of bytes quoted like cat -t does. */
 static bool opt_print_bytes;
 
+/* Show verbose output using hexadecimal numbers. */
+static bool opt_verbose_hex;
+
 /* Values for long options that do not have single-letter equivalents.  */
 enum
 {
@@ -106,6 +109,7 @@ static struct option const long_options[] =
   {"silent", 0, 0, 's'},
   {"quiet", 0, 0, 's'},
   {"version", 0, 0, 'v'},
+  {"verbose-hex", 0, 0, 'x'},
   {"help", 0, 0, HELP_OPTION},
   {0, 0, 0, 0}
 };
@@ -168,6 +172,8 @@ static char const * const option_help_msgid[] = {
   N_("-s, --quiet, --silent      suppress all normal output"),
   N_("    --help                 display this help and exit"),
   N_("-v, --version              output version information and exit"),
+  N_("-x, --verbose-hex          output byte numbers and differing byte values\n"
+     "                               using hexadecimal numbers"),
   0
 };
 
@@ -214,7 +220,7 @@ main (int argc, char **argv)
 
   /* Parse command line options.  */
 
-  while ((c = getopt_long (argc, argv, "bci:ln:sv", long_options, 0))
+  while ((c = getopt_long (argc, argv, "bci:ln:svx", long_options, 0))
          != -1)
     switch (c)
       {
@@ -256,6 +262,11 @@ main (int argc, char **argv)
         check_stdout ();
         return EXIT_SUCCESS;
 
+      case 'x':
+        specify_comparison_type (type_all_diffs);
+        opt_verbose_hex = true;
+        break;
+
       case HELP_OPTION:
         usage ();
         check_stdout ();
@@ -378,8 +389,10 @@ static int
 cmp (void)
 {
   bool at_line_start = true;
+  off_t start_offset = opt_verbose_hex ? 0 : 1;
   off_t line_number = 1;	/* Line number (1...) of difference. */
-  off_t byte_number = 1;	/* Byte number (1...) of difference. */
+  off_t byte_number = start_offset;
+				/* Byte number (0/1...) of difference. */
   intmax_t remaining = bytes;	/* Remaining bytes to compare, or -1.  */
   size_t read0, read1;		/* Number of bytes read from each file. */
   size_t first_diff;		/* Offset (0...) in buffers of 1st diff. */
@@ -396,6 +409,7 @@ cmp (void)
     {
       off_t byte_number_max = (0 <= bytes && bytes <= TYPE_MAXIMUM (off_t)
 			       ? bytes : TYPE_MAXIMUM (off_t));
+      int base = opt_verbose_hex ? 16 : 10;
 
       for (f = 0; f < 2; f++)
         if (S_ISREG (stat_buf[f].st_mode))
@@ -405,8 +419,13 @@ cmp (void)
               byte_number_max = file_bytes;
           }
 
-      for (offset_width = 1; (byte_number_max /= 10) != 0; offset_width++)
+      byte_number_max = byte_number_max + start_offset - 1;
+
+      for (offset_width = 1; (byte_number_max /= base) != 0; offset_width++)
         continue;
+
+      if (opt_verbose_hex && offset_width < 8)
+        offset_width = 8;
     }
 
   for (f = 0; f < 2; f++)
@@ -527,13 +546,14 @@ cmp (void)
                   unsigned char c1 = buf1[first_diff];
                   if (c0 != c1)
                     {
-                      char byte_buf[INT_BUFSIZE_BOUND (off_t)];
-                      char const *byte_num = offtostr (byte_number, byte_buf);
                       if (!opt_print_bytes)
                         {
                           /* See POSIX for this format.  */
-                          printf ("%*s %3o %3o\n",
-                                  offset_width, byte_num, c0, c1);
+                          printf (opt_verbose_hex ?
+                                  "%0*"PRIxMAX" %.2x %.2x\n" :
+                                  "%*"PRIuMAX" %3o %3o\n",
+                                  offset_width, (uintmax_t) byte_number,
+                                  c0, c1);
                         }
                       else
                         {
@@ -541,8 +561,11 @@ cmp (void)
                           char s1[5];
                           sprintc (s0, c0);
                           sprintc (s1, c1);
-                          printf ("%*s %3o %-4s %3o %s\n",
-                                  offset_width, byte_num, c0, s0, c1, s1);
+                          printf (opt_verbose_hex ?
+                                  "%0*"PRIxMAX" %.2x %-4s %.2x %s\n" :
+                                  "%*"PRIuMAX" %3o %-4s %3o %s\n",
+                                  offset_width, (uintmax_t) byte_number,
+                                  c0, s0, c1, s1);
                         }
                     }
                   byte_number++;
@@ -567,30 +590,30 @@ cmp (void)
               /* POSIX says that each of these format strings must be
                  "cmp: EOF on %s", optionally followed by a blank and
                  extra text sans newline, then terminated by "\n".  */
-              if (byte_number == 1)
+              if (byte_number == start_offset)
                 fprintf (stderr, _("cmp: EOF on %s which is empty\n"),
                          shorter_file);
               else
                 {
-                  char byte_buf[INT_BUFSIZE_BOUND (off_t)];
-                  char const *byte_num = offtostr (byte_number - 1, byte_buf);
-
                   if (comparison_type == type_first_diff)
                     {
-                      char line_buf[INT_BUFSIZE_BOUND (off_t)];
-                      char const *line_num
-                        = offtostr (line_number - at_line_start, line_buf);
                       fprintf (stderr,
                                (at_line_start
-                                ? _("cmp: EOF on %s after byte %s, line %s\n")
-                                : _("cmp: EOF on %s after byte %s,"
-                                    " in line %s\n")),
-                               shorter_file, byte_num, line_num);
+                                ? _("cmp: EOF on %s after byte %"PRIuMAX","
+                                    " line %"PRIuMAX"\n")
+                                : _("cmp: EOF on %s after byte %"PRIuMAX","
+                                    " in line %"PRIuMAX"\n")),
+                               shorter_file, (uintmax_t) (byte_number - 1),
+                               (uintmax_t) (line_number - at_line_start));
                     }
+                  else if (opt_verbose_hex)
+                    fprintf (stderr,
+                             _("cmp: EOF on %s at byte %#"PRIxMAX"\n"),
+                             shorter_file, (uintmax_t) byte_number);
                   else
                     fprintf (stderr,
-                             _("cmp: EOF on %s after byte %s\n"),
-                             shorter_file, byte_num);
+                             _("cmp: EOF on %s after byte %"PRIuMAX"\n"),
+                             shorter_file, (uintmax_t) (byte_number - 1));
                 }
             }
 
diff --git a/tests/cmp b/tests/cmp
index ff49388..5c96dd2 100755
--- a/tests/cmp
+++ b/tests/cmp
@@ -143,6 +143,51 @@ cmp -s d c
 2
 cmp -s d d
 2
+cmp -x a a
+0
+cmp -x a b
+00000000 61 62
+1
+cmp -x a c
+cmp: EOF on c which is empty
+1
+cmp -x a d
+cmp: d: No such file or directory
+2
+cmp -x b a
+00000000 62 61
+1
+cmp -x b b
+0
+cmp -x b c
+cmp: EOF on c which is empty
+1
+cmp -x b d
+cmp: d: No such file or directory
+2
+cmp -x c a
+cmp: EOF on c which is empty
+1
+cmp -x c b
+cmp: EOF on c which is empty
+1
+cmp -x c c
+0
+cmp -x c d
+cmp: d: No such file or directory
+2
+cmp -x d a
+cmp: d: No such file or directory
+2
+cmp -x d b
+cmp: d: No such file or directory
+2
+cmp -x d c
+cmp: d: No such file or directory
+2
+cmp -x d d
+cmp: d: No such file or directory
+2
 EOF
 
 echo a >a
@@ -150,7 +195,7 @@ echo b >b
 : >c
 rm -f d
 
-for option in '' -l -s; do
+for option in '' -l -s -x; do
   for i in a b c d; do
     for j in a b c d; do
       echo cmp $option $i $j
@@ -189,6 +234,15 @@ cmp -s a1 a2
 1
 cmp -s a2 a3
 1
+cmp -x a0 a1
+cmp: EOF on a0 which is empty
+1
+cmp -x a1 a2
+cmp: EOF on a1 at byte 0x2
+1
+cmp -x a2 a3
+cmp: EOF on a2 at byte 0x5
+1
 EOF
 
 printf '' >a0
@@ -196,7 +250,7 @@ printf '1\n' >a1
 printf '1\nfoo' >a2
 printf '1\nfoolery\n' >a3
 
-for option in '' -l -s; do
+for option in '' -l -s -x; do
   for files in 'a0 a1' 'a1 a2' 'a2 a3'; do
     echo cmp $option $files
     cmp $option $files >stdout 2>stderr