|
|
1.1 ! root 1: static char *rcsid = "$Header$"; ! 2: /* ! 3: * pdiff - differential project comparator ! 4: * ! 5: * Author: Peter J. Nicklin ! 6: */ ! 7: #include <stdio.h> ! 8: #include "getarg.h" ! 9: #include "macro.h" ! 10: #include "null.h" ! 11: #include "path.h" ! 12: #include "pdb.h" ! 13: #include "pdtyp.h" ! 14: #include "pld.h" ! 15: #include "ptree.h" ! 16: #include "spms.h" ! 17: #include "yesno.h" ! 18: ! 19: char **NARGV; /* new argument list */ ! 20: char *PGN = "pdiff"; /* program name */ ! 21: int EXECUTE = YES; /* execute command? */ ! 22: int NARGI = 0; /* new argument list index */ ! 23: int RECURSIVE = 0; /* recursively compare projects */ ! 24: PDTYP PDIRTYP; /* project directory type labels list */ ! 25: ! 26: main(argc, argv) ! 27: int argc; ! 28: char **argv; ! 29: { ! 30: extern int PPDEBUG; /* project pathname debug flag */ ! 31: char p1[PPATHSIZE]; /* project pathname buffer */ ! 32: char p2[PPATHSIZE]; /* project pathname buffer */ ! 33: char *strcpy(); /* string copy */ ! 34: int balance(); /* balance PDIR structs */ ! 35: int diffdir(); /* compare directories or files */ ! 36: int diffproject(); /* compare projects */ ! 37: int pdtparse(); /* parse boolean type label expr */ ! 38: int read_path(); /* read project or regular pathname */ ! 39: int status = 0; /* exit status */ ! 40: PATH pb1; /* pathname struct buffer 1 */ ! 41: PATH pb2; /* pathname struct buffer 2 */ ! 42: unsigned long pathtyp1; /* type of pathname 1 */ ! 43: unsigned long pathtyp2; /* type of pathname 2 */ ! 44: ! 45: NARGV = argv; ! 46: NARGV[NARGI++] = "diff"; ! 47: ! 48: { ! 49: register char *s; /* option pointer */ ! 50: while (--argc > 0 && **++argv == '-') ! 51: { ! 52: for (s = argv[0]+1; *s != '\0'; s++) ! 53: switch (*s) ! 54: { ! 55: case 'D': ! 56: PPDEBUG = YES; ! 57: break; ! 58: case 'T': ! 59: if (pdtparse(GETARG(s), &PDIRTYP) == NO) ! 60: status = 1; ! 61: goto endfor; ! 62: case 'r': ! 63: RECURSIVE++; ! 64: break; ! 65: case 'x': ! 66: EXECUTE = NO; ! 67: break; ! 68: default: ! 69: NARGV[NARGI++] = *argv; ! 70: break; ! 71: } ! 72: endfor: continue; ! 73: } ! 74: } ! 75: if (status == 1 || argc < 2) ! 76: { ! 77: warn("usage: pdiff [-rx] [-T typexpr] [diff options] p1 p2"); ! 78: exit(2); ! 79: } ! 80: ! 81: strcpy(p1, argv[0]); ! 82: strcpy(p2, argv[1]); ! 83: NARGV[NARGI+2] = NULL; ! 84: ! 85: if (read_path(p1, &pb1) == NO || read_path(p2, &pb2) == NO) ! 86: exit(2); ! 87: ! 88: pathtyp1 = (pb1.p_mode & P_IFMT); ! 89: pathtyp2 = (pb2.p_mode & P_IFMT); ! 90: ! 91: if (pathtyp1 == P_IFPROOT || pathtyp1 == P_IFHOME) ! 92: { ! 93: if (pathtyp2 == P_IFPROOT || pathtyp2 == P_IFHOME) ! 94: status = diffproject(p1, pb1.p_path, p2, pb2.p_path); ! 95: else if (balance(p1, &pb1, &pb2) == NO) ! 96: exit(2); ! 97: else ! 98: status = diffdir(p1, pb1.p_path, p2, pb2.p_path); ! 99: } ! 100: else if (pathtyp2 == P_IFPROOT || pathtyp2 == P_IFHOME) ! 101: { ! 102: if (balance(p2, &pb2, &pb1) == NO) ! 103: exit(2); ! 104: else ! 105: status = diffdir(p1, pb1.p_path, p2, pb2.p_path); ! 106: } ! 107: else { ! 108: status = diffdir(p1, pb1.p_path, p2, pb2.p_path); ! 109: } ! 110: ! 111: if (status > 1) ! 112: status = 2; ! 113: exit(status); ! 114: } ! 115: ! 116: ! 117: ! 118: /* ! 119: * balance() balances a PATH struct given a project and a directory or file. ! 120: * If a regular directory or file, then it is assumed to be relative to the ! 121: * current working project directory. Returns NO if balancing fails, otherwise ! 122: * YES. The project pathname p1 is updated to reflect the balancing. ! 123: */ ! 124: balance(p1, pb1, pb2) ! 125: char *p1; /* we know this is a project root dir */ ! 126: PATH *pb1; /* project root directory buffer */ ! 127: PATH *pb2; /* (project) directory or file buffer */ ! 128: { ! 129: char *pathcat(); /* regular pathname concatenation */ ! 130: char *ppathcat(); /* project pathname concatenation */ ! 131: int getcpd(); /* get current working project dir */ ! 132: int read_path(); /* read project or regular pathname */ ! 133: PATH cpathbuf; /* current pathname struct buffer */ ! 134: ! 135: if ((pb2->p_mode&P_IFMT) == P_IFPDIR) ! 136: { ! 137: ppathcat(p1, p1, pb2->p_alias); ! 138: return(read_path(p1, pb1)); ! 139: } ! 140: else if (*pb2->p_path == _RDIRC || getcpd(&cpathbuf) != 1) ! 141: { ! 142: warn("don't know which project directory to use in %s", p1); ! 143: return(NO); ! 144: } ! 145: else { ! 146: ppathcat(p1, p1, cpathbuf.p_alias); ! 147: pathcat(p1, p1, pb2->p_path); ! 148: return(read_path(p1, pb1)); ! 149: } ! 150: } ! 151: ! 152: ! 153: ! 154: /* ! 155: * diffdir() compares two directories or files. Returns whatever diff() ! 156: * returns. ! 157: */ ! 158: diffdir(pp1, d1, pp2, d2) ! 159: char *pp1; /* project pathname */ ! 160: char *d1; /* directory or file pathname */ ! 161: char *pp2; /* project pathname */ ! 162: char *d2; /* directory or file pathname */ ! 163: { ! 164: static int have_printed; /* has printing already been done? */ ! 165: int diff(); /* fork diff program */ ! 166: int iargi; /* argument index */ ! 167: ! 168: if (have_printed) ! 169: putchar('\n'); ! 170: have_printed = 1; ! 171: printf("==> "); ! 172: for (iargi = 0; iargi < NARGI; iargi++) ! 173: printf("%s ", NARGV[iargi]); ! 174: printf("%s %s <==\n", pp1, pp2); ! 175: fflush(stdout); ! 176: ! 177: if (EXECUTE == NO) ! 178: return(0); ! 179: ! 180: NARGV[NARGI] = d1; ! 181: NARGV[NARGI+1] = d2; ! 182: return(diff(NARGV)); ! 183: } ! 184: ! 185: ! 186: ! 187: /* ! 188: * diffproject() compares two projects, recursively if necessary. Returns ! 189: * 0 if no differences, 1 if some, 2 if trouble. ! 190: */ ! 191: diffproject(pp1, p1, pp2, p2) ! 192: char *pp1; /* project pathname */ ! 193: char *p1; /* project root directory pathname */ ! 194: char *pp2; /* project pathname */ ! 195: char *p2; /* project root directory pathname */ ! 196: { ! 197: int closepdb(); /* close database */ ! 198: int diffpdtree(); /* diff project directory tree */ ! 199: int diffptree(); /* diff tree of projects */ ! 200: int errpdb(); /* print database error message */ ! 201: int pdtmatch(); /* match project dir type label expr */ ! 202: int status = 0; /* return status */ ! 203: PATH *pd; /* pathname struct pointer */ ! 204: PATH *readpld(); /* read project link directory entry */ ! 205: PDB *openpdb(); /* open database */ ! 206: PDB *pldp; /* project link directory stream */ ! 207: PTREE *proot; /* root of project tree */ ! 208: PTREE *pdroot; /* root of project directory tree */ ! 209: PTREE *ptree(); /* search and insert in proj dir tree */ ! 210: void ptreerm(); /* remove project directory tree */ ! 211: ! 212: proot = NULL; ! 213: pdroot = NULL; ! 214: ! 215: /* read PLDNAME project link directory belonging to p1 */ ! 216: if ((pldp = openpdb(PLDNAME, p1, "r")) == NULL) ! 217: { ! 218: errpdb((PDB *) NULL); ! 219: return(2); ! 220: } ! 221: while ((pd = readpld(pldp)) != NULL) ! 222: { ! 223: if (EQUAL(pd->p_alias, PARENTPROJECT)) ! 224: continue; ! 225: else if (EQUAL(pd->p_alias, CURPROJECT)) ! 226: { ! 227: if (PDIRTYP.pfxsize==0 || pdtmatch(&PDIRTYP,pd->p_type)==YES) ! 228: pdroot = ptree(pdroot, "", pd->p_path, CNULL); ! 229: } ! 230: else if (pd->p_mode == P_IFPROOT) ! 231: { ! 232: if (RECURSIVE) ! 233: proot = ptree(proot, pd->p_alias, pd->p_path, CNULL); ! 234: } ! 235: else if (PDIRTYP.pfxsize==0 || pdtmatch(&PDIRTYP,pd->p_type)==YES) ! 236: pdroot = ptree(pdroot, pd->p_alias, pd->p_path, CNULL); ! 237: } ! 238: closepdb(pldp); ! 239: ! 240: /* read PLDNAME project link directory belonging to p2 */ ! 241: if ((pldp = openpdb(PLDNAME, p2, "r")) == NULL) ! 242: { ! 243: errpdb((PDB *) NULL); ! 244: return(2); ! 245: } ! 246: while ((pd = readpld(pldp)) != NULL) ! 247: { ! 248: if (EQUAL(pd->p_alias, PARENTPROJECT)) ! 249: continue; ! 250: else if (EQUAL(pd->p_alias, CURPROJECT)) ! 251: { ! 252: if (PDIRTYP.pfxsize==0 || pdtmatch(&PDIRTYP,pd->p_type)==YES) ! 253: pdroot = ptree(pdroot, "", CNULL, pd->p_path); ! 254: } ! 255: else if (pd->p_mode == P_IFPROOT) ! 256: { ! 257: if (RECURSIVE) ! 258: proot = ptree(proot, pd->p_alias, CNULL, pd->p_path); ! 259: } ! 260: else if (PDIRTYP.pfxsize==0 || pdtmatch(&PDIRTYP,pd->p_type)==YES) ! 261: pdroot = ptree(pdroot, pd->p_alias, CNULL, pd->p_path); ! 262: } ! 263: closepdb(pldp); ! 264: ! 265: /* diff project directory tree */ ! 266: status |= diffpdtree(pdroot, pp1, pp2); ! 267: ptreerm(pdroot); ! 268: ! 269: /* diff subprojects */ ! 270: status |= diffptree(proot, pp1, pp2); ! 271: ptreerm(proot); ! 272: ! 273: return(status); ! 274: } ! 275: ! 276: ! 277: ! 278: /* ! 279: * diffpdtree() compares project directories in a project directory tree. ! 280: */ ! 281: diffpdtree(p, pp1, pp2) ! 282: PTREE *p; /* current node in project dir tree */ ! 283: char *pp1; /* project pathname */ ! 284: char *pp2; /* project pathname */ ! 285: { ! 286: char ppathbuf1[PPATHSIZE]; /* project pathname buffer */ ! 287: char ppathbuf2[PPATHSIZE]; /* project pathname buffer */ ! 288: char *ppathcat(); /* project pathname concantenation */ ! 289: int diffdir(); /* compare directories or files */ ! 290: int status = 0; /* return status */ ! 291: void printonly(); /* print "only in project ..." mesg */ ! 292: ! 293: if (p == NULL) ! 294: return(0); ! 295: status |= diffpdtree(p->left, pp1, pp2); ! 296: if (p->pd1 == NULL) ! 297: printonly(pp2, p->alias); ! 298: else if (p->pd2 == NULL) ! 299: printonly(pp1, p->alias); ! 300: else { ! 301: ppathcat(ppathbuf1, pp1, p->alias); ! 302: ppathcat(ppathbuf2, pp2, p->alias); ! 303: status |= diffdir(ppathbuf1, p->pd1, ppathbuf2, p->pd2); ! 304: } ! 305: status |= diffpdtree(p->right, pp1, pp2); ! 306: return(status); ! 307: } ! 308: ! 309: ! 310: ! 311: /* ! 312: * diffptree() compares projects in a project tree. ! 313: */ ! 314: diffptree(p, pp1, pp2) ! 315: PTREE *p; /* current node in project tree */ ! 316: char *pp1; /* project pathname */ ! 317: char *pp2; /* project pathname */ ! 318: { ! 319: char ppathbuf1[PPATHSIZE]; /* project pathname buffer */ ! 320: char ppathbuf2[PPATHSIZE]; /* project pathname buffer */ ! 321: char *ppathcat(); /* project pathname concantenation */ ! 322: int diffproject(); /* compare projects */ ! 323: int status = 0; /* return status */ ! 324: void printonly(); /* print "only in project ..." mesg */ ! 325: ! 326: if (p == NULL) ! 327: return(0); ! 328: status |= diffptree(p->left, pp1, pp2); ! 329: if (p->pd1 == NULL) ! 330: printonly(pp2, p->alias); ! 331: else if (p->pd2 == NULL) ! 332: printonly(pp1, p->alias); ! 333: else { ! 334: ppathcat(ppathbuf1, pp1, p->alias); ! 335: ppathcat(ppathbuf2, pp2, p->alias); ! 336: status |= diffproject(ppathbuf1, p->pd1, ppathbuf2, p->pd2); ! 337: } ! 338: status |= diffptree(p->right, pp1, pp2); ! 339: return(status); ! 340: } ! 341: ! 342: ! 343: ! 344: /* ! 345: * printonly() prints "only in project ..." message. ! 346: */ ! 347: void ! 348: printonly(project, pdirname) ! 349: char *project; /* project pathname */ ! 350: char *pdirname; /* unique project directory */ ! 351: { ! 352: printf("Only in project %s: %s\n", project, ! 353: (*pdirname == '\0') ? CURPROJECT : pdirname); ! 354: fflush(stdout); ! 355: } ! 356: ! 357: ! 358: ! 359: /* ! 360: * read_path() loads a PATH struct given a regular or project pathname. ! 361: * Returns integer NO if an invalid pathname or non-existent target, ! 362: * otherwise YES. ! 363: */ ! 364: read_path(pathname, pb) ! 365: char *pathname; /* regular or project pathname */ ! 366: PATH *pb; /* pathname struct buffer */ ! 367: { ! 368: int readpath(); /* read project or regular pathname */ ! 369: ! 370: if (readpath(pathname, pb) == -1 || (pb->p_mode & P_IFMT) == P_IFNEW) ! 371: { ! 372: patherr(pathname); ! 373: return(NO); ! 374: } ! 375: return(YES); ! 376: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.