mirror of
https://github.com/postgres/postgres.git
synced 2025-07-11 10:01:57 +03:00
Implement %m in src/port/snprintf.c, and teach elog.c to rely on that.
I started out with the idea that we needed to detect use of %m format specs in contexts other than elog/ereport calls, because we couldn't rely on that working in *printf calls. But a better answer is to fix things so that it does work. Now that we're using snprintf.c all the time, we can implement %m in that and we've fixed the problem. This requires also adjusting our various printf-wrapping functions so that they ensure "errno" is preserved when they call snprintf.c. Remove elog.c's handmade implementation of %m, and let it rely on snprintf to support the feature. That should provide some performance gain, though I've not attempted to measure it. There are a lot of places where we could now simplify 'printf("%s", strerror(errno))' into 'printf("%m")', but I'm not in any big hurry to make that happen. Patch by me, reviewed by Michael Paquier Discussion: https://postgr.es/m/2975.1526862605@sss.pgh.pa.us
This commit is contained in:
@ -64,6 +64,14 @@
|
||||
*
|
||||
* 5. Space and '#' flags are not implemented.
|
||||
*
|
||||
* In addition, we support some extensions over C99:
|
||||
*
|
||||
* 1. Argument order control through "%n$" and "*n$", as required by POSIX.
|
||||
*
|
||||
* 2. "%m" expands to the value of strerror(errno), where errno is the
|
||||
* value that variable had at the start of the call. This is a glibc
|
||||
* extension, but a very useful one.
|
||||
*
|
||||
*
|
||||
* Historically the result values of sprintf/snprintf varied across platforms.
|
||||
* This implementation now follows the C99 standard:
|
||||
@ -155,6 +163,13 @@ static void flushbuffer(PrintfTarget *target);
|
||||
static void dopr(PrintfTarget *target, const char *format, va_list args);
|
||||
|
||||
|
||||
/*
|
||||
* Externally visible entry points.
|
||||
*
|
||||
* All of these are just wrappers around dopr(). Note it's essential that
|
||||
* they not change the value of "errno" before reaching dopr().
|
||||
*/
|
||||
|
||||
int
|
||||
pg_vsnprintf(char *str, size_t count, const char *fmt, va_list args)
|
||||
{
|
||||
@ -315,11 +330,12 @@ static void trailing_pad(int *padlen, PrintfTarget *target);
|
||||
|
||||
|
||||
/*
|
||||
* dopr(): poor man's version of doprintf
|
||||
* dopr(): the guts of *printf for all cases.
|
||||
*/
|
||||
static void
|
||||
dopr(PrintfTarget *target, const char *format, va_list args)
|
||||
{
|
||||
int save_errno = errno;
|
||||
const char *format_start = format;
|
||||
int ch;
|
||||
bool have_dollar;
|
||||
@ -497,6 +513,7 @@ nextch1:
|
||||
else
|
||||
have_non_dollar = true;
|
||||
break;
|
||||
case 'm':
|
||||
case '%':
|
||||
break;
|
||||
}
|
||||
@ -802,6 +819,15 @@ nextch2:
|
||||
precision, pointflag,
|
||||
target);
|
||||
break;
|
||||
case 'm':
|
||||
{
|
||||
char errbuf[PG_STRERROR_R_BUFLEN];
|
||||
const char *errm = strerror_r(save_errno,
|
||||
errbuf, sizeof(errbuf));
|
||||
|
||||
dostr(errm, strlen(errm), target);
|
||||
}
|
||||
break;
|
||||
case '%':
|
||||
dopr_outch('%', target);
|
||||
break;
|
||||
|
Reference in New Issue
Block a user