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.
Showing
7 changed files
with
315 additions
and
4 deletions
... | @@ -83,7 +83,9 @@ void mu_debug_log_begin (const char *fmt, ...) MU_PRINTFLIKE(1,2); | ... | @@ -83,7 +83,9 @@ void mu_debug_log_begin (const char *fmt, ...) MU_PRINTFLIKE(1,2); |
83 | void mu_debug_log_cont (const char *fmt, ...) MU_PRINTFLIKE(1,2); | 83 | void mu_debug_log_cont (const char *fmt, ...) MU_PRINTFLIKE(1,2); |
84 | void mu_debug_log_end (const char *fmt, ...) MU_PRINTFLIKE(1,2); | 84 | void mu_debug_log_end (const char *fmt, ...) MU_PRINTFLIKE(1,2); |
85 | void mu_debug_log_nl (void); | 85 | void mu_debug_log_nl (void); |
86 | 86 | ||
87 | int mu_debug_get_iterator (mu_iterator_t *piterator, int skipunset); | ||
88 | |||
87 | 89 | ||
88 | #define MU_ASSERT(expr) \ | 90 | #define MU_ASSERT(expr) \ |
89 | do \ | 91 | do \ | ... | ... |
... | @@ -72,6 +72,7 @@ extern void mu_scm_mutil_init (void); | ... | @@ -72,6 +72,7 @@ extern void mu_scm_mutil_init (void); |
72 | SCM mu_scm_make_debug_port (int level); | 72 | SCM mu_scm_make_debug_port (int level); |
73 | void mu_scm_debug_port_init (void); | 73 | void mu_scm_debug_port_init (void); |
74 | 74 | ||
75 | extern void mu_scm_debug_init (void); | ||
75 | 76 | ||
76 | extern void mu_guile_init (int debug); | 77 | extern void mu_guile_init (int debug); |
77 | extern int mu_guile_load (const char *filename, int argc, char **argv); | 78 | extern int mu_guile_load (const char *filename, int argc, char **argv); | ... | ... |
... | @@ -146,7 +146,7 @@ mu_iterator_dup (mu_iterator_t *piterator, mu_iterator_t orig) | ... | @@ -146,7 +146,7 @@ mu_iterator_dup (mu_iterator_t *piterator, mu_iterator_t orig) |
146 | if (status) | 146 | if (status) |
147 | return status; | 147 | return status; |
148 | 148 | ||
149 | status = orig->dup(&iterator->owner, orig->owner); | 149 | status = orig->dup (&iterator->owner, orig->owner); |
150 | if (status) | 150 | if (status) |
151 | { | 151 | { |
152 | free (iterator); | 152 | free (iterator); | ... | ... |
... | @@ -32,6 +32,8 @@ | ... | @@ -32,6 +32,8 @@ |
32 | #include <mailutils/wordsplit.h> | 32 | #include <mailutils/wordsplit.h> |
33 | #include <mailutils/stream.h> | 33 | #include <mailutils/stream.h> |
34 | #include <mailutils/stdstream.h> | 34 | #include <mailutils/stdstream.h> |
35 | #include <mailutils/iterator.h> | ||
36 | #include <mailutils/cstr.h> | ||
35 | 37 | ||
36 | int mu_debug_line_info; /* Debug messages include source locations */ | 38 | int mu_debug_line_info; /* Debug messages include source locations */ |
37 | 39 | ||
... | @@ -496,6 +498,176 @@ mu_debug_format_spec (mu_stream_t str, const char *names, int showunset) | ... | @@ -496,6 +498,176 @@ mu_debug_format_spec (mu_stream_t str, const char *names, int showunset) |
496 | return rc; | 498 | return rc; |
497 | } | 499 | } |
498 | 500 | ||
501 | |||
502 | /* Iterator */ | ||
503 | |||
504 | static mu_iterator_t iterator_head; | ||
505 | |||
506 | #define ITR_BACKWARDS 0x01 | ||
507 | #define ITR_SKIPUNSET 0x02 | ||
508 | #define ITR_FINISHED 0x04 | ||
509 | |||
510 | struct debug_iterator | ||
511 | { | ||
512 | size_t pos; | ||
513 | int flags; | ||
514 | }; | ||
515 | |||
516 | static int | ||
517 | first (void *owner) | ||
518 | { | ||
519 | struct debug_iterator *itr = owner; | ||
520 | itr->flags &= ~ITR_FINISHED; | ||
521 | if (itr->flags & ITR_BACKWARDS) | ||
522 | itr->pos = catcnt - 1; | ||
523 | else | ||
524 | itr->pos = 0; | ||
525 | return 0; | ||
526 | } | ||
527 | |||
528 | static int | ||
529 | next (void *owner) | ||
530 | { | ||
531 | struct debug_iterator *itr = owner; | ||
532 | itr->flags &= ~ITR_FINISHED; | ||
533 | do | ||
534 | { | ||
535 | if (itr->flags & ITR_BACKWARDS) | ||
536 | { | ||
537 | if (itr->pos) | ||
538 | itr->pos--; | ||
539 | else | ||
540 | itr->flags |= ITR_FINISHED; | ||
541 | } | ||
542 | else | ||
543 | { | ||
544 | if (itr->pos < catcnt - 1) | ||
545 | itr->pos++; | ||
546 | else | ||
547 | itr->flags |= ITR_FINISHED; | ||
548 | } | ||
549 | } | ||
550 | while ((itr->flags & ITR_SKIPUNSET) && | ||
551 | !(itr->flags & ITR_FINISHED) && | ||
552 | !cattab[itr->pos].isset); | ||
553 | |||
554 | return 0; | ||
555 | } | ||
556 | |||
557 | static int | ||
558 | getitem (void *owner, void **pret, const void **pkey) | ||
559 | { | ||
560 | struct debug_iterator *itr = owner; | ||
561 | *(mu_debug_level_t*) pret = cattab[itr->pos].level; | ||
562 | if (pkey) | ||
563 | *pkey = cattab[itr->pos].name; | ||
564 | return 0; | ||
565 | } | ||
566 | |||
567 | static int | ||
568 | finished_p (void *owner) | ||
569 | { | ||
570 | struct debug_iterator *itr = owner; | ||
571 | return itr->flags & ITR_FINISHED; | ||
572 | } | ||
573 | |||
574 | static int | ||
575 | curitem_p (void *owner, void *item) | ||
576 | { | ||
577 | struct debug_iterator *itr = owner; | ||
578 | return mu_c_strcasecmp (cattab[itr->pos].name, (char *) item) == 0; | ||
579 | } | ||
580 | |||
581 | static int | ||
582 | list_data_dup (void **ptr, void *owner) | ||
583 | { | ||
584 | *ptr = malloc (sizeof (struct debug_iterator)); | ||
585 | if (*ptr == NULL) | ||
586 | return ENOMEM; | ||
587 | memcpy (*ptr, owner, sizeof (struct debug_iterator)); | ||
588 | return 0; | ||
589 | } | ||
590 | |||
591 | static int | ||
592 | list_itrctl (void *owner, enum mu_itrctl_req req, void *arg) | ||
593 | { | ||
594 | struct debug_iterator *itr = owner; | ||
595 | |||
596 | switch (req) | ||
597 | { | ||
598 | case mu_itrctl_tell: | ||
599 | /* Return current position in the object */ | ||
600 | if (!arg) | ||
601 | return EINVAL; | ||
602 | *(size_t*)arg = itr->pos; | ||
603 | break; | ||
604 | |||
605 | case mu_itrctl_delete: | ||
606 | case mu_itrctl_delete_nd: | ||
607 | /* Delete current element */ | ||
608 | cattab[itr->pos].level = 0; | ||
609 | cattab[itr->pos].isset = 0; | ||
610 | break; | ||
611 | |||
612 | case mu_itrctl_replace: | ||
613 | case mu_itrctl_replace_nd: | ||
614 | if (!arg) | ||
615 | return EINVAL; | ||
616 | cattab[itr->pos].level = *(mu_debug_level_t*)arg; | ||
617 | break; | ||
618 | |||
619 | case mu_itrctl_qry_direction: | ||
620 | if (!arg) | ||
621 | return EINVAL; | ||
622 | else | ||
623 | *(int*)arg = itr->flags & ITR_BACKWARDS; | ||
624 | break; | ||
625 | |||
626 | case mu_itrctl_set_direction: | ||
627 | if (!arg) | ||
628 | return EINVAL; | ||
629 | else | ||
630 | itr->flags |= ITR_BACKWARDS; | ||
631 | break; | ||
632 | |||
633 | default: | ||
634 | return ENOSYS; | ||
635 | } | ||
636 | return 0; | ||
637 | } | ||
638 | |||
639 | int | ||
640 | mu_debug_get_iterator (mu_iterator_t *piterator, int skipunset) | ||
641 | { | ||
642 | int status; | ||
643 | mu_iterator_t iterator; | ||
644 | struct debug_iterator *itr; | ||
645 | |||
646 | itr = malloc (sizeof *itr); | ||
647 | if (!itr) | ||
648 | return ENOMEM; | ||
649 | itr->pos = 0; | ||
650 | itr->flags = skipunset ? ITR_SKIPUNSET : 0; | ||
651 | status = mu_iterator_create (&iterator, itr); | ||
652 | if (status) | ||
653 | { | ||
654 | free (itr); | ||
655 | return status; | ||
656 | } | ||
657 | |||
658 | mu_iterator_set_first (iterator, first); | ||
659 | mu_iterator_set_next (iterator, next); | ||
660 | mu_iterator_set_getitem (iterator, getitem); | ||
661 | mu_iterator_set_finished_p (iterator, finished_p); | ||
662 | mu_iterator_set_curitem_p (iterator, curitem_p); | ||
663 | mu_iterator_set_dup (iterator, list_data_dup); | ||
664 | mu_iterator_set_itrctl (iterator, list_itrctl); | ||
665 | |||
666 | mu_iterator_attach (&iterator_head, iterator); | ||
667 | |||
668 | *piterator = iterator; | ||
669 | return 0; | ||
670 | } | ||
499 | 671 | ||
500 | 672 | ||
501 | void | 673 | void | ... | ... |
... | @@ -24,6 +24,7 @@ lib_LTLIBRARIES=libmu_scm.la | ... | @@ -24,6 +24,7 @@ lib_LTLIBRARIES=libmu_scm.la |
24 | C_SRCS=\ | 24 | C_SRCS=\ |
25 | mu_address.c\ | 25 | mu_address.c\ |
26 | mu_body.c\ | 26 | mu_body.c\ |
27 | mu_debug.c\ | ||
27 | mu_dbgport.c\ | 28 | mu_dbgport.c\ |
28 | mu_guile.c\ | 29 | mu_guile.c\ |
29 | mu_mailbox.c\ | 30 | mu_mailbox.c\ | ... | ... |
libmu_scm/mu_debug.c
0 → 100644
1 | /* GNU Mailutils -- a suite of utilities for electronic mail | ||
2 | Copyright (C) 2011 Free Software Foundation, Inc. | ||
3 | |||
4 | This library is free software; you can redistribute it and/or | ||
5 | modify it under the terms of the GNU Lesser General Public | ||
6 | License as published by the Free Software Foundation; either | ||
7 | version 3 of the License, or (at your option) any later version. | ||
8 | |||
9 | This library is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
12 | Lesser General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU Lesser General | ||
15 | Public License along with this library. If not, see | ||
16 | <http://www.gnu.org/licenses/>. */ | ||
17 | |||
18 | #include "mu_scm.h" | ||
19 | #include <mailutils/iterator.h> | ||
20 | #include <mailutils/stdstream.h> | ||
21 | |||
22 | SCM_DEFINE_PUBLIC (scm_mu_debug_parse, "mu-debug-parse", 1, 0, 0, | ||
23 | (SCM spec), | ||
24 | "Parses @var{spec} and sets MU debugging level according to it.") | ||
25 | #define FUNC_NAME s_scm_mu_debug_parse | ||
26 | { | ||
27 | char *s; | ||
28 | |||
29 | SCM_ASSERT (scm_is_string (spec), spec, SCM_ARG1, FUNC_NAME); | ||
30 | s = scm_to_locale_string (spec); | ||
31 | mu_debug_parse_spec (s); | ||
32 | free (s); | ||
33 | return SCM_UNSPECIFIED; | ||
34 | } | ||
35 | #undef FUNC_NAME | ||
36 | |||
37 | static int | ||
38 | string_member_p (SCM list, SCM x) | ||
39 | { | ||
40 | return scm_member (x, list) != SCM_BOOL_F; | ||
41 | } | ||
42 | |||
43 | SCM_DEFINE_PUBLIC (scm_mu_debug_set, "mu-debug-set", 1, 0, 0, | ||
44 | (SCM catlist), | ||
45 | "Sets MU debug level according to @var{catlist}, which is a list of\n" | ||
46 | "conses: (cons category level)\n") | ||
47 | #define FUNC_NAME s_scm_mu_debug_set | ||
48 | { | ||
49 | SCM_ASSERT (scm_is_pair (catlist), catlist, SCM_ARG1, FUNC_NAME); | ||
50 | for (; !scm_is_null (catlist); catlist = SCM_CDR (catlist)) | ||
51 | { | ||
52 | SCM cell = SCM_CAR (catlist); | ||
53 | SCM x; | ||
54 | char *name; | ||
55 | mu_debug_level_t lev; | ||
56 | |||
57 | SCM_ASSERT (scm_is_pair (cell), cell, SCM_ARGn, FUNC_NAME); | ||
58 | x = scm_car (cell); | ||
59 | SCM_ASSERT (scm_is_string (x), x, SCM_ARGn, FUNC_NAME); | ||
60 | name = scm_to_locale_string (x); | ||
61 | x = scm_cdr (cell); | ||
62 | SCM_ASSERT (scm_is_integer (x), x, SCM_ARGn, FUNC_NAME); | ||
63 | lev = scm_to_int (x); | ||
64 | if (lev == 0) | ||
65 | mu_debug_disable_category (name, strlen (name)); | ||
66 | else | ||
67 | mu_debug_enable_category (name, strlen (name), lev); | ||
68 | free (name); | ||
69 | } | ||
70 | return SCM_UNSPECIFIED; | ||
71 | } | ||
72 | #undef FUNC_NAME | ||
73 | |||
74 | SCM_DEFINE_PUBLIC (scm_mu_debug_get, "mu-debug-get", 0, 2, 0, | ||
75 | (SCM catlist, SCM skipunset), | ||
76 | "Returns a list of MU debugging categories with corresponding levels.\n" | ||
77 | "If @var{catlist} is supplied, it is a list of category names. In this case\n" | ||
78 | "only categories from this list are returned") | ||
79 | #define FUNC_NAME s_scm_mu_debug_get | ||
80 | { | ||
81 | int skipunset_flag = 0; | ||
82 | mu_iterator_t itr; | ||
83 | SCM head = SCM_EOL, tail = SCM_EOL; | ||
84 | int (*member_p) (SCM list, SCM needle); | ||
85 | |||
86 | if (SCM_UNBNDP (catlist) || catlist == SCM_BOOL_F) | ||
87 | member_p = NULL; | ||
88 | else | ||
89 | { | ||
90 | SCM_ASSERT (scm_is_pair (catlist), catlist, SCM_ARG1, FUNC_NAME); | ||
91 | member_p = string_member_p; | ||
92 | } | ||
93 | |||
94 | if (!SCM_UNBNDP (skipunset)) | ||
95 | { | ||
96 | SCM_ASSERT (scm_is_bool (skipunset), skipunset, SCM_ARG2, FUNC_NAME); | ||
97 | skipunset_flag = skipunset == SCM_BOOL_T; | ||
98 | } | ||
99 | |||
100 | mu_debug_get_iterator (&itr, skipunset_flag); | ||
101 | for (mu_iterator_first (itr); !mu_iterator_is_done (itr); | ||
102 | mu_iterator_next (itr)) | ||
103 | { | ||
104 | const char *name; | ||
105 | mu_debug_level_t level; | ||
106 | SCM scm_name; | ||
107 | |||
108 | mu_iterator_current_kv (itr, (const void**) &name, (void**) &level); | ||
109 | scm_name = scm_from_locale_string (name); | ||
110 | if (!member_p || member_p (catlist, scm_name)) | ||
111 | { | ||
112 | SCM scm_new = scm_cons (scm_cons (scm_name, | ||
113 | scm_from_uintmax (level)), | ||
114 | SCM_EOL); | ||
115 | |||
116 | if (scm_is_null (head)) | ||
117 | head = tail = scm_new; | ||
118 | else | ||
119 | { | ||
120 | SCM_SETCDR (tail, scm_new); | ||
121 | tail = scm_new; | ||
122 | } | ||
123 | } | ||
124 | } | ||
125 | mu_iterator_destroy (&itr); | ||
126 | return head; | ||
127 | } | ||
128 | #undef FUNC_NAME | ||
129 | |||
130 | void | ||
131 | mu_scm_debug_init () | ||
132 | { | ||
133 | #include "mu_debug.x" | ||
134 | } |
... | @@ -128,7 +128,7 @@ SCM_DEFINE_PUBLIC (scm_mu_register_format, "mu-register-format", 0, 0, 1, | ... | @@ -128,7 +128,7 @@ SCM_DEFINE_PUBLIC (scm_mu_register_format, "mu-register-format", 0, 0, 1, |
128 | SCM_ASSERT (scm_is_string (scm), scm, SCM_ARGn, FUNC_NAME); | 128 | SCM_ASSERT (scm_is_string (scm), scm, SCM_ARGn, FUNC_NAME); |
129 | s = scm_to_locale_string (scm); | 129 | s = scm_to_locale_string (scm); |
130 | status = register_format (s); | 130 | status = register_format (s); |
131 | free (scm); | 131 | free (s); |
132 | if (status) | 132 | if (status) |
133 | mu_scm_error (FUNC_NAME, status, | 133 | mu_scm_error (FUNC_NAME, status, |
134 | "Cannot register format ~A", | 134 | "Cannot register format ~A", |
... | @@ -210,9 +210,10 @@ mu_scm_init () | ... | @@ -210,9 +210,10 @@ mu_scm_init () |
210 | mu_scm_port_init (); | 210 | mu_scm_port_init (); |
211 | mu_scm_mime_init (); | 211 | mu_scm_mime_init (); |
212 | mu_scm_debug_port_init (); | 212 | mu_scm_debug_port_init (); |
213 | mu_scm_debug_init (); | ||
213 | 214 | ||
214 | #include "mu_scm.x" | 215 | #include "mu_scm.x" |
215 | 216 | ||
216 | mu_registrar_record (MU_DEFAULT_RECORD); | 217 | mu_registrar_record (MU_DEFAULT_RECORD); |
217 | mu_registrar_set_default_record (MU_DEFAULT_RECORD); | 218 | mu_registrar_set_default_record (MU_DEFAULT_RECORD); |
218 | } | 219 | } | ... | ... |
-
Please register or sign in to post a comment