|
|
1.1 ! root 1: /* sdiff [-l] [-s] [-w #] [-o output] file1 file2 ! 2: * does side by side diff listing ! 3: * -l leftside only for identical lines ! 4: * -s silent only print differences ! 5: * -w # width of output ! 6: * -o output interactive creation of new output ! 7: commands: ! 8: s silent; do not print identical lines ! 9: v turn off silent ! 10: l copy left side to output ! 11: r copy right side to output ! 12: e l call ed with left side ! 13: e r call ed with right side ! 14: e b call ed with cat of left and right ! 15: e call ed with empty file ! 16: q exit from program ! 17: ! 18: * functions: ! 19: cmd decode diff commands ! 20: put1 output left side ! 21: put2 output right side ! 22: putmid output gutter ! 23: putline output n chars to indicated file ! 24: getlen calculate length of strings with tabs ! 25: cmdin read and process interactive cmds ! 26: cpp copy from file to file ! 27: edit call ed with file ! 28: */ ! 29: #define LMAX 200 ! 30: #define BMAX 256 ! 31: #define STDOUT 1 ! 32: #define WGUTTER 6 ! 33: #define WLEN 20 /* WGUTTER * 2 + WGUTTER + 2 */ ! 34: #define PROMPT '%' ! 35: #include <stdio.h> ! 36: #include <ctype.h> ! 37: #include <signal.h> ! 38: #include <sys/types.h> ! 39: #include <sys/stat.h> ! 40: ! 41: char BLANKS[100] = " "; ! 42: char GUTTER[WGUTTER] = " "; ! 43: char *DIFF = "diff -b "; ! 44: char diffcmd[BMAX]; ! 45: char inbuf[10]; ! 46: ! 47: int llen = 130; /* Default maximum line length written out */ ! 48: int hlen; /* Half line length with space for gutter */ ! 49: int len1; /* Calculated length of left side */ ! 50: int nchars; /* Number of characters in left side - used for tab expansion */ ! 51: char change = ' '; ! 52: int leftonly = 0; /* if set print left side only for identical lines */ ! 53: int silent = 0; /* if set do not print identical lines */ ! 54: int midflg = 0; /* set after middle was output */ ! 55: ! 56: char *pgmname; ! 57: ! 58: char *file1; ! 59: FILE *fdes1; ! 60: char buf1[BMAX+1]; ! 61: ! 62: char *file2; ! 63: FILE *fdes2; ! 64: char buf2[BMAX+1]; ! 65: ! 66: FILE *diffdes; ! 67: char diffbuf[LMAX+1]; ! 68: ! 69: int oflag; ! 70: char *ofile; ! 71: FILE *odes; ! 72: ! 73: char *ltemp; ! 74: FILE *left; ! 75: ! 76: char *rtemp; ! 77: FILE *right; ! 78: ! 79: FILE *tempdes; ! 80: char *temp; ! 81: ! 82: int from1, to1, from2, to2; /* decoded diff cmd- left side from to; right side from, to */ ! 83: int num1, num2; /*line count for left side file and right */ ! 84: ! 85: char *mktemp(); ! 86: FILE *popen(); ! 87: char *filename(); ! 88: char *malloc(); ! 89: ! 90: main(argc,argv) ! 91: int argc; ! 92: char **argv; ! 93: { ! 94: extern onintr(); ! 95: int com; ! 96: register int n1, n2, n; ! 97: ! 98: signal(SIGHUP,onintr); ! 99: signal(SIGINT,onintr); ! 100: signal(SIGPIPE,onintr); ! 101: signal(SIGTERM,onintr); ! 102: pgmname = argv[0]; ! 103: while(--argc>1 && **++argv == '-'){ ! 104: switch(*++*argv){ ! 105: ! 106: case 'w': ! 107: /* -w# instead of -w # */ ! 108: if(*++*argv) ! 109: llen = atoi(*argv); ! 110: else { ! 111: argc--; ! 112: llen = atoi(*++argv); ! 113: } ! 114: if(llen < WLEN) ! 115: error("Wrong line length %s",*argv); ! 116: if(llen > LMAX) ! 117: llen = LMAX; ! 118: break; ! 119: ! 120: case 'l': ! 121: leftonly++; ! 122: break; ! 123: ! 124: case 's': ! 125: silent++; ! 126: break; ! 127: case 'o': ! 128: oflag++; ! 129: argc--; ! 130: ofile = *++argv; ! 131: break; ! 132: default: ! 133: error("Illegal argument: %s",*argv); ! 134: } ! 135: } ! 136: if(argc != 2){ ! 137: fprintf(stderr,"Usage: sdiff [-l] [-s] [-o output] [-w #] file1 file2\n"); ! 138: exit(1); ! 139: } ! 140: ! 141: file1 = *argv++; ! 142: file2 = *argv; ! 143: file1=filename(file1,file2); ! 144: file2=filename(file2,file1); ! 145: hlen = (llen - WGUTTER +1)/2; ! 146: ! 147: if((fdes1 = fopen(file1,"r")) == NULL) ! 148: error("Cannot open: %s",file1); ! 149: ! 150: if((fdes2 = fopen(file2,"r")) == NULL) ! 151: error("Cannot open: %s",file2); ! 152: ! 153: if(oflag){ ! 154: if(!temp) ! 155: temp = mktemp("/tmp/sdiffXXXXX"); ! 156: ltemp = mktemp("/tmp/sdifflXXXXX"); ! 157: if((left = fopen(ltemp,"w")) == NULL) ! 158: error("Cannot open temp %s",ltemp); ! 159: rtemp = mktemp("/tmp/sdiffrXXXXX"); ! 160: if((right = fopen(rtemp,"w")) == NULL) ! 161: error("Cannot open temp file %s",rtemp); ! 162: if((odes = fopen(ofile,"w")) == NULL) ! 163: error("Cannot open output %s",ofile); ! 164: } ! 165: /* Call DIFF command */ ! 166: strcpy(diffcmd,DIFF); ! 167: strcat(diffcmd,file1); ! 168: strcat(diffcmd," "); ! 169: strcat(diffcmd,file2); ! 170: diffdes = popen(diffcmd,"r"); ! 171: ! 172: num1 = num2 = 0; ! 173: ! 174: /* Read in diff output and decode commands ! 175: * "change" is used to determine character to put in gutter ! 176: * num1 and num2 counts the number of lines in file1 and 2 ! 177: */ ! 178: ! 179: n = 0; ! 180: while(fgets(diffbuf,LMAX,diffdes) != NULL){ ! 181: change = ' '; ! 182: com = cmd(diffbuf); ! 183: ! 184: /* handles all diff output that is not cmd ! 185: lines starting with <, >, ., --- */ ! 186: if(com == 0) ! 187: continue; ! 188: ! 189: /* Catch up to from1 and from2 */ ! 190: n1=from1-num1; ! 191: n2=from2-num2; ! 192: n= n1>n2?n2:n1; ! 193: if(com =='c' && n!=0) ! 194: n--; ! 195: if(silent) ! 196: fputs(diffbuf,stdout); ! 197: while(n--){ ! 198: put1(); ! 199: put2(); ! 200: if(!silent) ! 201: putc('\n',stdout); ! 202: midflg = 0; ! 203: } ! 204: ! 205: /* Process diff cmd */ ! 206: switch(com){ ! 207: ! 208: case 'a': ! 209: change = '>'; ! 210: while(num2<to2){ ! 211: put2(); ! 212: putc('\n',stdout); ! 213: midflg = 0; ! 214: } ! 215: break; ! 216: ! 217: case 'd': ! 218: change = '<'; ! 219: while(num1<to1){ ! 220: put1(); ! 221: putc('\n',stdout); ! 222: midflg = 0; ! 223: } ! 224: break; ! 225: ! 226: case 'c': ! 227: n1 = to1-from1; ! 228: n2 = to2-from2; ! 229: n = n1>n2?n2:n1; ! 230: change = '|'; ! 231: do { ! 232: put1(); ! 233: put2(); ! 234: putc('\n',stdout); ! 235: midflg = 0; ! 236: } while(n--); ! 237: ! 238: change = '<'; ! 239: while(num1<to1){ ! 240: put1(); ! 241: putc('\n',stdout); ! 242: midflg = 0; ! 243: } ! 244: ! 245: change = '>'; ! 246: while(num2<to2){ ! 247: put2(); ! 248: putc('\n',stdout); ! 249: midflg = 0; ! 250: } ! 251: break; ! 252: ! 253: default: ! 254: fprintf(stderr,"cmd not found%c\n",cmd); ! 255: break; ! 256: } ! 257: ! 258: if(oflag==1 && com!=0){ ! 259: cmdin(); ! 260: if((left = fopen(ltemp,"w")) == NULL) ! 261: error("main: Cannot open temp %s",ltemp); ! 262: if((right = fopen(rtemp,"w")) == NULL) ! 263: error("main: Cannot open temp %s",rtemp); ! 264: } ! 265: } ! 266: /* put out remainder of input files */ ! 267: while(put1()){ ! 268: put2(); ! 269: if(!silent) ! 270: putc('\n',stdout); ! 271: midflg = 0; ! 272: } ! 273: if(odes) ! 274: fclose(odes); ! 275: remove(); ! 276: exit(0); ! 277: } ! 278: ! 279: put1() ! 280: { ! 281: /* len1 = length of left side */ ! 282: /* nchars = num of chars including tabs */ ! 283: ! 284: ! 285: if(fgets(buf1,BMAX,fdes1) != NULL){ ! 286: len1 = getlen(0,buf1); ! 287: if((!silent || change != ' ') && len1 != 0) ! 288: putline(stdout,buf1,nchars); ! 289: ! 290: if(oflag){ ! 291: /*put left side either to output file ! 292: if identical to right ! 293: or left temp file if not */ ! 294: ! 295: if(change == ' ') ! 296: putline(odes,buf1,strlen(buf1)); ! 297: else ! 298: putline(left,buf1,strlen(buf1)); ! 299: } ! 300: if(change != ' ') ! 301: putmid(1); ! 302: num1++; ! 303: return(1); ! 304: } else ! 305: return(0); ! 306: } ! 307: ! 308: put2() ! 309: { ! 310: ! 311: if(fgets(buf2,BMAX,fdes2) != NULL){ ! 312: getlen((hlen+WGUTTER)%8,buf2); ! 313: ! 314: /* if the left and right are different they are always ! 315: printed. ! 316: If the left and right are identical ! 317: right is only printed if leftonly is not specified ! 318: or silent mode is not specified ! 319: or the right contains other than white space (len1 !=0) ! 320: */ ! 321: if(change != ' '){ ! 322: ! 323: /* put right side to right temp file only ! 324: because left side was written to output for ! 325: identical lines */ ! 326: ! 327: if(oflag) ! 328: putline(right,buf2,strlen(buf2)); ! 329: ! 330: if(midflg == 0) ! 331: putmid(1); ! 332: putline(stdout,buf2,nchars); ! 333: } else ! 334: if(!silent && !leftonly && len1!=0) { ! 335: if(midflg == 0) ! 336: putmid(1); ! 337: putline(stdout,buf2,nchars); ! 338: } ! 339: num2++; ! 340: len1 = 0; ! 341: return(1); ! 342: } else { ! 343: len1 = 0; ! 344: return(0); ! 345: } ! 346: } ! 347: ! 348: putline(file,start,num) ! 349: FILE *file; ! 350: char *start; ! 351: int num; ! 352: { ! 353: ! 354: register char *cp, *end; ! 355: ! 356: cp = start; ! 357: end = cp + num; ! 358: while(cp < end) ! 359: putc(*cp++,file); ! 360: } ! 361: ! 362: cmd(start) ! 363: char *start; ! 364: { ! 365: ! 366: char *cp, *cps; ! 367: int com; ! 368: ! 369: if(*start == '>' || *start == '<' || *start == '-' || *start == '.') ! 370: return(0); ! 371: ! 372: cp = cps = start; ! 373: while(isdigit(*cp)) ! 374: cp++; ! 375: from1 = atoi(cps); ! 376: to1 = from1; ! 377: if(*cp == ','){ ! 378: cp++; ! 379: cps = cp; ! 380: while(isdigit(*cp)) ! 381: cp++; ! 382: to1 = atoi(cps); ! 383: } ! 384: ! 385: com = *cp++; ! 386: cps = cp; ! 387: ! 388: while(isdigit(*cp)) ! 389: cp++; ! 390: from2 = atoi(cps); ! 391: to2 = from2; ! 392: if(*cp == ','){ ! 393: cp++; ! 394: cps = cp; ! 395: while(isdigit(*cp)) ! 396: cp++; ! 397: to2 = atoi(cps); ! 398: } ! 399: return(com); ! 400: } ! 401: ! 402: getlen(startpos,buffer) ! 403: char *buffer; ! 404: int startpos; ! 405: { ! 406: /* get the length of the string in buffer ! 407: * expand tabs to next multiple of 8 ! 408: */ ! 409: ! 410: register char *cp; ! 411: register int slen, tlen; ! 412: int notspace; ! 413: ! 414: nchars = 0; ! 415: notspace = 0; ! 416: tlen = startpos; ! 417: for(cp=buffer; *cp != '\n'; cp++){ ! 418: if(*cp == '\t'){ ! 419: slen = tlen; ! 420: tlen += 8 - (tlen%8); ! 421: if(tlen>=hlen) { ! 422: tlen= slen; ! 423: break; ! 424: } ! 425: nchars++; ! 426: }else{ ! 427: if(tlen>=hlen)break; ! 428: if(!isspace(*cp)) ! 429: notspace = 1; ! 430: tlen++; ! 431: nchars++; ! 432: } ! 433: } ! 434: return(notspace?tlen:0); ! 435: } ! 436: ! 437: putmid(bflag) ! 438: int bflag; ! 439: { ! 440: /* len1 set by getlen to the possibly truncated ! 441: * length of left side ! 442: * hlen is length of half line ! 443: */ ! 444: ! 445: ! 446: midflg = 1; ! 447: if(bflag) ! 448: putline(stdout,BLANKS,(hlen-len1)); ! 449: GUTTER[2] = change; ! 450: putline(stdout,GUTTER,5); ! 451: } ! 452: ! 453: error(s1,s2) ! 454: char *s1, *s2; ! 455: { ! 456: fprintf(stderr,"%s: ",pgmname); ! 457: fprintf(stderr,s1,s2); ! 458: putc('\n',stderr); ! 459: remove(); ! 460: exit(1); ! 461: } ! 462: ! 463: onintr() ! 464: { ! 465: remove(); ! 466: exit(1); ! 467: } ! 468: ! 469: remove() ! 470: { ! 471: if(ltemp) ! 472: unlink(ltemp); ! 473: if(rtemp) ! 474: unlink(rtemp); ! 475: if(temp) ! 476: unlink(temp); ! 477: } ! 478: ! 479: cmdin() ! 480: { ! 481: char *cp, *ename; ! 482: int notacc; ! 483: ! 484: fclose(left); ! 485: fclose(right); ! 486: notacc = 1; ! 487: while(notacc){ ! 488: putc(PROMPT,stdout); ! 489: cp = fgets(inbuf,10,stdin); ! 490: switch(*cp){ ! 491: ! 492: case 's': ! 493: silent = 1; ! 494: break; ! 495: ! 496: case 'v': ! 497: silent = 0; ! 498: break; ! 499: ! 500: case 'q': ! 501: remove(); ! 502: exit(0); ! 503: ! 504: case 'l': ! 505: cpp(ltemp,left,odes); ! 506: notacc = 0; ! 507: break; ! 508: ! 509: case 'r': ! 510: cpp(rtemp,right,odes); ! 511: notacc = 0; ! 512: break; ! 513: ! 514: case 'e': ! 515: while(*++cp == ' ') ! 516: ; ! 517: switch(*cp){ ! 518: case 'l': ! 519: case '<': ! 520: notacc = 0; ! 521: ename = ltemp; ! 522: edit(ename); ! 523: break; ! 524: ! 525: case 'r': ! 526: case '>': ! 527: notacc = 0; ! 528: ename = rtemp; ! 529: edit(ename); ! 530: break; ! 531: ! 532: case 'b': ! 533: case '|': ! 534: if((tempdes = fopen(temp,"w")) == NULL) ! 535: error("Cannot open temp file %s",temp); ! 536: cpp(ltemp,left,tempdes); ! 537: cpp(rtemp,right,tempdes); ! 538: fclose(tempdes); ! 539: notacc = 0; ! 540: ename = temp; ! 541: edit(ename); ! 542: break; ! 543: ! 544: case '\n': ! 545: if((tempdes=fopen(temp,"w")) == NULL) ! 546: error("Cannot open temp %s",temp); ! 547: fclose(tempdes); ! 548: notacc = 0; ! 549: ename = temp; ! 550: edit(ename); ! 551: break; ! 552: default: ! 553: fprintf(stderr,"Illegal command %s reenter\n",cp); ! 554: break; ! 555: } ! 556: if(notacc == 0) ! 557: cpp(ename,tempdes,odes); ! 558: break; ! 559: ! 560: default: ! 561: fprintf(stderr,"Illegal command reenter\n"); ! 562: break; ! 563: } ! 564: } ! 565: } ! 566: ! 567: cpp(from,fromdes,todes) ! 568: char *from; ! 569: FILE *fromdes,*todes; ! 570: { ! 571: char tempbuf[BMAX+1]; ! 572: ! 573: if((fromdes = fopen(from,"r")) == NULL) ! 574: error("cpp: Cannot open %s",from); ! 575: while((fgets(tempbuf,BMAX,fromdes) != NULL)) ! 576: fputs(tempbuf,todes); ! 577: fclose(fromdes); ! 578: } ! 579: ! 580: edit(file) ! 581: char *file; ! 582: { ! 583: int i, pid; ! 584: ! 585: int (*oldintr) (); ! 586: ! 587: switch(pid=fork()){ ! 588: ! 589: case -1: ! 590: error("Cannot fork",""); ! 591: case 0: ! 592: execl("/bin/ed", "ed", file, 0); ! 593: } ! 594: ! 595: oldintr = signal(SIGINT, SIG_IGN); /*ignore interrupts while in ed */ ! 596: while(pid != wait(&i)) ! 597: ; ! 598: signal(SIGINT,oldintr); /*restore previous interrupt proc */ ! 599: } ! 600: ! 601: char *filename(pa1, pa2) ! 602: char *pa1, *pa2; ! 603: { ! 604: register int c; ! 605: register char *a1, *b1, *a2; ! 606: struct stat stbuf; ! 607: a1 = pa1; ! 608: a2 = pa2; ! 609: if(stat(a1,&stbuf)!=-1 && ((stbuf.st_mode&S_IFMT)==S_IFDIR)) { ! 610: b1 = pa1 = malloc(100); ! 611: while(*b1++ = *a1++) ; ! 612: b1[-1] = '/'; ! 613: a1 = b1; ! 614: while(*a1++ = *a2++) ! 615: if(*a2 && *a2!='/' && a2[-1]=='/') ! 616: a1 = b1; ! 617: } ! 618: else if(a1[0] == '-' && a1[1] == 0 && temp ==0) { ! 619: pa1 = temp = mktemp("/tmp/sdiffXXXXX"); ! 620: if((tempdes = fopen(temp,"w")) == NULL) ! 621: error("Cannot open temp %s",temp); ! 622: while((c=getc(stdin)) != EOF) ! 623: putc(c,tempdes); ! 624: fclose(tempdes); ! 625: } ! 626: return(pa1); ! 627: } ! 628:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.