Deleted Added
full compact
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 ---