1
0
Fork 0
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:
Oliver Kiddle 2001-10-15 11:34:27 +00:00
parent 0e6f265516
commit 577ebe0b8a
3 changed files with 87 additions and 55 deletions

View file

@ -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.

View file

@ -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

View file

@ -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 */