Commit 45d49848 45d49848cd34a99cc326be9997a4b5d7142898fe by Sergey Poznyakoff

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.
1 parent d9044ffe
...@@ -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\
......
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 }
......