util.c (32785) | util.c (44852) |
---|---|
1/* Support routines for GNU DIFF. | 1/* Support routines for GNU DIFF. |
2 Copyright (C) 1988, 1989, 1992, 1993, 1994, 1997 Free Software Foundation, Inc. | 2 Copyright (C) 1988, 1989, 1992, 1993, 1994, 1997, 1998 Free Software Foundation, Inc. |
3 4This file is part of GNU DIFF. 5 6GNU DIFF is free software; you can redistribute it and/or modify 7it under the terms of the GNU General Public License as published by 8the Free Software Foundation; either version 2, or (at your option) 9any later version. 10 11GNU DIFF is distributed in the hope that it will be useful, 12but WITHOUT ANY WARRANTY; without even the implied warranty of 13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14GNU General Public License for more details. 15 16You should have received a copy of the GNU General Public License 17along with GNU DIFF; see the file COPYING. If not, write to 18the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ 19 20#include "diff.h" 21 | 3 4This file is part of GNU DIFF. 5 6GNU DIFF is free software; you can redistribute it and/or modify 7it under the terms of the GNU General Public License as published by 8the Free Software Foundation; either version 2, or (at your option) 9any later version. 10 11GNU DIFF is distributed in the hope that it will be useful, 12but WITHOUT ANY WARRANTY; without even the implied warranty of 13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14GNU General Public License for more details. 15 16You should have received a copy of the GNU General Public License 17along with GNU DIFF; see the file COPYING. If not, write to 18the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ 19 20#include "diff.h" 21 |
22#ifdef __STDC__ 23#include <stdarg.h> 24#else 25#include <varargs.h> 26#endif 27 28#ifndef strerror 29extern char *strerror (); 30#endif 31 |
|
22/* Queue up one-line messages to be printed at the end, 23 when -l is specified. Each message is recorded with a `struct msg'. */ 24 25struct msg 26{ 27 struct msg *next; 28 char const *format; 29 char const *arg1; --- 13 unchanged lines hidden (view full) --- 43/* Use when a system call returns non-zero status. 44 TEXT should normally be the file name. */ 45 46void 47perror_with_name (text) 48 char const *text; 49{ 50 int e = errno; | 32/* Queue up one-line messages to be printed at the end, 33 when -l is specified. Each message is recorded with a `struct msg'. */ 34 35struct msg 36{ 37 struct msg *next; 38 char const *format; 39 char const *arg1; --- 13 unchanged lines hidden (view full) --- 53/* Use when a system call returns non-zero status. 54 TEXT should normally be the file name. */ 55 56void 57perror_with_name (text) 58 char const *text; 59{ 60 int e = errno; |
51 fprintf (stderr, "%s: ", diff_program_name); 52 errno = e; 53 perror (text); | 61 62 if (callbacks && callbacks->error) 63 (*callbacks->error) ("%s: %s", text, strerror (e)); 64 else 65 { 66 fprintf (stderr, "%s: ", diff_program_name); 67 errno = e; 68 perror (text); 69 } |
54} 55 56/* Use when a system call returns non-zero status and that is fatal. */ 57 58void 59pfatal_with_name (text) 60 char const *text; 61{ 62 int e = errno; 63 print_message_queue (); | 70} 71 72/* Use when a system call returns non-zero status and that is fatal. */ 73 74void 75pfatal_with_name (text) 76 char const *text; 77{ 78 int e = errno; 79 print_message_queue (); |
64 fprintf (stderr, "%s: ", diff_program_name); 65 errno = e; 66 perror (text); | 80 if (callbacks && callbacks->error) 81 (*callbacks->error) ("%s: %s", text, strerror (e)); 82 else 83 { 84 fprintf (stderr, "%s: ", diff_program_name); 85 errno = e; 86 perror (text); 87 } |
67 DIFF_ABORT (2); 68} 69 70/* Print an error message from the format-string FORMAT 71 with args ARG1 and ARG2. */ 72 73void 74diff_error (format, arg, arg1) 75 char const *format, *arg, *arg1; 76{ | 88 DIFF_ABORT (2); 89} 90 91/* Print an error message from the format-string FORMAT 92 with args ARG1 and ARG2. */ 93 94void 95diff_error (format, arg, arg1) 96 char const *format, *arg, *arg1; 97{ |
77 fprintf (stderr, "%s: ", diff_program_name); 78 fprintf (stderr, format, arg, arg1); 79 fprintf (stderr, "\n"); | 98 if (callbacks && callbacks->error) 99 (*callbacks->error) (format, arg, arg1); 100 else 101 { 102 fprintf (stderr, "%s: ", diff_program_name); 103 fprintf (stderr, format, arg, arg1); 104 fprintf (stderr, "\n"); 105 } |
80} 81 82/* Print an error message containing the string TEXT, then exit. */ 83 84void 85fatal (m) 86 char const *m; 87{ --- 26 unchanged lines hidden (view full) --- 114 new->arg4 = arg4 ? concat (arg4, "", "") : 0; 115 new->next = 0; 116 *msg_chain_end = new; 117 msg_chain_end = &new->next; 118 } 119 else 120 { 121 if (sdiff_help_sdiff) | 106} 107 108/* Print an error message containing the string TEXT, then exit. */ 109 110void 111fatal (m) 112 char const *m; 113{ --- 26 unchanged lines hidden (view full) --- 140 new->arg4 = arg4 ? concat (arg4, "", "") : 0; 141 new->next = 0; 142 *msg_chain_end = new; 143 msg_chain_end = &new->next; 144 } 145 else 146 { 147 if (sdiff_help_sdiff) |
122 putc (' ', outfile); 123 fprintf (outfile, format, arg1, arg2, arg3, arg4); | 148 write_output (" ", 1); 149 printf_output (format, arg1, arg2, arg3, arg4); |
124 } 125} 126 127/* Output all the messages that were saved up by calls to `message'. */ 128 129void 130print_message_queue () 131{ 132 struct msg *m; 133 134 for (m = msg_chain; m; m = m->next) | 150 } 151} 152 153/* Output all the messages that were saved up by calls to `message'. */ 154 155void 156print_message_queue () 157{ 158 struct msg *m; 159 160 for (m = msg_chain; m; m = m->next) |
135 fprintf (outfile, m->format, m->arg1, m->arg2, m->arg3, m->arg4); | 161 printf_output (m->format, m->arg1, m->arg2, m->arg3, m->arg4); |
136} 137 138/* Call before outputting the results of comparing files NAME0 and NAME1 139 to set up OUTFILE, the stdio stream for the output to go to. 140 141 Usually, OUTFILE is just stdout. But when -l was specified 142 we fork off a `pr' and make OUTFILE a pipe to it. 143 `pr' then outputs to our stdout. */ --- 31 unchanged lines hidden (view full) --- 175 name = xmalloc (strlen (current_name0) + strlen (current_name1) 176 + strlen (switch_string) + 7); 177 /* Posix.2 section 4.17.6.1.1 specifies this format. But there is a 178 bug in the first printing (IEEE Std 1003.2-1992 p 251 l 3304): 179 it says that we must print only the last component of the pathnames. 180 This requirement is silly and does not match historical practice. */ 181 sprintf (name, "diff%s %s %s", switch_string, current_name0, current_name1); 182 | 162} 163 164/* Call before outputting the results of comparing files NAME0 and NAME1 165 to set up OUTFILE, the stdio stream for the output to go to. 166 167 Usually, OUTFILE is just stdout. But when -l was specified 168 we fork off a `pr' and make OUTFILE a pipe to it. 169 `pr' then outputs to our stdout. */ --- 31 unchanged lines hidden (view full) --- 201 name = xmalloc (strlen (current_name0) + strlen (current_name1) 202 + strlen (switch_string) + 7); 203 /* Posix.2 section 4.17.6.1.1 specifies this format. But there is a 204 bug in the first printing (IEEE Std 1003.2-1992 p 251 l 3304): 205 it says that we must print only the last component of the pathnames. 206 This requirement is silly and does not match historical practice. */ 207 sprintf (name, "diff%s %s %s", switch_string, current_name0, current_name1); 208 |
209 if (paginate_flag && callbacks && callbacks->write_output) 210 fatal ("can't paginate when using library callbacks"); 211 |
|
183 if (paginate_flag) 184 { 185 /* Make OUTFILE a pipe to a subsidiary `pr'. */ 186 187#ifdef PR_PROGRAM 188 189# if HAVE_FORK 190 int pipes[2]; --- 47 unchanged lines hidden (view full) --- 238 else 239 { 240 241 /* If -l was not specified, output the diff straight to `stdout'. */ 242 243 /* If handling multiple files (because scanning a directory), 244 print which files the following output is about. */ 245 if (current_depth > 0) | 212 if (paginate_flag) 213 { 214 /* Make OUTFILE a pipe to a subsidiary `pr'. */ 215 216#ifdef PR_PROGRAM 217 218# if HAVE_FORK 219 int pipes[2]; --- 47 unchanged lines hidden (view full) --- 267 else 268 { 269 270 /* If -l was not specified, output the diff straight to `stdout'. */ 271 272 /* If handling multiple files (because scanning a directory), 273 print which files the following output is about. */ 274 if (current_depth > 0) |
246 fprintf (outfile, "%s\n", name); | 275 printf_output ("%s\n", name); |
247 } 248 249 free (name); 250 251 /* A special header is needed at the beginning of context output. */ 252 switch (output_style) 253 { 254 case OUTPUT_CONTEXT: --- 33 unchanged lines hidden (view full) --- 288 fatal ("subsidiary pr failed"); 289#else 290 fatal ("internal error in finish_output"); 291#endif 292 } 293 294 output_in_progress = 0; 295} | 276 } 277 278 free (name); 279 280 /* A special header is needed at the beginning of context output. */ 281 switch (output_style) 282 { 283 case OUTPUT_CONTEXT: --- 33 unchanged lines hidden (view full) --- 317 fatal ("subsidiary pr failed"); 318#else 319 fatal ("internal error in finish_output"); 320#endif 321 } 322 323 output_in_progress = 0; 324} |
325 326/* Write something to the output file. */ 327 328void 329write_output (text, len) 330 char const *text; 331 size_t len; 332{ 333 if (callbacks && callbacks->write_output) 334 (*callbacks->write_output) (text, len); 335 else if (len == 1) 336 putc (*text, outfile); 337 else 338 fwrite (text, sizeof (char), len, outfile); 339} 340 341/* Printf something to the output file. */ 342 343#ifdef __STDC__ 344#define VA_START(args, lastarg) va_start(args, lastarg) 345#else /* ! __STDC__ */ 346#define VA_START(args, lastarg) va_start(args) 347#endif /* __STDC__ */ 348 349void 350#if defined (__STDC__) 351printf_output (const char *format, ...) 352#else 353printf_output (format, va_alist) 354 char const *format; 355 va_dcl 356#endif 357{ 358 va_list args; 359 360 VA_START (args, format); 361 if (callbacks && callbacks->write_output) 362 { 363 char *p; 364 365 p = NULL; 366 vasprintf (&p, format, args); 367 if (p == NULL) 368 fatal ("out of memory"); 369 (*callbacks->write_output) (p, strlen (p)); 370 free (p); 371 } 372 else 373 vfprintf (outfile, format, args); 374 va_end (args); 375} 376 377/* Flush the output file. */ 378 379void 380flush_output () 381{ 382 if (callbacks && callbacks->flush_output) 383 (*callbacks->flush_output) (); 384 else 385 fflush (outfile); 386} |
|
296 297/* Compare two lines (typically one from each input file) 298 according to the command line options. 299 For efficiency, this is invoked only when the lines do not match exactly 300 but an option like -i might cause us to ignore the difference. 301 Return nonzero if the lines differ. */ 302 303int --- 160 unchanged lines hidden (view full) --- 464 the line is inserted, deleted, changed, etc.). */ 465 466void 467print_1_line (line_flag, line) 468 char const *line_flag; 469 char const * const *line; 470{ 471 char const *text = line[0], *limit = line[1]; /* Help the compiler. */ | 387 388/* Compare two lines (typically one from each input file) 389 according to the command line options. 390 For efficiency, this is invoked only when the lines do not match exactly 391 but an option like -i might cause us to ignore the difference. 392 Return nonzero if the lines differ. */ 393 394int --- 160 unchanged lines hidden (view full) --- 555 the line is inserted, deleted, changed, etc.). */ 556 557void 558print_1_line (line_flag, line) 559 char const *line_flag; 560 char const * const *line; 561{ 562 char const *text = line[0], *limit = line[1]; /* Help the compiler. */ |
472 FILE *out = outfile; /* Help the compiler some more. */ | |
473 char const *flag_format = 0; 474 475 /* If -T was specified, use a Tab between the line-flag and the text. 476 Otherwise use a Space (as Unix diff does). 477 Print neither space nor tab if line-flags are empty. */ 478 479 if (line_flag && *line_flag) 480 { 481 flag_format = tab_align_flag ? "%s\t" : "%s "; | 563 char const *flag_format = 0; 564 565 /* If -T was specified, use a Tab between the line-flag and the text. 566 Otherwise use a Space (as Unix diff does). 567 Print neither space nor tab if line-flags are empty. */ 568 569 if (line_flag && *line_flag) 570 { 571 flag_format = tab_align_flag ? "%s\t" : "%s "; |
482 fprintf (out, flag_format, line_flag); | 572 printf_output (flag_format, line_flag); |
483 } 484 485 output_1_line (text, limit, flag_format, line_flag); 486 487 if ((!line_flag || line_flag[0]) && limit[-1] != '\n') | 573 } 574 575 output_1_line (text, limit, flag_format, line_flag); 576 577 if ((!line_flag || line_flag[0]) && limit[-1] != '\n') |
488 fprintf (out, "\n\\ No newline at end of file\n"); | 578 printf_output ("\n\\ No newline at end of file\n"); |
489} 490 491/* Output a line from TEXT up to LIMIT. Without -t, output verbatim. 492 With -t, expand white space characters to spaces, and if FLAG_FORMAT 493 is nonzero, output it with argument LINE_FLAG after every 494 internal carriage return, so that tab stops continue to line up. */ 495 496void 497output_1_line (text, limit, flag_format, line_flag) 498 char const *text, *limit, *flag_format, *line_flag; 499{ 500 if (!tab_expand_flag) | 579} 580 581/* Output a line from TEXT up to LIMIT. Without -t, output verbatim. 582 With -t, expand white space characters to spaces, and if FLAG_FORMAT 583 is nonzero, output it with argument LINE_FLAG after every 584 internal carriage return, so that tab stops continue to line up. */ 585 586void 587output_1_line (text, limit, flag_format, line_flag) 588 char const *text, *limit, *flag_format, *line_flag; 589{ 590 if (!tab_expand_flag) |
501 fwrite (text, sizeof (char), limit - text, outfile); | 591 write_output (text, limit - text); |
502 else 503 { | 592 else 593 { |
504 register FILE *out = outfile; | |
505 register unsigned char c; 506 register char const *t = text; 507 register unsigned column = 0; | 594 register unsigned char c; 595 register char const *t = text; 596 register unsigned column = 0; |
597 /* CC is used to avoid taking the address of the register 598 variable C. */ 599 char cc; |
|
508 509 while (t < limit) 510 switch ((c = *t++)) 511 { 512 case '\t': 513 { 514 unsigned spaces = TAB_WIDTH - column % TAB_WIDTH; 515 column += spaces; 516 do | 600 601 while (t < limit) 602 switch ((c = *t++)) 603 { 604 case '\t': 605 { 606 unsigned spaces = TAB_WIDTH - column % TAB_WIDTH; 607 column += spaces; 608 do |
517 putc (' ', out); | 609 write_output (" ", 1); |
518 while (--spaces); 519 } 520 break; 521 522 case '\r': | 610 while (--spaces); 611 } 612 break; 613 614 case '\r': |
523 putc (c, out); | 615 write_output ("\r", 1); |
524 if (flag_format && t < limit && *t != '\n') | 616 if (flag_format && t < limit && *t != '\n') |
525 fprintf (out, flag_format, line_flag); | 617 printf_output (flag_format, line_flag); |
526 column = 0; 527 break; 528 529 case '\b': 530 if (column == 0) 531 continue; 532 column--; | 618 column = 0; 619 break; 620 621 case '\b': 622 if (column == 0) 623 continue; 624 column--; |
533 putc (c, out); | 625 write_output ("\b", 1); |
534 break; 535 536 default: 537 if (ISPRINT (c)) 538 column++; | 626 break; 627 628 default: 629 if (ISPRINT (c)) 630 column++; |
539 putc (c, out); | 631 cc = c; 632 write_output (&cc, 1); |
540 break; 541 } 542 } 543} 544 545int 546change_letter (inserts, deletes) 547 int inserts, deletes; --- 45 unchanged lines hidden (view full) --- 593{ 594 int trans_a, trans_b; 595 translate_range (file, a, b, &trans_a, &trans_b); 596 597 /* Note: we can have B < A in the case of a range of no lines. 598 In this case, we should print the line number before the range, 599 which is B. */ 600 if (trans_b > trans_a) | 633 break; 634 } 635 } 636} 637 638int 639change_letter (inserts, deletes) 640 int inserts, deletes; --- 45 unchanged lines hidden (view full) --- 686{ 687 int trans_a, trans_b; 688 translate_range (file, a, b, &trans_a, &trans_b); 689 690 /* Note: we can have B < A in the case of a range of no lines. 691 In this case, we should print the line number before the range, 692 which is B. */ 693 if (trans_b > trans_a) |
601 fprintf (outfile, "%d%c%d", trans_a, sepchar, trans_b); | 694 printf_output ("%d%c%d", trans_a, sepchar, trans_b); |
602 else | 695 else |
603 fprintf (outfile, "%d", trans_b); | 696 printf_output ("%d", trans_b); |
604} 605 606/* Look at a hunk of edit script and report the range of lines in each file 607 that it applies to. HUNK is the start of the hunk, which is a chain 608 of `struct change'. The first and last line numbers of file 0 are stored in 609 *FIRST0 and *LAST0, and likewise for file 1 in *FIRST1 and *LAST1. 610 Note that these are internal line numbers that count from 0. 611 --- 111 unchanged lines hidden --- | 697} 698 699/* Look at a hunk of edit script and report the range of lines in each file 700 that it applies to. HUNK is the start of the hunk, which is a chain 701 of `struct change'. The first and last line numbers of file 0 are stored in 702 *FIRST0 and *LAST0, and likewise for file 1 in *FIRST1 and *LAST1. 703 Note that these are internal line numbers that count from 0. 704 --- 111 unchanged lines hidden --- |