diff --git a/CHANGES.current b/CHANGES.current index 1ff98e258..570b0473f 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -1,6 +1,10 @@ Version 1.3.41 (in progress) ============================ +2009-12-20: wsfulton + Add -debug-tmsearch option for debugging the typemap pattern matching rules. + Documented in Typemaps.html. + 2009-12-12: wsfulton [Octave] Remove the -api option and use the new OCTAVE_API_VERSION_NUMBER macro provided in the octave headers for determining the api version instead. diff --git a/Doc/Manual/Typemaps.html b/Doc/Manual/Typemaps.html index 7a89a679a..3a8242866 100644 --- a/Doc/Manual/Typemaps.html +++ b/Doc/Manual/Typemaps.html @@ -31,10 +31,11 @@
  • Pattern matching rules
  • Code generation rules -
  • Typemaps for multiple languages +
  • Typemaps for multiple target languages
  • Optimal code generation when returning by value
  • Multi-argument typemaps
  • The run-time type checker @@ -1090,7 +1091,7 @@ void F(int x[1000]); // int [ANY] rule (typemap 5) -

    10.3.2 Typedef reductions

    +

    10.3.2 Typedef reductions

    @@ -1432,6 +1433,104 @@ but all subsequent arguments must match exactly.

    +

    10.3.6 Debugging typemap pattern matching

    + + +

    +The -debug-tmsearch command line option is available for debugging typemap searches. +This can be very useful for watching the pattern matching process in action and for debugging which typemaps are used. +The option displays all the typemaps and types that are looked for until a successful pattern match is made. +As the display includes searches for each and every type needed for wrapping, the amount of information displayed can be large. +Normally you would manually search through the displayed information for the particular type that you are interested in. +

    + +

    +For example, consider some of the code used in the Typedef reductions section already covered: +

    + +
    +
    +typedef int Integer;
    +typedef Integer Row4[4];
    +void foo(Row4 rows[10]);
    +
    +
    + +

    +A sample of the debugging output is shown below for the "in" typemap: +

    + +
    +
    +swig -debug-tmsearch example.i
    +...
    +---- Searching for a suitable 'in' typemap for: Row4 rows[10]
    +  Looking for: Row4 rows[10]
    +  Looking for: Row4 [10]
    +  Looking for: Row4 [ANY]
    +  Looking for: Integer rows[10][4]
    +  Looking for: Integer [10][4]
    +  Looking for: Integer [ANY][ANY]
    +  Looking for: int rows[10][4]
    +  Looking for: int [10][4]
    +  Looking for: int [ANY][ANY]
    +  Looking for: SWIGTYPE rows[ANY][ANY]
    +  Looking for: SWIGTYPE [ANY][ANY]
    +  Looking for: SWIGTYPE rows[ANY][]
    +  Looking for: SWIGTYPE [ANY][]
    +  Looking for: SWIGTYPE *rows[ANY]
    +  Looking for: SWIGTYPE *[ANY]
    +  Looking for: SWIGTYPE rows[ANY]
    +  Looking for: SWIGTYPE [ANY]
    +  Looking for: SWIGTYPE rows[]
    +  Looking for: SWIGTYPE []
    +  Using: %typemap(in) SWIGTYPE []
    +...
    +
    +
    + +

    +showing that the best default match supplied by SWIG is the SWIGTYPE [] typemap. +As the example shows, the successful match displays just the typemap method name and type in this format: %typemap(method) type. +This information might meet your debugging needs, however, you might want to analyze further. +If you next invoke SWIG with the -E option to display the preprocessed output, and search for this particular typemap, +you'll find the full typemap contents (example shown below for Python): +

    + +
    +
    +%typemap(in, noblock=1) SWIGTYPE [] (void *argp = 0, int res = 0) {
    +  res = SWIG_ConvertPtr($input, &argp,$descriptor, $disown |  0 );
    +  if (!SWIG_IsOK(res)) { 
    +    SWIG_exception_fail(SWIG_ArgError(res), "in method '" "$symname" "', argument " "$argnum"" of type '" "$type""'"); 
    +  } 
    +  $1 = ($ltype)(argp);
    +}
    +
    +
    + +

    +The generated code for the foo wrapper will then contain the snippets of the typemap with the special variables expanded. +The rest of this chapter will need reading though to fully understand all of this, however, the relevant parts of the generated code for the above typemap can be seen below: +

    + +
    +
    +SWIGINTERN PyObject *_wrap_foo(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
    +...
    +  void *argp1 = 0 ;
    +  int res1 = 0 ;
    +...
    +  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_a_4__int, 0 |  0 );
    +  if (!SWIG_IsOK(res1)) {
    +    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "foo" "', argument " "1"" of type '" "int [10][4]""'"); 
    +  } 
    +  arg1 = (int (*)[4])(argp1);
    +...
    +}
    +
    +
    +

    10.4 Code generation rules

    @@ -2705,12 +2804,12 @@ rather than blindly passing values to the underlying C/C++ program.

    Note: A more advanced constraint checking system is in development. Stay tuned.

    -

    10.7 Typemaps for multiple languages

    +

    10.7 Typemaps for multiple target languages

    The code within typemaps is usually language dependent, -however, many languages support the same typemaps. +however, many target languages support the same typemaps. In order to distinguish typemaps across different languages, the preprocessor should be used. For example, the "in" typemap for Perl and Ruby could be written as:

    @@ -3220,7 +3319,7 @@ language modules.
  • The run-time type checker is used by many, but not all, of SWIG's supported target languages. The run-time type checker features -are not required and are thus not used for strongly typed languages such as Java and C#. +are not required and are thus not used for statically typed languages such as Java and C#. The scripting and scheme based languages rely on it and it forms a critical part of SWIG's operation for these languages.

    diff --git a/Source/Modules/main.cxx b/Source/Modules/main.cxx index 4903416cd..9194d39a0 100644 --- a/Source/Modules/main.cxx +++ b/Source/Modules/main.cxx @@ -69,7 +69,8 @@ static const char *usage1 = (const char *) "\ -debug-template - Display information for debugging templates\n\ -debug-top - Display entire parse tree at stages 1-4, is a csv list of stages\n\ -debug-typedef - Display information about the types and typedefs in the interface\n\ - -debug-typemap - Display information for debugging typemaps\n\ + -debug-typemap - Display typemap debugging information\n\ + -debug-tmsearch - Display typemap search debugging information\n\ -directors - Turn on director mode for all the classes, mainly for testing\n\ -dirprot - Turn on wrapping of protected members for director classes (default)\n\ -D - Define a symbol (for conditional compilation)\n\ @@ -655,6 +656,9 @@ void SWIG_getoptions(int argc, char *argv[]) { } else if ((strcmp(argv[i], "-debug-typemap") == 0) || (strcmp(argv[i], "-debug_typemap") == 0) || (strcmp(argv[i], "-tm_debug") == 0)) { tm_debug = 1; Swig_mark_arg(i); + } else if (strcmp(argv[i], "-debug-tmsearch") == 0) { + Swig_typemap_search_debug_set(); + Swig_mark_arg(i); } else if (strcmp(argv[i], "-module") == 0) { Swig_mark_arg(i); if (argv[i + 1]) { diff --git a/Source/Swig/swig.h b/Source/Swig/swig.h index 2c2d4aa3b..677176cf8 100644 --- a/Source/Swig/swig.h +++ b/Source/Swig/swig.h @@ -374,6 +374,7 @@ extern int ParmList_is_compactdefargs(ParmList *p); extern int Swig_typemap_apply(ParmList *srcpat, ParmList *destpat); extern void Swig_typemap_clear_apply(ParmList *pattern); extern void Swig_typemap_debug(void); + extern void Swig_typemap_search_debug_set(void); extern String *Swig_typemap_lookup(const_String_or_char_ptr tmap_method, Node *n, const_String_or_char_ptr lname, Wrapper *f); extern String *Swig_typemap_lookup_out(const_String_or_char_ptr tmap_method, Node *n, const_String_or_char_ptr lname, Wrapper *f, String *actioncode); diff --git a/Source/Swig/typemap.c b/Source/Swig/typemap.c index b2c9ef3b2..ffd9f5e19 100644 --- a/Source/Swig/typemap.c +++ b/Source/Swig/typemap.c @@ -17,6 +17,9 @@ char cvsroot_typemap_c[] = "$Id$"; #define SWIG_DEBUG #endif +static int typemap_search_debug = 0; +static int in_typemap_search_multi = 0; + static void replace_embedded_typemap(String *s, ParmList *parm_sublist, Wrapper *f); /* ----------------------------------------------------------------------------- @@ -171,12 +174,12 @@ Hash *Swig_typemap_pop_scope() { #endif /* ----------------------------------------------------------------------------- - * Swig_typemap_register() + * typemap_register() * - * Add a new multi-argument typemap + * Internal implementation for Swig_typemap_register() * ----------------------------------------------------------------------------- */ -void Swig_typemap_register(const_String_or_char_ptr tmap_method, ParmList *parms, const_String_or_char_ptr code, ParmList *locals, ParmList *kwargs) { +static void typemap_register(const_String_or_char_ptr tmap_method, ParmList *parms, const_String_or_char_ptr code, ParmList *locals, ParmList *kwargs, const_String_or_char_ptr actual_tmap_method, ParmList *parmlist_start) { Hash *tm; Hash *tm1; Hash *tm2; @@ -249,13 +252,13 @@ void Swig_typemap_register(const_String_or_char_ptr tmap_method, ParmList *parms /* Make an entirely new typemap method key */ String *multi_tmap_method = NewStringf("%s-%s+%s:", tmap_method, type, pname); /* Now reregister on the remaining arguments */ - Swig_typemap_register(multi_tmap_method, np, code, locals, kwargs); + typemap_register(multi_tmap_method, np, code, locals, kwargs, actual_tmap_method, parmlist_start); /* Setattr(tm2,multi_tmap_method,multi_tmap_method); */ Delete(multi_tmap_method); } else { - String *str = SwigType_str(type, pname); - String *typemap = NewStringf("typemap(%s) %s", tmap_method, str); + String *parms_str = ParmList_str(parmlist_start); + String *typemap = NewStringf("typemap(%s) %s", actual_tmap_method, parms_str); ParmList *clocals = CopyParmList(locals); ParmList *ckwargs = CopyParmList(kwargs); @@ -271,11 +274,21 @@ void Swig_typemap_register(const_String_or_char_ptr tmap_method, ParmList *parms Delete(clocals); Delete(ckwargs); - Delete(str); + Delete(parms_str); Delete(typemap); } } +/* ----------------------------------------------------------------------------- + * Swig_typemap_register() + * + * Add a new, possibly multi-argument, typemap + * ----------------------------------------------------------------------------- */ + +void Swig_typemap_register(const_String_or_char_ptr tmap_method, ParmList *parms, const_String_or_char_ptr code, ParmList *locals, ParmList *kwargs) { + typemap_register(tmap_method, parms, code, locals, kwargs, tmap_method, parms); +} + /* ----------------------------------------------------------------------------- * typemap_get() * @@ -594,6 +607,13 @@ static SwigType *strip_arrays(SwigType *type) { return t; } +static void debug_search_result_display(Node *tm) { + if (tm) + Printf(stdout, " Using: %%%s\n", Getattr(tm, "typemap")); + else + Printf(stdout, " None found\n"); +} + /* ----------------------------------------------------------------------------- * typemap_search() * @@ -612,16 +632,23 @@ static Hash *typemap_search(const_String_or_char_ptr tmap_method, SwigType *type const String *cname = 0; SwigType *unstripped = 0; String *tm_method = typemap_method_name(tmap_method); + int debug_display = (in_typemap_search_multi == 0) && typemap_search_debug; if ((name) && Len(name)) cname = name; ts = tm_scope; + if (debug_display) { + const String *empty_string = NewStringEmpty(); + Printf(stdout, "---- Searching for a suitable '%s' typemap for: %s\n", tmap_method, SwigType_str(type, cname ? cname : empty_string)); + } while (ts >= 0) { ctype = type; while (ctype) { /* Try to get an exact type-match */ tm = get_typemap(ts, ctype); + if (debug_display && cname) + Printf(stdout, " Looking for: %s\n", SwigType_str(ctype, cname)); if (tm && cname) { tm1 = Getattr(tm, cname); if (tm1) { @@ -632,6 +659,8 @@ static Hash *typemap_search(const_String_or_char_ptr tmap_method, SwigType *type backup = result; } } + if (debug_display) + Printf(stdout, " Looking for: %s\n", SwigType_str(ctype, 0)); if (tm) { result = Getattr(tm, tm_method); /* See if there is simply a type match */ if (result && Getattr(result, "code")) @@ -647,6 +676,8 @@ static Hash *typemap_search(const_String_or_char_ptr tmap_method, SwigType *type noarrays = strip_arrays(ctype); } tma = get_typemap(ts, noarrays); + if (debug_display) + Printf(stdout, " Looking for: %s\n", SwigType_str(noarrays, 0)); if (tma && cname) { tm1 = Getattr(tma, cname); if (tm1) { @@ -694,11 +725,13 @@ static Hash *typemap_search(const_String_or_char_ptr tmap_method, SwigType *type } } - /* Hmmm. Well, no match seems to be found at all. See if there is some kind of default mapping */ + /* Hmmm. Well, no match seems to be found at all. See if there is some kind of default (SWIGTYPE) mapping */ primitive = SwigType_default(type); while (primitive) { tm = get_typemap(ts, primitive); + if (debug_display && cname) + Printf(stdout, " Looking for: %s\n", SwigType_str(primitive, cname)); if (tm && cname) { tm1 = Getattr(tm, cname); if (tm1) { @@ -707,6 +740,8 @@ static Hash *typemap_search(const_String_or_char_ptr tmap_method, SwigType *type goto ret_result; } } + if (debug_display) + Printf(stdout, " Looking for: %s\n", SwigType_str(primitive, 0)); if (tm) { /* See if there is simply a type match */ result = Getattr(tm, tm_method); if (result) @@ -771,16 +806,25 @@ static Hash *typemap_search_multi(const_String_or_char_ptr tmap_method, ParmList } Delete(mtype); multi_tmap_method = NewStringf("%s-%s+%s:", tmap_method, type, name); + in_typemap_search_multi++; tm1 = typemap_search_multi(multi_tmap_method, nextSibling(parms), nmatch); + in_typemap_search_multi--; if (tm1) tm = tm1; if (Getattr(tm, "code")) { *(nmatch) = *nmatch + 1; + if (typemap_search_debug && tm1 && (in_typemap_search_multi == 0)) { + Printf(stdout, " Multi-argument typemap found...\n"); + } } else { tm = 0; } Delete(multi_tmap_method); } + + if (typemap_search_debug && (in_typemap_search_multi == 0)) + debug_search_result_display(tm); + return tm; } @@ -1236,16 +1280,25 @@ static String *Swig_typemap_lookup_impl(const_String_or_char_ptr tmap_method, No if (qsn) { if (Len(qsn) && !Equal(qsn, pname)) { tm = typemap_search(tmap_method, type, qsn, &mtype); + /* TODO: move the search for qualified names into typemap_search to make it more efficient */ if (tm && (!Getattr(tm, "pname") || strstr(Char(Getattr(tm, "type")), "SWIGTYPE"))) { + if (typemap_search_debug) + Printf(stdout, " Found but not using\n"); tm = 0; + } else { + if (typemap_search_debug) + debug_search_result_display(tm); } } Delete(qsn); } } - if (!tm) + if (!tm) { #endif tm = typemap_search(tmap_method, type, pname, &mtype); + if (typemap_search_debug) + debug_search_result_display(tm); + } if (!tm) return sdef; @@ -1921,6 +1974,8 @@ static void replace_embedded_typemap(String *s, ParmList *parm_sublist, Wrapper /* ----------------------------------------------------------------------------- * Swig_typemap_debug() + * + * Display all typemaps * ----------------------------------------------------------------------------- */ void Swig_typemap_debug() { @@ -1937,3 +1992,13 @@ void Swig_typemap_debug() { } +/* ----------------------------------------------------------------------------- + * Swig_typemap_search_debug_set() + * + * Turn on typemap searching debug display + * ----------------------------------------------------------------------------- */ + +void Swig_typemap_search_debug_set(void) { + typemap_search_debug = 1; +} +