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
3631304807SPoul-Henning Kamp #include <stdio.h>
3731304807SPoul-Henning Kamp #include <stdlib.h>
3831304807SPoul-Henning Kamp #include <string.h>
3931304807SPoul-Henning Kamp #include <unistd.h>
4031304807SPoul-Henning Kamp #include <fcntl.h>
4131304807SPoul-Henning Kamp #include <ctype.h>
4231304807SPoul-Henning Kamp #include <sys/stat.h>
4331304807SPoul-Henning Kamp #include <sys/mman.h>
4431304807SPoul-Henning Kamp #include <sys/queue.h>
4531304807SPoul-Henning Kamp #include <sys/sbuf.h>
4631304807SPoul-Henning Kamp #include <err.h>
475624b2d4SPoul-Henning Kamp #include <bsdxml.h>
4831304807SPoul-Henning Kamp
49a99aa4c4SPoul-Henning Kamp FILE *fsubs;
50a99aa4c4SPoul-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;
5500d1e0f6SPoul-Henning Kamp const char *name;
5631304807SPoul-Henning Kamp struct sbuf *cont;
5731304807SPoul-Henning Kamp struct sbuf *key;
5800d1e0f6SPoul-Henning Kamp char *id;
5900d1e0f6SPoul-Henning Kamp char *ref;
6031304807SPoul-Henning Kamp };
6131304807SPoul-Henning Kamp
6231304807SPoul-Henning Kamp struct mytree {
6331304807SPoul-Henning Kamp struct node *top;
6431304807SPoul-Henning Kamp struct node *cur;
6531304807SPoul-Henning Kamp int indent;
666de2a2e8SPoul-Henning Kamp int ignore;
6731304807SPoul-Henning Kamp };
6831304807SPoul-Henning Kamp
6931304807SPoul-Henning Kamp struct ref {
7031304807SPoul-Henning Kamp LIST_ENTRY(ref) next;
7131304807SPoul-Henning Kamp char *k1;
7231304807SPoul-Henning Kamp char *k2;
7331304807SPoul-Henning Kamp };
7431304807SPoul-Henning Kamp
7513e403fdSAntoine Brodin LIST_HEAD(, ref) refs = LIST_HEAD_INITIALIZER(refs);
7631304807SPoul-Henning Kamp
7731304807SPoul-Henning Kamp static struct node *
new_node(void)7831304807SPoul-Henning Kamp new_node(void)
7931304807SPoul-Henning Kamp {
8031304807SPoul-Henning Kamp struct node *np;
8131304807SPoul-Henning Kamp
8231304807SPoul-Henning Kamp np = calloc(1, sizeof *np);
832616144eSDag-Erling Smørgrav np->cont = sbuf_new_auto();
8431304807SPoul-Henning Kamp sbuf_clear(np->cont);
852616144eSDag-Erling Smørgrav np->key = sbuf_new_auto();
8631304807SPoul-Henning Kamp sbuf_clear(np->key);
8731304807SPoul-Henning Kamp LIST_INIT(&np->children);
8831304807SPoul-Henning Kamp return (np);
8931304807SPoul-Henning Kamp }
9031304807SPoul-Henning Kamp
9131304807SPoul-Henning Kamp static void
indent(int n)9231304807SPoul-Henning Kamp indent(int n)
9331304807SPoul-Henning Kamp {
9431304807SPoul-Henning Kamp
9531304807SPoul-Henning Kamp printf("%*.*s", n, n, "");
9631304807SPoul-Henning Kamp }
9731304807SPoul-Henning Kamp
9831304807SPoul-Henning Kamp static void
StartElement(void * userData,const char * name,const char ** attr)9900d1e0f6SPoul-Henning Kamp StartElement(void *userData, const char *name, const char **attr)
10031304807SPoul-Henning Kamp {
10131304807SPoul-Henning Kamp struct mytree *mt;
10231304807SPoul-Henning Kamp struct node *np;
10300d1e0f6SPoul-Henning Kamp int i;
10431304807SPoul-Henning Kamp
10531304807SPoul-Henning Kamp mt = userData;
1066de2a2e8SPoul-Henning Kamp if (!strcmp(name, "FreeBSD")) {
1076de2a2e8SPoul-Henning Kamp mt->ignore = 1;
1086de2a2e8SPoul-Henning Kamp return;
1096de2a2e8SPoul-Henning Kamp }
1106de2a2e8SPoul-Henning Kamp mt->ignore = 0;
11131304807SPoul-Henning Kamp mt->indent += 2;
11231304807SPoul-Henning Kamp np = new_node();
11300d1e0f6SPoul-Henning Kamp for (i = 0; attr[i]; i += 2) {
11400d1e0f6SPoul-Henning Kamp if (!strcmp(attr[i], "id"))
11500d1e0f6SPoul-Henning Kamp np->id = strdup(attr[i+1]);
11600d1e0f6SPoul-Henning Kamp else if (!strcmp(attr[i], "ref"))
11700d1e0f6SPoul-Henning Kamp np->ref = strdup(attr[i+1]);
11800d1e0f6SPoul-Henning Kamp }
11931304807SPoul-Henning Kamp np->name = strdup(name);
12031304807SPoul-Henning Kamp sbuf_cat(np->key, name);
12131304807SPoul-Henning Kamp sbuf_cat(np->key, "::");
12231304807SPoul-Henning Kamp np->parent = mt->cur;
12331304807SPoul-Henning Kamp LIST_INSERT_HEAD(&mt->cur->children, np, siblings);
12431304807SPoul-Henning Kamp mt->cur = np;
12531304807SPoul-Henning Kamp }
12631304807SPoul-Henning Kamp
12731304807SPoul-Henning Kamp static void
EndElement(void * userData,const char * name __unused)12831304807SPoul-Henning Kamp EndElement(void *userData, const char *name __unused)
12931304807SPoul-Henning Kamp {
13031304807SPoul-Henning Kamp struct mytree *mt;
13131304807SPoul-Henning Kamp struct node *np;
13231304807SPoul-Henning Kamp
13331304807SPoul-Henning Kamp mt = userData;
1346de2a2e8SPoul-Henning Kamp if (mt->ignore)
1356de2a2e8SPoul-Henning Kamp return;
13631304807SPoul-Henning Kamp
13731304807SPoul-Henning Kamp mt->indent -= 2;
13831304807SPoul-Henning Kamp sbuf_finish(mt->cur->cont);
13931304807SPoul-Henning Kamp LIST_FOREACH(np, &mt->cur->children, siblings) {
14031304807SPoul-Henning Kamp if (strcmp(np->name, "name"))
14131304807SPoul-Henning Kamp continue;
14231304807SPoul-Henning Kamp sbuf_cat(mt->cur->key, sbuf_data(np->cont));
14331304807SPoul-Henning Kamp break;
14431304807SPoul-Henning Kamp }
14531304807SPoul-Henning Kamp sbuf_finish(mt->cur->key);
14631304807SPoul-Henning Kamp mt->cur = mt->cur->parent;
14731304807SPoul-Henning Kamp }
14831304807SPoul-Henning Kamp
14931304807SPoul-Henning Kamp static void
CharData(void * userData,const XML_Char * s,int len)15031304807SPoul-Henning Kamp CharData(void *userData , const XML_Char *s , int len)
15131304807SPoul-Henning Kamp {
15231304807SPoul-Henning Kamp struct mytree *mt;
15331304807SPoul-Henning Kamp const char *b, *e;
15431304807SPoul-Henning Kamp
15531304807SPoul-Henning Kamp mt = userData;
1566de2a2e8SPoul-Henning Kamp if (mt->ignore)
1576de2a2e8SPoul-Henning Kamp return;
15831304807SPoul-Henning Kamp b = s;
15931304807SPoul-Henning Kamp e = s + len - 1;
16031304807SPoul-Henning Kamp while (isspace(*b) && b < e)
16131304807SPoul-Henning Kamp b++;
16231304807SPoul-Henning Kamp while (isspace(*e) && e > b)
16331304807SPoul-Henning Kamp e--;
16449efad87SPoul-Henning Kamp if (e != b || *b)
16531304807SPoul-Henning Kamp sbuf_bcat(mt->cur->cont, b, e - b + 1);
16631304807SPoul-Henning Kamp }
16731304807SPoul-Henning Kamp
16831304807SPoul-Henning Kamp static struct mytree *
dofile(char * filename)16931304807SPoul-Henning Kamp dofile(char *filename)
17031304807SPoul-Henning Kamp {
17131304807SPoul-Henning Kamp XML_Parser parser;
17231304807SPoul-Henning Kamp struct mytree *mt;
17331304807SPoul-Henning Kamp struct stat st;
17431304807SPoul-Henning Kamp int fd;
17531304807SPoul-Henning Kamp char *p;
17631304807SPoul-Henning Kamp int i;
17731304807SPoul-Henning Kamp
17831304807SPoul-Henning Kamp parser = XML_ParserCreate(NULL);
17931304807SPoul-Henning Kamp mt = calloc(1, sizeof *mt);
18031304807SPoul-Henning Kamp mt->top = new_node();
18131304807SPoul-Henning Kamp mt->top->name = "(top)";
18231304807SPoul-Henning Kamp mt->top->parent = mt->top;
18331304807SPoul-Henning Kamp mt->cur = mt->top;
18431304807SPoul-Henning Kamp sbuf_finish(mt->top->key);
18531304807SPoul-Henning Kamp sbuf_finish(mt->top->cont);
18631304807SPoul-Henning Kamp XML_SetUserData(parser, mt);
18731304807SPoul-Henning Kamp XML_SetElementHandler(parser, StartElement, EndElement);
18831304807SPoul-Henning Kamp XML_SetCharacterDataHandler(parser, CharData);
18931304807SPoul-Henning Kamp fd = open(filename, O_RDONLY);
19031304807SPoul-Henning Kamp if (fd < 0)
19131304807SPoul-Henning Kamp err(1, filename);
19231304807SPoul-Henning Kamp fstat(fd, &st);
19331304807SPoul-Henning Kamp p = mmap(NULL, st.st_size, PROT_READ, MAP_NOCORE|MAP_PRIVATE, fd, 0);
19431304807SPoul-Henning Kamp i = XML_Parse(parser, p, st.st_size, 1);
1956de2a2e8SPoul-Henning Kamp if (i != 1)
1966de2a2e8SPoul-Henning Kamp errx(1, "XML_Parse complained -> %d", i);
19731304807SPoul-Henning Kamp munmap(p, st.st_size);
19831304807SPoul-Henning Kamp close(fd);
19931304807SPoul-Henning Kamp XML_ParserFree(parser);
20031304807SPoul-Henning Kamp sbuf_finish(mt->top->cont);
20131304807SPoul-Henning Kamp if (i)
20231304807SPoul-Henning Kamp return (mt);
20331304807SPoul-Henning Kamp else
20431304807SPoul-Henning Kamp return (NULL);
20531304807SPoul-Henning Kamp }
20631304807SPoul-Henning Kamp
20731304807SPoul-Henning Kamp static void
print_node(struct node * np)20831304807SPoul-Henning Kamp print_node(struct node *np)
20931304807SPoul-Henning Kamp {
21000d1e0f6SPoul-Henning Kamp printf("\"%s\" -- \"%s\" -- \"%s\"", np->name, sbuf_data(np->cont), sbuf_data(np->key));
21100d1e0f6SPoul-Henning Kamp if (np->id)
21200d1e0f6SPoul-Henning Kamp printf(" id=\"%s\"", np->id);
21300d1e0f6SPoul-Henning Kamp if (np->ref)
21400d1e0f6SPoul-Henning Kamp printf(" ref=\"%s\"", np->ref);
21500d1e0f6SPoul-Henning Kamp printf("\n");
21600d1e0f6SPoul-Henning Kamp }
21700d1e0f6SPoul-Henning Kamp
21800d1e0f6SPoul-Henning Kamp static void
print_tree(struct node * np,int n)21900d1e0f6SPoul-Henning Kamp print_tree(struct node *np, int n)
22000d1e0f6SPoul-Henning Kamp {
22100d1e0f6SPoul-Henning Kamp struct node *np1;
22200d1e0f6SPoul-Henning Kamp
22300d1e0f6SPoul-Henning Kamp indent(n); printf("%s id=%s ref=%s\n", np->name, np->id, np->ref);
22400d1e0f6SPoul-Henning Kamp LIST_FOREACH(np1, &np->children, siblings)
22500d1e0f6SPoul-Henning Kamp print_tree(np1, n + 2);
22631304807SPoul-Henning Kamp }
22731304807SPoul-Henning Kamp
22831304807SPoul-Henning Kamp static void
sort_node(struct node * np)22931304807SPoul-Henning Kamp sort_node(struct node *np)
23031304807SPoul-Henning Kamp {
23131304807SPoul-Henning Kamp struct node *np1, *np2;
23231304807SPoul-Henning Kamp int n;
23331304807SPoul-Henning Kamp
23431304807SPoul-Henning Kamp LIST_FOREACH(np1, &np->children, siblings)
23531304807SPoul-Henning Kamp sort_node(np1);
23631304807SPoul-Henning Kamp do {
23731304807SPoul-Henning Kamp np1 = LIST_FIRST(&np->children);
23831304807SPoul-Henning Kamp n = 0;
23931304807SPoul-Henning Kamp for (;;) {
24031304807SPoul-Henning Kamp if (np1 == NULL)
24131304807SPoul-Henning Kamp return;
24231304807SPoul-Henning Kamp np2 = LIST_NEXT(np1, siblings);
24331304807SPoul-Henning Kamp if (np2 == NULL)
24431304807SPoul-Henning Kamp return;
24531304807SPoul-Henning Kamp if (strcmp(sbuf_data(np1->key), sbuf_data(np2->key)) > 0) {
24631304807SPoul-Henning Kamp LIST_REMOVE(np2, siblings);
24731304807SPoul-Henning Kamp LIST_INSERT_BEFORE(np1, np2, siblings);
24831304807SPoul-Henning Kamp n++;
24931304807SPoul-Henning Kamp break;
25031304807SPoul-Henning Kamp }
25131304807SPoul-Henning Kamp np1 = np2;
25231304807SPoul-Henning Kamp }
25331304807SPoul-Henning Kamp } while (n);
25431304807SPoul-Henning Kamp }
25531304807SPoul-Henning Kamp
25631304807SPoul-Henning Kamp static int
refcmp(char * r1,char * r2)25731304807SPoul-Henning Kamp refcmp(char *r1, char *r2)
25831304807SPoul-Henning Kamp {
25931304807SPoul-Henning Kamp struct ref *r;
26031304807SPoul-Henning Kamp
26131304807SPoul-Henning Kamp LIST_FOREACH(r, &refs, next) {
26231304807SPoul-Henning Kamp if (!strcmp(r1, r->k1))
26331304807SPoul-Henning Kamp return (strcmp(r2, r->k2));
26431304807SPoul-Henning Kamp }
26531304807SPoul-Henning Kamp r = calloc(1, sizeof(*r));
26631304807SPoul-Henning Kamp r->k1 = strdup(r1);
26731304807SPoul-Henning Kamp r->k2 = strdup(r2);
26831304807SPoul-Henning Kamp LIST_INSERT_HEAD(&refs, r, next);
269a99aa4c4SPoul-Henning Kamp if (fsubs != NULL) {
270a99aa4c4SPoul-Henning Kamp fprintf(fsubs, "s/%s/%s/g\n", r1, r2);
271a99aa4c4SPoul-Henning Kamp fflush(fsubs);
272a99aa4c4SPoul-Henning Kamp }
27331304807SPoul-Henning Kamp return (0);
27431304807SPoul-Henning Kamp }
27531304807SPoul-Henning Kamp
27631304807SPoul-Henning Kamp static int compare_node2(struct node *n1, struct node *n2, int in);
27731304807SPoul-Henning Kamp
27831304807SPoul-Henning Kamp static int
compare_node(struct node * n1,struct node * n2,int in)27931304807SPoul-Henning Kamp compare_node(struct node *n1, struct node *n2, int in)
28031304807SPoul-Henning Kamp {
28131304807SPoul-Henning Kamp int i;
28231304807SPoul-Henning Kamp struct node *n1a, *n2a;
28331304807SPoul-Henning Kamp
28431304807SPoul-Henning Kamp i = strcmp(n1->name, n2->name);
28531304807SPoul-Henning Kamp if (i)
28631304807SPoul-Henning Kamp return (i);
28700d1e0f6SPoul-Henning Kamp if (n1->id && n2->id)
28800d1e0f6SPoul-Henning Kamp i = refcmp(n1->id, n2->id);
28900d1e0f6SPoul-Henning Kamp else if (n1->id || n2->id)
29000d1e0f6SPoul-Henning Kamp i = -1;
29100d1e0f6SPoul-Henning Kamp if (i)
29200d1e0f6SPoul-Henning Kamp return (i);
29300d1e0f6SPoul-Henning Kamp if (n1->ref && n2->ref)
29400d1e0f6SPoul-Henning Kamp i = refcmp(n1->ref, n2->ref);
29500d1e0f6SPoul-Henning Kamp else if (n1->ref || n2->ref)
29600d1e0f6SPoul-Henning Kamp i = -1;
29700d1e0f6SPoul-Henning Kamp if (i)
29800d1e0f6SPoul-Henning Kamp return (i);
29931304807SPoul-Henning Kamp if (!strcmp(n1->name, "ref"))
30031304807SPoul-Henning Kamp i = refcmp(sbuf_data(n1->cont), sbuf_data(n2->cont));
30131304807SPoul-Henning Kamp else
30231304807SPoul-Henning Kamp i = strcmp(sbuf_data(n1->cont), sbuf_data(n2->cont));
30331304807SPoul-Henning Kamp if (i)
30431304807SPoul-Henning Kamp return (1);
30531304807SPoul-Henning Kamp n1a = LIST_FIRST(&n1->children);
30631304807SPoul-Henning Kamp n2a = LIST_FIRST(&n2->children);
30731304807SPoul-Henning Kamp for (;;) {
30831304807SPoul-Henning Kamp if (n1a == NULL && n2a == NULL)
30931304807SPoul-Henning Kamp return (0);
310fdc34af0SPoul-Henning Kamp if (n1a != NULL && n2a == NULL) {
311fdc34af0SPoul-Henning Kamp printf("1>");
312fdc34af0SPoul-Henning Kamp indent(in);
313fdc34af0SPoul-Henning Kamp print_node(n1a);
314fdc34af0SPoul-Henning Kamp printf("2>\n");
31531304807SPoul-Henning Kamp return (1);
316fdc34af0SPoul-Henning Kamp }
317fdc34af0SPoul-Henning Kamp if (n1a == NULL && n2a != NULL) {
318fdc34af0SPoul-Henning Kamp printf("1>\n");
319fdc34af0SPoul-Henning Kamp printf("2>");
320fdc34af0SPoul-Henning Kamp indent(in);
321fdc34af0SPoul-Henning Kamp print_node(n2a);
32231304807SPoul-Henning Kamp return (1);
323fdc34af0SPoul-Henning Kamp }
32431304807SPoul-Henning Kamp i = compare_node2(n1a, n2a, in + 2);
32531304807SPoul-Henning Kamp if (i)
32631304807SPoul-Henning Kamp return (1);
32731304807SPoul-Henning Kamp n1a = LIST_NEXT(n1a, siblings);
32831304807SPoul-Henning Kamp n2a = LIST_NEXT(n2a, siblings);
32931304807SPoul-Henning Kamp }
33031304807SPoul-Henning Kamp return (0);
33131304807SPoul-Henning Kamp }
33231304807SPoul-Henning Kamp
33331304807SPoul-Henning Kamp static int
compare_node2(struct node * n1,struct node * n2,int in)33431304807SPoul-Henning Kamp compare_node2(struct node *n1, struct node *n2, int in)
33531304807SPoul-Henning Kamp {
33631304807SPoul-Henning Kamp int i;
33731304807SPoul-Henning Kamp
33831304807SPoul-Henning Kamp i = compare_node(n1, n2, in);
33931304807SPoul-Henning Kamp if (i) {
34031304807SPoul-Henning Kamp printf("1>");
34131304807SPoul-Henning Kamp indent(in);
34231304807SPoul-Henning Kamp print_node(n1);
34331304807SPoul-Henning Kamp printf("2>");
34431304807SPoul-Henning Kamp indent(in);
34531304807SPoul-Henning Kamp print_node(n2);
34631304807SPoul-Henning Kamp }
34731304807SPoul-Henning Kamp return (i);
34831304807SPoul-Henning Kamp }
34931304807SPoul-Henning Kamp
35031304807SPoul-Henning Kamp
35131304807SPoul-Henning Kamp
35231304807SPoul-Henning Kamp int
main(int argc,char ** argv)35331304807SPoul-Henning Kamp main(int argc, char **argv)
35431304807SPoul-Henning Kamp {
35531304807SPoul-Henning Kamp struct mytree *t1, *t2;
35631304807SPoul-Henning Kamp int i;
35731304807SPoul-Henning Kamp
358a99aa4c4SPoul-Henning Kamp fsubs = fopen("_.subs", "w");
35931304807SPoul-Henning Kamp setbuf(stdout, NULL);
36031304807SPoul-Henning Kamp setbuf(stderr, NULL);
36131304807SPoul-Henning Kamp if (argc != 3)
362d3974088SDag-Erling Smørgrav errx(1, "usage: %s file1 file2", argv[0]);
36331304807SPoul-Henning Kamp
36431304807SPoul-Henning Kamp t1 = dofile(argv[1]);
36531304807SPoul-Henning Kamp if (t1 == NULL)
36631304807SPoul-Henning Kamp errx(2, "XML parser error on file %s", argv[1]);
36731304807SPoul-Henning Kamp sort_node(t1->top);
36831304807SPoul-Henning Kamp t2 = dofile(argv[2]);
36931304807SPoul-Henning Kamp if (t2 == NULL)
37031304807SPoul-Henning Kamp errx(2, "XML parser error on file %s", argv[2]);
37131304807SPoul-Henning Kamp sort_node(t2->top);
37231304807SPoul-Henning Kamp i = compare_node(t1->top, t2->top, 0);
37331304807SPoul-Henning Kamp return (i);
37431304807SPoul-Henning Kamp }
37531304807SPoul-Henning Kamp
376