| 204 | } |
| 205 | |
| 206 | void |
| 207 | pg_log_generic_v(enum pg_log_level level, const char *pg_restrict fmt, va_list ap) |
| 208 | { |
| 209 | int save_errno = errno; |
| 210 | const char *filename = NULL; |
| 211 | uint64 lineno = 0; |
| 212 | va_list ap2; |
| 213 | size_t required_len; |
| 214 | char *buf; |
| 215 | |
| 216 | Assert(progname); |
| 217 | Assert(level); |
| 218 | Assert(fmt); |
| 219 | Assert(fmt[strlen(fmt) - 1] != '\n'); |
| 220 | |
| 221 | /* |
| 222 | * Flush stdout before output to stderr, to ensure sync even when stdout |
| 223 | * is buffered. |
| 224 | */ |
| 225 | fflush(stdout); |
| 226 | |
| 227 | if (log_pre_callback) |
| 228 | log_pre_callback(); |
| 229 | |
| 230 | if (log_locus_callback) |
| 231 | log_locus_callback(&filename, &lineno); |
| 232 | |
| 233 | fmt = _(fmt); |
| 234 | |
| 235 | if (!(log_flags & PG_LOG_FLAG_TERSE) || filename) |
| 236 | { |
| 237 | if (sgr_locus) |
| 238 | fprintf(stderr, ANSI_ESCAPE_FMT, sgr_locus); |
| 239 | if (!(log_flags & PG_LOG_FLAG_TERSE)) |
| 240 | fprintf(stderr, "%s:", progname); |
| 241 | if (filename) |
| 242 | { |
| 243 | fprintf(stderr, "%s:", filename); |
| 244 | if (lineno > 0) |
| 245 | fprintf(stderr, UINT64_FORMAT ":", lineno); |
| 246 | } |
| 247 | fprintf(stderr, " "); |
| 248 | if (sgr_locus) |
| 249 | fprintf(stderr, ANSI_ESCAPE_RESET); |
| 250 | } |
| 251 | |
| 252 | if (!(log_flags & PG_LOG_FLAG_TERSE)) |
| 253 | { |
| 254 | switch (level) |
| 255 | { |
| 256 | case PG_LOG_FATAL: |
| 257 | if (sgr_error) |
| 258 | fprintf(stderr, ANSI_ESCAPE_FMT, sgr_error); |
| 259 | fprintf(stderr, _("fatal: ")); |
| 260 | if (sgr_error) |
| 261 | fprintf(stderr, ANSI_ESCAPE_RESET); |
| 262 | break; |
| 263 | case PG_LOG_ERROR: |
no test coverage detected