📄 diff.c
字号:
if ((l = freelist) != NullStructLine) freelist = freelist->l_next; else { l = (struct line *) xmalloc(3 * sizeof(void *)); l->l_text = (char *) xmalloc((size + 2) * sizeof(char)); if ((l == 0) || (l->l_text == 0)) fatal_error("Out of memory", ""); } return l;}/* Free_line() releases storage allocated for <l>. */void free_line(l)register struct line *l;{ l->l_next = freelist; freelist = l;}/* Equal_line() compares two lines, <l1> and <l2>. * the returned value is the result of the strcmp() function. */int equal_line(l1, l2)struct line *l1, *l2;{ if (l1 == 0 || l2 == 0) return(0); else if (l1->l_eof || l2->l_eof) return(l1->l_eof == l2->l_eof); else return(strcmp(l1->l_text, l2->l_text) == 0);}int equal_3(l1, l2)struct line *l1, *l2;{ register int i, ansr; ansr = 1;#ifdef DEBUG if (l1 == 0) fprintf(stderr, "\t(null)\n"); else if (l1->l_eof) fprintf(stderr, "\t(eof)\n"); else fprintf(stderr, "\t%s", l1->l_text); if (l2 == 0) fprintf(stderr, "\t(null)\n"); else if (l2->l_eof) fprintf(stderr, "\t(eof)\n"); else fprintf(stderr, "\t%s", l2->l_text);#endif for (i = 0; i < 3; ++i) { if (!equal_line(l1, l2)) { ansr = 0; break; } l1 = stepup(l1); l2 = stepup(l2); }#ifdef DEBUG fprintf(stderr, "\t%d\n", ansr);#endif return(ansr);}struct line * read_line(fp)FILE *fp;{ register struct line *l = new_line(LINELEN); register char *p; register int c; (p = &(l->l_text[LINELEN]))[1] = '\377'; l->l_eof = 0; if (fgets(l->l_text, LINELEN + 2, fp) == 0) { l->l_eof = 1; l->l_text[0] = 0; } else if ((p[1] & 0377) != 0377 && *p != '\n') { while ((c = fgetc(fp)) != '\n' && c != EOF) { } *p++ = '\n'; *p = '\0'; } l->l_next = 0; if (trim_blanks == SET) {#ifdef DEBUG printf("xxx %s xxx\n", l->l_text);#endif trimming_blanks(l->l_text);#ifdef DEBUG printf("xxx %s xxx\n", l->l_text);#endif } return l;}/* File window handler */struct f { struct line *f_bwin, *f_ewin; struct line *f_aside; int f_linecnt; /* line number in file of last advanced line */ FILE *f_fp;};void advance(f)register struct f *f;{ register struct line *l; if ((l = f->f_bwin) != NullStructLine) { if (f->f_ewin == l) f->f_bwin = f->f_ewin = 0; else f->f_bwin = l->l_next; free_line(l); (f->f_linecnt)++; }}void aside(f, l)struct f *f;struct line *l;{ register struct line *ll; if (l == 0) return; if ((ll = l->l_next) != NullStructLine) { while (ll->l_next) ll = ll->l_next; ll->l_next = f->f_aside; f->f_aside = l->l_next; l->l_next = 0; f->f_ewin = l; }}struct line *next(f)register struct f *f;{ register struct line *l; if ((l = f->f_aside) != NullStructLine) { f->f_aside = l->l_next; l->l_next = 0; } else l = read_line(f->f_fp); if (l) { if (f->f_bwin == 0) f->f_bwin = f->f_ewin = l; else { if (f->f_ewin->l_eof && l->l_eof) { free_line(l); return(f->f_ewin); } f->f_ewin->l_next = l; f->f_ewin = l; } } return l;}/* Init_f() initialises a window structure (struct f). <fp> is the * file associated with <f>. */void init_f(f, fp)register struct f *f;FILE *fp;{ f->f_bwin = f->f_ewin = f->f_aside = 0; f->f_linecnt = 0; f->f_fp = fp;}/* Update() prints a window. <f> is a pointer to the window, <s> is the * string containing the "prefix" to the printout( either "<" or ">"). * after completion of update(), the window is empty. */void update(f, s)register struct f *f;char *s;{ char *help; int only_dot = 0; if (firstoutput && (recursive_dir == SET)) { printf("diff %s %s %s\n", options_string, oldfile, newfile); firstoutput = 0; } while (f->f_bwin && f->f_bwin != f->f_ewin) { if (mode != ed_mode) { printf("%s%s", s, f->f_bwin->l_text); } else {#ifdef DEBUG printf("ed_mode: test for only dot"); printf("%s", f->f_bwin->l_text);#endif help = f->f_bwin->l_text; while ((*help == ' ') || (*help == '.') || (*help == '\t')) { if (*(help++) == '.') only_dot++; if (only_dot > 1) break; } /* If only_dot is equal 1, there is only one dot on * the line, so we have to take special actions. * f the line with only one dot is found, we output * two dots (".."), terminate the append modus and * substitute "." for "..". Afterwards we restart * with the append command. */ if (*help == '\n' && only_dot == 1) { help = f->f_bwin->l_text; while (*help != '\0') { if (*help == '.') printf("."); putchar((int) *(help++)); } printf(".\n"); printf(".s/\\.\\././\n"); printf("a\n"); } else { printf("%s%s", s, f->f_bwin->l_text); } } advance(f); }}/* __Diff(), performs the "core operation" of the program. * Expects two file-pointers as arguments. This functions does * *not* check if the file-pointers are valid. */void __diff(fp1, fp2)FILE *fp1, *fp2;{ struct f f1, f2; struct line *l1, *s1, *b1, *l2, *s2, *b2; register struct line *ll; init_f(&f1, fp1); init_f(&f2, fp2); l1 = next(&f1); l2 = next(&f2); while ((l1->l_eof == 0) || (l2->l_eof == 0)) { if (equal_line(l1, l2)) { equal: advance(&f1); advance(&f2); l1 = next(&f1); l2 = next(&f2); continue; } s1 = b1 = l1; s2 = b2 = l2; /* Read several more lines */ next(&f1); next(&f1); next(&f2); next(&f2); /* Start searching */search: next(&f2); ll = s1; do { if (equal_3(ll, b2)) { l1 = ll; l2 = b2; aside(&f1, ll); aside(&f2, b2); differ(&f1, &f2); goto equal; } if (ll->l_eof) break; ll = stepup(ll); } while (ll); b2 = stepup(b2); next(&f1); ll = s2; do { if (equal_3(b1, ll)) { l1 = b1; l2 = ll; aside(&f2, ll); aside(&f1, b1); differ(&f1, &f2); goto equal; } if (ll->l_eof != 0) break; ll = stepup(ll); } while (ll); b1 = stepup(b1); goto search; } /* Both of the files reached EOF */}/* Differ() prints the differences between files. the arguments <f1> and * <f2> are pointers to the two windows, where the differences are. */void differ(f1, f2)register struct f *f1, *f2;{ int cnt1 = f1->f_linecnt, len1 = wlen(f1); int cnt2 = f2->f_linecnt, len2 = wlen(f2); if ((len1 != 0) || (len2 != 0)) { if (len1 == 0) { if (mode == ed_mode) { cnt1 += offset; printf("%d a\n", cnt1); update(f2, ""); printf(".\n"); offset += len2; } else { printf("%da", cnt1); range(cnt2 + 1, cnt2 + len2); } } else if (len2 == 0) { if (mode == ed_mode) { cnt1 += offset; range(cnt1 + 1, cnt1 + len1); printf("d\n"); offset -= len1; while (f1->f_bwin && f1->f_bwin != f1->f_ewin) advance(f1); } else { range(cnt1 + 1, cnt1 + len1); printf("d%d", cnt2); } } else { if (mode != ed_mode) { range(cnt1 + 1, cnt1 + len1); putchar('c'); range(cnt2 + 1, cnt2 + len2); } else { cnt1 += offset; if (len1 == len2) { range(cnt1 + 1, cnt1 + len1); printf("c\n"); update(f2, ""); printf(".\n"); } else { range(cnt1 + 1, cnt1 + len1); printf("d\n"); printf("%d a\n", cnt1); update(f2, ""); printf(".\n"); offset -= len1 - len2; } while (f1->f_bwin && f1->f_bwin != f1->f_ewin) advance(f1); } } if (mode != ed_mode) { putchar('\n'); if (len1 != 0) update(f1, "< "); if ((len1 != 0) && (len2 != 0)) printf("---\n"); if (len2 != 0) update(f2, "> "); } diffs++; }}/* Function wlen() calculates the number of lines in a window. */int wlen(f)struct f *f;{ register cnt = 0; register struct line *l = f->f_bwin, *e = f->f_ewin; while (l && l != e) { cnt++; l = l->l_next; } return cnt;}/* Range() prints the line numbers of a range. the arguments <a> and <b> * are the beginning and the ending line number of the range. if * <a> == <b>, only one line number is printed. otherwise <a> and <b> are * separated by a ",". */void range(a, b)int a, b;{ printf(((a == b) ? "%d" : "%d,%d"), a, b);}/* Here follows the code for option -c. * This code is from the cdiff program by Larry Wall. I changed it only * slightly to reflect the POSIX standard and to call the main routine * as function context_diff(). *//* Cdiff - context diff Author: Larry Wall *//* These global variables are still here from the original cdiff program... * I was to lazy just to sort them out... */char buff[512];FILE *oldfp, *newfp;int oldmin, oldmax, newmin, newmax;int oldbeg, oldend, newbeg, newend;int preoldmax, prenewmax;int preoldbeg, preoldend, prenewbeg, prenewend;int oldwanted, newwanted;char *oldhunk, *newhunk;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -