xref: /dflybsd-src/contrib/cvs-1.12/diff/side.c (revision 86d7f5d305c6adaa56ff4582ece9859d73106103)
1*86d7f5d3SJohn Marino /* sdiff-format output routines for GNU DIFF.
2*86d7f5d3SJohn Marino    Copyright (C) 1991, 1992, 1993, 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 distributed in the hope that it will be useful,
7*86d7f5d3SJohn Marino but WITHOUT ANY WARRANTY.  No author or distributor
8*86d7f5d3SJohn Marino accepts responsibility to anyone for the consequences of using it
9*86d7f5d3SJohn Marino or for whether it serves any particular purpose or works at all,
10*86d7f5d3SJohn Marino unless he says so in writing.  Refer to the GNU DIFF General Public
11*86d7f5d3SJohn Marino License for full details.
12*86d7f5d3SJohn Marino 
13*86d7f5d3SJohn Marino Everyone is granted permission to copy, modify and redistribute
14*86d7f5d3SJohn Marino GNU DIFF, but only under the conditions described in the
15*86d7f5d3SJohn Marino GNU DIFF General Public License.   A copy of this license is
16*86d7f5d3SJohn Marino supposed to have been given to you along with GNU DIFF so you
17*86d7f5d3SJohn Marino can know your rights and responsibilities.  It should be in a
18*86d7f5d3SJohn Marino file named COPYING.  Among other things, the copyright notice
19*86d7f5d3SJohn Marino and this notice must be preserved on all copies.  */
20*86d7f5d3SJohn Marino 
21*86d7f5d3SJohn Marino 
22*86d7f5d3SJohn Marino #include "diff.h"
23*86d7f5d3SJohn Marino 
24*86d7f5d3SJohn Marino static unsigned print_half_line PARAMS((char const * const *, unsigned, unsigned));
25*86d7f5d3SJohn Marino static unsigned tab_from_to PARAMS((unsigned, unsigned));
26*86d7f5d3SJohn Marino static void print_1sdiff_line PARAMS((char const * const *, int, char const * const *));
27*86d7f5d3SJohn Marino static void print_sdiff_common_lines PARAMS((int, int));
28*86d7f5d3SJohn Marino static void print_sdiff_hunk PARAMS((struct change *));
29*86d7f5d3SJohn Marino 
30*86d7f5d3SJohn Marino /* Next line number to be printed in the two input files.  */
31*86d7f5d3SJohn Marino static int next0, next1;
32*86d7f5d3SJohn Marino 
33*86d7f5d3SJohn Marino /* Print the edit-script SCRIPT as a sdiff style output.  */
34*86d7f5d3SJohn Marino 
35*86d7f5d3SJohn Marino void
print_sdiff_script(script)36*86d7f5d3SJohn Marino print_sdiff_script (script)
37*86d7f5d3SJohn Marino      struct change *script;
38*86d7f5d3SJohn Marino {
39*86d7f5d3SJohn Marino   begin_output ();
40*86d7f5d3SJohn Marino 
41*86d7f5d3SJohn Marino   next0 = next1 = - files[0].prefix_lines;
42*86d7f5d3SJohn Marino   print_script (script, find_change, print_sdiff_hunk);
43*86d7f5d3SJohn Marino 
44*86d7f5d3SJohn Marino   print_sdiff_common_lines (files[0].valid_lines, files[1].valid_lines);
45*86d7f5d3SJohn Marino }
46*86d7f5d3SJohn Marino 
47*86d7f5d3SJohn Marino /* Tab from column FROM to column TO, where FROM <= TO.  Yield TO.  */
48*86d7f5d3SJohn Marino 
49*86d7f5d3SJohn Marino static unsigned
tab_from_to(from,to)50*86d7f5d3SJohn Marino tab_from_to (from, to)
51*86d7f5d3SJohn Marino      unsigned from, to;
52*86d7f5d3SJohn Marino {
53*86d7f5d3SJohn Marino   unsigned tab;
54*86d7f5d3SJohn Marino 
55*86d7f5d3SJohn Marino   if (! tab_expand_flag)
56*86d7f5d3SJohn Marino     for (tab = from + TAB_WIDTH - from % TAB_WIDTH;  tab <= to;  tab += TAB_WIDTH)
57*86d7f5d3SJohn Marino       {
58*86d7f5d3SJohn Marino 	write_output ("\t", 1);
59*86d7f5d3SJohn Marino 	from = tab;
60*86d7f5d3SJohn Marino       }
61*86d7f5d3SJohn Marino   while (from++ < to)
62*86d7f5d3SJohn Marino     write_output (" ", 1);
63*86d7f5d3SJohn Marino   return to;
64*86d7f5d3SJohn Marino }
65*86d7f5d3SJohn Marino 
66*86d7f5d3SJohn Marino /*
67*86d7f5d3SJohn Marino  * Print the text for half an sdiff line.  This means truncate to width
68*86d7f5d3SJohn Marino  * observing tabs, and trim a trailing newline.  Returns the last column
69*86d7f5d3SJohn Marino  * written (not the number of chars).
70*86d7f5d3SJohn Marino  */
71*86d7f5d3SJohn Marino static unsigned
print_half_line(line,indent,out_bound)72*86d7f5d3SJohn Marino print_half_line (line, indent, out_bound)
73*86d7f5d3SJohn Marino      char const * const *line;
74*86d7f5d3SJohn Marino      unsigned indent, out_bound;
75*86d7f5d3SJohn Marino {
76*86d7f5d3SJohn Marino   register unsigned in_position = 0, out_position = 0;
77*86d7f5d3SJohn Marino   register char const
78*86d7f5d3SJohn Marino 	*text_pointer = line[0],
79*86d7f5d3SJohn Marino 	*text_limit = line[1];
80*86d7f5d3SJohn Marino 
81*86d7f5d3SJohn Marino   while (text_pointer < text_limit)
82*86d7f5d3SJohn Marino     {
83*86d7f5d3SJohn Marino       register unsigned char c = *text_pointer++;
84*86d7f5d3SJohn Marino       /* We use CC to avoid taking the address of the register
85*86d7f5d3SJohn Marino          variable C.  */
86*86d7f5d3SJohn Marino       char cc;
87*86d7f5d3SJohn Marino 
88*86d7f5d3SJohn Marino       switch (c)
89*86d7f5d3SJohn Marino 	{
90*86d7f5d3SJohn Marino 	case '\t':
91*86d7f5d3SJohn Marino 	  {
92*86d7f5d3SJohn Marino 	    unsigned spaces = TAB_WIDTH - in_position % TAB_WIDTH;
93*86d7f5d3SJohn Marino 	    if (in_position == out_position)
94*86d7f5d3SJohn Marino 	      {
95*86d7f5d3SJohn Marino 		unsigned tabstop = out_position + spaces;
96*86d7f5d3SJohn Marino 		if (tab_expand_flag)
97*86d7f5d3SJohn Marino 		  {
98*86d7f5d3SJohn Marino 		    if (out_bound < tabstop)
99*86d7f5d3SJohn Marino 		      tabstop = out_bound;
100*86d7f5d3SJohn Marino 		    for (;  out_position < tabstop;  out_position++)
101*86d7f5d3SJohn Marino 		      write_output (" ", 1);
102*86d7f5d3SJohn Marino 		  }
103*86d7f5d3SJohn Marino 		else
104*86d7f5d3SJohn Marino 		  if (tabstop < out_bound)
105*86d7f5d3SJohn Marino 		    {
106*86d7f5d3SJohn Marino 		      out_position = tabstop;
107*86d7f5d3SJohn Marino 		      cc = c;
108*86d7f5d3SJohn Marino 		      write_output (&cc, 1);
109*86d7f5d3SJohn Marino 		    }
110*86d7f5d3SJohn Marino 	      }
111*86d7f5d3SJohn Marino 	    in_position += spaces;
112*86d7f5d3SJohn Marino 	  }
113*86d7f5d3SJohn Marino 	  break;
114*86d7f5d3SJohn Marino 
115*86d7f5d3SJohn Marino 	case '\r':
116*86d7f5d3SJohn Marino 	  {
117*86d7f5d3SJohn Marino 	    cc = c;
118*86d7f5d3SJohn Marino 	    write_output (&cc, 1);
119*86d7f5d3SJohn Marino 	    tab_from_to (0, indent);
120*86d7f5d3SJohn Marino 	    in_position = out_position = 0;
121*86d7f5d3SJohn Marino 	  }
122*86d7f5d3SJohn Marino 	  break;
123*86d7f5d3SJohn Marino 
124*86d7f5d3SJohn Marino 	case '\b':
125*86d7f5d3SJohn Marino 	  if (in_position != 0 && --in_position < out_bound)
126*86d7f5d3SJohn Marino 	    if (out_position <= in_position)
127*86d7f5d3SJohn Marino 	      /* Add spaces to make up for suppressed tab past out_bound.  */
128*86d7f5d3SJohn Marino 	      for (;  out_position < in_position;  out_position++)
129*86d7f5d3SJohn Marino 		write_output (" ", 1);
130*86d7f5d3SJohn Marino 	    else
131*86d7f5d3SJohn Marino 	      {
132*86d7f5d3SJohn Marino 		out_position = in_position;
133*86d7f5d3SJohn Marino 		cc = c;
134*86d7f5d3SJohn Marino 		write_output (&cc, 1);
135*86d7f5d3SJohn Marino 	      }
136*86d7f5d3SJohn Marino 	  break;
137*86d7f5d3SJohn Marino 
138*86d7f5d3SJohn Marino 	case '\f':
139*86d7f5d3SJohn Marino 	case '\v':
140*86d7f5d3SJohn Marino 	control_char:
141*86d7f5d3SJohn Marino 	  if (in_position < out_bound)
142*86d7f5d3SJohn Marino 	    {
143*86d7f5d3SJohn Marino 	      cc = c;
144*86d7f5d3SJohn Marino 	      write_output (&cc, 1);
145*86d7f5d3SJohn Marino 	    }
146*86d7f5d3SJohn Marino 	  break;
147*86d7f5d3SJohn Marino 
148*86d7f5d3SJohn Marino 	default:
149*86d7f5d3SJohn Marino 	  if (! ISPRINT (c))
150*86d7f5d3SJohn Marino 	    goto control_char;
151*86d7f5d3SJohn Marino 	  /* falls through */
152*86d7f5d3SJohn Marino 	case ' ':
153*86d7f5d3SJohn Marino 	  if (in_position++ < out_bound)
154*86d7f5d3SJohn Marino 	    {
155*86d7f5d3SJohn Marino 	      out_position = in_position;
156*86d7f5d3SJohn Marino 	      cc = c;
157*86d7f5d3SJohn Marino 	      write_output (&cc, 1);
158*86d7f5d3SJohn Marino 	    }
159*86d7f5d3SJohn Marino 	  break;
160*86d7f5d3SJohn Marino 
161*86d7f5d3SJohn Marino 	case '\n':
162*86d7f5d3SJohn Marino 	  return out_position;
163*86d7f5d3SJohn Marino 	}
164*86d7f5d3SJohn Marino     }
165*86d7f5d3SJohn Marino 
166*86d7f5d3SJohn Marino   return out_position;
167*86d7f5d3SJohn Marino }
168*86d7f5d3SJohn Marino 
169*86d7f5d3SJohn Marino /*
170*86d7f5d3SJohn Marino  * Print side by side lines with a separator in the middle.
171*86d7f5d3SJohn Marino  * 0 parameters are taken to indicate white space text.
172*86d7f5d3SJohn Marino  * Blank lines that can easily be caught are reduced to a single newline.
173*86d7f5d3SJohn Marino  */
174*86d7f5d3SJohn Marino 
175*86d7f5d3SJohn Marino static void
print_1sdiff_line(left,sep,right)176*86d7f5d3SJohn Marino print_1sdiff_line (left, sep, right)
177*86d7f5d3SJohn Marino      char const * const *left;
178*86d7f5d3SJohn Marino      int sep;
179*86d7f5d3SJohn Marino      char const * const *right;
180*86d7f5d3SJohn Marino {
181*86d7f5d3SJohn Marino   unsigned hw = sdiff_half_width, c2o = sdiff_column2_offset;
182*86d7f5d3SJohn Marino   unsigned col = 0;
183*86d7f5d3SJohn Marino   int put_newline = 0;
184*86d7f5d3SJohn Marino 
185*86d7f5d3SJohn Marino   if (left)
186*86d7f5d3SJohn Marino     {
187*86d7f5d3SJohn Marino       if (left[1][-1] == '\n')
188*86d7f5d3SJohn Marino 	put_newline = 1;
189*86d7f5d3SJohn Marino       col = print_half_line (left, 0, hw);
190*86d7f5d3SJohn Marino     }
191*86d7f5d3SJohn Marino 
192*86d7f5d3SJohn Marino   if (sep != ' ')
193*86d7f5d3SJohn Marino     {
194*86d7f5d3SJohn Marino       char cc;
195*86d7f5d3SJohn Marino 
196*86d7f5d3SJohn Marino       col = tab_from_to (col, (hw + c2o - 1) / 2) + 1;
197*86d7f5d3SJohn Marino       if (sep == '|' && put_newline != (right[1][-1] == '\n'))
198*86d7f5d3SJohn Marino 	sep = put_newline ? '/' : '\\';
199*86d7f5d3SJohn Marino       cc = sep;
200*86d7f5d3SJohn Marino       write_output (&cc, 1);
201*86d7f5d3SJohn Marino     }
202*86d7f5d3SJohn Marino 
203*86d7f5d3SJohn Marino   if (right)
204*86d7f5d3SJohn Marino     {
205*86d7f5d3SJohn Marino       if (right[1][-1] == '\n')
206*86d7f5d3SJohn Marino 	put_newline = 1;
207*86d7f5d3SJohn Marino       if (**right != '\n')
208*86d7f5d3SJohn Marino 	{
209*86d7f5d3SJohn Marino 	  col = tab_from_to (col, c2o);
210*86d7f5d3SJohn Marino 	  print_half_line (right, col, hw);
211*86d7f5d3SJohn Marino 	}
212*86d7f5d3SJohn Marino     }
213*86d7f5d3SJohn Marino 
214*86d7f5d3SJohn Marino   if (put_newline)
215*86d7f5d3SJohn Marino     write_output ("\n", 1);
216*86d7f5d3SJohn Marino }
217*86d7f5d3SJohn Marino 
218*86d7f5d3SJohn Marino /* Print lines common to both files in side-by-side format.  */
219*86d7f5d3SJohn Marino static void
print_sdiff_common_lines(limit0,limit1)220*86d7f5d3SJohn Marino print_sdiff_common_lines (limit0, limit1)
221*86d7f5d3SJohn Marino      int limit0, limit1;
222*86d7f5d3SJohn Marino {
223*86d7f5d3SJohn Marino   int i0 = next0, i1 = next1;
224*86d7f5d3SJohn Marino 
225*86d7f5d3SJohn Marino   if (! sdiff_skip_common_lines  &&  (i0 != limit0 || i1 != limit1))
226*86d7f5d3SJohn Marino     {
227*86d7f5d3SJohn Marino       if (sdiff_help_sdiff)
228*86d7f5d3SJohn Marino 	printf_output ("i%d,%d\n", limit0 - i0, limit1 - i1);
229*86d7f5d3SJohn Marino 
230*86d7f5d3SJohn Marino       if (! sdiff_left_only)
231*86d7f5d3SJohn Marino 	{
232*86d7f5d3SJohn Marino 	  while (i0 != limit0 && i1 != limit1)
233*86d7f5d3SJohn Marino 	    print_1sdiff_line (&files[0].linbuf[i0++], ' ', &files[1].linbuf[i1++]);
234*86d7f5d3SJohn Marino 	  while (i1 != limit1)
235*86d7f5d3SJohn Marino 	    print_1sdiff_line (0, ')', &files[1].linbuf[i1++]);
236*86d7f5d3SJohn Marino 	}
237*86d7f5d3SJohn Marino       while (i0 != limit0)
238*86d7f5d3SJohn Marino 	print_1sdiff_line (&files[0].linbuf[i0++], '(', 0);
239*86d7f5d3SJohn Marino     }
240*86d7f5d3SJohn Marino 
241*86d7f5d3SJohn Marino   next0 = limit0;
242*86d7f5d3SJohn Marino   next1 = limit1;
243*86d7f5d3SJohn Marino }
244*86d7f5d3SJohn Marino 
245*86d7f5d3SJohn Marino /* Print a hunk of an sdiff diff.
246*86d7f5d3SJohn Marino    This is a contiguous portion of a complete edit script,
247*86d7f5d3SJohn Marino    describing changes in consecutive lines.  */
248*86d7f5d3SJohn Marino 
249*86d7f5d3SJohn Marino static void
print_sdiff_hunk(hunk)250*86d7f5d3SJohn Marino print_sdiff_hunk (hunk)
251*86d7f5d3SJohn Marino      struct change *hunk;
252*86d7f5d3SJohn Marino {
253*86d7f5d3SJohn Marino   int first0, last0, first1, last1, deletes, inserts;
254*86d7f5d3SJohn Marino   register int i, j;
255*86d7f5d3SJohn Marino 
256*86d7f5d3SJohn Marino   /* Determine range of line numbers involved in each file.  */
257*86d7f5d3SJohn Marino   analyze_hunk (hunk, &first0, &last0, &first1, &last1, &deletes, &inserts);
258*86d7f5d3SJohn Marino   if (!deletes && !inserts)
259*86d7f5d3SJohn Marino     return;
260*86d7f5d3SJohn Marino 
261*86d7f5d3SJohn Marino   /* Print out lines up to this change.  */
262*86d7f5d3SJohn Marino   print_sdiff_common_lines (first0, first1);
263*86d7f5d3SJohn Marino 
264*86d7f5d3SJohn Marino   if (sdiff_help_sdiff)
265*86d7f5d3SJohn Marino     printf_output ("c%d,%d\n", last0 - first0 + 1, last1 - first1 + 1);
266*86d7f5d3SJohn Marino 
267*86d7f5d3SJohn Marino   /* Print ``xxx  |  xxx '' lines */
268*86d7f5d3SJohn Marino   if (inserts && deletes)
269*86d7f5d3SJohn Marino     {
270*86d7f5d3SJohn Marino       for (i = first0, j = first1;  i <= last0 && j <= last1; ++i, ++j)
271*86d7f5d3SJohn Marino 	print_1sdiff_line (&files[0].linbuf[i], '|', &files[1].linbuf[j]);
272*86d7f5d3SJohn Marino       deletes = i <= last0;
273*86d7f5d3SJohn Marino       inserts = j <= last1;
274*86d7f5d3SJohn Marino       next0 = first0 = i;
275*86d7f5d3SJohn Marino       next1 = first1 = j;
276*86d7f5d3SJohn Marino     }
277*86d7f5d3SJohn Marino 
278*86d7f5d3SJohn Marino 
279*86d7f5d3SJohn Marino   /* Print ``     >  xxx '' lines */
280*86d7f5d3SJohn Marino   if (inserts)
281*86d7f5d3SJohn Marino     {
282*86d7f5d3SJohn Marino       for (j = first1; j <= last1; ++j)
283*86d7f5d3SJohn Marino 	print_1sdiff_line (0, '>', &files[1].linbuf[j]);
284*86d7f5d3SJohn Marino       next1 = j;
285*86d7f5d3SJohn Marino     }
286*86d7f5d3SJohn Marino 
287*86d7f5d3SJohn Marino   /* Print ``xxx  <     '' lines */
288*86d7f5d3SJohn Marino   if (deletes)
289*86d7f5d3SJohn Marino     {
290*86d7f5d3SJohn Marino       for (i = first0; i <= last0; ++i)
291*86d7f5d3SJohn Marino 	print_1sdiff_line (&files[0].linbuf[i], '<', 0);
292*86d7f5d3SJohn Marino       next0 = i;
293*86d7f5d3SJohn Marino     }
294*86d7f5d3SJohn Marino }
295