blob: fb83f4ac820c66959ebd3473b3a6727e12cec05b [file]
/* C99 array parameters: static and type qualifiers in the brackets and variable length arrays, which SWIG wraps as plain arrays */
%module c99_parameter_array_declarators
%{
/* C++, C before C99 and MSVC reject this syntax, so their compilers see only the plain definitions */
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L && !defined(__cplusplus) && !defined(_MSC_VER)
#define TEST_C99_ARRAY_DECLARATORS
#endif
static int add_n(int n, const int *a) {
int sum = 0;
int i;
for (i = 0; i < n; i++) {
sum += a[i];
}
return sum;
}
%}
%inline %{
int *three_numbers(void) {
static int numbers[] = {1, 2, 3};
return numbers;
}
%}
// Static and type qualifiers in parameter array declarators
/* Matches only if 'static' and the pointer qualifiers are dropped and the dimension kept */
%rename(sum_qualified) sum_static_const(const int [3]);
/* Matches when written as declared */
%rename(sum_static_renamed) sum_static(int a[static 3]);
%inline %{
#if defined(SWIG) || defined(TEST_C99_ARRAY_DECLARATORS)
int sum_static(int a[static 3]);
int sum_const(int a[const 3]);
int sum_static_const(const int a[static const 3]);
int sum_const_static(int a[const static 3]);
int sum_qualifiers(int a[const volatile restrict 3]);
int sum_qualifiers_only(int a[const]);
int sum_unnamed(int [static 3]);
int sum_pointers(int *a[static 2]);
int sum_grid(int a[static 2][3]);
typedef int (*summer)(const int a[static 3]);
#endif
%}
%{
int sum_static(int a[3]) { return add_n(3, a); }
int sum_const(int a[3]) { return add_n(3, a); }
int sum_static_const(const int a[3]) { return add_n(3, a); }
int sum_const_static(int a[3]) { return add_n(3, a); }
int sum_qualifiers(int a[3]) { return add_n(3, a); }
int sum_qualifiers_only(int a[]) { return add_n(3, a); }
int sum_unnamed(int a[3]) { return add_n(3, a); }
int sum_pointers(int *a[2]) { return *a[0] + *a[1]; }
int sum_grid(int a[2][3]) { return a[0][0] + a[1][2]; }
%}
// Variable length array type, the size being an earlier parameter in the parameter list
/* Matches only if the variable length array's size is dropped */
%rename(sum_n_renamed) sum_n(int, const int []);
/* Matches when written as declared */
%rename(sum_n_static_renamed) sum_n_static(int n, const int a[static n]);
%inline %{
#if defined(SWIG) || (defined(TEST_C99_ARRAY_DECLARATORS) && !defined(__STDC_NO_VLA__))
int sum_n(int n, const int a[n]);
int sum_n_static(int n, const int a[static n]);
int char_length(int n, const char s[n]);
int char_length_offset(int offset, int n, const char s[n - offset]);
int count_names(int n, char *names[n]);
#endif
%}
%{
int sum_n(int n, const int *a) { return add_n(n, a); }
int sum_n_static(int n, const int *a) { return add_n(n, a); }
int char_length(int n, const char *s) {
int i = 0;
while (i < n && s[i]) {
i++;
}
return i;
}
int char_length_offset(int offset, int n, const char *s) { return char_length(n - offset, s); }
int count_names(int n, char **names) {
int count = 0;
int i;
for (i = 0; i < n; i++) {
if (names[i]) {
count++;
}
}
return count;
}
%}
// A %rename, %ignore or %exception given with an unnamed size parameter matches the size as declared
%rename(char_length_unnamed_renamed) char_length_unnamed(int, const char [n]);
%ignore char_length_ignored(int, const char [n]);
%exception char_length_excepted "this_will_not_compile";
%exception char_length_excepted(int, const char [n]) "$action";
%inline %{
#if defined(SWIG) || (defined(TEST_C99_ARRAY_DECLARATORS) && !defined(__STDC_NO_VLA__))
int char_length_unnamed(int n, const char s[n]);
int char_length_ignored(int n, const char s[n]);
int char_length_excepted(int n, const char s[n]);
#endif
%}
%{
int char_length_unnamed(int n, const char *s) { return char_length(n, s); }
int char_length_ignored(int n, const char *s) { return char_length(n, s); }
int char_length_excepted(int n, const char *s) { return char_length(n, s); }
%}
// Variable length array type of unspecified size
%rename(sum_n_unsized_renamed) sum_n_unsized(int n, const int a[*]);
%inline %{
#if defined(SWIG) || (defined(TEST_C99_ARRAY_DECLARATORS) && !defined(__STDC_NO_VLA__))
int sum_n_unsized(int n, const int a[*]);
int sum_n_unnamed(int, const int [const *]);
#endif
%}
%{
int sum_n_unsized(int n, const int *a) { return add_n(n, a); }
int sum_n_unnamed(int n, const int *a) { return add_n(n, a); }
%}
// Variably modified types: variable length arrays inside an array, a pointer or a function pointer's parameters
%inline %{
#if defined(SWIG) || (defined(TEST_C99_ARRAY_DECLARATORS) && !defined(__STDC_NO_VLA__))
double trace(int n, double m[n][n]);
double trace_unsized(int n, double m[*][*]);
int first_row_sum(int n, int (*rows)[n]);
int apply_sum(int n, int (*f)(const int a[n]), const int numbers[n]);
#endif
%}
%{
#if defined(TEST_C99_ARRAY_DECLARATORS) && !defined(__STDC_NO_VLA__)
double trace(int n, double m[n][n]) {
double sum = 0;
int i;
for (i = 0; i < n; i++) {
sum += m[i][i];
}
return sum;
}
double trace_unsized(int n, double m[n][n]) { return trace(n, m); }
int first_row_sum(int n, int (*rows)[n]) { return add_n(n, rows[0]); }
int apply_sum(int n, int (*f)(const int a[n]), const int numbers[n]) { return n > 0 ? f(numbers) : 0; }
#else
/* A pointer to an array of unknown size converts to 'const void *' in C++ too */
double trace(int n, const void *m) {
const double *elements = (const double *)m;
double sum = 0;
int i;
for (i = 0; i < n; i++) {
sum += elements[i * n + i];
}
return sum;
}
double trace_unsized(int n, const void *m) { return trace(n, m); }
int first_row_sum(int n, const void *rows) { return add_n(n, (const int *)rows); }
int apply_sum(int n, int (*f)(const int *a), const int *numbers) { return n > 0 ? f(numbers) : 0; }
#endif
%}
// A function declared with an unspecified size and then with the size uses the size for the '[*]' typemaps
%warnfilter(SWIGWARN_PARSE_REDUNDANT) char_length_redeclared;
%inline %{
#if defined(SWIG) || (defined(TEST_C99_ARRAY_DECLARATORS) && !defined(__STDC_NO_VLA__))
int char_length_redeclared(int, const char [*]);
int char_length_redeclared(int n, const char s[n]);
#endif
%}
%{
int char_length_redeclared(int n, const char *s) { return char_length(n, s); }
%}
// A method, whose wrapper is passed self before the parameters
%inline %{
struct Text {
int id;
};
%}
%extend Text {
int char_length(int n, const char s[n]) {
int i = 0;
(void)$self;
while (i < n && s[i]) {
i++;
}
return i;
}
}
// A constructor and a function declared with its name in parentheses
%{
#include <stdlib.h>
%}
%inline %{
struct Name {
int length;
};
#if defined(SWIG) || (defined(TEST_C99_ARRAY_DECLARATORS) && !defined(__STDC_NO_VLA__))
int (char_length_parenthesized)(int n, const char s[n]);
int (char_length_parenthesized_unsized)(int n, const char s[*]);
#endif
%}
%{
int char_length_parenthesized(int n, const char *s) { return char_length(n, s); }
int char_length_parenthesized_unsized(int n, const char *s) { return char_length(n, s); }
%}
%extend Name {
Name(int n, const char s[n]) {
struct Name *name = (struct Name *)malloc(sizeof(struct Name));
name->length = char_length(n, s);
return name;
}
~Name() {
free($self);
}
}
// A size that is not an earlier parameter, such as a global variable, is kept as the size of a fixed size array
%inline %{
int global_n = 5;
#if defined(SWIG) || (defined(TEST_C99_ARRAY_DECLARATORS) && !defined(__STDC_NO_VLA__))
int sum_global_dimension(int n, const int a[global_n]);
#endif
%}
%{
int sum_global_dimension(int n, const int *a) { return add_n(n, a); }
%}
// A parameter's name used as a member name or in a literal does not refer to the parameter
%inline %{
struct Dimensions {
int n;
};
struct Sizes {
int n;
struct Dimensions dims;
};
#if defined(SWIG) || (defined(TEST_C99_ARRAY_DECLARATORS) && !defined(__STDC_NO_VLA__))
int char_length_member(const struct Sizes *sizes, int n, const char s[sizes->n]);
int char_length_dot_member(const struct Sizes *sizes, int n, const char s[sizes->dims.n]);
#endif
int char_length_literal(int a, const char s['a' - 'a' + 2]) { return a + char_length(2, s); }
%}
%{
int char_length_member(const struct Sizes *sizes, int n, const char *s) { return n + char_length(sizes->n, s); }
int char_length_dot_member(const struct Sizes *sizes, int n, const char *s) { return n + char_length(sizes->dims.n, s); }
%}
// Typedefs in a variable length array parameter: the size, the element type and a const char string
%inline %{
typedef int count_t;
typedef int element_t;
typedef const char text_t;
#if defined(SWIG) || (defined(TEST_C99_ARRAY_DECLARATORS) && !defined(__STDC_NO_VLA__))
int sum_typedef_size(count_t n, const int a[n]);
int sum_typedef_element(int n, const element_t a[n]);
int char_length_typedef(int n, text_t s[n]);
#endif
%}
%{
int sum_typedef_size(count_t n, const int *a) { return add_n(n, a); }
int sum_typedef_element(int n, const element_t *a) { return add_n(n, a); }
int char_length_typedef(int n, text_t *s) { return char_length(n, s); }
%}