BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bsla_nullterminated.h
Go to the documentation of this file.
1
/// @file bsla_nullterminated.h
2
///
3
/// The content of this file has been pre-processed for Doxygen.
4
///
5
6
7
// bsla_nullterminated.h -*-C++-*-
8
#ifndef INCLUDED_BSLA_NULLTERMINATED
9
#define INCLUDED_BSLA_NULLTERMINATED
10
11
#include <
bsls_ident.h
>
12
BSLS_IDENT
(
"$Id: $"
)
13
14
/// @defgroup bsla_nullterminated bsla_nullterminated
15
/// @brief Provide macros for use with `NULL`-terminated variadic functions.
16
/// @addtogroup bsl
17
/// @{
18
/// @addtogroup bsla
19
/// @{
20
/// @addtogroup bsla_nullterminated
21
/// @{
22
///
23
/// <h1> Outline </h1>
24
/// * <a href="#bsla_nullterminated-purpose"> Purpose</a>
25
/// * <a href="#bsla_nullterminated-macros"> Macros </a>
26
/// * <a href="#bsla_nullterminated-description"> Description </a>
27
/// * <a href="#bsla_nullterminated-macro-reference"> Macro Reference </a>
28
/// * <a href="#bsla_nullterminated-usage"> Usage </a>
29
/// * <a href="#bsla_nullterminated-example-1-catstrings-function"> Example 1: catStrings Function </a>
30
/// * <a href="#bsla_nullterminated-example-2-catverdict-function"> Example 2: catVerdict Function </a>
31
///
32
/// # Purpose {#bsla_nullterminated-purpose}
33
/// Provide macros for use with `NULL`-terminated variadic functions.
34
///
35
/// # Macros {#bsla_nullterminated-macros}
36
///
37
/// - BSLA_NULLTERMINATED: warn if last argument is not `NULL`
38
/// - BSLA_NULLTERMINATEDAT(ARG_IDX): warn if argument at `ARG_IDX` is not `NULL`
39
/// - BSLA_NULLTERMINATED_IS_ACTIVE: defined if `BSLA_NULLTERMINATED` is active
40
/// - BSLA_NULLTERMINATEDAT_IS_ACTIVE: defined if `BSLA_NULLTERMINATEDAT` active
41
///
42
/// @see bsla_annotations
43
///
44
/// # Description {#bsla_nullterminated-description}
45
/// This component provides preprocessor macros to indicate that a
46
/// variadic function's arguments are terminated by `NULL`, or, in the case of
47
/// `BSLA_NULLTERMINATEDAT`, by `NULL` at a certain index. Note that the
48
/// terminating `NULL` must actually be `NULL` or, with C++11, `nullptr`;
49
/// passing 0 in its place will result in a warning.
50
///
51
/// ## Macro Reference {#bsla_nullterminated-macro-reference}
52
///
53
///
54
/// `BSLA_NULLTERMINATED`:
55
/// This annotation on a variadic macro indicates that a warning should be
56
/// issued unless the last argument to the function is explicitly `NULL`.
57
///
58
/// `BSLA_NULLTERMINATEDAT(ARG_IDX)`:
59
/// This annotation on a variadic function indicates that a warning should
60
/// be issued unless the argument at `ARG_IDX` is `NULL`, where `ARG_IDX`
61
/// is the number of arguments from the last, the last argument having
62
/// `ARG_IDX == 0`. Thus, `BSLA_NULLTERMINATED` is equivalent to
63
/// `BSLA_NULLTERMINATEDAT(0)`.
64
///
65
/// `BSLA_NULLTERMINATED_IS_ACTIVE`:
66
/// The macro `BSLA_NULLTERMINATED_IS_ACTIVE` is defined if
67
/// `BSLA_NULLTERMINATED` expands to something with the desired effect;
68
/// otherwise `BSLA_NULLTERMINATED_IS_ACTIVE` is not defined and
69
/// `BSLA_NULLTERMINATED` expands to nothing.
70
///
71
/// `BSLA_NULLTERMINATEDAT_IS_ACTIVE`:
72
/// The macro `BSLA_NULLTERMINATEDAT_IS_ACTIVE` is defined if
73
/// `BSLA_NULLTERMINATEDAT` expands to something with the desired effect;
74
/// otherwise `BSLA_NULLTERMINATEDAT_IS_ACTIVE` is not defined and
75
/// `BSLA_NULLTERMINATEDAT` expands to nothing.
76
///
77
/// ## Usage {#bsla_nullterminated-usage}
78
///
79
///
80
/// This section illustrates intended use of this component.
81
///
82
/// ### Example 1: catStrings Function {#bsla_nullterminated-example-1-catstrings-function}
83
///
84
///
85
/// Suppose we want to have a function that, passed a variable length argument
86
/// list of `const char *` strings terminated by `NULL`, concatenates the
87
/// strings, separated by spaces, into a buffer.
88
///
89
/// First, we declare and define the function, annotated with
90
/// `BSLA_NULL_TERMINATED`:
91
/// @code
92
/// void catStrings(char *outputBuffer, ...) BSLA_NULLTERMINATED;
93
/// void catStrings(char *outputBuffer, ...)
94
/// // The specified 'outputBuffer' is a buffer where the output of this
95
/// // function is placed. The specified '...' is a 'NULL'-terminated list
96
/// // of 'const char *' strings, which are to be copied into
97
/// // 'outputBuffer', concatenated together and separated by spaces. The
98
/// // behavior is undefined unless the '...' is a 'NULL'-terminated list
99
/// // of 'const char *' arguments.
100
/// {
101
/// *outputBuffer = 0;
102
///
103
/// va_list ap;
104
/// va_start(ap, outputBuffer);
105
/// const char *next;
106
/// for (bool first = 1; (next = va_arg(ap, const char *)); first = 0) {
107
/// ::strcat(outputBuffer, first ? "" : " ");
108
/// ::strcat(outputBuffer, next);
109
/// }
110
/// va_end(ap);
111
/// }
112
/// @endcode
113
/// Then, in `main`, we call `catStrings` correctly:
114
/// @code
115
/// char buf[1000];
116
/// catStrings(buf, "Now", "you", "see", "it.", NULL);
117
/// printf("%s\n", buf);
118
/// @endcode
119
/// which compiles without a warning and produces the output:
120
/// @code
121
/// Now you see it.
122
/// @endcode
123
/// Now, we call `catStrings" again and forget to add the terminating `NULL':
124
/// @code
125
/// catStrings(buf, "Now", "you", "don't.");
126
/// printf("%s\n", buf);
127
/// @endcode
128
/// Finally, we get the compiler warning:
129
/// @code
130
/// .../bsla_nullterminated.t.cpp:412:47: warning: missing sentinel in function
131
/// call [-Wsentinel]
132
/// catStrings(buf, "Now", "you", "don't.");
133
/// ^
134
/// , nullptr
135
/// .../bsla_nullterminated.t.cpp:137:10: note: function has been explicitly
136
/// marked sentinel here
137
/// void catStrings(char *outputBuffer, ...)
138
/// ^
139
/// @endcode
140
///
141
/// ### Example 2: catVerdict Function {#bsla_nullterminated-example-2-catverdict-function}
142
///
143
///
144
/// Suppose we want to have a function that, passed a variable length argument
145
/// list of `const char *` strings terminated by `NULL`, concatenates the
146
/// strings, separated by spaces, into a buffer, and then there's an additional
147
/// integer argument, interpreted as a boolean, that determines what is to be
148
/// appended to the end of the buffer.
149
///
150
/// First, we declare and define the function, annotated with
151
/// `BSLA_NULL_TERMINATEDAT(1)`:
152
/// @code
153
/// void catVerdict(char *outputBuffer, ...) BSLA_NULLTERMINATEDAT(1);
154
/// void catVerdict(char *outputBuffer, ...)
155
/// // The specified 'outputBuffer' is a buffer where output is to be
156
/// // placed. All but the last 2 of the specified '...' arguments are
157
/// // 'const char *' strings to be concatenated together into
158
/// // 'outputBuffer', separated by spaces. The second-to-last argument is
159
/// // to be 'NULL', and the last argument is an 'int' interpreted as a
160
/// // boolean to determine whether the buffer is to end with a verdict of
161
/// // "guilty" or "not guilty". The behavior is undefined unless the
162
/// // types of all the arguments are correct and the second to last
163
/// // argument is 'NULL'.
164
/// {
165
/// *outputBuffer = 0;
166
///
167
/// va_list ap;
168
/// va_start(ap, outputBuffer);
169
/// const char *next;
170
/// for (bool first = 1; (next = va_arg(ap, const char *)); first = 0) {
171
/// ::strcat(outputBuffer, first ? "" : " ");
172
/// ::strcat(outputBuffer, next);
173
/// }
174
///
175
/// const bool guilty = va_arg(ap, int);
176
/// ::strcat(outputBuffer, guilty ? ": guilty" : ": not guilty");
177
/// va_end(ap);
178
/// }
179
/// @endcode
180
/// Then, in `main`, we call `catVerdict` correctly:
181
/// @code
182
/// char buf[1000];
183
/// catVerdict(buf, "We find the", "defendant,", "Bugs Bunny", NULL, 0);
184
/// printf("%s\n", buf);
185
/// @endcode
186
/// which compiles without a warning and produces the output:
187
/// @code
188
/// We find the defendant, Bugs Bunny: not guilty
189
/// @endcode
190
/// Next, we call `catVerdict` with no `NULL` passed, and get a warning (and
191
/// probably a core dump if we ran it):
192
/// @code
193
/// catVerdict(buf, "We find the", "defendant,", "Wile E. Coyote", 1);
194
/// printf("%s\n", buf);
195
/// @endcode
196
/// And we get the following compiler warning:
197
/// @code
198
/// .../bsla_nullterminated.t.cpp:447:70: warning: missing sentinel in function
199
/// call [-Wsentinel]
200
/// catVerdict(buf, "We find the", "defendant,", "Wile E. Coyote", 1);
201
/// ^
202
/// , nullptr
203
/// .../bsla_nullterminated.t.cpp:171:10: note: function has been explicitly
204
/// marked sentinel here
205
/// void catVerdict(char *outputBuffer, ...)
206
/// ^
207
/// @endcode
208
/// Now, we call `catVerdict` and forget to put the integer that indicates guilt
209
/// or innocence after the `NULL`. This means that `NULL` is happening at index
210
/// 0, not index 1, which violates the requirement imposed by the annotation:
211
/// @code
212
/// catVerdict(buf, "We find the", "defendant,", "Road Runner", NULL);
213
/// printf("%s\n", buf);
214
/// @endcode
215
/// Finally, we get the compiler warning:
216
/// @code
217
/// .../bsla_nullterminated.t.cpp:471:67: warning: missing sentinel in function
218
/// call [-Wsentinel]
219
/// catVerdict(buf, "We find the", "defendant,", "Road Runner", NULL);
220
/// ^
221
/// , nullptr
222
/// .../bsla_nullterminated.t.cpp:171:10: note: function has been explicitly
223
/// marked sentinel here
224
/// void catVerdict(char *outputBuffer, ...)
225
/// ^
226
/// @endcode
227
/// @}
228
/** @} */
229
/** @} */
230
231
/** @addtogroup bsl
232
* @{
233
*/
234
/** @addtogroup bsla
235
* @{
236
*/
237
/** @addtogroup bsla_nullterminated
238
* @{
239
*/
240
241
#include <bsls_platform.h>
242
243
// =============================
244
// Checks for Pre-Defined macros
245
// =============================
246
247
#if defined(BSLA_NULLTERMINATED)
248
#error BSLA_NULLTERMINATED is already defined!
249
#endif
250
251
#if defined(BSLA_NULLTERMINATED_IS_ACTIVE)
252
#error BSLA_NULLTERMINATED_IS_ACTIVE is already defined!
253
#endif
254
255
#if defined(BSLA_NULLTERMINATEDAT)
256
#error BSLA_NULLTERMINATEDAT is already defined!
257
#endif
258
259
#if defined(BSLA_NULLTERMINATEDAT_IS_ACTIVE)
260
#error BSLA_NULLTERMINATEDAT_IS_ACTIVE is already defined!
261
#endif
262
// =========================
263
// Set macros as appropriate
264
// =========================
265
266
#if (defined(BSLS_PLATFORM_CMP_GNU) || defined(BSLS_PLATFORM_CMP_CLANG)) && \
267
!defined(BSLS_PLATFORM_OS_SOLARIS)
268
#define BSLA_NULLTERMINATED __attribute__((__sentinel__))
269
#define BSLA_NULLTERMINATEDAT(ARG_IDX) \
270
__attribute__((__sentinel__(ARG_IDX)))
271
272
#define BSLA_NULLTERMINATED_IS_ACTIVE 1
273
#define BSLA_NULLTERMINATEDAT_IS_ACTIVE 1
274
#else
275
#define BSLA_NULLTERMINATED
276
#define BSLA_NULLTERMINATEDAT(ARG_IDX)
277
#endif
278
279
#endif
280
281
// ----------------------------------------------------------------------------
282
// Copyright 2019 Bloomberg Finance L.P.
283
//
284
// Licensed under the Apache License, Version 2.0 (the "License");
285
// you may not use this file except in compliance with the License.
286
// You may obtain a copy of the License at
287
//
288
// http://www.apache.org/licenses/LICENSE-2.0
289
//
290
// Unless required by applicable law or agreed to in writing, software
291
// distributed under the License is distributed on an "AS IS" BASIS,
292
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
293
// See the License for the specific language governing permissions and
294
// limitations under the License.
295
// ----------------------------- END-OF-FILE ----------------------------------
296
297
/** @} */
298
/** @} */
299
/** @} */
bsls_ident.h
BSLS_IDENT
#define BSLS_IDENT(str)
Definition
bsls_ident.h:195
doxygen_input
bde
groups
bsl
bsla
bsla_nullterminated.h
Generated by
1.9.8