From a2687bcbe35f98c4646842fdc225f11b58c4a46f Mon Sep 17 00:00:00 2001 From: Mike Alexander Date: Tue, 4 Apr 2017 02:23:44 -0400 Subject: [PATCH] Fix the SWIG Guile wrapping of functions that have a "struct tm" parameter. The biggest problem was that a pointer to an out of scope struct tm was passed to the wrapped function. With opt level 2, clang doesn't bother setting the contents of the struct since it goes out of scope without being used. This caused the transaction report to never report anything since the start and end times it got were ridiculous. Also most functions that take a struct tm pointer can change the contents of the struct (if only to normalize it) so pass the new values back to Scheme. Finally all calls to gnc_localtime and gnc_gmtime from Scheme leaked a struct tm and calling gnc_tm_free from Scheme is a really bad idea so don't wrap it. --- src/base-typemaps.i | 63 +++++++++++++++++++++++++++++++-------------- src/engine/engine.i | 4 +++ 2 files changed, 47 insertions(+), 20 deletions(-) diff --git a/src/base-typemaps.i b/src/base-typemaps.i index 727949fb05..187b64ea63 100644 --- a/src/base-typemaps.i +++ b/src/base-typemaps.i @@ -72,23 +72,23 @@ typedef char gchar; %typemap(in) time64 * (time64 t) "t = scm_to_int64($input); $1 = &t;" %typemap(out) time64 * " $result = ($1) ? scm_from_int64(*($1)) : SCM_BOOL_F; " -%typemap(in) struct tm * { +%typemap(in) struct tm * (struct tm t) { SCM tm = $input; - struct tm t = { - scm_to_int(SCM_SIMPLE_VECTOR_REF(tm, 0)), - scm_to_int(SCM_SIMPLE_VECTOR_REF(tm, 1)), - scm_to_int(SCM_SIMPLE_VECTOR_REF(tm, 2)), - scm_to_int(SCM_SIMPLE_VECTOR_REF(tm, 3)), - scm_to_int(SCM_SIMPLE_VECTOR_REF(tm, 4)), - scm_to_int(SCM_SIMPLE_VECTOR_REF(tm, 5)), - scm_to_int(SCM_SIMPLE_VECTOR_REF(tm, 6)), - scm_to_int(SCM_SIMPLE_VECTOR_REF(tm, 7)), - scm_to_int(SCM_SIMPLE_VECTOR_REF(tm, 8)), -#ifdef HAVE_STRUCT_TM_GMTOFF - scm_to_int(SCM_SIMPLE_VECTOR_REF(tm, 9)), - scm_to_locale_string(SCM_SIMPLE_VECTOR_REF(tm, 10)), -#endif - }; + SCM zone; + t.tm_sec = scm_to_int(SCM_SIMPLE_VECTOR_REF(tm, 0)); + t.tm_min = scm_to_int(SCM_SIMPLE_VECTOR_REF(tm, 1)); + t.tm_hour = scm_to_int(SCM_SIMPLE_VECTOR_REF(tm, 2)); + t.tm_mday = scm_to_int(SCM_SIMPLE_VECTOR_REF(tm, 3)); + t.tm_mon = scm_to_int(SCM_SIMPLE_VECTOR_REF(tm, 4)); + t.tm_year = scm_to_int(SCM_SIMPLE_VECTOR_REF(tm, 5)); + t.tm_wday = scm_to_int(SCM_SIMPLE_VECTOR_REF(tm, 6)); + t.tm_yday = scm_to_int(SCM_SIMPLE_VECTOR_REF(tm, 7)); + t.tm_isdst = scm_to_int(SCM_SIMPLE_VECTOR_REF(tm, 8)); +%#ifdef HAVE_STRUCT_TM_GMTOFF + t.tm_gmtoff = scm_to_int(SCM_SIMPLE_VECTOR_REF(tm, 9)); + zone = SCM_SIMPLE_VECTOR_REF(tm, 10); + t.tm_zone = SCM_UNBNDP(zone) ? NULL : scm_to_locale_string(zone); +%#endif $1 = &t; } @@ -104,15 +104,38 @@ typedef char gchar; SCM_SIMPLE_VECTOR_SET(tm, 6, scm_from_int(t->tm_wday)); SCM_SIMPLE_VECTOR_SET(tm, 7, scm_from_int(t->tm_yday)); SCM_SIMPLE_VECTOR_SET(tm, 8, scm_from_int(t->tm_isdst)); -#ifdef HAVE_STRUCT_TM_GMTOFF +%#ifdef HAVE_STRUCT_TM_GMTOFF SCM_SIMPLE_VECTOR_SET(tm, 9, scm_from_long(t->tm_gmtoff)); - SCM_SIMPLE_VECTOR_SET(tm, 10, scm_from_locale_string(t->tm_zone)); -#else + SCM_SIMPLE_VECTOR_SET(tm, 10, scm_from_locale_string(t->tm_zone?t->tm_zone:"Unset")); +%#else SCM_SIMPLE_VECTOR_SET(tm, 9, scm_from_long(0)); SCM_SIMPLE_VECTOR_SET(tm, 10, scm_from_locale_string("GMT")); -#endif +%#endif $result = tm; } + +%typemap(newfree) struct tm * "gnc_tm_free($1);" + +%typemap(argout) struct tm * { + struct tm* t = $1; + SCM tm = $input; + SCM_SIMPLE_VECTOR_SET(tm, 0, scm_from_int(t->tm_sec)); + SCM_SIMPLE_VECTOR_SET(tm, 1, scm_from_int(t->tm_min)); + SCM_SIMPLE_VECTOR_SET(tm, 2, scm_from_int(t->tm_hour)); + SCM_SIMPLE_VECTOR_SET(tm, 3, scm_from_int(t->tm_mday)); + SCM_SIMPLE_VECTOR_SET(tm, 4, scm_from_int(t->tm_mon)); + SCM_SIMPLE_VECTOR_SET(tm, 5, scm_from_int(t->tm_year)); + SCM_SIMPLE_VECTOR_SET(tm, 6, scm_from_int(t->tm_wday)); + SCM_SIMPLE_VECTOR_SET(tm, 7, scm_from_int(t->tm_yday)); + SCM_SIMPLE_VECTOR_SET(tm, 8, scm_from_int(t->tm_isdst)); +%#ifdef HAVE_STRUCT_TM_GMTOFF + SCM_SIMPLE_VECTOR_SET(tm, 9, scm_from_long(t->tm_gmtoff)); + SCM_SIMPLE_VECTOR_SET(tm, 10, scm_from_locale_string(t->tm_zone?t->tm_zone:"Unset")); +%#else + SCM_SIMPLE_VECTOR_SET(tm, 9, scm_from_long(0)); + SCM_SIMPLE_VECTOR_SET(tm, 10, scm_from_locale_string("GMT")); +%#endif + } %define GLIST_HELPER_INOUT(ListType, ElemSwigType) %typemap(in) ListType * { diff --git a/src/engine/engine.i b/src/engine/engine.i index 14c1214e5c..9001eb6b48 100644 --- a/src/engine/engine.i +++ b/src/engine/engine.i @@ -107,6 +107,9 @@ functions. */ %newobject xaccSplitGetCorrAccountFullName; %newobject gnc_numeric_to_string; +%newobject gnc_localtime; +%newobject gnc_gmtime; + /* Parse the header file to generate wrappers */ %inline { static QofIdType QOF_ID_BOOK_SCM (void) { return QOF_ID_BOOK; } @@ -168,6 +171,7 @@ void qof_book_kvp_changed (QofBook *book); const char *qof_session_get_url (QofSession *session); %ignore qof_print_date_time_buff; +%ignore gnc_tm_free; %include extern const char *gnc_default_strftime_date_format;