Skip to content

Commit fc9f0d8

Browse files
Printf format style params decoration (#4625)
1 parent 64177d1 commit fc9f0d8

File tree

6 files changed

+134
-32
lines changed

6 files changed

+134
-32
lines changed

pjlib/include/pj/errno.h

Lines changed: 53 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,52 @@ PJ_DECL(pj_str_t) pj_strerror( pj_status_t statcode,
190190
pj_perror_wrapper_##level(arg); \
191191
} while (0)
192192

193+
/**
194+
* A utility macro to print error message pertaining to the specified error
195+
* code to the log. This macro will construct the error message title
196+
* according to the 'title_fmt' argument, and add the error string pertaining
197+
* to the error code after the title string. A colon (':') will be added
198+
* automatically between the title and the error string.
199+
*
200+
* This function is similar to pj_perror() function, but has the advantage
201+
* that the function call can be omitted from the link process if the
202+
* log level argument is below PJ_LOG_MAX_LEVEL threshold.
203+
*
204+
* Note that the title string constructed from the title_fmt will be built on
205+
* a string buffer which size is PJ_PERROR_TITLE_BUF_SIZE, which normally is
206+
* allocated from the stack. By default this buffer size is small (around
207+
* 120 characters). Application MUST ensure that the constructed title string
208+
* will not exceed this limit, since not all platforms support truncating
209+
* the string.
210+
*
211+
* @see pj_perror()
212+
*
213+
* @param LVL The logging verbosity level, valid values are 0-6. Lower
214+
* number indicates higher importance, with level zero
215+
* indicates fatal error. Variable argument is not permitted,
216+
* the argument may be a numeral constant or a numeral value
217+
* macros.
218+
* @param arg Enclosed 'printf' like arguments, with the following
219+
* arguments:
220+
* @param sender the sender (NULL terminated string),
221+
* @param status the error code (pj_status_t)
222+
* @param title_fmt the printf style format string, and optional variable
223+
* number of arguments suitable for the format string.
224+
*
225+
* Sample:
226+
* \verbatim
227+
#ifdef PJ_DEBUG
228+
# define MY_ERROR_LEVEL 1
229+
#else
230+
# define MY_ERROR_LEVEL 2
231+
#endif
232+
PJ_PERROR_(MY_ERROR_LEVEL, __FILE__, PJ_EBUSY, "Error making %s", "coffee");
233+
\endverbatim
234+
* @hideinitializer
235+
*/
236+
#define PJ_PERROR_(LVL, sender, status, title_fmt, ...) \
237+
PJ_PERROR(LVL,(sender,status,title_fmt, __VA_ARGS__))
238+
193239
/**
194240
* A utility function to print error message pertaining to the specified error
195241
* code to the log. This function will construct the error message title
@@ -213,7 +259,7 @@ PJ_DECL(pj_str_t) pj_strerror( pj_status_t statcode,
213259
* @see PJ_PERROR()
214260
*/
215261
PJ_DECL(void) pj_perror(int log_level, const char *sender, pj_status_t status,
216-
const char *title_fmt, ...)
262+
PJ_PRINT_PARAM_DECOR const char *title_fmt, ...)
217263
PJ_PRINT_FUNC_DECOR(4);
218264

219265

@@ -512,7 +558,7 @@ void pj_errno_clear_handlers(void);
512558
#define pj_perror_wrapper_1(arg) pj_perror_1 arg
513559
/** Internal function. */
514560
PJ_DECL(void) pj_perror_1(const char *sender, pj_status_t status,
515-
const char *title_fmt, ...)
561+
PJ_PRINT_PARAM_DECOR const char *title_fmt, ...)
516562
PJ_PRINT_FUNC_DECOR(3);
517563
#else
518564
#define pj_perror_wrapper_1(arg)
@@ -528,7 +574,7 @@ void pj_errno_clear_handlers(void);
528574
#define pj_perror_wrapper_2(arg) pj_perror_2 arg
529575
/** Internal function. */
530576
PJ_DECL(void) pj_perror_2(const char *sender, pj_status_t status,
531-
const char *title_fmt, ...)
577+
PJ_PRINT_PARAM_DECOR const char *title_fmt, ...)
532578
PJ_PRINT_FUNC_DECOR(3);
533579
#else
534580
#define pj_perror_wrapper_2(arg)
@@ -544,7 +590,7 @@ void pj_errno_clear_handlers(void);
544590
#define pj_perror_wrapper_3(arg) pj_perror_3 arg
545591
/** Internal function. */
546592
PJ_DECL(void) pj_perror_3(const char *sender, pj_status_t status,
547-
const char *title_fmt, ...)
593+
PJ_PRINT_PARAM_DECOR const char *title_fmt, ...)
548594
PJ_PRINT_FUNC_DECOR(3);
549595
#else
550596
#define pj_perror_wrapper_3(arg)
@@ -560,7 +606,7 @@ void pj_errno_clear_handlers(void);
560606
#define pj_perror_wrapper_4(arg) pj_perror_4 arg
561607
/** Internal function. */
562608
PJ_DECL(void) pj_perror_4(const char *sender, pj_status_t status,
563-
const char *title_fmt, ...)
609+
PJ_PRINT_PARAM_DECOR const char *title_fmt, ...)
564610
PJ_PRINT_FUNC_DECOR(3);
565611
#else
566612
#define pj_perror_wrapper_4(arg)
@@ -576,7 +622,7 @@ void pj_errno_clear_handlers(void);
576622
#define pj_perror_wrapper_5(arg) pj_perror_5 arg
577623
/** Internal function. */
578624
PJ_DECL(void) pj_perror_5(const char *sender, pj_status_t status,
579-
const char *title_fmt, ...)
625+
PJ_PRINT_PARAM_DECOR const char *title_fmt, ...)
580626
PJ_PRINT_FUNC_DECOR(3);
581627
#else
582628
#define pj_perror_wrapper_5(arg)
@@ -592,7 +638,7 @@ void pj_errno_clear_handlers(void);
592638
#define pj_perror_wrapper_6(arg) pj_perror_6 arg
593639
/** Internal function. */
594640
PJ_DECL(void) pj_perror_6(const char *sender, pj_status_t status,
595-
const char *title_fmt, ...)
641+
PJ_PRINT_PARAM_DECOR const char *title_fmt, ...)
596642
PJ_PRINT_FUNC_DECOR(3);
597643
#else
598644
#define pj_perror_wrapper_6(arg)

pjlib/include/pj/log.h

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,31 @@ enum pj_log_decoration
109109
} \
110110
} while (0)
111111

112+
/**
113+
* Write log message.
114+
*
115+
* @param LVL The logging verbosity level. Lower number indicates higher
116+
* importance, with level zero indicates fatal error. Variable
117+
* argument is not permitted, the argument may be a numeral
118+
* constant or a numeral value macros.
119+
* @param src The first argument is the sender.
120+
* @param format The second argument is 'printf' like format string and
121+
* the following arguments are variable number of
122+
* arguments suitable for the format string.
123+
*
124+
* Sample:
125+
* \verbatim
126+
#ifdef PJ_DEBUG
127+
# define MY_LOG_LEVEL 2
128+
#else
129+
# define MY_LOG_LEVEL 6
130+
#endif
131+
PJ_LOG_(MY_LOG_LEVEL, __FILE__, "current value is %d", value);
132+
\endverbatim
133+
* @hideinitializer
134+
*/
135+
#define PJ_LOG_(LVL, src, format, ...) PJ_LOG(LVL,(src, format, __VA_ARGS__))
136+
112137
/**
113138
* Signature for function to be registered to the logging subsystem to
114139
* write the actual log message to some output device.
@@ -143,7 +168,7 @@ PJ_DECL(void) pj_log_write(int level, const char *buffer, int len);
143168
* @param marker Marker.
144169
*/
145170
PJ_DECL(void) pj_log(const char *sender, int level,
146-
const char *format, va_list marker);
171+
PJ_PRINT_PARAM_DECOR const char *format, va_list marker);
147172

148173
/**
149174
* Change log output function. The front-end logging functions will call
@@ -406,7 +431,8 @@ pj_status_t pj_log_init(void);
406431
#if PJ_LOG_MAX_LEVEL >= 1
407432
#define pj_log_wrapper_1(arg) pj_log_1 arg
408433
/** Internal function. */
409-
PJ_DECL(void) pj_log_1(const char *src, const char *format, ...)
434+
PJ_DECL(void) pj_log_1(const char *src,
435+
PJ_PRINT_PARAM_DECOR const char *format, ...)
410436
PJ_PRINT_FUNC_DECOR(2);
411437
#else
412438
#define pj_log_wrapper_1(arg)
@@ -421,7 +447,8 @@ pj_status_t pj_log_init(void);
421447
#if PJ_LOG_MAX_LEVEL >= 2
422448
#define pj_log_wrapper_2(arg) pj_log_2 arg
423449
/** Internal function. */
424-
PJ_DECL(void) pj_log_2(const char *src, const char *format, ...)
450+
PJ_DECL(void) pj_log_2(const char *src,
451+
PJ_PRINT_PARAM_DECOR const char *format, ...)
425452
PJ_PRINT_FUNC_DECOR(2);
426453
#else
427454
#define pj_log_wrapper_2(arg)
@@ -436,7 +463,8 @@ pj_status_t pj_log_init(void);
436463
#if PJ_LOG_MAX_LEVEL >= 3
437464
#define pj_log_wrapper_3(arg) pj_log_3 arg
438465
/** Internal function. */
439-
PJ_DECL(void) pj_log_3(const char *src, const char *format, ...)
466+
PJ_DECL(void) pj_log_3(const char *src,
467+
PJ_PRINT_PARAM_DECOR const char *format, ...)
440468
PJ_PRINT_FUNC_DECOR(2);
441469
#else
442470
#define pj_log_wrapper_3(arg)
@@ -451,7 +479,8 @@ pj_status_t pj_log_init(void);
451479
#if PJ_LOG_MAX_LEVEL >= 4
452480
#define pj_log_wrapper_4(arg) pj_log_4 arg
453481
/** Internal function. */
454-
PJ_DECL(void) pj_log_4(const char *src, const char *format, ...)
482+
PJ_DECL(void) pj_log_4(const char *src,
483+
PJ_PRINT_PARAM_DECOR const char *format, ...)
455484
PJ_PRINT_FUNC_DECOR(2);
456485
#else
457486
#define pj_log_wrapper_4(arg)
@@ -466,7 +495,8 @@ pj_status_t pj_log_init(void);
466495
#if PJ_LOG_MAX_LEVEL >= 5
467496
#define pj_log_wrapper_5(arg) pj_log_5 arg
468497
/** Internal function. */
469-
PJ_DECL(void) pj_log_5(const char *src, const char *format, ...)
498+
PJ_DECL(void) pj_log_5(const char *src,
499+
PJ_PRINT_PARAM_DECOR const char *format, ...)
470500
PJ_PRINT_FUNC_DECOR(2);
471501
#else
472502
#define pj_log_wrapper_5(arg)
@@ -481,7 +511,8 @@ pj_status_t pj_log_init(void);
481511
#if PJ_LOG_MAX_LEVEL >= 6
482512
#define pj_log_wrapper_6(arg) pj_log_6 arg
483513
/** Internal function. */
484-
PJ_DECL(void) pj_log_6(const char *src, const char *format, ...)
514+
PJ_DECL(void) pj_log_6(const char *src,
515+
PJ_PRINT_PARAM_DECOR const char *format, ...)
485516
PJ_PRINT_FUNC_DECOR(2);
486517
#else
487518
#define pj_log_wrapper_6(arg)

pjlib/include/pj/types.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,17 @@ typedef int pj_exception_id_t;
330330
# define PJ_PRINT_FUNC_DECOR(idx)
331331
#endif
332332

333+
/**
334+
* We need to tell the compiler that the function arguments is of printf
335+
* style, so the compiler can check the code more carefully and
336+
* generate the appropriate warnings, if necessary.
337+
*/
338+
#if defined(_In_z_) && defined(_Printf_format_string_)
339+
# define PJ_PRINT_PARAM_DECOR _In_z_ _Printf_format_string_
340+
#else
341+
# define PJ_PRINT_PARAM_DECOR
342+
#endif
343+
333344
/* ************************************************************************* */
334345
/*
335346
* General.

pjlib/src/pj/errno.c

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,8 @@ PJ_DEF(pj_str_t) pj_strerror( pj_status_t statcode,
215215
}
216216

217217
#if PJ_LOG_MAX_LEVEL >= 1
218-
static void invoke_log(const char *sender, int level, const char *format, ...)
218+
static void invoke_log(const char *sender, int level,
219+
PJ_PRINT_PARAM_DECOR const char *format, ...)
219220
{
220221
va_list arg;
221222
va_start(arg, format);
@@ -225,14 +226,21 @@ static void invoke_log(const char *sender, int level, const char *format, ...)
225226

226227
static void pj_perror_imp(int log_level, const char *sender,
227228
pj_status_t status,
228-
const char *title_fmt, va_list marker)
229+
PJ_PRINT_PARAM_DECOR const char *title_fmt,
230+
va_list marker)
229231
{
230232
char titlebuf[PJ_PERROR_TITLE_BUF_SIZE];
231233
char errmsg[PJ_ERR_MSG_SIZE];
232234
int len;
233235

234236
/* Build the title */
235237
len = pj_ansi_vsnprintf(titlebuf, sizeof(titlebuf), title_fmt, marker);
238+
if (len < 0) {
239+
/* if you see this message in your log, please increase or set
240+
PJ_PERROR_TITLE_BUF_SIZE in your config_site.h */
241+
len = pj_ansi_snprintf(titlebuf, sizeof(titlebuf),
242+
"<pj_perror_imp error: msg too long>");
243+
}
236244
if (len < 0 || len >= (int)sizeof(titlebuf))
237245
pj_ansi_strxcpy(titlebuf, "Error", sizeof(titlebuf));
238246

@@ -244,7 +252,7 @@ static void pj_perror_imp(int log_level, const char *sender,
244252
}
245253

246254
PJ_DEF(void) pj_perror(int log_level, const char *sender, pj_status_t status,
247-
const char *title_fmt, ...)
255+
PJ_PRINT_PARAM_DECOR const char *title_fmt, ...)
248256
{
249257
va_list marker;
250258
va_start(marker, title_fmt);
@@ -253,7 +261,7 @@ PJ_DEF(void) pj_perror(int log_level, const char *sender, pj_status_t status,
253261
}
254262

255263
PJ_DEF(void) pj_perror_1(const char *sender, pj_status_t status,
256-
const char *title_fmt, ...)
264+
PJ_PRINT_PARAM_DECOR const char *title_fmt, ...)
257265
{
258266
va_list marker;
259267
va_start(marker, title_fmt);
@@ -263,15 +271,15 @@ PJ_DEF(void) pj_perror_1(const char *sender, pj_status_t status,
263271

264272
#else /* #if PJ_LOG_MAX_LEVEL >= 1 */
265273
PJ_DEF(void) pj_perror(int log_level, const char *sender, pj_status_t status,
266-
const char *title_fmt, ...)
274+
PJ_PRINT_PARAM_DECOR const char *title_fmt, ...)
267275
{
268276
}
269277
#endif /* #if PJ_LOG_MAX_LEVEL >= 1 */
270278

271279

272280
#if PJ_LOG_MAX_LEVEL >= 2
273281
PJ_DEF(void) pj_perror_2(const char *sender, pj_status_t status,
274-
const char *title_fmt, ...)
282+
PJ_PRINT_PARAM_DECOR const char *title_fmt, ...)
275283
{
276284
va_list marker;
277285
va_start(marker, title_fmt);
@@ -282,7 +290,7 @@ PJ_DEF(void) pj_perror_2(const char *sender, pj_status_t status,
282290

283291
#if PJ_LOG_MAX_LEVEL >= 3
284292
PJ_DEF(void) pj_perror_3(const char *sender, pj_status_t status,
285-
const char *title_fmt, ...)
293+
PJ_PRINT_PARAM_DECOR const char *title_fmt, ...)
286294
{
287295
va_list marker;
288296
va_start(marker, title_fmt);
@@ -293,7 +301,7 @@ PJ_DEF(void) pj_perror_3(const char *sender, pj_status_t status,
293301

294302
#if PJ_LOG_MAX_LEVEL >= 4
295303
PJ_DEF(void) pj_perror_4(const char *sender, pj_status_t status,
296-
const char *title_fmt, ...)
304+
PJ_PRINT_PARAM_DECOR const char *title_fmt, ...)
297305
{
298306
va_list marker;
299307
va_start(marker, title_fmt);
@@ -304,7 +312,7 @@ PJ_DEF(void) pj_perror_4(const char *sender, pj_status_t status,
304312

305313
#if PJ_LOG_MAX_LEVEL >= 5
306314
PJ_DEF(void) pj_perror_5(const char *sender, pj_status_t status,
307-
const char *title_fmt, ...)
315+
PJ_PRINT_PARAM_DECOR const char *title_fmt, ...)
308316
{
309317
va_list marker;
310318
va_start(marker, title_fmt);
@@ -315,7 +323,7 @@ PJ_DEF(void) pj_perror_5(const char *sender, pj_status_t status,
315323

316324
#if PJ_LOG_MAX_LEVEL >= 6
317325
PJ_DEF(void) pj_perror_6(const char *sender, pj_status_t status,
318-
const char *title_fmt, ...)
326+
PJ_PRINT_PARAM_DECOR const char *title_fmt, ...)
319327
{
320328
va_list marker;
321329
va_start(marker, title_fmt);

0 commit comments

Comments
 (0)