mirror of
git://git.code.sf.net/p/zsh/code
synced 2025-10-17 12:41:14 +02:00
use arithmetic evaluation for numeric arguments to printf (16042)
This commit is contained in:
parent
0e6f265516
commit
577ebe0b8a
3 changed files with 87 additions and 55 deletions
|
@ -1,3 +1,8 @@
|
||||||
|
2001-10-15 Oliver Kiddle <opk@zsh.org>
|
||||||
|
|
||||||
|
* 16042: Src/builtin.c, Doc/Zsh/builtins.yo: use arithmetic
|
||||||
|
evaluation for numeric arguments to printf
|
||||||
|
|
||||||
2001-10-15 Sven Wischnowsky <wischnow@zsh.org>
|
2001-10-15 Sven Wischnowsky <wischnow@zsh.org>
|
||||||
|
|
||||||
* Bart: 16038 and 16041: Src/cond.c, Src/loop.c: for caching of
|
* Bart: 16038 and 16041: Src/cond.c, Src/loop.c: for caching of
|
||||||
|
@ -35,7 +40,7 @@
|
||||||
|
|
||||||
2001-10-10 Oliver Kiddle <opk@zsh.org>
|
2001-10-10 Oliver Kiddle <opk@zsh.org>
|
||||||
|
|
||||||
* 16xxx: acconfig.h, zshconfig.ac, Etc/MACHINES,
|
* 16018: acconfig.h, zshconfig.ac, Etc/MACHINES,
|
||||||
Test/C02cond.ztst: allow dynamic loading to work on MacOS X
|
Test/C02cond.ztst: allow dynamic loading to work on MacOS X
|
||||||
if the dlcompat library is installed.
|
if the dlcompat library is installed.
|
||||||
|
|
||||||
|
|
|
@ -732,8 +732,10 @@ recognised and `tt(%q)' can be used to quote the argument in such a way
|
||||||
that allows it to be reused as shell input. With the numeric format
|
that allows it to be reused as shell input. With the numeric format
|
||||||
specifiers, if the corresponding argument starts with a quote character,
|
specifiers, if the corresponding argument starts with a quote character,
|
||||||
the numeric value of the following character is used as the number to
|
the numeric value of the following character is used as the number to
|
||||||
print. With `tt(%n)', the corresponding argument is taken as an identifier
|
print otherwise the argument is evaluated as an arithmetic expression. See
|
||||||
which is created as an integer parameter.
|
noderef(Arithmetic Evaluation) for a description of arithmetic
|
||||||
|
expressions. With `tt(%n)', the corresponding argument is taken as an
|
||||||
|
identifier which is created as an integer parameter.
|
||||||
|
|
||||||
If arguments remain unused after formatting, the format string is reused
|
If arguments remain unused after formatting, the format string is reused
|
||||||
until all arguments have been consumed. If more arguments are required by
|
until all arguments have been consumed. If more arguments are required by
|
||||||
|
|
129
Src/builtin.c
129
Src/builtin.c
|
@ -2883,32 +2883,27 @@ mod_export LinkList bufstack;
|
||||||
/* echo, print, printf, pushln */
|
/* echo, print, printf, pushln */
|
||||||
|
|
||||||
#define print_val(VAL) \
|
#define print_val(VAL) \
|
||||||
if (width >= 0) { \
|
if (prec >= 0) \
|
||||||
if (prec >= 0) \
|
count += fprintf(fout, spec, width, prec, VAL); \
|
||||||
count += fprintf(fout, start, width, prec, VAL); \
|
else \
|
||||||
else \
|
count += fprintf(fout, spec, width, VAL);
|
||||||
count += fprintf(fout, start, width, VAL); \
|
|
||||||
} else { \
|
|
||||||
if (prec >= 0) \
|
|
||||||
count += fprintf(fout, start, prec, VAL); \
|
|
||||||
else \
|
|
||||||
count += fprintf(fout, start, VAL); \
|
|
||||||
}
|
|
||||||
|
|
||||||
/**/
|
/**/
|
||||||
int
|
int
|
||||||
bin_print(char *name, char **args, char *ops, int func)
|
bin_print(char *name, char **args, char *ops, int func)
|
||||||
{
|
{
|
||||||
int flen, width, prec, type, argc, n, nnl = 0, ret = 0;
|
int flen, width, prec, type, argc, n, nnl = 0, ret = 0;
|
||||||
int *len;
|
int flags[5], *len;
|
||||||
char *start, *endptr, *c, *fmt = NULL;
|
char *start, *endptr, *c, *d, *flag, spec[11], *fmt = NULL;
|
||||||
char **first, nullstr = '\0', save = '\0';
|
char **first, *flagch = "0+- #", save, nullstr = '\0';
|
||||||
zlong count = 0;
|
zlong count = 0;
|
||||||
FILE *fout = stdout;
|
FILE *fout = stdout;
|
||||||
|
|
||||||
|
mnumber mnumval;
|
||||||
double doubleval;
|
double doubleval;
|
||||||
int intval;
|
int intval;
|
||||||
unsigned int uintval;
|
zlong zlongval;
|
||||||
|
zulong zulongval;
|
||||||
char *stringval;
|
char *stringval;
|
||||||
|
|
||||||
if (func == BIN_PRINTF) auxdata = *args++;
|
if (func == BIN_PRINTF) auxdata = *args++;
|
||||||
|
@ -2940,7 +2935,7 @@ bin_print(char *name, char **args, char *ops, int func)
|
||||||
len = (int *) hcalloc(argc * sizeof(int));
|
len = (int *) hcalloc(argc * sizeof(int));
|
||||||
for(n = 0; n < argc; n++) {
|
for(n = 0; n < argc; n++) {
|
||||||
/* first \ sequences */
|
/* first \ sequences */
|
||||||
if (fmt || !ops['e'] && (ops['R'] || ops['r'] || ops['E']))
|
if (fmt || (!ops['e'] && (ops['R'] || ops['r'] || ops['E'])))
|
||||||
unmetafy(args[n], &len[n]);
|
unmetafy(args[n], &len[n]);
|
||||||
else
|
else
|
||||||
args[n] = getkeystring(args[n], &len[n], ops['b'] ? 2 :
|
args[n] = getkeystring(args[n], &len[n], ops['b'] ? 2 :
|
||||||
|
@ -3098,6 +3093,7 @@ bin_print(char *name, char **args, char *ops, int func)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* printf style output */
|
/* printf style output */
|
||||||
|
*spec='%';
|
||||||
do {
|
do {
|
||||||
for (c = fmt;c-fmt < flen;c++) {
|
for (c = fmt;c-fmt < flen;c++) {
|
||||||
if (*c != '%') {
|
if (*c != '%') {
|
||||||
|
@ -3112,34 +3108,48 @@ bin_print(char *name, char **args, char *ops, int func)
|
||||||
++count;
|
++count;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
type = prec = width = -1;
|
|
||||||
|
|
||||||
if (strchr("+- #", *c)) c++;
|
type = prec = -1;
|
||||||
|
width = 0;
|
||||||
|
d = spec + 1;
|
||||||
|
|
||||||
|
/* copy only one of each flag as spec has finite size */
|
||||||
|
memset(flags, 0, sizeof(flags));
|
||||||
|
while (flag = strchr(flagch, *c)) {
|
||||||
|
if (!flags[flag - flagch]) {
|
||||||
|
flags[flag - flagch] = 1;
|
||||||
|
*d++ = *c;
|
||||||
|
}
|
||||||
|
c++;
|
||||||
|
}
|
||||||
|
|
||||||
if (*c == '*') {
|
if (*c == '*') {
|
||||||
width = (*args) ? strtoul(*args++, NULL, 0) : 0;
|
if (*args) width = (int)mathevali(*args++);
|
||||||
c++;
|
c++;
|
||||||
} else {
|
} else if (idigit(*c)) {
|
||||||
while (idigit(*c)) c++;
|
width = strtoul(c, &endptr, 0);
|
||||||
|
c = endptr;
|
||||||
}
|
}
|
||||||
|
*d++ = '*';
|
||||||
|
|
||||||
if (*c == '.') {
|
if (*c == '.') {
|
||||||
c++;
|
c++;
|
||||||
if (*c == '*') {
|
if (*c == '*') {
|
||||||
prec = (*args) ? strtoul(*args++, NULL, 0) : 0;
|
prec = (*args) ? (int)mathevali(*args++) : 0;
|
||||||
c++;
|
c++;
|
||||||
} else {
|
} else if (idigit(*c)) {
|
||||||
while (idigit(*c)) c++;
|
prec = strtoul(c, &endptr, 0);
|
||||||
|
c = endptr;
|
||||||
}
|
}
|
||||||
|
if (prec >= 0) *d++ = '.', *d++ = '*';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ignore any size modifier */
|
||||||
if (*c == 'l' || *c == 'L' || *c == 'h') c++;
|
if (*c == 'l' || *c == 'L' || *c == 'h') c++;
|
||||||
|
|
||||||
if (*c) {
|
errflag = 0;
|
||||||
save = c[1];
|
d[1] = '\0';
|
||||||
c[1] = '\0';
|
switch (*d = *c) {
|
||||||
}
|
|
||||||
switch (*c) {
|
|
||||||
case 'c':
|
case 'c':
|
||||||
if (*args) {
|
if (*args) {
|
||||||
intval = **args;
|
intval = **args;
|
||||||
|
@ -3162,7 +3172,7 @@ bin_print(char *name, char **args, char *ops, int func)
|
||||||
break;
|
break;
|
||||||
case 'q':
|
case 'q':
|
||||||
stringval = *args ? bslashquote(*args++, NULL, 0) : &nullstr;
|
stringval = *args ? bslashquote(*args++, NULL, 0) : &nullstr;
|
||||||
*c = 's';
|
*d = 's';
|
||||||
print_val(stringval);
|
print_val(stringval);
|
||||||
break;
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
|
@ -3186,50 +3196,65 @@ bin_print(char *name, char **args, char *ops, int func)
|
||||||
if (*args) setiparam(*args++, count);
|
if (*args) setiparam(*args++, count);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
zerrnam(name, "%s: invalid directive", start, 0);
|
if (*c) {
|
||||||
|
save = c[1];
|
||||||
|
c[1] = '\0';
|
||||||
|
}
|
||||||
|
zwarnnam(name, "%s: invalid directive", start, 0);
|
||||||
ret = 1;
|
ret = 1;
|
||||||
|
if (*c) c[1] = save;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type > 0) {
|
if (type > 0) {
|
||||||
if (*args && (**args == '\'' || **args == '"' )) {
|
if (*args && (**args == '\'' || **args == '"' )) {
|
||||||
if (type == 2) {
|
if (type == 2) {
|
||||||
doubleval = (*args)[1];
|
doubleval = (unsigned char)(*args)[1];
|
||||||
print_val(doubleval);
|
print_val(doubleval);
|
||||||
} else {
|
} else {
|
||||||
intval = (*args)[1];
|
intval = (unsigned char)(*args)[1];
|
||||||
print_val(intval);
|
print_val(intval);
|
||||||
}
|
}
|
||||||
args++;
|
args++;
|
||||||
} else {
|
} else {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 1:
|
case 1:
|
||||||
intval = (*args) ? strtol(*args, &endptr, 0) : 0;
|
#ifdef ZSH_64_BIT_TYPE
|
||||||
print_val(intval);
|
*d++ = 'l';
|
||||||
|
#endif
|
||||||
|
*d++ = 'l', *d++ = *c, *d = '\0';
|
||||||
|
zlongval = (*args) ? mathevali(*args++) : 0;
|
||||||
|
if (errflag) {
|
||||||
|
zlongval = 0;
|
||||||
|
errflag = 0;
|
||||||
|
}
|
||||||
|
print_val(zlongval)
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
doubleval = (*args) ? strtod(*args, &endptr) : 0;
|
if (*args) {
|
||||||
print_val(doubleval);
|
mnumval = matheval(*args++);
|
||||||
|
doubleval = (mnumval.type & MN_FLOAT) ?
|
||||||
|
mnumval.u.d : (double)mnumval.u.l;
|
||||||
|
} else doubleval = 0;
|
||||||
|
if (errflag) {
|
||||||
|
doubleval = 0;
|
||||||
|
errflag = 0;
|
||||||
|
}
|
||||||
|
print_val(doubleval)
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
uintval = (*args) ? strtoul(*args, &endptr, 0) : 0;
|
#ifdef ZSH_64_BIT_TYPE
|
||||||
print_val(uintval);
|
*d++ = 'l';
|
||||||
}
|
#endif
|
||||||
if (*args) {
|
*d++ = 'l', *d++ = *c, *d = '\0';
|
||||||
if (errno == ERANGE) {
|
zulongval = (*args) ? mathevali(*args++) : 0;
|
||||||
zerrnam(name, "`%s' arithmetic overflow", *args, 0);
|
if (errflag) {
|
||||||
ret = 1;
|
doubleval = 0;
|
||||||
} else if (**args && endptr == *args) {
|
errflag = 0;
|
||||||
zerrnam(name, "`%s' expected numeric value", endptr, 0);
|
|
||||||
ret = 1;
|
|
||||||
} else if (*endptr) {
|
|
||||||
zerrnam(name, "`%s' not completely converted", *args, 0);
|
|
||||||
ret = 1;
|
|
||||||
}
|
}
|
||||||
args++;
|
print_val(zulongval)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (*c) c[1] = save;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if there are remaining args, reuse format string */
|
/* if there are remaining args, reuse format string */
|
||||||
|
|
Loading…
Reference in a new issue