xref: /freebsd/tools/regression/geom/ConfCmp/ConfCmp.c (revision 6de2a2e8a5ecc812a85e5933d42ce57fecd9a922)
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;
646de2a2e8SPoul-Henning Kamp 	int			ignore;
6531304807SPoul-Henning Kamp };
6631304807SPoul-Henning Kamp 
6731304807SPoul-Henning Kamp struct ref {
6831304807SPoul-Henning Kamp 	LIST_ENTRY(ref)		next;
6931304807SPoul-Henning Kamp 	char 			*k1;
7031304807SPoul-Henning Kamp 	char			*k2;
7131304807SPoul-Henning Kamp };
7231304807SPoul-Henning Kamp 
7331304807SPoul-Henning Kamp LIST_HEAD(, ref)		refs = LIST_HEAD_INITIALIZER(&refs);
7431304807SPoul-Henning Kamp 
7531304807SPoul-Henning Kamp static struct node *
7631304807SPoul-Henning Kamp new_node(void)
7731304807SPoul-Henning Kamp {
7831304807SPoul-Henning Kamp 	struct node *np;
7931304807SPoul-Henning Kamp 
8031304807SPoul-Henning Kamp 	np = calloc(1, sizeof *np);
8131304807SPoul-Henning Kamp 	np->cont = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND);
8231304807SPoul-Henning Kamp 	sbuf_clear(np->cont);
8331304807SPoul-Henning Kamp 	np->key = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND);
8431304807SPoul-Henning Kamp 	sbuf_clear(np->key);
8531304807SPoul-Henning Kamp 	LIST_INIT(&np->children);
8631304807SPoul-Henning Kamp 	return (np);
8731304807SPoul-Henning Kamp }
8831304807SPoul-Henning Kamp 
8931304807SPoul-Henning Kamp static void
9031304807SPoul-Henning Kamp indent(int n)
9131304807SPoul-Henning Kamp {
9231304807SPoul-Henning Kamp 
9331304807SPoul-Henning Kamp 	printf("%*.*s", n, n, "");
9431304807SPoul-Henning Kamp }
9531304807SPoul-Henning Kamp 
9631304807SPoul-Henning Kamp static void
9731304807SPoul-Henning Kamp StartElement(void *userData, const char *name, const char **atts __unused)
9831304807SPoul-Henning Kamp {
9931304807SPoul-Henning Kamp 	struct mytree *mt;
10031304807SPoul-Henning Kamp 	struct node *np;
10131304807SPoul-Henning Kamp 
10231304807SPoul-Henning Kamp 	mt = userData;
1036de2a2e8SPoul-Henning Kamp 	if (!strcmp(name, "FreeBSD")) {
1046de2a2e8SPoul-Henning Kamp 		mt->ignore = 1;
1056de2a2e8SPoul-Henning Kamp 		return;
1066de2a2e8SPoul-Henning Kamp 	}
1076de2a2e8SPoul-Henning Kamp 	mt->ignore = 0;
10831304807SPoul-Henning Kamp 	mt->indent += 2;
10931304807SPoul-Henning Kamp 	np = new_node();
11031304807SPoul-Henning Kamp 	np->name = strdup(name);
11131304807SPoul-Henning Kamp 	sbuf_cat(np->key, name);
11231304807SPoul-Henning Kamp 	sbuf_cat(np->key, "::");
11331304807SPoul-Henning Kamp 	np->parent = mt->cur;
11431304807SPoul-Henning Kamp 	LIST_INSERT_HEAD(&mt->cur->children, np, siblings);
11531304807SPoul-Henning Kamp 	mt->cur = np;
11631304807SPoul-Henning Kamp }
11731304807SPoul-Henning Kamp 
11831304807SPoul-Henning Kamp static void
11931304807SPoul-Henning Kamp EndElement(void *userData, const char *name __unused)
12031304807SPoul-Henning Kamp {
12131304807SPoul-Henning Kamp 	struct mytree *mt;
12231304807SPoul-Henning Kamp 	struct node *np;
12331304807SPoul-Henning Kamp 
12431304807SPoul-Henning Kamp 	mt = userData;
1256de2a2e8SPoul-Henning Kamp 	if (mt->ignore)
1266de2a2e8SPoul-Henning Kamp 		return;
12731304807SPoul-Henning Kamp 
12831304807SPoul-Henning Kamp 	mt->indent -= 2;
12931304807SPoul-Henning Kamp 	sbuf_finish(mt->cur->cont);
13031304807SPoul-Henning Kamp 	LIST_FOREACH(np, &mt->cur->children, siblings) {
13131304807SPoul-Henning Kamp 		if (strcmp(np->name, "name"))
13231304807SPoul-Henning Kamp 			continue;
13331304807SPoul-Henning Kamp 		sbuf_cat(mt->cur->key, sbuf_data(np->cont));
13431304807SPoul-Henning Kamp 		break;
13531304807SPoul-Henning Kamp 	}
13631304807SPoul-Henning Kamp 	sbuf_finish(mt->cur->key);
13731304807SPoul-Henning Kamp 	mt->cur = mt->cur->parent;
13831304807SPoul-Henning Kamp }
13931304807SPoul-Henning Kamp 
14031304807SPoul-Henning Kamp static void
14131304807SPoul-Henning Kamp CharData(void *userData , const XML_Char *s , int len)
14231304807SPoul-Henning Kamp {
14331304807SPoul-Henning Kamp 	struct mytree *mt;
14431304807SPoul-Henning Kamp 	const char *b, *e;
14531304807SPoul-Henning Kamp 
14631304807SPoul-Henning Kamp 	mt = userData;
1476de2a2e8SPoul-Henning Kamp 	if (mt->ignore)
1486de2a2e8SPoul-Henning Kamp 		return;
14931304807SPoul-Henning Kamp 	b = s;
15031304807SPoul-Henning Kamp 	e = s + len - 1;
15131304807SPoul-Henning Kamp 	while (isspace(*b) && b < e)
15231304807SPoul-Henning Kamp 		b++;
15331304807SPoul-Henning Kamp 	while (isspace(*e) && e > b)
15431304807SPoul-Henning Kamp 		e--;
15531304807SPoul-Henning Kamp 	if (e != b)
15631304807SPoul-Henning Kamp 		sbuf_bcat(mt->cur->cont, b, e - b + 1);
15731304807SPoul-Henning Kamp }
15831304807SPoul-Henning Kamp 
15931304807SPoul-Henning Kamp static struct mytree *
16031304807SPoul-Henning Kamp dofile(char *filename)
16131304807SPoul-Henning Kamp {
16231304807SPoul-Henning Kamp 	XML_Parser parser;
16331304807SPoul-Henning Kamp 	struct mytree *mt;
16431304807SPoul-Henning Kamp 	struct stat st;
16531304807SPoul-Henning Kamp 	int fd;
16631304807SPoul-Henning Kamp 	char *p;
16731304807SPoul-Henning Kamp 	int i;
16831304807SPoul-Henning Kamp 
16931304807SPoul-Henning Kamp 	parser = XML_ParserCreate(NULL);
17031304807SPoul-Henning Kamp 	mt = calloc(1, sizeof *mt);
17131304807SPoul-Henning Kamp 	mt->top = new_node();
17231304807SPoul-Henning Kamp 	mt->top->name = "(top)";
17331304807SPoul-Henning Kamp 	mt->top->parent = mt->top;
17431304807SPoul-Henning Kamp 	mt->cur = mt->top;
17531304807SPoul-Henning Kamp 	sbuf_finish(mt->top->key);
17631304807SPoul-Henning Kamp 	sbuf_finish(mt->top->cont);
17731304807SPoul-Henning Kamp 	XML_SetUserData(parser, mt);
17831304807SPoul-Henning Kamp 	XML_SetElementHandler(parser, StartElement, EndElement);
17931304807SPoul-Henning Kamp 	XML_SetCharacterDataHandler(parser, CharData);
18031304807SPoul-Henning Kamp 	fd = open(filename, O_RDONLY);
18131304807SPoul-Henning Kamp 	if (fd < 0)
18231304807SPoul-Henning Kamp 		err(1, filename);
18331304807SPoul-Henning Kamp 	fstat(fd, &st);
18431304807SPoul-Henning Kamp 	p = mmap(NULL, st.st_size, PROT_READ, MAP_NOCORE|MAP_PRIVATE, fd, 0);
18531304807SPoul-Henning Kamp 	i = XML_Parse(parser, p, st.st_size, 1);
1866de2a2e8SPoul-Henning Kamp 	if (i != 1)
1876de2a2e8SPoul-Henning Kamp 		errx(1, "XML_Parse complained -> %d", i);
18831304807SPoul-Henning Kamp 	munmap(p, st.st_size);
18931304807SPoul-Henning Kamp 	close(fd);
19031304807SPoul-Henning Kamp 	XML_ParserFree(parser);
19131304807SPoul-Henning Kamp 	sbuf_finish(mt->top->cont);
19231304807SPoul-Henning Kamp 	if (i)
19331304807SPoul-Henning Kamp 		return (mt);
19431304807SPoul-Henning Kamp 	else
19531304807SPoul-Henning Kamp 		return (NULL);
19631304807SPoul-Henning Kamp }
19731304807SPoul-Henning Kamp 
19831304807SPoul-Henning Kamp static void
19931304807SPoul-Henning Kamp print_node(struct node *np)
20031304807SPoul-Henning Kamp {
20131304807SPoul-Henning Kamp 	printf("\"%s\" -- \"%s\" -- \"%s\"\n", np->name, sbuf_data(np->cont), sbuf_data(np->key));
20231304807SPoul-Henning Kamp }
20331304807SPoul-Henning Kamp 
20431304807SPoul-Henning Kamp static void
20531304807SPoul-Henning Kamp sort_node(struct node *np)
20631304807SPoul-Henning Kamp {
20731304807SPoul-Henning Kamp 	struct node *np1, *np2;
20831304807SPoul-Henning Kamp 	int n;
20931304807SPoul-Henning Kamp 
21031304807SPoul-Henning Kamp 	LIST_FOREACH(np1, &np->children, siblings)
21131304807SPoul-Henning Kamp 		sort_node(np1);
21231304807SPoul-Henning Kamp 	do {
21331304807SPoul-Henning Kamp 		np1 = LIST_FIRST(&np->children);
21431304807SPoul-Henning Kamp 		n = 0;
21531304807SPoul-Henning Kamp 		for (;;) {
21631304807SPoul-Henning Kamp 			if (np1 == NULL)
21731304807SPoul-Henning Kamp 				return;
21831304807SPoul-Henning Kamp 			np2 = LIST_NEXT(np1, siblings);
21931304807SPoul-Henning Kamp 			if (np2 == NULL)
22031304807SPoul-Henning Kamp 				return;
22131304807SPoul-Henning Kamp 			if (strcmp(sbuf_data(np1->key), sbuf_data(np2->key)) > 0) {
22231304807SPoul-Henning Kamp 				LIST_REMOVE(np2, siblings);
22331304807SPoul-Henning Kamp 				LIST_INSERT_BEFORE(np1, np2, siblings);
22431304807SPoul-Henning Kamp 				n++;
22531304807SPoul-Henning Kamp 				break;
22631304807SPoul-Henning Kamp 			}
22731304807SPoul-Henning Kamp 			np1 = np2;
22831304807SPoul-Henning Kamp 		}
22931304807SPoul-Henning Kamp 	} while (n);
23031304807SPoul-Henning Kamp }
23131304807SPoul-Henning Kamp 
23231304807SPoul-Henning Kamp static int
23331304807SPoul-Henning Kamp refcmp(char *r1, char *r2)
23431304807SPoul-Henning Kamp {
23531304807SPoul-Henning Kamp 	struct ref *r;
23631304807SPoul-Henning Kamp 
23731304807SPoul-Henning Kamp 	LIST_FOREACH(r, &refs, next) {
23831304807SPoul-Henning Kamp 		if (!strcmp(r1, r->k1))
23931304807SPoul-Henning Kamp 			return (strcmp(r2, r->k2));
24031304807SPoul-Henning Kamp 	}
24131304807SPoul-Henning Kamp 	r = calloc(1, sizeof(*r));
24231304807SPoul-Henning Kamp 	r->k1 = strdup(r1);
24331304807SPoul-Henning Kamp 	r->k2 = strdup(r2);
24431304807SPoul-Henning Kamp 	LIST_INSERT_HEAD(&refs, r, next);
24531304807SPoul-Henning Kamp 	return (0);
24631304807SPoul-Henning Kamp }
24731304807SPoul-Henning Kamp 
24831304807SPoul-Henning Kamp static int compare_node2(struct node *n1, struct node *n2, int in);
24931304807SPoul-Henning Kamp 
25031304807SPoul-Henning Kamp static int
25131304807SPoul-Henning Kamp compare_node(struct node *n1, struct node *n2, int in)
25231304807SPoul-Henning Kamp {
25331304807SPoul-Henning Kamp 	int i;
25431304807SPoul-Henning Kamp 	struct node *n1a, *n2a;
25531304807SPoul-Henning Kamp 
25631304807SPoul-Henning Kamp 	i = strcmp(n1->name, n2->name);
25731304807SPoul-Henning Kamp 	if (i)
25831304807SPoul-Henning Kamp 		return (i);
25931304807SPoul-Henning Kamp 	if (!strcmp(n1->name, "ref"))
26031304807SPoul-Henning Kamp 		i = refcmp(sbuf_data(n1->cont), sbuf_data(n2->cont));
26131304807SPoul-Henning Kamp 	else
26231304807SPoul-Henning Kamp 		i = strcmp(sbuf_data(n1->cont), sbuf_data(n2->cont));
26331304807SPoul-Henning Kamp 	if (i)
26431304807SPoul-Henning Kamp 		return (1);
26531304807SPoul-Henning Kamp 	n1a = LIST_FIRST(&n1->children);
26631304807SPoul-Henning Kamp 	n2a = LIST_FIRST(&n2->children);
26731304807SPoul-Henning Kamp 	for (;;) {
26831304807SPoul-Henning Kamp 		if (n1a == NULL && n2a == NULL)
26931304807SPoul-Henning Kamp 			return (0);
27031304807SPoul-Henning Kamp 		if (n1a != NULL && n2a == NULL)
27131304807SPoul-Henning Kamp 			return (1);
27231304807SPoul-Henning Kamp 		if (n1a == NULL && n2a != NULL)
27331304807SPoul-Henning Kamp 			return (1);
27431304807SPoul-Henning Kamp 		i = compare_node2(n1a, n2a, in + 2);
27531304807SPoul-Henning Kamp 		if (i)
27631304807SPoul-Henning Kamp 			return (1);
27731304807SPoul-Henning Kamp 		n1a = LIST_NEXT(n1a, siblings);
27831304807SPoul-Henning Kamp 		n2a = LIST_NEXT(n2a, siblings);
27931304807SPoul-Henning Kamp 	}
28031304807SPoul-Henning Kamp 	return (0);
28131304807SPoul-Henning Kamp }
28231304807SPoul-Henning Kamp 
28331304807SPoul-Henning Kamp static int
28431304807SPoul-Henning Kamp compare_node2(struct node *n1, struct node *n2, int in)
28531304807SPoul-Henning Kamp {
28631304807SPoul-Henning Kamp 	int i;
28731304807SPoul-Henning Kamp 
28831304807SPoul-Henning Kamp 	i = compare_node(n1, n2, in);
28931304807SPoul-Henning Kamp 	if (i) {
29031304807SPoul-Henning Kamp 		printf("1>");
29131304807SPoul-Henning Kamp 		indent(in);
29231304807SPoul-Henning Kamp 		print_node(n1);
29331304807SPoul-Henning Kamp 		printf("2>");
29431304807SPoul-Henning Kamp 		indent(in);
29531304807SPoul-Henning Kamp 		print_node(n2);
29631304807SPoul-Henning Kamp 	}
29731304807SPoul-Henning Kamp 	return (i);
29831304807SPoul-Henning Kamp }
29931304807SPoul-Henning Kamp 
30031304807SPoul-Henning Kamp 
30131304807SPoul-Henning Kamp 
30231304807SPoul-Henning Kamp int
30331304807SPoul-Henning Kamp main(int argc, char **argv)
30431304807SPoul-Henning Kamp {
30531304807SPoul-Henning Kamp 	struct mytree *t1, *t2;
30631304807SPoul-Henning Kamp 	int i;
30731304807SPoul-Henning Kamp 
30831304807SPoul-Henning Kamp 	setbuf(stdout, NULL);
30931304807SPoul-Henning Kamp 	setbuf(stderr, NULL);
31031304807SPoul-Henning Kamp 	if (argc != 3)
31131304807SPoul-Henning Kamp 		errx(1, "Usage: %s file1 file2", argv[0]);
31231304807SPoul-Henning Kamp 
31331304807SPoul-Henning Kamp 	t1 = dofile(argv[1]);
31431304807SPoul-Henning Kamp 	if (t1 == NULL)
31531304807SPoul-Henning Kamp 		errx(2, "XML parser error on file %s", argv[1]);
31631304807SPoul-Henning Kamp 	sort_node(t1->top);
31731304807SPoul-Henning Kamp 	t2 = dofile(argv[2]);
31831304807SPoul-Henning Kamp 	if (t2 == NULL)
31931304807SPoul-Henning Kamp 		errx(2, "XML parser error on file %s", argv[2]);
32031304807SPoul-Henning Kamp 	sort_node(t2->top);
32131304807SPoul-Henning Kamp 	i = compare_node(t1->top, t2->top, 0);
32231304807SPoul-Henning Kamp 	return (i);
32331304807SPoul-Henning Kamp }
32431304807SPoul-Henning Kamp 
325