Commit | Line | Data |
---|---|---|
89dd82fa WJ |
1 | /* Shared definitions for GNU DIFF |
2 | Copyright (C) 1988, 1989 Free Software Foundation, Inc. | |
3 | ||
4 | This file is part of GNU DIFF. | |
5 | ||
6 | GNU DIFF is free software; you can redistribute it and/or modify | |
7 | it under the terms of the GNU General Public License as published by | |
8 | the Free Software Foundation; either version 1, or (at your option) | |
9 | any later version. | |
10 | ||
11 | GNU DIFF is distributed in the hope that it will be useful, | |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | GNU General Public License for more details. | |
15 | ||
16 | You should have received a copy of the GNU General Public License | |
17 | along with GNU DIFF; see the file COPYING. If not, write to | |
18 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ | |
19 | ||
20 | ||
21 | #include <ctype.h> | |
22 | #include <stdio.h> | |
23 | #include <sys/types.h> | |
24 | #include <sys/stat.h> | |
25 | ||
26 | #ifdef USG | |
27 | #include <time.h> | |
28 | #ifdef HAVE_NDIR | |
29 | #ifdef NDIR_IN_SYS | |
30 | #include <sys/ndir.h> | |
31 | #else | |
32 | #include <ndir.h> | |
33 | #endif /* not NDIR_IN_SYS */ | |
34 | #else | |
35 | #include <dirent.h> | |
36 | #endif /* not HAVE_NDIR */ | |
37 | #include <fcntl.h> | |
38 | #ifndef HAVE_DIRECT | |
39 | #define direct dirent | |
40 | #endif | |
41 | #else /* not USG */ | |
42 | #include <sys/time.h> | |
43 | #include <sys/dir.h> | |
44 | #include <sys/file.h> | |
45 | #endif | |
46 | ||
47 | #ifdef USG | |
48 | /* Define needed BSD functions in terms of sysV library. */ | |
49 | ||
50 | #define bcopy(s,d,n) memcpy((d),(s),(n)) | |
51 | #define bcmp(s1,s2,n) memcmp((s1),(s2),(n)) | |
52 | #define bzero(s,n) memset((s),0,(n)) | |
53 | ||
54 | #ifndef XENIX | |
55 | #define dup2(f,t) (close(t),fcntl((f),F_DUPFD,(t))) | |
56 | #endif | |
57 | ||
58 | #define vfork fork | |
59 | #define index strchr | |
60 | #define rindex strrchr | |
61 | #endif | |
62 | ||
63 | #ifdef sparc | |
64 | /* vfork clobbers registers on the Sparc, so don't use it. */ | |
65 | #define vfork fork | |
66 | #endif | |
67 | \f | |
68 | #include <errno.h> | |
69 | extern int errno; | |
70 | extern int sys_nerr; | |
71 | extern char *sys_errlist[]; | |
72 | ||
73 | #define EOS (0) | |
74 | #define FALSE (0) | |
75 | #define TRUE 1 | |
76 | ||
77 | #define min(a,b) ((a) <= (b) ? (a) : (b)) | |
78 | #define max(a,b) ((a) >= (b) ? (a) : (b)) | |
79 | ||
80 | #ifndef PR_FILE_NAME | |
81 | #define PR_FILE_NAME "/bin/pr" | |
82 | #endif | |
83 | ||
84 | /* Support old-fashioned C compilers. */ | |
85 | #if defined (__STDC__) || defined (__GNUC__) | |
86 | #include "limits.h" | |
87 | #else | |
88 | #define INT_MAX 2147483647 | |
89 | #define CHAR_BIT 8 | |
90 | #endif | |
91 | ||
92 | /* Support old-fashioned C compilers. */ | |
93 | #if !defined (__STDC__) && !defined (__GNUC__) | |
94 | #define const | |
95 | #endif | |
96 | ||
97 | #ifndef O_RDONLY | |
98 | #define O_RDONLY 0 | |
99 | #endif | |
100 | \f | |
101 | /* Variables for command line options */ | |
102 | ||
103 | #ifndef GDIFF_MAIN | |
104 | #define EXTERN extern | |
105 | #else | |
106 | #define EXTERN | |
107 | #endif | |
108 | ||
109 | enum output_style { | |
110 | /* Default output style. */ | |
111 | OUTPUT_NORMAL, | |
112 | /* Output the differences with lines of context before and after (-c). */ | |
113 | OUTPUT_CONTEXT, | |
114 | /* Output the differences in a unified context diff format (-u). */ | |
115 | OUTPUT_UNIFIED, | |
116 | /* Output the differences as commands suitable for `ed' (-e). */ | |
117 | OUTPUT_ED, | |
118 | /* Output the diff as a forward ed script (-f). */ | |
119 | OUTPUT_FORWARD_ED, | |
120 | /* Like -f, but output a count of changed lines in each "command" (-n). */ | |
121 | OUTPUT_RCS, | |
122 | /* Output merged #ifdef'd file (-D). */ | |
123 | OUTPUT_IFDEF }; | |
124 | ||
125 | /* True for output styles that are robust, | |
126 | i.e. can handle a file that ends in a non-newline. */ | |
127 | #define ROBUST_OUTPUT_STYLE(S) \ | |
128 | ((S) == OUTPUT_CONTEXT || (S) == OUTPUT_UNIFIED || (S) == OUTPUT_RCS \ | |
129 | || (S) == OUTPUT_NORMAL) | |
130 | ||
131 | EXTERN enum output_style output_style; | |
132 | ||
133 | /* Number of lines of context to show in each set of diffs. | |
134 | This is zero when context is not to be shown. */ | |
135 | EXTERN int context; | |
136 | ||
137 | /* Consider all files as text files (-a). | |
138 | Don't interpret codes over 0177 as implying a "binary file". */ | |
139 | EXTERN int always_text_flag; | |
140 | ||
141 | /* Ignore changes in horizontal whitespace (-b). */ | |
142 | EXTERN int ignore_space_change_flag; | |
143 | ||
144 | /* Ignore all horizontal whitespace (-w). */ | |
145 | EXTERN int ignore_all_space_flag; | |
146 | ||
147 | /* Ignore changes that affect only blank lines (-B). */ | |
148 | EXTERN int ignore_blank_lines_flag; | |
149 | ||
150 | /* Ignore changes that affect only lines matching this regexp (-I). */ | |
151 | EXTERN char *ignore_regexp; | |
152 | ||
153 | /* Result of regex-compilation of `ignore_regexp'. */ | |
154 | EXTERN struct re_pattern_buffer ignore_regexp_compiled; | |
155 | ||
156 | /* 1 if lines may match even if their lengths are different. | |
157 | This depends on various options. */ | |
158 | EXTERN int length_varies; | |
159 | ||
160 | /* Ignore differences in case of letters (-i). */ | |
161 | EXTERN int ignore_case_flag; | |
162 | ||
163 | /* File labels for `-c' output headers (-L). */ | |
164 | EXTERN char *file_label[2]; | |
165 | ||
166 | /* Regexp to identify function-header lines (-F). */ | |
167 | EXTERN char *function_regexp; | |
168 | ||
169 | /* Result of regex-compilation of `function_regexp'. */ | |
170 | EXTERN struct re_pattern_buffer function_regexp_compiled; | |
171 | ||
172 | /* Say only whether files differ, not how (-q). */ | |
173 | EXTERN int no_details_flag; | |
174 | ||
175 | /* Report files compared that match (-s). | |
176 | Normally nothing is output when that happens. */ | |
177 | EXTERN int print_file_same_flag; | |
178 | ||
179 | /* character that ends a line. Currently this is always `\n'. */ | |
180 | EXTERN char line_end_char; | |
181 | ||
182 | /* Output the differences with exactly 8 columns added to each line | |
183 | so that any tabs in the text line up properly (-T). */ | |
184 | EXTERN int tab_align_flag; | |
185 | ||
186 | /* Expand tabs in the output so the text lines up properly | |
187 | despite the characters added to the front of each line (-t). */ | |
188 | EXTERN int tab_expand_flag; | |
189 | ||
190 | /* In directory comparison, specify file to start with (-S). | |
191 | All file names less than this name are ignored. */ | |
192 | EXTERN char *dir_start_file; | |
193 | ||
194 | /* If a file is new (appears in only one dir) | |
195 | include its entire contents (-N). | |
196 | Then `patch' would create the file with appropriate contents. */ | |
197 | EXTERN int entire_new_file_flag; | |
198 | ||
199 | /* Pipe each file's output through pr (-l). */ | |
200 | EXTERN int paginate_flag; | |
201 | ||
202 | /* String to use for #ifdef (-D). */ | |
203 | EXTERN char * ifdef_string; | |
204 | ||
205 | /* String containing all the command options diff received, | |
206 | with spaces between and at the beginning but none at the end. | |
207 | If there were no options given, this string is empty. */ | |
208 | EXTERN char * switch_string; | |
209 | ||
210 | /* Nonzero means use heuristics for better speed. */ | |
211 | EXTERN int heuristic; | |
212 | ||
213 | /* Name of program the user invoked (for error messages). */ | |
214 | EXTERN char * program; | |
215 | \f | |
216 | /* The result of comparison is an "edit script": a chain of `struct change'. | |
217 | Each `struct change' represents one place where some lines are deleted | |
218 | and some are inserted. | |
219 | ||
220 | LINE0 and LINE1 are the first affected lines in the two files (origin 0). | |
221 | DELETED is the number of lines deleted here from file 0. | |
222 | INSERTED is the number of lines inserted here in file 1. | |
223 | ||
224 | If DELETED is 0 then LINE0 is the number of the line before | |
225 | which the insertion was done; vice versa for INSERTED and LINE1. */ | |
226 | ||
227 | struct change | |
228 | { | |
229 | struct change *link; /* Previous or next edit command */ | |
230 | int inserted; /* # lines of file 1 changed here. */ | |
231 | int deleted; /* # lines of file 0 changed here. */ | |
232 | int line0; /* Line number of 1st deleted line. */ | |
233 | int line1; /* Line number of 1st inserted line. */ | |
234 | char ignore; /* Flag used in context.c */ | |
235 | }; | |
236 | \f | |
237 | /* Structures that describe the input files. */ | |
238 | ||
239 | /* Data on one line of text. */ | |
240 | ||
241 | struct line_def { | |
242 | char *text; | |
243 | int length; | |
244 | unsigned hash; | |
245 | }; | |
246 | ||
247 | /* Data on one input file being compared. */ | |
248 | ||
249 | struct file_data { | |
250 | int desc; /* File descriptor */ | |
251 | char *name; /* File name */ | |
252 | struct stat stat; /* File status from fstat() */ | |
253 | int dir_p; /* 1 if file is a directory */ | |
254 | ||
255 | /* Buffer in which text of file is read. */ | |
256 | char * buffer; | |
257 | /* Allocated size of buffer. */ | |
258 | int bufsize; | |
259 | /* Number of valid characters now in the buffer. */ | |
260 | int buffered_chars; | |
261 | ||
262 | /* Array of data on analyzed lines of this chunk of this file. */ | |
263 | struct line_def *linbuf; | |
264 | ||
265 | /* Allocated size of linbuf array (# of elements). */ | |
266 | int linbufsize; | |
267 | ||
268 | /* Number of elements of linbuf containing valid data. */ | |
269 | int buffered_lines; | |
270 | ||
271 | /* Pointer to end of prefix of this file to ignore when hashing. */ | |
272 | char *prefix_end; | |
273 | ||
274 | /* Count of lines in the prefix. */ | |
275 | int prefix_lines; | |
276 | ||
277 | /* Pointer to start of suffix of this file to ignore when hashing. */ | |
278 | char *suffix_begin; | |
279 | ||
280 | /* Count of lines in the suffix. */ | |
281 | int suffix_lines; | |
282 | ||
283 | /* Vector, indexed by line number, containing an equivalence code for | |
284 | each line. It is this vector that is actually compared with that | |
285 | of another file to generate differences. */ | |
286 | int *equivs; | |
287 | ||
288 | /* Vector, like the previous one except that | |
289 | the elements for discarded lines have been squeezed out. */ | |
290 | int *undiscarded; | |
291 | ||
292 | /* Vector mapping virtual line numbers (not counting discarded lines) | |
293 | to real ones (counting those lines). Both are origin-0. */ | |
294 | int *realindexes; | |
295 | ||
296 | /* Total number of nondiscarded lines. */ | |
297 | int nondiscarded_lines; | |
298 | ||
299 | /* Vector, indexed by real origin-0 line number, | |
300 | containing 1 for a line that is an insertion or a deletion. | |
301 | The results of comparison are stored here. */ | |
302 | char *changed_flag; | |
303 | ||
304 | /* 1 if file ends in a line with no final newline. */ | |
305 | int missing_newline; | |
306 | ||
307 | /* 1 more than the maximum equivalence value used for this or its | |
308 | sibling file. */ | |
309 | int equiv_max; | |
310 | ||
311 | /* Table translating diff's internal line numbers | |
312 | to actual line numbers in the file. | |
313 | This is needed only when some lines have been discarded. | |
314 | The allocated size is always linbufsize | |
315 | and the number of valid elements is buffered_lines. */ | |
316 | int *ltran; | |
317 | }; | |
318 | ||
319 | /* Describe the two files currently being compared. */ | |
320 | ||
321 | struct file_data files[2]; | |
322 | \f | |
323 | /* Queue up one-line messages to be printed at the end, | |
324 | when -l is specified. Each message is recorded with a `struct msg'. */ | |
325 | ||
326 | struct msg | |
327 | { | |
328 | struct msg *next; | |
329 | char *format; | |
330 | char *arg1; | |
331 | char *arg2; | |
332 | }; | |
333 | ||
334 | /* Head of the chain of queues messages. */ | |
335 | ||
336 | EXTERN struct msg *msg_chain; | |
337 | ||
338 | /* Tail of the chain of queues messages. */ | |
339 | ||
340 | EXTERN struct msg *msg_chain_end; | |
341 | ||
342 | /* Stdio stream to output diffs to. */ | |
343 | ||
344 | EXTERN FILE *outfile; | |
345 | \f | |
346 | /* Declare various functions. */ | |
347 | ||
348 | #ifdef __STDC__ | |
349 | #define VOID void | |
350 | #else | |
351 | #define VOID char | |
352 | #endif | |
353 | VOID *xmalloc (); | |
354 | VOID *xrealloc (); | |
355 | char *concat (); | |
356 | void free (); | |
357 | char *rindex (); | |
358 | char *index (); | |
359 | ||
360 | void analyze_hunk (); | |
361 | void error (); | |
362 | void fatal (); | |
363 | void message (); | |
364 | void perror_with_name (); | |
365 | void pfatal_with_name (); | |
366 | void print_1_line (); | |
367 | void print_message_queue (); | |
368 | void print_number_range (); | |
369 | void print_script (); | |
370 | void translate_range (); |