Amend the previous change: we can have (almost) the best of both
worlds, as when the first arg (which should be the format) contains no % conversions, and there are more args, the results are unspecified (according to POSIX). We can use this so the previous usage printf -- format arg... (which is stupid, and pointless, but used to work) continues to simply ignore the -- (unspecified results mean we can do whatever feels good...) This brings back the #if 0'd block from the previous modification (so there is no longer anything that needs cleaning up later) but runs the getopt() loop it contained only when there are at least 2 args (so any 1 arg printf always uses that arg as the format string, whatever it contains, including just "--") and also only when the first (format) arg contains no '%' characters (which guarantees no % conversions without needing to actually parse the arg). This is the (or a) "unspecified results" case from POSIX, so we are free to do anything we like - including assuming that we might have options (we don't) and pretending to process them.
This commit is contained in:
parent
d3d2abdc28
commit
8ad10c91e9
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: printf.c,v 1.49 2019/07/21 15:25:39 kre Exp $ */
|
||||
/* $NetBSD: printf.c,v 1.50 2019/07/22 17:34:31 kre Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1989, 1993
|
||||
|
@ -41,7 +41,7 @@ __COPYRIGHT("@(#) Copyright (c) 1989, 1993\
|
|||
#if 0
|
||||
static char sccsid[] = "@(#)printf.c 8.2 (Berkeley) 3/22/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: printf.c,v 1.49 2019/07/21 15:25:39 kre Exp $");
|
||||
__RCSID("$NetBSD: printf.c,v 1.50 2019/07/22 17:34:31 kre Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
|
@ -138,27 +138,39 @@ main(int argc, char *argv[])
|
|||
|
||||
rval = 0; /* clear for builtin versions (avoid holdover) */
|
||||
|
||||
#if 0
|
||||
int o;
|
||||
|
||||
/*
|
||||
* printf does not comply with Posix XBD 12.2 - there are no opts,
|
||||
* not even the -- end of options marker. Do not run getoot().
|
||||
*/
|
||||
while ((o = getopt(argc, argv, "")) != -1) {
|
||||
switch (o) {
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
return 1;
|
||||
if (argc > 2 && strchr(argv[1], '%') == NULL) {
|
||||
int o;
|
||||
|
||||
/*
|
||||
* except that if there are multiple args and
|
||||
* the first (the nominal format) contains no '%'
|
||||
* conversions (which we will approximate as no '%'
|
||||
* characters at all, conversions or not) then the
|
||||
* results are unspecified, and we can do what we
|
||||
* like. So in that case, for some backward compat
|
||||
* to scripts which (stupidly) do:
|
||||
* printf -- format args
|
||||
* process this case the old way.
|
||||
*/
|
||||
|
||||
while ((o = getopt(argc, argv, "")) != -1) {
|
||||
switch (o) {
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
} else {
|
||||
argc -= 1; /* drop argv[0] (the program name) */
|
||||
argv += 1;
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
#else
|
||||
argc -= 1;
|
||||
argv += 1;
|
||||
#endif
|
||||
|
||||
if (argc < 1) {
|
||||
usage();
|
||||
|
|
Loading…
Reference in New Issue