xref: /freebsd/tools/regression/geom/ConfCmp/ConfCmp.c (revision 31304807c110eaaa179ed7d59bc8606a8f9a34dc)
131304807SPoul-Henning Kamp /*-
231304807SPoul-Henning Kamp  * Copyright (c) 2002 Poul-Henning Kamp
331304807SPoul-Henning Kamp  * Copyright (c) 2002 Networks Associates Technology, Inc.
431304807SPoul-Henning Kamp  * All rights reserved.
531304807SPoul-Henning Kamp  *
631304807SPoul-Henning Kamp  * This software was developed for the FreeBSD Project by Poul-Henning Kamp
731304807SPoul-Henning Kamp  * and NAI Labs, the Security Research Division of Network Associates, Inc.
831304807SPoul-Henning Kamp  * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the
931304807SPoul-Henning Kamp  * DARPA CHATS research program.
1031304807SPoul-Henning Kamp  *
1131304807SPoul-Henning Kamp  * Redistribution and use in source and binary forms, with or without
1231304807SPoul-Henning Kamp  * modification, are permitted provided that the following conditions
1331304807SPoul-Henning Kamp  * are met:
1431304807SPoul-Henning Kamp  * 1. Redistributions of source code must retain the above copyright
1531304807SPoul-Henning Kamp  *    notice, this list of conditions and the following disclaimer.
1631304807SPoul-Henning Kamp  * 2. Redistributions in binary form must reproduce the above copyright
1731304807SPoul-Henning Kamp  *    notice, this list of conditions and the following disclaimer in the
1831304807SPoul-Henning Kamp  *    documentation and/or other materials provided with the distribution.
1931304807SPoul-Henning Kamp  * 3. The names of the authors may not be used to endorse or promote
2031304807SPoul-Henning Kamp  *    products derived from this software without specific prior written
2131304807SPoul-Henning Kamp  *    permission.
2231304807SPoul-Henning Kamp  *
2331304807SPoul-Henning Kamp  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
2431304807SPoul-Henning Kamp  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2531304807SPoul-Henning Kamp  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2631304807SPoul-Henning Kamp  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2731304807SPoul-Henning Kamp  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2831304807SPoul-Henning Kamp  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2931304807SPoul-Henning Kamp  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3031304807SPoul-Henning Kamp  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3131304807SPoul-Henning Kamp  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3231304807SPoul-Henning Kamp  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3331304807SPoul-Henning Kamp  * SUCH DAMAGE.
3431304807SPoul-Henning Kamp  *
3531304807SPoul-Henning Kamp  * $FreeBSD$
3631304807SPoul-Henning Kamp  */
3731304807SPoul-Henning Kamp 
3831304807SPoul-Henning Kamp #include <stdio.h>
3931304807SPoul-Henning Kamp #include <stdlib.h>
4031304807SPoul-Henning Kamp #include <string.h>
4131304807SPoul-Henning Kamp #include <unistd.h>
4231304807SPoul-Henning Kamp #include <fcntl.h>
4331304807SPoul-Henning Kamp #include <ctype.h>
4431304807SPoul-Henning Kamp #include <sys/stat.h>
4531304807SPoul-Henning Kamp #include <sys/mman.h>
4631304807SPoul-Henning Kamp #include <sys/queue.h>
4731304807SPoul-Henning Kamp #include <sys/sbuf.h>
4831304807SPoul-Henning Kamp #include <err.h>
4931304807SPoul-Henning Kamp #include "xmlparse.h"
5031304807SPoul-Henning Kamp 
5131304807SPoul-Henning Kamp struct node {
5231304807SPoul-Henning Kamp 	LIST_HEAD(, node)	children;
5331304807SPoul-Henning Kamp 	LIST_ENTRY(node)	siblings;
5431304807SPoul-Henning Kamp 	struct node		*parent;
5531304807SPoul-Henning Kamp 	char			*name;
5631304807SPoul-Henning Kamp 	struct sbuf		*cont;
5731304807SPoul-Henning Kamp 	struct sbuf		*key;
5831304807SPoul-Henning Kamp };
5931304807SPoul-Henning Kamp 
6031304807SPoul-Henning Kamp struct mytree {
6131304807SPoul-Henning Kamp 	struct node		*top;
6231304807SPoul-Henning Kamp 	struct node		*cur;
6331304807SPoul-Henning Kamp 	int			indent;
6431304807SPoul-Henning Kamp };
6531304807SPoul-Henning Kamp 
6631304807SPoul-Henning Kamp struct ref {
6731304807SPoul-Henning Kamp 	LIST_ENTRY(ref)		next;
6831304807SPoul-Henning Kamp 	char 			*k1;
6931304807SPoul-Henning Kamp 	char			*k2;
7031304807SPoul-Henning Kamp };
7131304807SPoul-Henning Kamp 
7231304807SPoul-Henning Kamp LIST_HEAD(, ref)		refs = LIST_HEAD_INITIALIZER(&refs);
7331304807SPoul-Henning Kamp 
7431304807SPoul-Henning Kamp static struct node *
7531304807SPoul-Henning Kamp new_node(void)
7631304807SPoul-Henning Kamp {
7731304807SPoul-Henning Kamp 	struct node *np;
7831304807SPoul-Henning Kamp 
7931304807SPoul-Henning Kamp 	np = calloc(1, sizeof *np);
8031304807SPoul-Henning Kamp 	np->cont = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND);
8131304807SPoul-Henning Kamp 	sbuf_clear(np->cont);
8231304807SPoul-Henning Kamp 	np->key = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND);
8331304807SPoul-Henning Kamp 	sbuf_clear(np->key);
8431304807SPoul-Henning Kamp 	LIST_INIT(&np->children);
8531304807SPoul-Henning Kamp 	return (np);
8631304807SPoul-Henning Kamp }
8731304807SPoul-Henning Kamp 
8831304807SPoul-Henning Kamp static void
8931304807SPoul-Henning Kamp indent(int n)
9031304807SPoul-Henning Kamp {
9131304807SPoul-Henning Kamp 
9231304807SPoul-Henning Kamp 	printf("%*.*s", n, n, "");
9331304807SPoul-Henning Kamp }
9431304807SPoul-Henning Kamp 
9531304807SPoul-Henning Kamp static void
9631304807SPoul-Henning Kamp StartElement(void *userData, const char *name, const char **atts __unused)
9731304807SPoul-Henning Kamp {
9831304807SPoul-Henning Kamp 	struct mytree *mt;
9931304807SPoul-Henning Kamp 	struct node *np;
10031304807SPoul-Henning Kamp 
10131304807SPoul-Henning Kamp 	mt = userData;
10231304807SPoul-Henning Kamp 	mt->indent += 2;
10331304807SPoul-Henning Kamp 	np = new_node();
10431304807SPoul-Henning Kamp 	np->name = strdup(name);
10531304807SPoul-Henning Kamp 	sbuf_cat(np->key, name);
10631304807SPoul-Henning Kamp 	sbuf_cat(np->key, "::");
10731304807SPoul-Henning Kamp 	np->parent = mt->cur;
10831304807SPoul-Henning Kamp 	LIST_INSERT_HEAD(&mt->cur->children, np, siblings);
10931304807SPoul-Henning Kamp 	mt->cur = np;
11031304807SPoul-Henning Kamp }
11131304807SPoul-Henning Kamp 
11231304807SPoul-Henning Kamp static void
11331304807SPoul-Henning Kamp EndElement(void *userData, const char *name __unused)
11431304807SPoul-Henning Kamp {
11531304807SPoul-Henning Kamp 	struct mytree *mt;
11631304807SPoul-Henning Kamp 	struct node *np;
11731304807SPoul-Henning Kamp 
11831304807SPoul-Henning Kamp 	mt = userData;
11931304807SPoul-Henning Kamp 
12031304807SPoul-Henning Kamp 	mt->indent -= 2;
12131304807SPoul-Henning Kamp 	sbuf_finish(mt->cur->cont);
12231304807SPoul-Henning Kamp 	LIST_FOREACH(np, &mt->cur->children, siblings) {
12331304807SPoul-Henning Kamp 		if (strcmp(np->name, "name"))
12431304807SPoul-Henning Kamp 			continue;
12531304807SPoul-Henning Kamp 		sbuf_cat(mt->cur->key, sbuf_data(np->cont));
12631304807SPoul-Henning Kamp 		break;
12731304807SPoul-Henning Kamp 	}
12831304807SPoul-Henning Kamp 	sbuf_finish(mt->cur->key);
12931304807SPoul-Henning Kamp 	mt->cur = mt->cur->parent;
13031304807SPoul-Henning Kamp }
13131304807SPoul-Henning Kamp 
13231304807SPoul-Henning Kamp static void
13331304807SPoul-Henning Kamp CharData(void *userData , const XML_Char *s , int len)
13431304807SPoul-Henning Kamp {
13531304807SPoul-Henning Kamp 	struct mytree *mt;
13631304807SPoul-Henning Kamp 	const char *b, *e;
13731304807SPoul-Henning Kamp 
13831304807SPoul-Henning Kamp 	mt = userData;
13931304807SPoul-Henning Kamp 	b = s;
14031304807SPoul-Henning Kamp 	e = s + len - 1;
14131304807SPoul-Henning Kamp 	while (isspace(*b) && b < e)
14231304807SPoul-Henning Kamp 		b++;
14331304807SPoul-Henning Kamp 	while (isspace(*e) && e > b)
14431304807SPoul-Henning Kamp 		e--;
14531304807SPoul-Henning Kamp 	if (e != b)
14631304807SPoul-Henning Kamp 		sbuf_bcat(mt->cur->cont, b, e - b + 1);
14731304807SPoul-Henning Kamp }
14831304807SPoul-Henning Kamp 
14931304807SPoul-Henning Kamp static struct mytree *
15031304807SPoul-Henning Kamp dofile(char *filename)
15131304807SPoul-Henning Kamp {
15231304807SPoul-Henning Kamp 	XML_Parser parser;
15331304807SPoul-Henning Kamp 	struct mytree *mt;
15431304807SPoul-Henning Kamp 	struct stat st;
15531304807SPoul-Henning Kamp 	int fd;
15631304807SPoul-Henning Kamp 	char *p;
15731304807SPoul-Henning Kamp 	int i;
15831304807SPoul-Henning Kamp 
15931304807SPoul-Henning Kamp 	parser = XML_ParserCreate(NULL);
16031304807SPoul-Henning Kamp 	mt = calloc(1, sizeof *mt);
16131304807SPoul-Henning Kamp 	mt->top = new_node();
16231304807SPoul-Henning Kamp 	mt->top->name = "(top)";
16331304807SPoul-Henning Kamp 	mt->top->parent = mt->top;
16431304807SPoul-Henning Kamp 	mt->cur = mt->top;
16531304807SPoul-Henning Kamp 	sbuf_finish(mt->top->key);
16631304807SPoul-Henning Kamp 	sbuf_finish(mt->top->cont);
16731304807SPoul-Henning Kamp 	XML_SetUserData(parser, mt);
16831304807SPoul-Henning Kamp 	XML_SetElementHandler(parser, StartElement, EndElement);
16931304807SPoul-Henning Kamp 	XML_SetCharacterDataHandler(parser, CharData);
17031304807SPoul-Henning Kamp 	fd = open(filename, O_RDONLY);
17131304807SPoul-Henning Kamp 	if (fd < 0)
17231304807SPoul-Henning Kamp 		err(1, filename);
17331304807SPoul-Henning Kamp 	fstat(fd, &st);
17431304807SPoul-Henning Kamp 	p = mmap(NULL, st.st_size, PROT_READ, MAP_NOCORE|MAP_PRIVATE, fd, 0);
17531304807SPoul-Henning Kamp 	i = XML_Parse(parser, p, st.st_size, 1);
17631304807SPoul-Henning Kamp 	munmap(p, st.st_size);
17731304807SPoul-Henning Kamp 	close(fd);
17831304807SPoul-Henning Kamp 	XML_ParserFree(parser);
17931304807SPoul-Henning Kamp 	sbuf_finish(mt->top->cont);
18031304807SPoul-Henning Kamp 	if (i)
18131304807SPoul-Henning Kamp 		return (mt);
18231304807SPoul-Henning Kamp 	else
18331304807SPoul-Henning Kamp 		return (NULL);
18431304807SPoul-Henning Kamp }
18531304807SPoul-Henning Kamp 
18631304807SPoul-Henning Kamp static void
18731304807SPoul-Henning Kamp print_node(struct node *np)
18831304807SPoul-Henning Kamp {
18931304807SPoul-Henning Kamp 	printf("\"%s\" -- \"%s\" -- \"%s\"\n", np->name, sbuf_data(np->cont), sbuf_data(np->key));
19031304807SPoul-Henning Kamp }
19131304807SPoul-Henning Kamp 
19231304807SPoul-Henning Kamp static void
19331304807SPoul-Henning Kamp sort_node(struct node *np)
19431304807SPoul-Henning Kamp {
19531304807SPoul-Henning Kamp 	struct node *np1, *np2;
19631304807SPoul-Henning Kamp 	int n;
19731304807SPoul-Henning Kamp 
19831304807SPoul-Henning Kamp 	LIST_FOREACH(np1, &np->children, siblings)
19931304807SPoul-Henning Kamp 		sort_node(np1);
20031304807SPoul-Henning Kamp 	do {
20131304807SPoul-Henning Kamp 		np1 = LIST_FIRST(&np->children);
20231304807SPoul-Henning Kamp 		n = 0;
20331304807SPoul-Henning Kamp 		for (;;) {
20431304807SPoul-Henning Kamp 			if (np1 == NULL)
20531304807SPoul-Henning Kamp 				return;
20631304807SPoul-Henning Kamp 			np2 = LIST_NEXT(np1, siblings);
20731304807SPoul-Henning Kamp 			if (np2 == NULL)
20831304807SPoul-Henning Kamp 				return;
20931304807SPoul-Henning Kamp 			if (strcmp(sbuf_data(np1->key), sbuf_data(np2->key)) > 0) {
21031304807SPoul-Henning Kamp 				LIST_REMOVE(np2, siblings);
21131304807SPoul-Henning Kamp 				LIST_INSERT_BEFORE(np1, np2, siblings);
21231304807SPoul-Henning Kamp 				n++;
21331304807SPoul-Henning Kamp 				break;
21431304807SPoul-Henning Kamp 			}
21531304807SPoul-Henning Kamp 			np1 = np2;
21631304807SPoul-Henning Kamp 		}
21731304807SPoul-Henning Kamp 	} while (n);
21831304807SPoul-Henning Kamp }
21931304807SPoul-Henning Kamp 
22031304807SPoul-Henning Kamp static int
22131304807SPoul-Henning Kamp refcmp(char *r1, char *r2)
22231304807SPoul-Henning Kamp {
22331304807SPoul-Henning Kamp 	struct ref *r;
22431304807SPoul-Henning Kamp 
22531304807SPoul-Henning Kamp 	LIST_FOREACH(r, &refs, next) {
22631304807SPoul-Henning Kamp 		if (!strcmp(r1, r->k1))
22731304807SPoul-Henning Kamp 			return (strcmp(r2, r->k2));
22831304807SPoul-Henning Kamp 	}
22931304807SPoul-Henning Kamp 	r = calloc(1, sizeof(*r));
23031304807SPoul-Henning Kamp 	r->k1 = strdup(r1);
23131304807SPoul-Henning Kamp 	r->k2 = strdup(r2);
23231304807SPoul-Henning Kamp 	LIST_INSERT_HEAD(&refs, r, next);
23331304807SPoul-Henning Kamp 	return (0);
23431304807SPoul-Henning Kamp }
23531304807SPoul-Henning Kamp 
23631304807SPoul-Henning Kamp static int compare_node2(struct node *n1, struct node *n2, int in);
23731304807SPoul-Henning Kamp 
23831304807SPoul-Henning Kamp static int
23931304807SPoul-Henning Kamp compare_node(struct node *n1, struct node *n2, int in)
24031304807SPoul-Henning Kamp {
24131304807SPoul-Henning Kamp 	int i;
24231304807SPoul-Henning Kamp 	struct node *n1a, *n2a;
24331304807SPoul-Henning Kamp 
24431304807SPoul-Henning Kamp 	i = strcmp(n1->name, n2->name);
24531304807SPoul-Henning Kamp 	if (i)
24631304807SPoul-Henning Kamp 		return (i);
24731304807SPoul-Henning Kamp 	if (!strcmp(n1->name, "ref"))
24831304807SPoul-Henning Kamp 		i = refcmp(sbuf_data(n1->cont), sbuf_data(n2->cont));
24931304807SPoul-Henning Kamp 	else
25031304807SPoul-Henning Kamp 		i = strcmp(sbuf_data(n1->cont), sbuf_data(n2->cont));
25131304807SPoul-Henning Kamp 	if (i)
25231304807SPoul-Henning Kamp 		return (1);
25331304807SPoul-Henning Kamp 	n1a = LIST_FIRST(&n1->children);
25431304807SPoul-Henning Kamp 	n2a = LIST_FIRST(&n2->children);
25531304807SPoul-Henning Kamp 	for (;;) {
25631304807SPoul-Henning Kamp 		if (n1a == NULL && n2a == NULL)
25731304807SPoul-Henning Kamp 			return (0);
25831304807SPoul-Henning Kamp 		if (n1a != NULL && n2a == NULL)
25931304807SPoul-Henning Kamp 			return (1);
26031304807SPoul-Henning Kamp 		if (n1a == NULL && n2a != NULL)
26131304807SPoul-Henning Kamp 			return (1);
26231304807SPoul-Henning Kamp 		i = compare_node2(n1a, n2a, in + 2);
26331304807SPoul-Henning Kamp 		if (i)
26431304807SPoul-Henning Kamp 			return (1);
26531304807SPoul-Henning Kamp 		n1a = LIST_NEXT(n1a, siblings);
26631304807SPoul-Henning Kamp 		n2a = LIST_NEXT(n2a, siblings);
26731304807SPoul-Henning Kamp 	}
26831304807SPoul-Henning Kamp 	return (0);
26931304807SPoul-Henning Kamp }
27031304807SPoul-Henning Kamp 
27131304807SPoul-Henning Kamp static int
27231304807SPoul-Henning Kamp compare_node2(struct node *n1, struct node *n2, int in)
27331304807SPoul-Henning Kamp {
27431304807SPoul-Henning Kamp 	int i;
27531304807SPoul-Henning Kamp 
27631304807SPoul-Henning Kamp 	i = compare_node(n1, n2, in);
27731304807SPoul-Henning Kamp 	if (i) {
27831304807SPoul-Henning Kamp 		printf("1>");
27931304807SPoul-Henning Kamp 		indent(in);
28031304807SPoul-Henning Kamp 		print_node(n1);
28131304807SPoul-Henning Kamp 		printf("2>");
28231304807SPoul-Henning Kamp 		indent(in);
28331304807SPoul-Henning Kamp 		print_node(n2);
28431304807SPoul-Henning Kamp 	}
28531304807SPoul-Henning Kamp 	return (i);
28631304807SPoul-Henning Kamp }
28731304807SPoul-Henning Kamp 
28831304807SPoul-Henning Kamp 
28931304807SPoul-Henning Kamp 
29031304807SPoul-Henning Kamp int
29131304807SPoul-Henning Kamp main(int argc, char **argv)
29231304807SPoul-Henning Kamp {
29331304807SPoul-Henning Kamp 	struct mytree *t1, *t2;
29431304807SPoul-Henning Kamp 	int i;
29531304807SPoul-Henning Kamp 
29631304807SPoul-Henning Kamp 	setbuf(stdout, NULL);
29731304807SPoul-Henning Kamp 	setbuf(stderr, NULL);
29831304807SPoul-Henning Kamp 	if (argc != 3)
29931304807SPoul-Henning Kamp 		errx(1, "Usage: %s file1 file2", argv[0]);
30031304807SPoul-Henning Kamp 
30131304807SPoul-Henning Kamp 	t1 = dofile(argv[1]);
30231304807SPoul-Henning Kamp 	if (t1 == NULL)
30331304807SPoul-Henning Kamp 		errx(2, "XML parser error on file %s", argv[1]);
30431304807SPoul-Henning Kamp 	sort_node(t1->top);
30531304807SPoul-Henning Kamp 	t2 = dofile(argv[2]);
30631304807SPoul-Henning Kamp 	if (t2 == NULL)
30731304807SPoul-Henning Kamp 		errx(2, "XML parser error on file %s", argv[2]);
30831304807SPoul-Henning Kamp 	sort_node(t2->top);
30931304807SPoul-Henning Kamp 	i = compare_node(t1->top, t2->top, 0);
31031304807SPoul-Henning Kamp 	return (i);
31131304807SPoul-Henning Kamp }
31231304807SPoul-Henning Kamp 
313