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.
This commit is contained in:
Mike Alexander 2017-04-04 02:23:44 -04:00
parent e20009a08d
commit a2687bcbe3
2 changed files with 47 additions and 20 deletions

View File

@ -72,23 +72,23 @@ typedef char gchar;
%typemap(in) time64 * (time64 t) "t = scm_to_int64($input); $1 = &t;" %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(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; SCM tm = $input;
struct tm t = { SCM zone;
scm_to_int(SCM_SIMPLE_VECTOR_REF(tm, 0)), t.tm_sec = scm_to_int(SCM_SIMPLE_VECTOR_REF(tm, 0));
scm_to_int(SCM_SIMPLE_VECTOR_REF(tm, 1)), t.tm_min = scm_to_int(SCM_SIMPLE_VECTOR_REF(tm, 1));
scm_to_int(SCM_SIMPLE_VECTOR_REF(tm, 2)), t.tm_hour = scm_to_int(SCM_SIMPLE_VECTOR_REF(tm, 2));
scm_to_int(SCM_SIMPLE_VECTOR_REF(tm, 3)), t.tm_mday = scm_to_int(SCM_SIMPLE_VECTOR_REF(tm, 3));
scm_to_int(SCM_SIMPLE_VECTOR_REF(tm, 4)), t.tm_mon = scm_to_int(SCM_SIMPLE_VECTOR_REF(tm, 4));
scm_to_int(SCM_SIMPLE_VECTOR_REF(tm, 5)), t.tm_year = scm_to_int(SCM_SIMPLE_VECTOR_REF(tm, 5));
scm_to_int(SCM_SIMPLE_VECTOR_REF(tm, 6)), t.tm_wday = scm_to_int(SCM_SIMPLE_VECTOR_REF(tm, 6));
scm_to_int(SCM_SIMPLE_VECTOR_REF(tm, 7)), t.tm_yday = scm_to_int(SCM_SIMPLE_VECTOR_REF(tm, 7));
scm_to_int(SCM_SIMPLE_VECTOR_REF(tm, 8)), t.tm_isdst = scm_to_int(SCM_SIMPLE_VECTOR_REF(tm, 8));
#ifdef HAVE_STRUCT_TM_GMTOFF %#ifdef HAVE_STRUCT_TM_GMTOFF
scm_to_int(SCM_SIMPLE_VECTOR_REF(tm, 9)), t.tm_gmtoff = scm_to_int(SCM_SIMPLE_VECTOR_REF(tm, 9));
scm_to_locale_string(SCM_SIMPLE_VECTOR_REF(tm, 10)), zone = SCM_SIMPLE_VECTOR_REF(tm, 10);
#endif t.tm_zone = SCM_UNBNDP(zone) ? NULL : scm_to_locale_string(zone);
}; %#endif
$1 = &t; $1 = &t;
} }
@ -104,16 +104,39 @@ typedef char gchar;
SCM_SIMPLE_VECTOR_SET(tm, 6, scm_from_int(t->tm_wday)); 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, 7, scm_from_int(t->tm_yday));
SCM_SIMPLE_VECTOR_SET(tm, 8, scm_from_int(t->tm_isdst)); 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, 9, scm_from_long(t->tm_gmtoff));
SCM_SIMPLE_VECTOR_SET(tm, 10, scm_from_locale_string(t->tm_zone)); SCM_SIMPLE_VECTOR_SET(tm, 10, scm_from_locale_string(t->tm_zone?t->tm_zone:"Unset"));
#else %#else
SCM_SIMPLE_VECTOR_SET(tm, 9, scm_from_long(0)); SCM_SIMPLE_VECTOR_SET(tm, 9, scm_from_long(0));
SCM_SIMPLE_VECTOR_SET(tm, 10, scm_from_locale_string("GMT")); SCM_SIMPLE_VECTOR_SET(tm, 10, scm_from_locale_string("GMT"));
#endif %#endif
$result = tm; $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) %define GLIST_HELPER_INOUT(ListType, ElemSwigType)
%typemap(in) ListType * { %typemap(in) ListType * {
SCM list = $input; SCM list = $input;

View File

@ -107,6 +107,9 @@ functions. */
%newobject xaccSplitGetCorrAccountFullName; %newobject xaccSplitGetCorrAccountFullName;
%newobject gnc_numeric_to_string; %newobject gnc_numeric_to_string;
%newobject gnc_localtime;
%newobject gnc_gmtime;
/* Parse the header file to generate wrappers */ /* Parse the header file to generate wrappers */
%inline { %inline {
static QofIdType QOF_ID_BOOK_SCM (void) { return QOF_ID_BOOK; } 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); const char *qof_session_get_url (QofSession *session);
%ignore qof_print_date_time_buff; %ignore qof_print_date_time_buff;
%ignore gnc_tm_free;
%include <gnc-date.h> %include <gnc-date.h>
extern const char *gnc_default_strftime_date_format; extern const char *gnc_default_strftime_date_format;