home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume1 / diffc < prev    next >
Internet Message Format  |  1986-11-30  |  7KB

  1. Date: Wed, 23 Jan 85 14:01:24 est
  2. From: john (John Nelson)
  3. Subject: contextual diff on Bell systems
  4.  
  5. This is a program for all those poor slobs that have to deal with UNIX systems
  6. that don't have a -c option on their diff.  This program eliminates the last
  7. excuse for bug fixes to be in standard diff format (especially since "patch"
  8. works so much more reliably on diffc format).
  9.  
  10. Send bug reports to:  John Nelson  (decvax!genrad!john).
  11.  
  12. ------------------- cut here -------------------------
  13. : Run this shell script with "sh" not "csh"
  14. PATH=:/bin:/usr/bin:/usr/ucb
  15. export PATH
  16. echo 'x - diffc.1'
  17. sed 's/^X//' <<'//go.sysin dd *' >diffc.1
  18. X.TH DIFFC l  "22 January 1985"
  19. X.UC 4
  20. X.SH NAME
  21. diffc \- context diff for systems whose diff has no \-c option
  22. X.SH SYNOPSIS
  23. X.B diff
  24. [
  25. X.B \-options
  26. ] [
  27. X.B \-r
  28. ] [
  29. \fB\-c#
  30. ] file1 file2
  31. X.SH DESCRIPTION
  32. X.I Diffc
  33. is a front end for
  34. X.IR diff (1)
  35. which outputs contextual diff format like Berkeley system's "diff -c".
  36. X.I Diffc
  37. will actually run
  38. X.I diff
  39. as a subprocess, and will merge the "standard" diff format with lines from
  40. both files.
  41. As far as I can tell, the output is exactly the same as that of a diff with
  42. the -c option.
  43. X.PP
  44. The -c# option allows the amount of context to be specified.
  45. The default is 3 lines above and below the change.
  46. I find that -c1 works well for updates intended for use with patch(1).
  47. Any other options specified on the command line are passed along to
  48. X.IR diff .
  49. Note that most options to
  50. X.I diff
  51. should NOT be specified when using 
  52. X.IR diffc ,
  53. but the capability is there, nevertheless.
  54. X.PP
  55. The output format begins with identification of the files involved and
  56. their creation dates and then each change is separated
  57. by a line with a dozen *'s.
  58. The lines removed from
  59. X.I file1
  60. are marked with `\(mi'; those added to
  61. X.I file2
  62. are marked `+'.  Lines which are changed from one
  63. file to the other are marked in both files with `!'.
  64. X.PP
  65. No claim is made that the algoritm used is either fast or bulletproof.
  66. It was only intended for standard text files with lines shorter than
  67. BUFSIZ.
  68. XFseek is used extensively to move around in the files, precluding the
  69. use of standard input as one of the files to be diff'ed.
  70. X.SH "SEE ALSO"
  71. cmp(1), diff(1), comm(1), patch(1)
  72. X.SH DIAGNOSTICS
  73. Exit status is nonzero to indicate problems.
  74. X.SH BUGS
  75. This program is a hack, and should really be incorporated as part of "diff"
  76. by Bell.
  77. X.SH AUTHOR
  78. John P. Nelson
  79. //go.sysin dd *
  80. echo 'x - diffc.c'
  81. sed 's/^X//' <<'//go.sysin dd *' >diffc.c
  82. X/* diffc.c - provide diff -c output on non-berkeley systems
  83. **
  84. ** cc -o diffc diffc.c
  85. **
  86. **  or for V7 type systems
  87. **
  88. ** cc -o diffc -DV7 diffc.c
  89. */
  90.  
  91. #include <stdio.h>
  92. #include <ctype.h>
  93. #include <sys/types.h>
  94. #include <sys/stat.h>
  95.  
  96. #ifdef V7
  97. #define strchr index
  98. #include <string.h>        /* BEZERKELY 4.2 is strings.h */
  99. #else
  100. #include <string.h>
  101. #endif
  102.  
  103. #define WIDTH 3
  104. #define SEPERATE "***************"
  105. #define max(_a,_b) (((_a)>(_b))?(_a):(_b))
  106.  
  107. XFILE *diff, *fd1, *fd2;
  108. int line1 = 1, line2 = 1;
  109. long off1, off2;
  110. char buffer[BUFSIZ];
  111. int width = WIDTH;
  112.  
  113. char *ctime();
  114. XFILE *popen();
  115.  
  116. main(argc, argv)
  117. int argc;
  118. char **argv;
  119.     {
  120.     int i;
  121.     struct stat statbuf;
  122.  
  123.     strcpy(buffer, "diff");
  124.     /* skip over minus args - they must be for diff */
  125.     for (i = 1; i < argc; ++i)
  126.     {
  127.     if (argv[i][0] != '-')
  128.         break;
  129.     else if (!strncmp(argv[i], "-c", 2))
  130.         {
  131.         width = atoi(argv[i]+2);
  132.         if (width < 1 || width > 20)
  133.         width = WIDTH;
  134.         }
  135.     else
  136.         {
  137.         strcat(buffer, " ");
  138.         strcat(buffer, argv[i]);
  139.         }
  140.     }
  141.     if (argc - i != 2)
  142.     {
  143.     fprintf(stderr, "Usage: %s [-minusargs] file1 file2\n", argv[0]);
  144.     exit(1);
  145.     }
  146.     strcat(buffer, " ");
  147.     strcat(buffer, argv[i]);
  148.     strcat(buffer, " ");
  149.     strcat(buffer, argv[i+1]);
  150.  
  151.     fd1 = fopen(argv[i], "r");
  152.     fd2 = fopen(argv[i+1], "r");
  153.  
  154.     if (!fd1 || !fd2)
  155.     {
  156.     fprintf(stderr, "%s: File not accessible\n", argv[0]);
  157.     exit(1);
  158.     }
  159.  
  160.     if ((diff = popen(buffer, "r")) == NULL)
  161.     {
  162.     fprintf(stderr, "%s: Cant find diff\n", argv[0]);
  163.     exit(1);
  164.     }
  165.  
  166.     stat(argv[i], &statbuf);
  167.     printf("*** %s\t%s", argv[i], ctime(&(statbuf.st_mtime)));
  168.     stat(argv[i+1], &statbuf);
  169.     printf("--- %s\t%s", argv[i+1], ctime(&(statbuf.st_mtime)));
  170.  
  171.     dodiffs();
  172.     }
  173.  
  174. dodiffs()
  175.     {
  176.     char line[BUFSIZ];
  177.     char type, disp;
  178.     int from1, to1, from2, to2;
  179.     int dfrom1, dto1, dfrom2, dto2;
  180.     int i;
  181.     int skip;
  182.  
  183.     while (fgets(line, sizeof(line), diff))
  184.     {
  185.     parse(line, &from1, &from2, &to1, &to2, &type);
  186.  
  187.     dfrom1 = max(from1 - width, 1);
  188.     dfrom2 = max(from2 - width, 1);
  189.  
  190.     line1 = toline(fd1, line1, dfrom1);
  191.     line2 = toline(fd2, line2, dfrom2);
  192.  
  193.     off1 = ftell(fd1);
  194.     off2 = ftell(fd2);
  195.  
  196.     dto1 = checkline(fd1, line1, to1 + width);
  197.     dto2 = checkline(fd2, line2, to2 + width);
  198.  
  199.     /* checkline moved the position, so seek back to last point */
  200.     fseek(fd1, off1, 0);
  201.     fseek(fd2, off2, 0);
  202.  
  203.     printf("*** %d,%d\n", dfrom1, dto1);
  204.     for (i = dfrom1; i <= dto1; ++i)
  205.         {
  206.         if (!fgets(buffer, sizeof(buffer), fd1))
  207.         break;
  208.         disp = ' ';
  209.         if (i >= from1 && i <= to1)
  210.         disp = (type == 'c') ? '!': '-';
  211.         printf("%c %s", disp, buffer);
  212.         }
  213.     printf("\n--- %d,%d -----\n", dfrom2, dto2);
  214.     for (i = dfrom2; i <= dto2; ++i)
  215.         {
  216.         if (!fgets(buffer, sizeof(buffer), fd2))
  217.         break;
  218.         disp = ' ';
  219.         if (i >= from2 && i <= to2)
  220.         disp = (type == 'c') ? '!': '+';
  221.         printf("%c %s", disp, buffer);
  222.         }
  223.  
  224.     /* seek back because next diff may overlap */
  225.     fseek(fd1, off1, 0);
  226.     fseek(fd2, off2, 0);
  227.  
  228.     /* calculate the number of display lines generated by diff */
  229.     skip = to1 - from1 + to2 - from2 + 2;
  230.     if (type == 'c')
  231.         skip++;        /* add one for the seperator */
  232.     toline(diff, 0, skip);
  233.     }
  234.     }
  235.  
  236. parse(line, from1, from2, to1, to2, type)
  237. char *line, *type;
  238. int *from1, *from2, *to1, *to2;
  239.     {
  240.     char *part2, *ptr;
  241.  
  242.     /* expect a line range type range */
  243.     if(!isdigit(line[0]))
  244.     {
  245.     fprintf(stderr, "Unknown junk from diff: %s\n", line);
  246.     exit(2);
  247.     }
  248.     if ((part2 = strchr(line, 'a')) || (part2 = strchr(line, 'c')) || (part2 = strchr(line, 'd')))
  249.     {
  250.     *type = *part2;
  251.     *part2++ = '\0';
  252.     printf("%s\n", SEPERATE);
  253.     }
  254.     else
  255.     {
  256.     fprintf(stderr, "Unknown junk from diff: %s\n", line);
  257.     exit(2);
  258.     }
  259. X/* file 1 */
  260.     *from1 = atoi(line);
  261.     if (ptr = strchr(line, ','))
  262.     *to1 = atoi(++ptr);
  263.     else
  264.     *to1 = *from1;
  265. X/* file 2 */
  266.     *from2 = atoi(part2);
  267.     if (ptr = strchr(part2, ','))
  268.     *to2 = atoi(++ptr);
  269.     else
  270.     *to2 = *from2;
  271.  
  272.     if (*type == 'a')
  273.     ++*from1;
  274.  
  275.     if (*type == 'd')
  276.     ++*from2;
  277.     }
  278.  
  279.  
  280. toline(fd, lineis, linenum)
  281. XFILE *fd;
  282. int lineis, linenum;
  283.     {
  284.     /* note: toline can seek to one more line than there actually is (EOF) */
  285.     while (lineis < linenum)
  286.     {
  287.     if (fgets(buffer, sizeof(buffer), fd))
  288.         ++lineis;
  289.     else
  290.         break;
  291.     }
  292.     return lineis;
  293.     }
  294.  
  295. checkline(fd, lineis, linenum)
  296. XFILE *fd;
  297. int lineis, linenum;
  298.     {
  299.     lineis = toline(fd, lineis, linenum);
  300.     if (!fgets(buffer, sizeof(buffer), fd))
  301.     --lineis;
  302.     return lineis;
  303.     }
  304. //go.sysin dd *
  305.