From 325056453a1a112d59002025c4fde447edd1c911 Mon Sep 17 00:00:00 2001 From: Seth R Johnson Date: Fri, 16 Feb 2018 15:44:00 -0500 Subject: [PATCH 1/2] Enable multiple 'fragment' keywords to be attached to typemaps This is consistent with the use of `%fragment`. Previously only the last `fragment=` keyword would be added. --- Examples/test-suite/fragments.i | 83 +++++++++++++++++++++++++++++++++ Source/Swig/typemap.c | 55 ++++++++++++++++++++++ 2 files changed, 138 insertions(+) diff --git a/Examples/test-suite/fragments.i b/Examples/test-suite/fragments.i index 4bf399a21..8db01e110 100644 --- a/Examples/test-suite/fragments.i +++ b/Examples/test-suite/fragments.i @@ -34,3 +34,86 @@ int foo(int hola) } %} + +/* Instantiate multiple fragments at once using multiple keywords */ +typedef int int_infrag3; +typedef int explicit_frag3; + +%fragment("explicit_frag1","header", noblock=1) { +typedef int explicit_frag1; +} + +%fragment("explicit_frag2","header", noblock=1, noblock=1) { +typedef explicit_frag1 explicit_frag2; +} + +%fragment("explicit_frag3","header", + fragment="explicit_frag1", fragment="explicit_frag2") +%{typedef explicit_frag2 explicit_frag3;%} + +%fragment("explicit_frag3"); +%inline %{ +explicit_frag3 my_int = 0; +%} + +/* Test typemap's ability to instantiate multiple fragments on demand */ +typedef int int_infrag1; +typedef int int_infrag2; +typedef int int_outfrag1; +typedef int int_outfrag2; +typedef int int_outfrag3; + +%fragment("infrag2","runtime") %{ +typedef int_infrag1 int_infrag2; +%} + +%fragment("infrag1","runtime") %{ +typedef int int_infrag1; +%} +%fragment("infrag2","runtime") %{ +typedef int_infrag1 int_infrag2; +%} + +%fragment("outfrag1","runtime") %{ +typedef int int_outfrag1; +%} +%fragment("outfrag2","runtime") %{ +typedef int_outfrag1 int_outfrag2; +%} + +%fragment("tcfrag1","runtime") %{ +typedef int int_tcfrag1; +%} +%fragment("tcfrag2","runtime") %{ +typedef int_tcfrag1 int_tcfrag2; +%} + +%fragment("outspecial"{bool},"runtime") %{ +typedef int int_outfrag3_temp; +%} +%fragment("outfrag3","runtime") %{ +typedef int_outfrag3_temp int_outfrag3; +%} + +%typemap(in, fragment="infrag1", fragment="infrag2") int_infrag2 +%{$typemap(in,int)%} + +%typemap(check, fragment="tcfrag1", noblock=1, fragment="tcfrag2") int_infrag2 +{(void)sizeof(int_tcfrag2);} + +%typemap(out, fragment="outfrag1", fragment="outfrag2", noblock=1) int_outfrag2 +{$typemap(out,int)} + +/* Test another permutation of keyword order */ +%typemap(out, noblock=1, fragment="outfrag1", fragment="outfrag2") int_outfrag1 +{$typemap(out,int)} + +/* Test fragment specialization */ +%typemap(out, noblock=1, fragment="outspecial"{bool}, fragment="outfrag3") int_outfrag3 +{$typemap(out,int)} + +%inline %{ +int identity_in(int_infrag2 inp) { return inp; } +int_outfrag2 identity_out(int inp) { return inp; } +int_outfrag3 identity_out_2(int inp) { return inp; } +%} diff --git a/Source/Swig/typemap.c b/Source/Swig/typemap.c index c0f5397c1..e2fee3480 100644 --- a/Source/Swig/typemap.c +++ b/Source/Swig/typemap.c @@ -1256,6 +1256,59 @@ static String *typemap_warn(const_String_or_char_ptr tmap_method, Parm *p) { return w ? Copy(w) : 0; } +/* ----------------------------------------------------------------------------- + * typemap_merge_fragment_kwargs() + * + * If multiple 'fragment' attributes are provided to a typemap, combine them by + * concatenating with commas. + * ----------------------------------------------------------------------------- */ + +static void typemap_merge_fragment_kwargs(Parm *kw) { + Parm *reattach_kw = NULL; + Parm *prev_kw = NULL; + Parm *next_kw = NULL; + String *fragment = NULL; + while (kw) { + next_kw = nextSibling(kw); + if (Strcmp(Getattr(kw, "name"), "fragment") == 0) { + String *thisfragment = Getattr(kw, "value"); + String *kwtype = Getattr(kw, "type"); + if (!fragment) { + /* First fragment found; it should remain in the list */ + fragment = thisfragment; + prev_kw = kw; + } else { + /* Concatentate to previously found fragment */ + Printv(fragment, ",", thisfragment, NULL); + reattach_kw = prev_kw; + } + if (kwtype) { + String *mangle = Swig_string_mangle(kwtype); + Append(fragment, mangle); + Delete(mangle); + /* Remove 'type' from kwargs so it's not duplicated later */ + Setattr(kw, "type", NULL); + } + } else { + /* Not a fragment */ + if (reattach_kw) { + /* Update linked list to remove duplicate fragment */ + DohIncref(kw); + set_nextSibling(reattach_kw, kw); + set_previousSibling(kw, reattach_kw); + Delete(reattach_kw); + reattach_kw = NULL; + } + prev_kw = kw; + } + kw = next_kw; + } + if (reattach_kw) { + /* Update linked list to remove duplicate fragment */ + set_nextSibling(reattach_kw, kw); + } +} + /* ----------------------------------------------------------------------------- * Swig_typemap_lookup() * @@ -1463,6 +1516,7 @@ static String *Swig_typemap_lookup_impl(const_String_or_char_ptr tmap_method, No /* Attach kwargs - ie the typemap attributes */ kw = Getattr(tm, "kwargs"); + typemap_merge_fragment_kwargs(kw); while (kw) { String *value = Copy(Getattr(kw, "value")); String *kwtype = Getattr(kw, "type"); @@ -1577,6 +1631,7 @@ String *Swig_typemap_lookup(const_String_or_char_ptr tmap_method, Node *node, co static void typemap_attach_kwargs(Hash *tm, const_String_or_char_ptr tmap_method, Parm *firstp, int nmatch) { String *temp = NewStringEmpty(); Parm *kw = Getattr(tm, "kwargs"); + typemap_merge_fragment_kwargs(kw); while (kw) { String *value = Copy(Getattr(kw, "value")); String *type = Getattr(kw, "type"); From 6c41db3b8c1c9596bb3d7e52b493de0fb06741fc Mon Sep 17 00:00:00 2001 From: Seth R Johnson Date: Sat, 5 Feb 2022 19:12:06 -0500 Subject: [PATCH 2/2] Add documentation --- Doc/Manual/Typemaps.html | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/Doc/Manual/Typemaps.html b/Doc/Manual/Typemaps.html index 220af4398..58da41ec3 100644 --- a/Doc/Manual/Typemaps.html +++ b/Doc/Manual/Typemaps.html @@ -3983,9 +3983,19 @@ inclusion of the other fragments.
  • -A typemap can also use more than one fragment, but since the -syntax is different, you need to specify the dependent fragments in a comma separated -list. Consider: +A typemap can also use more than one fragment with the same syntax: +

    +
    +
    +%typemap("in", "header", fragment="frag1", fragment="frag2", fragment="frag3") "";
    +
    +
    +

    +New in SWIG 4.1. +

    + +

    An older syntax allows multiple fragments to be specified in a comma +separated list inside a single keyword argument. Consider: