17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate */ 227c478bd9Sstevel@tonic-gate 237c478bd9Sstevel@tonic-gate /* 24*78eb75caSchin * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 257c478bd9Sstevel@tonic-gate * Use is subject to license terms. 267c478bd9Sstevel@tonic-gate */ 277c478bd9Sstevel@tonic-gate 28*78eb75caSchin /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 29*78eb75caSchin /* All Rights Reserved */ 30*78eb75caSchin 317c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 327c478bd9Sstevel@tonic-gate 337c478bd9Sstevel@tonic-gate #include <stdio.h> 347c478bd9Sstevel@tonic-gate #include <stdlib.h> 357c478bd9Sstevel@tonic-gate #include <unistd.h> 367c478bd9Sstevel@tonic-gate #include <ctype.h> 377c478bd9Sstevel@tonic-gate #include <locale.h> 387c478bd9Sstevel@tonic-gate #include <sys/types.h> 397c478bd9Sstevel@tonic-gate #include <sys/stat.h> 407c478bd9Sstevel@tonic-gate #include <limits.h> 417c478bd9Sstevel@tonic-gate #include <stdarg.h> 427c478bd9Sstevel@tonic-gate 437c478bd9Sstevel@tonic-gate #define C 3 447c478bd9Sstevel@tonic-gate #define RANGE 30 457c478bd9Sstevel@tonic-gate #define LEN 255 467c478bd9Sstevel@tonic-gate #define INF 16384 477c478bd9Sstevel@tonic-gate 487c478bd9Sstevel@tonic-gate char *text[2][RANGE]; 497c478bd9Sstevel@tonic-gate long lineno[2] = {1, 1}; /* no. of 1st stored line in each file */ 507c478bd9Sstevel@tonic-gate int ntext[2]; /* number of stored lines in each */ 517c478bd9Sstevel@tonic-gate long n0, n1; /* scan pointer in each */ 527c478bd9Sstevel@tonic-gate int bflag; 537c478bd9Sstevel@tonic-gate int debug = 0; 547c478bd9Sstevel@tonic-gate FILE *file[2]; 557c478bd9Sstevel@tonic-gate static int diffFound = 0; 567c478bd9Sstevel@tonic-gate 577c478bd9Sstevel@tonic-gate static char *getl(int f, long n); 587c478bd9Sstevel@tonic-gate static void clrl(int f, long n); 597c478bd9Sstevel@tonic-gate static void movstr(char *s, char *t); 607c478bd9Sstevel@tonic-gate static int easysynch(void); 617c478bd9Sstevel@tonic-gate static int output(int a, int b); 627c478bd9Sstevel@tonic-gate static void change(long a, int b, long c, int d, char *s); 637c478bd9Sstevel@tonic-gate static void range(long a, int b); 647c478bd9Sstevel@tonic-gate static int cmp(char *s, char *t); 657c478bd9Sstevel@tonic-gate static FILE *dopen(char *f1, char *f2); 667c478bd9Sstevel@tonic-gate static void progerr(char *s); 677c478bd9Sstevel@tonic-gate static void error(char *err, ...); 687c478bd9Sstevel@tonic-gate static int hardsynch(void); 697c478bd9Sstevel@tonic-gate 707c478bd9Sstevel@tonic-gate /* return pointer to line n of file f */ 717c478bd9Sstevel@tonic-gate static char * 727c478bd9Sstevel@tonic-gate getl(int f, long n) 737c478bd9Sstevel@tonic-gate { 747c478bd9Sstevel@tonic-gate char *t; 757c478bd9Sstevel@tonic-gate int delta, nt; 767c478bd9Sstevel@tonic-gate 777c478bd9Sstevel@tonic-gate again: 787c478bd9Sstevel@tonic-gate delta = n - lineno[f]; 797c478bd9Sstevel@tonic-gate nt = ntext[f]; 807c478bd9Sstevel@tonic-gate if (delta < 0) 817c478bd9Sstevel@tonic-gate progerr("1"); 827c478bd9Sstevel@tonic-gate if (delta < nt) 837c478bd9Sstevel@tonic-gate return (text[f][delta]); 847c478bd9Sstevel@tonic-gate if (delta > nt) 857c478bd9Sstevel@tonic-gate progerr("2"); 867c478bd9Sstevel@tonic-gate if (nt >= RANGE) 877c478bd9Sstevel@tonic-gate progerr("3"); 887c478bd9Sstevel@tonic-gate if (feof(file[f])) 897c478bd9Sstevel@tonic-gate return (NULL); 907c478bd9Sstevel@tonic-gate t = text[f][nt]; 917c478bd9Sstevel@tonic-gate if (t == 0) { 927c478bd9Sstevel@tonic-gate t = text[f][nt] = (char *)malloc(LEN+1); 937c478bd9Sstevel@tonic-gate if (t == NULL) 947c478bd9Sstevel@tonic-gate if (hardsynch()) 957c478bd9Sstevel@tonic-gate goto again; 967c478bd9Sstevel@tonic-gate else 977c478bd9Sstevel@tonic-gate progerr("5"); 987c478bd9Sstevel@tonic-gate } 997c478bd9Sstevel@tonic-gate t = fgets(t, LEN, file[f]); 1007c478bd9Sstevel@tonic-gate if (t != NULL) 1017c478bd9Sstevel@tonic-gate ntext[f]++; 1027c478bd9Sstevel@tonic-gate return (t); 1037c478bd9Sstevel@tonic-gate } 1047c478bd9Sstevel@tonic-gate 1057c478bd9Sstevel@tonic-gate /* remove thru line n of file f from storage */ 1067c478bd9Sstevel@tonic-gate static void 1077c478bd9Sstevel@tonic-gate clrl(int f, long n) 1087c478bd9Sstevel@tonic-gate { 1097c478bd9Sstevel@tonic-gate int i, j; 1107c478bd9Sstevel@tonic-gate 1117c478bd9Sstevel@tonic-gate j = n-lineno[f]+1; 1127c478bd9Sstevel@tonic-gate for (i = 0; i+j < ntext[f]; i++) 1137c478bd9Sstevel@tonic-gate movstr(text[f][i+j], text[f][i]); 1147c478bd9Sstevel@tonic-gate lineno[f] = n+1; 1157c478bd9Sstevel@tonic-gate ntext[f] -= j; 1167c478bd9Sstevel@tonic-gate } 1177c478bd9Sstevel@tonic-gate 1187c478bd9Sstevel@tonic-gate static void 1197c478bd9Sstevel@tonic-gate movstr(char *s, char *t) 1207c478bd9Sstevel@tonic-gate { 1217c478bd9Sstevel@tonic-gate while (*t++ = *s++) 1227c478bd9Sstevel@tonic-gate continue; 1237c478bd9Sstevel@tonic-gate } 1247c478bd9Sstevel@tonic-gate 1257c478bd9Sstevel@tonic-gate int 1267c478bd9Sstevel@tonic-gate main(int argc, char **argv) 1277c478bd9Sstevel@tonic-gate { 1287c478bd9Sstevel@tonic-gate char *s0, *s1; 1297c478bd9Sstevel@tonic-gate 1307c478bd9Sstevel@tonic-gate if ((argc > 1) && (*argv[1] == '-')) { 1317c478bd9Sstevel@tonic-gate argc--; 1327c478bd9Sstevel@tonic-gate argv++; 1337c478bd9Sstevel@tonic-gate while (*++argv[0]) 1347c478bd9Sstevel@tonic-gate if (*argv[0] == 'b') 1357c478bd9Sstevel@tonic-gate bflag++; 1367c478bd9Sstevel@tonic-gate } 1377c478bd9Sstevel@tonic-gate 1387c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 1397c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ 1407c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */ 1417c478bd9Sstevel@tonic-gate #endif 1427c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 1437c478bd9Sstevel@tonic-gate 1447c478bd9Sstevel@tonic-gate if (argc != 3) 1457c478bd9Sstevel@tonic-gate error(gettext("must have 2 file arguments")); 1467c478bd9Sstevel@tonic-gate file[0] = dopen(argv[1], argv[2]); 1477c478bd9Sstevel@tonic-gate file[1] = dopen(argv[2], argv[1]); 1487c478bd9Sstevel@tonic-gate for (;;) { 1497c478bd9Sstevel@tonic-gate s0 = getl(0, ++n0); 1507c478bd9Sstevel@tonic-gate s1 = getl(1, ++n1); 1517c478bd9Sstevel@tonic-gate if (s0 == NULL || s1 == NULL) 1527c478bd9Sstevel@tonic-gate break; 1537c478bd9Sstevel@tonic-gate if (cmp(s0, s1) != 0) { 1547c478bd9Sstevel@tonic-gate if (!easysynch() && !hardsynch()) 1557c478bd9Sstevel@tonic-gate progerr("5"); 1567c478bd9Sstevel@tonic-gate } else { 1577c478bd9Sstevel@tonic-gate clrl(0, n0); 1587c478bd9Sstevel@tonic-gate clrl(1, n1); 1597c478bd9Sstevel@tonic-gate } 1607c478bd9Sstevel@tonic-gate } 1617c478bd9Sstevel@tonic-gate /* diff is expected to return 1 if the files differ */ 1627c478bd9Sstevel@tonic-gate if (s0 == NULL && s1 == NULL) 1637c478bd9Sstevel@tonic-gate return (diffFound); 1647c478bd9Sstevel@tonic-gate if (s0 == NULL) { 1657c478bd9Sstevel@tonic-gate (void) output(-1, INF); 1667c478bd9Sstevel@tonic-gate return (1); 1677c478bd9Sstevel@tonic-gate } 1687c478bd9Sstevel@tonic-gate if (s1 == NULL) { 1697c478bd9Sstevel@tonic-gate (void) output(INF, -1); 1707c478bd9Sstevel@tonic-gate return (1); 1717c478bd9Sstevel@tonic-gate } 1727c478bd9Sstevel@tonic-gate /* NOTREACHED */ 173*78eb75caSchin return (0); 1747c478bd9Sstevel@tonic-gate } 1757c478bd9Sstevel@tonic-gate 1767c478bd9Sstevel@tonic-gate /* synch on C successive matches */ 1777c478bd9Sstevel@tonic-gate static int 1787c478bd9Sstevel@tonic-gate easysynch() 1797c478bd9Sstevel@tonic-gate { 1807c478bd9Sstevel@tonic-gate int i, j; 1817c478bd9Sstevel@tonic-gate int k, m; 1827c478bd9Sstevel@tonic-gate char *s0, *s1; 1837c478bd9Sstevel@tonic-gate 1847c478bd9Sstevel@tonic-gate for (i = j = 1; i < RANGE && j < RANGE; i++, j++) { 1857c478bd9Sstevel@tonic-gate s0 = getl(0, n0+i); 1867c478bd9Sstevel@tonic-gate if (s0 == NULL) 1877c478bd9Sstevel@tonic-gate return (output(INF, INF)); 1887c478bd9Sstevel@tonic-gate for (k = C-1; k < j; k++) { 1897c478bd9Sstevel@tonic-gate for (m = 0; m < C; m++) 1907c478bd9Sstevel@tonic-gate if (cmp(getl(0, n0+i-m), 1917c478bd9Sstevel@tonic-gate getl(1, n1+k-m)) != 0) 1927c478bd9Sstevel@tonic-gate goto cont1; 1937c478bd9Sstevel@tonic-gate return (output(i-C, k-C)); 1947c478bd9Sstevel@tonic-gate cont1: 1957c478bd9Sstevel@tonic-gate ; 1967c478bd9Sstevel@tonic-gate } 1977c478bd9Sstevel@tonic-gate s1 = getl(1, n1+j); 1987c478bd9Sstevel@tonic-gate if (s1 == NULL) 1997c478bd9Sstevel@tonic-gate return (output(INF, INF)); 2007c478bd9Sstevel@tonic-gate for (k = C-1; k <= i; k++) { 2017c478bd9Sstevel@tonic-gate for (m = 0; m < C; m++) 2027c478bd9Sstevel@tonic-gate if (cmp(getl(0, n0+k-m), 2037c478bd9Sstevel@tonic-gate getl(1, n1+j-m)) != 0) 2047c478bd9Sstevel@tonic-gate goto cont2; 2057c478bd9Sstevel@tonic-gate return (output(k-C, j-C)); 2067c478bd9Sstevel@tonic-gate cont2: 2077c478bd9Sstevel@tonic-gate ; 2087c478bd9Sstevel@tonic-gate } 2097c478bd9Sstevel@tonic-gate } 2107c478bd9Sstevel@tonic-gate return (0); 2117c478bd9Sstevel@tonic-gate } 2127c478bd9Sstevel@tonic-gate 2137c478bd9Sstevel@tonic-gate static int 2147c478bd9Sstevel@tonic-gate output(int a, int b) 2157c478bd9Sstevel@tonic-gate { 2167c478bd9Sstevel@tonic-gate int i; 2177c478bd9Sstevel@tonic-gate char *s; 2187c478bd9Sstevel@tonic-gate 2197c478bd9Sstevel@tonic-gate if (a < 0) 2207c478bd9Sstevel@tonic-gate change(n0-1, 0, n1, b, "a"); 2217c478bd9Sstevel@tonic-gate else if (b < 0) 2227c478bd9Sstevel@tonic-gate change(n0, a, n1-1, 0, "d"); 2237c478bd9Sstevel@tonic-gate else 2247c478bd9Sstevel@tonic-gate change(n0, a, n1, b, "c"); 2257c478bd9Sstevel@tonic-gate for (i = 0; i <= a; i++) { 2267c478bd9Sstevel@tonic-gate s = getl(0, n0+i); 2277c478bd9Sstevel@tonic-gate if (s == NULL) 2287c478bd9Sstevel@tonic-gate break; 2297c478bd9Sstevel@tonic-gate (void) printf("< %s", s); 2307c478bd9Sstevel@tonic-gate clrl(0, n0+i); 2317c478bd9Sstevel@tonic-gate } 2327c478bd9Sstevel@tonic-gate n0 += i-1; 2337c478bd9Sstevel@tonic-gate if (a >= 0 && b >= 0) 2347c478bd9Sstevel@tonic-gate (void) printf("---\n"); 2357c478bd9Sstevel@tonic-gate for (i = 0; i <= b; i++) { 2367c478bd9Sstevel@tonic-gate s = getl(1, n1+i); 2377c478bd9Sstevel@tonic-gate if (s == NULL) 2387c478bd9Sstevel@tonic-gate break; 2397c478bd9Sstevel@tonic-gate (void) printf("> %s", s); 2407c478bd9Sstevel@tonic-gate clrl(1, n1+i); 2417c478bd9Sstevel@tonic-gate } 2427c478bd9Sstevel@tonic-gate diffFound = 1; 2437c478bd9Sstevel@tonic-gate n1 += i-1; 2447c478bd9Sstevel@tonic-gate return (1); 2457c478bd9Sstevel@tonic-gate } 2467c478bd9Sstevel@tonic-gate 2477c478bd9Sstevel@tonic-gate static void 2487c478bd9Sstevel@tonic-gate change(long a, int b, long c, int d, char *s) 2497c478bd9Sstevel@tonic-gate { 2507c478bd9Sstevel@tonic-gate range(a, b); 2517c478bd9Sstevel@tonic-gate (void) printf("%s", s); 2527c478bd9Sstevel@tonic-gate range(c, d); 2537c478bd9Sstevel@tonic-gate (void) printf("\n"); 2547c478bd9Sstevel@tonic-gate } 2557c478bd9Sstevel@tonic-gate 2567c478bd9Sstevel@tonic-gate static void 2577c478bd9Sstevel@tonic-gate range(long a, int b) 2587c478bd9Sstevel@tonic-gate { 2597c478bd9Sstevel@tonic-gate if (b == INF) 2607c478bd9Sstevel@tonic-gate (void) printf("%ld,$", a); 2617c478bd9Sstevel@tonic-gate else if (b == 0) 2627c478bd9Sstevel@tonic-gate (void) printf("%ld", a); 2637c478bd9Sstevel@tonic-gate else 2647c478bd9Sstevel@tonic-gate (void) printf("%ld,%ld", a, a+b); 2657c478bd9Sstevel@tonic-gate } 2667c478bd9Sstevel@tonic-gate 2677c478bd9Sstevel@tonic-gate static int 2687c478bd9Sstevel@tonic-gate cmp(char *s, char *t) 2697c478bd9Sstevel@tonic-gate { 2707c478bd9Sstevel@tonic-gate if (debug) 2717c478bd9Sstevel@tonic-gate (void) printf("%s:%s\n", s, t); 2727c478bd9Sstevel@tonic-gate for (;;) { 2737c478bd9Sstevel@tonic-gate if (bflag && isspace(*s) && isspace(*t)) { 2747c478bd9Sstevel@tonic-gate while (isspace(*++s)) 2757c478bd9Sstevel@tonic-gate ; 2767c478bd9Sstevel@tonic-gate while (isspace(*++t)) 2777c478bd9Sstevel@tonic-gate ; 2787c478bd9Sstevel@tonic-gate } 2797c478bd9Sstevel@tonic-gate if (*s != *t || *s == 0) 2807c478bd9Sstevel@tonic-gate break; 2817c478bd9Sstevel@tonic-gate s++; 2827c478bd9Sstevel@tonic-gate t++; 2837c478bd9Sstevel@tonic-gate } 2847c478bd9Sstevel@tonic-gate return (*s-*t); 2857c478bd9Sstevel@tonic-gate } 2867c478bd9Sstevel@tonic-gate 2877c478bd9Sstevel@tonic-gate static FILE * 2887c478bd9Sstevel@tonic-gate dopen(char *f1, char *f2) 2897c478bd9Sstevel@tonic-gate { 2907c478bd9Sstevel@tonic-gate FILE *f; 2917c478bd9Sstevel@tonic-gate char b[PATH_MAX], *bptr, *eptr; 2927c478bd9Sstevel@tonic-gate struct stat statbuf; 2937c478bd9Sstevel@tonic-gate 2947c478bd9Sstevel@tonic-gate if (cmp(f1, "-") == 0) { 2957c478bd9Sstevel@tonic-gate if (cmp(f2, "-") == 0) 2967c478bd9Sstevel@tonic-gate error(gettext("can't do - -")); 2977c478bd9Sstevel@tonic-gate else { 2987c478bd9Sstevel@tonic-gate if (fstat(fileno(stdin), &statbuf) == -1) 2997c478bd9Sstevel@tonic-gate error(gettext("can't access stdin")); 3007c478bd9Sstevel@tonic-gate else 3017c478bd9Sstevel@tonic-gate return (stdin); 3027c478bd9Sstevel@tonic-gate } 3037c478bd9Sstevel@tonic-gate } 3047c478bd9Sstevel@tonic-gate if (stat(f1, &statbuf) == -1) 3057c478bd9Sstevel@tonic-gate error(gettext("can't access %s"), f1); 3067c478bd9Sstevel@tonic-gate if ((statbuf.st_mode & S_IFMT) == S_IFDIR) { 3077c478bd9Sstevel@tonic-gate for (bptr = b; *bptr = *f1++; bptr++) 3087c478bd9Sstevel@tonic-gate ; 3097c478bd9Sstevel@tonic-gate *bptr++ = '/'; 3107c478bd9Sstevel@tonic-gate for (eptr = f2; *eptr; eptr++) 3117c478bd9Sstevel@tonic-gate if (*eptr == '/' && eptr[1] != 0 && eptr[1] != '/') 3127c478bd9Sstevel@tonic-gate f2 = eptr+1; 3137c478bd9Sstevel@tonic-gate while (*bptr++ = *f2++) 3147c478bd9Sstevel@tonic-gate ; 3157c478bd9Sstevel@tonic-gate f1 = b; 3167c478bd9Sstevel@tonic-gate } 3177c478bd9Sstevel@tonic-gate f = fopen(f1, "r"); 3187c478bd9Sstevel@tonic-gate if (f == NULL) 3197c478bd9Sstevel@tonic-gate error(gettext("can't open %s"), f1); 3207c478bd9Sstevel@tonic-gate return (f); 3217c478bd9Sstevel@tonic-gate } 3227c478bd9Sstevel@tonic-gate 3237c478bd9Sstevel@tonic-gate 3247c478bd9Sstevel@tonic-gate static void 3257c478bd9Sstevel@tonic-gate progerr(char *s) 3267c478bd9Sstevel@tonic-gate { 3277c478bd9Sstevel@tonic-gate error(gettext("program error %s"), s); 3287c478bd9Sstevel@tonic-gate } 3297c478bd9Sstevel@tonic-gate 3307c478bd9Sstevel@tonic-gate static void 3317c478bd9Sstevel@tonic-gate error(char *err, ...) 3327c478bd9Sstevel@tonic-gate { 3337c478bd9Sstevel@tonic-gate va_list ap; 3347c478bd9Sstevel@tonic-gate 3357c478bd9Sstevel@tonic-gate va_start(ap, err); 3367c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "diffh: "); 3377c478bd9Sstevel@tonic-gate (void) vfprintf(stderr, err, ap); 3387c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "\n"); 3397c478bd9Sstevel@tonic-gate va_end(ap); 3407c478bd9Sstevel@tonic-gate exit(2); 3417c478bd9Sstevel@tonic-gate } 3427c478bd9Sstevel@tonic-gate 3437c478bd9Sstevel@tonic-gate /* stub for resychronization beyond limits of text buf */ 3447c478bd9Sstevel@tonic-gate static int 3457c478bd9Sstevel@tonic-gate hardsynch() 3467c478bd9Sstevel@tonic-gate { 3477c478bd9Sstevel@tonic-gate change(n0, INF, n1, INF, "c"); 3487c478bd9Sstevel@tonic-gate (void) printf(gettext("---change record omitted\n")); 3497c478bd9Sstevel@tonic-gate error(gettext("can't resynchronize")); 3507c478bd9Sstevel@tonic-gate return (0); 3517c478bd9Sstevel@tonic-gate } 352