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