Commit 33d4f6f2 33d4f6f29fc6cf4da1fdf382d547061e65bd8f9f by Sergey Poznyakoff

*** empty log message ***

1 parent bbedfc8f
1 /* cfg_print.c -- convert configuration parse tree to human-readable format.
2 Copyright (C) 2007 Free Software Foundation, Inc.
3
4 GNU Mailutils is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License as
6 published by the Free Software Foundation; either version 3, or (at
7 your option) any later version.
8
9 This program is distributed in the hope that it will be useful, but
10 WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #ifdef HAVE_CONFIG_H
19 # include <config.h>
20 #endif
21 #include <mailutils/stream.h>
22 #include <mailutils/error.h>
23 #include <mailutils/cfg.h>
24 #include <mailutils/argcv.h>
25 #include <mailutils/nls.h>
26
27 struct tree_print
28 {
29 unsigned level;
30 mu_stream_t stream;
31 char *buf;
32 size_t bufsize;
33 };
34
35 static void
36 format_level (struct tree_print *tp)
37 {
38 int i;
39 for (i = 0; i < tp->level; i++)
40 mu_stream_sequential_write (tp->stream, " ", 2);
41 }
42
43 static void
44 format_label (struct tree_print *tp, const char *label)
45 {
46 size_t size;
47 int quote;
48 char *p;
49
50 size = mu_argcv_quoted_length (label, &quote);
51 if (quote)
52 size += 2;
53 size++;
54 if (size > tp->bufsize)
55 {
56 p = realloc (tp->buf, size);
57 if (!p)
58 {
59 mu_stream_sequential_printf (tp->stream, "%s\n",
60 _("ERROR: not enough memory"));
61 return;
62 }
63 tp->bufsize = size;
64 tp->buf = p;
65 }
66
67 p = tp->buf;
68 if (quote)
69 {
70 tp->buf[0] = '"';
71 tp->buf[size-2] = '"';
72 p++;
73 }
74 tp->buf[size-1] = 0;
75 mu_argcv_quote_copy (p, label);
76 mu_stream_sequential_write (tp->stream, tp->buf, size - 1);
77 }
78
79 static int
80 format_node (const mu_cfg_node_t *node, void *data)
81 {
82 struct tree_print *tp = data;
83
84 if (node->locus.file)
85 mu_stream_sequential_printf (tp->stream, "# %d \"%s\"\n",
86 node->locus.line, node->locus.file);
87 format_level (tp);
88 switch (node->type)
89 {
90 case mu_cfg_node_undefined:
91 mu_stream_sequential_printf (tp->stream, "%s",
92 _("ERROR: undefined statement"));
93 break;
94
95 case mu_cfg_node_tag:
96 {
97 mu_stream_sequential_write (tp->stream, node->tag_name,
98 strlen (node->tag_name));
99 if (node->tag_label)
100 {
101 mu_stream_sequential_write (tp->stream, " ", 1);
102 format_label (tp, node->tag_label);
103 }
104 mu_stream_sequential_write (tp->stream, " {", 2);
105 tp->level++;
106 }
107 break;
108
109 case mu_cfg_node_param:
110 mu_stream_sequential_write (tp->stream, node->tag_name,
111 strlen (node->tag_name));
112 if (node->tag_label)
113 {
114 mu_stream_sequential_write (tp->stream, " ", 1);
115 format_label (tp, node->tag_label);
116 mu_stream_sequential_write (tp->stream, ";", 1);
117 }
118 break;
119 }
120 mu_stream_sequential_write (tp->stream, "\n", 1);
121 return MU_CFG_ITER_OK;
122 }
123
124 static int
125 format_node_end (const mu_cfg_node_t *node, void *data)
126 {
127 struct tree_print *tp = data;
128 tp->level--;
129 format_level (tp);
130 mu_stream_sequential_write (tp->stream, "};\n", 3);
131 return MU_CFG_ITER_OK;
132 }
133
134 void
135 mu_cfg_format_tree (mu_stream_t stream, mu_cfg_tree_t *tree)
136 {
137 struct tree_print t;
138 t.level = 0;
139 t.stream = stream;
140 t.buf = NULL;
141 t.bufsize = 0;
142 mu_cfg_preorder (tree->node, format_node, format_node_end, &t);
143 free (t.buf);
144 }