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