Path: blob/main/tools/regression/geom/ConfCmp/ConfCmp.c
48253 views
/*-1* Copyright (c) 2002 Poul-Henning Kamp2* Copyright (c) 2002 Networks Associates Technology, Inc.3* All rights reserved.4*5* This software was developed for the FreeBSD Project by Poul-Henning Kamp6* and NAI Labs, the Security Research Division of Network Associates, Inc.7* under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the8* DARPA CHATS research program.9*10* Redistribution and use in source and binary forms, with or without11* modification, are permitted provided that the following conditions12* are met:13* 1. Redistributions of source code must retain the above copyright14* notice, this list of conditions and the following disclaimer.15* 2. Redistributions in binary form must reproduce the above copyright16* notice, this list of conditions and the following disclaimer in the17* documentation and/or other materials provided with the distribution.18* 3. The names of the authors may not be used to endorse or promote19* products derived from this software without specific prior written20* permission.21*22* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND23* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE24* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE25* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE26* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL27* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS28* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)29* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT30* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY31* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF32* SUCH DAMAGE.33*/3435#include <stdio.h>36#include <stdlib.h>37#include <string.h>38#include <unistd.h>39#include <fcntl.h>40#include <ctype.h>41#include <sys/stat.h>42#include <sys/mman.h>43#include <sys/queue.h>44#include <sys/sbuf.h>45#include <err.h>46#include <bsdxml.h>4748FILE *fsubs;4950struct node {51LIST_HEAD(, node) children;52LIST_ENTRY(node) siblings;53struct node *parent;54const char *name;55struct sbuf *cont;56struct sbuf *key;57char *id;58char *ref;59};6061struct mytree {62struct node *top;63struct node *cur;64int indent;65int ignore;66};6768struct ref {69LIST_ENTRY(ref) next;70char *k1;71char *k2;72};7374LIST_HEAD(, ref) refs = LIST_HEAD_INITIALIZER(refs);7576static struct node *77new_node(void)78{79struct node *np;8081np = calloc(1, sizeof *np);82np->cont = sbuf_new_auto();83sbuf_clear(np->cont);84np->key = sbuf_new_auto();85sbuf_clear(np->key);86LIST_INIT(&np->children);87return (np);88}8990static void91indent(int n)92{9394printf("%*.*s", n, n, "");95}9697static void98StartElement(void *userData, const char *name, const char **attr)99{100struct mytree *mt;101struct node *np;102int i;103104mt = userData;105if (!strcmp(name, "FreeBSD")) {106mt->ignore = 1;107return;108}109mt->ignore = 0;110mt->indent += 2;111np = new_node();112for (i = 0; attr[i]; i += 2) {113if (!strcmp(attr[i], "id"))114np->id = strdup(attr[i+1]);115else if (!strcmp(attr[i], "ref"))116np->ref = strdup(attr[i+1]);117}118np->name = strdup(name);119sbuf_cat(np->key, name);120sbuf_cat(np->key, "::");121np->parent = mt->cur;122LIST_INSERT_HEAD(&mt->cur->children, np, siblings);123mt->cur = np;124}125126static void127EndElement(void *userData, const char *name __unused)128{129struct mytree *mt;130struct node *np;131132mt = userData;133if (mt->ignore)134return;135136mt->indent -= 2;137sbuf_finish(mt->cur->cont);138LIST_FOREACH(np, &mt->cur->children, siblings) {139if (strcmp(np->name, "name"))140continue;141sbuf_cat(mt->cur->key, sbuf_data(np->cont));142break;143}144sbuf_finish(mt->cur->key);145mt->cur = mt->cur->parent;146}147148static void149CharData(void *userData , const XML_Char *s , int len)150{151struct mytree *mt;152const char *b, *e;153154mt = userData;155if (mt->ignore)156return;157b = s;158e = s + len - 1;159while (isspace(*b) && b < e)160b++;161while (isspace(*e) && e > b)162e--;163if (e != b || *b)164sbuf_bcat(mt->cur->cont, b, e - b + 1);165}166167static struct mytree *168dofile(char *filename)169{170XML_Parser parser;171struct mytree *mt;172struct stat st;173int fd;174char *p;175int i;176177parser = XML_ParserCreate(NULL);178mt = calloc(1, sizeof *mt);179mt->top = new_node();180mt->top->name = "(top)";181mt->top->parent = mt->top;182mt->cur = mt->top;183sbuf_finish(mt->top->key);184sbuf_finish(mt->top->cont);185XML_SetUserData(parser, mt);186XML_SetElementHandler(parser, StartElement, EndElement);187XML_SetCharacterDataHandler(parser, CharData);188fd = open(filename, O_RDONLY);189if (fd < 0)190err(1, filename);191fstat(fd, &st);192p = mmap(NULL, st.st_size, PROT_READ, MAP_NOCORE|MAP_PRIVATE, fd, 0);193i = XML_Parse(parser, p, st.st_size, 1);194if (i != 1)195errx(1, "XML_Parse complained -> %d", i);196munmap(p, st.st_size);197close(fd);198XML_ParserFree(parser);199sbuf_finish(mt->top->cont);200if (i)201return (mt);202else203return (NULL);204}205206static void207print_node(struct node *np)208{209printf("\"%s\" -- \"%s\" -- \"%s\"", np->name, sbuf_data(np->cont), sbuf_data(np->key));210if (np->id)211printf(" id=\"%s\"", np->id);212if (np->ref)213printf(" ref=\"%s\"", np->ref);214printf("\n");215}216217static void218print_tree(struct node *np, int n)219{220struct node *np1;221222indent(n); printf("%s id=%s ref=%s\n", np->name, np->id, np->ref);223LIST_FOREACH(np1, &np->children, siblings)224print_tree(np1, n + 2);225}226227static void228sort_node(struct node *np)229{230struct node *np1, *np2;231int n;232233LIST_FOREACH(np1, &np->children, siblings)234sort_node(np1);235do {236np1 = LIST_FIRST(&np->children);237n = 0;238for (;;) {239if (np1 == NULL)240return;241np2 = LIST_NEXT(np1, siblings);242if (np2 == NULL)243return;244if (strcmp(sbuf_data(np1->key), sbuf_data(np2->key)) > 0) {245LIST_REMOVE(np2, siblings);246LIST_INSERT_BEFORE(np1, np2, siblings);247n++;248break;249}250np1 = np2;251}252} while (n);253}254255static int256refcmp(char *r1, char *r2)257{258struct ref *r;259260LIST_FOREACH(r, &refs, next) {261if (!strcmp(r1, r->k1))262return (strcmp(r2, r->k2));263}264r = calloc(1, sizeof(*r));265r->k1 = strdup(r1);266r->k2 = strdup(r2);267LIST_INSERT_HEAD(&refs, r, next);268if (fsubs != NULL) {269fprintf(fsubs, "s/%s/%s/g\n", r1, r2);270fflush(fsubs);271}272return (0);273}274275static int compare_node2(struct node *n1, struct node *n2, int in);276277static int278compare_node(struct node *n1, struct node *n2, int in)279{280int i;281struct node *n1a, *n2a;282283i = strcmp(n1->name, n2->name);284if (i)285return (i);286if (n1->id && n2->id)287i = refcmp(n1->id, n2->id);288else if (n1->id || n2->id)289i = -1;290if (i)291return (i);292if (n1->ref && n2->ref)293i = refcmp(n1->ref, n2->ref);294else if (n1->ref || n2->ref)295i = -1;296if (i)297return (i);298if (!strcmp(n1->name, "ref"))299i = refcmp(sbuf_data(n1->cont), sbuf_data(n2->cont));300else301i = strcmp(sbuf_data(n1->cont), sbuf_data(n2->cont));302if (i)303return (1);304n1a = LIST_FIRST(&n1->children);305n2a = LIST_FIRST(&n2->children);306for (;;) {307if (n1a == NULL && n2a == NULL)308return (0);309if (n1a != NULL && n2a == NULL) {310printf("1>");311indent(in);312print_node(n1a);313printf("2>\n");314return (1);315}316if (n1a == NULL && n2a != NULL) {317printf("1>\n");318printf("2>");319indent(in);320print_node(n2a);321return (1);322}323i = compare_node2(n1a, n2a, in + 2);324if (i)325return (1);326n1a = LIST_NEXT(n1a, siblings);327n2a = LIST_NEXT(n2a, siblings);328}329return (0);330}331332static int333compare_node2(struct node *n1, struct node *n2, int in)334{335int i;336337i = compare_node(n1, n2, in);338if (i) {339printf("1>");340indent(in);341print_node(n1);342printf("2>");343indent(in);344print_node(n2);345}346return (i);347}348349350351int352main(int argc, char **argv)353{354struct mytree *t1, *t2;355int i;356357fsubs = fopen("_.subs", "w");358setbuf(stdout, NULL);359setbuf(stderr, NULL);360if (argc != 3)361errx(1, "usage: %s file1 file2", argv[0]);362363t1 = dofile(argv[1]);364if (t1 == NULL)365errx(2, "XML parser error on file %s", argv[1]);366sort_node(t1->top);367t2 = dofile(argv[2]);368if (t2 == NULL)369errx(2, "XML parser error on file %s", argv[2]);370sort_node(t2->top);371i = compare_node(t1->top, t2->top, 0);372return (i);373}374375376377