1 /*
2 * Copyright (c) 2001, 2002, 2003, 2004, 2005 Netli, Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $Id: ncnf_dump.c,v 1.1 2005/05/26 12:08:19 vlm Exp $
27 */
28 #include "headers.h"
29 #include "ncnf_int.h"
30
31 static void
_print_indent(FILE * f,int indent)32 _print_indent(FILE *f, int indent) {
33 while(indent--)
34 fprintf(f, " ");
35 }
36
37 /*
38 * Process value and insert necessary escaping.
39 */
40 static void
_display_value(FILE * f,const char * value)41 _display_value(FILE *f, const char *value) {
42 int to_escape = 0;
43 const char *v;
44
45 for(v = value; *v; v++) {
46 switch(*v) {
47 default:
48 continue;
49 case '\\':
50 if(v != value)
51 continue;
52 case '"':
53 case '\n':
54 case '\v':
55 case '\f':
56 case '\r':
57 to_escape = 1;
58 }
59 break;
60 }
61
62 if(!to_escape) {
63 /* No escaping is necessary */
64 fwrite(value, v - value, 1, f);
65 return;
66 }
67
68 /* Print out the string, escaping certain characters */
69 for(v = value; *v; v++) {
70 switch(*v) {
71 case '\v': fputs("\\v", f); break;
72 case '\f': fputs("\\f", f); break;
73 case '\n': fputs("\\n", f); break;
74 case '\r': fputs("\\r", f); break;
75 case '"': fputs("\\\"", f); break;
76 case '\\': fputs("\\\\", f); break;
77 default:
78 if(v == value) {
79 fputc('\\', f);
80 if(v[0] != ' '
81 && v[0] != '\n'
82 && v[0] != '\r'
83 && v[0] != '\t'
84 ) fputc('\n', f);
85 }
86 fputc(*v, f);
87 }
88 }
89
90 }
91
92 void
_ncnf_obj_dump_recursive(FILE * f,struct ncnf_obj_s * obj,const char * flatten_type,int marked_only,int verbose,int indent,int indent_shift,int single_level,int * ret_rsize)93 _ncnf_obj_dump_recursive(FILE *f, struct ncnf_obj_s *obj,
94 const char *flatten_type, int marked_only,
95 int verbose, int indent, int indent_shift, int single_level,
96 int *ret_rsize
97 ) {
98 int cc;
99 int recursive_size = sizeof(*obj);
100
101 assert(obj->obj_class != NOBJ_INVALID);
102
103 if(marked_only && !obj->mark) /* Skip unmarked entries */
104 return;
105
106 if(obj->obj_class != NOBJ_ROOT)
107 _print_indent(f, indent);
108
109 if(flatten_type) indent_shift = 0;
110
111 if(!flatten_type)
112 switch(obj->obj_class) {
113 case NOBJ_COMPLEX:
114 if(single_level) {
115 fprintf(f, "%s %s { ... }", obj->type, obj->value);
116 } else {
117 fprintf(f, "%s \"%s\" {", obj->type, obj->value);
118 }
119 if(verbose)
120 fprintf(f, "\t# line %d <%d> <%p>",
121 obj->config_line,
122 obj->obj_class,
123 obj
124 );
125 fputs("\n", f);
126 break;
127 case NOBJ_ATTRIBUTE:
128 if(single_level) {
129 fprintf(f, "%s\t", obj->type);
130 _display_value(f, obj->value);
131 } else {
132 fprintf(f, "%s \"", obj->type);
133 _display_value(f, obj->value);
134 fprintf(f, "\";");
135 }
136 if(verbose)
137 fprintf(f,
138 "\t# line %d\t<%d>",
139 obj->config_line,
140 obj->obj_class
141 );
142 fputs("\n", f);
143 break;
144 case NOBJ_REFERENCE:
145 if(single_level) {
146 fprintf(f, "%s %s => %s %s { ... }",
147 obj->type, obj->value,
148 obj->m_ref_type, obj->m_ref_value
149 );
150 } else {
151 fprintf(f, "%s %s \"%s\" = %s \"%s\";",
152 (obj->m_ref_flags & 1) ? "attach" : "ref",
153 obj->type, obj->value,
154 obj->m_ref_type, obj->m_ref_value
155 );
156 }
157 if(verbose)
158 fprintf(f,
159 "\t# line %d <%p>-><%p>",
160 obj->config_line,
161 obj,
162 _ncnf_real_object(obj)
163 );
164 fputs("\n", f);
165 break;
166 default:
167 /* Do nothing */
168 break;
169 }
170
171 if(!single_level)
172 switch(obj->obj_class) {
173 case NOBJ_ROOT:
174 case NOBJ_COMPLEX:
175
176 /* Count the overhead for collections */
177 for(cc = 0; cc < MAX_COLLECTIONS; cc++) {
178 collection_t *coll = &obj->m_collection[cc];
179 int i;
180
181 /* Count the overhead */
182 recursive_size += coll->size * sizeof(coll->entry[0]);
183
184 for(i = 0; i < coll->entries; i++) {
185 struct ncnf_obj_s *child=coll->entry[i].object;
186
187 if(flatten_type
188 && *flatten_type != '-'
189 && *flatten_type != '*'
190 && strcmp(flatten_type, child->type)
191 ) continue;
192
193 _ncnf_obj_dump_recursive(f, child, 0,
194 marked_only,
195 verbose,
196 indent + (obj->type?indent_shift:0),
197 indent_shift, flatten_type ? 1 : 0,
198 &recursive_size);
199 }
200
201 /* Put some space between entries */
202 if(obj->m_collection[cc].entries
203 && obj->m_collection[cc + 1].entries
204 && !flatten_type)
205 fprintf(f, "\n");
206 }
207
208 default:
209 /* Do nothing */
210 break;
211 }
212
213 if(obj->obj_class == NOBJ_COMPLEX && !flatten_type && !single_level) {
214 _print_indent(f, indent);
215 fputs("}", f);
216
217 if(verbose) {
218 fprintf(f, " # %s \"%s\" RSIZE=%d",
219 obj->type, obj->value,
220 recursive_size
221 );
222 }
223
224 fputs(indent?"\n":"\n\n", f);
225 }
226
227 if(ret_rsize) *ret_rsize += recursive_size;
228 }
229
230