1 /* Support routines for GNU DIFF. 2 3 Copyright (C) 1988-1989, 1992-1995, 1998, 2001-2002, 2004, 2006, 2009-2013 4 Free Software Foundation, Inc. 5 6 This file is part of GNU DIFF. 7 8 This program is free software: you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation, either version 3 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 20 21 #include "diff.h" 22 #include <dirname.h> 23 #include <error.h> 24 #include <system-quote.h> 25 #include <xalloc.h> 26 #include "xvasprintf.h" 27 28 char const pr_program[] = PR_PROGRAM; 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 args[1]; /* Format + 4 args, each '\0' terminated, concatenated. */ 37 }; 38 39 /* Head of the chain of queues messages. */ 40 41 static struct msg *msg_chain; 42 43 /* Tail of the chain of queues messages. */ 44 45 static struct msg **msg_chain_end = &msg_chain; 46 47 /* Use when a system call returns non-zero status. 48 NAME should normally be the file name. */ 49 50 void 51 perror_with_name (char const *name) 52 { 53 error (0, errno, "%s", name); 54 } 55 56 /* Use when a system call returns non-zero status and that is fatal. */ 57 58 void 59 pfatal_with_name (char const *name) 60 { 61 int e = errno; 62 print_message_queue (); 63 error (EXIT_TROUBLE, e, "%s", name); 64 abort (); 65 } 66 67 /* Print an error message containing MSGID, then exit. */ 68 69 void 70 fatal (char const *msgid) 71 { 72 print_message_queue (); 73 error (EXIT_TROUBLE, 0, "%s", _(msgid)); 74 abort (); 75 } 76 77 /* Like printf, except if -l in effect then save the message and print later. 78 This is used for things like "Only in ...". */ 79 80 void 81 message (char const *format_msgid, char const *arg1, char const *arg2) 82 { 83 message5 (format_msgid, arg1, arg2, 0, 0); 84 } 85 86 void 87 message5 (char const *format_msgid, char const *arg1, char const *arg2, 88 char const *arg3, char const *arg4) 89 { 90 if (paginate) 91 { 92 char *p; 93 char const *arg[5]; 94 int i; 95 size_t size[5]; 96 size_t total_size = offsetof (struct msg, args); 97 struct msg *new; 98 99 arg[0] = format_msgid; 100 arg[1] = arg1; 101 arg[2] = arg2; 102 arg[3] = arg3 ? arg3 : ""; 103 arg[4] = arg4 ? arg4 : ""; 104 105 for (i = 0; i < 5; i++) 106 total_size += size[i] = strlen (arg[i]) + 1; 107 108 new = xmalloc (total_size); 109 110 for (i = 0, p = new->args; i < 5; p += size[i++]) 111 memcpy (p, arg[i], size[i]); 112 113 *msg_chain_end = new; 114 new->next = 0; 115 msg_chain_end = &new->next; 116 } 117 else 118 { 119 if (sdiff_merge_assist) 120 putchar (' '); 121 printf (_(format_msgid), arg1, arg2, arg3, arg4); 122 } 123 } 124 125 /* Output all the messages that were saved up by calls to 'message'. */ 126 127 void 128 print_message_queue (void) 129 { 130 char const *arg[5]; 131 int i; 132 struct msg *m = msg_chain; 133 134 while (m) 135 { 136 struct msg *next = m->next; 137 arg[0] = m->args; 138 for (i = 0; i < 4; i++) 139 arg[i + 1] = arg[i] + strlen (arg[i]) + 1; 140 printf (_(arg[0]), arg[1], arg[2], arg[3], arg[4]); 141 free (m); 142 m = next; 143 } 144 } 145 146 /* Call before outputting the results of comparing files NAME0 and NAME1 147 to set up OUTFILE, the stdio stream for the output to go to. 148 149 Usually, OUTFILE is just stdout. But when -l was specified 150 we fork off a 'pr' and make OUTFILE a pipe to it. 151 'pr' then outputs to our stdout. */ 152 153 static char const *current_name0; 154 static char const *current_name1; 155 static bool currently_recursive; 156 157 void 158 setup_output (char const *name0, char const *name1, bool recursive) 159 { 160 current_name0 = name0; 161 current_name1 = name1; 162 currently_recursive = recursive; 163 outfile = 0; 164 } 165 166 #if HAVE_WORKING_FORK 167 static pid_t pr_pid; 168 #endif 169 170 static char c_escape_char (char c) 171 { 172 switch (c) { 173 case '\a': return 'a'; 174 case '\b': return 'b'; 175 case '\t': return 't'; 176 case '\n': return 'n'; 177 case '\v': return 'v'; 178 case '\f': return 'f'; 179 case '\r': return 'r'; 180 case '"': return '"'; 181 case '\\': return '\\'; 182 default: 183 return c < 32; 184 } 185 } 186 187 static char * 188 c_escape (char const *str) 189 { 190 char const *s; 191 size_t plus = 0; 192 bool must_quote = false; 193 194 for (s = str; *s; s++) 195 { 196 char c = *s; 197 198 if (c == ' ') 199 { 200 must_quote = true; 201 continue; 202 } 203 switch (c_escape_char (*s)) 204 { 205 case 1: 206 plus += 3; 207 /* fall through */ 208 case 0: 209 break; 210 default: 211 plus++; 212 break; 213 } 214 } 215 216 if (must_quote || plus) 217 { 218 size_t s_len = s - str; 219 char *buffer = xmalloc (s_len + plus + 3); 220 char *b = buffer; 221 222 *b++ = '"'; 223 for (s = str; *s; s++) 224 { 225 char c = *s; 226 char escape = c_escape_char (c); 227 228 switch (escape) 229 { 230 case 0: 231 *b++ = c; 232 break; 233 case 1: 234 *b++ = '\\'; 235 *b++ = ((c >> 6) & 03) + '0'; 236 *b++ = ((c >> 3) & 07) + '0'; 237 *b++ = ((c >> 0) & 07) + '0'; 238 break; 239 default: 240 *b++ = '\\'; 241 *b++ = escape; 242 break; 243 } 244 } 245 *b++ = '"'; 246 *b = 0; 247 return buffer; 248 } 249 250 return (char *) str; 251 } 252 253 void 254 begin_output (void) 255 { 256 char *names[2]; 257 char *name; 258 259 if (outfile != 0) 260 return; 261 262 names[0] = c_escape (current_name0); 263 names[1] = c_escape (current_name1); 264 265 /* Construct the header of this piece of diff. */ 266 /* POSIX 1003.1-2001 specifies this format. But there are some bugs in 267 the standard: it says that we must print only the last component 268 of the pathnames, and it requires two spaces after "diff" if 269 there are no options. These requirements are silly and do not 270 match historical practice. */ 271 name = xasprintf ("diff%s %s %s", switch_string, names[0], names[1]); 272 273 if (paginate) 274 { 275 char const *argv[4]; 276 277 if (fflush (stdout) != 0) 278 pfatal_with_name (_("write failed")); 279 280 argv[0] = pr_program; 281 argv[1] = "-h"; 282 argv[2] = name; 283 argv[3] = 0; 284 285 /* Make OUTFILE a pipe to a subsidiary 'pr'. */ 286 { 287 #if HAVE_WORKING_FORK 288 int pipes[2]; 289 290 if (pipe (pipes) != 0) 291 pfatal_with_name ("pipe"); 292 293 pr_pid = fork (); 294 if (pr_pid < 0) 295 pfatal_with_name ("fork"); 296 297 if (pr_pid == 0) 298 { 299 close (pipes[1]); 300 if (pipes[0] != STDIN_FILENO) 301 { 302 if (dup2 (pipes[0], STDIN_FILENO) < 0) 303 pfatal_with_name ("dup2"); 304 close (pipes[0]); 305 } 306 307 execv (pr_program, (char **) argv); 308 _exit (errno == ENOENT ? 127 : 126); 309 } 310 else 311 { 312 close (pipes[0]); 313 outfile = fdopen (pipes[1], "w"); 314 if (!outfile) 315 pfatal_with_name ("fdopen"); 316 } 317 #else 318 char *command = system_quote_argv (SCI_SYSTEM, (char **) argv); 319 errno = 0; 320 outfile = popen (command, "w"); 321 if (!outfile) 322 pfatal_with_name (command); 323 free (command); 324 #endif 325 } 326 } 327 else 328 { 329 330 /* If -l was not specified, output the diff straight to 'stdout'. */ 331 332 outfile = stdout; 333 334 /* If handling multiple files (because scanning a directory), 335 print which files the following output is about. */ 336 if (currently_recursive) 337 printf ("%s\n", name); 338 } 339 340 free (name); 341 342 /* A special header is needed at the beginning of context output. */ 343 switch (output_style) 344 { 345 case OUTPUT_CONTEXT: 346 print_context_header (files, (char const *const *)names, false); 347 break; 348 349 case OUTPUT_UNIFIED: 350 print_context_header (files, (char const *const *)names, true); 351 break; 352 353 default: 354 break; 355 } 356 357 if (names[0] != current_name0) 358 free (names[0]); 359 if (names[1] != current_name1) 360 free (names[1]); 361 } 362 363 /* Call after the end of output of diffs for one file. 364 Close OUTFILE and get rid of the 'pr' subfork. */ 365 366 void 367 finish_output (void) 368 { 369 if (outfile != 0 && outfile != stdout) 370 { 371 int status; 372 int wstatus; 373 int werrno = 0; 374 if (ferror (outfile)) 375 fatal ("write failed"); 376 #if ! HAVE_WORKING_FORK 377 wstatus = pclose (outfile); 378 if (wstatus == -1) 379 werrno = errno; 380 #else 381 if (fclose (outfile) != 0) 382 pfatal_with_name (_("write failed")); 383 if (waitpid (pr_pid, &wstatus, 0) < 0) 384 pfatal_with_name ("waitpid"); 385 #endif 386 status = (! werrno && WIFEXITED (wstatus) 387 ? WEXITSTATUS (wstatus) 388 : INT_MAX); 389 if (status) 390 error (EXIT_TROUBLE, werrno, 391 _(status == 126 392 ? "subsidiary program '%s' could not be invoked" 393 : status == 127 394 ? "subsidiary program '%s' not found" 395 : status == INT_MAX 396 ? "subsidiary program '%s' failed" 397 : "subsidiary program '%s' failed (exit status %d)"), 398 pr_program, status); 399 } 400 401 outfile = 0; 402 } 403 404 /* Compare two lines (typically one from each input file) 405 according to the command line options. 406 For efficiency, this is invoked only when the lines do not match exactly 407 but an option like -i might cause us to ignore the difference. 408 Return nonzero if the lines differ. */ 409 410 bool 411 lines_differ (char const *s1, char const *s2) 412 { 413 register char const *t1 = s1; 414 register char const *t2 = s2; 415 size_t column = 0; 416 417 while (1) 418 { 419 register unsigned char c1 = *t1++; 420 register unsigned char c2 = *t2++; 421 422 /* Test for exact char equality first, since it's a common case. */ 423 if (c1 != c2) 424 { 425 switch (ignore_white_space) 426 { 427 case IGNORE_ALL_SPACE: 428 /* For -w, just skip past any white space. */ 429 while (isspace (c1) && c1 != '\n') c1 = *t1++; 430 while (isspace (c2) && c2 != '\n') c2 = *t2++; 431 break; 432 433 case IGNORE_SPACE_CHANGE: 434 /* For -b, advance past any sequence of white space in 435 line 1 and consider it just one space, or nothing at 436 all if it is at the end of the line. */ 437 if (isspace (c1)) 438 { 439 while (c1 != '\n') 440 { 441 c1 = *t1++; 442 if (! isspace (c1)) 443 { 444 --t1; 445 c1 = ' '; 446 break; 447 } 448 } 449 } 450 451 /* Likewise for line 2. */ 452 if (isspace (c2)) 453 { 454 while (c2 != '\n') 455 { 456 c2 = *t2++; 457 if (! isspace (c2)) 458 { 459 --t2; 460 c2 = ' '; 461 break; 462 } 463 } 464 } 465 466 if (c1 != c2) 467 { 468 /* If we went too far when doing the simple test 469 for equality, go back to the first non-white-space 470 character in both sides and try again. */ 471 if (c2 == ' ' && c1 != '\n' 472 && s1 + 1 < t1 473 && isspace ((unsigned char) t1[-2])) 474 { 475 --t1; 476 continue; 477 } 478 if (c1 == ' ' && c2 != '\n' 479 && s2 + 1 < t2 480 && isspace ((unsigned char) t2[-2])) 481 { 482 --t2; 483 continue; 484 } 485 } 486 487 break; 488 489 case IGNORE_TRAILING_SPACE: 490 case IGNORE_TAB_EXPANSION_AND_TRAILING_SPACE: 491 if (isspace (c1) && isspace (c2)) 492 { 493 unsigned char c; 494 if (c1 != '\n') 495 { 496 char const *p = t1; 497 while ((c = *p) != '\n' && isspace (c)) 498 ++p; 499 if (c != '\n') 500 break; 501 } 502 if (c2 != '\n') 503 { 504 char const *p = t2; 505 while ((c = *p) != '\n' && isspace (c)) 506 ++p; 507 if (c != '\n') 508 break; 509 } 510 /* Both lines have nothing but whitespace left. */ 511 return false; 512 } 513 if (ignore_white_space == IGNORE_TRAILING_SPACE) 514 break; 515 /* Fall through. */ 516 case IGNORE_TAB_EXPANSION: 517 if ((c1 == ' ' && c2 == '\t') 518 || (c1 == '\t' && c2 == ' ')) 519 { 520 size_t column2 = column; 521 for (;; c1 = *t1++) 522 { 523 if (c1 == ' ') 524 column++; 525 else if (c1 == '\t') 526 column += tabsize - column % tabsize; 527 else 528 break; 529 } 530 for (;; c2 = *t2++) 531 { 532 if (c2 == ' ') 533 column2++; 534 else if (c2 == '\t') 535 column2 += tabsize - column2 % tabsize; 536 else 537 break; 538 } 539 if (column != column2) 540 return true; 541 } 542 break; 543 544 case IGNORE_NO_WHITE_SPACE: 545 break; 546 } 547 548 /* Lowercase all letters if -i is specified. */ 549 550 if (ignore_case) 551 { 552 c1 = tolower (c1); 553 c2 = tolower (c2); 554 } 555 556 if (c1 != c2) 557 break; 558 } 559 if (c1 == '\n') 560 return false; 561 562 column += c1 == '\t' ? tabsize - column % tabsize : 1; 563 } 564 565 return true; 566 } 567 568 /* Find the consecutive changes at the start of the script START. 569 Return the last link before the first gap. */ 570 571 struct change * _GL_ATTRIBUTE_CONST 572 find_change (struct change *start) 573 { 574 return start; 575 } 576 577 struct change * _GL_ATTRIBUTE_CONST 578 find_reverse_change (struct change *start) 579 { 580 return start; 581 } 582 583 /* Divide SCRIPT into pieces by calling HUNKFUN and 584 print each piece with PRINTFUN. 585 Both functions take one arg, an edit script. 586 587 HUNKFUN is called with the tail of the script 588 and returns the last link that belongs together with the start 589 of the tail. 590 591 PRINTFUN takes a subscript which belongs together (with a null 592 link at the end) and prints it. */ 593 594 void 595 print_script (struct change *script, 596 struct change * (*hunkfun) (struct change *), 597 void (*printfun) (struct change *)) 598 { 599 struct change *next = script; 600 601 while (next) 602 { 603 struct change *this, *end; 604 605 /* Find a set of changes that belong together. */ 606 this = next; 607 end = (*hunkfun) (next); 608 609 /* Disconnect them from the rest of the changes, 610 making them a hunk, and remember the rest for next iteration. */ 611 next = end->link; 612 end->link = 0; 613 #ifdef DEBUG 614 debug_script (this); 615 #endif 616 617 /* Print this hunk. */ 618 (*printfun) (this); 619 620 /* Reconnect the script so it will all be freed properly. */ 621 end->link = next; 622 } 623 } 624 625 /* Print the text of a single line LINE, 626 flagging it with the characters in LINE_FLAG (which say whether 627 the line is inserted, deleted, changed, etc.). LINE_FLAG must not 628 end in a blank, unless it is a single blank. */ 629 630 void 631 print_1_line (char const *line_flag, char const *const *line) 632 { 633 char const *base = line[0], *limit = line[1]; /* Help the compiler. */ 634 FILE *out = outfile; /* Help the compiler some more. */ 635 char const *flag_format = 0; 636 637 /* If -T was specified, use a Tab between the line-flag and the text. 638 Otherwise use a Space (as Unix diff does). 639 Print neither space nor tab if line-flags are empty. 640 But omit trailing blanks if requested. */ 641 642 if (line_flag && *line_flag) 643 { 644 char const *flag_format_1 = flag_format = initial_tab ? "%s\t" : "%s "; 645 char const *line_flag_1 = line_flag; 646 647 if (suppress_blank_empty && **line == '\n') 648 { 649 flag_format_1 = "%s"; 650 651 /* This hack to omit trailing blanks takes advantage of the 652 fact that the only way that LINE_FLAG can end in a blank 653 is when LINE_FLAG consists of a single blank. */ 654 line_flag_1 += *line_flag_1 == ' '; 655 } 656 657 fprintf (out, flag_format_1, line_flag_1); 658 } 659 660 output_1_line (base, limit, flag_format, line_flag); 661 662 if ((!line_flag || line_flag[0]) && limit[-1] != '\n') 663 fprintf (out, "\n\\ %s\n", _("No newline at end of file")); 664 } 665 666 /* Output a line from BASE up to LIMIT. 667 With -t, expand white space characters to spaces, and if FLAG_FORMAT 668 is nonzero, output it with argument LINE_FLAG after every 669 internal carriage return, so that tab stops continue to line up. */ 670 671 void 672 output_1_line (char const *base, char const *limit, char const *flag_format, 673 char const *line_flag) 674 { 675 if (!expand_tabs) 676 fwrite (base, sizeof (char), limit - base, outfile); 677 else 678 { 679 register FILE *out = outfile; 680 register unsigned char c; 681 register char const *t = base; 682 register size_t column = 0; 683 size_t tab_size = tabsize; 684 685 while (t < limit) 686 switch ((c = *t++)) 687 { 688 case '\t': 689 { 690 size_t spaces = tab_size - column % tab_size; 691 column += spaces; 692 do 693 putc (' ', out); 694 while (--spaces); 695 } 696 break; 697 698 case '\r': 699 putc (c, out); 700 if (flag_format && t < limit && *t != '\n') 701 fprintf (out, flag_format, line_flag); 702 column = 0; 703 break; 704 705 case '\b': 706 if (column == 0) 707 continue; 708 column--; 709 putc (c, out); 710 break; 711 712 default: 713 column += isprint (c) != 0; 714 putc (c, out); 715 break; 716 } 717 } 718 } 719 720 char const change_letter[] = { 0, 'd', 'a', 'c' }; 721 722 /* Translate an internal line number (an index into diff's table of lines) 723 into an actual line number in the input file. 724 The internal line number is I. FILE points to the data on the file. 725 726 Internal line numbers count from 0 starting after the prefix. 727 Actual line numbers count from 1 within the entire file. */ 728 729 lin _GL_ATTRIBUTE_PURE 730 translate_line_number (struct file_data const *file, lin i) 731 { 732 return i + file->prefix_lines + 1; 733 } 734 735 /* Translate a line number range. This is always done for printing, 736 so for convenience translate to long int rather than lin, so that the 737 caller can use printf with "%ld" without casting. */ 738 739 void 740 translate_range (struct file_data const *file, 741 lin a, lin b, 742 long int *aptr, long int *bptr) 743 { 744 *aptr = translate_line_number (file, a - 1) + 1; 745 *bptr = translate_line_number (file, b + 1) - 1; 746 } 747 748 /* Print a pair of line numbers with SEPCHAR, translated for file FILE. 749 If the two numbers are identical, print just one number. 750 751 Args A and B are internal line numbers. 752 We print the translated (real) line numbers. */ 753 754 void 755 print_number_range (char sepchar, struct file_data *file, lin a, lin b) 756 { 757 long int trans_a, trans_b; 758 translate_range (file, a, b, &trans_a, &trans_b); 759 760 /* Note: we can have B < A in the case of a range of no lines. 761 In this case, we should print the line number before the range, 762 which is B. */ 763 if (trans_b > trans_a) 764 fprintf (outfile, "%ld%c%ld", trans_a, sepchar, trans_b); 765 else 766 fprintf (outfile, "%ld", trans_b); 767 } 768 769 /* Look at a hunk of edit script and report the range of lines in each file 770 that it applies to. HUNK is the start of the hunk, which is a chain 771 of 'struct change'. The first and last line numbers of file 0 are stored in 772 *FIRST0 and *LAST0, and likewise for file 1 in *FIRST1 and *LAST1. 773 Note that these are internal line numbers that count from 0. 774 775 If no lines from file 0 are deleted, then FIRST0 is LAST0+1. 776 777 Return UNCHANGED if only ignorable lines are inserted or deleted, 778 OLD if lines of file 0 are deleted, 779 NEW if lines of file 1 are inserted, 780 and CHANGED if both kinds of changes are found. */ 781 782 enum changes 783 analyze_hunk (struct change *hunk, 784 lin *first0, lin *last0, 785 lin *first1, lin *last1) 786 { 787 struct change *next; 788 lin l0, l1; 789 lin show_from, show_to; 790 lin i; 791 bool trivial = ignore_blank_lines || ignore_regexp.fastmap; 792 size_t trivial_length = ignore_blank_lines - 1; 793 /* If 0, ignore zero-length lines; 794 if SIZE_MAX, do not ignore lines just because of their length. */ 795 796 bool skip_white_space = 797 ignore_blank_lines && IGNORE_TRAILING_SPACE <= ignore_white_space; 798 bool skip_leading_white_space = 799 skip_white_space && IGNORE_SPACE_CHANGE <= ignore_white_space; 800 801 char const * const *linbuf0 = files[0].linbuf; /* Help the compiler. */ 802 char const * const *linbuf1 = files[1].linbuf; 803 804 show_from = show_to = 0; 805 806 *first0 = hunk->line0; 807 *first1 = hunk->line1; 808 809 next = hunk; 810 do 811 { 812 l0 = next->line0 + next->deleted - 1; 813 l1 = next->line1 + next->inserted - 1; 814 show_from += next->deleted; 815 show_to += next->inserted; 816 817 for (i = next->line0; i <= l0 && trivial; i++) 818 { 819 char const *line = linbuf0[i]; 820 char const *newline = linbuf0[i + 1] - 1; 821 size_t len = newline - line; 822 char const *p = line; 823 if (skip_white_space) 824 for (; *p != '\n'; p++) 825 if (! isspace ((unsigned char) *p)) 826 { 827 if (! skip_leading_white_space) 828 p = line; 829 break; 830 } 831 if (newline - p != trivial_length 832 && (! ignore_regexp.fastmap 833 || re_search (&ignore_regexp, line, len, 0, len, 0) < 0)) 834 trivial = 0; 835 } 836 837 for (i = next->line1; i <= l1 && trivial; i++) 838 { 839 char const *line = linbuf1[i]; 840 char const *newline = linbuf1[i + 1] - 1; 841 size_t len = newline - line; 842 char const *p = line; 843 if (skip_white_space) 844 for (; *p != '\n'; p++) 845 if (! isspace ((unsigned char) *p)) 846 { 847 if (! skip_leading_white_space) 848 p = line; 849 break; 850 } 851 if (newline - p != trivial_length 852 && (! ignore_regexp.fastmap 853 || re_search (&ignore_regexp, line, len, 0, len, 0) < 0)) 854 trivial = 0; 855 } 856 } 857 while ((next = next->link) != 0); 858 859 *last0 = l0; 860 *last1 = l1; 861 862 /* If all inserted or deleted lines are ignorable, 863 tell the caller to ignore this hunk. */ 864 865 if (trivial) 866 return UNCHANGED; 867 868 return (show_from ? OLD : UNCHANGED) | (show_to ? NEW : UNCHANGED); 869 } 870 871 /* Concatenate three strings, returning a newly malloc'd string. */ 872 873 char * 874 concat (char const *s1, char const *s2, char const *s3) 875 { 876 char *new = xmalloc (strlen (s1) + strlen (s2) + strlen (s3) + 1); 877 sprintf (new, "%s%s%s", s1, s2, s3); 878 return new; 879 } 880 881 /* Yield a new block of SIZE bytes, initialized to zero. */ 882 883 void * 884 zalloc (size_t size) 885 { 886 void *p = xmalloc (size); 887 memset (p, 0, size); 888 return p; 889 } 890 891 void 892 debug_script (struct change *sp) 893 { 894 fflush (stdout); 895 896 for (; sp; sp = sp->link) 897 { 898 long int line0 = sp->line0; 899 long int line1 = sp->line1; 900 long int deleted = sp->deleted; 901 long int inserted = sp->inserted; 902 fprintf (stderr, "%3ld %3ld delete %ld insert %ld\n", 903 line0, line1, deleted, inserted); 904 } 905 906 fflush (stderr); 907 } 908