12286d8edStholo /* Shared definitions for GNU DIFF 2*b2346922Stholo Copyright (C) 1988, 89, 91, 92, 93, 97, 1998 Free Software Foundation, Inc. 32286d8edStholo 42286d8edStholo This file is part of GNU DIFF. 52286d8edStholo 62286d8edStholo GNU DIFF is free software; you can redistribute it and/or modify 72286d8edStholo it under the terms of the GNU General Public License as published by 82286d8edStholo the Free Software Foundation; either version 2, or (at your option) 92286d8edStholo any later version. 102286d8edStholo 112286d8edStholo GNU DIFF is distributed in the hope that it will be useful, 122286d8edStholo but WITHOUT ANY WARRANTY; without even the implied warranty of 132286d8edStholo MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 142286d8edStholo GNU General Public License for more details. 152286d8edStholo 162286d8edStholo You should have received a copy of the GNU General Public License 172286d8edStholo along with GNU DIFF; see the file COPYING. If not, write to 182286d8edStholo the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ 192286d8edStholo 202286d8edStholo #include "system.h" 212286d8edStholo #include <stdio.h> 222286d8edStholo #include <setjmp.h> 232286d8edStholo #include "regex.h" 24*b2346922Stholo #include "diffrun.h" 252286d8edStholo 262286d8edStholo #define TAB_WIDTH 8 272286d8edStholo 282286d8edStholo /* Variables for command line options */ 292286d8edStholo 302286d8edStholo #ifndef GDIFF_MAIN 312286d8edStholo #define EXTERN extern 322286d8edStholo #else 332286d8edStholo #define EXTERN 342286d8edStholo #endif 352286d8edStholo 36*b2346922Stholo /* The callbacks to use for output. */ 37*b2346922Stholo EXTERN const struct diff_callbacks *callbacks; 38*b2346922Stholo 392286d8edStholo enum output_style { 402286d8edStholo /* Default output style. */ 412286d8edStholo OUTPUT_NORMAL, 422286d8edStholo /* Output the differences with lines of context before and after (-c). */ 432286d8edStholo OUTPUT_CONTEXT, 442286d8edStholo /* Output the differences in a unified context diff format (-u). */ 452286d8edStholo OUTPUT_UNIFIED, 462286d8edStholo /* Output the differences as commands suitable for `ed' (-e). */ 472286d8edStholo OUTPUT_ED, 482286d8edStholo /* Output the diff as a forward ed script (-f). */ 492286d8edStholo OUTPUT_FORWARD_ED, 502286d8edStholo /* Like -f, but output a count of changed lines in each "command" (-n). */ 512286d8edStholo OUTPUT_RCS, 522286d8edStholo /* Output merged #ifdef'd file (-D). */ 532286d8edStholo OUTPUT_IFDEF, 542286d8edStholo /* Output sdiff style (-y). */ 552286d8edStholo OUTPUT_SDIFF 562286d8edStholo }; 572286d8edStholo 582286d8edStholo /* True for output styles that are robust, 592286d8edStholo i.e. can handle a file that ends in a non-newline. */ 602286d8edStholo #define ROBUST_OUTPUT_STYLE(S) ((S) != OUTPUT_ED && (S) != OUTPUT_FORWARD_ED) 612286d8edStholo 622286d8edStholo EXTERN enum output_style output_style; 632286d8edStholo 642286d8edStholo /* Nonzero if output cannot be generated for identical files. */ 652286d8edStholo EXTERN int no_diff_means_no_output; 662286d8edStholo 672286d8edStholo /* Number of lines of context to show in each set of diffs. 682286d8edStholo This is zero when context is not to be shown. */ 692286d8edStholo EXTERN int context; 702286d8edStholo 712286d8edStholo /* Consider all files as text files (-a). 722286d8edStholo Don't interpret codes over 0177 as implying a "binary file". */ 732286d8edStholo EXTERN int always_text_flag; 742286d8edStholo 752286d8edStholo /* Number of lines to keep in identical prefix and suffix. */ 762286d8edStholo EXTERN int horizon_lines; 772286d8edStholo 782286d8edStholo /* Ignore changes in horizontal white space (-b). */ 792286d8edStholo EXTERN int ignore_space_change_flag; 802286d8edStholo 812286d8edStholo /* Ignore all horizontal white space (-w). */ 822286d8edStholo EXTERN int ignore_all_space_flag; 832286d8edStholo 842286d8edStholo /* Ignore changes that affect only blank lines (-B). */ 852286d8edStholo EXTERN int ignore_blank_lines_flag; 862286d8edStholo 872286d8edStholo /* 1 if lines may match even if their contents do not match exactly. 882286d8edStholo This depends on various options. */ 892286d8edStholo EXTERN int ignore_some_line_changes; 902286d8edStholo 912286d8edStholo /* 1 if files may match even if their contents are not byte-for-byte identical. 922286d8edStholo This depends on various options. */ 932286d8edStholo EXTERN int ignore_some_changes; 942286d8edStholo 952286d8edStholo /* Ignore differences in case of letters (-i). */ 962286d8edStholo EXTERN int ignore_case_flag; 972286d8edStholo 982286d8edStholo /* File labels for `-c' output headers (-L). */ 992286d8edStholo EXTERN char *file_label[2]; 1002286d8edStholo 1012286d8edStholo struct regexp_list 1022286d8edStholo { 1032286d8edStholo struct re_pattern_buffer buf; 1042286d8edStholo struct regexp_list *next; 1052286d8edStholo }; 1062286d8edStholo 1072286d8edStholo /* Regexp to identify function-header lines (-F). */ 1082286d8edStholo EXTERN struct regexp_list *function_regexp_list; 1092286d8edStholo 1102286d8edStholo /* Ignore changes that affect only lines matching this regexp (-I). */ 1112286d8edStholo EXTERN struct regexp_list *ignore_regexp_list; 1122286d8edStholo 1132286d8edStholo /* Say only whether files differ, not how (-q). */ 1142286d8edStholo EXTERN int no_details_flag; 1152286d8edStholo 1162286d8edStholo /* Report files compared that match (-s). 1172286d8edStholo Normally nothing is output when that happens. */ 1182286d8edStholo EXTERN int print_file_same_flag; 1192286d8edStholo 1202286d8edStholo /* Output the differences with exactly 8 columns added to each line 1212286d8edStholo so that any tabs in the text line up properly (-T). */ 1222286d8edStholo EXTERN int tab_align_flag; 1232286d8edStholo 1242286d8edStholo /* Expand tabs in the output so the text lines up properly 1252286d8edStholo despite the characters added to the front of each line (-t). */ 1262286d8edStholo EXTERN int tab_expand_flag; 1272286d8edStholo 1282286d8edStholo /* In directory comparison, specify file to start with (-S). 1292286d8edStholo All file names less than this name are ignored. */ 1302286d8edStholo EXTERN char *dir_start_file; 1312286d8edStholo 1322286d8edStholo /* If a file is new (appears in only one dir) 1332286d8edStholo include its entire contents (-N). 1342286d8edStholo Then `patch' would create the file with appropriate contents. */ 1352286d8edStholo EXTERN int entire_new_file_flag; 1362286d8edStholo 1372286d8edStholo /* If a file is new (appears in only the second dir) 1382286d8edStholo include its entire contents (-P). 1392286d8edStholo Then `patch' would create the file with appropriate contents. */ 1402286d8edStholo EXTERN int unidirectional_new_file_flag; 1412286d8edStholo 1422286d8edStholo /* Pipe each file's output through pr (-l). */ 1432286d8edStholo EXTERN int paginate_flag; 1442286d8edStholo 1452286d8edStholo enum line_class { 1462286d8edStholo /* Lines taken from just the first file. */ 1472286d8edStholo OLD, 1482286d8edStholo /* Lines taken from just the second file. */ 1492286d8edStholo NEW, 1502286d8edStholo /* Lines common to both files. */ 1512286d8edStholo UNCHANGED, 1522286d8edStholo /* A hunk containing both old and new lines (line groups only). */ 1532286d8edStholo CHANGED 1542286d8edStholo }; 1552286d8edStholo 1562286d8edStholo /* Line group formats for old, new, unchanged, and changed groups. */ 1572286d8edStholo EXTERN char *group_format[CHANGED + 1]; 1582286d8edStholo 1592286d8edStholo /* Line formats for old, new, and unchanged lines. */ 1602286d8edStholo EXTERN char *line_format[UNCHANGED + 1]; 1612286d8edStholo 1622286d8edStholo /* If using OUTPUT_SDIFF print extra information to help the sdiff filter. */ 1632286d8edStholo EXTERN int sdiff_help_sdiff; 1642286d8edStholo 1652286d8edStholo /* Tell OUTPUT_SDIFF to show only the left version of common lines. */ 1662286d8edStholo EXTERN int sdiff_left_only; 1672286d8edStholo 1682286d8edStholo /* Tell OUTPUT_SDIFF to not show common lines. */ 1692286d8edStholo EXTERN int sdiff_skip_common_lines; 1702286d8edStholo 1712286d8edStholo /* The half line width and column 2 offset for OUTPUT_SDIFF. */ 1722286d8edStholo EXTERN unsigned sdiff_half_width; 1732286d8edStholo EXTERN unsigned sdiff_column2_offset; 1742286d8edStholo 1752286d8edStholo /* String containing all the command options diff received, 1762286d8edStholo with spaces between and at the beginning but none at the end. 1772286d8edStholo If there were no options given, this string is empty. */ 1782286d8edStholo EXTERN char * switch_string; 1792286d8edStholo 1802286d8edStholo /* Nonzero means use heuristics for better speed. */ 1812286d8edStholo EXTERN int heuristic; 1822286d8edStholo 1832286d8edStholo /* Name of program the user invoked (for error messages). */ 1842286d8edStholo EXTERN char *diff_program_name; 1852286d8edStholo 1862286d8edStholo /* Jump buffer for nonlocal exits. */ 1872286d8edStholo EXTERN jmp_buf diff_abort_buf; 1882286d8edStholo #define DIFF_ABORT(retval) longjmp(diff_abort_buf, retval) 1892286d8edStholo 1902286d8edStholo /* The result of comparison is an "edit script": a chain of `struct change'. 1912286d8edStholo Each `struct change' represents one place where some lines are deleted 1922286d8edStholo and some are inserted. 1932286d8edStholo 1942286d8edStholo LINE0 and LINE1 are the first affected lines in the two files (origin 0). 1952286d8edStholo DELETED is the number of lines deleted here from file 0. 1962286d8edStholo INSERTED is the number of lines inserted here in file 1. 1972286d8edStholo 1982286d8edStholo If DELETED is 0 then LINE0 is the number of the line before 1992286d8edStholo which the insertion was done; vice versa for INSERTED and LINE1. */ 2002286d8edStholo 2012286d8edStholo struct change 2022286d8edStholo { 2032286d8edStholo struct change *link; /* Previous or next edit command */ 2042286d8edStholo int inserted; /* # lines of file 1 changed here. */ 2052286d8edStholo int deleted; /* # lines of file 0 changed here. */ 2062286d8edStholo int line0; /* Line number of 1st deleted line. */ 2072286d8edStholo int line1; /* Line number of 1st inserted line. */ 2082286d8edStholo char ignore; /* Flag used in context.c */ 2092286d8edStholo }; 2102286d8edStholo 2112286d8edStholo /* Structures that describe the input files. */ 2122286d8edStholo 2132286d8edStholo /* Data on one input file being compared. */ 2142286d8edStholo 2152286d8edStholo struct file_data { 2162286d8edStholo int desc; /* File descriptor */ 2172286d8edStholo char const *name; /* File name */ 2182286d8edStholo struct stat stat; /* File status from fstat() */ 2192286d8edStholo int dir_p; /* nonzero if file is a directory */ 2202286d8edStholo 2212286d8edStholo /* Buffer in which text of file is read. */ 2222286d8edStholo char * buffer; 2232286d8edStholo /* Allocated size of buffer. */ 2242286d8edStholo size_t bufsize; 2252286d8edStholo /* Number of valid characters now in the buffer. */ 2262286d8edStholo size_t buffered_chars; 2272286d8edStholo 2282286d8edStholo /* Array of pointers to lines in the file. */ 2292286d8edStholo char const **linbuf; 2302286d8edStholo 2312286d8edStholo /* linbuf_base <= buffered_lines <= valid_lines <= alloc_lines. 2322286d8edStholo linebuf[linbuf_base ... buffered_lines - 1] are possibly differing. 2332286d8edStholo linebuf[linbuf_base ... valid_lines - 1] contain valid data. 2342286d8edStholo linebuf[linbuf_base ... alloc_lines - 1] are allocated. */ 2352286d8edStholo int linbuf_base, buffered_lines, valid_lines, alloc_lines; 2362286d8edStholo 2372286d8edStholo /* Pointer to end of prefix of this file to ignore when hashing. */ 2382286d8edStholo char const *prefix_end; 2392286d8edStholo 2402286d8edStholo /* Count of lines in the prefix. 2412286d8edStholo There are this many lines in the file before linbuf[0]. */ 2422286d8edStholo int prefix_lines; 2432286d8edStholo 2442286d8edStholo /* Pointer to start of suffix of this file to ignore when hashing. */ 2452286d8edStholo char const *suffix_begin; 2462286d8edStholo 2472286d8edStholo /* Vector, indexed by line number, containing an equivalence code for 2482286d8edStholo each line. It is this vector that is actually compared with that 2492286d8edStholo of another file to generate differences. */ 2502286d8edStholo int *equivs; 2512286d8edStholo 2522286d8edStholo /* Vector, like the previous one except that 2532286d8edStholo the elements for discarded lines have been squeezed out. */ 2542286d8edStholo int *undiscarded; 2552286d8edStholo 2562286d8edStholo /* Vector mapping virtual line numbers (not counting discarded lines) 2572286d8edStholo to real ones (counting those lines). Both are origin-0. */ 2582286d8edStholo int *realindexes; 2592286d8edStholo 2602286d8edStholo /* Total number of nondiscarded lines. */ 2612286d8edStholo int nondiscarded_lines; 2622286d8edStholo 2632286d8edStholo /* Vector, indexed by real origin-0 line number, 2642286d8edStholo containing 1 for a line that is an insertion or a deletion. 2652286d8edStholo The results of comparison are stored here. */ 2662286d8edStholo char *changed_flag; 2672286d8edStholo 2682286d8edStholo /* 1 if file ends in a line with no final newline. */ 2692286d8edStholo int missing_newline; 2702286d8edStholo 2712286d8edStholo /* 1 more than the maximum equivalence value used for this or its 2722286d8edStholo sibling file. */ 2732286d8edStholo int equiv_max; 2742286d8edStholo }; 2752286d8edStholo 2762286d8edStholo /* Describe the two files currently being compared. */ 2772286d8edStholo 2782286d8edStholo EXTERN struct file_data files[2]; 2792286d8edStholo 2802286d8edStholo /* Stdio stream to output diffs to. */ 2812286d8edStholo 2822286d8edStholo EXTERN FILE *outfile; 2832286d8edStholo 2842286d8edStholo /* Declare various functions. */ 2852286d8edStholo 2862286d8edStholo /* analyze.c */ 2872286d8edStholo int diff_2_files PARAMS((struct file_data[], int)); 2882286d8edStholo 2892286d8edStholo /* context.c */ 2902286d8edStholo void print_context_header PARAMS((struct file_data[], int)); 2912286d8edStholo void print_context_script PARAMS((struct change *, int)); 2922286d8edStholo 2932286d8edStholo /* diff.c */ 2942286d8edStholo int excluded_filename PARAMS((char const *)); 2952286d8edStholo 2962286d8edStholo /* dir.c */ 2972286d8edStholo int diff_dirs PARAMS((struct file_data const[], int (*) PARAMS((char const *, char const *, char const *, char const *, int)), int)); 2982286d8edStholo 2992286d8edStholo /* ed.c */ 3002286d8edStholo void print_ed_script PARAMS((struct change *)); 3012286d8edStholo void pr_forward_ed_script PARAMS((struct change *)); 3022286d8edStholo 3032286d8edStholo /* ifdef.c */ 3042286d8edStholo void print_ifdef_script PARAMS((struct change *)); 3052286d8edStholo 3062286d8edStholo /* io.c */ 3072286d8edStholo int read_files PARAMS((struct file_data[], int)); 3082286d8edStholo int sip PARAMS((struct file_data *, int)); 3092286d8edStholo void slurp PARAMS((struct file_data *)); 3102286d8edStholo 3112286d8edStholo /* normal.c */ 3122286d8edStholo void print_normal_script PARAMS((struct change *)); 3132286d8edStholo 3142286d8edStholo /* rcs.c */ 3152286d8edStholo void print_rcs_script PARAMS((struct change *)); 3162286d8edStholo 3172286d8edStholo /* side.c */ 3182286d8edStholo void print_sdiff_script PARAMS((struct change *)); 3192286d8edStholo 3202286d8edStholo /* util.c */ 3212286d8edStholo VOID *xmalloc PARAMS((size_t)); 3222286d8edStholo VOID *xrealloc PARAMS((VOID *, size_t)); 3232286d8edStholo char *concat PARAMS((char const *, char const *, char const *)); 3242286d8edStholo char *dir_file_pathname PARAMS((char const *, char const *)); 3252286d8edStholo int change_letter PARAMS((int, int)); 3262286d8edStholo int line_cmp PARAMS((char const *, char const *)); 3272286d8edStholo int translate_line_number PARAMS((struct file_data const *, int)); 3282286d8edStholo struct change *find_change PARAMS((struct change *)); 3292286d8edStholo struct change *find_reverse_change PARAMS((struct change *)); 3302286d8edStholo void analyze_hunk PARAMS((struct change *, int *, int *, int *, int *, int *, int *)); 3312286d8edStholo void begin_output PARAMS((void)); 3322286d8edStholo void debug_script PARAMS((struct change *)); 3332286d8edStholo void diff_error PARAMS((char const *, char const *, char const *)); 3342286d8edStholo void fatal PARAMS((char const *)); 3352286d8edStholo void finish_output PARAMS((void)); 336*b2346922Stholo void write_output PARAMS((char const *, size_t)); 337*b2346922Stholo void printf_output PARAMS((char const *, ...)) 338*b2346922Stholo #if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 6) 339*b2346922Stholo __attribute__ ((__format__ (__printf__, 1, 2))) 340*b2346922Stholo #endif 341*b2346922Stholo ; 342*b2346922Stholo void flush_output PARAMS((void)); 3432286d8edStholo void message PARAMS((char const *, char const *, char const *)); 3442286d8edStholo void message5 PARAMS((char const *, char const *, char const *, char const *, char const *)); 3452286d8edStholo void output_1_line PARAMS((char const *, char const *, char const *, char const *)); 3462286d8edStholo void perror_with_name PARAMS((char const *)); 3472286d8edStholo void pfatal_with_name PARAMS((char const *)); 3482286d8edStholo void print_1_line PARAMS((char const *, char const * const *)); 3492286d8edStholo void print_message_queue PARAMS((void)); 3502286d8edStholo void print_number_range PARAMS((int, struct file_data *, int, int)); 3512286d8edStholo void print_script PARAMS((struct change *, struct change * (*) PARAMS((struct change *)), void (*) PARAMS((struct change *)))); 3522286d8edStholo void setup_output PARAMS((char const *, char const *, int)); 3532286d8edStholo void translate_range PARAMS((struct file_data const *, int, int, int *, int *)); 3542286d8edStholo 3552286d8edStholo /* version.c */ 3562286d8edStholo extern char const diff_version_string[]; 357