diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2011-01-21 17:29:15 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2011-01-21 17:29:15 +0200 |
commit | 45d49848cd34a99cc326be9997a4b5d7142898fe (patch) | |
tree | ae3a73e0f7ce94c995294ddf454951bd3b5ecf4b | |
parent | d9044ffe99b447598e649b24f5ed49ccb110e15e (diff) | |
download | mailutils-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.h | 4 | ||||
-rw-r--r-- | include/mailutils/guile.h | 1 | ||||
-rw-r--r-- | libmailutils/base/iterator.c | 2 | ||||
-rw-r--r-- | libmailutils/diag/debug.c | 172 | ||||
-rw-r--r-- | libmu_scm/Makefile.am | 1 | ||||
-rw-r--r-- | libmu_scm/mu_debug.c | 134 | ||||
-rw-r--r-- | libmu_scm/mu_scm.c | 5 |
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); } |