xxd -r: without -p, stop at more than one whitespace, closes 14786
function old new delta xxd_main 888 1076 +188 Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
5a9d2b6e02
commit
f318adaaab
@ -37,4 +37,13 @@ testing 'xxd -p -r' \
|
|||||||
'' \
|
'' \
|
||||||
'30313233343536373736353433323130 30313233343536373736353433323130'
|
'30313233343536373736353433323130 30313233343536373736353433323130'
|
||||||
|
|
||||||
|
testing 'xxd -r skips leading whitespace and truncates at two spaces' \
|
||||||
|
'xxd -r' \
|
||||||
|
'0123456789:;<=>?@' \
|
||||||
|
'' \
|
||||||
|
"\
|
||||||
|
00000000: 3031 3233 3435 3637 3839 3a3b 3c3d 3e3f 0123456789:;<=>?
|
||||||
|
00000010: 40 @
|
||||||
|
"
|
||||||
|
|
||||||
exit $FAILCOUNT
|
exit $FAILCOUNT
|
||||||
|
@ -76,12 +76,14 @@ static void reverse(unsigned opt, const char *filename)
|
|||||||
|
|
||||||
fp = filename ? xfopen_for_read(filename) : stdin;
|
fp = filename ? xfopen_for_read(filename) : stdin;
|
||||||
|
|
||||||
|
get_new_line:
|
||||||
while ((buf = xmalloc_fgetline(fp)) != NULL) {
|
while ((buf = xmalloc_fgetline(fp)) != NULL) {
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
p = buf;
|
p = buf;
|
||||||
if (!(opt & OPT_p)) {
|
if (!(opt & OPT_p)) {
|
||||||
/* skip address */
|
skip_address:
|
||||||
|
p = skip_whitespace(p);
|
||||||
while (isxdigit(*p)) p++;
|
while (isxdigit(*p)) p++;
|
||||||
/* NB: for xxd -r, first hex portion is address even without colon */
|
/* NB: for xxd -r, first hex portion is address even without colon */
|
||||||
/* If it's there, skip it: */
|
/* If it's there, skip it: */
|
||||||
@ -94,36 +96,45 @@ static void reverse(unsigned opt, const char *filename)
|
|||||||
/* Process hex bytes optionally separated by whitespace */
|
/* Process hex bytes optionally separated by whitespace */
|
||||||
for (;;) {
|
for (;;) {
|
||||||
uint8_t val, c;
|
uint8_t val, c;
|
||||||
|
int badchar = 0;
|
||||||
nibble1:
|
nibble1:
|
||||||
|
if (opt & OPT_p)
|
||||||
p = skip_whitespace(p);
|
p = skip_whitespace(p);
|
||||||
|
|
||||||
c = *p++;
|
c = *p++;
|
||||||
if (isdigit(c))
|
if (isdigit(c))
|
||||||
val = c - '0';
|
val = c - '0';
|
||||||
else if ((c|0x20) >= 'a' && (c|0x20) <= 'f')
|
else if ((c|0x20) >= 'a' && (c|0x20) <= 'f')
|
||||||
val = (c|0x20) - ('a' - 10);
|
val = (c|0x20) - ('a' - 10);
|
||||||
else {
|
else {
|
||||||
/* xxd V1.10 is inconsistent here.
|
/* xxd V1.10 allows one non-hexnum char:
|
||||||
* echo -e "31 !3 0a 0a" | xxd -r -p
|
* echo -e "31 !3 0a 0a" | xxd -r -p
|
||||||
* is "10<a0>" (no <cr>) - "!" is ignored,
|
* is "10<a0>" (no <cr>) - "!" is ignored,
|
||||||
* but
|
* but stops for more than one:
|
||||||
* echo -e "31 !!343434\n30 0a" | xxd -r -p
|
* echo -e "31 !!343434\n30 0a" | xxd -r -p
|
||||||
* is "10<cr>" - "!!" drops rest of the line.
|
* is "10<cr>" - "!!" drops rest of the line.
|
||||||
* We will ignore all invalid chars:
|
* Note: this also covers whitespace chars:
|
||||||
|
* xxxxxxxx: 3031 3233 3435 3637 3839 3a3b 3c3d 3e3f 0123456789:;<=>?
|
||||||
|
* detects this ^ - skips this one space
|
||||||
|
* xxxxxxxx: 3031 3233 3435 3637 3839 3a3b 3c3d 3e3f 0123456789:;<=>?
|
||||||
|
* detects this ^^ - skips the rest
|
||||||
*/
|
*/
|
||||||
if (c != '\0')
|
if (c == '\0' || badchar)
|
||||||
goto nibble1;
|
|
||||||
break;
|
break;
|
||||||
|
badchar++;
|
||||||
|
goto nibble1;
|
||||||
}
|
}
|
||||||
val <<= 4;
|
val <<= 4;
|
||||||
|
|
||||||
|
nibble2:
|
||||||
|
if (opt & OPT_p) {
|
||||||
/* Works the same with xxd V1.10:
|
/* Works the same with xxd V1.10:
|
||||||
* echo "31 09 32 0a" | xxd -r -p
|
* echo "31 09 32 0a" | xxd -r -p
|
||||||
* echo "31 0 9 32 0a" | xxd -r -p
|
* echo "31 0 9 32 0a" | xxd -r -p
|
||||||
* thus allow whitespace even within the byte:
|
* thus allow whitespace (even multiple chars)
|
||||||
|
* after byte's 1st char:
|
||||||
*/
|
*/
|
||||||
nibble2:
|
|
||||||
p = skip_whitespace(p);
|
p = skip_whitespace(p);
|
||||||
|
}
|
||||||
|
|
||||||
c = *p++;
|
c = *p++;
|
||||||
if (isdigit(c))
|
if (isdigit(c))
|
||||||
@ -132,7 +143,16 @@ static void reverse(unsigned opt, const char *filename)
|
|||||||
val |= (c|0x20) - ('a' - 10);
|
val |= (c|0x20) - ('a' - 10);
|
||||||
else {
|
else {
|
||||||
if (c != '\0') {
|
if (c != '\0') {
|
||||||
/* "...3<not_hex_char>..." ignores both chars */
|
/* "...3<not_hex_char>...": ignore "3",
|
||||||
|
* skip everything up to next hexchar or newline:
|
||||||
|
*/
|
||||||
|
while (!isxdigit(*p)) {
|
||||||
|
if (*p == '\0') {
|
||||||
|
free(buf);
|
||||||
|
goto get_new_line;
|
||||||
|
}
|
||||||
|
p++;
|
||||||
|
}
|
||||||
goto nibble1;
|
goto nibble1;
|
||||||
}
|
}
|
||||||
/* Nibbles can join even through newline:
|
/* Nibbles can join even through newline:
|
||||||
@ -143,10 +163,12 @@ static void reverse(unsigned opt, const char *filename)
|
|||||||
p = buf = xmalloc_fgetline(fp);
|
p = buf = xmalloc_fgetline(fp);
|
||||||
if (!buf)
|
if (!buf)
|
||||||
break;
|
break;
|
||||||
|
if (!(opt & OPT_p)) /* -p and !-p: different behavior */
|
||||||
|
goto skip_address;
|
||||||
goto nibble2;
|
goto nibble2;
|
||||||
}
|
}
|
||||||
putchar(val);
|
putchar(val);
|
||||||
}
|
} /* for(;;) */
|
||||||
free(buf);
|
free(buf);
|
||||||
}
|
}
|
||||||
//fclose(fp);
|
//fclose(fp);
|
||||||
|
Loading…
Reference in New Issue
Block a user