[BACK]Return to sdiff.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / sdiff

Diff for /src/usr.bin/sdiff/sdiff.c between version 1.7 and 1.8

version 1.7, 2005/12/27 04:35:22 version 1.8, 2005/12/27 04:43:01
Line 10 
Line 10 
 #include <sys/types.h>  #include <sys/types.h>
 #include <sys/wait.h>  #include <sys/wait.h>
   
 #include <assert.h>  
 #include <ctype.h>  #include <ctype.h>
 #include <err.h>  #include <err.h>
 #include <getopt.h>  #include <getopt.h>
Line 59 
Line 58 
 size_t   line_width;    /* width of a line (two columns and divider) */  size_t   line_width;    /* width of a line (two columns and divider) */
 size_t   width;         /* width of each column */  size_t   width;         /* width of each column */
 size_t   file1ln, file2ln;      /* line number of file1 and file2 */  size_t   file1ln, file2ln;      /* line number of file1 and file2 */
 int      Dflag;         /* debug - verify lots of things */  
 int      lflag;         /* print only left column for identical lines */  int      lflag;         /* print only left column for identical lines */
 int      sflag;         /* skip identical lines */  int      sflag;         /* skip identical lines */
 FILE    *outfile;       /* file to save changes to */  FILE    *outfile;       /* file to save changes to */
