/* 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"#endif extern 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;#endif struct 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");Lines 1–500 of 1109. Load more
/* 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 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. GNU DIFF 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 GNU DIFF; see the file COPYING. If not, write to the 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" #endif extern 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_FORK static pid_t volatile diffpid; #endif struct 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 void try_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 void usage () { 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 void cleanup () { #if HAVE_FORK if (0 < diffpid) kill (diffpid, SIGPIPE); #endif if (tmpmade) unlink (tmpname); } static void exiterr () { cleanup (); untrapsig (0); checksigs (); exit (2); } static void fatal (msg) char const *msg; { fprintf (stderr, "%s: %s\n", program_name, msg); exiterr (); } static void perror_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 void ck_fclose (f) FILE *f; { if (fclose (f)) perror_fatal ("input/output error"); } static size_t ck_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 void ck_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 void ck_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 void lf_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_t lf_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 void lf_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 void lf_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 int lf_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; } } int main (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");