00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include <errno.h>
00035 #include <stdlib.h>
00036 #include <limits.h>
00037 #include <string.h>
00038 #include <sys/types.h>
00039 #include <sys/stat.h>
00040 #include <sys/wait.h>
00041 #include <ctype.h>
00042 #include <time.h>
00043 #include <dirent.h>
00044 #include <unistd.h>
00045 #include <stdio.h>
00046
00047
00048 #define Nullfp ((FILE*)0)
00049 #define Nullch ((char*)0)
00050 #define NullStructLine ((struct line *)0)
00051
00052 #define LINELEN 128
00053
00054
00055 #define NOT_SET 0
00056 #define SET 1
00057
00058
00059 #define EXCLUSIVE_OPTIONS 0
00060 #define CANNOT_OPEN_FILE 1
00061
00062
00063 typedef enum {
00064 undefined, context, ed_mode
00065 } MODE;
00066
00067
00068 char *progname;
00069 int diffs = 0;
00070 MODE mode;
00071 int severe_error;
00072
00073
00074
00075
00076
00077 int firstoutput = 1;
00078 char options_string[10];
00079 char oldfile[PATH_MAX];
00080 char newfile[PATH_MAX];
00081
00082
00083
00084 int trim_blanks = NOT_SET;
00085 int recursive_dir = NOT_SET;
00086 int context_lines = 3;
00087 static int offset;
00088
00089
00090 struct f;
00091 _PROTOTYPE(int main, (int argc, char **argv ));
00092 _PROTOTYPE(void process_command_line, (int argc, char **argv ));
00093 _PROTOTYPE(void analyse_input_files, (char *arg1, char *arg2, char *input1,
00094 char *input2 ));
00095 _PROTOTYPE(void diff, (char *filename1, char *filename2 ));
00096 _PROTOTYPE(FILE *check_file, (char *name ));
00097 _PROTOTYPE(void build_option_string, (void ));
00098 _PROTOTYPE(void fatal_error, (char *fmt, char *s ));
00099 _PROTOTYPE(void warn, (int number, char *string ));
00100 _PROTOTYPE(void trimming_blanks, (char *l_text ));
00101 _PROTOTYPE(char *filename, (char *path_string));
00102 _PROTOTYPE(struct line *new_line, (int size ));
00103 _PROTOTYPE(void free_line, (struct line *l ));
00104 _PROTOTYPE(int equal_line, (struct line *l1, struct line *l2 ));
00105 _PROTOTYPE(int equal_3, (struct line *l1, struct line *l2 ));
00106 _PROTOTYPE(struct line *read_line, (FILE *fp ));
00107 _PROTOTYPE(void advance, (struct f *f ));
00108 _PROTOTYPE(void aside, (struct f *f, struct line *l ));
00109 _PROTOTYPE(struct line *next, (struct f *f ));
00110 _PROTOTYPE(void init_f, (struct f *f, FILE *fp ));
00111 _PROTOTYPE(void update, (struct f *f, char *s ));
00112 _PROTOTYPE(void __diff, (FILE *fp1, FILE *fp2 ));
00113 _PROTOTYPE(void differ, (struct f *f1, struct f *f2 ));
00114 _PROTOTYPE(int wlen, (struct f *f ));
00115 _PROTOTYPE(void range, (int a, int b ));
00116 _PROTOTYPE(void cdiff, (char *old, char *new, FILE *file1, FILE *file2 ));
00117 _PROTOTYPE(void dumphunk, (void ));
00118 _PROTOTYPE(char *getold, (int targ ));
00119 _PROTOTYPE(char *getnew, (int targ ));
00120 _PROTOTYPE(int isdir, (char *path ));
00121 _PROTOTYPE(void diff_recursive, (char *dir1, char *dir2 ));
00122 _PROTOTYPE(void file_type_error, (char *filename1, char *filename2,
00123 struct stat *statbuf1, struct stat *statbuf2 ));
00124 _PROTOTYPE(void *xmalloc, (size_t size));
00125 _PROTOTYPE(void *xrealloc, (void *ptr, size_t size));
00126
00127 int main(argc, argv)
00128 int argc;
00129 char **argv;
00130 {
00131 char file1[PATH_MAX], file2[PATH_MAX];
00132 extern int optind;
00133
00134 progname = argv[0];
00135 process_command_line(argc, argv);
00136
00137 analyse_input_files(argv[optind], argv[optind + 1], file1, file2);
00138 optind++;
00139
00140 if (recursive_dir == SET) {
00141 build_option_string();
00142 diff_recursive(file1, file2);
00143 } else {
00144 diff(file1, file2);
00145 }
00146
00147 return(severe_error ? 2 : diffs > 0 ? 1 : 0);
00148 }
00149
00150
00151
00152
00153
00154 void process_command_line(argc, argv)
00155 int argc;
00156 char **argv;
00157 {
00158 int c;
00159 extern char *optarg;
00160 extern int optind;
00161
00162
00163 if (argc < 3) {
00164 fatal_error("Usage: %s [-c|-e|-C n][-br] file1 file2\n", progname);
00165 }
00166
00167
00168 while ((c = getopt(argc, argv, "ceC:br")) != -1) {
00169 switch (c) {
00170 case 'c':
00171 if (mode != undefined) warn(EXCLUSIVE_OPTIONS, "c");
00172 mode = context;
00173 context_lines = 3;
00174 break;
00175 case 'e':
00176 if (mode != undefined) warn(EXCLUSIVE_OPTIONS, "e");
00177 mode = ed_mode;
00178 break;
00179 case 'C':
00180 if (mode != undefined) warn(EXCLUSIVE_OPTIONS, "C");
00181 mode = context;
00182 context_lines = atoi(optarg);
00183 break;
00184 case 'b': trim_blanks = SET; break;
00185 case 'r': recursive_dir = SET; break;
00186 case '?':
00187 exit(2);
00188 }
00189 }
00190
00191
00192 if ((argc - optind) != 2)
00193 fatal_error("Need exactly two input file-names!\n", "");
00194 }
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204 void analyse_input_files(arg1, arg2, input1, input2)
00205 char *arg1, *arg2;
00206 char *input1, *input2;
00207 {
00208 int stat1 = 0, stat2 = 0;
00209
00210 if (strcmp(arg1, "-") != 0)
00211 stat1 = isdir(arg1);
00212 if (strcmp(arg2, "-") != 0) stat2 = isdir(arg2);
00213 #ifdef DEBUG
00214 fprintf(stderr, "%s, stat = %d\n", arg1, stat1);
00215 fprintf(stderr, "%s, stat = %d\n", arg2, stat2);
00216 #endif
00217 if (stat1 && stat2) {
00218 recursive_dir = SET;
00219 strcpy(input1, arg1);
00220 strcpy(input2, arg2);
00221 return;
00222 }
00223 if (stat1 != 0) {
00224 if (strcmp(arg2, "-") != 0) {
00225 strcpy(input1, arg1);
00226 strcat(input1, "/");
00227 strcat(input1, arg2);
00228 strcpy(input2, arg2);
00229 return;
00230 } else {
00231 fatal_error("cannot compare stdin (-) with a directory!", "");
00232 }
00233 }
00234 if (stat2 != 0) {
00235 if (strcmp(arg1, "-") != 0) {
00236 strcpy(input1, arg1);
00237 strcpy(input2, arg2);
00238 strcat(input2, "/");
00239 strcat(input2, arg1);
00240 return;
00241 } else {
00242 fatal_error("cannot compare stdin (-) with a directory!", "");
00243 }
00244 }
00245
00246
00247 strcpy(input1, arg1);
00248 strcpy(input2, arg2);
00249 }
00250
00251
00252
00253
00254
00255
00256 void diff(filename1, filename2)
00257 char *filename1, *filename2;
00258 {
00259 FILE *file1 = check_file(filename1);
00260 FILE *file2 = check_file(filename2);
00261 struct stat statbuf1, statbuf2;
00262
00263 if ((file1 != Nullfp) && (file2 != Nullfp)) {
00264
00265
00266
00267 fstat(fileno(file1), &statbuf1);
00268 fstat(fileno(file2), &statbuf2);
00269 if ((((statbuf1.st_mode & S_IFREG) != S_IFREG) ||
00270 ((statbuf2.st_mode & S_IFREG) != S_IFREG)) &&
00271 (recursive_dir == SET)) {
00272 file_type_error(filename1, filename2, &statbuf1, &statbuf2);
00273 } else {
00274 switch (mode) {
00275 case context:
00276 cdiff(filename1, filename2, file1, file2);
00277 break;
00278 case ed_mode:
00279 case undefined:
00280 __diff(file1, file2);
00281 if (mode == ed_mode) printf("w\n");
00282 break;
00283 }
00284 }
00285 } else
00286 severe_error = 1;
00287 if (file1 != Nullfp) fclose(file1);
00288 if (file2 != Nullfp) fclose(file2);
00289 }
00290
00291
00292
00293
00294 FILE *check_file(name)
00295 char *name;
00296 {
00297 FILE *temp;
00298
00299 if (strcmp(name, "-") == 0) {
00300 return(stdin);
00301 } else {
00302 temp = fopen(name, "r");
00303 if (temp == Nullfp) warn(CANNOT_OPEN_FILE, name);
00304 return(temp);
00305 }
00306 }
00307
00308
00309
00310
00311
00312
00313 void build_option_string()
00314 {
00315 switch (mode) {
00316 case ed_mode:sprintf(options_string, "-e");
00317 break;
00318 case context:
00319 if (context_lines == 3)
00320 sprintf(options_string, "-c");
00321 else
00322 sprintf(options_string, "-C %d", context_lines);
00323 break;
00324 }
00325
00326 }
00327
00328
00329
00330
00331
00332
00333 void fatal_error(fmt, s)
00334 char *fmt;
00335 char *s;
00336
00337 {
00338 fprintf(stderr, "%s: ", progname);
00339 fprintf(stderr, fmt, s);
00340 fprintf(stderr, "\n");
00341 exit(2);
00342 }
00343
00344
00345
00346
00347
00348
00349 void warn(number, string)
00350 int number;
00351 char *string;
00352 {
00353 static char *warning[] = {
00354 "%s: The options -c, -e, -C n are mutually exclusive! Assuming -%c\n",
00355 "%s: cannot open file %s for reading\n",
00356 };
00357 fprintf(stderr, warning[number], progname, string);
00358 }
00359
00360
00361
00362
00363
00364 void trimming_blanks(l_text)
00365 char *l_text;
00366 {
00367 char *line = l_text;
00368 char *copy_to, *copy_from;
00369
00370 do {
00371 if (*line == ' ') {
00372 copy_from = line;
00373 copy_to = line;
00374 while (*(++copy_from) == ' ');
00375 if (*copy_from != '\n') copy_to++;
00376 while (*copy_from != '\0') *(copy_to++) = *(copy_from++);
00377 *copy_to = '\0';
00378 }
00379 } while (*(++line) != '\0');
00380 }
00381
00382
00383
00384
00385
00386 char *filename(path_string)
00387 char *path_string;
00388 {
00389 char name[NAME_MAX + 2];
00390 char *ptr;
00391
00392 name[0] = '/';
00393 ptr = strrchr(path_string, '/');
00394
00395 if (ptr == 0) {
00396 strcat(name, path_string);
00397 } else {
00398 strcat(name, ptr);
00399 }
00400
00401 return(name);
00402 }
00403
00404
00405 struct line {
00406 struct line *l_next;
00407 char l_eof;
00408 char *l_text;
00409 };
00410
00411 struct line *freelist = 0;
00412 #define stepup(ll) ( ((ll) && ((ll)->l_eof==0)) ? (ll)->l_next : (ll) )
00413
00414
00415 struct line *new_line(size)
00416 int size;
00417 {
00418 register struct line *l;
00419
00420 if ((l = freelist) != NullStructLine)
00421 freelist = freelist->l_next;
00422 else {
00423 l = (struct line *) xmalloc(3 * sizeof(void *));
00424 l->l_text = (char *) xmalloc((size + 2) * sizeof(char));
00425 if ((l == 0) || (l->l_text == 0)) fatal_error("Out of memory", "");
00426 }
00427 return l;
00428 }
00429
00430
00431
00432 void free_line(l)
00433 register struct line *l;
00434 {
00435 l->l_next = freelist;
00436 freelist = l;
00437 }
00438
00439
00440
00441
00442 int equal_line(l1, l2)
00443 struct line *l1, *l2;
00444 {
00445 if (l1 == 0 || l2 == 0)
00446 return(0);
00447 else if (l1->l_eof || l2->l_eof)
00448 return(l1->l_eof == l2->l_eof);
00449 else
00450 return(strcmp(l1->l_text, l2->l_text) == 0);
00451 }
00452
00453 int equal_3(l1, l2)
00454 struct line *l1, *l2;
00455 {
00456 register int i, ansr;
00457
00458 ansr = 1;
00459 #ifdef DEBUG
00460 if (l1 == 0)
00461 fprintf(stderr, "\t(null)\n");
00462 else if (l1->l_eof)
00463 fprintf(stderr, "\t(eof)\n");
00464 else
00465 fprintf(stderr, "\t%s", l1->l_text);
00466 if (l2 == 0)
00467 fprintf(stderr, "\t(null)\n");
00468 else if (l2->l_eof)
00469 fprintf(stderr, "\t(eof)\n");
00470 else
00471 fprintf(stderr, "\t%s", l2->l_text);
00472 #endif
00473 for (i = 0; i < 3; ++i) {
00474 if (!equal_line(l1, l2)) {
00475 ansr = 0;
00476 break;
00477 }
00478 l1 = stepup(l1);
00479 l2 = stepup(l2);
00480 }
00481 #ifdef DEBUG
00482 fprintf(stderr, "\t%d\n", ansr);
00483 #endif
00484 return(ansr);
00485 }
00486
00487 struct line *
00488 read_line(fp)
00489 FILE *fp;
00490 {
00491 register struct line *l = new_line(LINELEN);
00492 register char *p;
00493 register int c;
00494
00495 (p = &(l->l_text[LINELEN]))[1] = '\377';
00496 l->l_eof = 0;
00497 if (fgets(l->l_text, LINELEN + 2, fp) == 0) {
00498 l->l_eof = 1;
00499 l->l_text[0] = 0;
00500 } else if ((p[1] & 0377) != 0377 && *p != '\n') {
00501 while ((c = fgetc(fp)) != '\n' && c != EOF) {
00502 }
00503 *p++ = '\n';
00504 *p = '\0';
00505 }
00506 l->l_next = 0;
00507 if (trim_blanks == SET) {
00508 #ifdef DEBUG
00509 printf("xxx %s xxx\n", l->l_text);
00510 #endif
00511 trimming_blanks(l->l_text);
00512 #ifdef DEBUG
00513 printf("xxx %s xxx\n", l->l_text);
00514 #endif
00515 }
00516 return l;
00517 }
00518
00519
00520 struct f {
00521 struct line *f_bwin, *f_ewin;
00522 struct line *f_aside;
00523 int f_linecnt;
00524 FILE *f_fp;
00525 };
00526
00527 void advance(f)
00528 register struct f *f;
00529 {
00530 register struct line *l;
00531
00532 if ((l = f->f_bwin) != NullStructLine) {
00533 if (f->f_ewin == l)
00534 f->f_bwin = f->f_ewin = 0;
00535 else
00536 f->f_bwin = l->l_next;
00537 free_line(l);
00538 (f->f_linecnt)++;
00539 }
00540 }
00541
00542 void aside(f, l)
00543 struct f *f;
00544 struct line *l;
00545 {
00546 register struct line *ll;
00547
00548 if (l == 0) return;
00549 if ((ll = l->l_next) != NullStructLine) {
00550 while (ll->l_next) ll = ll->l_next;
00551 ll->l_next = f->f_aside;
00552 f->f_aside = l->l_next;
00553 l->l_next = 0;
00554 f->f_ewin = l;
00555 }
00556 }
00557
00558
00559 struct line *next(f)
00560 register struct f *f;
00561 {
00562 register struct line *l;
00563
00564 if ((l = f->f_aside) != NullStructLine) {
00565 f->f_aside = l->l_next;
00566 l->l_next = 0;
00567 } else
00568 l = read_line(f->f_fp);
00569 if (l) {
00570 if (f->f_bwin == 0)
00571 f->f_bwin = f->f_ewin = l;
00572 else {
00573 if (f->f_ewin->l_eof && l->l_eof) {
00574 free_line(l);
00575 return(f->f_ewin);
00576 }
00577 f->f_ewin->l_next = l;
00578 f->f_ewin = l;
00579 }
00580 }
00581 return l;
00582 }
00583
00584
00585
00586
00587
00588 void init_f(f, fp)
00589 register struct f *f;
00590 FILE *fp;
00591 {
00592 f->f_bwin = f->f_ewin = f->f_aside = 0;
00593 f->f_linecnt = 0;
00594 f->f_fp = fp;
00595 }
00596
00597
00598
00599
00600
00601
00602 void update(f, s)
00603 register struct f *f;
00604 char *s;
00605 {
00606 char *help;
00607 int only_dot = 0;
00608
00609 if (firstoutput && (recursive_dir == SET)) {
00610 printf("diff %s %s %s\n", options_string, oldfile, newfile);
00611 firstoutput = 0;
00612 }
00613 while (f->f_bwin && f->f_bwin != f->f_ewin) {
00614 if (mode != ed_mode) {
00615 printf("%s%s", s, f->f_bwin->l_text);
00616 } else {
00617 #ifdef DEBUG
00618 printf("ed_mode: test for only dot");
00619 printf("%s", f->f_bwin->l_text);
00620 #endif
00621 help = f->f_bwin->l_text;
00622 while ((*help == ' ') ||
00623 (*help == '.') ||
00624 (*help == '\t')) {
00625 if (*(help++) == '.') only_dot++;
00626 if (only_dot > 1) break;
00627 }
00628
00629
00630
00631
00632
00633
00634
00635 if (*help == '\n' && only_dot == 1) {
00636 help = f->f_bwin->l_text;
00637 while (*help != '\0') {
00638 if (*help == '.') printf(".");
00639 putchar((int) *(help++));
00640 }
00641 printf(".\n");
00642 printf(".s/\\.\\././\n");
00643 printf("a\n");
00644 } else {
00645 printf("%s%s", s, f->f_bwin->l_text);
00646 }
00647 }
00648 advance(f);
00649 }
00650 }
00651
00652
00653
00654
00655
00656
00657 void __diff(fp1, fp2)
00658 FILE *fp1, *fp2;
00659 {
00660 struct f f1, f2;
00661 struct line *l1, *s1, *b1, *l2, *s2, *b2;
00662 register struct line *ll;
00663
00664 init_f(&f1, fp1);
00665 init_f(&f2, fp2);
00666 l1 = next(&f1);
00667 l2 = next(&f2);
00668 while ((l1->l_eof == 0) || (l2->l_eof == 0)) {
00669 if (equal_line(l1, l2)) {
00670 equal:
00671 advance(&f1);
00672 advance(&f2);
00673 l1 = next(&f1);
00674 l2 = next(&f2);
00675 continue;
00676 }
00677 s1 = b1 = l1;
00678 s2 = b2 = l2;
00679
00680 next(&f1);
00681 next(&f1);
00682 next(&f2);
00683 next(&f2);
00684
00685 search:
00686 next(&f2);
00687 ll = s1;
00688 do {
00689 if (equal_3(ll, b2)) {
00690 l1 = ll;
00691 l2 = b2;
00692 aside(&f1, ll);
00693 aside(&f2, b2);
00694 differ(&f1, &f2);
00695 goto equal;
00696 }
00697 if (ll->l_eof) break;
00698 ll = stepup(ll);
00699 } while (ll);
00700 b2 = stepup(b2);
00701
00702 next(&f1);
00703 ll = s2;
00704 do {
00705 if (equal_3(b1, ll)) {
00706 l1 = b1;
00707 l2 = ll;
00708 aside(&f2, ll);
00709 aside(&f1, b1);
00710 differ(&f1, &f2);
00711 goto equal;
00712 }
00713 if (ll->l_eof != 0) break;
00714 ll = stepup(ll);
00715 } while (ll);
00716 b1 = stepup(b1);
00717
00718 goto search;
00719 }
00720
00721
00722 }
00723
00724
00725
00726
00727 void differ(f1, f2)
00728 register struct f *f1, *f2;
00729 {
00730 int cnt1 = f1->f_linecnt, len1 = wlen(f1);
00731 int cnt2 = f2->f_linecnt, len2 = wlen(f2);
00732 if ((len1 != 0) || (len2 != 0)) {
00733 if (len1 == 0) {
00734 if (mode == ed_mode) {
00735 cnt1 += offset;
00736 printf("%d a\n", cnt1);
00737 update(f2, "");
00738 printf(".\n");
00739 offset += len2;
00740 } else {
00741 printf("%da", cnt1);
00742 range(cnt2 + 1, cnt2 + len2);
00743 }
00744 } else if (len2 == 0) {
00745 if (mode == ed_mode) {
00746 cnt1 += offset;
00747 range(cnt1 + 1, cnt1 + len1);
00748 printf("d\n");
00749 offset -= len1;
00750 while (f1->f_bwin && f1->f_bwin != f1->f_ewin)
00751 advance(f1);
00752 } else {
00753 range(cnt1 + 1, cnt1 + len1);
00754 printf("d%d", cnt2);
00755 }
00756 } else {
00757 if (mode != ed_mode) {
00758 range(cnt1 + 1, cnt1 + len1);
00759 putchar('c');
00760 range(cnt2 + 1, cnt2 + len2);
00761 } else {
00762 cnt1 += offset;
00763 if (len1 == len2) {
00764 range(cnt1 + 1, cnt1 + len1);
00765 printf("c\n");
00766 update(f2, "");
00767 printf(".\n");
00768 } else {
00769 range(cnt1 + 1, cnt1 + len1);
00770 printf("d\n");
00771 printf("%d a\n", cnt1);
00772 update(f2, "");
00773 printf(".\n");
00774 offset -= len1 - len2;
00775 }
00776 while (f1->f_bwin && f1->f_bwin != f1->f_ewin)
00777 advance(f1);
00778 }
00779 }
00780 if (mode != ed_mode) {
00781 putchar('\n');
00782 if (len1 != 0) update(f1, "< ");
00783 if ((len1 != 0) && (len2 != 0)) printf("---\n");
00784 if (len2 != 0) update(f2, "> ");
00785 }
00786 diffs++;
00787 }
00788 }
00789
00790
00791
00792 int wlen(f)
00793 struct f *f;
00794 {
00795 register cnt = 0;
00796 register struct line *l = f->f_bwin, *e = f->f_ewin;
00797
00798 while (l && l != e) {
00799 cnt++;
00800 l = l->l_next;
00801 }
00802 return cnt;
00803 }
00804
00805
00806
00807
00808
00809
00810
00811 void range(a, b)
00812 int a, b;
00813 {
00814 printf(((a == b) ? "%d" : "%d,%d"), a, b);
00815 }
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828 char buff[512];
00829 FILE *oldfp, *newfp;
00830
00831 int oldmin, oldmax, newmin, newmax;
00832 int oldbeg, oldend, newbeg, newend;
00833 int preoldmax, prenewmax;
00834 int preoldbeg, preoldend, prenewbeg, prenewend;
00835 int oldwanted, newwanted;
00836
00837 char *oldhunk, *newhunk;
00838 size_t oldsize, oldalloc, newsize, newalloc;
00839
00840 int oldline, newline;
00841
00842 void cdiff(old, new, file1, file2)
00843 char *old, *new;
00844 FILE *file1, *file2;
00845 {
00846 FILE *inputfp;
00847 struct stat statbuf;
00848 register char *s;
00849 char op;
00850 char *newmark, *oldmark;
00851 int len;
00852 char *line;
00853 int i, status;
00854
00855 oldfp = file1;
00856 newfp = file2;
00857
00858 oldalloc = 512;
00859 oldhunk = (char *) xmalloc(oldalloc);
00860 newalloc = 512;
00861 newhunk = (char *) xmalloc(newalloc);
00862
00863
00864
00865
00866
00867 if (trim_blanks == SET)
00868 sprintf(buff, "diff -b %s %s", old, new);
00869 else
00870 sprintf(buff, "diff %s %s", old, new);
00871
00872 inputfp = popen(buff, "r");
00873 if (!inputfp) {
00874 fprintf(stderr, "Can't execute diff %s %s, popen failed with %s\n",
00875 old, new, strerror(errno));
00876 exit(2);
00877 }
00878 preoldend = -1000;
00879 firstoutput = 1;
00880 oldline = newline = 0;
00881 while (fgets(buff, sizeof buff, inputfp) != Nullch) {
00882 if (firstoutput) {
00883 if (recursive_dir == SET) {
00884 printf("diff %s %s %s\n", options_string,
00885 oldfile, newfile);
00886 }
00887 fstat(fileno(oldfp), &statbuf);
00888 printf("*** %s %s", old, ctime(&statbuf.st_mtime));
00889 fstat(fileno(newfp), &statbuf);
00890 printf("--- %s %s", new, ctime(&statbuf.st_mtime));
00891 firstoutput = 0;
00892 }
00893 if (isdigit(*buff)) {
00894 oldmin = atoi(buff);
00895 for (s = buff; isdigit(*s); s++);
00896 if (*s == ',') {
00897 s++;
00898 oldmax = atoi(s);
00899 for (; isdigit(*s); s++);
00900 } else {
00901 oldmax = oldmin;
00902 }
00903 if (*s != 'a' && *s != 'd' && *s != 'c') {
00904 fprintf(stderr, "Unparseable input: %s", s);
00905 exit(2);
00906 }
00907 op = *s;
00908 s++;
00909 newmin = atoi(s);
00910 for (; isdigit(*s); s++);
00911 if (*s == ',') {
00912 s++;
00913 newmax = atoi(s);
00914 for (; isdigit(*s); s++);
00915 } else {
00916 newmax = newmin;
00917 }
00918 if (*s != '\n' && *s != ' ') {
00919 fprintf(stderr, "Unparseable input: %s", s);
00920 exit(2);
00921 }
00922 newmark = oldmark = "! ";
00923 if (op == 'a') {
00924 oldmin++;
00925 newmark = "+ ";
00926 }
00927 if (op == 'd') {
00928 newmin++;
00929 oldmark = "- ";
00930 }
00931 oldbeg = oldmin - context_lines;
00932 oldend = oldmax + context_lines;
00933 if (oldbeg < 1) oldbeg = 1;
00934 newbeg = newmin - context_lines;
00935 newend = newmax + context_lines;
00936 if (newbeg < 1) newbeg = 1;
00937
00938 if (preoldend < oldbeg - 1) {
00939 if (preoldend >= 0) {
00940 dumphunk();
00941 }
00942 preoldbeg = oldbeg;
00943 prenewbeg = newbeg;
00944 oldwanted = newwanted = 0;
00945 oldsize = newsize = 0;
00946 } else {
00947 oldbeg = preoldmax + 1;
00948 newbeg = prenewmax + 1;
00949 }
00950
00951 for (i = oldbeg; i <= oldmax; i++) {
00952 line = getold(i);
00953 if (!line) {
00954 oldend = oldmax = i - 1;
00955 break;
00956 }
00957 len = strlen(line) + 2;
00958 if (oldsize + len + 1 >= oldalloc) {
00959 oldalloc *= 2;
00960 oldhunk = (char *) xrealloc(oldhunk, oldalloc);
00961 }
00962 if (i >= oldmin) {
00963 strcpy(oldhunk + oldsize, oldmark);
00964 oldwanted++;
00965 } else {
00966 strcpy(oldhunk + oldsize, " ");
00967 }
00968 strcpy(oldhunk + oldsize + 2, line);
00969 oldsize += len;
00970 }
00971 preoldmax = oldmax;
00972 preoldend = oldend;
00973
00974 for (i = newbeg; i <= newmax; i++) {
00975 line = getnew(i);
00976 if (!line) {
00977 newend = newmax = i - 1;
00978 break;
00979 }
00980 len = strlen(line) + 2;
00981 if (newsize + len + 1 >= newalloc) {
00982 newalloc *= 2;
00983 newhunk = (char *) xrealloc(newhunk, newalloc);
00984 }
00985 if (i >= newmin) {
00986 strcpy(newhunk + newsize, newmark);
00987 newwanted++;
00988 } else {
00989 strcpy(newhunk + newsize, " ");
00990 }
00991 strcpy(newhunk + newsize + 2, line);
00992 newsize += len;
00993 }
00994 prenewmax = newmax;
00995 prenewend = newend;
00996 }
00997 }
00998 status = pclose(inputfp);
00999 if (status != 0) diffs++;
01000 if (!WIFEXITED(status) || WEXITSTATUS(status) > 1) severe_error = 1;
01001
01002 if (preoldend >= 0) {
01003 dumphunk();
01004 }
01005 }
01006
01007 void dumphunk()
01008 {
01009 int i;
01010 char *line;
01011 int len;
01012
01013 for (i = preoldmax + 1; i <= preoldend; i++) {
01014 line = getold(i);
01015 if (!line) {
01016 preoldend = i - 1;
01017 break;
01018 }
01019 len = strlen(line) + 2;
01020 if (oldsize + len + 1 >= oldalloc) {
01021 oldalloc *= 2;
01022 oldhunk = (char *) xrealloc(oldhunk, oldalloc);
01023 }
01024 strcpy(oldhunk + oldsize, " ");
01025 strcpy(oldhunk + oldsize + 2, line);
01026 oldsize += len;
01027 }
01028 for (i = prenewmax + 1; i <= prenewend; i++) {
01029 line = getnew(i);
01030 if (!line) {
01031 prenewend = i - 1;
01032 break;
01033 }
01034 len = strlen(line) + 2;
01035 if (newsize + len + 1 >= newalloc) {
01036 newalloc *= 2;
01037 newhunk = (char *) xrealloc(newhunk, newalloc);
01038 }
01039 strcpy(newhunk + newsize, " ");
01040 strcpy(newhunk + newsize + 2, line);
01041 newsize += len;
01042 }
01043 fputs("***************\n", stdout);
01044 if (preoldbeg >= preoldend) {
01045 printf("*** %d ****\n", preoldend);
01046 } else {
01047 printf("*** %d,%d ****\n", preoldbeg, preoldend);
01048 }
01049 if (oldwanted) {
01050 fputs(oldhunk, stdout);
01051 }
01052 oldsize = 0;
01053 *oldhunk = '\0';
01054 if (prenewbeg >= prenewend) {
01055 printf("--- %d ----\n", prenewend);
01056 } else {
01057 printf("--- %d,%d ----\n", prenewbeg, prenewend);
01058 }
01059 if (newwanted) {
01060 fputs(newhunk, stdout);
01061 }
01062 newsize = 0;
01063 *newhunk = '\0';
01064 }
01065
01066 char *getold(targ)
01067 int targ;
01068 {
01069 while (fgets(buff, sizeof buff, oldfp) != Nullch) {
01070 oldline++;
01071 if (oldline == targ) return buff;
01072 }
01073 return Nullch;
01074 }
01075
01076 char *getnew(targ)
01077 int targ;
01078 {
01079 while (fgets(buff, sizeof buff, newfp) != Nullch) {
01080 newline++;
01081 if (newline == targ) return buff;
01082 }
01083 return Nullch;
01084 }
01085
01086
01087
01088
01089
01090 int isdir(path)
01091 char *path;
01092 {
01093 struct stat buf;
01094 stat(path, &buf);
01095 if (buf.st_mode & S_IFDIR) {
01096 return(~0);
01097 } else {
01098 return(0);
01099 }
01100 }
01101
01102
01103
01104
01105
01106
01107 void diff_recursive(dir1, dir2)
01108 char *dir1, *dir2;
01109 {
01110 FILE *ls1, *ls2;
01111 char file1[PATH_MAX], file2[PATH_MAX];
01112 char jointfile1[PATH_MAX], jointfile2[PATH_MAX];
01113 char command[PATH_MAX];
01114 int difference, eof1, eof2;
01115
01116 sprintf(command, "ls %s", dir1);
01117 ls1 = popen(command, "r");
01118 sprintf(command, "ls %s", dir2);
01119 ls2 = popen(command, "r");
01120
01121 if ((ls1 == NULL) || (ls2 == NULL))
01122 fatal_error("cannot execute ls!", "");
01123
01124 file1[0] = '\0';
01125 eof1 = fscanf(ls1, "%s\n", file1);
01126 file2[0] = '\0';
01127 eof2 = fscanf(ls2, "%s\n", file2);
01128
01129 while ((file1[0] != '\0') && (file2[0] != '\0')) {
01130 difference = strcmp(file1, file2);
01131 while (difference != 0) {
01132 if (difference < 0) {
01133 printf("Only in %s: %s\n", dir1, file1);
01134 file1[0] = '\0';
01135 eof1 = fscanf(ls1, "%s\n", file1);
01136 if (file1[0] == '\0') break;
01137 } else {
01138 printf("Only in %s: %s\n", dir2, file2);
01139 file2[0] = '\0';
01140 eof2 = fscanf(ls2, "%s\n", file2);
01141 if (file2[0] == '\0') break;
01142 }
01143 difference = strcmp(file1, file2);
01144 }
01145 if (eof1 != EOF && eof2 != EOF) {
01146 strcpy(jointfile1, dir1);
01147 strcat(jointfile1, "/");
01148 strcat(jointfile1, file1);
01149 strcpy(jointfile2, dir2);
01150 strcat(jointfile2, "/");
01151 strcat(jointfile2, file2);
01152
01153 if ((isdir(jointfile1) != 0) && (isdir(jointfile2) != 0)) {
01154 printf("Common subdirectories: %s and %s\n",
01155 jointfile1, jointfile2);
01156 diff_recursive(jointfile1, jointfile2);
01157 } else {
01158 firstoutput = 1;
01159 strcpy(oldfile, jointfile1);
01160 strcpy(newfile, jointfile2);
01161 diff(jointfile1, jointfile2);
01162 }
01163 file1[0] = '\0';
01164 eof1 = fscanf(ls1, "%s\n", file1);
01165 file2[0] = '\0';
01166 eof2 = fscanf(ls2, "%s\n", file2);
01167 }
01168 }
01169
01170 if (file1[0] != '\0') {
01171 do {
01172 printf("Only in %s: %s\n", dir1, file1);
01173 eof1 = fscanf(ls1, " %s\n", file1);
01174 } while (eof1 != EOF);
01175 }
01176 if (file2[0] != '\0') {
01177 do {
01178 printf("Only in %s: %s\n", dir2, file2);
01179 eof2 = fscanf(ls2, " %s\n", file2);
01180 } while (eof2 != EOF);
01181 }
01182 if (pclose(ls1) != 0) severe_error = 1;
01183 if (pclose(ls2) != 0) severe_error = 1;
01184 }
01185
01186
01187
01188
01189
01190 void file_type_error(filename1, filename2, statbuf1, statbuf2)
01191 char *filename1, *filename2;
01192 struct stat *statbuf1, *statbuf2;
01193 {
01194 char type1[25], type2[25];
01195
01196 switch (statbuf1->st_mode & S_IFMT) {
01197 case S_IFREG:
01198 sprintf(type1, "regular file ");
01199 break;
01200 case S_IFBLK:
01201 sprintf(type1, "block special file ");
01202 break;
01203 case S_IFDIR: sprintf(type1, "directory "); break;
01204 case S_IFCHR:
01205 sprintf(type1, "character special file ");
01206 break;
01207 case S_IFIFO:
01208 sprintf(type1, "FIFO special file ");
01209 break;
01210 }
01211
01212 switch (statbuf2->st_mode & S_IFMT) {
01213 case S_IFREG:
01214 sprintf(type2, "regular file ");
01215 break;
01216 case S_IFBLK:
01217 sprintf(type2, "block special file ");
01218 break;
01219 case S_IFDIR: sprintf(type2, "directory "); break;
01220 case S_IFCHR:
01221 sprintf(type2, "character special file ");
01222 break;
01223 case S_IFIFO:
01224 sprintf(type2, "FIFO special file ");
01225 break;
01226 }
01227 printf("File %s is a %s while file %s is a %s\n",
01228 filename1, type1, filename2, type2);
01229 }
01230
01231 void *xmalloc(size)
01232 size_t size;
01233 {
01234 void *ptr;
01235
01236 ptr = malloc(size);
01237 if (ptr == NULL) {
01238 fprintf(stderr, "%s: out of memory\n", progname);
01239 exit(2);
01240 }
01241 return(ptr);
01242 }
01243
01244 void *xrealloc(ptr, size)
01245 void *ptr;
01246 size_t size;
01247 {
01248 ptr = realloc(ptr, size);
01249 if (ptr == NULL) {
01250 fprintf(stderr, "%s: out of memory\n", progname);
01251 exit(2);
01252 }
01253 return(ptr);
01254 }