* guile: some general improvements / cleanups in module loading, object

visibilty. turn some integers (such as message priority, log level, contact
  type) into symbols.
This commit is contained in:
djcb
2012-07-14 12:32:15 +03:00
parent fcb202d618
commit 8e3fbe380e
10 changed files with 576 additions and 671 deletions

View File

@ -32,6 +32,17 @@
#include <mu-msg.h>
#include <mu-msg-part.h>
/* pseudo field, not in Xapian */
#define MU_GUILE_MSG_FIELD_ID_TIMESTAMP (MU_MSG_FIELD_ID_NUM + 1)
/* some symbols */
static SCM SYMB_PRIO_LOW, SYMB_PRIO_NORMAL, SYMB_PRIO_HIGH;
static SCM SYMB_FLAG_NEW, SYMB_FLAG_PASSED, SYMB_FLAG_REPLIED,
SYMB_FLAG_SEEN, SYMB_FLAG_TRASHED, SYMB_FLAG_DRAFT,
SYMB_FLAG_FLAGGED, SYMB_FLAG_SIGNED, SYMB_FLAG_ENCRYPTED,
SYMB_FLAG_HAS_ATTACH, SYMB_FLAG_UNREAD;
static SCM SYMB_CONTACT_TO, SYMB_CONTACT_CC, SYMB_CONTACT_BCC,
SYMB_CONTACT_FROM;
struct _MuMsgWrapper {
MuMsg *_msg;
@ -40,10 +51,6 @@ struct _MuMsgWrapper {
typedef struct _MuMsgWrapper MuMsgWrapper;
static long MSG_TAG;
/* pseudo field, not in Xapian */
#define MU_GUILE_MSG_FIELD_ID_TIMESTAMP (MU_MSG_FIELD_ID_NUM + 1)
static gboolean
mu_guile_scm_is_msg (SCM scm)
{
@ -64,109 +71,6 @@ mu_guile_msg_to_scm (MuMsg *msg)
SCM_RETURN_NEWSMOB (MSG_TAG, msgwrap);
}
static SCM
msg_mark (SCM msg_smob)
{
MuMsgWrapper *msgwrap;
msgwrap = (MuMsgWrapper*) SCM_CDR(msg_smob);
msgwrap->_unrefme = TRUE;
return SCM_UNSPECIFIED;
}
static size_t
msg_free (SCM msg_smob)
{
MuMsgWrapper *msgwrap;
msgwrap = (MuMsgWrapper*) SCM_CDR(msg_smob);
if (msgwrap->_unrefme)
mu_msg_unref (msgwrap->_msg);
return sizeof (MuMsgWrapper);
}
static int
msg_print (SCM msg_smob, SCM port, scm_print_state * pstate)
{
MuMsgWrapper *msgwrap;
msgwrap = (MuMsgWrapper*) SCM_CDR(msg_smob);
scm_puts ("#<msg ", port);
if (msg_smob == SCM_BOOL_F)
scm_puts ("#f", port);
else
scm_puts (mu_msg_get_path(msgwrap->_msg),
port);
scm_puts (">", port);
return 1;
}
/* SCM_DEFINE_PUBLIC (msg_make_from_file, "mu:msg:make-from-file", 1, 0, 0, */
/* (SCM PATH), */
/* "Create a message object based on the message in PATH.\n") */
/* #define FUNC_NAME s_msg_make_from_file */
/* { */
/* MuMsg *msg; */
/* GError *err; */
/* SCM_ASSERT (scm_is_string (PATH), PATH, SCM_ARG1, FUNC_NAME); */
/* err = NULL; */
/* msg = mu_msg_new_from_file (scm_to_utf8_string (PATH), NULL, &err); */
/* if (err) { */
/* mu_guile_g_error (FUNC_NAME, err); */
/* g_error_free (err); */
/* } */
/* return msg ? mu_guile_msg_to_scm (msg) : SCM_UNDEFINED; */
/* } */
/* #undef FUNC_NAME */
/* SCM_DEFINE_PUBLIC (msg_move, "mu:msg:move-to-maildir", 2, 0, 0, */
/* (SCM MSG, SCM TARGETMDIR), */
/* "Move message to another maildir TARGETMDIR. Note that this the " */
/* "base-level Maildir, ie. /home/user/Maildir/archive, and must" */
/* " _not_ include the 'cur' or 'new' part. mu_msg_move_to_maildir " */
/* "will make sure that the copy is from new/ to new/ and cur/ to " */
/* "cur/. Also note that the target maildir must be on the same " */
/* "filesystem. Returns #t if it worked, #f otherwise.\n") */
/* #define FUNC_NAME s_msg_move */
/* { */
/* GError *err; */
/* MuMsgWrapper *msgwrap; */
/* gboolean rv; */
/* MuFlags flags; */
/* SCM_ASSERT (mu_guile_scm_is_msg(MSG), MSG, SCM_ARG1, FUNC_NAME); */
/* SCM_ASSERT (scm_is_string (TARGETMDIR), TARGETMDIR, SCM_ARG2, FUNC_NAME); */
/* msgwrap = (MuMsgWrapper*) SCM_CDR(MSG); */
/* err = NULL; */
/* flags = mu_msg_get_flags (msgwrap->_msg); */
/* rv = mu_msg_move_to_maildir (msgwrap->_msg, */
/* scm_to_utf8_string (TARGETMDIR), flags, */
/* FALSE, &err); */
/* if (!rv && err) { */
/* mu_guile_g_error (FUNC_NAME, err); */
/* g_error_free (err); */
/* } */
/* return rv ? SCM_BOOL_T : SCM_BOOL_F; */
/* } */
/* #undef FUNC_NAME */
struct _FlagData {
MuFlags flags;
SCM lst;
@ -174,23 +78,37 @@ struct _FlagData {
typedef struct _FlagData FlagData;
static void
check_flag (MuFlags flag, FlagData *fdata)
{
SCM item;
char *flagsym;
SCM flag_scm;
if (!(fdata->flags & flag))
return;
flagsym = g_strconcat ("mu:", mu_flag_name(flag), NULL);
item = scm_list_1 (scm_from_utf8_symbol(flagsym));
g_free (flagsym);
switch (flag) {
case MU_FLAG_NEW: flag_scm = SYMB_FLAG_NEW; break;
case MU_FLAG_PASSED: flag_scm = SYMB_FLAG_PASSED; break;
case MU_FLAG_REPLIED: flag_scm = SYMB_FLAG_REPLIED; break;
case MU_FLAG_SEEN: flag_scm = SYMB_FLAG_SEEN; break;
case MU_FLAG_TRASHED: flag_scm = SYMB_FLAG_TRASHED; break;
case MU_FLAG_SIGNED: flag_scm = SYMB_FLAG_SIGNED; break;
case MU_FLAG_DRAFT: flag_scm = SYMB_FLAG_DRAFT; break;
case MU_FLAG_FLAGGED: flag_scm = SYMB_FLAG_FLAGGED; break;
case MU_FLAG_ENCRYPTED: flag_scm = SYMB_FLAG_ENCRYPTED; break;
case MU_FLAG_HAS_ATTACH: flag_scm = SYMB_FLAG_HAS_ATTACH; break;
case MU_FLAG_UNREAD: flag_scm = SYMB_FLAG_UNREAD; break;
default: flag_scm = SCM_UNDEFINED;
}
fdata->lst = scm_append_x (scm_list_2(fdata->lst, item));
fdata->lst = scm_append_x
(scm_list_2(fdata->lst,
scm_list_1 (flag_scm)));
}
static SCM
get_flags_scm (MuMsg *msg)
{
@ -210,12 +128,10 @@ get_prio_scm (MuMsg *msg)
{
switch (mu_msg_get_prio (msg)) {
case MU_MSG_PRIO_LOW:
return scm_from_utf8_symbol("mu:low");
case MU_MSG_PRIO_NORMAL:
return scm_from_utf8_symbol("mu:normal");
case MU_MSG_PRIO_HIGH:
return scm_from_utf8_symbol("mu:high");
case MU_MSG_PRIO_LOW: return SYMB_PRIO_LOW;
case MU_MSG_PRIO_NORMAL: return SYMB_PRIO_NORMAL;
case MU_MSG_PRIO_HIGH: return SYMB_PRIO_HIGH;
default:
g_return_val_if_reached (SCM_UNDEFINED);
}
@ -241,9 +157,9 @@ msg_string_list_field (MuMsg *msg, MuMsgFieldId mfid)
}
SCM_DEFINE_PUBLIC(get_field, "mu:get-field", 2, 0, 0,
(SCM MSG, SCM FIELD),
"Get the field FIELD from message MSG.\n")
SCM_DEFINE (get_field, "mu:c:get-field", 2, 0, 0,
(SCM MSG, SCM FIELD),
"Get the field FIELD from message MSG.\n")
#define FUNC_NAME s_get_field
{
MuMsgWrapper *msgwrap;
@ -326,17 +242,16 @@ contacts_to_list (MuMsgContact *contact, EachContactData *ecdata)
}
SCM_DEFINE_PUBLIC (get_contacts, "mu:get-contacts", 2, 0, 0,
(SCM MSG, SCM CONTACT_TYPE),
"Get a list of contact information pairs.\n")
SCM_DEFINE (get_contacts, "mu:c:get-contacts", 2, 0, 0,
(SCM MSG, SCM CONTACT_TYPE),
"Get a list of contact information pairs.\n")
#define FUNC_NAME s_get_contacts
{
MuMsgWrapper *msgwrap;
EachContactData ecdata;
SCM_ASSERT (mu_guile_scm_is_msg(MSG), MSG, SCM_ARG1, FUNC_NAME);
SCM_ASSERT (scm_integer_p (CONTACT_TYPE) || scm_is_bool(CONTACT_TYPE),
SCM_ASSERT (scm_symbol_p (CONTACT_TYPE) || scm_is_bool(CONTACT_TYPE),
CONTACT_TYPE, SCM_ARG2, FUNC_NAME);
if (CONTACT_TYPE == SCM_BOOL_F)
@ -344,15 +259,17 @@ SCM_DEFINE_PUBLIC (get_contacts, "mu:get-contacts", 2, 0, 0,
else if (CONTACT_TYPE == SCM_BOOL_T)
ecdata.ctype = MU_MSG_CONTACT_TYPE_ALL;
else {
MuMsgFieldId mfid;
mfid = scm_to_uint (CONTACT_TYPE);
switch (mfid) {
case MU_MSG_FIELD_ID_TO: ecdata.ctype = MU_MSG_CONTACT_TYPE_TO; break;
case MU_MSG_FIELD_ID_FROM: ecdata.ctype = MU_MSG_CONTACT_TYPE_FROM; break;
case MU_MSG_FIELD_ID_CC: ecdata.ctype = MU_MSG_CONTACT_TYPE_CC; break;
case MU_MSG_FIELD_ID_BCC: ecdata.ctype = MU_MSG_CONTACT_TYPE_BCC; break;
default: g_return_val_if_reached (SCM_UNDEFINED);
}
if (scm_is_eq (CONTACT_TYPE, SYMB_CONTACT_TO))
ecdata.ctype = MU_MSG_CONTACT_TYPE_TO;
else if (scm_is_eq (CONTACT_TYPE, SYMB_CONTACT_CC))
ecdata.ctype = MU_MSG_CONTACT_TYPE_CC;
else if (scm_is_eq (CONTACT_TYPE, SYMB_CONTACT_BCC))
ecdata.ctype = MU_MSG_CONTACT_TYPE_BCC;
else if (scm_is_eq (CONTACT_TYPE, SYMB_CONTACT_FROM))
ecdata.ctype = MU_MSG_CONTACT_TYPE_FROM;
else
/* FIXME: rais error */
g_return_val_if_reached (SCM_UNDEFINED);
}
ecdata.lst = SCM_EOL;
@ -360,8 +277,7 @@ SCM_DEFINE_PUBLIC (get_contacts, "mu:get-contacts", 2, 0, 0,
mu_msg_contact_foreach (msgwrap->_msg,
(MuMsgContactForeachFunc)contacts_to_list,
&ecdata);
/* explicitly close the file backend, so we won't run of fds */
/* explicitly close the file backend, so we won't run out of fds */
mu_msg_close_file_backend (msgwrap->_msg);
return ecdata.lst;
@ -412,7 +328,7 @@ each_part (MuMsg *msg, MuMsgPart *part, AttInfo *attinfo)
}
SCM_DEFINE_PUBLIC (get_parts, "mu:get-parts", 1, 1, 0,
SCM_DEFINE (get_parts, "mu:c:get-parts", 1, 1, 0,
(SCM MSG, SCM ATTS_ONLY),
"Get the list of mime-parts for MSG. If ATTS_ONLY is #t, only"
"get parts that are (look like) attachments. The resulting list has "
@ -441,56 +357,8 @@ SCM_DEFINE_PUBLIC (get_parts, "mu:get-parts", 1, 1, 0,
#undef FUNC_NAME
SCM_DEFINE_PUBLIC (save_part, "mu:save-part", 2, 0, 0,
(SCM MSGPATH, SCM INDEX),
"Create a temporary file containing the attachment; this function "
"returns the full path to that temporary file.\n")
#define FUNC_NAME s_save_part
{
GError *err;
gchar *attachpath, *msgpath;
unsigned index;
MuMsg *msg;
SCM rv_scm;
SCM_ASSERT (scm_is_string(MSGPATH), MSGPATH, SCM_ARG1, FUNC_NAME);
SCM_ASSERT (scm_is_integer (INDEX),
INDEX,SCM_ARG2, FUNC_NAME);
index = scm_to_uint (INDEX);
msgpath = scm_to_utf8_string (MSGPATH);
attachpath = NULL;
err = NULL;
msg = mu_msg_new_from_file (msgpath, NULL, &err);
if (!msg) {
rv_scm = mu_guile_g_error (FUNC_NAME, err);
goto leave;
}
attachpath = mu_msg_part_save_temp (msg, index, &err);
if (!attachpath) {
rv_scm = mu_guile_g_error (FUNC_NAME, err);
goto leave;
}
rv_scm = mu_guile_scm_from_str (attachpath);
leave:
mu_msg_unref (msg);
g_clear_error (&err);
g_free (attachpath);
return rv_scm;
}
#undef FUNC_NAME
SCM_DEFINE_PUBLIC (get_header, "mu:get-header", 2, 0, 0,
(SCM MSG, SCM HEADER),
"Get an arbitary HEADER from MSG.\n")
SCM_DEFINE (get_header, "mu:c:get-header", 2, 0, 0,
(SCM MSG, SCM HEADER), "Get an arbitary HEADER from MSG.\n")
#define FUNC_NAME s_get_header
{
MuMsgWrapper *msgwrap;
@ -514,89 +382,6 @@ SCM_DEFINE_PUBLIC (get_header, "mu:get-header", 2, 0, 0,
#undef FUNC_NAME
static struct {
const char* name;
unsigned val;
} SYMPAIRS[] = {
{ "mu:prio:high", MU_MSG_PRIO_HIGH },
{ "mu:prio:low", MU_MSG_PRIO_LOW },
{ "mu:prio:normal", MU_MSG_PRIO_NORMAL },
{ "mu:flag:new", MU_FLAG_NEW },
{ "mu:flag:passed", MU_FLAG_PASSED },
{ "mu:flag:replied", MU_FLAG_REPLIED },
{ "mu:flag:seen", MU_FLAG_SEEN },
{ "mu:flag:trashed", MU_FLAG_TRASHED },
{ "mu:flag:draft", MU_FLAG_DRAFT },
{ "mu:flag:flagged", MU_FLAG_FLAGGED },
{ "mu:flag:signed", MU_FLAG_SIGNED },
{ "mu:flag:encrypted", MU_FLAG_ENCRYPTED },
{ "mu:flag:has-attach", MU_FLAG_HAS_ATTACH },
{ "mu:flag:unread", MU_FLAG_UNREAD },
{ "mu:field:bcc", MU_MSG_FIELD_ID_BCC },
{ "mu:field:body-html", MU_MSG_FIELD_ID_BODY_HTML },
{ "mu:field:body-txt", MU_MSG_FIELD_ID_BODY_TEXT },
{ "mu:field:cc", MU_MSG_FIELD_ID_CC },
{ "mu:field:date", MU_MSG_FIELD_ID_DATE },
{ "mu:field:flags", MU_MSG_FIELD_ID_FLAGS },
{ "mu:field:from", MU_MSG_FIELD_ID_FROM },
{ "mu:field:maildir", MU_MSG_FIELD_ID_MAILDIR },
{ "mu:field:message-id",MU_MSG_FIELD_ID_MSGID },
{ "mu:field:path", MU_MSG_FIELD_ID_PATH },
{ "mu:field:prio", MU_MSG_FIELD_ID_PRIO },
{ "mu:field:refs", MU_MSG_FIELD_ID_REFS },
{ "mu:field:size", MU_MSG_FIELD_ID_SIZE },
{ "mu:field:subject", MU_MSG_FIELD_ID_SUBJECT },
{ "mu:field:tags", MU_MSG_FIELD_ID_TAGS },
{ "mu:field:to", MU_MSG_FIELD_ID_TO },
/* non-Xapian field: timestamp */
{ "mu:field:timestamp", MU_GUILE_MSG_FIELD_ID_TIMESTAMP }
};
static void
define_symbols (void)
{
unsigned u;
for (u = 0; u != G_N_ELEMENTS(SYMPAIRS); ++u) {
scm_c_define (SYMPAIRS[u].name,
scm_from_uint (SYMPAIRS[u].val));
scm_c_export (SYMPAIRS[u].name, NULL);
}
}
/* gboolean */
/* mu_guile_msg_load_current (const char *path) */
/* { */
/* MuMsg *msg; */
/* GError *err; */
/* SCM msgsmob; */
/* err = NULL; */
/* msg = mu_msg_new_from_file (path, NULL, &err); */
/* if (!msg) { */
/* g_printerr ("error creating message for '%s'", path); */
/* if (err) { */
/* g_printerr (": %s", err->message); */
/* g_error_free (err); */
/* } */
/* g_printerr ("\n"); */
/* return FALSE; */
/* } */
/* msgsmob = mu_guile_msg_to_scm (msg); */
/* scm_c_define ("mu:current-msg", msgsmob); */
/* return TRUE; */
/* } */
static void
call_func (SCM FUNC, MuMsgIter *iter, const char* func_name)
{
@ -628,14 +413,14 @@ get_query_iter (MuQuery *query, const char* expr, int maxnum)
}
SCM_DEFINE_PUBLIC (for_each_msg_internal, "mu:for-each-msg-internal", 3, 0, 0,
(SCM FUNC, SCM EXPR, SCM MAXNUM),
"Call FUNC for each msg in the message store matching EXPR. EXPR is "
SCM_DEFINE (for_each_message, "mu:c:for-each-message", 3, 0, 0,
(SCM FUNC, SCM EXPR, SCM MAXNUM),
"Call FUNC for each msg in the message store matching EXPR. EXPR is"
"either a string containing a mu search expression or a boolean; in the former "
"case, limit the messages to only those matching the expression, in the "
"latter case, match /all/ messages if the EXPR equals #t, and match "
"none if EXPR equals #f. Note -- function for internal use.")
#define FUNC_NAME s_for_each_msg_internal
"none if EXPR equals #f.")
#define FUNC_NAME s_for_each_message
{
MuMsgIter *iter;
char* expr;
@ -645,9 +430,6 @@ SCM_DEFINE_PUBLIC (for_each_msg_internal, "mu:for-each-msg-internal", 3, 0, 0,
EXPR, SCM_ARG2, FUNC_NAME);
SCM_ASSERT (scm_is_integer (MAXNUM), MAXNUM, SCM_ARG3, FUNC_NAME);
if (!mu_guile_initialized())
return mu_guile_error (FUNC_NAME, 0, "mu not initialized",
SCM_UNSPECIFIED);
if (EXPR == SCM_BOOL_F)
return SCM_UNSPECIFIED; /* nothing to do */
@ -673,6 +455,124 @@ SCM_DEFINE_PUBLIC (for_each_msg_internal, "mu:for-each-msg-internal", 3, 0, 0,
#undef FUNC_NAME
static SCM
register_symbol (const char *name)
{
SCM scm;
scm = scm_from_utf8_symbol (name);
scm_c_define (name, scm);
scm_c_export (name, NULL);
return scm;
}
static void
define_symbols (void)
{
SYMB_CONTACT_TO = register_symbol ("mu:contact:to");
SYMB_CONTACT_CC = register_symbol ("mu:contact:cc");
SYMB_CONTACT_FROM = register_symbol ("mu:contact:from");
SYMB_CONTACT_BCC = register_symbol ("mu:contact:bcc");
SYMB_PRIO_LOW = register_symbol ("mu:prio:low");
SYMB_PRIO_NORMAL = register_symbol ("mu:prio:normal");
SYMB_PRIO_HIGH = register_symbol ("mu:prio:high");
SYMB_FLAG_NEW = register_symbol ("mu:flag:new");
SYMB_FLAG_PASSED = register_symbol ("mu:flag:passed");
SYMB_FLAG_REPLIED = register_symbol ("mu:flag:replied");
SYMB_FLAG_SEEN = register_symbol ("mu:flag:seen");
SYMB_FLAG_TRASHED = register_symbol ("mu:flag:trashed");
SYMB_FLAG_DRAFT = register_symbol ("mu:flag:draft");
SYMB_FLAG_FLAGGED = register_symbol ("mu:flag:flagged");
SYMB_FLAG_SIGNED = register_symbol ("mu:flag:signed");
SYMB_FLAG_ENCRYPTED = register_symbol ("mu:flag:encrypted");
SYMB_FLAG_HAS_ATTACH = register_symbol ("mu:flag:has-attach");
SYMB_FLAG_UNREAD = register_symbol ("mu:flag:unread");
}
static struct {
const char* name;
unsigned val;
} VAR_PAIRS[] = {
{ "mu:field:bcc", MU_MSG_FIELD_ID_BCC },
{ "mu:field:body-html", MU_MSG_FIELD_ID_BODY_HTML },
{ "mu:field:body-txt", MU_MSG_FIELD_ID_BODY_TEXT },
{ "mu:field:cc", MU_MSG_FIELD_ID_CC },
{ "mu:field:date", MU_MSG_FIELD_ID_DATE },
{ "mu:field:flags", MU_MSG_FIELD_ID_FLAGS },
{ "mu:field:from", MU_MSG_FIELD_ID_FROM },
{ "mu:field:maildir", MU_MSG_FIELD_ID_MAILDIR },
{ "mu:field:message-id",MU_MSG_FIELD_ID_MSGID },
{ "mu:field:path", MU_MSG_FIELD_ID_PATH },
{ "mu:field:prio", MU_MSG_FIELD_ID_PRIO },
{ "mu:field:refs", MU_MSG_FIELD_ID_REFS },
{ "mu:field:size", MU_MSG_FIELD_ID_SIZE },
{ "mu:field:subject", MU_MSG_FIELD_ID_SUBJECT },
{ "mu:field:tags", MU_MSG_FIELD_ID_TAGS },
{ "mu:field:to", MU_MSG_FIELD_ID_TO },
/* non-Xapian field: timestamp */
{ "mu:field:timestamp", MU_GUILE_MSG_FIELD_ID_TIMESTAMP }
};
static void
define_vars (void)
{
unsigned u;
for (u = 0; u != G_N_ELEMENTS(VAR_PAIRS); ++u) {
scm_c_define (VAR_PAIRS[u].name,
scm_from_uint (VAR_PAIRS[u].val));
scm_c_export (VAR_PAIRS[u].name, NULL);
}
}
static SCM
msg_mark (SCM msg_smob)
{
MuMsgWrapper *msgwrap;
msgwrap = (MuMsgWrapper*) SCM_CDR(msg_smob);
msgwrap->_unrefme = TRUE;
return SCM_UNSPECIFIED;
}
static size_t
msg_free (SCM msg_smob)
{
MuMsgWrapper *msgwrap;
msgwrap = (MuMsgWrapper*) SCM_CDR(msg_smob);
if (msgwrap->_unrefme)
mu_msg_unref (msgwrap->_msg);
return sizeof (MuMsgWrapper);
}
static int
msg_print (SCM msg_smob, SCM port, scm_print_state * pstate)
{
MuMsgWrapper *msgwrap;
msgwrap = (MuMsgWrapper*) SCM_CDR(msg_smob);
scm_puts ("#<msg ", port);
if (msg_smob == SCM_BOOL_F)
scm_puts ("#f", port);
else
scm_puts (mu_msg_get_path(msgwrap->_msg),
port);
scm_puts (">", port);
return 1;
}
void*
mu_guile_message_init (void *data)
@ -683,9 +583,12 @@ mu_guile_message_init (void *data)
scm_set_smob_free (MSG_TAG, msg_free);
scm_set_smob_print (MSG_TAG, msg_print);
define_vars ();
define_symbols ();
#ifndef SCM_MAGIC_SNARFER
#include "mu-guile-message.x"
#endif /*SCM_MAGIC_SNARFER*/
return NULL;
}