joachim99@52: /* Shared definitions for GNU DIFF joachim99@52: joachim99@52: Modified for KDiff3 by Joachim Eibl 2003. joachim99@53: The original file was part of GNU DIFF. joachim99@52: joachim99@52: Copyright (C) 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1998, 2001, joachim99@52: 2002 Free Software Foundation, Inc. joachim99@52: joachim99@52: GNU DIFF is free software; you can redistribute it and/or modify joachim99@52: it under the terms of the GNU General Public License as published by joachim99@52: the Free Software Foundation; either version 2, or (at your option) joachim99@52: any later version. joachim99@52: joachim99@52: GNU DIFF is distributed in the hope that it will be useful, joachim99@52: but WITHOUT ANY WARRANTY; without even the implied warranty of joachim99@52: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the joachim99@52: GNU General Public License for more details. joachim99@52: joachim99@52: You should have received a copy of the GNU General Public License joachim99@52: along with this program; see the file COPYING. joachim99@52: If not, write to the Free Software Foundation, joachim99@52: 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ joachim99@52: joachim99@53: #ifndef GNUDIFF_DIFF_H joachim99@53: #define GNUDIFF_DIFF_H joachim99@53: joachim99@52: #include "gnudiff_system.h" joachim99@52: joachim99@52: #include joachim99@52: joachim99@52: #define TAB_WIDTH 8 joachim99@52: joachim99@53: class GnuDiff joachim99@52: { joachim99@53: public: joachim99@52: /* What kind of changes a hunk contains. */ joachim99@52: enum changes joachim99@52: { joachim99@52: /* No changes: lines common to both files. */ joachim99@52: UNCHANGED, joachim99@52: joachim99@52: /* Deletes only: lines taken from just the first file. */ joachim99@52: OLD, joachim99@52: joachim99@52: /* Inserts only: lines taken from just the second file. */ joachim99@52: NEW, joachim99@52: joachim99@52: /* Both deletes and inserts: a hunk containing both old and new lines. */ joachim99@52: CHANGED joachim99@52: }; joachim99@52: joachim99@52: /* Variables for command line options */ joachim99@52: joachim99@52: enum output_style joachim99@52: { joachim99@52: /* No output style specified. */ joachim99@52: OUTPUT_UNSPECIFIED, joachim99@52: joachim99@52: /* Default output style. */ joachim99@52: OUTPUT_NORMAL, joachim99@52: joachim99@52: /* Output the differences with lines of context before and after (-c). */ joachim99@52: OUTPUT_CONTEXT, joachim99@52: joachim99@52: /* Output the differences in a unified context diff format (-u). */ joachim99@52: OUTPUT_UNIFIED, joachim99@52: joachim99@52: /* Output the differences as commands suitable for `ed' (-e). */ joachim99@52: OUTPUT_ED, joachim99@52: joachim99@52: /* Output the diff as a forward ed script (-f). */ joachim99@52: OUTPUT_FORWARD_ED, joachim99@52: joachim99@52: /* Like -f, but output a count of changed lines in each "command" (-n). */ joachim99@52: OUTPUT_RCS, joachim99@52: joachim99@52: /* Output merged #ifdef'd file (-D). */ joachim99@52: OUTPUT_IFDEF, joachim99@52: joachim99@52: /* Output sdiff style (-y). */ joachim99@52: OUTPUT_SDIFF joachim99@52: }; joachim99@52: joachim99@52: /* True for output styles that are robust, joachim99@52: i.e. can handle a file that ends in a non-newline. */ joachim99@52: #define ROBUST_OUTPUT_STYLE(S) ((S) != OUTPUT_ED && (S) != OUTPUT_FORWARD_ED) joachim99@52: joachim99@53: enum output_style output_style; joachim99@52: joachim99@52: /* Nonzero if output cannot be generated for identical files. */ joachim99@53: bool no_diff_means_no_output; joachim99@52: joachim99@52: /* Number of lines of context to show in each set of diffs. joachim99@52: This is zero when context is not to be shown. */ joachim99@53: lin context; joachim99@52: joachim99@52: /* Consider all files as text files (-a). joachim99@52: Don't interpret codes over 0177 as implying a "binary file". */ joachim99@53: bool text; joachim99@52: joachim99@52: /* Number of lines to keep in identical prefix and suffix. */ joachim99@53: lin horizon_lines; joachim99@52: joachim99@52: /* The significance of white space during comparisons. */ joachim99@53: enum joachim99@52: { joachim99@52: /* All white space is significant (the default). */ joachim99@52: IGNORE_NO_WHITE_SPACE, joachim99@52: joachim99@52: /* Ignore changes due to tab expansion (-E). */ joachim99@52: IGNORE_TAB_EXPANSION, joachim99@52: joachim99@52: /* Ignore changes in horizontal white space (-b). */ joachim99@52: IGNORE_SPACE_CHANGE, joachim99@52: joachim99@52: /* Ignore all horizontal white space (-w). */ joachim99@52: IGNORE_ALL_SPACE joachim99@52: } ignore_white_space; joachim99@52: joachim99@52: /* Ignore changes that affect only blank lines (-B). */ joachim99@53: bool ignore_blank_lines; joachim99@52: joachim99@52: /* Ignore changes that affect only numbers. (J. Eibl) */ joachim99@53: bool bIgnoreNumbers; joachim99@53: bool bIgnoreWhiteSpace; joachim99@52: joachim99@52: /* Files can be compared byte-by-byte, as if they were binary. joachim99@52: This depends on various options. */ joachim99@53: bool files_can_be_treated_as_binary; joachim99@52: joachim99@52: /* Ignore differences in case of letters (-i). */ joachim99@53: bool ignore_case; joachim99@52: joachim99@52: /* Ignore differences in case of letters in file names. */ joachim99@53: bool ignore_file_name_case; joachim99@52: joachim99@52: /* File labels for `-c' output headers (--label). */ joachim99@53: char *file_label[2]; joachim99@52: joachim99@52: /* Regexp to identify function-header lines (-F). */ joachim99@53: //struct re_pattern_buffer function_regexp; joachim99@52: joachim99@52: /* Ignore changes that affect only lines matching this regexp (-I). */ joachim99@53: //struct re_pattern_buffer ignore_regexp; joachim99@52: joachim99@52: /* Say only whether files differ, not how (-q). */ joachim99@53: bool brief; joachim99@52: joachim99@52: /* Expand tabs in the output so the text lines up properly joachim99@52: despite the characters added to the front of each line (-t). */ joachim99@53: bool expand_tabs; joachim99@52: joachim99@52: /* Use a tab in the output, rather than a space, before the text of an joachim99@52: input line, so as to keep the proper alignment in the input line joachim99@52: without changing the characters in it (-T). */ joachim99@53: bool initial_tab; joachim99@52: joachim99@52: /* Remove trailing carriage returns from input. */ joachim99@53: bool strip_trailing_cr; joachim99@52: joachim99@52: /* In directory comparison, specify file to start with (-S). joachim99@52: This is used for resuming an aborted comparison. joachim99@52: All file names less than this name are ignored. */ joachim99@53: char const *starting_file; joachim99@52: joachim99@52: /* Pipe each file's output through pr (-l). */ joachim99@53: bool paginate; joachim99@52: joachim99@52: /* Line group formats for unchanged, old, new, and changed groups. */ joachim99@53: char const *group_format[CHANGED + 1]; joachim99@52: joachim99@52: /* Line formats for unchanged, old, and new lines. */ joachim99@53: char const *line_format[NEW + 1]; joachim99@52: joachim99@52: /* If using OUTPUT_SDIFF print extra information to help the sdiff filter. */ joachim99@53: bool sdiff_merge_assist; joachim99@52: joachim99@52: /* Tell OUTPUT_SDIFF to show only the left version of common lines. */ joachim99@53: bool left_column; joachim99@52: joachim99@52: /* Tell OUTPUT_SDIFF to not show common lines. */ joachim99@53: bool suppress_common_lines; joachim99@52: joachim99@52: /* The half line width and column 2 offset for OUTPUT_SDIFF. */ joachim99@53: unsigned int sdiff_half_width; joachim99@53: unsigned int sdiff_column2_offset; joachim99@52: joachim99@52: /* String containing all the command options diff received, joachim99@52: with spaces between and at the beginning but none at the end. joachim99@52: If there were no options given, this string is empty. */ joachim99@53: char *switch_string; joachim99@52: joachim99@52: /* Use heuristics for better speed with large files with a small joachim99@52: density of changes. */ joachim99@53: bool speed_large_files; joachim99@52: joachim99@52: /* Patterns that match file names to be excluded. */ joachim99@53: struct exclude *excluded; joachim99@52: joachim99@52: /* Don't discard lines. This makes things slower (sometimes much joachim99@52: slower) but will find a guaranteed minimal set of changes. */ joachim99@53: bool minimal; joachim99@52: joachim99@52: /* Name of program the user invoked (for error messages). */ joachim99@53: char *program_name; joachim99@52: joachim99@52: /* The strftime format to use for time strings. */ joachim99@53: char const *time_format; joachim99@52: joachim99@52: /* The result of comparison is an "edit script": a chain of `struct change'. joachim99@52: Each `struct change' represents one place where some lines are deleted joachim99@52: and some are inserted. joachim99@52: joachim99@52: LINE0 and LINE1 are the first affected lines in the two files (origin 0). joachim99@52: DELETED is the number of lines deleted here from file 0. joachim99@52: INSERTED is the number of lines inserted here in file 1. joachim99@52: joachim99@52: If DELETED is 0 then LINE0 is the number of the line before joachim99@52: which the insertion was done; vice versa for INSERTED and LINE1. */ joachim99@52: joachim99@52: struct change joachim99@52: { joachim99@52: struct change *link; /* Previous or next edit command */ joachim99@52: lin inserted; /* # lines of file 1 changed here. */ joachim99@52: lin deleted; /* # lines of file 0 changed here. */ joachim99@52: lin line0; /* Line number of 1st deleted line. */ joachim99@52: lin line1; /* Line number of 1st inserted line. */ joachim99@52: bool ignore; /* Flag used in context.c. */ joachim99@52: }; joachim99@52: joachim99@52: /* Structures that describe the input files. */ joachim99@52: joachim99@52: /* Data on one input file being compared. */ joachim99@52: joachim99@52: struct file_data { joachim99@52: #if 0 joachim99@52: int desc; /* File descriptor */ joachim99@52: char const *name; /* File name */ joachim99@52: struct stat stat; /* File status */ joachim99@52: #endif joachim99@52: /* Buffer in which text of file is read. */ joachim99@52: word *buffer; joachim99@52: joachim99@52: /* Allocated size of buffer, in bytes. Always a multiple of joachim99@52: sizeof *buffer. */ joachim99@52: size_t bufsize; joachim99@52: joachim99@52: /* Number of valid bytes now in the buffer. */ joachim99@52: size_t buffered; joachim99@52: joachim99@52: /* Array of pointers to lines in the file. */ joachim99@52: char const **linbuf; joachim99@52: joachim99@52: /* linbuf_base <= buffered_lines <= valid_lines <= alloc_lines. joachim99@52: linebuf[linbuf_base ... buffered_lines - 1] are possibly differing. joachim99@52: linebuf[linbuf_base ... valid_lines - 1] contain valid data. joachim99@52: linebuf[linbuf_base ... alloc_lines - 1] are allocated. */ joachim99@52: lin linbuf_base, buffered_lines, valid_lines, alloc_lines; joachim99@52: joachim99@52: /* Pointer to end of prefix of this file to ignore when hashing. */ joachim99@52: char const *prefix_end; joachim99@52: joachim99@52: /* Count of lines in the prefix. joachim99@52: There are this many lines in the file before linbuf[0]. */ joachim99@52: lin prefix_lines; joachim99@52: joachim99@52: /* Pointer to start of suffix of this file to ignore when hashing. */ joachim99@52: char const *suffix_begin; joachim99@52: joachim99@52: /* Vector, indexed by line number, containing an equivalence code for joachim99@52: each line. It is this vector that is actually compared with that joachim99@52: of another file to generate differences. */ joachim99@52: lin *equivs; joachim99@52: joachim99@52: /* Vector, like the previous one except that joachim99@52: the elements for discarded lines have been squeezed out. */ joachim99@52: lin *undiscarded; joachim99@52: joachim99@52: /* Vector mapping virtual line numbers (not counting discarded lines) joachim99@52: to real ones (counting those lines). Both are origin-0. */ joachim99@52: lin *realindexes; joachim99@52: joachim99@52: /* Total number of nondiscarded lines. */ joachim99@52: lin nondiscarded_lines; joachim99@52: joachim99@52: /* Vector, indexed by real origin-0 line number, joachim99@52: containing TRUE for a line that is an insertion or a deletion. joachim99@52: The results of comparison are stored here. */ joachim99@52: bool *changed; joachim99@52: joachim99@52: /* 1 if file ends in a line with no final newline. */ joachim99@52: bool missing_newline; joachim99@52: joachim99@52: /* 1 if at end of file. */ joachim99@52: bool eof; joachim99@52: joachim99@52: /* 1 more than the maximum equivalence value used for this or its joachim99@52: sibling file. */ joachim99@52: lin equiv_max; joachim99@52: }; joachim99@52: joachim99@52: /* The file buffer, considered as an array of bytes rather than joachim99@52: as an array of words. */ joachim99@52: #define FILE_BUFFER(f) ((char *) (f)->buffer) joachim99@52: joachim99@52: /* Data on two input files being compared. */ joachim99@52: joachim99@52: struct comparison joachim99@52: { joachim99@52: struct file_data file[2]; joachim99@52: struct comparison const *parent; /* parent, if a recursive comparison */ joachim99@52: }; joachim99@52: joachim99@52: /* Describe the two files currently being compared. */ joachim99@52: joachim99@53: struct file_data files[2]; joachim99@52: joachim99@52: /* Stdio stream to output diffs to. */ joachim99@52: joachim99@53: FILE *outfile; joachim99@52: joachim99@52: /* Declare various functions. */ joachim99@52: joachim99@52: /* analyze.c */ joachim99@52: struct change* diff_2_files (struct comparison *); joachim99@52: joachim99@52: /* context.c */ joachim99@52: void print_context_header (struct file_data[], bool); joachim99@52: void print_context_script (struct change *, bool); joachim99@52: joachim99@52: /* dir.c */ joachim99@52: int diff_dirs (struct comparison const *, int (*) (struct comparison const *, char const *, char const *)); joachim99@52: joachim99@52: /* ed.c */ joachim99@52: void print_ed_script (struct change *); joachim99@52: void pr_forward_ed_script (struct change *); joachim99@52: joachim99@52: /* ifdef.c */ joachim99@52: void print_ifdef_script (struct change *); joachim99@52: joachim99@52: /* io.c */ joachim99@52: void file_block_read (struct file_data *, size_t); joachim99@52: bool read_files (struct file_data[], bool); joachim99@52: joachim99@52: /* normal.c */ joachim99@52: void print_normal_script (struct change *); joachim99@52: joachim99@52: /* rcs.c */ joachim99@52: void print_rcs_script (struct change *); joachim99@52: joachim99@52: /* side.c */ joachim99@52: void print_sdiff_script (struct change *); joachim99@52: joachim99@52: /* util.c */ joachim99@53: //extern char const change_letter[4]; joachim99@53: //extern char const pr_program[]; joachim99@52: char *concat (char const *, char const *, char const *); joachim99@52: char *dir_file_pathname (char const *, char const *); joachim99@52: bool lines_differ (char const *, char const *); joachim99@52: lin translate_line_number (struct file_data const *, lin); joachim99@52: struct change *find_change (struct change *); joachim99@52: struct change *find_reverse_change (struct change *); joachim99@52: void *zalloc (size_t); joachim99@52: enum changes analyze_hunk (struct change *, lin *, lin *, lin *, lin *); joachim99@52: void begin_output (void); joachim99@52: void debug_script (struct change *); joachim99@52: void fatal (char const *) __attribute__((noreturn)); joachim99@52: void finish_output (void); joachim99@52: void message (char const *, char const *, char const *); joachim99@52: void message5 (char const *, char const *, char const *, char const *, char const *); joachim99@52: void output_1_line (char const *, char const *, char const *, char const *); joachim99@52: void perror_with_name (char const *); joachim99@52: void pfatal_with_name (char const *) __attribute__((noreturn)); joachim99@52: void print_1_line (char const *, char const * const *); joachim99@52: void print_message_queue (void); joachim99@52: void print_number_range (char, struct file_data *, lin, lin); joachim99@52: void print_script (struct change *, struct change * (*) (struct change *), void (*) (struct change *)); joachim99@52: void setup_output (char const *, char const *, bool); joachim99@52: void translate_range (struct file_data const *, lin, lin, long *, long *); joachim99@52: joachim99@52: /* version.c */ joachim99@53: //extern char const version_string[]; joachim99@53: joachim99@53: private: joachim99@53: // gnudiff_analyze.cpp joachim99@53: lin diag (lin xoff, lin xlim, lin yoff, lin ylim, bool find_minimal, struct partition *part); joachim99@53: void compareseq (lin xoff, lin xlim, lin yoff, lin ylim, bool find_minimal); joachim99@53: void discard_confusing_lines (struct file_data filevec[]); joachim99@53: void shift_boundaries (struct file_data filevec[]); joachim99@53: struct change * add_change (lin line0, lin line1, lin deleted, lin inserted, struct change *old); joachim99@53: struct change * build_reverse_script (struct file_data const filevec[]); joachim99@53: struct change* build_script (struct file_data const filevec[]); joachim99@53: joachim99@53: // gnudiff_io.cpp joachim99@53: void find_and_hash_each_line (struct file_data *current); joachim99@53: void prepare_text (struct file_data *current); joachim99@53: void find_identical_ends (struct file_data filevec[]); joachim99@53: joachim99@53: // gnudiff_xmalloc.cpp joachim99@53: void *xmalloc (size_t n); joachim99@53: void *xcalloc (size_t n, size_t s); joachim99@53: void *xrealloc(void *p, size_t n); joachim99@53: char *xstrdup (const char *str); joachim99@53: void xalloc_die (void); joachim99@53: joachim99@53: inline bool isWhite( char c ) joachim99@53: { joachim99@53: return c==' ' || c=='\t' || c=='\r'; joachim99@53: } joachim99@53: }; // class GnuDiff joachim99@53: joachim99@53: # define XMALLOC(Type, N_items) ((Type *) xmalloc (sizeof (Type) * (N_items))) joachim99@53: # define XCALLOC(Type, N_items) ((Type *) xcalloc (sizeof (Type), (N_items))) joachim99@53: # define XREALLOC(Ptr, Type, N_items) \ joachim99@53: ((Type *) xrealloc ((void *) (Ptr), sizeof (Type) * (N_items))) joachim99@53: joachim99@53: /* Declare and alloc memory for VAR of type TYPE. */ joachim99@53: # define NEW(Type, Var) Type *(Var) = XMALLOC (Type, 1) joachim99@53: joachim99@53: /* Free VAR only if non NULL. */ joachim99@53: # define XFREE(Var) \ joachim99@53: do { \ joachim99@53: if (Var) \ joachim99@53: free (Var); \ joachim99@53: } while (0) joachim99@53: joachim99@53: /* Return a pointer to a malloc'ed copy of the array SRC of NUM elements. */ joachim99@53: # define CCLONE(Src, Num) \ joachim99@53: (memcpy (xmalloc (sizeof (*Src) * (Num)), (Src), sizeof (*Src) * (Num))) joachim99@53: joachim99@53: /* Return a malloc'ed copy of SRC. */ joachim99@53: # define CLONE(Src) CCLONE (Src, 1) joachim99@53: joachim99@53: #endif