Line 116 
Line 114 
         /* Add first argument, the program name. */          /* Add first argument, the program name. */
         diffargv[diffargc++] = diffprog;          diffargv[diffargc++] = diffprog;
   
         while ((ch = getopt_long(argc, argv, "aBbDdEHI:ilo:stWw:",          while ((ch = getopt_long(argc, argv, "aBbdEHI:ilo:stWw:",
             longopts, NULL)) != -1) {              longopts, NULL)) != -1) {
                 const char *errstr;                  const char *errstr;
   
Line 130 
Line 128 
                 case 'b':                  case 'b':
                         diffargv[diffargc++] = "-b";                          diffargv[diffargc++] = "-b";
                         break;                          break;
                 case 'D':  
                         Dflag = 1;  
                         break;  
                 case 'd':                  case 'd':
                         diffargv[diffargc++] = "-d";                          diffargv[diffargc++] = "-d";
                         break;                          break;
Line 200 
Line 195 
   
         /* Subtract column divider and divide by two. */          /* Subtract column divider and divide by two. */
         width = (wflag - 3) / 2;          width = (wflag - 3) / 2;
         if (Dflag)  
                 assert(width > 0);  
         /* Make sure line_width can fit in size_t. */          /* Make sure line_width can fit in size_t. */
         if (width > (SIZE_T_MAX - 3) / 2)          if (width > (SIZE_T_MAX - 3) / 2)
                 errx(2, "width is too large: %zu", width);                  errx(2, "width is too large: %zu", width);
Line 309 
Line 302 
 static void  static void
 printcol(const char *s, size_t *col, const size_t col_max)  printcol(const char *s, size_t *col, const size_t col_max)
 {  {
         if (Dflag) {  
                 assert(s);  
                 assert(*col <= col_max);  
         }  
   
         for (; *s && *col < col_max; ++s) {          for (; *s && *col < col_max; ++s) {
                 size_t new_col;                  size_t new_col;
   
                 if (Dflag)  
                         assert(*s != '\n');  
   
                 switch (*s) {                  switch (*s) {
                 case '\t':                  case '\t':
                         /*                          /*
Line 443 
Line 429 
 {  {
         size_t col;          size_t col;
   
         if (Dflag) {  
                 /* These are the only legal column dividers. */  
                 assert(div == '<' || div == '|' || div == '>' || div == ' ');  
                 /* These are the only valid combinations. */  
                 assert((s1 != NULL && div == '<' && s2 == NULL) || div != '<');  
                 assert((s1 == NULL && div == '>' && s2 != NULL) || div != '>');  
                 assert((s1 != NULL && div == '|' && s2 != NULL && s2 != s1) ||  
                     div != '|');  
                 assert((s1 != NULL && div == ' ' && (s2 == s1 || s2 == NULL)) ||  
                     div != ' ');  
         }  
   
         /* Print first column.  Skips if s1 == NULL. */          /* Print first column.  Skips if s1 == NULL. */
         col = 0;          col = 0;
         if (s1) {          if (s1) {
                 /* Skip angle bracket and space. */                  /* Skip angle bracket and space. */
                 printcol(s1, &col, width);                  printcol(s1, &col, width);
   
                 /* We should never exceed the width. */  
                 if (Dflag)  
                         assert(col <= width);  
         }          }
   
         /* Only print left column. */          /* Only print left column. */
Line 490 
Line 461 
         /* Skip angle bracket and space. */          /* Skip angle bracket and space. */
         printcol(s2, &col, line_width);          printcol(s2, &col, line_width);
   
         /* We should never exceed the line width. */  
         if (Dflag)  
                 assert(col <= line_width);  
   
         putchar('\n');          putchar('\n');
 }  }
   
Line 507 
Line 474 
         const char delim[3] = {'\0', '\0', '\0'};          const char delim[3] = {'\0', '\0', '\0'};
         char *s;          char *s;
   
         if (Dflag)  
                 assert(file);  
   
         /* XXX - Is this necessary? */          /* XXX - Is this necessary? */
         clearerr(file);          clearerr(file);
   
Line 518 
Line 482 
                 err(2, "error reading file");                  err(2, "error reading file");
   
         if (!s) {          if (!s) {
                 /* NULL from fparseln() should mean EOF. */  
                 if (Dflag)  
                         assert(feof(file));  
   
                 return (NULL);                  return (NULL);
         }          }
   
Line 632 
Line 592 
         /* Process unmodified lines. */          /* Process unmodified lines. */
         processq();          processq();
   
         if (Dflag) {  
                 /*  
                  * We are now at the line where adds, changes,  
                  * or deletions occur.  
                  */  
                 assert(file1start == file1ln);  
                 assert(file2start == file2ln);  
                 assert(file1start <= file1end);  
                 assert(file2start <= file2end);  
         }  
         switch (cmd) {          switch (cmd) {
         case 'a':          case 'a':
                 /* A range cannot be specified for file1. */  
                 if (Dflag)  
                         assert(file1start == file1end);  
   
                 printa(difffile, file2end);                  printa(difffile, file2end);
                 break;                  break;
   
Line 656 
Line 602 
                 break;                  break;
   
         case 'd':          case 'd':
                 /* A range cannot be specified for file2. */  
                 if (Dflag)  
                         assert(file2start == file2end);  
   
                 printd(origfile, difffile, file1end);                  printd(origfile, difffile, file1end);
                 break;                  break;
   
Line 692 
Line 634 
 static void  static void
 freediff(const struct diffline *diffp)  freediff(const struct diffline *diffp)
 {  {
         if (Dflag)  
                 assert(diffp);  
   
         if (diffp->left)          if (diffp->left)
                 free((void *)diffp->left);                  free((void *)diffp->left);
Line 722 
Line 662 
         const static char *oldstr = NULL;          const static char *oldstr = NULL;
         char *newstr;          char *newstr;
   
         if (Dflag)  
                 assert(append);  
   
         /*          /*
          * First string is NULL, so just copy append.           * First string is NULL, so just copy append.
Line 752 
Line 690 
                 offset = strlen(*s);                  offset = strlen(*s);
                 oldstr = *s;                  oldstr = *s;
         }          }
         /* This should always be the end of the string. */  
         if (Dflag) {  
                 assert(*(*s + offset) == '\0');  
                 assert(strlen(*s) == offset);  
         }  
   
         /* Length = strlen(*s) + \n + strlen(append) + '\0'. */          /* Length = strlen(*s) + \n + strlen(append) + '\0'. */
         newlen = offset + 1 + strlen(append) + 1;          newlen = offset + 1 + strlen(append) + 1;
Line 771 
Line 704 
         strlcpy(*s + offset, "\n", newlen - offset);          strlcpy(*s + offset, "\n", newlen - offset);
         copied = strlcat(*s + offset, append, newlen - offset);          copied = strlcat(*s + offset, append, newlen - offset);
   
         /*  
          * We should have copied exactly newlen characters, including  
          * the terminating NUL.  `copied' includes the \n character.  
          */  
         if (Dflag)  
                 assert(offset + copied + 1 == newlen);  
   
         /* Store generated string's values. */          /* Store generated string's values. */
         offset = newlen - 1;          offset = newlen - 1;
         oldstr = *s;          oldstr = *s;
Line 811 
Line 737 
                  * should be the same.  If div is not set, then store                   * should be the same.  If div is not set, then store
                  * this as this set's div.                   * this as this set's div.
                  */                   */
                 if (Dflag)  
                         assert(div == diffp->div || !div);  
                 if (!div)                  if (!div)
                         div = diffp->div;                          div = diffp->div;
   
Line 830 
Line 754 
                         astrcat(&right, diffp->right);                          astrcat(&right, diffp->right);
         }          }
   
         /* div should no longer be NUL. */  
         if (Dflag)  
                 assert(div);  
   
         /* Empty queue and free each diff line and its elements. */          /* Empty queue and free each diff line and its elements. */
         while (!SIMPLEQ_EMPTY(&diffhead)) {          while (!SIMPLEQ_EMPTY(&diffhead)) {
                 diffp = SIMPLEQ_FIRST(&diffhead);                  diffp = SIMPLEQ_FIRST(&diffhead);
Line 865 
Line 785 
 {  {
         size_t len;          size_t len;
   
         if (Dflag) {  
                 assert(s);  
                 assert(*s == '<' || *s == '>');  
                 assert(*(s + 1) == ' ');  
         }  
   
         /* Remove angle bracket and space but keep the NUL. */          /* Remove angle bracket and space but keep the NUL. */
         len = strlen(s) - 2 + 1;          len = strlen(s) - 2 + 1;
         /* Copy at least the NUL. */  
         if (Dflag)  
                 assert(len > 0);  
         /* Move everything two characters over. */          /* Move everything two characters over. */
         memmove(s, s + 2, len);          memmove(s, s + 2, len);
 }  }
Line 888 
Line 799 
 {  {
         char *line;          char *line;
   
         if (Dflag) {  
                 assert(file);  
                 assert(file2ln <= line2);  
         }  
   
         for (; file2ln <= line2; ++file2ln) {          for (; file2ln <= line2; ++file2ln) {
                 if (!(line = xfgets(file)))                  if (!(line = xfgets(file)))
                         errx(2, "append ended early");                          errx(2, "append ended early");
Line 917 
Line 823 
         SIMPLEQ_HEAD(, fileline) delqhead = SIMPLEQ_HEAD_INITIALIZER(delqhead);          SIMPLEQ_HEAD(, fileline) delqhead = SIMPLEQ_HEAD_INITIALIZER(delqhead);
         char *line;          char *line;
   
         if (Dflag) {  
                 assert(file1);  
                 assert(file2);  
                 assert(file1ln <= file1end);  
                 assert(file2ln <= file2end);  
                 /* Change diff sets always start out with an empty queue. */  
                 assert(SIMPLEQ_EMPTY(&diffhead));  
         }  
   
         /* Read lines to be deleted. */          /* Read lines to be deleted. */
         for (; file1ln <= file1end; ++file1ln) {          for (; file1ln <= file1end; ++file1ln) {
                 struct fileline *linep;                  struct fileline *linep;
Line 937 
Line 834 
                 if (!(line2 = xfgets(file2)))                  if (!(line2 = xfgets(file2)))
                         errx(2, "error reading diff in delete in change");                          errx(2, "error reading diff in delete in change");
   
                 /* Verify lines. */  
                 if (Dflag && strncmp("< ", line2, 2) != 0)  
                         errx(2, "invalid del/change diff: %s", line2);  
                 if (Dflag && strcmp(line1, line2 + 2))  
                         warnx("diff differs from file1:\ndiff:\n%s\nfile:\n%s",  
                             line2, line1);  
   
                 /* Unused now. */                  /* Unused now. */
                 free((void *)line2);                  free((void *)line2);
   
Line 957 
Line 847 
         /* There should be a divider here. */          /* There should be a divider here. */
         if (!(line = xfgets(file2)))          if (!(line = xfgets(file2)))
                 errx(2, "error reading diff in change: expected divider");                  errx(2, "error reading diff in change: expected divider");
         if (Dflag && strcmp("---", line))  
                 errx(2, "divider expected: %s", line);  
         free(line);          free(line);
   
 #define getaddln(add) do {                                      \  #define getaddln(add) do {                                      \
         /* Read diff for line. */                               \          /* Read diff for line. */                               \
         if (!((add) = xfgets(file2)))                           \          if (!((add) = xfgets(file2)))                           \
                 errx(2, "error reading add in change");         \                  errx(2, "error reading add in change");         \
         /* Verify line. */                                      \  
         if (Dflag && strncmp("> ", (add), 2))                   \  
                 errx(2, "invalid add/change diff: %s", (add));  \  
         /* Remove ``> ''. */                                    \          /* Remove ``> ''. */                                    \
         undiff(add);                                            \          undiff(add);                                            \
 } while (0)  } while (0)
Line 1023 
Line 908 
 {  {
         const char *line1, *line2;          const char *line1, *line2;
   
         if (Dflag) {  
                 assert(file1);  
                 assert(file2);  
                 assert(file1ln <= file1end);  
                 /* Delete diff sets always start with an empty queue. */  
                 assert(SIMPLEQ_EMPTY(&diffhead));  
         }  
   
         /* Print out lines file1ln to line2. */          /* Print out lines file1ln to line2. */
         for (; file1ln <= file1end; ++file1ln) {          for (; file1ln <= file1end; ++file1ln) {
                 /* XXX - Why can't this handle stdin? */                  /* XXX - Why can't this handle stdin? */
Line 1038 
Line 915 
                         errx(2, "file1 ended early in delete");                          errx(2, "file1 ended early in delete");
                 if (!(line2 = xfgets(file2)))                  if (!(line2 = xfgets(file2)))
                         errx(2, "diff ended early in delete");                          errx(2, "diff ended early in delete");
                 /* Compare delete line from diff to file1. */  
                 if (Dflag && strcmp(line1, line2 + 2) != 0)  
                         warnx("diff differs from file1:\ndiff:\n%s\nfile:\n%s",  
                             line2, line1);  
                 free((void *)line2);                  free((void *)line2);
                 enqueue(line1, '<', NULL);                  enqueue(line1, '<', NULL);
         }          }
Line 1071 
Line 944 
         extern char *__progname;          extern char *__progname;
   
         fprintf(stderr,          fprintf(stderr,
             "usage: %s [-abDdilstW] [-I regexp] [-o outfile] [-w width] file1 file2\n",              "usage: %s [-abdilstW] [-I regexp] [-o outfile] [-w width] file1 file2\n",
             __progname);              __progname);
         exit(2);          exit(2);
 }  }

Legend:
Removed from v.1.7  
changed lines
  Added in v.1.8