⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sdiff.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
/* SDIFF -- interactive merge front end to diff   Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc.This file is part of GNU DIFF.GNU DIFF is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2, or (at your option)any later version.GNU DIFF is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with GNU DIFF; see the file COPYING.  If not, write tothe Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  *//* GNU SDIFF was written by Thomas Lord. */#include <sys/cdefs.h>__FBSDID("$FreeBSD: src/contrib/diff/sdiff.c,v 1.1.1.1.12.1 2002/01/28 01:26:35 nectar Exp $");#include "system.h"#include <stdio.h>#include <signal.h>#include "getopt.h"/* Size of chunks read from files which must be parsed into lines. */#define SDIFF_BUFSIZE ((size_t) 65536)/* Default name of the diff program */#ifndef DIFF_PROGRAM#define DIFF_PROGRAM "/usr/bin/diff"#endif/* Users' editor of nonchoice */#ifndef DEFAULT_EDITOR_PROGRAM#define DEFAULT_EDITOR_PROGRAM "ed"#endifextern char version_string[];static char const *program_name;static char const *diffbin = DIFF_PROGRAM;static char const *edbin = DEFAULT_EDITOR_PROGRAM;static char const **diffargv;static char *tmpname;static int volatile tmpmade;#if HAVE_FORKstatic pid_t volatile diffpid;#endifstruct line_filter;static FILE *ck_fopen PARAMS((char const *, char const *));static RETSIGTYPE catchsig PARAMS((int));static VOID *xmalloc PARAMS((size_t));static char const *expand_name PARAMS((char *, int, char const *));static int edit PARAMS((struct line_filter *, int, struct line_filter *, int, FILE*));static int interact PARAMS((struct line_filter *, struct line_filter *, struct line_filter *, FILE*));static int lf_snarf PARAMS((struct line_filter *, char *, size_t));static int skip_white PARAMS((void));static size_t ck_fread PARAMS((char *, size_t, FILE *));static size_t lf_refill PARAMS((struct line_filter *));static void checksigs PARAMS((void));static void ck_fclose PARAMS((FILE *));static void ck_fflush PARAMS((FILE *));static void ck_fwrite PARAMS((char const *, size_t, FILE *));static void cleanup PARAMS((void));static void diffarg PARAMS((char const *));static void execdiff PARAMS((void));static void exiterr PARAMS((void));static void fatal PARAMS((char const *));static void flush_line PARAMS((void));static void give_help PARAMS((void));static void lf_copy PARAMS((struct line_filter *, int, FILE *));static void lf_init PARAMS((struct line_filter *, FILE *));static void lf_skip PARAMS((struct line_filter *, int));static void perror_fatal PARAMS((char const *));static void trapsigs PARAMS((void));static void try_help PARAMS((char const *));static void untrapsig PARAMS((int));static void usage PARAMS((void));static int diraccess PARAMS((char const *));/* Options: *//* name of output file if -o spec'd */static char *out_file;/* do not print common lines if true, set by -s option */static int suppress_common_flag;static struct option const longopts[] ={  {"ignore-blank-lines", 0, 0, 'B'},  {"speed-large-files", 0, 0, 'H'},  {"ignore-matching-lines", 1, 0, 'I'},  {"ignore-all-space", 0, 0, 'W'}, /* swap W and w for historical reasons */  {"text", 0, 0, 'a'},  {"ignore-space-change", 0, 0, 'b'},  {"minimal", 0, 0, 'd'},  {"ignore-case", 0, 0, 'i'},  {"left-column", 0, 0, 'l'},  {"output", 1, 0, 'o'},  {"suppress-common-lines", 0, 0, 's'},  {"expand-tabs", 0, 0, 't'},  {"width", 1, 0, 'w'},  {"version", 0, 0, 'v'},  {"help", 0, 0, 129},  {0, 0, 0, 0}};static voidtry_help (reason)     char const *reason;{  if (reason)    fprintf (stderr, "%s: %s\n", program_name, reason);  fprintf (stderr, "%s: Try `%s --help' for more information.\n",	   program_name, program_name);  exit (2);}static voidusage (){  printf ("Usage: %s [OPTIONS]... FILE1 FILE2\n\n", program_name);  printf ("%s", "\  -o FILE  --output=FILE  Operate interactively, sending output to FILE.\n\n");  printf ("%s", "\  -i  --ignore-case  Consider upper- and lower-case to be the same.\n\  -W  --ignore-all-space  Ignore all white space.\n\  -b  --ignore-space-change  Ignore changes in the amount of white space.\n\  -B  --ignore-blank-lines  Ignore changes whose lines are all blank.\n\  -I RE  --ignore-matching-lines=RE  Ignore changes whose lines all match RE.\n\  -a  --text  Treat all files as text.\n\n");  printf ("%s", "\  -w NUM  --width=NUM  Output at most NUM (default 130) characters per line.\n\  -l  --left-column  Output only the left column of common lines.\n\  -s  --suppress-common-lines  Do not output common lines.\n\n");  printf ("\  -t  --expand-tabs  Expand tabs to spaces in output.\n\n");  printf ("%s", "\  -d  --minimal  Try hard to find a smaller set of changes.\n\  -H  --speed-large-files  Assume large files and many scattered small changes.\n\n"); printf ("%s", "\  -v  --version  Output version info.\n\  --help  Output this help.\n\n\If FILE1 or FILE2 is `-', read standard input.\n");}static voidcleanup (){#if HAVE_FORK  if (0 < diffpid)    kill (diffpid, SIGPIPE);#endif  if (tmpmade)    unlink (tmpname);}static voidexiterr (){  cleanup ();  untrapsig (0);  checksigs ();  exit (2);}static voidfatal (msg)     char const *msg;{  fprintf (stderr, "%s: %s\n", program_name, msg);  exiterr ();}static voidperror_fatal (msg)     char const *msg;{  int e = errno;  checksigs ();  fprintf (stderr, "%s: ", program_name);  errno = e;  perror (msg);  exiterr ();}/* malloc freely or DIE! */static VOID *xmalloc (size)     size_t size;{  VOID *r = (VOID *) malloc (size);  if (!r)    fatal ("memory exhausted");  return r;}static FILE *ck_fopen (fname, type)     char const *fname, *type;{  FILE *r = fopen (fname, type);  if (!r)    perror_fatal (fname);  return r;}static voidck_fclose (f)     FILE *f;{  if (fclose (f))    perror_fatal ("input/output error");}static size_tck_fread (buf, size, f)     char *buf;     size_t size;     FILE *f;{  size_t r = fread (buf, sizeof (char), size, f);  if (r == 0 && ferror (f))    perror_fatal ("input error");  return r;}static voidck_fwrite (buf, size, f)     char const *buf;     size_t size;     FILE *f;{  if (fwrite (buf, sizeof (char), size, f) != size)    perror_fatal ("output error");}static voidck_fflush (f)     FILE *f;{  if (fflush (f) != 0)    perror_fatal ("output error");}static char const *expand_name (name, is_dir, other_name)     char *name;     int is_dir;     char const *other_name;{  if (strcmp (name, "-") == 0)    fatal ("cannot interactively merge standard input");  if (!is_dir)    return name;  else    {      /* Yield NAME/BASE, where BASE is OTHER_NAME's basename.  */      char const *p = filename_lastdirchar (other_name);      char const *base = p ? p+1 : other_name;      size_t namelen = strlen (name), baselen = strlen (base);      char *r = xmalloc (namelen + baselen + 2);      memcpy (r, name, namelen);      r[namelen] = '/';      memcpy (r + namelen + 1, base, baselen + 1);      return r;    }}struct line_filter {  FILE *infile;  char *bufpos;  char *buffer;  char *buflim;};static voidlf_init (lf, infile)     struct line_filter *lf;     FILE *infile;{  lf->infile = infile;  lf->bufpos = lf->buffer = lf->buflim = xmalloc (SDIFF_BUFSIZE + 1);  lf->buflim[0] = '\n';}/* Fill an exhausted line_filter buffer from its INFILE */static size_tlf_refill (lf)     struct line_filter *lf;{  size_t s = ck_fread (lf->buffer, SDIFF_BUFSIZE, lf->infile);  lf->bufpos = lf->buffer;  lf->buflim = lf->buffer + s;  lf->buflim[0] = '\n';  checksigs ();  return s;}/* Advance LINES on LF's infile, copying lines to OUTFILE */static voidlf_copy (lf, lines, outfile)     struct line_filter *lf;     int lines;     FILE *outfile;{  char *start = lf->bufpos;  while (lines)    {      lf->bufpos = (char *) memchr (lf->bufpos, '\n', lf->buflim - lf->bufpos);      if (! lf->bufpos)	{	  ck_fwrite (start, lf->buflim - start, outfile);	  if (! lf_refill (lf))	    return;	  start = lf->bufpos;	}      else	{	  --lines;	  ++lf->bufpos;	}    }  ck_fwrite (start, lf->bufpos - start, outfile);}/* Advance LINES on LF's infile without doing output */static voidlf_skip (lf, lines)     struct line_filter *lf;     int lines;{  while (lines)    {      lf->bufpos = (char *) memchr (lf->bufpos, '\n', lf->buflim - lf->bufpos);      if (! lf->bufpos)	{	  if (! lf_refill (lf))	    break;	}      else	{	  --lines;	  ++lf->bufpos;	}    }}/* Snarf a line into a buffer.  Return EOF if EOF, 0 if error, 1 if OK.  */static intlf_snarf (lf, buffer, bufsize)     struct line_filter *lf;     char *buffer;     size_t bufsize;{  char *start = lf->bufpos;  for (;;)    {      char *next = (char *) memchr (start, '\n', lf->buflim + 1 - start);      size_t s = next - start;      if (bufsize <= s)	return 0;      memcpy (buffer, start, s);      if (next < lf->buflim)	{	  buffer[s] = 0;	  lf->bufpos = next + 1;	  return 1;	}      if (! lf_refill (lf))	return s ? 0 : EOF;      buffer += s;      bufsize -= s;      start = next;    }}intmain (argc, argv)     int argc;     char *argv[];{  int opt;  char *editor;  char *differ;  initialize_main (&argc, &argv);  program_name = argv[0];  editor = getenv ("EDITOR");  if (editor)    edbin = editor;  differ = getenv ("DIFF");  if (differ)    diffbin = differ;  diffarg ("diff");  /* parse command line args */  while ((opt = getopt_long (argc, argv, "abBdHiI:lo:stvw:W", longopts, 0))	 != EOF)    {      switch (opt)	{	case 'a':	  diffarg ("-a");	  break;	case 'b':	  diffarg ("-b");	  break;	case 'B':	  diffarg ("-B");	  break;	case 'd':	  diffarg ("-d");	  break;	case 'H':	  diffarg ("-H");	  break;	case 'i':	  diffarg ("-i");	  break;	case 'I':	  diffarg ("-I");	  diffarg (optarg);	  break;	case 'l':	  diffarg ("--left-column");	  break;	case 'o':	  out_file = optarg;	  break;	case 's':	  suppress_common_flag = 1;	  break;	case 't':	  diffarg ("-t");	  break;	case 'v':	  printf ("sdiff - GNU diffutils version %s\n", version_string);	  exit (0);	case 'w':	  diffarg ("-W");	  diffarg (optarg);	  break;	case 'W':	  diffarg ("-w");	  break;	case 129:	  usage ();	  if (ferror (stdout) || fclose (stdout) != 0)	    fatal ("write error");	  exit (0);	default:	  try_help (0);	}    }  if (argc - optind != 2)    try_help (argc - optind < 2 ? "missing operand" : "extra operand");  if (! out_file)    {      /* easy case: diff does everything for us */      if (suppress_common_flag)	diffarg ("--suppress-common-lines");      diffarg ("-y");      diffarg ("--");      diffarg (argv[optind]);      diffarg (argv[optind + 1]);      diffarg (0);      execdiff ();    }  else    {      FILE *left, *right, *out, *diffout;      int interact_ok;      struct line_filter lfilt;      struct line_filter rfilt;      struct line_filter diff_filt;      int leftdir = diraccess (argv[optind]);      int rightdir = diraccess (argv[optind + 1]);      if (leftdir && rightdir)	fatal ("both files to be compared are directories");      left = ck_fopen (expand_name (argv[optind], leftdir, argv[optind + 1]), "r");      ;      right = ck_fopen (expand_name (argv[optind + 1], rightdir, argv[optind]), "r");      out = ck_fopen (out_file, "w");      diffarg ("--sdiff-merge-assist");      diffarg ("--");      diffarg (argv[optind]);      diffarg (argv[optind + 1]);      diffarg (0);      trapsigs ();#if ! HAVE_FORK      {	size_t cmdsize = 1;	char *p, *command;	int i;	for (i = 0;  diffargv[i];  i++)	  cmdsize += 4 * strlen (diffargv[i]) + 3;	command = p = xmalloc (cmdsize);	for (i = 0;  diffargv[i];  i++)	  {	    char const *a = diffargv[i];	    SYSTEM_QUOTE_ARG (p, a);	    *p++ = ' ';	  }	p[-1] = '\0';	diffout = popen (command, "r");	if (!diffout)	  perror_fatal (command);	free (command);      }#else /* HAVE_FORK */      {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -