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