]> granicus.if.org Git - strace/blob - xstring.h
tests: add support of multi-line diagnostics to check_h
[strace] / xstring.h
1 /*
2  * Copyright (c) 2018 Eugene Syromyatnikov <evgsyr@gmail.com>
3  * All rights reserved.
4  *
5  * SPDX-License-Identifier: LGPL-2.1-or-later
6  */
7
8 #ifndef STRACE_XSTRING_H
9 # define STRACE_XSTRING_H
10
11 # include <stdarg.h>
12 # include <stdio.h>
13
14 # include "error_prints.h"
15 # include "gcc_compat.h"
16
17 /**
18  * Print to static buffer and die on (really unexpected) errors and overflows.
19  * Shouldn't be used directly; please refer to helper macros xsnprintf and
20  * xsprint instead.
21  *
22  * @param str    String buffer to print into.
23  * @param size   Size of the string buffer in bytes.
24  * @param func   Function name from which this function is called.
25  * @param argstr Stringified arguments (including format argument).
26  * @param format Format string.
27  * @param ...    Format arguments.
28  * @return       Number of characters printed, excluding terminating null byte
29  *               (the same as s(n)printf).
30  */
31 static inline int ATTRIBUTE_FORMAT((printf, 5, 6))
32 xsnprintf_(char *str, size_t size, const char *func, const char *argstr,
33            const char *format, ...)
34 {
35         int ret;
36         va_list ap;
37
38         va_start(ap, format);
39         ret = vsnprintf(str, size, format, ap);
40         va_end(ap);
41
42         if (ret < 0 || (unsigned int) ret >= size)
43                 error_msg_and_die("%s: got unexpected return value %d for "
44                                   "snprintf(buf, %zu, %s)",
45                                   func, ret, size, argstr);
46
47         return ret;
48 }
49
50 /**
51  * snprintf that dies on (really unexpected) errors and overflows.
52  *
53  * @param str_  String buffer to print into.
54  * @param size_ Size of the string buffer in bytes.
55  * @param fmt_  Format string.
56  * @param ...   Format arguments.
57  */
58 # define xsnprintf(str_, size_, fmt_, ...) \
59         xsnprintf_((str_), (size_), __func__, #fmt_ ", " #__VA_ARGS__, \
60                    (fmt_), __VA_ARGS__)
61
62 /**
63  * Print to a character array buffer and die on (really unexpected) errors and
64  * overflows.  Buffer size is obtained with sizeof().
65  *
66  * @param str_  Character array buffer to print into.
67  * @param fmt_  Format string.
68  * @param ...   Format arguments.
69  */
70 # define xsprintf(str_, fmt_, ...) \
71         xsnprintf((str_), sizeof(str_) + MUST_BE_ARRAY(str_), (fmt_), \
72                   __VA_ARGS__)
73
74 static inline size_t
75 get_pos_diff_(char *str, size_t size, char *pos, const char *func,
76            const char *call)
77 {
78         if ((str + size) < str)
79                 error_msg_and_die("%s: string size overflow (%p+%zu) in %s",
80                                   func, str, size, call);
81
82         if (pos > (str + size))
83                 error_msg_and_die("%s: got position (%p) beyond string "
84                                   "(%p+%zu) in %s",
85                                   func, pos, str, size, call);
86
87         if (pos < str)
88                 error_msg_and_die("%s: got position %p before string %p in %s",
89                                   func, pos, str, call);
90
91         return pos - str;
92 }
93
94 /**
95  * Helper function for constructing string in a character array by appending
96  * new formatted parts.  Returns new position.  Fails on error or buffer
97  * overflow, in line with the rest of x* functions.  Obtains buffer size via
98  * sizeof(str_).
99  *
100  * @param str_  Character array buffer to print into.
101  * @param pos_  Current position.
102  * @param fmt_  Format string.
103  * @param ...   Format arguments.
104  * @return      New position.
105  */
106 # define xappendstr(str_, pos_, fmt_, ...) \
107         (xsnprintf((pos_), sizeof(str_) + MUST_BE_ARRAY(str_) - \
108                    get_pos_diff_((str_), sizeof(str_), (pos_), __func__, \
109                                  "xappendstr(" #str_ ", " #pos_ ", " #fmt_ ", " \
110                                  #__VA_ARGS__ ")"), \
111                    (fmt_), ##__VA_ARGS__) + (pos_))
112
113 #endif /* !STRACE_XSTRING_H */