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