* PATCH: various fixes to print builtin
@ 2005-07-31 13:36 Thorsten Dahlheimer
0 siblings, 0 replies; only message in thread
From: Thorsten Dahlheimer @ 2005-07-31 13:36 UTC (permalink / raw)
To: zsh-workers
[-- Attachment #1: Type: text/plain, Size: 2167 bytes --]
When I prepared the \c handling patch for the print builtin, I noticed
a couple of other (mostly minor) issues, which I've addressed in the
attached patch. They are:
- The '%b' specifier of printf gets the character count wrong when a
width is given:
% printf '%5b%n\n' abc count; echo $count
abc
3
- The output of a '%%' specifier and padding spaces from '%b' go to
stdout even if output has been redirected with one of the -u, -p,
-z, -s options:
% print -u3 -f 'a%3bc%%d\n' 'b' 3>fd3.out
%
% cat fd3.out
abcd
- When there's no argument left for a '%b', it does not behave as if
the argument were an empty string, but rather nothing is output at
all. This makes a difference if a width is given:
% printf '%s!%5b!\n' abc
abc!!
vs.
% printf '%s!%5b!\n' abc ''
abc! !
- The argument to a '%b' specifier gets passed to getkeystring() in
unmetafied form, and that may lead to wrong output:
% printf '%b\n' $'\x83 ' | od -tx1
0000000 00 0a
0000002
vs.
% echo $'\x83 ' | od -tx1
0000000 83 20 0a
0000003
- If both the -f and -c/-C options are given to print, the -f inhibits
the initial expansion of escape sequences in the argument strings,
but is then simply ignored:
% print -f 'arg: %b\n' -C2 '\x41' '\x42' '\x43'
\x41 \x43
\x42
vs.
% print -C2 '\x41' '\x42' '\x43'
A C
B
I've resolved this strange interaction by having -f completely
override -c/-C.
- If print -f output has been redirected with -u, -p, -z, or -s, and
an error aborts execution, the fout file isn't closed.
- In the builtins[] table, the BINF_PRINTOPTS flag is not necessary
for the echo and pushln commands, since these don't support the -R
option.
- I've replaced two (unsigned char) casts to STOUC invocations,
according to the advice in the zsh-development-guide.
- I've removed the 'count=mcount' assignment (in the last hunk)
because it is (a) unnecessary and (b) off by one, I think.
- I've slightly tweaked formatting in a few places.
Regards,
Thorsten Dahlheimer
[-- Attachment #2: print1.patch --]
[-- Type: application/octet-stream, Size: 8123 bytes --]
Index: Src/builtin.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/builtin.c,v
retrieving revision 1.141
diff -u -p -r1.141 builtin.c
--- Src/builtin.c 26 Jul 2005 00:07:11 -0000 1.141
+++ Src/builtin.c 30 Jul 2005 15:01:47 -0000
@@ -57,7 +57,7 @@ static struct builtin builtins[] =
BUILTIN("dirs", 0, bin_dirs, 0, -1, 0, "clpv", NULL),
BUILTIN("disable", 0, bin_enable, 0, -1, BIN_DISABLE, "afmrs", NULL),
BUILTIN("disown", 0, bin_fg, 0, -1, BIN_DISOWN, NULL, NULL),
- BUILTIN("echo", BINF_PRINTOPTS | BINF_SKIPINVALID, bin_print, 0, -1, BIN_ECHO, "neE", "-"),
+ BUILTIN("echo", BINF_SKIPINVALID, bin_print, 0, -1, BIN_ECHO, "neE", "-"),
BUILTIN("emulate", 0, bin_emulate, 1, 1, 0, "LR", NULL),
BUILTIN("enable", 0, bin_enable, 0, -1, BIN_ENABLE, "afmrs", NULL),
BUILTIN("eval", BINF_PSPECIAL, bin_eval, 0, -1, BIN_EVAL, NULL, NULL),
@@ -102,7 +102,7 @@ static struct builtin builtins[] =
BUILTIN("print", BINF_PRINTOPTS, bin_print, 0, -1, BIN_PRINT, "abcC:Df:ilmnNoOpPrRsu:z-", NULL),
BUILTIN("printf", 0, bin_print, 1, -1, BIN_PRINTF, NULL, NULL),
BUILTIN("pushd", BINF_SKIPINVALID | BINF_SKIPDASH | BINF_DASHDASHVALID, bin_cd, 0, 2, BIN_PUSHD, "sPL", NULL),
- BUILTIN("pushln", BINF_PRINTOPTS, bin_print, 0, -1, BIN_PRINT, NULL, "-nz"),
+ BUILTIN("pushln", 0, bin_print, 0, -1, BIN_PRINT, NULL, "-nz"),
BUILTIN("pwd", 0, bin_pwd, 0, 0, 0, "rLP", NULL),
BUILTIN("r", 0, bin_fc, 0, -1, BIN_R, "nrl", NULL),
BUILTIN("read", 0, bin_read, 0, -1, 0, "cd:ek:%lnpqrst:%zu:AE", NULL),
@@ -3283,11 +3283,11 @@ mod_export LinkList bufstack;
int
bin_print(char *name, char **args, Options ops, int func)
{
- int flen, width, prec, type, argc, n, narg;
+ int flen, width, prec, type, argc, n, narg, curlen;
int nnl = 0, fmttrunc = 0, ret = 0, maxarg = 0;
int flags[5], *len;
char *start, *endptr, *c, *d, *flag, *buf, spec[13], *fmt = NULL;
- char **first, *curarg, *flagch = "0+- #", save = '\0', nullstr = '\0';
+ char **first, **argp, *curarg, *flagch = "0+- #", save = '\0', nullstr = '\0';
size_t rcount, count = 0;
#ifdef HAVE_OPEN_MEMSTREAM
size_t mcount;
@@ -3330,7 +3330,7 @@ bin_print(char *name, char **args, Optio
tokenize(*args);
if (!(pprog = patcompile(*args, PAT_STATIC, NULL))) {
untokenize(*args);
- zwarnnam(name, "bad pattern : %s", *args, 0);
+ zwarnnam(name, "bad pattern: %s", *args, 0);
return 1;
}
for (t = p = ++args; *p; p++)
@@ -3440,7 +3440,7 @@ bin_print(char *name, char **args, Optio
len[n] = strlen(args[n]);
/* -c -- output in columns */
- if (OPT_ISSET(ops,'c') || OPT_ISSET(ops,'C')) {
+ if (!fmt && (OPT_ISSET(ops,'c') || OPT_ISSET(ops,'C'))) {
int l, nc, nr, sc, n, t, i;
char **ap;
@@ -3528,7 +3528,7 @@ bin_print(char *name, char **args, Optio
l = strlen(*ap);
fprintf(fout, "%s", *ap);
for (t = nr; t && *ap; t--, ap++);
- if(*ap)
+ if (*ap)
for (; l < sc; l++)
fputc(' ', fout);
} while (*ap);
@@ -3613,7 +3613,8 @@ bin_print(char *name, char **args, Optio
}
/* printf style output */
- *spec='%';
+ *spec = '%';
+ argp = args;
do {
rcount = count;
if (maxarg) {
@@ -3621,7 +3622,7 @@ bin_print(char *name, char **args, Optio
argc -= maxarg;
maxarg = 0;
}
- for (c = fmt;c-fmt < flen;c++) {
+ for (c = fmt; c-fmt < flen; c++) {
if (*c != '%') {
putc(*c, fout);
++count;
@@ -3630,7 +3631,7 @@ bin_print(char *name, char **args, Optio
start = c++;
if (*c == '%') {
- putchar('%');
+ putc('%', fout);
++count;
continue;
}
@@ -3648,14 +3649,16 @@ bin_print(char *name, char **args, Optio
if (narg > argc) {
zwarnnam(name, "%d: argument specifier out of range",
0, narg);
+ if (fout != stdout)
+ fclose(fout);
return 1;
} else {
if (narg > maxarg) maxarg = narg;
curarg = *(first + narg - 1);
+ curlen = len[first - args + narg - 1];
}
}
}
-
/* copy only one of each flag as spec has finite size */
memset(flags, 0, sizeof(flags));
@@ -3679,15 +3682,17 @@ bin_print(char *name, char **args, Optio
zwarnnam(name,
"%d: argument specifier out of range",
0, narg);
+ if (fout != stdout)
+ fclose(fout);
return 1;
} else {
if (narg > maxarg) maxarg = narg;
- args = first + narg - 1;
+ argp = first + narg - 1;
}
}
}
- if (*args) {
- width = (int)mathevali(*args++);
+ if (*argp) {
+ width = (int)mathevali(*argp++);
if (errflag) {
errflag = 0;
ret = 1;
@@ -3706,16 +3711,18 @@ bin_print(char *name, char **args, Optio
zwarnnam(name,
"%d: argument specifier out of range",
0, narg);
+ if (fout != stdout)
+ fclose(fout);
return 1;
} else {
if (narg > maxarg) maxarg = narg;
- args = first + narg - 1;
+ argp = first + narg - 1;
}
}
}
- if (*args) {
- prec = (int)mathevali(*args++);
+ if (*argp) {
+ prec = (int)mathevali(*argp++);
if (errflag) {
errflag = 0;
ret = 1;
@@ -3731,7 +3738,10 @@ bin_print(char *name, char **args, Optio
/* ignore any size modifier */
if (*c == 'l' || *c == 'L' || *c == 'h') c++;
- if (!curarg && *args) curarg = *args++;
+ if (!curarg && *argp) {
+ curarg = *argp;
+ curlen = len[argp++ - args];
+ }
d[1] = '\0';
switch (*d = *c) {
case 'c':
@@ -3748,24 +3758,24 @@ bin_print(char *name, char **args, Optio
case 'b':
if (curarg) {
int l;
- char *b = getkeystring(curarg, &l,
+ char *b = getkeystring(metafy(curarg, curlen, META_USEHEAP), &l,
OPT_ISSET(ops,'b') ? 2 : 0, &nnl);
/* handle width/precision here and use fwrite so that
* nul characters can be output */
if (prec >= 0 && prec < l) l = prec;
if (width > 0 && flags[2]) width = -width;
if (width > 0 && l < width)
- printf("%*c", width - l, ' ');
- fwrite(b, l, 1, fout);
+ count += fprintf(fout, "%*c", width - l, ' ');
+ count += fwrite(b, 1, l, fout);
if (width < 0 && l < -width)
- printf("%*c", -width - l, ' ');
- count += l;
+ count += fprintf(fout, "%*c", -width - l, ' ');
if (nnl) {
/* If the %b arg had a \c escape, truncate the fmt. */
flen = c - fmt + 1;
fmttrunc = 1;
}
- }
+ } else
+ count += fprintf(fout, "%*c", width, ' ');
break;
case 'q':
stringval = curarg ? bslashquote(curarg, NULL, 0) : &nullstr;
@@ -3810,10 +3820,10 @@ bin_print(char *name, char **args, Optio
if (type > 0) {
if (curarg && (*curarg == '\'' || *curarg == '"' )) {
if (type == 2) {
- doubleval = (unsigned char)curarg[1];
+ doubleval = STOUC(curarg[1]);
print_val(doubleval);
} else {
- intval = (unsigned char)curarg[1];
+ intval = STOUC(curarg[1]);
print_val(intval);
}
} else {
@@ -3859,19 +3869,18 @@ bin_print(char *name, char **args, Optio
}
}
}
- if (maxarg && (args - first > maxarg))
- maxarg = args - first;
+ if (maxarg && (argp - first > maxarg))
+ maxarg = argp - first;
}
- if (maxarg) args = first + maxarg;
+ if (maxarg) argp = first + maxarg;
/* if there are remaining args, reuse format string */
- } while (*args && args != first && !fmttrunc && !OPT_ISSET(ops,'r'));
+ } while (*argp && argp != first && !fmttrunc && !OPT_ISSET(ops,'r'));
if (OPT_ISSET(ops,'z') || OPT_ISSET(ops,'s')) {
#ifdef HAVE_OPEN_MEMSTREAM
putc(0, fout);
fflush(fout);
- count = mcount;
#else
rewind(fout);
buf = (char *)zalloc(count + 1);
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2005-07-31 13:29 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2005-07-31 13:36 PATCH: various fixes to print builtin Thorsten Dahlheimer
Code repositories for project(s) associated with this public inbox
https://git.vuxu.org/mirror/zsh/
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).