📄 diff.c
字号:
size_t oldsize, oldalloc, newsize, newalloc;void cdiff(old, new, file1, file2)char *old, *new; /* The names of the two files to be compared */FILE *file1, *file2; /* The corresponding file-pointers */{ FILE *inputfp; struct stat statbuf; register char *s; char op; char *newmark, *oldmark; int len; char *line; int i, status; oldfp = file1; newfp = file2; oldalloc = 512; oldhunk = (char *) xmalloc(oldalloc); newalloc = 512; newhunk = (char *) xmalloc(newalloc);/* The context diff spawns a new process that executes a normal diff * and parses the output. */ if (trim_blanks == SET) sprintf(buff, "diff -b %s %s", old, new); else sprintf(buff, "diff %s %s", old, new); inputfp = popen(buff, "r"); if (!inputfp) { fprintf(stderr, "Can't execute diff %s %s\n", old, new); exit(2); } preoldend = -1000; firstoutput = 1; while (fgets(buff, sizeof buff, inputfp) != Nullch) { if (firstoutput) { if (recursive_dir == SET) { printf("diff %s %s %s\n", options_string, oldfile, newfile); } fstat(fileno(oldfp), &statbuf); printf("*** %s %s", old, ctime(&statbuf.st_mtime)); fstat(fileno(newfp), &statbuf); printf("--- %s %s", new, ctime(&statbuf.st_mtime)); firstoutput = 0; } if (isdigit(*buff)) { oldmin = atoi(buff); for (s = buff; isdigit(*s); s++); if (*s == ',') { s++; oldmax = atoi(s); for (; isdigit(*s); s++); } else { oldmax = oldmin; } if (*s != 'a' && *s != 'd' && *s != 'c') { fprintf(stderr, "Unparseable input: %s", s); exit(2); } op = *s; s++; newmin = atoi(s); for (; isdigit(*s); s++); if (*s == ',') { s++; newmax = atoi(s); for (; isdigit(*s); s++); } else { newmax = newmin; } if (*s != '\n' && *s != ' ') { fprintf(stderr, "Unparseable input: %s", s); exit(2); } newmark = oldmark = "! "; if (op == 'a') { oldmin++; newmark = "+ "; } if (op == 'd') { newmin++; oldmark = "- "; } oldbeg = oldmin - context_lines; oldend = oldmax + context_lines; if (oldbeg < 1) oldbeg = 1; newbeg = newmin - context_lines; newend = newmax + context_lines; if (newbeg < 1) newbeg = 1; if (preoldend < oldbeg - 1) { if (preoldend >= 0) { dumphunk(); } preoldbeg = oldbeg; prenewbeg = newbeg; oldwanted = newwanted = 0; oldsize = newsize = 0; } else { /* we want to append to previous hunk */ oldbeg = preoldmax + 1; newbeg = prenewmax + 1; } for (i = oldbeg; i <= oldmax; i++) { line = getold(i); if (!line) { oldend = oldmax = i - 1; break; } len = strlen(line) + 2; if (oldsize + len + 1 >= oldalloc) { oldalloc *= 2; oldhunk = (char *) xrealloc(oldhunk, oldalloc); } if (i >= oldmin) { strcpy(oldhunk + oldsize, oldmark); oldwanted++; } else { strcpy(oldhunk + oldsize, " "); } strcpy(oldhunk + oldsize + 2, line); oldsize += len; } preoldmax = oldmax; preoldend = oldend; for (i = newbeg; i <= newmax; i++) { line = getnew(i); if (!line) { newend = newmax = i - 1; break; } len = strlen(line) + 2; if (newsize + len + 1 >= newalloc) { newalloc *= 2; newhunk = (char *) xrealloc(newhunk, newalloc); } if (i >= newmin) { strcpy(newhunk + newsize, newmark); newwanted++; } else { strcpy(newhunk + newsize, " "); } strcpy(newhunk + newsize + 2, line); newsize += len; } prenewmax = newmax; prenewend = newend; } } status = pclose(inputfp); if (status != 0) diffs++; if (!WIFEXITED(status) || WEXITSTATUS(status) > 1) severe_error = 1; if (preoldend >= 0) { dumphunk(); }}void dumphunk(){ int i; char *line; int len; for (i = preoldmax + 1; i <= preoldend; i++) { line = getold(i); if (!line) { preoldend = i - 1; break; } len = strlen(line) + 2; if (oldsize + len + 1 >= oldalloc) { oldalloc *= 2; oldhunk = (char *) xrealloc(oldhunk, oldalloc); } strcpy(oldhunk + oldsize, " "); strcpy(oldhunk + oldsize + 2, line); oldsize += len; } for (i = prenewmax + 1; i <= prenewend; i++) { line = getnew(i); if (!line) { prenewend = i - 1; break; } len = strlen(line) + 2; if (newsize + len + 1 >= newalloc) { newalloc *= 2; newhunk = (char *) xrealloc(newhunk, newalloc); } strcpy(newhunk + newsize, " "); strcpy(newhunk + newsize + 2, line); newsize += len; } fputs("***************\n", stdout); if (preoldbeg >= preoldend) { printf("*** %d ****\n", preoldend); } else { printf("*** %d,%d ****\n", preoldbeg, preoldend); } if (oldwanted) { fputs(oldhunk, stdout); } oldsize = 0; *oldhunk = '\0'; if (prenewbeg >= prenewend) { printf("--- %d ----\n", prenewend); } else { printf("--- %d,%d ----\n", prenewbeg, prenewend); } if (newwanted) { fputs(newhunk, stdout); } newsize = 0; *newhunk = '\0';}char *getold(targ)int targ;{ static int oldline = 0; while (fgets(buff, sizeof buff, oldfp) != Nullch) { oldline++; if (oldline == targ) return buff; } return Nullch;}char *getnew(targ)int targ;{ static int newline = 0; while (fgets(buff, sizeof buff, newfp) != Nullch) { newline++; if (newline == targ) return buff; } return Nullch;}/* Isdir() checks, if <path> is the name of a directory. a return value * is 0, <path> is a normal file. otherwise the <path> is a directory. */int isdir(path)char *path;{ struct stat buf; stat(path, &buf); if (buf.st_mode & S_IFDIR) { /* path is a directory */ return(~0); } else { return(0); }}/* This is the "main" function if a diff of two directories has to be * done. diff_recursive() expects the names of the two directories to * be compared. */void diff_recursive(dir1, dir2)char *dir1, *dir2;{ FILE *ls1, *ls2; char file1[PATH_MAX], file2[PATH_MAX]; char jointfile1[PATH_MAX], jointfile2[PATH_MAX]; char command[PATH_MAX]; int difference, eof1, eof2; sprintf(command, "ls %s", dir1); ls1 = popen(command, "r"); sprintf(command, "ls %s", dir2); ls2 = popen(command, "r"); if ((ls1 == NULL) || (ls2 == NULL)) fatal_error("cannot execute ls!", ""); file1[0] = '\0'; eof1 = fscanf(ls1, "%s\n", file1); file2[0] = '\0'; eof2 = fscanf(ls2, "%s\n", file2); while ((file1[0] != '\0') && (file2[0] != '\0')) { difference = strcmp(file1, file2); while (difference != 0) { if (difference < 0) { printf("Only in %s: %s\n", dir1, file1); file1[0] = '\0'; eof1 = fscanf(ls1, "%s\n", file1); if (file1[0] == '\0') break; } else { printf("Only in %s: %s\n", dir2, file2); file2[0] = '\0'; eof2 = fscanf(ls2, "%s\n", file2); if (file2[0] == '\0') break; } difference = strcmp(file1, file2); } if (eof1 != EOF && eof2 != EOF) { strcpy(jointfile1, dir1); strcat(jointfile1, "/"); strcat(jointfile1, file1); strcpy(jointfile2, dir2); strcat(jointfile2, "/"); strcat(jointfile2, file2); if ((isdir(jointfile1) != 0) && (isdir(jointfile2) != 0)) { printf("Common subdirectories: %s and %s\n", jointfile1, jointfile2); diff_recursive(jointfile1, jointfile2); } else { firstoutput = 1; strcpy(oldfile, jointfile1); strcpy(newfile, jointfile2); diff(jointfile1, jointfile2); } file1[0] = '\0'; eof1 = fscanf(ls1, "%s\n", file1); file2[0] = '\0'; eof2 = fscanf(ls2, "%s\n", file2); } } if (file1[0] != '\0') { /* first arg still has files */ do { printf("Only in %s: %s\n", dir1, file1); eof1 = fscanf(ls1, " %s\n", file1); } while (eof1 != EOF); } if (file2[0] != '\0') { do { printf("Only in %s: %s\n", dir2, file2); eof2 = fscanf(ls2, " %s\n", file2); } while (eof2 != EOF); } if (pclose(ls1) != 0) severe_error = 1; if (pclose(ls2) != 0) severe_error = 1;}/* File_type_error is called, if in a recursive diff ( -r) one of the two * files a block special, a character special or a FIFO special file is. * The corresponding error message is printed here. */void file_type_error(filename1, filename2, statbuf1, statbuf2)char *filename1, *filename2;struct stat *statbuf1, *statbuf2;{ char type1[25], type2[25]; switch (statbuf1->st_mode & S_IFMT) { /* select only file mode */ case S_IFREG: sprintf(type1, "regular file "); break; case S_IFBLK: sprintf(type1, "block special file "); break; case S_IFDIR: sprintf(type1, "directory "); break; case S_IFCHR: sprintf(type1, "character special file "); break; case S_IFIFO: sprintf(type1, "FIFO special file "); break; } switch (statbuf2->st_mode & S_IFMT) { /* select only file mode */ case S_IFREG: sprintf(type2, "regular file "); break; case S_IFBLK: sprintf(type2, "block special file "); break; case S_IFDIR: sprintf(type2, "directory "); break; case S_IFCHR: sprintf(type2, "character special file "); break; case S_IFIFO: sprintf(type2, "FIFO special file "); break; } printf("File %s is a %s while file %s is a %s\n", filename1, type1, filename2, type2);}void *xmalloc(size)size_t size;{ void *ptr; ptr = malloc(size); if (ptr == NULL) { fprintf(stderr, "%s: out of memory\n", progname); exit(2); } return(ptr);}void *xrealloc(ptr, size)void *ptr;size_t size;{ ptr = realloc(ptr, size); if (ptr == NULL) { fprintf(stderr, "%s: out of memory\n", progname); exit(2); } return(ptr);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -