summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2011-01-21 17:29:15 +0200
committerSergey Poznyakoff <gray@gnu.org.ua>2011-01-21 17:29:15 +0200
commit45d49848cd34a99cc326be9997a4b5d7142898fe (patch)
treeae3a73e0f7ce94c995294ddf454951bd3b5ecf4b
parentd9044ffe99b447598e649b24f5ed49ccb110e15e (diff)
downloadmailutils-45d49848cd34a99cc326be9997a4b5d7142898fe.tar.gz
mailutils-45d49848cd34a99cc326be9997a4b5d7142898fe.tar.bz2
Scheme: add primitives for manipulating the MU debug levels.
* include/mailutils/debug.h (mu_debug_get_iterator): New proto. * libmailutils/diag/debug.c (mu_debug_get_iterator): New function. * libmu_scm/Makefile.am (lib_LTLIBRARIES): Add mu_debug.c. * include/mailutils/guile.h (mu_scm_debug_init): New proto. * libmu_scm/mu_scm.c (mu-register-format): Bugfix. (mu_scm_init): Call mu_scm_debug_init.
-rw-r--r--include/mailutils/debug.h4
-rw-r--r--include/mailutils/guile.h1
-rw-r--r--libmailutils/base/iterator.c2
-rw-r--r--libmailutils/diag/debug.c172
-rw-r--r--libmu_scm/Makefile.am1
-rw-r--r--libmu_scm/mu_debug.c134
-rw-r--r--libmu_scm/mu_scm.c5
7 files changed, 315 insertions, 4 deletions
diff --git a/include/mailutils/debug.h b/include/mailutils/debug.h
index 4c7b9301e..5072d51d2 100644
--- a/include/mailutils/debug.h
+++ b/include/mailutils/debug.h
@@ -83,7 +83,9 @@ void mu_debug_log_begin (const char *fmt, ...) MU_PRINTFLIKE(1,2);
void mu_debug_log_cont (const char *fmt, ...) MU_PRINTFLIKE(1,2);
void mu_debug_log_end (const char *fmt, ...) MU_PRINTFLIKE(1,2);
void mu_debug_log_nl (void);
-
+
+ int mu_debug_get_iterator (mu_iterator_t *piterator, int skipunset);
+
#define MU_ASSERT(expr) \
do \
diff --git a/include/mailutils/guile.h b/include/mailutils/guile.h
index 741d8cfde..b990e1939 100644
--- a/include/mailutils/guile.h
+++ b/include/mailutils/guile.h
@@ -72,6 +72,7 @@ extern void mu_scm_mutil_init (void);
SCM mu_scm_make_debug_port (int level);
void mu_scm_debug_port_init (void);
+extern void mu_scm_debug_init (void);
extern void mu_guile_init (int debug);
extern int mu_guile_load (const char *filename, int argc, char **argv);
diff --git a/libmailutils/base/iterator.c b/libmailutils/base/iterator.c
index 45cb10ac8..23e4edf8e 100644
--- a/libmailutils/base/iterator.c
+++ b/libmailutils/base/iterator.c
@@ -146,7 +146,7 @@ mu_iterator_dup (mu_iterator_t *piterator, mu_iterator_t orig)
if (status)
return status;
- status = orig->dup(&iterator->owner, orig->owner);
+ status = orig->dup (&iterator->owner, orig->owner);
if (status)
{
free (iterator);
diff --git a/libmailutils/diag/debug.c b/libmailutils/diag/debug.c
index 7bcbb1353..124311bd8 100644
--- a/libmailutils/diag/debug.c
+++ b/libmailutils/diag/debug.c
@@ -32,6 +32,8 @@
#include <mailutils/wordsplit.h>
#include <mailutils/stream.h>
#include <mailutils/stdstream.h>
+#include <mailutils/iterator.h>
+#include <mailutils/cstr.h>
int mu_debug_line_info; /* Debug messages include source locations */
@@ -496,6 +498,176 @@ mu_debug_format_spec (mu_stream_t str, const char *names, int showunset)
return rc;
}
+
+/* Iterator */
+
+static mu_iterator_t iterator_head;
+
+#define ITR_BACKWARDS 0x01
+#define ITR_SKIPUNSET 0x02
+#define ITR_FINISHED 0x04
+
+struct debug_iterator
+{
+ size_t pos;
+ int flags;
+};
+
+static int
+first (void *owner)
+{
+ struct debug_iterator *itr = owner;
+ itr->flags &= ~ITR_FINISHED;
+ if (itr->flags & ITR_BACKWARDS)
+ itr->pos = catcnt - 1;
+ else
+ itr->pos = 0;
+ return 0;
+}
+
+static int
+next (void *owner)
+{
+ struct debug_iterator *itr = owner;
+ itr->flags &= ~ITR_FINISHED;
+ do
+ {
+ if (itr->flags & ITR_BACKWARDS)
+ {
+ if (itr->pos)
+ itr->pos--;
+ else
+ itr->flags |= ITR_FINISHED;
+ }
+ else
+ {
+ if (itr->pos < catcnt - 1)
+ itr->pos++;
+ else
+ itr->flags |= ITR_FINISHED;
+ }
+ }
+ while ((itr->flags & ITR_SKIPUNSET) &&
+ !(itr->flags & ITR_FINISHED) &&
+ !cattab[itr->pos].isset);
+
+ return 0;
+}
+
+static int
+getitem (void *owner, void **pret, const void **pkey)
+{
+ struct debug_iterator *itr = owner;
+ *(mu_debug_level_t*) pret = cattab[itr->pos].level;
+ if (pkey)
+ *pkey = cattab[itr->pos].name;
+ return 0;
+}
+
+static int
+finished_p (void *owner)
+{
+ struct debug_iterator *itr = owner;
+ return itr->flags & ITR_FINISHED;
+}
+
+static int
+curitem_p (void *owner, void *item)
+{
+ struct debug_iterator *itr = owner;
+ return mu_c_strcasecmp (cattab[itr->pos].name, (char *) item) == 0;
+}
+
+static int
+list_data_dup (void **ptr, void *owner)
+{
+ *ptr = malloc (sizeof (struct debug_iterator));
+ if (*ptr == NULL)
+ return ENOMEM;
+ memcpy (*ptr, owner, sizeof (struct debug_iterator));
+ return 0;
+}
+
+static int
+list_itrctl (void *owner, enum mu_itrctl_req req, void *arg)
+{
+ struct debug_iterator *itr = owner;
+
+ switch (req)
+ {
+ case mu_itrctl_tell:
+ /* Return current position in the object */
+ if (!arg)
+ return EINVAL;
+ *(size_t*)arg = itr->pos;
+ break;
+
+ case mu_itrctl_delete:
+ case mu_itrctl_delete_nd:
+ /* Delete current element */
+ cattab[itr->pos].level = 0;
+ cattab[itr->pos].isset = 0;
+ break;
+
+ case mu_itrctl_replace:
+ case mu_itrctl_replace_nd:
+ if (!arg)
+ return EINVAL;
+ cattab[itr->pos].level = *(mu_debug_level_t*)arg;
+ break;
+
+ case mu_itrctl_qry_direction:
+ if (!arg)
+ return EINVAL;
+ else
+ *(int*)arg = itr->flags & ITR_BACKWARDS;
+ break;
+
+ case mu_itrctl_set_direction:
+ if (!arg)
+ return EINVAL;
+ else
+ itr->flags |= ITR_BACKWARDS;
+ break;
+
+ default:
+ return ENOSYS;
+ }
+ return 0;
+}
+
+int
+mu_debug_get_iterator (mu_iterator_t *piterator, int skipunset)
+{
+ int status;
+ mu_iterator_t iterator;
+ struct debug_iterator *itr;
+
+ itr = malloc (sizeof *itr);
+ if (!itr)
+ return ENOMEM;
+ itr->pos = 0;
+ itr->flags = skipunset ? ITR_SKIPUNSET : 0;
+ status = mu_iterator_create (&iterator, itr);
+ if (status)
+ {
+ free (itr);
+ return status;
+ }
+
+ mu_iterator_set_first (iterator, first);
+ mu_iterator_set_next (iterator, next);
+ mu_iterator_set_getitem (iterator, getitem);
+ mu_iterator_set_finished_p (iterator, finished_p);
+ mu_iterator_set_curitem_p (iterator, curitem_p);
+ mu_iterator_set_dup (iterator, list_data_dup);
+ mu_iterator_set_itrctl (iterator, list_itrctl);
+
+ mu_iterator_attach (&iterator_head, iterator);
+
+ *piterator = iterator;
+ return 0;
+}
void
diff --git a/libmu_scm/Makefile.am b/libmu_scm/Makefile.am
index b870486f5..de74c991a 100644
--- a/libmu_scm/Makefile.am
+++ b/libmu_scm/Makefile.am
@@ -24,6 +24,7 @@ lib_LTLIBRARIES=libmu_scm.la
C_SRCS=\
mu_address.c\
mu_body.c\
+ mu_debug.c\
mu_dbgport.c\
mu_guile.c\
mu_mailbox.c\
diff --git a/libmu_scm/mu_debug.c b/libmu_scm/mu_debug.c
new file mode 100644
index 000000000..0dfcd5b45
--- /dev/null
+++ b/libmu_scm/mu_debug.c
@@ -0,0 +1,134 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 2011 Free Software Foundation, Inc.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 3 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General
+ Public License along with this library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include "mu_scm.h"
+#include <mailutils/iterator.h>
+#include <mailutils/stdstream.h>
+
+SCM_DEFINE_PUBLIC (scm_mu_debug_parse, "mu-debug-parse", 1, 0, 0,
+ (SCM spec),
+"Parses @var{spec} and sets MU debugging level according to it.")
+#define FUNC_NAME s_scm_mu_debug_parse
+{
+ char *s;
+
+ SCM_ASSERT (scm_is_string (spec), spec, SCM_ARG1, FUNC_NAME);
+ s = scm_to_locale_string (spec);
+ mu_debug_parse_spec (s);
+ free (s);
+ return SCM_UNSPECIFIED;
+}
+#undef FUNC_NAME
+
+static int
+string_member_p (SCM list, SCM x)
+{
+ return scm_member (x, list) != SCM_BOOL_F;
+}
+
+SCM_DEFINE_PUBLIC (scm_mu_debug_set, "mu-debug-set", 1, 0, 0,
+ (SCM catlist),
+"Sets MU debug level according to @var{catlist}, which is a list of\n"
+"conses: (cons category level)\n")
+#define FUNC_NAME s_scm_mu_debug_set
+{
+ SCM_ASSERT (scm_is_pair (catlist), catlist, SCM_ARG1, FUNC_NAME);
+ for (; !scm_is_null (catlist); catlist = SCM_CDR (catlist))
+ {
+ SCM cell = SCM_CAR (catlist);
+ SCM x;
+ char *name;
+ mu_debug_level_t lev;
+
+ SCM_ASSERT (scm_is_pair (cell), cell, SCM_ARGn, FUNC_NAME);
+ x = scm_car (cell);
+ SCM_ASSERT (scm_is_string (x), x, SCM_ARGn, FUNC_NAME);
+ name = scm_to_locale_string (x);
+ x = scm_cdr (cell);
+ SCM_ASSERT (scm_is_integer (x), x, SCM_ARGn, FUNC_NAME);
+ lev = scm_to_int (x);
+ if (lev == 0)
+ mu_debug_disable_category (name, strlen (name));
+ else
+ mu_debug_enable_category (name, strlen (name), lev);
+ free (name);
+ }
+ return SCM_UNSPECIFIED;
+}
+#undef FUNC_NAME
+
+SCM_DEFINE_PUBLIC (scm_mu_debug_get, "mu-debug-get", 0, 2, 0,
+ (SCM catlist, SCM skipunset),
+"Returns a list of MU debugging categories with corresponding levels.\n"
+"If @var{catlist} is supplied, it is a list of category names. In this case\n"
+"only categories from this list are returned")
+#define FUNC_NAME s_scm_mu_debug_get
+{
+ int skipunset_flag = 0;
+ mu_iterator_t itr;
+ SCM head = SCM_EOL, tail = SCM_EOL;
+ int (*member_p) (SCM list, SCM needle);
+
+ if (SCM_UNBNDP (catlist) || catlist == SCM_BOOL_F)
+ member_p = NULL;
+ else
+ {
+ SCM_ASSERT (scm_is_pair (catlist), catlist, SCM_ARG1, FUNC_NAME);
+ member_p = string_member_p;
+ }
+
+ if (!SCM_UNBNDP (skipunset))
+ {
+ SCM_ASSERT (scm_is_bool (skipunset), skipunset, SCM_ARG2, FUNC_NAME);
+ skipunset_flag = skipunset == SCM_BOOL_T;
+ }
+
+ mu_debug_get_iterator (&itr, skipunset_flag);
+ for (mu_iterator_first (itr); !mu_iterator_is_done (itr);
+ mu_iterator_next (itr))
+ {
+ const char *name;
+ mu_debug_level_t level;
+ SCM scm_name;
+
+ mu_iterator_current_kv (itr, (const void**) &name, (void**) &level);
+ scm_name = scm_from_locale_string (name);
+ if (!member_p || member_p (catlist, scm_name))
+ {
+ SCM scm_new = scm_cons (scm_cons (scm_name,
+ scm_from_uintmax (level)),
+ SCM_EOL);
+
+ if (scm_is_null (head))
+ head = tail = scm_new;
+ else
+ {
+ SCM_SETCDR (tail, scm_new);
+ tail = scm_new;
+ }
+ }
+ }
+ mu_iterator_destroy (&itr);
+ return head;
+}
+#undef FUNC_NAME
+
+void
+mu_scm_debug_init ()
+{
+#include "mu_debug.x"
+}
diff --git a/libmu_scm/mu_scm.c b/libmu_scm/mu_scm.c
index 9e43506ff..dc24b1e65 100644
--- a/libmu_scm/mu_scm.c
+++ b/libmu_scm/mu_scm.c
@@ -128,7 +128,7 @@ SCM_DEFINE_PUBLIC (scm_mu_register_format, "mu-register-format", 0, 0, 1,
SCM_ASSERT (scm_is_string (scm), scm, SCM_ARGn, FUNC_NAME);
s = scm_to_locale_string (scm);
status = register_format (s);
- free (scm);
+ free (s);
if (status)
mu_scm_error (FUNC_NAME, status,
"Cannot register format ~A",
@@ -210,9 +210,10 @@ mu_scm_init ()
mu_scm_port_init ();
mu_scm_mime_init ();
mu_scm_debug_port_init ();
+ mu_scm_debug_init ();
#include "mu_scm.x"
-
+
mu_registrar_record (MU_DEFAULT_RECORD);
mu_registrar_set_default_record (MU_DEFAULT_RECORD);
}

Return to:

Send suggestions and report system problems to the System administrator.