diff options
author | stevel@tonic-gate <none@none> | 2005-06-14 00:00:00 -0700 |
---|---|---|
committer | stevel@tonic-gate <none@none> | 2005-06-14 00:00:00 -0700 |
commit | 7c478bd95313f5f23a4c958a745db2134aa03244 (patch) | |
tree | c871e58545497667cbb4b0a4f2daf204743e1fe7 /usr/src/cmd/diff/diffh.c | |
download | illumos-gate-7c478bd95313f5f23a4c958a745db2134aa03244.tar.gz |
OpenSolaris Launch
Diffstat (limited to 'usr/src/cmd/diff/diffh.c')
-rw-r--r-- | usr/src/cmd/diff/diffh.c | 350 |
1 files changed, 350 insertions, 0 deletions
diff --git a/usr/src/cmd/diff/diffh.c b/usr/src/cmd/diff/diffh.c new file mode 100644 index 0000000000..6d64cb89ce --- /dev/null +++ b/usr/src/cmd/diff/diffh.c @@ -0,0 +1,350 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ +/* All Rights Reserved */ + + +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <ctype.h> +#include <locale.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <limits.h> +#include <stdarg.h> + +#define C 3 +#define RANGE 30 +#define LEN 255 +#define INF 16384 + +char *text[2][RANGE]; +long lineno[2] = {1, 1}; /* no. of 1st stored line in each file */ +int ntext[2]; /* number of stored lines in each */ +long n0, n1; /* scan pointer in each */ +int bflag; +int debug = 0; +FILE *file[2]; +static int diffFound = 0; + +static char *getl(int f, long n); +static void clrl(int f, long n); +static void movstr(char *s, char *t); +static int easysynch(void); +static int output(int a, int b); +static void change(long a, int b, long c, int d, char *s); +static void range(long a, int b); +static int cmp(char *s, char *t); +static FILE *dopen(char *f1, char *f2); +static void progerr(char *s); +static void error(char *err, ...); +static int hardsynch(void); + + /* return pointer to line n of file f */ +static char * +getl(int f, long n) +{ + char *t; + int delta, nt; + +again: + delta = n - lineno[f]; + nt = ntext[f]; + if (delta < 0) + progerr("1"); + if (delta < nt) + return (text[f][delta]); + if (delta > nt) + progerr("2"); + if (nt >= RANGE) + progerr("3"); + if (feof(file[f])) + return (NULL); + t = text[f][nt]; + if (t == 0) { + t = text[f][nt] = (char *)malloc(LEN+1); + if (t == NULL) + if (hardsynch()) + goto again; + else + progerr("5"); + } + t = fgets(t, LEN, file[f]); + if (t != NULL) + ntext[f]++; + return (t); +} + + /* remove thru line n of file f from storage */ +static void +clrl(int f, long n) +{ + int i, j; + + j = n-lineno[f]+1; + for (i = 0; i+j < ntext[f]; i++) + movstr(text[f][i+j], text[f][i]); + lineno[f] = n+1; + ntext[f] -= j; +} + +static void +movstr(char *s, char *t) +{ + while (*t++ = *s++) + continue; +} + +int +main(int argc, char **argv) +{ + char *s0, *s1; + + if ((argc > 1) && (*argv[1] == '-')) { + argc--; + argv++; + while (*++argv[0]) + if (*argv[0] == 'b') + bflag++; + } + + (void) setlocale(LC_ALL, ""); +#if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ +#define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */ +#endif + (void) textdomain(TEXT_DOMAIN); + + if (argc != 3) + error(gettext("must have 2 file arguments")); + file[0] = dopen(argv[1], argv[2]); + file[1] = dopen(argv[2], argv[1]); + for (;;) { + s0 = getl(0, ++n0); + s1 = getl(1, ++n1); + if (s0 == NULL || s1 == NULL) + break; + if (cmp(s0, s1) != 0) { + if (!easysynch() && !hardsynch()) + progerr("5"); + } else { + clrl(0, n0); + clrl(1, n1); + } + } + /* diff is expected to return 1 if the files differ */ + if (s0 == NULL && s1 == NULL) + return (diffFound); + if (s0 == NULL) { + (void) output(-1, INF); + return (1); + } + if (s1 == NULL) { + (void) output(INF, -1); + return (1); + } + /* NOTREACHED */ +} + + /* synch on C successive matches */ +static int +easysynch() +{ + int i, j; + int k, m; + char *s0, *s1; + + for (i = j = 1; i < RANGE && j < RANGE; i++, j++) { + s0 = getl(0, n0+i); + if (s0 == NULL) + return (output(INF, INF)); + for (k = C-1; k < j; k++) { + for (m = 0; m < C; m++) + if (cmp(getl(0, n0+i-m), + getl(1, n1+k-m)) != 0) + goto cont1; + return (output(i-C, k-C)); +cont1: + ; + } + s1 = getl(1, n1+j); + if (s1 == NULL) + return (output(INF, INF)); + for (k = C-1; k <= i; k++) { + for (m = 0; m < C; m++) + if (cmp(getl(0, n0+k-m), + getl(1, n1+j-m)) != 0) + goto cont2; + return (output(k-C, j-C)); +cont2: + ; + } + } + return (0); +} + +static int +output(int a, int b) +{ + int i; + char *s; + + if (a < 0) + change(n0-1, 0, n1, b, "a"); + else if (b < 0) + change(n0, a, n1-1, 0, "d"); + else + change(n0, a, n1, b, "c"); + for (i = 0; i <= a; i++) { + s = getl(0, n0+i); + if (s == NULL) + break; + (void) printf("< %s", s); + clrl(0, n0+i); + } + n0 += i-1; + if (a >= 0 && b >= 0) + (void) printf("---\n"); + for (i = 0; i <= b; i++) { + s = getl(1, n1+i); + if (s == NULL) + break; + (void) printf("> %s", s); + clrl(1, n1+i); + } + diffFound = 1; + n1 += i-1; + return (1); +} + +static void +change(long a, int b, long c, int d, char *s) +{ + range(a, b); + (void) printf("%s", s); + range(c, d); + (void) printf("\n"); +} + +static void +range(long a, int b) +{ + if (b == INF) + (void) printf("%ld,$", a); + else if (b == 0) + (void) printf("%ld", a); + else + (void) printf("%ld,%ld", a, a+b); +} + +static int +cmp(char *s, char *t) +{ + if (debug) + (void) printf("%s:%s\n", s, t); + for (;;) { + if (bflag && isspace(*s) && isspace(*t)) { + while (isspace(*++s)) + ; + while (isspace(*++t)) + ; + } + if (*s != *t || *s == 0) + break; + s++; + t++; + } + return (*s-*t); +} + +static FILE * +dopen(char *f1, char *f2) +{ + FILE *f; + char b[PATH_MAX], *bptr, *eptr; + struct stat statbuf; + + if (cmp(f1, "-") == 0) { + if (cmp(f2, "-") == 0) + error(gettext("can't do - -")); + else { + if (fstat(fileno(stdin), &statbuf) == -1) + error(gettext("can't access stdin")); + else + return (stdin); + } + } + if (stat(f1, &statbuf) == -1) + error(gettext("can't access %s"), f1); + if ((statbuf.st_mode & S_IFMT) == S_IFDIR) { + for (bptr = b; *bptr = *f1++; bptr++) + ; + *bptr++ = '/'; + for (eptr = f2; *eptr; eptr++) + if (*eptr == '/' && eptr[1] != 0 && eptr[1] != '/') + f2 = eptr+1; + while (*bptr++ = *f2++) + ; + f1 = b; + } + f = fopen(f1, "r"); + if (f == NULL) + error(gettext("can't open %s"), f1); + return (f); +} + + +static void +progerr(char *s) +{ + error(gettext("program error %s"), s); +} + +static void +error(char *err, ...) +{ + va_list ap; + + va_start(ap, err); + (void) fprintf(stderr, "diffh: "); + (void) vfprintf(stderr, err, ap); + (void) fprintf(stderr, "\n"); + va_end(ap); + exit(2); +} + + /* stub for resychronization beyond limits of text buf */ +static int +hardsynch() +{ + change(n0, INF, n1, INF, "c"); + (void) printf(gettext("---change record omitted\n")); + error(gettext("can't resynchronize")); + return (0); +} |