1 /* Shared definitions for GNU DIFF 2 Copyright (C) 1988, 89, 91, 92, 93 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 2, 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 #include "system.h" 21 #include <stdio.h> 22 #ifdef __FreeBSD__ 23 #include <gnuregex.h> 24 #else 25 #include "regex.h" 26 #endif 27 28 #define TAB_WIDTH 8 29 30 /* Variables for command line options */ 31 32 #ifndef GDIFF_MAIN 33 #define EXTERN extern 34 #else 35 #define EXTERN 36 #endif 37 38 enum output_style { 39 /* Default output style. */ 40 OUTPUT_NORMAL, 41 /* Output the differences with lines of context before and after (-c). */ 42 OUTPUT_CONTEXT, 43 /* Output the differences in a unified context diff format (-u). */ 44 OUTPUT_UNIFIED, 45 /* Output the differences as commands suitable for `ed' (-e). */ 46 OUTPUT_ED, 47 /* Output the diff as a forward ed script (-f). */ 48 OUTPUT_FORWARD_ED, 49 /* Like -f, but output a count of changed lines in each "command" (-n). */ 50 OUTPUT_RCS, 51 /* Output merged #ifdef'd file (-D). */ 52 OUTPUT_IFDEF, 53 /* Output sdiff style (-y). */ 54 OUTPUT_SDIFF 55 }; 56 57 /* True for output styles that are robust, 58 i.e. can handle a file that ends in a non-newline. */ 59 #define ROBUST_OUTPUT_STYLE(S) ((S) != OUTPUT_ED && (S) != OUTPUT_FORWARD_ED) 60 61 EXTERN enum output_style output_style; 62 63 /* Nonzero if output cannot be generated for identical files. */ 64 EXTERN int no_diff_means_no_output; 65 66 /* Number of lines of context to show in each set of diffs. 67 This is zero when context is not to be shown. */ 68 EXTERN int context; 69 70 /* Consider all files as text files (-a). 71 Don't interpret codes over 0177 as implying a "binary file". */ 72 EXTERN int always_text_flag; 73 74 /* Number of lines to keep in identical prefix and suffix. */ 75 EXTERN int horizon_lines; 76 77 /* Ignore changes in horizontal white space (-b). */ 78 EXTERN int ignore_space_change_flag; 79 80 /* Ignore all horizontal white space (-w). */ 81 EXTERN int ignore_all_space_flag; 82 83 /* Ignore changes that affect only blank lines (-B). */ 84 EXTERN int ignore_blank_lines_flag; 85 86 /* 1 if lines may match even if their contents do not match exactly. 87 This depends on various options. */ 88 EXTERN int ignore_some_line_changes; 89 90 /* 1 if files may match even if their contents are not byte-for-byte identical. 91 This depends on various options. */ 92 EXTERN int ignore_some_changes; 93 94 /* Ignore differences in case of letters (-i). */ 95 EXTERN int ignore_case_flag; 96 97 /* File labels for `-c' output headers (-L). */ 98 EXTERN char *file_label[2]; 99 100 struct regexp_list 101 { 102 struct re_pattern_buffer buf; 103 struct regexp_list *next; 104 }; 105 106 /* Regexp to identify function-header lines (-F). */ 107 EXTERN struct regexp_list *function_regexp_list; 108 109 /* Ignore changes that affect only lines matching this regexp (-I). */ 110 EXTERN struct regexp_list *ignore_regexp_list; 111 112 /* Say only whether files differ, not how (-q). */ 113 EXTERN int no_details_flag; 114 115 /* Report files compared that match (-s). 116 Normally nothing is output when that happens. */ 117 EXTERN int print_file_same_flag; 118 119 /* Output the differences with exactly 8 columns added to each line 120 so that any tabs in the text line up properly (-T). */ 121 EXTERN int tab_align_flag; 122 123 /* Expand tabs in the output so the text lines up properly 124 despite the characters added to the front of each line (-t). */ 125 EXTERN int tab_expand_flag; 126 127 /* In directory comparison, specify file to start with (-S). 128 All file names less than this name are ignored. */ 129 EXTERN char *dir_start_file; 130 131 /* If a file is new (appears in only one dir) 132 include its entire contents (-N). 133 Then `patch' would create the file with appropriate contents. */ 134 EXTERN int entire_new_file_flag; 135 136 /* If a file is new (appears in only the second dir) 137 include its entire contents (-P). 138 Then `patch' would create the file with appropriate contents. */ 139 EXTERN int unidirectional_new_file_flag; 140 141 /* Pipe each file's output through pr (-l). */ 142 EXTERN int paginate_flag; 143 144 enum line_class { 145 /* Lines taken from just the first file. */ 146 OLD, 147 /* Lines taken from just the second file. */ 148 NEW, 149 /* Lines common to both files. */ 150 UNCHANGED, 151 /* A hunk containing both old and new lines (line groups only). */ 152 CHANGED 153 }; 154 155 /* Line group formats for old, new, unchanged, and changed groups. */ 156 EXTERN char *group_format[CHANGED + 1]; 157 158 /* Line formats for old, new, and unchanged lines. */ 159 EXTERN char *line_format[UNCHANGED + 1]; 160 161 /* If using OUTPUT_SDIFF print extra information to help the sdiff filter. */ 162 EXTERN int sdiff_help_sdiff; 163 164 /* Tell OUTPUT_SDIFF to show only the left version of common lines. */ 165 EXTERN int sdiff_left_only; 166 167 /* Tell OUTPUT_SDIFF to not show common lines. */ 168 EXTERN int sdiff_skip_common_lines; 169 170 /* The half line width and column 2 offset for OUTPUT_SDIFF. */ 171 EXTERN unsigned sdiff_half_width; 172 EXTERN unsigned sdiff_column2_offset; 173 174 /* String containing all the command options diff received, 175 with spaces between and at the beginning but none at the end. 176 If there were no options given, this string is empty. */ 177 EXTERN char * switch_string; 178 179 /* Nonzero means use heuristics for better speed. */ 180 EXTERN int heuristic; 181 182 /* Name of program the user invoked (for error messages). */ 183 EXTERN char *program_name; 184 185 /* The result of comparison is an "edit script": a chain of `struct change'. 186 Each `struct change' represents one place where some lines are deleted 187 and some are inserted. 188 189 LINE0 and LINE1 are the first affected lines in the two files (origin 0). 190 DELETED is the number of lines deleted here from file 0. 191 INSERTED is the number of lines inserted here in file 1. 192 193 If DELETED is 0 then LINE0 is the number of the line before 194 which the insertion was done; vice versa for INSERTED and LINE1. */ 195 196 struct change 197 { 198 struct change *link; /* Previous or next edit command */ 199 int inserted; /* # lines of file 1 changed here. */ 200 int deleted; /* # lines of file 0 changed here. */ 201 int line0; /* Line number of 1st deleted line. */ 202 int line1; /* Line number of 1st inserted line. */ 203 char ignore; /* Flag used in context.c */ 204 }; 205 206 /* Structures that describe the input files. */ 207 208 /* Data on one input file being compared. */ 209 210 struct file_data { 211 int desc; /* File descriptor */ 212 char const *name; /* File name */ 213 struct stat stat; /* File status from fstat() */ 214 int dir_p; /* nonzero if file is a directory */ 215 216 /* Buffer in which text of file is read. */ 217 char * buffer; 218 /* Allocated size of buffer. */ 219 size_t bufsize; 220 /* Number of valid characters now in the buffer. */ 221 size_t buffered_chars; 222 223 /* Array of pointers to lines in the file. */ 224 char const **linbuf; 225 226 /* linbuf_base <= buffered_lines <= valid_lines <= alloc_lines. 227 linebuf[linbuf_base ... buffered_lines - 1] are possibly differing. 228 linebuf[linbuf_base ... valid_lines - 1] contain valid data. 229 linebuf[linbuf_base ... alloc_lines - 1] are allocated. */ 230 int linbuf_base, buffered_lines, valid_lines, alloc_lines; 231 232 /* Pointer to end of prefix of this file to ignore when hashing. */ 233 char const *prefix_end; 234 235 /* Count of lines in the prefix. 236 There are this many lines in the file before linbuf[0]. */ 237 int prefix_lines; 238 239 /* Pointer to start of suffix of this file to ignore when hashing. */ 240 char const *suffix_begin; 241 242 /* Vector, indexed by line number, containing an equivalence code for 243 each line. It is this vector that is actually compared with that 244 of another file to generate differences. */ 245 int *equivs; 246 247 /* Vector, like the previous one except that 248 the elements for discarded lines have been squeezed out. */ 249 int *undiscarded; 250 251 /* Vector mapping virtual line numbers (not counting discarded lines) 252 to real ones (counting those lines). Both are origin-0. */ 253 int *realindexes; 254 255 /* Total number of nondiscarded lines. */ 256 int nondiscarded_lines; 257 258 /* Vector, indexed by real origin-0 line number, 259 containing 1 for a line that is an insertion or a deletion. 260 The results of comparison are stored here. */ 261 char *changed_flag; 262 263 /* 1 if file ends in a line with no final newline. */ 264 int missing_newline; 265 266 /* 1 more than the maximum equivalence value used for this or its 267 sibling file. */ 268 int equiv_max; 269 }; 270 271 /* Describe the two files currently being compared. */ 272 273 EXTERN struct file_data files[2]; 274 275 /* Stdio stream to output diffs to. */ 276 277 EXTERN FILE *outfile; 278 279 /* Declare various functions. */ 280 281 /* analyze.c */ 282 int diff_2_files PARAMS((struct file_data[], int)); 283 284 /* context.c */ 285 void print_context_header PARAMS((struct file_data[], int)); 286 void print_context_script PARAMS((struct change *, int)); 287 288 /* diff.c */ 289 int excluded_filename PARAMS((char const *)); 290 291 /* dir.c */ 292 int diff_dirs PARAMS((struct file_data const[], int (*) PARAMS((char const *, char const *, char const *, char const *, int)), int)); 293 294 /* ed.c */ 295 void print_ed_script PARAMS((struct change *)); 296 void pr_forward_ed_script PARAMS((struct change *)); 297 298 /* ifdef.c */ 299 void print_ifdef_script PARAMS((struct change *)); 300 301 /* io.c */ 302 int read_files PARAMS((struct file_data[], int)); 303 int sip PARAMS((struct file_data *, int)); 304 void slurp PARAMS((struct file_data *)); 305 306 /* normal.c */ 307 void print_normal_script PARAMS((struct change *)); 308 309 /* rcs.c */ 310 void print_rcs_script PARAMS((struct change *)); 311 312 /* side.c */ 313 void print_sdiff_script PARAMS((struct change *)); 314 315 /* util.c */ 316 VOID *xmalloc PARAMS((size_t)); 317 VOID *xrealloc PARAMS((VOID *, size_t)); 318 char *concat PARAMS((char const *, char const *, char const *)); 319 char *dir_file_pathname PARAMS((char const *, char const *)); 320 int change_letter PARAMS((int, int)); 321 int line_cmp PARAMS((char const *, char const *)); 322 int translate_line_number PARAMS((struct file_data const *, int)); 323 struct change *find_change PARAMS((struct change *)); 324 struct change *find_reverse_change PARAMS((struct change *)); 325 void analyze_hunk PARAMS((struct change *, int *, int *, int *, int *, int *, int *)); 326 void begin_output PARAMS((void)); 327 void debug_script PARAMS((struct change *)); 328 void error PARAMS((char const *, char const *, char const *)); 329 void fatal PARAMS((char const *)); 330 void finish_output PARAMS((void)); 331 void message PARAMS((char const *, char const *, char const *)); 332 void message5 PARAMS((char const *, char const *, char const *, char const *, char const *)); 333 void output_1_line PARAMS((char const *, char const *, char const *, char const *)); 334 void perror_with_name PARAMS((char const *)); 335 void pfatal_with_name PARAMS((char const *)); 336 void print_1_line PARAMS((char const *, char const * const *)); 337 void print_message_queue PARAMS((void)); 338 void print_number_range PARAMS((int, struct file_data *, int, int)); 339 void print_script PARAMS((struct change *, struct change * (*) PARAMS((struct change *)), void (*) PARAMS((struct change *)))); 340 void setup_output PARAMS((char const *, char const *, int)); 341 void translate_range PARAMS((struct file_data const *, int, int, int *, int *)); 342 343 /* version.c */ 344 extern char const version_string[]; 345