1 /* Support routines for GNU DIFF. 2 Copyright (C) 1988, 1989, 1992, 1993, 1994, 1997, 1998 Free Software Foundation, Inc. 3 4 This file is part of GNU DIFF. 5 6 GNU DIFF is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 2, or (at your option) 9 any later version. 10 11 GNU DIFF is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 */ 17 18 #include "diff.h" 19 20 #if __STDC__ 21 #include <stdarg.h> 22 #else 23 #include <varargs.h> 24 #endif 25 26 #ifndef strerror 27 extern char *strerror (); 28 #endif 29 30 /* Queue up one-line messages to be printed at the end, 31 when -l is specified. Each message is recorded with a `struct msg'. */ 32 33 struct msg 34 { 35 struct msg *next; 36 char const *format; 37 char const *arg1; 38 char const *arg2; 39 char const *arg3; 40 char const *arg4; 41 }; 42 43 /* Head of the chain of queues messages. */ 44 45 static struct msg *msg_chain; 46 47 /* Tail of the chain of queues messages. */ 48 49 static struct msg **msg_chain_end = &msg_chain; 50 51 /* Use when a system call returns non-zero status. 52 TEXT should normally be the file name. */ 53 54 void 55 perror_with_name (text) 56 char const *text; 57 { 58 int e = errno; 59 60 if (callbacks && callbacks->error) 61 (*callbacks->error) ("%s: %s", text, strerror (e)); 62 else 63 { 64 fprintf (stderr, "%s: ", diff_program_name); 65 errno = e; 66 perror (text); 67 } 68 } 69 70 /* Use when a system call returns non-zero status and that is fatal. */ 71 72 void 73 pfatal_with_name (text) 74 char const *text; 75 { 76 int e = errno; 77 print_message_queue (); 78 if (callbacks && callbacks->error) 79 (*callbacks->error) ("%s: %s", text, strerror (e)); 80 else 81 { 82 fprintf (stderr, "%s: ", diff_program_name); 83 errno = e; 84 perror (text); 85 } 86 DIFF_ABORT (2); 87 } 88 89 /* Print an error message from the format-string FORMAT 90 with args ARG1 and ARG2. */ 91 92 void 93 diff_error (format, arg, arg1) 94 char const *format, *arg, *arg1; 95 { 96 if (callbacks && callbacks->error) 97 (*callbacks->error) (format, arg, arg1); 98 else 99 { 100 fprintf (stderr, "%s: ", diff_program_name); 101 fprintf (stderr, format, arg, arg1); 102 fprintf (stderr, "\n"); 103 } 104 } 105 106 /* Print an error message containing the string TEXT, then exit. */ 107 108 void 109 fatal (m) 110 char const *m; 111 { 112 print_message_queue (); 113 diff_error ("%s", m, 0); 114 DIFF_ABORT (2); 115 } 116 117 /* Like printf, except if -l in effect then save the message and print later. 118 This is used for things like "binary files differ" and "Only in ...". */ 119 120 void 121 message (format, arg1, arg2) 122 char const *format, *arg1, *arg2; 123 { 124 message5 (format, arg1, arg2, 0, 0); 125 } 126 127 void 128 message5 (format, arg1, arg2, arg3, arg4) 129 char const *format, *arg1, *arg2, *arg3, *arg4; 130 { 131 if (paginate_flag) 132 { 133 struct msg *new = (struct msg *) xmalloc (sizeof (struct msg)); 134 new->format = format; 135 new->arg1 = concat (arg1, "", ""); 136 new->arg2 = concat (arg2, "", ""); 137 new->arg3 = arg3 ? concat (arg3, "", "") : 0; 138 new->arg4 = arg4 ? concat (arg4, "", "") : 0; 139 new->next = 0; 140 *msg_chain_end = new; 141 msg_chain_end = &new->next; 142 } 143 else 144 { 145 if (sdiff_help_sdiff) 146 write_output (" ", 1); 147 printf_output (format, arg1, arg2, arg3, arg4); 148 } 149 } 150 151 /* Output all the messages that were saved up by calls to `message'. */ 152 153 void 154 print_message_queue () 155 { 156 struct msg *m; 157 158 for (m = msg_chain; m; m = m->next) 159 printf_output (m->format, m->arg1, m->arg2, m->arg3, m->arg4); 160 } 161 162 /* Call before outputting the results of comparing files NAME0 and NAME1 163 to set up OUTFILE, the stdio stream for the output to go to. 164 165 Usually, OUTFILE is just stdout. But when -l was specified 166 we fork off a `pr' and make OUTFILE a pipe to it. 167 `pr' then outputs to our stdout. */ 168 169 static char const *current_name0; 170 static char const *current_name1; 171 static int current_depth; 172 173 static int output_in_progress = 0; 174 175 void 176 setup_output (name0, name1, depth) 177 char const *name0, *name1; 178 int depth; 179 { 180 current_name0 = name0; 181 current_name1 = name1; 182 current_depth = depth; 183 } 184 185 #if HAVE_FORK && defined (PR_PROGRAM) 186 static pid_t pr_pid; 187 #endif 188 189 void 190 begin_output () 191 { 192 char *name; 193 194 if (output_in_progress) 195 return; 196 output_in_progress = 1; 197 198 /* Construct the header of this piece of diff. */ 199 name = xmalloc (strlen (current_name0) + strlen (current_name1) 200 + strlen (switch_string) + 7); 201 /* Posix.2 section 4.17.6.1.1 specifies this format. But there is a 202 bug in the first printing (IEEE Std 1003.2-1992 p 251 l 3304): 203 it says that we must print only the last component of the pathnames. 204 This requirement is silly and does not match historical practice. */ 205 sprintf (name, "diff%s %s %s", switch_string, current_name0, current_name1); 206 207 if (paginate_flag && callbacks && callbacks->write_output) 208 fatal ("can't paginate when using library callbacks"); 209 210 if (paginate_flag) 211 { 212 /* Make OUTFILE a pipe to a subsidiary `pr'. */ 213 214 #ifdef PR_PROGRAM 215 216 # if HAVE_FORK 217 int pipes[2]; 218 219 if (pipe (pipes) != 0) 220 pfatal_with_name ("pipe"); 221 222 fflush (stdout); 223 224 pr_pid = vfork (); 225 if (pr_pid < 0) 226 pfatal_with_name ("vfork"); 227 228 if (pr_pid == 0) 229 { 230 close (pipes[1]); 231 if (pipes[0] != STDIN_FILENO) 232 { 233 if (dup2 (pipes[0], STDIN_FILENO) < 0) 234 pfatal_with_name ("dup2"); 235 close (pipes[0]); 236 } 237 238 execl (PR_PROGRAM, PR_PROGRAM, "-f", "-h", name, (char *)NULL); 239 pfatal_with_name (PR_PROGRAM); 240 } 241 else 242 { 243 close (pipes[0]); 244 outfile = fdopen (pipes[1], "w"); 245 if (!outfile) 246 pfatal_with_name ("fdopen"); 247 } 248 # else /* ! HAVE_FORK */ 249 char *command = xmalloc (4 * strlen (name) + strlen (PR_PROGRAM) + 10); 250 char *p; 251 char const *a = name; 252 sprintf (command, "%s -f -h ", PR_PROGRAM); 253 p = command + strlen (command); 254 SYSTEM_QUOTE_ARG (p, a); 255 *p = 0; 256 outfile = popen (command, "w"); 257 if (!outfile) 258 pfatal_with_name (command); 259 free (command); 260 # endif /* ! HAVE_FORK */ 261 #else 262 fatal ("This port does not support the --paginate option to diff."); 263 #endif 264 } 265 else 266 { 267 268 /* If -l was not specified, output the diff straight to `stdout'. */ 269 270 /* If handling multiple files (because scanning a directory), 271 print which files the following output is about. */ 272 if (current_depth > 0) 273 printf_output ("%s\n", name); 274 } 275 276 free (name); 277 278 /* A special header is needed at the beginning of context output. */ 279 switch (output_style) 280 { 281 case OUTPUT_CONTEXT: 282 print_context_header (files, 0); 283 break; 284 285 case OUTPUT_UNIFIED: 286 print_context_header (files, 1); 287 break; 288 289 default: 290 break; 291 } 292 } 293 294 /* Call after the end of output of diffs for one file. 295 If -l was given, close OUTFILE and get rid of the `pr' subfork. */ 296 297 void 298 finish_output () 299 { 300 if (paginate_flag && outfile != 0 && outfile != stdout) 301 { 302 #ifdef PR_PROGRAM 303 int wstatus; 304 if (ferror (outfile)) 305 fatal ("write error"); 306 # if ! HAVE_FORK 307 wstatus = pclose (outfile); 308 # else /* HAVE_FORK */ 309 if (fclose (outfile) != 0) 310 pfatal_with_name ("write error"); 311 if (waitpid (pr_pid, &wstatus, 0) < 0) 312 pfatal_with_name ("waitpid"); 313 # endif /* HAVE_FORK */ 314 if (wstatus != 0) 315 fatal ("subsidiary pr failed"); 316 #else 317 fatal ("internal error in finish_output"); 318 #endif 319 } 320 321 output_in_progress = 0; 322 } 323 324 /* Write something to the output file. */ 325 326 void 327 write_output (text, len) 328 char const *text; 329 size_t len; 330 { 331 if (callbacks && callbacks->write_output) 332 (*callbacks->write_output) (text, len); 333 else if (len == 1) 334 putc (*text, outfile); 335 else 336 fwrite (text, sizeof (char), len, outfile); 337 } 338 339 /* Printf something to the output file. */ 340 341 #if __STDC__ 342 #define VA_START(args, lastarg) va_start(args, lastarg) 343 #else /* ! __STDC__ */ 344 #define VA_START(args, lastarg) va_start(args) 345 #endif /* __STDC__ */ 346 347 void 348 #if __STDC__ 349 printf_output (const char *format, ...) 350 #else 351 printf_output (format, va_alist) 352 char const *format; 353 va_dcl 354 #endif 355 { 356 va_list args; 357 358 VA_START (args, format); 359 if (callbacks && callbacks->write_output) 360 { 361 /* We implement our own limited printf-like functionality (%s, %d, 362 and %c only). Callers who want something fancier can use 363 sprintf. */ 364 const char *p = format; 365 char *q; 366 char *str; 367 int num; 368 int ch; 369 char buf[100]; 370 371 while ((q = strchr (p, '%')) != NULL) 372 { 373 static const char msg[] = 374 "\ninternal error: bad % in printf_output\n"; 375 (*callbacks->write_output) (p, q - p); 376 377 switch (q[1]) 378 { 379 case 's': 380 str = va_arg (args, char *); 381 (*callbacks->write_output) (str, strlen (str)); 382 break; 383 case 'd': 384 num = va_arg (args, int); 385 sprintf (buf, "%d", num); 386 (*callbacks->write_output) (buf, strlen (buf)); 387 break; 388 case 'c': 389 ch = va_arg (args, int); 390 buf[0] = ch; 391 (*callbacks->write_output) (buf, 1); 392 break; 393 default: 394 (*callbacks->write_output) (msg, sizeof (msg) - 1); 395 /* Don't just keep going, because q + 1 might point to the 396 terminating '\0'. */ 397 goto out; 398 } 399 p = q + 2; 400 } 401 (*callbacks->write_output) (p, strlen (p)); 402 } 403 else 404 vfprintf (outfile, format, args); 405 out: 406 va_end (args); 407 } 408 409 /* Flush the output file. */ 410 411 void 412 flush_output () 413 { 414 if (callbacks && callbacks->flush_output) 415 (*callbacks->flush_output) (); 416 else 417 fflush (outfile); 418 } 419 420 /* Compare two lines (typically one from each input file) 421 according to the command line options. 422 For efficiency, this is invoked only when the lines do not match exactly 423 but an option like -i might cause us to ignore the difference. 424 Return nonzero if the lines differ. */ 425 426 int 427 line_cmp (s1, s2) 428 char const *s1, *s2; 429 { 430 register unsigned char const *t1 = (unsigned char const *) s1; 431 register unsigned char const *t2 = (unsigned char const *) s2; 432 433 while (1) 434 { 435 register unsigned char c1 = *t1++; 436 register unsigned char c2 = *t2++; 437 438 /* Test for exact char equality first, since it's a common case. */ 439 if (c1 != c2) 440 { 441 /* Ignore horizontal white space if -b or -w is specified. */ 442 443 if (ignore_all_space_flag) 444 { 445 /* For -w, just skip past any white space. */ 446 while (ISSPACE (c1) && c1 != '\n') c1 = *t1++; 447 while (ISSPACE (c2) && c2 != '\n') c2 = *t2++; 448 } 449 else if (ignore_space_change_flag) 450 { 451 /* For -b, advance past any sequence of white space in line 1 452 and consider it just one Space, or nothing at all 453 if it is at the end of the line. */ 454 if (ISSPACE (c1)) 455 { 456 while (c1 != '\n') 457 { 458 c1 = *t1++; 459 if (! ISSPACE (c1)) 460 { 461 --t1; 462 c1 = ' '; 463 break; 464 } 465 } 466 } 467 468 /* Likewise for line 2. */ 469 if (ISSPACE (c2)) 470 { 471 while (c2 != '\n') 472 { 473 c2 = *t2++; 474 if (! ISSPACE (c2)) 475 { 476 --t2; 477 c2 = ' '; 478 break; 479 } 480 } 481 } 482 483 if (c1 != c2) 484 { 485 /* If we went too far when doing the simple test 486 for equality, go back to the first non-white-space 487 character in both sides and try again. */ 488 if (c2 == ' ' && c1 != '\n' 489 && (unsigned char const *) s1 + 1 < t1 490 && ISSPACE(t1[-2])) 491 { 492 --t1; 493 continue; 494 } 495 if (c1 == ' ' && c2 != '\n' 496 && (unsigned char const *) s2 + 1 < t2 497 && ISSPACE(t2[-2])) 498 { 499 --t2; 500 continue; 501 } 502 } 503 } 504 505 /* Lowercase all letters if -i is specified. */ 506 507 if (ignore_case_flag) 508 { 509 if (ISUPPER (c1)) 510 c1 = tolower (c1); 511 if (ISUPPER (c2)) 512 c2 = tolower (c2); 513 } 514 515 if (c1 != c2) 516 break; 517 } 518 if (c1 == '\n') 519 return 0; 520 } 521 522 return (1); 523 } 524 525 /* Find the consecutive changes at the start of the script START. 526 Return the last link before the first gap. */ 527 528 struct change * 529 find_change (start) 530 struct change *start; 531 { 532 return start; 533 } 534 535 struct change * 536 find_reverse_change (start) 537 struct change *start; 538 { 539 return start; 540 } 541 542 /* Divide SCRIPT into pieces by calling HUNKFUN and 543 print each piece with PRINTFUN. 544 Both functions take one arg, an edit script. 545 546 HUNKFUN is called with the tail of the script 547 and returns the last link that belongs together with the start 548 of the tail. 549 550 PRINTFUN takes a subscript which belongs together (with a null 551 link at the end) and prints it. */ 552 553 void 554 print_script (script, hunkfun, printfun) 555 struct change *script; 556 struct change * (*hunkfun) PARAMS((struct change *)); 557 void (*printfun) PARAMS((struct change *)); 558 { 559 struct change *next = script; 560 561 while (next) 562 { 563 struct change *this, *end; 564 565 /* Find a set of changes that belong together. */ 566 this = next; 567 end = (*hunkfun) (next); 568 569 /* Disconnect them from the rest of the changes, 570 making them a hunk, and remember the rest for next iteration. */ 571 next = end->link; 572 end->link = 0; 573 #ifdef DEBUG 574 debug_script (this); 575 #endif 576 577 /* Print this hunk. */ 578 (*printfun) (this); 579 580 /* Reconnect the script so it will all be freed properly. */ 581 end->link = next; 582 } 583 } 584 585 /* Print the text of a single line LINE, 586 flagging it with the characters in LINE_FLAG (which say whether 587 the line is inserted, deleted, changed, etc.). */ 588 589 void 590 print_1_line (line_flag, line) 591 char const *line_flag; 592 char const * const *line; 593 { 594 char const *text = line[0], *limit = line[1]; /* Help the compiler. */ 595 char const *flag_format = 0; 596 597 /* If -T was specified, use a Tab between the line-flag and the text. 598 Otherwise use a Space (as Unix diff does). 599 Print neither space nor tab if line-flags are empty. */ 600 601 if (line_flag && *line_flag) 602 { 603 flag_format = tab_align_flag ? "%s\t" : "%s "; 604 printf_output (flag_format, line_flag); 605 } 606 607 output_1_line (text, limit, flag_format, line_flag); 608 609 if ((!line_flag || line_flag[0]) && limit[-1] != '\n') 610 printf_output ("\n\\ No newline at end of file\n"); 611 } 612 613 /* Output a line from TEXT up to LIMIT. Without -t, output verbatim. 614 With -t, expand white space characters to spaces, and if FLAG_FORMAT 615 is nonzero, output it with argument LINE_FLAG after every 616 internal carriage return, so that tab stops continue to line up. */ 617 618 void 619 output_1_line (text, limit, flag_format, line_flag) 620 char const *text, *limit, *flag_format, *line_flag; 621 { 622 if (!tab_expand_flag) 623 write_output (text, limit - text); 624 else 625 { 626 register unsigned char c; 627 register char const *t = text; 628 register unsigned column = 0; 629 /* CC is used to avoid taking the address of the register 630 variable C. */ 631 char cc; 632 633 while (t < limit) 634 switch ((c = *t++)) 635 { 636 case '\t': 637 { 638 unsigned spaces = TAB_WIDTH - column % TAB_WIDTH; 639 column += spaces; 640 do 641 write_output (" ", 1); 642 while (--spaces); 643 } 644 break; 645 646 case '\r': 647 write_output ("\r", 1); 648 if (flag_format && t < limit && *t != '\n') 649 printf_output (flag_format, line_flag); 650 column = 0; 651 break; 652 653 case '\b': 654 if (column == 0) 655 continue; 656 column--; 657 write_output ("\b", 1); 658 break; 659 660 default: 661 if (ISPRINT (c)) 662 column++; 663 cc = c; 664 write_output (&cc, 1); 665 break; 666 } 667 } 668 } 669 670 int 671 change_letter (inserts, deletes) 672 int inserts, deletes; 673 { 674 if (!inserts) 675 return 'd'; 676 else if (!deletes) 677 return 'a'; 678 else 679 return 'c'; 680 } 681 682 /* Translate an internal line number (an index into diff's table of lines) 683 into an actual line number in the input file. 684 The internal line number is LNUM. FILE points to the data on the file. 685 686 Internal line numbers count from 0 starting after the prefix. 687 Actual line numbers count from 1 within the entire file. */ 688 689 int 690 translate_line_number (file, lnum) 691 struct file_data const *file; 692 int lnum; 693 { 694 return lnum + file->prefix_lines + 1; 695 } 696 697 void 698 translate_range (file, a, b, aptr, bptr) 699 struct file_data const *file; 700 int a, b; 701 int *aptr, *bptr; 702 { 703 *aptr = translate_line_number (file, a - 1) + 1; 704 *bptr = translate_line_number (file, b + 1) - 1; 705 } 706 707 /* Print a pair of line numbers with SEPCHAR, translated for file FILE. 708 If the two numbers are identical, print just one number. 709 710 Args A and B are internal line numbers. 711 We print the translated (real) line numbers. */ 712 713 void 714 print_number_range (sepchar, file, a, b) 715 int sepchar; 716 struct file_data *file; 717 int a, b; 718 { 719 int trans_a, trans_b; 720 translate_range (file, a, b, &trans_a, &trans_b); 721 722 /* Note: we can have B < A in the case of a range of no lines. 723 In this case, we should print the line number before the range, 724 which is B. */ 725 if (trans_b > trans_a) 726 printf_output ("%d%c%d", trans_a, sepchar, trans_b); 727 else 728 printf_output ("%d", trans_b); 729 } 730 731 /* Look at a hunk of edit script and report the range of lines in each file 732 that it applies to. HUNK is the start of the hunk, which is a chain 733 of `struct change'. The first and last line numbers of file 0 are stored in 734 *FIRST0 and *LAST0, and likewise for file 1 in *FIRST1 and *LAST1. 735 Note that these are internal line numbers that count from 0. 736 737 If no lines from file 0 are deleted, then FIRST0 is LAST0+1. 738 739 Also set *DELETES nonzero if any lines of file 0 are deleted 740 and set *INSERTS nonzero if any lines of file 1 are inserted. 741 If only ignorable lines are inserted or deleted, both are 742 set to 0. */ 743 744 void 745 analyze_hunk (hunk, first0, last0, first1, last1, deletes, inserts) 746 struct change *hunk; 747 int *first0, *last0, *first1, *last1; 748 int *deletes, *inserts; 749 { 750 int l0, l1, show_from, show_to; 751 int i; 752 int trivial = ignore_blank_lines_flag || ignore_regexp_list; 753 struct change *next; 754 755 show_from = show_to = 0; 756 757 *first0 = hunk->line0; 758 *first1 = hunk->line1; 759 760 next = hunk; 761 do 762 { 763 l0 = next->line0 + next->deleted - 1; 764 l1 = next->line1 + next->inserted - 1; 765 show_from += next->deleted; 766 show_to += next->inserted; 767 768 for (i = next->line0; i <= l0 && trivial; i++) 769 if (!ignore_blank_lines_flag || files[0].linbuf[i][0] != '\n') 770 { 771 struct regexp_list *r; 772 char const *line = files[0].linbuf[i]; 773 int len = files[0].linbuf[i + 1] - line; 774 775 for (r = ignore_regexp_list; r; r = r->next) 776 if (0 <= re_search (&r->buf, line, len, 0, len, 0)) 777 break; /* Found a match. Ignore this line. */ 778 /* If we got all the way through the regexp list without 779 finding a match, then it's nontrivial. */ 780 if (!r) 781 trivial = 0; 782 } 783 784 for (i = next->line1; i <= l1 && trivial; i++) 785 if (!ignore_blank_lines_flag || files[1].linbuf[i][0] != '\n') 786 { 787 struct regexp_list *r; 788 char const *line = files[1].linbuf[i]; 789 int len = files[1].linbuf[i + 1] - line; 790 791 for (r = ignore_regexp_list; r; r = r->next) 792 if (0 <= re_search (&r->buf, line, len, 0, len, 0)) 793 break; /* Found a match. Ignore this line. */ 794 /* If we got all the way through the regexp list without 795 finding a match, then it's nontrivial. */ 796 if (!r) 797 trivial = 0; 798 } 799 } 800 while ((next = next->link) != 0); 801 802 *last0 = l0; 803 *last1 = l1; 804 805 /* If all inserted or deleted lines are ignorable, 806 tell the caller to ignore this hunk. */ 807 808 if (trivial) 809 show_from = show_to = 0; 810 811 *deletes = show_from; 812 *inserts = show_to; 813 } 814 815 /* Concatenate three strings, returning a newly malloc'd string. */ 816 817 char * 818 concat (s1, s2, s3) 819 char const *s1, *s2, *s3; 820 { 821 size_t len = strlen (s1) + strlen (s2) + strlen (s3); 822 char *new = xmalloc (len + 1); 823 sprintf (new, "%s%s%s", s1, s2, s3); 824 return new; 825 } 826 827 /* Yield the newly malloc'd pathname 828 of the file in DIR whose filename is FILE. */ 829 830 char * 831 dir_file_pathname (dir, file) 832 char const *dir, *file; 833 { 834 char const *p = filename_lastdirchar (dir); 835 return concat (dir, "/" + (p && !p[1]), file); 836 } 837 838 void 839 debug_script (sp) 840 struct change *sp; 841 { 842 fflush (stdout); 843 for (; sp; sp = sp->link) 844 fprintf (stderr, "%3d %3d delete %d insert %d\n", 845 sp->line0, sp->line1, sp->deleted, sp->inserted); 846 fflush (stderr); 847 } 848