ConfCmp.c revision 285830
1275970Scy/*-
2275970Scy * Copyright (c) 2002 Poul-Henning Kamp
3275970Scy * Copyright (c) 2002 Networks Associates Technology, Inc.
4275970Scy * All rights reserved.
5275970Scy *
6275970Scy * This software was developed for the FreeBSD Project by Poul-Henning Kamp
7275970Scy * and NAI Labs, the Security Research Division of Network Associates, Inc.
8275970Scy * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the
9275970Scy * DARPA CHATS research program.
10275970Scy *
11275970Scy * Redistribution and use in source and binary forms, with or without
12275970Scy * modification, are permitted provided that the following conditions
13275970Scy * are met:
14275970Scy * 1. Redistributions of source code must retain the above copyright
15275970Scy *    notice, this list of conditions and the following disclaimer.
16275970Scy * 2. Redistributions in binary form must reproduce the above copyright
17275970Scy *    notice, this list of conditions and the following disclaimer in the
18275970Scy *    documentation and/or other materials provided with the distribution.
19275970Scy * 3. The names of the authors may not be used to endorse or promote
20275970Scy *    products derived from this software without specific prior written
21275970Scy *    permission.
22275970Scy *
23275970Scy * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
24275970Scy * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25275970Scy * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26275970Scy * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
27275970Scy * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28275970Scy * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29275970Scy * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30275970Scy * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31275970Scy * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32275970Scy * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33275970Scy * SUCH DAMAGE.
34275970Scy *
35275970Scy * $FreeBSD: releng/10.2/tools/regression/geom/ConfCmp/ConfCmp.c 201145 2009-12-28 22:56:30Z antoine $
36275970Scy */
37275970Scy
38275970Scy#include <stdio.h>
39275970Scy#include <stdlib.h>
40275970Scy#include <string.h>
41275970Scy#include <unistd.h>
42275970Scy#include <fcntl.h>
43275970Scy#include <ctype.h>
44275970Scy#include <sys/stat.h>
45275970Scy#include <sys/mman.h>
46275970Scy#include <sys/queue.h>
47275970Scy#include <sys/sbuf.h>
48275970Scy#include <err.h>
49275970Scy#include <bsdxml.h>
50275970Scy
51275970ScyFILE *fsubs;
52275970Scy
53275970Scystruct node {
54275970Scy	LIST_HEAD(, node)	children;
55275970Scy	LIST_ENTRY(node)	siblings;
56275970Scy	struct node		*parent;
57275970Scy	const char		*name;
58275970Scy	struct sbuf		*cont;
59285612Sdelphij	struct sbuf		*key;
60275970Scy	char			*id;
61275970Scy	char			*ref;
62275970Scy};
63275970Scy
64275970Scystruct mytree {
65275970Scy	struct node		*top;
66275970Scy	struct node		*cur;
67275970Scy	int			indent;
68275970Scy	int			ignore;
69275970Scy};
70275970Scy
71275970Scystruct ref {
72275970Scy	LIST_ENTRY(ref)		next;
73275970Scy	char 			*k1;
74275970Scy	char			*k2;
75275970Scy};
76275970Scy
77275970ScyLIST_HEAD(, ref)		refs = LIST_HEAD_INITIALIZER(refs);
78275970Scy
79275970Scystatic struct node *
80275970Scynew_node(void)
81275970Scy{
82275970Scy	struct node *np;
83275970Scy
84275970Scy	np = calloc(1, sizeof *np);
85275970Scy	np->cont = sbuf_new_auto();
86275970Scy	sbuf_clear(np->cont);
87275970Scy	np->key = sbuf_new_auto();
88275970Scy	sbuf_clear(np->key);
89275970Scy	LIST_INIT(&np->children);
90275970Scy	return (np);
91275970Scy}
92275970Scy
93275970Scystatic void
94275970Scyindent(int n)
95275970Scy{
96275970Scy
97275970Scy	printf("%*.*s", n, n, "");
98275970Scy}
99285612Sdelphij
100275970Scystatic void
101275970ScyStartElement(void *userData, const char *name, const char **attr)
102275970Scy{
103275970Scy	struct mytree *mt;
104275970Scy	struct node *np;
105275970Scy	int i;
106275970Scy
107275970Scy	mt = userData;
108285612Sdelphij	if (!strcmp(name, "FreeBSD")) {
109275970Scy		mt->ignore = 1;
110275970Scy		return;
111275970Scy	}
112275970Scy	mt->ignore = 0;
113275970Scy	mt->indent += 2;
114275970Scy	np = new_node();
115275970Scy	for (i = 0; attr[i]; i += 2) {
116275970Scy		if (!strcmp(attr[i], "id"))
117275970Scy			np->id = strdup(attr[i+1]);
118275970Scy		else if (!strcmp(attr[i], "ref"))
119275970Scy			np->ref = strdup(attr[i+1]);
120275970Scy	}
121275970Scy	np->name = strdup(name);
122275970Scy	sbuf_cat(np->key, name);
123275970Scy	sbuf_cat(np->key, "::");
124275970Scy	np->parent = mt->cur;
125275970Scy	LIST_INSERT_HEAD(&mt->cur->children, np, siblings);
126275970Scy	mt->cur = np;
127275970Scy}
128275970Scy
129275970Scystatic void
130275970ScyEndElement(void *userData, const char *name __unused)
131275970Scy{
132275970Scy	struct mytree *mt;
133275970Scy	struct node *np;
134275970Scy
135275970Scy	mt = userData;
136275970Scy	if (mt->ignore)
137275970Scy		return;
138275970Scy
139275970Scy	mt->indent -= 2;
140275970Scy	sbuf_finish(mt->cur->cont);
141275970Scy	LIST_FOREACH(np, &mt->cur->children, siblings) {
142275970Scy		if (strcmp(np->name, "name"))
143275970Scy			continue;
144275970Scy		sbuf_cat(mt->cur->key, sbuf_data(np->cont));
145275970Scy		break;
146275970Scy	}
147275970Scy	sbuf_finish(mt->cur->key);
148275970Scy	mt->cur = mt->cur->parent;
149275970Scy}
150275970Scy
151275970Scystatic void
152275970ScyCharData(void *userData , const XML_Char *s , int len)
153275970Scy{
154275970Scy	struct mytree *mt;
155275970Scy	const char *b, *e;
156275970Scy
157275970Scy	mt = userData;
158275970Scy	if (mt->ignore)
159275970Scy		return;
160275970Scy	b = s;
161275970Scy	e = s + len - 1;
162275970Scy	while (isspace(*b) && b < e)
163275970Scy		b++;
164275970Scy	while (isspace(*e) && e > b)
165275970Scy		e--;
166275970Scy	if (e != b || *b)
167275970Scy		sbuf_bcat(mt->cur->cont, b, e - b + 1);
168275970Scy}
169275970Scy
170275970Scystatic struct mytree *
171275970Scydofile(char *filename)
172275970Scy{
173275970Scy	XML_Parser parser;
174275970Scy	struct mytree *mt;
175275970Scy	struct stat st;
176275970Scy	int fd;
177275970Scy	char *p;
178275970Scy	int i;
179275970Scy
180275970Scy	parser = XML_ParserCreate(NULL);
181275970Scy	mt = calloc(1, sizeof *mt);
182275970Scy	mt->top = new_node();
183275970Scy	mt->top->name = "(top)";
184275970Scy	mt->top->parent = mt->top;
185275970Scy	mt->cur = mt->top;
186275970Scy	sbuf_finish(mt->top->key);
187275970Scy	sbuf_finish(mt->top->cont);
188275970Scy	XML_SetUserData(parser, mt);
189275970Scy	XML_SetElementHandler(parser, StartElement, EndElement);
190275970Scy	XML_SetCharacterDataHandler(parser, CharData);
191275970Scy	fd = open(filename, O_RDONLY);
192275970Scy	if (fd < 0)
193275970Scy		err(1, filename);
194275970Scy	fstat(fd, &st);
195275970Scy	p = mmap(NULL, st.st_size, PROT_READ, MAP_NOCORE|MAP_PRIVATE, fd, 0);
196275970Scy	i = XML_Parse(parser, p, st.st_size, 1);
197275970Scy	if (i != 1)
198275970Scy		errx(1, "XML_Parse complained -> %d", i);
199275970Scy	munmap(p, st.st_size);
200275970Scy	close(fd);
201275970Scy	XML_ParserFree(parser);
202275970Scy	sbuf_finish(mt->top->cont);
203275970Scy	if (i)
204275970Scy		return (mt);
205275970Scy	else
206275970Scy		return (NULL);
207275970Scy}
208275970Scy
209275970Scystatic void
210275970Scyprint_node(struct node *np)
211275970Scy{
212275970Scy	printf("\"%s\" -- \"%s\" -- \"%s\"", np->name, sbuf_data(np->cont), sbuf_data(np->key));
213275970Scy	if (np->id)
214275970Scy		printf(" id=\"%s\"", np->id);
215275970Scy	if (np->ref)
216275970Scy		printf(" ref=\"%s\"", np->ref);
217275970Scy	printf("\n");
218275970Scy}
219275970Scy
220275970Scystatic void
221275970Scyprint_tree(struct node *np, int n)
222275970Scy{
223275970Scy	struct node *np1;
224275970Scy
225275970Scy	indent(n); printf("%s id=%s ref=%s\n", np->name, np->id, np->ref);
226275970Scy	LIST_FOREACH(np1, &np->children, siblings)
227275970Scy		print_tree(np1, n + 2);
228275970Scy}
229275970Scy
230275970Scystatic void
231275970Scysort_node(struct node *np)
232275970Scy{
233275970Scy	struct node *np1, *np2;
234275970Scy	int n;
235275970Scy
236275970Scy	LIST_FOREACH(np1, &np->children, siblings)
237275970Scy		sort_node(np1);
238275970Scy	do {
239275970Scy		np1 = LIST_FIRST(&np->children);
240275970Scy		n = 0;
241275970Scy		for (;;) {
242275970Scy			if (np1 == NULL)
243275970Scy				return;
244275970Scy			np2 = LIST_NEXT(np1, siblings);
245275970Scy			if (np2 == NULL)
246275970Scy				return;
247275970Scy			if (strcmp(sbuf_data(np1->key), sbuf_data(np2->key)) > 0) {
248275970Scy				LIST_REMOVE(np2, siblings);
249275970Scy				LIST_INSERT_BEFORE(np1, np2, siblings);
250275970Scy				n++;
251275970Scy				break;
252275970Scy			}
253275970Scy			np1 = np2;
254275970Scy		}
255275970Scy	} while (n);
256275970Scy}
257275970Scy
258275970Scystatic int
259275970Scyrefcmp(char *r1, char *r2)
260275970Scy{
261275970Scy	struct ref *r;
262275970Scy
263275970Scy	LIST_FOREACH(r, &refs, next) {
264275970Scy		if (!strcmp(r1, r->k1))
265275970Scy			return (strcmp(r2, r->k2));
266275970Scy	}
267275970Scy	r = calloc(1, sizeof(*r));
268275970Scy	r->k1 = strdup(r1);
269275970Scy	r->k2 = strdup(r2);
270275970Scy	LIST_INSERT_HEAD(&refs, r, next);
271275970Scy	if (fsubs != NULL) {
272275970Scy		fprintf(fsubs, "s/%s/%s/g\n", r1, r2);
273275970Scy		fflush(fsubs);
274275970Scy	}
275275970Scy	return (0);
276275970Scy}
277275970Scy
278275970Scystatic int compare_node2(struct node *n1, struct node *n2, int in);
279275970Scy
280275970Scystatic int
281285612Sdelphijcompare_node(struct node *n1, struct node *n2, int in)
282275970Scy{
283275970Scy	int i;
284275970Scy	struct node *n1a, *n2a;
285275970Scy
286275970Scy	i = strcmp(n1->name, n2->name);
287275970Scy	if (i)
288275970Scy		return (i);
289275970Scy	if (n1->id && n2->id)
290275970Scy		i = refcmp(n1->id, n2->id);
291275970Scy	else if (n1->id || n2->id)
292275970Scy		i = -1;
293275970Scy	if (i)
294275970Scy		return (i);
295275970Scy	if (n1->ref && n2->ref)
296275970Scy		i = refcmp(n1->ref, n2->ref);
297275970Scy	else if (n1->ref || n2->ref)
298275970Scy		i = -1;
299285612Sdelphij	if (i)
300285612Sdelphij		return (i);
301275970Scy	if (!strcmp(n1->name, "ref"))
302285612Sdelphij		i = refcmp(sbuf_data(n1->cont), sbuf_data(n2->cont));
303285612Sdelphij	else
304275970Scy		i = strcmp(sbuf_data(n1->cont), sbuf_data(n2->cont));
305275970Scy	if (i)
306275970Scy		return (1);
307275970Scy	n1a = LIST_FIRST(&n1->children);
308285612Sdelphij	n2a = LIST_FIRST(&n2->children);
309275970Scy	for (;;) {
310285612Sdelphij		if (n1a == NULL && n2a == NULL)
311275970Scy			return (0);
312275970Scy		if (n1a != NULL && n2a == NULL) {
313275970Scy			printf("1>");
314275970Scy			indent(in);
315275970Scy			print_node(n1a);
316275970Scy			printf("2>\n");
317275970Scy			return (1);
318275970Scy		}
319275970Scy		if (n1a == NULL && n2a != NULL) {
320275970Scy			printf("1>\n");
321275970Scy			printf("2>");
322275970Scy			indent(in);
323275970Scy			print_node(n2a);
324275970Scy			return (1);
325275970Scy		}
326275970Scy		i = compare_node2(n1a, n2a, in + 2);
327275970Scy		if (i)
328275970Scy			return (1);
329275970Scy		n1a = LIST_NEXT(n1a, siblings);
330275970Scy		n2a = LIST_NEXT(n2a, siblings);
331275970Scy	}
332275970Scy	return (0);
333275970Scy}
334275970Scy
335275970Scystatic int
336275970Scycompare_node2(struct node *n1, struct node *n2, int in)
337275970Scy{
338275970Scy	int i;
339275970Scy
340275970Scy	i = compare_node(n1, n2, in);
341275970Scy	if (i) {
342275970Scy		printf("1>");
343275970Scy		indent(in);
344275970Scy		print_node(n1);
345275970Scy		printf("2>");
346275970Scy		indent(in);
347275970Scy		print_node(n2);
348275970Scy	}
349	return (i);
350}
351
352
353
354int
355main(int argc, char **argv)
356{
357	struct mytree *t1, *t2;
358	int i;
359
360	fsubs = fopen("_.subs", "w");
361	setbuf(stdout, NULL);
362	setbuf(stderr, NULL);
363	if (argc != 3)
364		errx(1, "usage: %s file1 file2", argv[0]);
365
366	t1 = dofile(argv[1]);
367	if (t1 == NULL)
368		errx(2, "XML parser error on file %s", argv[1]);
369	sort_node(t1->top);
370	t2 = dofile(argv[2]);
371	if (t2 == NULL)
372		errx(2, "XML parser error on file %s", argv[2]);
373	sort_node(t2->top);
374	i = compare_node(t1->top, t2->top, 0);
375	return (i);
376}
377
378