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