Add -debug-tmsearch option for debugging the typemap pattern matching rules

git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@11790 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
William S Fulton 2009-12-20 00:24:34 +00:00
commit d1ff2c6a8b
5 changed files with 189 additions and 16 deletions

View file

@ -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.

View file

@ -31,10 +31,11 @@
<li><a href="#Typemaps_pattern_matching">Pattern matching rules</a>
<ul>
<li><a href="#Typemaps_nn17">Basic matching rules</a>
<li><a href="#Typemaps_nn18">Typedef reductions</a>
<li><a href="#Typemaps_typedef_reductions">Typedef reductions</a>
<li><a href="#Typemaps_nn19">Default typemaps</a>
<li><a href="#Typemaps_mixed_default">Mixed default typemaps</a>
<li><a href="#Typemaps_nn20">Multi-arguments typemaps</a>
<li><a href="#Typemaps_debugging_search">Debugging typemap pattern matching</a>
</ul>
<li><a href="#Typemaps_nn21">Code generation rules</a>
<ul>
@ -68,7 +69,7 @@
<li><a href="#Typemaps_nn40">Typemaps for arrays</a>
<li><a href="#Typemaps_nn41">Implementing constraints with typemaps</a>
</ul>
<li><a href="#Typemaps_nn43">Typemaps for multiple languages</a>
<li><a href="#Typemaps_nn43">Typemaps for multiple target languages</a>
<li><a href="#Typemaps_optimal">Optimal code generation when returning by value</a>
<li><a href="#Typemaps_multi_argument_typemaps">Multi-argument typemaps</a>
<li><a href="#runtime_type_checker">The run-time type checker</a>
@ -1090,7 +1091,7 @@ void F(int x[1000]); // int [ANY] rule (typemap 5)
</pre>
</div>
<H3><a name="Typemaps_nn18"></a>10.3.2 Typedef reductions</H3>
<H3><a name="Typemaps_typedef_reductions"></a>10.3.2 Typedef reductions</H3>
<p>
@ -1432,6 +1433,104 @@ but all subsequent arguments must match exactly.
</p>
<H3><a name="Typemaps_debugging_search"></a>10.3.6 Debugging typemap pattern matching</H3>
<p>
The <tt>-debug-tmsearch</tt> 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.
</p>
<p>
For example, consider some of the code used in the <a href="#Typemaps_typedef_reductions">Typedef reductions</a> section already covered:
</p>
<div class="code">
<pre>
typedef int Integer;
typedef Integer Row4[4];
void foo(Row4 rows[10]);
</pre>
</div>
<p>
A sample of the debugging output is shown below for the "in" typemap:
</p>
<div class="shell">
<pre>
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 []
...
</pre>
</div>
<p>
showing that the best default match supplied by SWIG is the <tt>SWIGTYPE []</tt> typemap.
As the example shows, the successful match displays just the typemap method name and type in this format: <tt>%typemap(method) type</tt>.
This information might meet your debugging needs, however, you might want to analyze further.
If you next invoke SWIG with the <tt>-E</tt> option to display the preprocessed output, and search for this particular typemap,
you'll find the full typemap contents (example shown below for Python):
</p>
<div class="code">
<pre>
%typemap(in, noblock=1) SWIGTYPE [] (void *argp = 0, int res = 0) {
res = SWIG_ConvertPtr($input, &amp;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);
}
</pre>
</div>
<p>
The generated code for the <tt>foo</tt> 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:
</p>
<div class="code">
<pre>
SWIGINTERN PyObject *_wrap_foo(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
...
void *argp1 = 0 ;
int res1 = 0 ;
...
res1 = SWIG_ConvertPtr(obj0, &amp;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);
...
}
</pre>
</div>
<H2><a name="Typemaps_nn21"></a>10.4 Code generation rules</H2>
@ -2705,12 +2804,12 @@ rather than blindly passing values to the underlying C/C++ program.</p>
Note: A more advanced constraint checking system is in development. Stay tuned.
</p>
<H2><a name="Typemaps_nn43"></a>10.7 Typemaps for multiple languages</H2>
<H2><a name="Typemaps_nn43"></a>10.7 Typemaps for multiple target languages</H2>
<p>
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:
</p>
@ -3220,7 +3319,7 @@ language modules.</li>
<p>
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.
</p>

View file

@ -69,7 +69,8 @@ static const char *usage1 = (const char *) "\
-debug-template - Display information for debugging templates\n\
-debug-top <n> - Display entire parse tree at stages 1-4, <n> 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<symbol> - Define a symbol <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]) {

View file

@ -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);

View file

@ -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;
}