/* wdiff -- front end to diff for comparing on a word per word basis.
Copyright (C) 1992 Free Software Foundation, Inc.
Francois Pinard <[email protected]>.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#if HAVE_CONFIG_H
# include <config.h>
#endif
/* Exit codes values. */
#define EXIT_NO_DIFFERENCES 0 /* no differences found */
#define EXIT_ANY_DIFFERENCE 1 /* some differences found */
#define EXIT_OTHER_REASON 2 /* any other reason for exit */
/* It is mandatory that some `diff' program is selected for use. The
following definition may also include the complete path. */
#ifndef DIFF_PROGRAM
# define DIFF_PROGRAM "diff"
#endif
/* One may also, optionnaly, define a default PAGER_PROGRAM. This might
be done from the Makefile. If PAGER_PROGRAM is undefined and the
PAGER environment variable is not set, none will be used. */
/* Define the separator lines when output is inhibited. */
#define SEPARATOR_LINE \
"======================================================================"
/* Library declarations. */
#if STDC_HEADERS
# include <stdlib.h>
#endif
#include <ctype.h>
#include <stdio.h>
#if STDC_HEADERS
# include <string.h>
#else
# if HAVE_STRING_H
# include <string.h>
# else
# include <strings.h>
# define strrchr rindex
# endif
#endif
char *strstr ();
#if HAVE_TPUTS
# if HAVE_TERMCAP_H
# include <termcap.h>
# else
const char *tgetstr ();
# endif
#endif
#include <sys/types.h>
#include <setjmp.h>
#include <signal.h>
#ifndef RETSIGTYPE
# define RETSIGTYPE void
#endif
#include <sys/stat.h>
#if HAVE_UNISTD_H
# include <unistd.h>
#endif
#include <errno.h>
#ifndef errno
extern int errno;
#endif
#include "getopt.h"
#ifdef PROTOTYPES
# define _(Args) Args
#else
# define _(Args) ()
#endif
char *getenv ();
FILE *readpipe _((const char *, ...));
FILE *writepipe _((const char *, ...));
char *tmpnam ();
void error ();
/* Declarations. */
/* Option variables. */
struct option const longopts[] =
{
{"copyright" , 0, NULL, 'C'},
{"version" , 0, NULL, 'V'},
{"no-deleted" , 0, NULL, '1'},
{"no-inserted" , 0, NULL, '2'},
{"no-common" , 0, NULL, '3'},
{"help" , 0, NULL, 'h'},
{"ignore-case" , 0, NULL, 'i'},
{"printer" , 0, NULL, 'p'},
{"statistics" , 0, NULL, 's'},
{"terminal" , 0, NULL, 't'},
{"start-delete", 1, NULL, 'w'},
{"end-delete" , 1, NULL, 'x'},
{"start-insert", 1, NULL, 'y'},
{"end-insert" , 1, NULL, 'z'},
{NULL , 0, NULL, 0}
};
static char const copyright[] =
"Copyright (C) 1992 Free Software Foundation, Inc.";
const char *program_name; /* name of executing program */
int inhibit_left; /* inhibit display of left side words */
int inhibit_right; /* inhibit display of left side words */
int inhibit_common; /* inhibit display of common words */
int ignore_case; /* ignore case in comparisons */
int show_statistics; /* if printing summary statistics */
int no_wrapping; /* end/restart strings at end of lines */
int autopager; /* if calling the pager automatically */
int overstrike; /* if using printer overstrikes */
int overstrike_for_less; /* if output aimed to the "less" program */
const char *user_delete_start; /* user specified string for start of delete */
const char *user_delete_end; /* user specified string for end of delete */
const char *user_insert_start; /* user specified string for start of insert */
const char *user_insert_end; /* user specified string for end of insert */
int find_termcap; /* initialize the termcap strings */
const char *term_delete_start; /* termcap string for start of delete */
const char *term_delete_end; /* termcap string for end of delete */
const char *term_insert_start; /* termcap string for start of insert */
const char *term_insert_end; /* termcap string for end of insert */
/* Other variables. */
enum copy_mode
{
COPY_NORMAL, /* copy text unemphasized */
COPY_DELETED, /* copy text underlined */
COPY_INSERTED /* copy text bolded */
}
copy_mode;
jmp_buf signal_label; /* where to jump when signal received */
int interrupted; /* set when some signal has been received */
/* Guarantee some value for L_tmpnam. */
#ifndef L_tmpnam
# include "pathmax.h"
# define L_tmpnam PATH_MAX
#endif
typedef struct side SIDE; /* all variables for one side */
struct side
{
const char *filename; /* original input file name */
FILE *file; /* original input file */
int position; /* number of words read so far */
int character; /* one character look ahead */
char temp_name[L_tmpnam]; /* temporary file name */
FILE *temp_file; /* temporary file */
};
SIDE side_array[2]; /* area for holding side descriptions */
SIDE *left_side = &side_array[0];
SIDE *right_side = &side_array[1];
FILE *input_file; /* stream being produced by diff */
int character; /* for reading input_file */
char directive; /* diff directive character */
int argument[4]; /* four diff directive arguments */
FILE *output_file; /* file to which we write output */
const char *termcap_init_string; /* how to initialize the termcap mode */
const char *termcap_end_string; /* how to complete the termcap mode */
int count_total_left; /* count of total words in left file */
int count_total_right; /* count of total words in right file */
int count_isolated_left; /* count of deleted words in left file */
int count_isolated_right; /* count of added words in right file */
int count_changed_left; /* count of changed words in left file */
int count_changed_right; /* count of changed words in right file */
/* Signal processing. */
/*-----------------.
| Signal handler. |
`-----------------*/
static RETSIGTYPE
signal_handler (int number)
{
interrupted = 1;
signal (number, signal_handler);
}
/*----------------------------.
| Prepare to handle signals. |
`----------------------------*/
static void
setup_signals (void)
{
interrupted = 0;
/* Intercept willingful requests for stopping. */
signal (SIGINT, signal_handler);
signal (SIGPIPE, signal_handler);
signal (SIGTERM, signal_handler);
}
/* Terminal initialization. */
static void
initialize_strings (void)
{
#if HAVE_TPUTS
if (find_termcap)
{
const char *name; /* terminal capability name */
char term_buffer[2048]; /* terminal description */
static char *buffer; /* buffer for capabilities */
char *filler; /* cursor into allocated strings */
int success; /* tgetent results */
name = getenv ("TERM");
if (name == NULL)
error (1, 0, "Specify a terminal type with `setenv TERM <yourtype>'.");
success = tgetent (term_buffer, name);
if (success < 0)
error (1, 0, "Could not access the termcap data base.");
if (success == 0)
error (1, 0, "Terminal type `%s' is not defined.", name);
buffer = (char *) malloc (strlen (term_buffer));
filler = buffer;
termcap_init_string = tgetstr ("ti", &filler);
termcap_end_string = tgetstr ("te", &filler);
term_delete_start = tgetstr ("us", &filler);
term_delete_end = tgetstr ("ue", &filler);
term_insert_start = tgetstr ("so", &filler);
term_insert_end = tgetstr ("se", &filler);
}
#endif /* HAVE_TPUTS */
/* Ensure some default strings. */
if (!overstrike)
{
if (!term_delete_start && !user_delete_start)
user_delete_start = "[-";
if (!term_delete_en
评论0