Fix the output of NUL bytes within %b formats.
(Approved by Christos)
This commit is contained in:
parent
a01816b280
commit
a5f7364038
|
@ -1,4 +1,4 @@
|
||||||
/* $NetBSD: printf.c,v 1.25 2002/11/24 22:35:45 christos Exp $ */
|
/* $NetBSD: printf.c,v 1.26 2003/02/24 14:42:27 dsl Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1989, 1993
|
* Copyright (c) 1989, 1993
|
||||||
|
@ -45,7 +45,7 @@ __COPYRIGHT("@(#) Copyright (c) 1989, 1993\n\
|
||||||
#if 0
|
#if 0
|
||||||
static char sccsid[] = "@(#)printf.c 8.2 (Berkeley) 3/22/95";
|
static char sccsid[] = "@(#)printf.c 8.2 (Berkeley) 3/22/95";
|
||||||
#else
|
#else
|
||||||
__RCSID("$NetBSD: printf.c,v 1.25 2002/11/24 22:35:45 christos Exp $");
|
__RCSID("$NetBSD: printf.c,v 1.26 2003/02/24 14:42:27 dsl Exp $");
|
||||||
#endif
|
#endif
|
||||||
#endif /* not lint */
|
#endif /* not lint */
|
||||||
|
|
||||||
|
@ -69,7 +69,7 @@ __RCSID("$NetBSD: printf.c,v 1.25 2002/11/24 22:35:45 christos Exp $");
|
||||||
#define ESCAPE 033
|
#define ESCAPE 033
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static char *conv_escape_str(char *);
|
static void conv_escape_str(char *, void (*)(int));
|
||||||
static char *conv_escape(char *, char *);
|
static char *conv_escape(char *, char *);
|
||||||
static char *conv_expand(const char *);
|
static char *conv_expand(const char *);
|
||||||
static int getchr(void);
|
static int getchr(void);
|
||||||
|
@ -82,6 +82,11 @@ static char *mklong(const char *, int);
|
||||||
static void check_conversion(const char *, const char *);
|
static void check_conversion(const char *, const char *);
|
||||||
static void usage(void);
|
static void usage(void);
|
||||||
|
|
||||||
|
static void b_count(int);
|
||||||
|
static void b_output(int);
|
||||||
|
static int b_length;
|
||||||
|
static char *b_fmt;
|
||||||
|
|
||||||
static int rval;
|
static int rval;
|
||||||
static char **gargv;
|
static char **gargv;
|
||||||
|
|
||||||
|
@ -106,6 +111,18 @@ static char **gargv;
|
||||||
(void)printf(f, func); \
|
(void)printf(f, func); \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define APF(cpp, f, func) { \
|
||||||
|
if (fieldwidth != -1) { \
|
||||||
|
if (precision != -1) \
|
||||||
|
(void)asprintf(cpp, f, fieldwidth, precision, func); \
|
||||||
|
else \
|
||||||
|
(void)asprintf(cpp, f, fieldwidth, func); \
|
||||||
|
} else if (precision != -1) \
|
||||||
|
(void)asprintf(cpp, f, precision, func); \
|
||||||
|
else \
|
||||||
|
(void)asprintf(cpp, f, func); \
|
||||||
|
}
|
||||||
|
|
||||||
int main(int, char **);
|
int main(int, char **);
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
|
@ -197,9 +214,34 @@ int main(int argc, char *argv[])
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'b': {
|
case 'b': {
|
||||||
char *p = conv_escape_str(getstr());
|
/* There has to be a better way to do this,
|
||||||
|
* but the string we generate might have
|
||||||
|
* embedded nulls. */
|
||||||
|
static char *a, *t;
|
||||||
|
char *cp = getstr();
|
||||||
|
/* Free on entry in case shell longjumped out */
|
||||||
|
if (a != NULL)
|
||||||
|
free(a);
|
||||||
|
a = NULL;
|
||||||
|
if (t != NULL)
|
||||||
|
free(t);
|
||||||
|
t = NULL;
|
||||||
|
/* Count number of bytes we want to output */
|
||||||
|
b_length = 0;
|
||||||
|
conv_escape_str(cp, b_count);
|
||||||
|
t = malloc(b_length + 1);
|
||||||
|
if (t == NULL)
|
||||||
|
break;
|
||||||
|
memset(t, 'x', b_length);
|
||||||
|
t[b_length] = 0;
|
||||||
|
/* Get printf to calculate the lengths */
|
||||||
*fmt = 's';
|
*fmt = 's';
|
||||||
PF(start, p);
|
APF(&a, start, t);
|
||||||
|
b_fmt = a;
|
||||||
|
/* Output leading spaces and data bytes */
|
||||||
|
conv_escape_str(cp, b_output);
|
||||||
|
/* Add any trailing spaces */
|
||||||
|
printf("%s", b_fmt);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'c': {
|
case 'c': {
|
||||||
|
@ -252,30 +294,49 @@ int main(int argc, char *argv[])
|
||||||
return (rval);
|
return (rval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* helper functions for conv_escape_str */
|
||||||
|
|
||||||
|
static void
|
||||||
|
b_count(int ch)
|
||||||
|
{
|
||||||
|
b_length++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Output one converted character for every 'x' in the 'format' */
|
||||||
|
|
||||||
|
static void
|
||||||
|
b_output(int ch)
|
||||||
|
{
|
||||||
|
for (;;) {
|
||||||
|
switch (*b_fmt++) {
|
||||||
|
case 0:
|
||||||
|
b_fmt--;
|
||||||
|
return;
|
||||||
|
case ' ':
|
||||||
|
putchar(' ');
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
putchar(ch);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Print SysV echo(1) style escape string
|
* Print SysV echo(1) style escape string
|
||||||
* Halts processing string if a \c escape is encountered.
|
* Halts processing string if a \c escape is encountered.
|
||||||
*/
|
*/
|
||||||
static char *
|
static void
|
||||||
conv_escape_str(char *str)
|
conv_escape_str(char *str, void (*do_putchar)(int))
|
||||||
{
|
{
|
||||||
int value;
|
int value;
|
||||||
int ch;
|
int ch;
|
||||||
static char *conv_str;
|
char c;
|
||||||
char *cp;
|
|
||||||
|
|
||||||
/* convert string into a temporary buffer... */
|
|
||||||
if (conv_str)
|
|
||||||
free(conv_str);
|
|
||||||
conv_str = malloc(strlen(str) + 4);
|
|
||||||
if (!conv_str)
|
|
||||||
return "<no memory>";
|
|
||||||
cp = conv_str;
|
|
||||||
|
|
||||||
while ((ch = *str++)) {
|
while ((ch = *str++)) {
|
||||||
if (ch != '\\') {
|
if (ch != '\\') {
|
||||||
*cp++ = ch;
|
do_putchar(ch);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -297,14 +358,14 @@ conv_escape_str(char *str)
|
||||||
octnum[1] = str[1];
|
octnum[1] = str[1];
|
||||||
octnum[2] = str[2];
|
octnum[2] = str[2];
|
||||||
octnum[3] = 0;
|
octnum[3] = 0;
|
||||||
*cp++ = strtoul(octnum, &oct_end, 8);
|
do_putchar(strtoul(octnum, &oct_end, 8));
|
||||||
str += oct_end - octnum;
|
str += oct_end - octnum;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* \[M][^|-]C as defined by vis(3) */
|
/* \[M][^|-]C as defined by vis(3) */
|
||||||
if (ch == 'M' && *str == '-') {
|
if (ch == 'M' && *str == '-') {
|
||||||
*cp++ = 0200 | str[1];
|
do_putchar(0200 | str[1]);
|
||||||
str += 2;
|
str += 2;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -320,17 +381,14 @@ conv_escape_str(char *str)
|
||||||
value |= 0177;
|
value |= 0177;
|
||||||
else
|
else
|
||||||
value |= ch & 037;
|
value |= ch & 037;
|
||||||
*cp++ = value;
|
do_putchar(value);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Finally test for sequences valid in the format string */
|
/* Finally test for sequences valid in the format string */
|
||||||
str = conv_escape(str - 1, cp);
|
str = conv_escape(str - 1, &c);
|
||||||
cp++;
|
do_putchar(c);
|
||||||
}
|
}
|
||||||
*cp = 0;
|
|
||||||
|
|
||||||
return conv_str;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -383,9 +441,9 @@ conv_escape(char *str, char *conv_ch)
|
||||||
case 'v': value = '\v'; break; /* vertical-tab */
|
case 'v': value = '\v'; break; /* vertical-tab */
|
||||||
|
|
||||||
default:
|
default:
|
||||||
warnx("unknown escape sequence `\\%c'", *str);
|
warnx("unknown escape sequence `\\%c'", ch);
|
||||||
rval = 1;
|
rval = 1;
|
||||||
value = *str;
|
value = ch;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue