@@ -314,6 +314,93 @@ RCUTILS_PUBLIC
314314void
315315rcutils_reset_error (void );
316316
317+ // Helper macro for nested macro expansion
318+ #define _RCUTILS_EXPAND (x ) x
319+
320+ /// Set the error message, as well as append the current file, line number, and previous error.
321+ /**
322+ * If there is no previous error, has same behavior as RCUTILS_SET_ERROR_MSG.
323+ * \param[in] msg The error message to be set.
324+ */
325+ #define RCUTILS_SET_ERROR_MSG_AND_APPEND_PREV_ERROR (msg ) \
326+ do { \
327+ if (rcutils_error_is_set()) { \
328+ rcutils_error_string_t error_string = rcutils_get_error_string(); \
329+ rcutils_reset_error(); \
330+ RCUTILS_SET_ERROR_MSG_WITH_FORMAT_STRING( \
331+ _RCUTILS_EXPAND(msg ":\n%s"), error_string.str); \
332+ } else { \
333+ RCUTILS_SET_ERROR_MSG(msg); \
334+ } \
335+ } while (0)
336+
337+ /// Set the error message using a format string, format arguments, and previous error.
338+ /**
339+ * This function sets the error message using the given format string, and appends and resets the
340+ * latest error string.
341+ * The resulting formatted string is silently truncated at RCUTILS_ERROR_MESSAGE_MAX_LENGTH.
342+ *
343+ * If there is no previous error, has same behavior as RCUTILS_SET_ERROR_MSG_WITH_FORMAT_STRING.
344+ *
345+ * \param[in] format_string The string to be used as the format of the error message.
346+ * \param[in] ... Arguments for the format string.
347+ */
348+ #define RCUTILS_SET_ERROR_MSG_WITH_FORMAT_STRING_AND_APPEND_PREV_ERROR (format_string , ...) \
349+ do { \
350+ if (rcutils_error_is_set()) { \
351+ rcutils_error_string_t error_string = rcutils_get_error_string(); \
352+ rcutils_reset_error(); \
353+ RCUTILS_SET_ERROR_MSG_WITH_FORMAT_STRING( \
354+ _RCUTILS_EXPAND(format_string ":\n%s"), __VA_ARGS__, error_string.str); \
355+ } else { \
356+ RCUTILS_SET_ERROR_MSG_WITH_FORMAT_STRING(format_string, __VA_ARGS__); \
357+ } \
358+ } while (0)
359+
360+ /// Write the given msg out to stderr, limiting the buffer size in the `fwrite`, appending the
361+ /// previous error.
362+ /**
363+ * This will reset the previous error, if it exists.
364+ * If there is no previous error, has same behavior as RCUTILS_SAFE_FWRITE_TO_STDERR.
365+ */
366+ #define RCUTILS_SAFE_FWRITE_TO_STDERR_AND_APPEND_PREV_ERROR (msg ) \
367+ do { \
368+ if (rcutils_error_is_set()) { \
369+ rcutils_error_string_t error_string = rcutils_get_error_string(); \
370+ rcutils_reset_error(); \
371+ RCUTILS_SAFE_FWRITE_TO_STDERR_WITH_FORMAT_STRING( \
372+ _RCUTILS_EXPAND(msg ":\n%s"), error_string.str); \
373+ } else { \
374+ RCUTILS_SAFE_FWRITE_TO_STDERR(msg); \
375+ } \
376+ } while (0)
377+
378+ /// Set the error message to stderr using a format string and format arguments, appending the
379+ /// previous error.
380+ /**
381+ * This function sets the error message to stderr using the given format string, appending and
382+ * resetting the previous error..
383+ * The resulting formatted string is silently truncated at RCUTILS_ERROR_MESSAGE_MAX_LENGTH.
384+ *
385+ * This will reset the previous error, if it exists.
386+ * If there is no previous error, has same behavior as
387+ * RCUTILS_SAFE_FWRITE_TO_STDERR_WITH_FORMAT_STRING.
388+ *
389+ * \param[in] format_string The string to be used as the format of the error message.
390+ * \param[in] ... Arguments for the format string.
391+ */
392+ #define RCUTILS_SAFE_FWRITE_TO_STDERR_WITH_FORMAT_STRING_AND_APPEND_PREV_ERROR (format_string , ...) \
393+ do { \
394+ if (rcutils_error_is_set()) { \
395+ rcutils_error_string_t error_string = rcutils_get_error_string(); \
396+ rcutils_reset_error(); \
397+ RCUTILS_SAFE_FWRITE_TO_STDERR_WITH_FORMAT_STRING( \
398+ _RCUTILS_EXPAND(format_string ":\n%s"), __VA_ARGS__, error_string.str); \
399+ } else { \
400+ RCUTILS_SAFE_FWRITE_TO_STDERR_WITH_FORMAT_STRING(format_string, __VA_ARGS__); \
401+ } \
402+ } while (0)
403+
317404#ifdef __cplusplus
318405}
319406#endif
0 commit comments