BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bsla_format.h
Go to the documentation of this file.
1/// @file bsla_format.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bsla_format.h -*-C++-*-
8#ifndef INCLUDED_BSLA_FORMAT
9#define INCLUDED_BSLA_FORMAT
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bsla_format bsla_format
15/// @brief Provide a macro to indicate that a return value is a format string.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bsla
19/// @{
20/// @addtogroup bsla_format
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bsla_format-purpose"> Purpose</a>
25/// * <a href="#bsla_format-macros"> Macros </a>
26/// * <a href="#bsla_format-description"> Description </a>
27/// * <a href="#bsla_format-macro-reference"> Macro Reference </a>
28/// * <a href="#bsla_format-usage"> Usage </a>
29/// * <a href="#bsla_format-example-1-a-language-translator-function"> Example 1: A Language Translator Function </a>
30///
31/// # Purpose {#bsla_format-purpose}
32/// Provide a macro to indicate that a return value is a format string.
33///
34/// # Macros {#bsla_format-macros}
35///
36/// - BSLA_FORMAT(FMT_IDX): validate `printf`-style format spec. in `n`th arg.
37/// - BSLA_FORMAT_IS_ACTIVE: defined if `BSLA_FORMAT` is active
38///
39/// @see bsla_annotations
40///
41/// # Description {#bsla_format-description}
42/// This component provides a preprocessor macro to indicate that
43/// an indexed argument of a function is a `printf`-style format specification,
44/// and that the function will return a `printf`-style format string with an
45/// equivalent specification.
46///
47/// ## Macro Reference {#bsla_format-macro-reference}
48///
49///
50/// `BSLA_FORMAT(FMT_IDX)`:
51/// This annotation specifies that the so-annotated function takes an
52/// argument that is a valid format string for a `printf`-style function
53/// and returns a format string that is consistent with that format. This
54/// allows format strings manipulated by translation functions to be
55/// checked against arguments. Without this annotation, attempting to
56/// manipulate the format string via this kind of function might generate
57/// warnings about non-literal formats, or fail to generate warnings about
58/// mismatched arguments.
59///
60/// `BSLA_FORMAT_IS_ACTIVE`:
61/// The macro `BSLA_FORMAT_IS_ACTIVE` is defined if `BSLA_FORMAT` expands
62/// to something with the desired effect; otherwise `BSLA_FORMAT_IS_ACTIVE`
63/// is not defined and `BSLA_FORMAT` expands to nothing.
64///
65/// ## Usage {#bsla_format-usage}
66///
67///
68/// This section illustrates intended use of this component.
69///
70/// ### Example 1: A Language Translator Function {#bsla_format-example-1-a-language-translator-function}
71///
72///
73/// First, we define an `enum`, `Language`, to indicate the choice of languages:
74/// @code
75/// enum Language {
76/// e_ENGLISH,
77/// e_SPANISH,
78/// e_DUTCH,
79/// e_FRENCH };
80/// @endcode
81/// Then, we define a function, `prefixName`, which will take a format string
82/// and prefix it with the word `name` in the selected language. The
83/// `BSLA_FORMAT` annotation indicates that the result will be a pointer to a
84/// `printf`-style format string equivalent to the format string passed to the
85/// third argument:
86/// @code
87/// const char *prefixName(char *buf, Language lang, const char *format)
88/// BSLA_FORMAT(3);
89/// const char *prefixName(char *buf, Language lang, const char *format)
90/// // Create a buffer beginning with the word 'name' translated to the
91/// // specified 'lang', followed by the specified format string 'format',
92/// // using the specified 'buf' for memory.
93/// {
94/// const char *name = "";
95/// switch (lang) {
96/// case e_ENGLISH: name = "Name"; break;
97/// case e_SPANISH: name = "Nombre"; break;
98/// case e_DUTCH: name = "Naam"; break;
99/// case e_FRENCH: name = "Nom"; break;
100/// }
101/// ::strcpy(buf, name);
102/// ::strcat(buf, ": ");
103/// ::strcat(buf, format);
104///
105/// return buf;
106/// }
107/// @endcode
108/// Next, in `main`, we call `printf` and `sscanf` using the return value of
109/// `prefixName`. No warnings occur when correct arguments are passed:
110/// @code
111/// char buffer[1000];
112/// ::printf(prefixName(buffer, e_SPANISH, "%s\n"), "Michael Bloomberg");
113///
114/// char name[100];
115/// ::sscanf("Emmanuel Macron", prefixName(buffer, e_FRENCH, "%s"), name);
116/// @endcode
117/// Now, we call `printf` and `sscanf` passing arguments that won't match the
118/// resulting format string:
119/// @code
120/// ::printf(prefixName(buffer, e_ENGLISH, "%s\n"), 2.7);
121/// int x;
122/// ::sscanf("Sharon den Adel", prefixName(buffer, e_DUTCH, "%s"), &x);
123/// @endcode
124/// Finally, we observe the following warning messages with g++:
125/// @code
126/// .../bsla/bsla_format.t.cpp:306:56: warning: format '%s' expects argument
127/// of type 'char*', but argument 2 has type 'double' [-Wformat=]
128/// ::printf(prefixName(buffer, e_ENGLISH, "%s\n"), 2.7);
129/// ^
130/// .../bsla_format.t.cpp:308:70: warning: format '%s' expects argument of
131/// type 'char*', but argument 3 has type 'int*' [-Wformat=]
132/// ::sscanf("Sharon den Adel", prefixName(buffer, e_DUTCH, "%s"), &x);
133/// ~~^
134/// @endcode
135/// @}
136/** @} */
137/** @} */
138
139/** @addtogroup bsl
140 * @{
141 */
142/** @addtogroup bsla
143 * @{
144 */
145/** @addtogroup bsla_format
146 * @{
147 */
148
149#include <bsls_platform.h>
150
151 // =============================
152 // Checks for Pre-Defined macros
153 // =============================
154
155#if defined(BSLA_FORMAT)
156#error BSLA_FORMAT is already defined!
157#endif
158
159#if defined(BSLA_FORMAT_IS_ACTIVE)
160#error BSLA_FORMAT_IS_ACTIVE is already defined!
161#endif
162
163 // =========================
164 // Set macros as appropriate
165 // =========================
166
167#if defined(BSLS_PLATFORM_CMP_GNU) || \
168 defined(BSLS_PLATFORM_CMP_CLANG) || \
169 defined(BSLS_PLATFORM_CMP_IBM)
170 #define BSLA_FORMAT(FMT_IDX) __attribute__((format_arg(FMT_IDX)))
171
172 #define BSLA_FORMAT_IS_ACTIVE 1
173#else
174 #define BSLA_FORMAT(FMT_IDX)
175#endif
176
177#endif
178
179// ----------------------------------------------------------------------------
180// Copyright 2019 Bloomberg Finance L.P.
181//
182// Licensed under the Apache License, Version 2.0 (the "License");
183// you may not use this file except in compliance with the License.
184// You may obtain a copy of the License at
185//
186// http://www.apache.org/licenses/LICENSE-2.0
187//
188// Unless required by applicable law or agreed to in writing, software
189// distributed under the License is distributed on an "AS IS" BASIS,
190// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
191// See the License for the specific language governing permissions and
192// limitations under the License.
193// ----------------------------- END-OF-FILE ----------------------------------
194
195/** @} */
196/** @} */
197/** @} */
#define BSLS_IDENT(str)
Definition bsls_ident.h:195