mirror of https://github.com/swig/swig
parent
d1303767e9
commit
a7eca8b415
|
@ -18,6 +18,10 @@
|
|||
<li><a href="#CPlusPlus20_lambda_templates">Lambda templates</a>
|
||||
<li><a href="#CPlusPlus20_constexpr_destructors">Constexpr destructors</a>
|
||||
</ul>
|
||||
<li><a href="#CPlusPlus20_preprocessor_changes">Preprocessor changes</a>
|
||||
<ul>
|
||||
<li><a href="#CPlusPlus20_va_opt">__VA_OPT__()</a>
|
||||
</ul>
|
||||
<li><a href="#CPlusPlus20_standard_library_changes">Standard library changes</a>
|
||||
</ul>
|
||||
</div>
|
||||
|
@ -84,7 +88,18 @@ public:
|
|||
</pre>
|
||||
</div>
|
||||
|
||||
<H2><a name="CPlusPlus20_standard_library_changes">10.3 Standard library changes</a></H2>
|
||||
<H2><a name="CPlusPlus20_preprocessor_changes">10.3 Preprocessor changes</a></H2>
|
||||
|
||||
|
||||
<H3><a name="CPlusPlus20_va_opt">10.3.1 __VA_OPT__()</a></H3>
|
||||
|
||||
|
||||
<p>
|
||||
Support for <tt>__VA_OPT__()</tt> was added in SWIG 4.3.0.
|
||||
</p>
|
||||
|
||||
|
||||
<H2><a name="CPlusPlus20_standard_library_changes">10.4 Standard library changes</a></H2>
|
||||
|
||||
|
||||
</body>
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
<li><a href="#Preprocessor_condition_compilation">Conditional Compilation</a>
|
||||
<li><a href="#Preprocessor_nn5">Macro Expansion</a>
|
||||
<li><a href="#Preprocessor_nn6">SWIG Macros</a>
|
||||
<li><a href="#Preprocessor_nn7">C99 and GNU Extensions</a>
|
||||
<li><a href="#Preprocessor_nn7">Variadic Macros</a>
|
||||
<li><a href="#Preprocessor_delimiters">Preprocessing and delimiters</a>
|
||||
<ul>
|
||||
<li><a href="#Preprocessor_nn8">Preprocessing and %{ ... %} & " ... " delimiters</a>
|
||||
|
@ -322,11 +322,12 @@ many of SWIG's advanced features and libraries are built using this mechanism (s
|
|||
support).
|
||||
</p>
|
||||
|
||||
<H2><a name="Preprocessor_nn7">11.6 C99 and GNU Extensions</a></H2>
|
||||
<H2><a name="Preprocessor_nn7">11.6 Variadic Macros</a></H2>
|
||||
|
||||
|
||||
<p>
|
||||
SWIG-1.3.12 and newer releases support variadic preprocessor macros. For example:
|
||||
SWIG-1.3.12 and newer releases support variadic preprocessor macros which were
|
||||
standardised by C99 and C++11. For example:
|
||||
</p>
|
||||
|
||||
<div class="code">
|
||||
|
@ -342,8 +343,9 @@ macros defined using <tt>%define</tt>.
|
|||
</p>
|
||||
|
||||
<p>
|
||||
SWIG allows a variable number of arguments to be empty. However, this often results
|
||||
in an extra comma (, ) and syntax error in the resulting expansion. For example:
|
||||
The variable arguments can be empty. However, this often results
|
||||
in an extra comma (<tt>,</tt>) and syntax error in the resulting expansion. For
|
||||
example:
|
||||
</p>
|
||||
|
||||
<div class="code">
|
||||
|
@ -353,7 +355,25 @@ DEBUGF("hello"); --> fprintf(stderr, "hello", );
|
|||
</div>
|
||||
|
||||
<p>
|
||||
To get rid of the extra comma, use <tt>##</tt> like this:
|
||||
C++20 and C23 added <tt>__VA_OPT__()</tt> as a solution to this, which SWIG
|
||||
4.3.0 added support for. <tt>__VA_OPT__()</tt> expands to its argument if the
|
||||
variable arguments contain any tokens, and to nothing otherwise. It can be
|
||||
used to solve the problem above like so:
|
||||
</p>
|
||||
|
||||
<div class="code">
|
||||
<pre>
|
||||
#define DEBUGF(fmt, ...) fprintf(stderr, fmt __VA_OPT__(,) __VA_ARGS__)
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
An early non-standardised solution to this problem which gave a special
|
||||
meaning to the token sequence <tt>, ## __VAR_ARGS__</tt> is supported by
|
||||
several C and C++ compilers, and also by SWIG 4.3.0 and later (it was
|
||||
documented as supported by earlier SWIG versions, but didn't actually work in
|
||||
at least SWIG 2.x and 3.x). Using this feature you can get rid of the extra
|
||||
comma like this:
|
||||
</p>
|
||||
|
||||
<div class="code">
|
||||
|
@ -363,7 +383,8 @@ To get rid of the extra comma, use <tt>##</tt> like this:
|
|||
</div>
|
||||
|
||||
<p>
|
||||
SWIG also supports GNU-style variadic macros. For example:
|
||||
SWIG also supports GNU-style variadic macros, which specify a name for the
|
||||
variable arguments instead of using <tt>__VA_ARGS__<tt>. For example:
|
||||
</p>
|
||||
|
||||
<div class="code">
|
||||
|
@ -373,11 +394,12 @@ SWIG also supports GNU-style variadic macros. For example:
|
|||
</div>
|
||||
|
||||
<p>
|
||||
<b>Comment:</b> It's not entirely clear how variadic macros might be useful to
|
||||
interface building. However, they are used internally to implement a number of
|
||||
SWIG directives and are provided to make SWIG more compatible with C99 code.
|
||||
SWIG supports <tt>__VA_OPT__()</tt> in combination with GNU-style variadic
|
||||
macros (following the lead of GCC and clang which also support this, albeit
|
||||
with a warning by default).
|
||||
</p>
|
||||
|
||||
|
||||
<H2><a name="Preprocessor_delimiters">11.7 Preprocessing and delimiters</a></H2>
|
||||
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ check::functions(array('hello0','hello1','hello2','f','test','method','methodX',
|
|||
// New classes
|
||||
check::classes(array('preproc','EmbeddedDefines','TypeNameTraits','tcxMessageTest','tcxMessageBug'));
|
||||
// No new vars
|
||||
check::globals(array('endif_','define','defined','FOO','BAR','global_var','global_var2'));
|
||||
check::globals(array('endif_','define','defined','FOO','BAR','global_var','global_var2','global_var3','global_var4','global_var5','global_var6','global_var7','global_var8','global_var9','global_var10','global_var11','global_var12'));
|
||||
|
||||
check::equal(preproc::endif__get(), 1);
|
||||
check::equal(preproc::define_get(), 1);
|
||||
|
|
|
@ -472,3 +472,41 @@ DECLARE_GLOBAL_VAR2()
|
|||
int global_var = 42;
|
||||
int global_var2 = 345;
|
||||
%}
|
||||
|
||||
/* Feature test for __VA_OPT__ support. This was standardised in C++20 but
|
||||
* we're only testing SWIG's support for it here so this doesn't require a
|
||||
* C++20 compiler.
|
||||
*/
|
||||
#define DECLARE_GLOBAL_VA(N,...) int global_var##N __VA_OPT__(=)__VA_ARGS__;
|
||||
/* Named varargs is a GCC extension. Both GCC and clang support __VA_OPT__
|
||||
* with named varargs (albeit with a warning) and SWIG supports it too for
|
||||
* compatibility.
|
||||
*/
|
||||
#define DECLARE_GLOBAL_NAMED(N,NAMED...) int global_var##N __VA_OPT__(=)NAMED;
|
||||
DECLARE_GLOBAL_VA(3)
|
||||
DECLARE_GLOBAL_VA(4,)
|
||||
DECLARE_GLOBAL_VA(5, )
|
||||
DECLARE_GLOBAL_VA(6, /**Hello,World)**/ )
|
||||
|
||||
DECLARE_GLOBAL_NAMED(7)
|
||||
DECLARE_GLOBAL_NAMED(8,)
|
||||
DECLARE_GLOBAL_NAMED(9, )
|
||||
DECLARE_GLOBAL_NAMED(10, /**Hello,World)**/ )
|
||||
|
||||
DECLARE_GLOBAL_VA(11,111)
|
||||
|
||||
DECLARE_GLOBAL_NAMED(12,121)
|
||||
|
||||
// Show the compiler simple definitions so we don't need __VA_OPT__ support.
|
||||
%{
|
||||
int global_var3 = 3;
|
||||
int global_var4 = 4;
|
||||
int global_var5 = 5;
|
||||
int global_var6 = 6;
|
||||
int global_var7 = 7;
|
||||
int global_var8 = 8;
|
||||
int global_var9 = 9;
|
||||
int global_var10 = 10;
|
||||
int global_var11 = 111;
|
||||
int global_var12 = 121;
|
||||
%}
|
||||
|
|
|
@ -503,6 +503,10 @@ Hash *Preprocessor_define(const_String_or_char_ptr _str, int swigmacro) {
|
|||
Replace(macrovalue, "\001@", "\004", DOH_REPLACE_ANY);
|
||||
/* Replace '##@' with a special token */
|
||||
Replace(macrovalue, "\002@", "\005", DOH_REPLACE_ANY);
|
||||
if (varargs) {
|
||||
/* Replace '__VA_OPT__' with a special token */
|
||||
Replace(macrovalue, "__VA_OPT__", "\006", DOH_REPLACE_ID|DOH_REPLACE_ANY);
|
||||
}
|
||||
|
||||
/* Go create the macro */
|
||||
macro = NewHash();
|
||||
|
@ -918,6 +922,38 @@ static String *expand_macro(String *name, List *args, String *line_file) {
|
|||
Printf(tempa, "\"%s\"", arg);
|
||||
Replace(ns, temp, tempa, DOH_REPLACE_ID_END);
|
||||
}
|
||||
if (isvarargs && i == l - 1) {
|
||||
char *s = Char(ns);
|
||||
char *a = s;
|
||||
while ((a = strchr(a, '\006')) != NULL) {
|
||||
*a = ' ';
|
||||
while (isspace((unsigned char)*++a)) { }
|
||||
if (*a == '(') {
|
||||
char *e = a;
|
||||
int depth = 1;
|
||||
while (*++e) {
|
||||
if (*e == ')') {
|
||||
if (--depth == 0) break;
|
||||
} else if (*e == '(') {
|
||||
++depth;
|
||||
}
|
||||
}
|
||||
if (*e) {
|
||||
if (Len(arg) == 0) {
|
||||
// Empty varargs so replace ( and ) and everything between with
|
||||
// spaces.
|
||||
memset(a, ' ', e - a + 1);
|
||||
} else {
|
||||
// Non-empty varargs so replace ( and ) with spaces.
|
||||
*a = ' ';
|
||||
*e = ' ';
|
||||
}
|
||||
}
|
||||
a = e + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (strchr(Char(ns), '\002')) {
|
||||
/* Look for concatenation tokens */
|
||||
Clear(temp);
|
||||
|
|
Loading…
Reference in New Issue