commit bash-20050317 snapshot

This commit is contained in:
Chet Ramey
2011-12-03 13:44:53 -05:00
parent af91506ad6
commit 3ee6b87dbc
25 changed files with 2906 additions and 2118 deletions
+108 -16
View File
@@ -1,7 +1,7 @@
This file is printf.def, from which is created printf.c.
It implements the builtin "printf" in Bash.
Copyright (C) 1997-2003 Free Software Foundation, Inc.
Copyright (C) 1997-2005 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -23,7 +23,7 @@ $PRODUCES printf.c
$BUILTIN printf
$FUNCTION printf_builtin
$SHORT_DOC printf format [arguments]
$SHORT_DOC printf [-v var] format [arguments]
printf formats and prints ARGUMENTS under control of the FORMAT. FORMAT
is a character string which contains three types of objects: plain
characters, which are simply copied to standard output, character escape
@@ -32,6 +32,8 @@ format specifications, each of which causes printing of the next successive
argument. In addition to the standard printf(1) formats, %b means to
expand backslash escape sequences in the corresponding argument, and %q
means to quote the argument in a way that can be reused as shell input.
If the -v option is supplied, the output is placed into the value of the
shell variable VAR rather than being sent to the standard output.
$END
#include <config.h>
@@ -74,28 +76,58 @@ $END
extern int errno;
#endif
#define PC(c) \
do { \
char b[2]; \
tw++; \
b[0] = c; b[1] = '\0'; \
if (vflag) \
vbadd (b, 1); \
else \
putchar (c); \
} while (0)
#define PF(f, func) \
do { \
char *b = 0; \
int nw; \
if (have_fieldwidth && have_precision) \
tw += printf(f, fieldwidth, precision, func); \
nw = asprintf(&b, f, fieldwidth, precision, func); \
else if (have_fieldwidth) \
tw += printf(f, fieldwidth, func); \
nw = asprintf(&b, f, fieldwidth, func); \
else if (have_precision) \
tw += printf(f, precision, func); \
nw = asprintf(&b, f, precision, func); \
else \
tw += printf(f, func); \
nw = asprintf(&b, f, func); \
tw += nw; \
if (b) \
{ \
if (vflag) \
(void)vbadd (b, nw); \
else \
(void)fputs (b, stdout); \
free (b); \
} \
} while (0)
/* We free the buffer used by mklong() if it's `too big'. */
#define PRETURN(value) \
do \
{ \
if (vflag) \
bind_variable (vname, vbuf, 0); \
if (conv_bufsize > 4096 ) \
{ \
free(conv_buf); \
free (conv_buf); \
conv_bufsize = 0; \
conv_buf = 0; \
} \
if (vbsize > 4096) \
{ \
free (vbuf); \
vbsize = 0; \
vbuf = 0; \
} \
fflush (stdout); \
return (value); \
} \
@@ -108,6 +140,7 @@ static void printf_erange __P((char *));
static int printstr __P((char *, char *, int, int, int));
static int tescape __P((char *, char *, int *));
static char *bexpand __P((char *, int, int *, int *));
static char *vbadd __P((char *, int));
static char *mklong __P((char *, char *, size_t));
static int getchr __P((void));
static char *getstr __P((void));
@@ -132,6 +165,14 @@ static WORD_LIST *garglist;
static int retval;
static int conversion_error;
/* printf -v var support */
static int vflag = 0;
static char *vbuf, *vname;
static size_t vbsize;
static int vblen;
static intmax_t tw;
static char *conv_buf;
static size_t conv_bufsize;
@@ -141,14 +182,35 @@ printf_builtin (list)
{
int ch, fieldwidth, precision;
int have_fieldwidth, have_precision;
intmax_t tw;
char convch, thisch, nextch, *format, *modstart, *fmt, *start;
conversion_error = 0;
retval = EXECUTION_SUCCESS;
if (no_options (list))
return (EX_USAGE);
vflag = 0;
reset_internal_getopt ();
while ((ch = internal_getopt (list, "v:")) != -1)
{
switch (ch)
{
case 'v':
if (legal_identifier (vname = list_optarg))
{
vflag = 1;
vblen = 0;
}
else
{
sh_invalidid (vname);
return (EX_USAGE);
}
break;
default:
builtin_usage ();
return (EX_USAGE);
}
}
list = loptend; /* skip over possible `--' */
if (list == 0)
@@ -161,6 +223,7 @@ printf_builtin (list)
return (EXECUTION_SUCCESS);
format = list->word->word;
tw = 0;
garglist = list->next;
@@ -189,14 +252,14 @@ printf_builtin (list)
/* A NULL third argument to tescape means to bypass the
special processing for arguments to %b. */
fmt += tescape (fmt, &nextch, (int *)NULL);
putchar (nextch);
PC (nextch);
fmt--; /* for loop will increment it for us again */
continue;
}
if (*fmt != '%')
{
putchar (*fmt);
PC (*fmt);
continue;
}
@@ -205,7 +268,7 @@ printf_builtin (list)
if (*fmt == '%') /* %% prints a % */
{
putchar ('%');
PC ('%');
continue;
}
@@ -544,15 +607,15 @@ printstr (fmt, string, len, fieldwidth, precision)
/* leading pad characters */
for (; padlen > 0; padlen--)
putchar (' ');
PC (' ');
/* output NC characters from STRING */
for (i = 0; i < nc; i++)
putchar (string[i]);
PC (string[i]);
/* output any necessary trailing padding */
for (; padlen < 0; padlen++)
putchar (' ');
PC (' ');
return (ferror (stdout) ? -1 : 0);
}
@@ -712,6 +775,35 @@ bexpand (string, len, sawc, lenp)
return ret;
}
static char *
vbadd (buf, blen)
char *buf;
int blen;
{
size_t nlen;
nlen = vblen + blen + 1;
if (nlen >= vbsize)
{
vbsize = ((nlen + 63) >> 6) << 6;
vbuf = (char *)xrealloc (vbuf, vbsize);
}
if (blen == 1)
vbuf[vblen++] = buf[0];
else
{
FASTCOPY (buf, vbuf + vblen, blen);
vblen += blen;
}
vbuf[vblen] = '\0';
if (strlen (vbuf) != vblen)
internal_error ("printf:vbadd: vblen (%d) != strlen (vbuf) (%d)", vblen, strlen (vbuf));
return vbuf;
}
static char *
mklong (str, modifiers, mlen)
char *str;