1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 29*7c478bd9Sstevel@tonic-gate 30*7c478bd9Sstevel@tonic-gate /* 31*7c478bd9Sstevel@tonic-gate * University Copyright- Copyright (c) 1982, 1986, 1988 32*7c478bd9Sstevel@tonic-gate * The Regents of the University of California 33*7c478bd9Sstevel@tonic-gate * All Rights Reserved 34*7c478bd9Sstevel@tonic-gate * 35*7c478bd9Sstevel@tonic-gate * University Acknowledgment- Portions of this document are derived from 36*7c478bd9Sstevel@tonic-gate * software developed by the University of California, Berkeley, and its 37*7c478bd9Sstevel@tonic-gate * contributors. 38*7c478bd9Sstevel@tonic-gate */ 39*7c478bd9Sstevel@tonic-gate 40*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 41*7c478bd9Sstevel@tonic-gate 42*7c478bd9Sstevel@tonic-gate /* 43*7c478bd9Sstevel@tonic-gate * diff - differential file comparison 44*7c478bd9Sstevel@tonic-gate * 45*7c478bd9Sstevel@tonic-gate * Uses an algorithm which finds 46*7c478bd9Sstevel@tonic-gate * a pair of longest identical subsequences in the two 47*7c478bd9Sstevel@tonic-gate * files. 48*7c478bd9Sstevel@tonic-gate * 49*7c478bd9Sstevel@tonic-gate * The major goal is to generate the match vector J. 50*7c478bd9Sstevel@tonic-gate * J[i] is the index of the line in file1 corresponding 51*7c478bd9Sstevel@tonic-gate * to line i file0. J[i] = 0 if there is no 52*7c478bd9Sstevel@tonic-gate * such line in file1. 53*7c478bd9Sstevel@tonic-gate * 54*7c478bd9Sstevel@tonic-gate * Lines are hashed so as to work in core. All potential 55*7c478bd9Sstevel@tonic-gate * matches are located by sorting the lines of each file 56*7c478bd9Sstevel@tonic-gate * on the hash (called value). In particular, this 57*7c478bd9Sstevel@tonic-gate * collects the equivalence classes in file1 together. 58*7c478bd9Sstevel@tonic-gate * Subroutine equiv replaces the value of each line in 59*7c478bd9Sstevel@tonic-gate * file0 by the index of the first element of its 60*7c478bd9Sstevel@tonic-gate * matching equivalence in (the reordered) file1. 61*7c478bd9Sstevel@tonic-gate * To save space equiv squeezes file1 into a single 62*7c478bd9Sstevel@tonic-gate * array member in which the equivalence classes 63*7c478bd9Sstevel@tonic-gate * are simply concatenated, except that their first 64*7c478bd9Sstevel@tonic-gate * members are flagged by changing sign. 65*7c478bd9Sstevel@tonic-gate * 66*7c478bd9Sstevel@tonic-gate * Next the indices that point into member are unsorted into 67*7c478bd9Sstevel@tonic-gate * array class according to the original order of file0. 68*7c478bd9Sstevel@tonic-gate * 69*7c478bd9Sstevel@tonic-gate * The cleverness lies in routine stone. This marches 70*7c478bd9Sstevel@tonic-gate * through the lines of file0, developing a vector klist 71*7c478bd9Sstevel@tonic-gate * of "k-candidates". At step i a k-candidate is a matched 72*7c478bd9Sstevel@tonic-gate * pair of lines x,y (x in file0 y in file1) such that 73*7c478bd9Sstevel@tonic-gate * there is a common subsequence of lenght k 74*7c478bd9Sstevel@tonic-gate * between the first i lines of file0 and the first y 75*7c478bd9Sstevel@tonic-gate * lines of file1, but there is no such subsequence for 76*7c478bd9Sstevel@tonic-gate * any smaller y. x is the earliest possible mate to y 77*7c478bd9Sstevel@tonic-gate * that occurs in such a subsequence. 78*7c478bd9Sstevel@tonic-gate * 79*7c478bd9Sstevel@tonic-gate * Whenever any of the members of the equivalence class of 80*7c478bd9Sstevel@tonic-gate * lines in file1 matable to a line in file0 has serial number 81*7c478bd9Sstevel@tonic-gate * less than the y of some k-candidate, that k-candidate 82*7c478bd9Sstevel@tonic-gate * with the smallest such y is replaced. The new 83*7c478bd9Sstevel@tonic-gate * k-candidate is chained (via pred) to the current 84*7c478bd9Sstevel@tonic-gate * k-1 candidate so that the actual subsequence can 85*7c478bd9Sstevel@tonic-gate * be recovered. When a member has serial number greater 86*7c478bd9Sstevel@tonic-gate * that the y of all k-candidates, the klist is extended. 87*7c478bd9Sstevel@tonic-gate * At the end, the longest subsequence is pulled out 88*7c478bd9Sstevel@tonic-gate * and placed in the array J by unravel. 89*7c478bd9Sstevel@tonic-gate * 90*7c478bd9Sstevel@tonic-gate * With J in hand, the matches there recorded are 91*7c478bd9Sstevel@tonic-gate * checked against reality to assure that no spurious 92*7c478bd9Sstevel@tonic-gate * matches have crept in due to hashing. If they have, 93*7c478bd9Sstevel@tonic-gate * they are broken, and "jackpot " is recorded--a harmless 94*7c478bd9Sstevel@tonic-gate * matter except that a true match for a spuriously 95*7c478bd9Sstevel@tonic-gate * mated line may now be unnecessarily reported as a change. 96*7c478bd9Sstevel@tonic-gate * 97*7c478bd9Sstevel@tonic-gate * Much of the complexity of the program comes simply 98*7c478bd9Sstevel@tonic-gate * from trying to minimize core utilization and 99*7c478bd9Sstevel@tonic-gate * maximize the range of doable problems by dynamically 100*7c478bd9Sstevel@tonic-gate * allocating what is needed and reusing what is not. 101*7c478bd9Sstevel@tonic-gate * The core requirements for problems larger than somewhat 102*7c478bd9Sstevel@tonic-gate * are (in words) 2*length(file0) + length(file1) + 103*7c478bd9Sstevel@tonic-gate * 3*(number of k-candidates installed), typically about 104*7c478bd9Sstevel@tonic-gate * 6n words for files of length n. 105*7c478bd9Sstevel@tonic-gate */ 106*7c478bd9Sstevel@tonic-gate #include <stdio.h> 107*7c478bd9Sstevel@tonic-gate #include <wchar.h> 108*7c478bd9Sstevel@tonic-gate #include <ctype.h> 109*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 110*7c478bd9Sstevel@tonic-gate #include <limits.h> 111*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 112*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 113*7c478bd9Sstevel@tonic-gate #include <sys/wait.h> 114*7c478bd9Sstevel@tonic-gate #include <unistd.h> 115*7c478bd9Sstevel@tonic-gate #include <signal.h> 116*7c478bd9Sstevel@tonic-gate #include <fcntl.h> 117*7c478bd9Sstevel@tonic-gate #include <dirent.h> 118*7c478bd9Sstevel@tonic-gate #include <locale.h> 119*7c478bd9Sstevel@tonic-gate #include <stdarg.h> 120*7c478bd9Sstevel@tonic-gate #include <errno.h> 121*7c478bd9Sstevel@tonic-gate #include <string.h> 122*7c478bd9Sstevel@tonic-gate #include "diff.h" 123*7c478bd9Sstevel@tonic-gate 124*7c478bd9Sstevel@tonic-gate #define CHRTRAN(x) (iflag ? (iswupper(x) ? towlower(x) : (x)) : (x)) 125*7c478bd9Sstevel@tonic-gate #define NCCHRTRAN(x) (iswupper(x) ? towlower(x) : (x)) 126*7c478bd9Sstevel@tonic-gate #define max(a, b) ((a) < (b) ? (b) : (a)) 127*7c478bd9Sstevel@tonic-gate #define min(a, b) ((a) > (b) ? (b) : (a)) 128*7c478bd9Sstevel@tonic-gate 129*7c478bd9Sstevel@tonic-gate int pref, suff; /* length of prefix and suffix */ 130*7c478bd9Sstevel@tonic-gate int *class; /* will be overlaid on file[0] */ 131*7c478bd9Sstevel@tonic-gate int *member; /* will be overlaid on file[1] */ 132*7c478bd9Sstevel@tonic-gate int *klist; /* will be overlaid on file[0] after class */ 133*7c478bd9Sstevel@tonic-gate struct cand *clist; /* merely a free storage pot for candidates */ 134*7c478bd9Sstevel@tonic-gate int clen = 0; 135*7c478bd9Sstevel@tonic-gate int *J; /* will be overlaid on class */ 136*7c478bd9Sstevel@tonic-gate long *ixold; /* will be overlaid on klist */ 137*7c478bd9Sstevel@tonic-gate long *ixnew; /* will be overlaid on file[1] */ 138*7c478bd9Sstevel@tonic-gate 139*7c478bd9Sstevel@tonic-gate static int mbcurmax; 140*7c478bd9Sstevel@tonic-gate 141*7c478bd9Sstevel@tonic-gate static void error(const char *); 142*7c478bd9Sstevel@tonic-gate static void unravel(int); 143*7c478bd9Sstevel@tonic-gate static void check(void); 144*7c478bd9Sstevel@tonic-gate static void output(void); 145*7c478bd9Sstevel@tonic-gate static void change(int, int, int, int); 146*7c478bd9Sstevel@tonic-gate static void range(int, int, char *); 147*7c478bd9Sstevel@tonic-gate static void fetch(long *, int, int, int, char *, int); 148*7c478bd9Sstevel@tonic-gate static void dump_context_vec(void); 149*7c478bd9Sstevel@tonic-gate static void diffdir(char **); 150*7c478bd9Sstevel@tonic-gate static void setfile(char **, char **, char *); 151*7c478bd9Sstevel@tonic-gate static void scanpr(struct dir *, int, char *, char *, 152*7c478bd9Sstevel@tonic-gate char *, char *, char *); 153*7c478bd9Sstevel@tonic-gate static void only(struct dir *, int); 154*7c478bd9Sstevel@tonic-gate static void sort(struct line *, int); 155*7c478bd9Sstevel@tonic-gate static void unsort(struct line *, int, int *); 156*7c478bd9Sstevel@tonic-gate static void filename(char **, char **, struct stat *, char **); 157*7c478bd9Sstevel@tonic-gate static void prepare(int, char *); 158*7c478bd9Sstevel@tonic-gate static void prune(void); 159*7c478bd9Sstevel@tonic-gate static void equiv(struct line *, int, struct line *, int, int *); 160*7c478bd9Sstevel@tonic-gate static void done(void); 161*7c478bd9Sstevel@tonic-gate static void noroom(void); 162*7c478bd9Sstevel@tonic-gate static void usage(void); 163*7c478bd9Sstevel@tonic-gate static void initbuf(FILE *, int, long); 164*7c478bd9Sstevel@tonic-gate static void resetbuf(int); 165*7c478bd9Sstevel@tonic-gate 166*7c478bd9Sstevel@tonic-gate static int stone(int *, int, int *, int *); 167*7c478bd9Sstevel@tonic-gate static int newcand(int, int, int); 168*7c478bd9Sstevel@tonic-gate static int search(int *, int, int); 169*7c478bd9Sstevel@tonic-gate static int skipline(int); 170*7c478bd9Sstevel@tonic-gate static int readhash(FILE *, int, char *); 171*7c478bd9Sstevel@tonic-gate static int entcmp(struct dir *, struct dir *); 172*7c478bd9Sstevel@tonic-gate static int compare(struct dir *); 173*7c478bd9Sstevel@tonic-gate static int calldiff(char *); 174*7c478bd9Sstevel@tonic-gate static int binary(int); 175*7c478bd9Sstevel@tonic-gate static int filebinary(FILE *); 176*7c478bd9Sstevel@tonic-gate static int isbinary(char *, int); 177*7c478bd9Sstevel@tonic-gate static int useless(char *); 178*7c478bd9Sstevel@tonic-gate static char *copytemp(char *); 179*7c478bd9Sstevel@tonic-gate static char *pfiletype(mode_t); 180*7c478bd9Sstevel@tonic-gate static struct dir *setupdir(char *); 181*7c478bd9Sstevel@tonic-gate static wint_t getbufwchar(int, int *); 182*7c478bd9Sstevel@tonic-gate static wint_t wcput(wint_t); 183*7c478bd9Sstevel@tonic-gate static long ftellbuf(int); 184*7c478bd9Sstevel@tonic-gate 185*7c478bd9Sstevel@tonic-gate 186*7c478bd9Sstevel@tonic-gate /* 187*7c478bd9Sstevel@tonic-gate * error message string constants 188*7c478bd9Sstevel@tonic-gate */ 189*7c478bd9Sstevel@tonic-gate #define BAD_MB_ERR "invalid multibyte character encountered" 190*7c478bd9Sstevel@tonic-gate #define NO_PROCS_ERR "no more processes" 191*7c478bd9Sstevel@tonic-gate #define NO_MEM_ERR "out of memory" 192*7c478bd9Sstevel@tonic-gate 193*7c478bd9Sstevel@tonic-gate static void * 194*7c478bd9Sstevel@tonic-gate talloc(size_t n) 195*7c478bd9Sstevel@tonic-gate { 196*7c478bd9Sstevel@tonic-gate void *p; 197*7c478bd9Sstevel@tonic-gate p = malloc(n); 198*7c478bd9Sstevel@tonic-gate if (p == NULL) 199*7c478bd9Sstevel@tonic-gate noroom(); 200*7c478bd9Sstevel@tonic-gate return (p); 201*7c478bd9Sstevel@tonic-gate } 202*7c478bd9Sstevel@tonic-gate 203*7c478bd9Sstevel@tonic-gate static void * 204*7c478bd9Sstevel@tonic-gate ralloc(void *p, size_t n) /* compacting reallocation */ 205*7c478bd9Sstevel@tonic-gate { 206*7c478bd9Sstevel@tonic-gate void *q; 207*7c478bd9Sstevel@tonic-gate #if 0 208*7c478bd9Sstevel@tonic-gate free(p); 209*7c478bd9Sstevel@tonic-gate #endif 210*7c478bd9Sstevel@tonic-gate q = realloc(p, n); 211*7c478bd9Sstevel@tonic-gate if (q == NULL) 212*7c478bd9Sstevel@tonic-gate noroom(); 213*7c478bd9Sstevel@tonic-gate return (q); 214*7c478bd9Sstevel@tonic-gate } 215*7c478bd9Sstevel@tonic-gate 216*7c478bd9Sstevel@tonic-gate 217*7c478bd9Sstevel@tonic-gate void 218*7c478bd9Sstevel@tonic-gate main(int argc, char **argv) 219*7c478bd9Sstevel@tonic-gate { 220*7c478bd9Sstevel@tonic-gate int k; 221*7c478bd9Sstevel@tonic-gate char *argp; 222*7c478bd9Sstevel@tonic-gate int flag; /* option flag read by getopt() */ 223*7c478bd9Sstevel@tonic-gate int i, j; 224*7c478bd9Sstevel@tonic-gate char buf1[BUFSIZ], buf2[BUFSIZ]; 225*7c478bd9Sstevel@tonic-gate 226*7c478bd9Sstevel@tonic-gate 227*7c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 228*7c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ 229*7c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */ 230*7c478bd9Sstevel@tonic-gate #endif 231*7c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 232*7c478bd9Sstevel@tonic-gate 233*7c478bd9Sstevel@tonic-gate mbcurmax = MB_CUR_MAX; 234*7c478bd9Sstevel@tonic-gate 235*7c478bd9Sstevel@tonic-gate diffargv = argv; 236*7c478bd9Sstevel@tonic-gate whichtemp = 0; 237*7c478bd9Sstevel@tonic-gate while ((flag = getopt(argc, argv, "bitwcuefhnlrsC:D:S:U:")) != EOF) { 238*7c478bd9Sstevel@tonic-gate switch (flag) { 239*7c478bd9Sstevel@tonic-gate case 'D': 240*7c478bd9Sstevel@tonic-gate opt = D_IFDEF; 241*7c478bd9Sstevel@tonic-gate wantelses = 1; 242*7c478bd9Sstevel@tonic-gate ifdef1 = ""; 243*7c478bd9Sstevel@tonic-gate ifdef2 = optarg; 244*7c478bd9Sstevel@tonic-gate break; 245*7c478bd9Sstevel@tonic-gate 246*7c478bd9Sstevel@tonic-gate case 'b': 247*7c478bd9Sstevel@tonic-gate bflag = 1; 248*7c478bd9Sstevel@tonic-gate break; 249*7c478bd9Sstevel@tonic-gate 250*7c478bd9Sstevel@tonic-gate case 'C': 251*7c478bd9Sstevel@tonic-gate case 'U': 252*7c478bd9Sstevel@tonic-gate opt = D_CONTEXT; 253*7c478bd9Sstevel@tonic-gate argp = optarg; 254*7c478bd9Sstevel@tonic-gate context = 0; 255*7c478bd9Sstevel@tonic-gate while (*argp >= '0' && *argp <= '9') 256*7c478bd9Sstevel@tonic-gate context *= 10, context += *argp++ - '0'; 257*7c478bd9Sstevel@tonic-gate if (*argp) 258*7c478bd9Sstevel@tonic-gate error(gettext("use [ -C num | -U num ]")); 259*7c478bd9Sstevel@tonic-gate if (flag == 'U') 260*7c478bd9Sstevel@tonic-gate uflag++; 261*7c478bd9Sstevel@tonic-gate else 262*7c478bd9Sstevel@tonic-gate uflag = 0; 263*7c478bd9Sstevel@tonic-gate break; 264*7c478bd9Sstevel@tonic-gate 265*7c478bd9Sstevel@tonic-gate case 'c': 266*7c478bd9Sstevel@tonic-gate case 'u': 267*7c478bd9Sstevel@tonic-gate opt = D_CONTEXT; 268*7c478bd9Sstevel@tonic-gate context = 3; 269*7c478bd9Sstevel@tonic-gate if (flag == 'u') 270*7c478bd9Sstevel@tonic-gate uflag++; 271*7c478bd9Sstevel@tonic-gate else 272*7c478bd9Sstevel@tonic-gate uflag = 0; 273*7c478bd9Sstevel@tonic-gate break; 274*7c478bd9Sstevel@tonic-gate 275*7c478bd9Sstevel@tonic-gate case 'e': 276*7c478bd9Sstevel@tonic-gate opt = D_EDIT; 277*7c478bd9Sstevel@tonic-gate break; 278*7c478bd9Sstevel@tonic-gate 279*7c478bd9Sstevel@tonic-gate case 'f': 280*7c478bd9Sstevel@tonic-gate opt = D_REVERSE; 281*7c478bd9Sstevel@tonic-gate break; 282*7c478bd9Sstevel@tonic-gate 283*7c478bd9Sstevel@tonic-gate case 'h': 284*7c478bd9Sstevel@tonic-gate hflag++; 285*7c478bd9Sstevel@tonic-gate break; 286*7c478bd9Sstevel@tonic-gate 287*7c478bd9Sstevel@tonic-gate case 'i': 288*7c478bd9Sstevel@tonic-gate iflag = 1; 289*7c478bd9Sstevel@tonic-gate break; 290*7c478bd9Sstevel@tonic-gate 291*7c478bd9Sstevel@tonic-gate case 'l': 292*7c478bd9Sstevel@tonic-gate lflag = 1; 293*7c478bd9Sstevel@tonic-gate break; 294*7c478bd9Sstevel@tonic-gate 295*7c478bd9Sstevel@tonic-gate case 'n': 296*7c478bd9Sstevel@tonic-gate opt = D_NREVERSE; 297*7c478bd9Sstevel@tonic-gate break; 298*7c478bd9Sstevel@tonic-gate 299*7c478bd9Sstevel@tonic-gate case 'r': 300*7c478bd9Sstevel@tonic-gate rflag = 1; 301*7c478bd9Sstevel@tonic-gate break; 302*7c478bd9Sstevel@tonic-gate 303*7c478bd9Sstevel@tonic-gate case 'S': 304*7c478bd9Sstevel@tonic-gate (void) strcpy(start, optarg); 305*7c478bd9Sstevel@tonic-gate break; 306*7c478bd9Sstevel@tonic-gate 307*7c478bd9Sstevel@tonic-gate case 's': 308*7c478bd9Sstevel@tonic-gate sflag = 1; 309*7c478bd9Sstevel@tonic-gate break; 310*7c478bd9Sstevel@tonic-gate 311*7c478bd9Sstevel@tonic-gate case 't': 312*7c478bd9Sstevel@tonic-gate tflag = 1; 313*7c478bd9Sstevel@tonic-gate break; 314*7c478bd9Sstevel@tonic-gate 315*7c478bd9Sstevel@tonic-gate case 'w': 316*7c478bd9Sstevel@tonic-gate wflag = 1; 317*7c478bd9Sstevel@tonic-gate break; 318*7c478bd9Sstevel@tonic-gate 319*7c478bd9Sstevel@tonic-gate case '?': 320*7c478bd9Sstevel@tonic-gate usage(); 321*7c478bd9Sstevel@tonic-gate break; 322*7c478bd9Sstevel@tonic-gate 323*7c478bd9Sstevel@tonic-gate default: 324*7c478bd9Sstevel@tonic-gate /* Not sure how it would get here, but just in case */ 325*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "diff: "); 326*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 327*7c478bd9Sstevel@tonic-gate gettext("invalid option -%c\n"), flag); 328*7c478bd9Sstevel@tonic-gate usage(); 329*7c478bd9Sstevel@tonic-gate } 330*7c478bd9Sstevel@tonic-gate } 331*7c478bd9Sstevel@tonic-gate 332*7c478bd9Sstevel@tonic-gate argc -= optind; 333*7c478bd9Sstevel@tonic-gate argv = &argv[optind]; 334*7c478bd9Sstevel@tonic-gate 335*7c478bd9Sstevel@tonic-gate if (opt != D_CONTEXT && uflag) 336*7c478bd9Sstevel@tonic-gate uflag = 0; 337*7c478bd9Sstevel@tonic-gate 338*7c478bd9Sstevel@tonic-gate if (argc != 2) 339*7c478bd9Sstevel@tonic-gate error(gettext("two filename arguments required")); 340*7c478bd9Sstevel@tonic-gate 341*7c478bd9Sstevel@tonic-gate file1 = argv[0]; 342*7c478bd9Sstevel@tonic-gate file2 = argv[1]; 343*7c478bd9Sstevel@tonic-gate 344*7c478bd9Sstevel@tonic-gate if (hflag) { 345*7c478bd9Sstevel@tonic-gate if (opt) { 346*7c478bd9Sstevel@tonic-gate error( 347*7c478bd9Sstevel@tonic-gate gettext("-h doesn't support -e, -f, -n, -c, or -I")); 348*7c478bd9Sstevel@tonic-gate } else { 349*7c478bd9Sstevel@tonic-gate diffargv[0] = "diffh"; 350*7c478bd9Sstevel@tonic-gate (void) execv(diffh, diffargv); 351*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "diffh: "); 352*7c478bd9Sstevel@tonic-gate perror(diffh); 353*7c478bd9Sstevel@tonic-gate status = 2; 354*7c478bd9Sstevel@tonic-gate done(); 355*7c478bd9Sstevel@tonic-gate } 356*7c478bd9Sstevel@tonic-gate 357*7c478bd9Sstevel@tonic-gate } 358*7c478bd9Sstevel@tonic-gate 359*7c478bd9Sstevel@tonic-gate if (strcmp(file1, "-") == 0) { 360*7c478bd9Sstevel@tonic-gate if (fstat(fileno(stdin), &stb1) == 0) 361*7c478bd9Sstevel@tonic-gate stb1.st_mode = S_IFREG; 362*7c478bd9Sstevel@tonic-gate else { 363*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "diff: "); 364*7c478bd9Sstevel@tonic-gate perror("stdin"); 365*7c478bd9Sstevel@tonic-gate done(); 366*7c478bd9Sstevel@tonic-gate } 367*7c478bd9Sstevel@tonic-gate } else if (stat(file1, &stb1) < 0) { 368*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "diff: "); 369*7c478bd9Sstevel@tonic-gate perror(file1); 370*7c478bd9Sstevel@tonic-gate done(); 371*7c478bd9Sstevel@tonic-gate } 372*7c478bd9Sstevel@tonic-gate 373*7c478bd9Sstevel@tonic-gate if (strcmp(file2, "-") == 0) { 374*7c478bd9Sstevel@tonic-gate if (strcmp(file1, "-") == 0) 375*7c478bd9Sstevel@tonic-gate error(gettext("cannot specify - -")); 376*7c478bd9Sstevel@tonic-gate else { 377*7c478bd9Sstevel@tonic-gate if (fstat(fileno(stdin), &stb2) == 0) 378*7c478bd9Sstevel@tonic-gate stb2.st_mode = S_IFREG; 379*7c478bd9Sstevel@tonic-gate else { 380*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "diff: "); 381*7c478bd9Sstevel@tonic-gate perror("stdin"); 382*7c478bd9Sstevel@tonic-gate done(); 383*7c478bd9Sstevel@tonic-gate } 384*7c478bd9Sstevel@tonic-gate } 385*7c478bd9Sstevel@tonic-gate } else if (stat(file2, &stb2) < 0) { 386*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "diff: "); 387*7c478bd9Sstevel@tonic-gate perror(file2); 388*7c478bd9Sstevel@tonic-gate done(); 389*7c478bd9Sstevel@tonic-gate } 390*7c478bd9Sstevel@tonic-gate 391*7c478bd9Sstevel@tonic-gate if ((stb1.st_mode & S_IFMT) == S_IFDIR && 392*7c478bd9Sstevel@tonic-gate (stb2.st_mode & S_IFMT) == S_IFDIR) { 393*7c478bd9Sstevel@tonic-gate diffdir(argv); 394*7c478bd9Sstevel@tonic-gate done(); 395*7c478bd9Sstevel@tonic-gate } 396*7c478bd9Sstevel@tonic-gate 397*7c478bd9Sstevel@tonic-gate filename(&file1, &file2, &stb1, &input_file1); 398*7c478bd9Sstevel@tonic-gate filename(&file2, &file1, &stb2, &input_file2); 399*7c478bd9Sstevel@tonic-gate if ((input[0] = fopen(file1, "r")) == NULL) { 400*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "diff: "); 401*7c478bd9Sstevel@tonic-gate perror(file1); 402*7c478bd9Sstevel@tonic-gate status = 2; 403*7c478bd9Sstevel@tonic-gate done(); 404*7c478bd9Sstevel@tonic-gate } 405*7c478bd9Sstevel@tonic-gate initbuf(input[0], 0, 0); 406*7c478bd9Sstevel@tonic-gate 407*7c478bd9Sstevel@tonic-gate if ((input[1] = fopen(file2, "r")) == NULL) { 408*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "diff: "); 409*7c478bd9Sstevel@tonic-gate perror(file2); 410*7c478bd9Sstevel@tonic-gate status = 2; 411*7c478bd9Sstevel@tonic-gate done(); 412*7c478bd9Sstevel@tonic-gate } 413*7c478bd9Sstevel@tonic-gate initbuf(input[1], 1, 0); 414*7c478bd9Sstevel@tonic-gate 415*7c478bd9Sstevel@tonic-gate if (stb1.st_size != stb2.st_size) 416*7c478bd9Sstevel@tonic-gate goto notsame; 417*7c478bd9Sstevel@tonic-gate 418*7c478bd9Sstevel@tonic-gate for (;;) { 419*7c478bd9Sstevel@tonic-gate i = fread(buf1, 1, BUFSIZ, input[0]); 420*7c478bd9Sstevel@tonic-gate j = fread(buf2, 1, BUFSIZ, input[1]); 421*7c478bd9Sstevel@tonic-gate if (ferror(input[0]) || ferror(input[1])) { 422*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "diff: "); 423*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Error reading ")); 424*7c478bd9Sstevel@tonic-gate perror(ferror(input[0])? file1:file2); 425*7c478bd9Sstevel@tonic-gate (void) fclose(input[0]); 426*7c478bd9Sstevel@tonic-gate (void) fclose(input[1]); 427*7c478bd9Sstevel@tonic-gate status = 2; 428*7c478bd9Sstevel@tonic-gate done(); 429*7c478bd9Sstevel@tonic-gate } 430*7c478bd9Sstevel@tonic-gate if (i != j) 431*7c478bd9Sstevel@tonic-gate goto notsame; 432*7c478bd9Sstevel@tonic-gate if (i == 0 && j == 0) { 433*7c478bd9Sstevel@tonic-gate /* files are the same; diff -D needs to print one */ 434*7c478bd9Sstevel@tonic-gate if (opt == D_IFDEF) { 435*7c478bd9Sstevel@tonic-gate rewind(input[0]); 436*7c478bd9Sstevel@tonic-gate while (i = fread(buf1, 1, BUFSIZ, input[0])) 437*7c478bd9Sstevel@tonic-gate (void) fwrite(buf1, 1, i, stdout); 438*7c478bd9Sstevel@tonic-gate } 439*7c478bd9Sstevel@tonic-gate (void) fclose(input[0]); 440*7c478bd9Sstevel@tonic-gate (void) fclose(input[1]); 441*7c478bd9Sstevel@tonic-gate status = 0; 442*7c478bd9Sstevel@tonic-gate goto same; /* files don't differ */ 443*7c478bd9Sstevel@tonic-gate } 444*7c478bd9Sstevel@tonic-gate for (j = 0; j < i; j++) 445*7c478bd9Sstevel@tonic-gate if (buf1[j] != buf2[j]) 446*7c478bd9Sstevel@tonic-gate goto notsame; 447*7c478bd9Sstevel@tonic-gate } 448*7c478bd9Sstevel@tonic-gate 449*7c478bd9Sstevel@tonic-gate notsame: 450*7c478bd9Sstevel@tonic-gate status = 1; 451*7c478bd9Sstevel@tonic-gate if (filebinary(input[0]) || filebinary(input[1])) { 452*7c478bd9Sstevel@tonic-gate if (ferror(input[0]) || ferror(input[1])) { 453*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "diff: "); 454*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Error reading ")); 455*7c478bd9Sstevel@tonic-gate perror(ferror(input[0])? file1:file2); 456*7c478bd9Sstevel@tonic-gate (void) fclose(input[0]); 457*7c478bd9Sstevel@tonic-gate (void) fclose(input[1]); 458*7c478bd9Sstevel@tonic-gate status = 2; 459*7c478bd9Sstevel@tonic-gate done(); 460*7c478bd9Sstevel@tonic-gate } 461*7c478bd9Sstevel@tonic-gate (void) printf(gettext("Binary files %s and %s differ\n"), 462*7c478bd9Sstevel@tonic-gate file1, file2); 463*7c478bd9Sstevel@tonic-gate (void) fclose(input[0]); 464*7c478bd9Sstevel@tonic-gate (void) fclose(input[1]); 465*7c478bd9Sstevel@tonic-gate done(); 466*7c478bd9Sstevel@tonic-gate } 467*7c478bd9Sstevel@tonic-gate prepare(0, file1); 468*7c478bd9Sstevel@tonic-gate prepare(1, file2); 469*7c478bd9Sstevel@tonic-gate prune(); 470*7c478bd9Sstevel@tonic-gate sort(sfile[0], slen[0]); 471*7c478bd9Sstevel@tonic-gate sort(sfile[1], slen[1]); 472*7c478bd9Sstevel@tonic-gate 473*7c478bd9Sstevel@tonic-gate member = (int *)file[1]; 474*7c478bd9Sstevel@tonic-gate equiv(sfile[0], slen[0], sfile[1], slen[1], member); 475*7c478bd9Sstevel@tonic-gate member = (int *)ralloc((void *)member, (slen[1] + 2) * sizeof (int)); 476*7c478bd9Sstevel@tonic-gate 477*7c478bd9Sstevel@tonic-gate class = (int *)file[0]; 478*7c478bd9Sstevel@tonic-gate unsort(sfile[0], slen[0], class); 479*7c478bd9Sstevel@tonic-gate class = (int *)ralloc((void *)class, (slen[0] + 2) * sizeof (int)); 480*7c478bd9Sstevel@tonic-gate 481*7c478bd9Sstevel@tonic-gate klist = (int *)talloc((slen[0] + 2) * sizeof (int)); 482*7c478bd9Sstevel@tonic-gate clist = (struct cand *)talloc(sizeof (cand)); 483*7c478bd9Sstevel@tonic-gate k = stone(class, slen[0], member, klist); 484*7c478bd9Sstevel@tonic-gate free((void *)member); 485*7c478bd9Sstevel@tonic-gate free((void *)class); 486*7c478bd9Sstevel@tonic-gate 487*7c478bd9Sstevel@tonic-gate J = (int *)talloc((len[0] + 2) * sizeof (int)); 488*7c478bd9Sstevel@tonic-gate unravel(klist[k]); 489*7c478bd9Sstevel@tonic-gate free((char *)clist); 490*7c478bd9Sstevel@tonic-gate free((char *)klist); 491*7c478bd9Sstevel@tonic-gate 492*7c478bd9Sstevel@tonic-gate ixold = (long *)talloc((len[0] + 2) * sizeof (long)); 493*7c478bd9Sstevel@tonic-gate ixnew = (long *)talloc((len[1] + 2) * sizeof (long)); 494*7c478bd9Sstevel@tonic-gate check(); 495*7c478bd9Sstevel@tonic-gate output(); 496*7c478bd9Sstevel@tonic-gate status = anychange; 497*7c478bd9Sstevel@tonic-gate 498*7c478bd9Sstevel@tonic-gate same: 499*7c478bd9Sstevel@tonic-gate if (opt == D_CONTEXT && anychange == 0) 500*7c478bd9Sstevel@tonic-gate (void) printf(gettext("No differences encountered\n")); 501*7c478bd9Sstevel@tonic-gate done(); 502*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 503*7c478bd9Sstevel@tonic-gate } 504*7c478bd9Sstevel@tonic-gate 505*7c478bd9Sstevel@tonic-gate static int 506*7c478bd9Sstevel@tonic-gate stone(int *a, int n, int *b, int *c) 507*7c478bd9Sstevel@tonic-gate { 508*7c478bd9Sstevel@tonic-gate int i, k, y; 509*7c478bd9Sstevel@tonic-gate int j, l; 510*7c478bd9Sstevel@tonic-gate int oldc, tc; 511*7c478bd9Sstevel@tonic-gate int oldl; 512*7c478bd9Sstevel@tonic-gate 513*7c478bd9Sstevel@tonic-gate k = 0; 514*7c478bd9Sstevel@tonic-gate c[0] = newcand(0, 0, 0); 515*7c478bd9Sstevel@tonic-gate for (i = 1; i <= n; i++) { 516*7c478bd9Sstevel@tonic-gate j = a[i]; 517*7c478bd9Sstevel@tonic-gate if (j == 0) 518*7c478bd9Sstevel@tonic-gate continue; 519*7c478bd9Sstevel@tonic-gate y = -b[j]; 520*7c478bd9Sstevel@tonic-gate oldl = 0; 521*7c478bd9Sstevel@tonic-gate oldc = c[0]; 522*7c478bd9Sstevel@tonic-gate do { 523*7c478bd9Sstevel@tonic-gate if (y <= clist[oldc].y) 524*7c478bd9Sstevel@tonic-gate continue; 525*7c478bd9Sstevel@tonic-gate l = search(c, k, y); 526*7c478bd9Sstevel@tonic-gate if (l != oldl+1) 527*7c478bd9Sstevel@tonic-gate oldc = c[l-1]; 528*7c478bd9Sstevel@tonic-gate if (l <= k) { 529*7c478bd9Sstevel@tonic-gate if (clist[c[l]].y <= y) 530*7c478bd9Sstevel@tonic-gate continue; 531*7c478bd9Sstevel@tonic-gate tc = c[l]; 532*7c478bd9Sstevel@tonic-gate c[l] = newcand(i, y, oldc); 533*7c478bd9Sstevel@tonic-gate oldc = tc; 534*7c478bd9Sstevel@tonic-gate oldl = l; 535*7c478bd9Sstevel@tonic-gate } else { 536*7c478bd9Sstevel@tonic-gate c[l] = newcand(i, y, oldc); 537*7c478bd9Sstevel@tonic-gate k++; 538*7c478bd9Sstevel@tonic-gate break; 539*7c478bd9Sstevel@tonic-gate } 540*7c478bd9Sstevel@tonic-gate } while ((y = b[++j]) > 0); 541*7c478bd9Sstevel@tonic-gate } 542*7c478bd9Sstevel@tonic-gate return (k); 543*7c478bd9Sstevel@tonic-gate } 544*7c478bd9Sstevel@tonic-gate 545*7c478bd9Sstevel@tonic-gate static int 546*7c478bd9Sstevel@tonic-gate newcand(int x, int y, int pred) 547*7c478bd9Sstevel@tonic-gate { 548*7c478bd9Sstevel@tonic-gate struct cand *q; 549*7c478bd9Sstevel@tonic-gate 550*7c478bd9Sstevel@tonic-gate clist = (struct cand *)ralloc((void *)clist, ++clen * sizeof (cand)); 551*7c478bd9Sstevel@tonic-gate q = clist + clen -1; 552*7c478bd9Sstevel@tonic-gate q->x = x; 553*7c478bd9Sstevel@tonic-gate q->y = y; 554*7c478bd9Sstevel@tonic-gate q->pred = pred; 555*7c478bd9Sstevel@tonic-gate return (clen - 1); 556*7c478bd9Sstevel@tonic-gate } 557*7c478bd9Sstevel@tonic-gate 558*7c478bd9Sstevel@tonic-gate static int 559*7c478bd9Sstevel@tonic-gate search(int *c, int k, int y) 560*7c478bd9Sstevel@tonic-gate { 561*7c478bd9Sstevel@tonic-gate int i, j, l; 562*7c478bd9Sstevel@tonic-gate int t; 563*7c478bd9Sstevel@tonic-gate 564*7c478bd9Sstevel@tonic-gate if (clist[c[k]].y < y) /* quick look for typical case */ 565*7c478bd9Sstevel@tonic-gate return (k + 1); 566*7c478bd9Sstevel@tonic-gate i = 0; 567*7c478bd9Sstevel@tonic-gate j = k+1; 568*7c478bd9Sstevel@tonic-gate while ((l = (i + j) / 2) > i) { 569*7c478bd9Sstevel@tonic-gate t = clist[c[l]].y; 570*7c478bd9Sstevel@tonic-gate if (t > y) 571*7c478bd9Sstevel@tonic-gate j = l; 572*7c478bd9Sstevel@tonic-gate else if (t < y) 573*7c478bd9Sstevel@tonic-gate i = l; 574*7c478bd9Sstevel@tonic-gate else 575*7c478bd9Sstevel@tonic-gate return (l); 576*7c478bd9Sstevel@tonic-gate } 577*7c478bd9Sstevel@tonic-gate return (l + 1); 578*7c478bd9Sstevel@tonic-gate } 579*7c478bd9Sstevel@tonic-gate 580*7c478bd9Sstevel@tonic-gate static void 581*7c478bd9Sstevel@tonic-gate unravel(int p) 582*7c478bd9Sstevel@tonic-gate { 583*7c478bd9Sstevel@tonic-gate int i; 584*7c478bd9Sstevel@tonic-gate struct cand *q; 585*7c478bd9Sstevel@tonic-gate 586*7c478bd9Sstevel@tonic-gate for (i = 0; i <= len[0]; i++) 587*7c478bd9Sstevel@tonic-gate J[i] = i <= pref ? i : 588*7c478bd9Sstevel@tonic-gate i > len[0] - suff ? i + len[1] - len[0]: 589*7c478bd9Sstevel@tonic-gate 0; 590*7c478bd9Sstevel@tonic-gate for (q = clist + p; q->y != 0; q = clist + q->pred) 591*7c478bd9Sstevel@tonic-gate J[q->x + pref] = q->y + pref; 592*7c478bd9Sstevel@tonic-gate } 593*7c478bd9Sstevel@tonic-gate 594*7c478bd9Sstevel@tonic-gate /* 595*7c478bd9Sstevel@tonic-gate * check does double duty: 596*7c478bd9Sstevel@tonic-gate * 1. ferret out any fortuitous correspondences due to confounding by 597*7c478bd9Sstevel@tonic-gate * hashing (which result in "jackpot") 598*7c478bd9Sstevel@tonic-gate * 2. collect random access indexes to the two files 599*7c478bd9Sstevel@tonic-gate */ 600*7c478bd9Sstevel@tonic-gate 601*7c478bd9Sstevel@tonic-gate static void 602*7c478bd9Sstevel@tonic-gate check(void) 603*7c478bd9Sstevel@tonic-gate { 604*7c478bd9Sstevel@tonic-gate wint_t c, d; 605*7c478bd9Sstevel@tonic-gate int i, j; 606*7c478bd9Sstevel@tonic-gate /* int jackpot; */ 607*7c478bd9Sstevel@tonic-gate int mlen; 608*7c478bd9Sstevel@tonic-gate long ctold, ctnew; 609*7c478bd9Sstevel@tonic-gate 610*7c478bd9Sstevel@tonic-gate resetbuf(0); 611*7c478bd9Sstevel@tonic-gate resetbuf(1); 612*7c478bd9Sstevel@tonic-gate 613*7c478bd9Sstevel@tonic-gate j = 1; 614*7c478bd9Sstevel@tonic-gate ixold[0] = ixnew[0] = 0; 615*7c478bd9Sstevel@tonic-gate /* jackpot = 0; */ 616*7c478bd9Sstevel@tonic-gate 617*7c478bd9Sstevel@tonic-gate /* 618*7c478bd9Sstevel@tonic-gate * ctold and ctnew are byte positions within the file (suitable for 619*7c478bd9Sstevel@tonic-gate * lseek()). After we get a character with getwc(), instead of 620*7c478bd9Sstevel@tonic-gate * just incrementing the byte position by 1, we have to determine 621*7c478bd9Sstevel@tonic-gate * how many bytes the character actually is. This is the reason for 622*7c478bd9Sstevel@tonic-gate * the wctomb() calls here and in skipline(). 623*7c478bd9Sstevel@tonic-gate */ 624*7c478bd9Sstevel@tonic-gate ctold = ctnew = 0; 625*7c478bd9Sstevel@tonic-gate for (i = 1; i <= len[0]; i++) { 626*7c478bd9Sstevel@tonic-gate if (J[i] == 0) { 627*7c478bd9Sstevel@tonic-gate ixold[i] = ctold += skipline(0); 628*7c478bd9Sstevel@tonic-gate continue; 629*7c478bd9Sstevel@tonic-gate } 630*7c478bd9Sstevel@tonic-gate while (j < J[i]) { 631*7c478bd9Sstevel@tonic-gate ixnew[j] = ctnew += skipline(1); 632*7c478bd9Sstevel@tonic-gate j++; 633*7c478bd9Sstevel@tonic-gate } 634*7c478bd9Sstevel@tonic-gate if (bflag || wflag || iflag) { 635*7c478bd9Sstevel@tonic-gate for (;;) { 636*7c478bd9Sstevel@tonic-gate c = getbufwchar(0, &mlen); 637*7c478bd9Sstevel@tonic-gate ctold += mlen; 638*7c478bd9Sstevel@tonic-gate d = getbufwchar(1, &mlen); 639*7c478bd9Sstevel@tonic-gate ctnew += mlen; 640*7c478bd9Sstevel@tonic-gate 641*7c478bd9Sstevel@tonic-gate if (bflag && iswspace(c) && iswspace(d)) { 642*7c478bd9Sstevel@tonic-gate while (iswspace(c)) { 643*7c478bd9Sstevel@tonic-gate if (c == '\n' || c == WEOF) 644*7c478bd9Sstevel@tonic-gate break; 645*7c478bd9Sstevel@tonic-gate 646*7c478bd9Sstevel@tonic-gate c = getbufwchar(0, &mlen); 647*7c478bd9Sstevel@tonic-gate ctold += mlen; 648*7c478bd9Sstevel@tonic-gate } 649*7c478bd9Sstevel@tonic-gate while (iswspace(d)) { 650*7c478bd9Sstevel@tonic-gate if (d == '\n' || d == WEOF) 651*7c478bd9Sstevel@tonic-gate break; 652*7c478bd9Sstevel@tonic-gate 653*7c478bd9Sstevel@tonic-gate d = getbufwchar(1, &mlen); 654*7c478bd9Sstevel@tonic-gate ctnew += mlen; 655*7c478bd9Sstevel@tonic-gate } 656*7c478bd9Sstevel@tonic-gate } else if (wflag) { 657*7c478bd9Sstevel@tonic-gate while (iswspace(c) && c != '\n') { 658*7c478bd9Sstevel@tonic-gate c = getbufwchar(0, &mlen); 659*7c478bd9Sstevel@tonic-gate ctold += mlen; 660*7c478bd9Sstevel@tonic-gate } 661*7c478bd9Sstevel@tonic-gate while (iswspace(d) && d != '\n') { 662*7c478bd9Sstevel@tonic-gate d = getbufwchar(1, &mlen); 663*7c478bd9Sstevel@tonic-gate ctnew += mlen; 664*7c478bd9Sstevel@tonic-gate } 665*7c478bd9Sstevel@tonic-gate } 666*7c478bd9Sstevel@tonic-gate if (c == WEOF || d == WEOF) { 667*7c478bd9Sstevel@tonic-gate if (c != d) { 668*7c478bd9Sstevel@tonic-gate /* jackpot++; */ 669*7c478bd9Sstevel@tonic-gate J[i] = 0; 670*7c478bd9Sstevel@tonic-gate if (c != '\n' && c != WEOF) 671*7c478bd9Sstevel@tonic-gate ctold += skipline(0); 672*7c478bd9Sstevel@tonic-gate if (d != '\n' && d != WEOF) 673*7c478bd9Sstevel@tonic-gate ctnew += skipline(1); 674*7c478bd9Sstevel@tonic-gate break; 675*7c478bd9Sstevel@tonic-gate } 676*7c478bd9Sstevel@tonic-gate break; 677*7c478bd9Sstevel@tonic-gate } else { 678*7c478bd9Sstevel@tonic-gate if (CHRTRAN(c) != CHRTRAN(d)) { 679*7c478bd9Sstevel@tonic-gate /* jackpot++; */ 680*7c478bd9Sstevel@tonic-gate J[i] = 0; 681*7c478bd9Sstevel@tonic-gate if (c != '\n') 682*7c478bd9Sstevel@tonic-gate ctold += skipline(0); 683*7c478bd9Sstevel@tonic-gate if (d != '\n') 684*7c478bd9Sstevel@tonic-gate ctnew += skipline(1); 685*7c478bd9Sstevel@tonic-gate break; 686*7c478bd9Sstevel@tonic-gate } 687*7c478bd9Sstevel@tonic-gate if (c == '\n') 688*7c478bd9Sstevel@tonic-gate break; 689*7c478bd9Sstevel@tonic-gate } 690*7c478bd9Sstevel@tonic-gate } 691*7c478bd9Sstevel@tonic-gate } else { 692*7c478bd9Sstevel@tonic-gate for (;;) { 693*7c478bd9Sstevel@tonic-gate c = getbufwchar(0, &mlen); 694*7c478bd9Sstevel@tonic-gate ctold += mlen; 695*7c478bd9Sstevel@tonic-gate d = getbufwchar(1, &mlen); 696*7c478bd9Sstevel@tonic-gate ctnew += mlen; 697*7c478bd9Sstevel@tonic-gate if (c != d) { 698*7c478bd9Sstevel@tonic-gate /* jackpot++; */ 699*7c478bd9Sstevel@tonic-gate J[i] = 0; 700*7c478bd9Sstevel@tonic-gate if (c != '\n' && c != WEOF) 701*7c478bd9Sstevel@tonic-gate ctold += skipline(0); 702*7c478bd9Sstevel@tonic-gate if (d != '\n' && d != WEOF) 703*7c478bd9Sstevel@tonic-gate ctnew += skipline(1); 704*7c478bd9Sstevel@tonic-gate break; 705*7c478bd9Sstevel@tonic-gate } 706*7c478bd9Sstevel@tonic-gate if (c == '\n' || c == WEOF) 707*7c478bd9Sstevel@tonic-gate break; 708*7c478bd9Sstevel@tonic-gate } 709*7c478bd9Sstevel@tonic-gate } 710*7c478bd9Sstevel@tonic-gate ixold[i] = ctold; 711*7c478bd9Sstevel@tonic-gate ixnew[j] = ctnew; 712*7c478bd9Sstevel@tonic-gate j++; 713*7c478bd9Sstevel@tonic-gate } 714*7c478bd9Sstevel@tonic-gate for (; j <= len[1]; j++) { 715*7c478bd9Sstevel@tonic-gate ixnew[j] = ctnew += skipline(1); 716*7c478bd9Sstevel@tonic-gate } 717*7c478bd9Sstevel@tonic-gate 718*7c478bd9Sstevel@tonic-gate /* if(jackpot) */ 719*7c478bd9Sstevel@tonic-gate /* fprintf(stderr, "diff: jackpot\n"); */ 720*7c478bd9Sstevel@tonic-gate } 721*7c478bd9Sstevel@tonic-gate 722*7c478bd9Sstevel@tonic-gate static int 723*7c478bd9Sstevel@tonic-gate skipline(int f) 724*7c478bd9Sstevel@tonic-gate { 725*7c478bd9Sstevel@tonic-gate int i; 726*7c478bd9Sstevel@tonic-gate wint_t c; 727*7c478bd9Sstevel@tonic-gate int mlen; 728*7c478bd9Sstevel@tonic-gate 729*7c478bd9Sstevel@tonic-gate for (i = 1; c = getbufwchar(f, &mlen); ) { 730*7c478bd9Sstevel@tonic-gate if (c == '\n' || c == WEOF) 731*7c478bd9Sstevel@tonic-gate return (i); 732*7c478bd9Sstevel@tonic-gate i += mlen; 733*7c478bd9Sstevel@tonic-gate } 734*7c478bd9Sstevel@tonic-gate return (i); 735*7c478bd9Sstevel@tonic-gate } 736*7c478bd9Sstevel@tonic-gate 737*7c478bd9Sstevel@tonic-gate static void 738*7c478bd9Sstevel@tonic-gate output(void) 739*7c478bd9Sstevel@tonic-gate { 740*7c478bd9Sstevel@tonic-gate int m; 741*7c478bd9Sstevel@tonic-gate wint_t wc; 742*7c478bd9Sstevel@tonic-gate int i0, i1, j1; 743*7c478bd9Sstevel@tonic-gate int j0; 744*7c478bd9Sstevel@tonic-gate int mlen; 745*7c478bd9Sstevel@tonic-gate 746*7c478bd9Sstevel@tonic-gate resetbuf(0); 747*7c478bd9Sstevel@tonic-gate resetbuf(1); 748*7c478bd9Sstevel@tonic-gate 749*7c478bd9Sstevel@tonic-gate m = len[0]; 750*7c478bd9Sstevel@tonic-gate J[0] = 0; 751*7c478bd9Sstevel@tonic-gate J[m + 1] = len[1] + 1; 752*7c478bd9Sstevel@tonic-gate if (opt != D_EDIT) 753*7c478bd9Sstevel@tonic-gate for (i0 = 1; i0 <= m; i0 = i1+1) { 754*7c478bd9Sstevel@tonic-gate while (i0 <= m && J[i0] == J[i0 - 1] + 1) 755*7c478bd9Sstevel@tonic-gate i0++; 756*7c478bd9Sstevel@tonic-gate j0 = J[i0 - 1] + 1; 757*7c478bd9Sstevel@tonic-gate i1 = i0 - 1; 758*7c478bd9Sstevel@tonic-gate while (i1 < m && J[i1 + 1] == 0) 759*7c478bd9Sstevel@tonic-gate i1++; 760*7c478bd9Sstevel@tonic-gate j1 = J[i1 + 1] - 1; 761*7c478bd9Sstevel@tonic-gate J[i1] = j1; 762*7c478bd9Sstevel@tonic-gate change(i0, i1, j0, j1); 763*7c478bd9Sstevel@tonic-gate } else for (i0 = m; i0 >= 1; i0 = i1 - 1) { 764*7c478bd9Sstevel@tonic-gate while (i0 >= 1 && J[i0] == J[i0 + 1] - 1 && J[i0] != 0) 765*7c478bd9Sstevel@tonic-gate i0--; 766*7c478bd9Sstevel@tonic-gate j0 = J[i0 + 1] - 1; 767*7c478bd9Sstevel@tonic-gate i1 = i0 + 1; 768*7c478bd9Sstevel@tonic-gate while (i1 > 1 && J[i1 - 1] == 0) 769*7c478bd9Sstevel@tonic-gate i1--; 770*7c478bd9Sstevel@tonic-gate j1 = J[i1 - 1] + 1; 771*7c478bd9Sstevel@tonic-gate J[i1] = j1; 772*7c478bd9Sstevel@tonic-gate change(i1, i0, j1, j0); 773*7c478bd9Sstevel@tonic-gate } 774*7c478bd9Sstevel@tonic-gate if (m == 0) 775*7c478bd9Sstevel@tonic-gate change(1, 0, 1, len[1]); 776*7c478bd9Sstevel@tonic-gate if (opt == D_IFDEF) { 777*7c478bd9Sstevel@tonic-gate for (;;) { 778*7c478bd9Sstevel@tonic-gate wc = getbufwchar(0, &mlen); 779*7c478bd9Sstevel@tonic-gate if (wc == WEOF) 780*7c478bd9Sstevel@tonic-gate return; 781*7c478bd9Sstevel@tonic-gate (void) wcput(wc); 782*7c478bd9Sstevel@tonic-gate } 783*7c478bd9Sstevel@tonic-gate } 784*7c478bd9Sstevel@tonic-gate if (anychange && opt == D_CONTEXT) 785*7c478bd9Sstevel@tonic-gate dump_context_vec(); 786*7c478bd9Sstevel@tonic-gate } 787*7c478bd9Sstevel@tonic-gate 788*7c478bd9Sstevel@tonic-gate 789*7c478bd9Sstevel@tonic-gate /* 790*7c478bd9Sstevel@tonic-gate * indicate that there is a difference between lines a and b of the from file 791*7c478bd9Sstevel@tonic-gate * to get to lines c to d of the to file. 792*7c478bd9Sstevel@tonic-gate * If a is greater then b then there are no lines in the from file involved 793*7c478bd9Sstevel@tonic-gate * and this means that there were lines appended (beginning at b). 794*7c478bd9Sstevel@tonic-gate * If c is greater than d then there are lines missing from the to file. 795*7c478bd9Sstevel@tonic-gate */ 796*7c478bd9Sstevel@tonic-gate static void 797*7c478bd9Sstevel@tonic-gate change(int a, int b, int c, int d) 798*7c478bd9Sstevel@tonic-gate { 799*7c478bd9Sstevel@tonic-gate char time_buf[BUFSIZ]; 800*7c478bd9Sstevel@tonic-gate char *dcmsg; 801*7c478bd9Sstevel@tonic-gate 802*7c478bd9Sstevel@tonic-gate if (opt != D_IFDEF && a > b && c > d) 803*7c478bd9Sstevel@tonic-gate return; 804*7c478bd9Sstevel@tonic-gate if (anychange == 0) { 805*7c478bd9Sstevel@tonic-gate anychange = 1; 806*7c478bd9Sstevel@tonic-gate if (opt == D_CONTEXT) { 807*7c478bd9Sstevel@tonic-gate /* 808*7c478bd9Sstevel@tonic-gate * TRANSLATION_NOTE_FOR_DC 809*7c478bd9Sstevel@tonic-gate * This message is the format of file 810*7c478bd9Sstevel@tonic-gate * timestamps written with the -C and 811*7c478bd9Sstevel@tonic-gate * -c options. 812*7c478bd9Sstevel@tonic-gate * %a -- locale's abbreviated weekday name 813*7c478bd9Sstevel@tonic-gate * %b -- locale's abbreviated month name 814*7c478bd9Sstevel@tonic-gate * %e -- day of month [1,31] 815*7c478bd9Sstevel@tonic-gate * %T -- Time as %H:%M:%S 816*7c478bd9Sstevel@tonic-gate * %Y -- Year, including the century 817*7c478bd9Sstevel@tonic-gate */ 818*7c478bd9Sstevel@tonic-gate dcmsg = dcgettext(NULL, "%a %b %e %T %Y", LC_TIME); 819*7c478bd9Sstevel@tonic-gate (void) cftime(time_buf, dcmsg, &stb1.st_mtime); 820*7c478bd9Sstevel@tonic-gate if (uflag) 821*7c478bd9Sstevel@tonic-gate (void) printf("--- %s %s\n", input_file1, 822*7c478bd9Sstevel@tonic-gate time_buf); 823*7c478bd9Sstevel@tonic-gate else 824*7c478bd9Sstevel@tonic-gate (void) printf("*** %s %s\n", input_file1, 825*7c478bd9Sstevel@tonic-gate time_buf); 826*7c478bd9Sstevel@tonic-gate (void) cftime(time_buf, dcmsg, &stb2.st_mtime); 827*7c478bd9Sstevel@tonic-gate if (uflag) 828*7c478bd9Sstevel@tonic-gate (void) printf("+++ %s %s\n", input_file2, 829*7c478bd9Sstevel@tonic-gate time_buf); 830*7c478bd9Sstevel@tonic-gate else 831*7c478bd9Sstevel@tonic-gate (void) printf("--- %s %s\n", input_file2, 832*7c478bd9Sstevel@tonic-gate time_buf); 833*7c478bd9Sstevel@tonic-gate 834*7c478bd9Sstevel@tonic-gate context_vec_start = (struct context_vec *) 835*7c478bd9Sstevel@tonic-gate malloc(MAX_CONTEXT * 836*7c478bd9Sstevel@tonic-gate sizeof (struct context_vec)); 837*7c478bd9Sstevel@tonic-gate if (context_vec_start == NULL) 838*7c478bd9Sstevel@tonic-gate error(gettext(NO_MEM_ERR)); 839*7c478bd9Sstevel@tonic-gate 840*7c478bd9Sstevel@tonic-gate context_vec_end = context_vec_start + (MAX_CONTEXT - 1); 841*7c478bd9Sstevel@tonic-gate context_vec_ptr = context_vec_start - 1; 842*7c478bd9Sstevel@tonic-gate } 843*7c478bd9Sstevel@tonic-gate } 844*7c478bd9Sstevel@tonic-gate 845*7c478bd9Sstevel@tonic-gate if (opt == D_CONTEXT) { 846*7c478bd9Sstevel@tonic-gate /* 847*7c478bd9Sstevel@tonic-gate * if this new change is within 'context' lines of 848*7c478bd9Sstevel@tonic-gate * the previous change, just add it to the change 849*7c478bd9Sstevel@tonic-gate * record. If the record is full or if this 850*7c478bd9Sstevel@tonic-gate * change is more than 'context' lines from the previous 851*7c478bd9Sstevel@tonic-gate * change, dump the record, reset it & add the new change. 852*7c478bd9Sstevel@tonic-gate */ 853*7c478bd9Sstevel@tonic-gate if (context_vec_ptr >= context_vec_end || 854*7c478bd9Sstevel@tonic-gate (context_vec_ptr >= context_vec_start && 855*7c478bd9Sstevel@tonic-gate a > (context_vec_ptr->b + 2 * context) && 856*7c478bd9Sstevel@tonic-gate c > (context_vec_ptr->d + 2 * context))) 857*7c478bd9Sstevel@tonic-gate dump_context_vec(); 858*7c478bd9Sstevel@tonic-gate 859*7c478bd9Sstevel@tonic-gate context_vec_ptr++; 860*7c478bd9Sstevel@tonic-gate context_vec_ptr->a = a; 861*7c478bd9Sstevel@tonic-gate context_vec_ptr->b = b; 862*7c478bd9Sstevel@tonic-gate context_vec_ptr->c = c; 863*7c478bd9Sstevel@tonic-gate context_vec_ptr->d = d; 864*7c478bd9Sstevel@tonic-gate return; 865*7c478bd9Sstevel@tonic-gate } 866*7c478bd9Sstevel@tonic-gate 867*7c478bd9Sstevel@tonic-gate switch (opt) { 868*7c478bd9Sstevel@tonic-gate case D_NORMAL: 869*7c478bd9Sstevel@tonic-gate case D_EDIT: 870*7c478bd9Sstevel@tonic-gate range(a, b, ","); 871*7c478bd9Sstevel@tonic-gate (void) putchar(a > b ? 'a' : c > d ? 'd' : 'c'); 872*7c478bd9Sstevel@tonic-gate if (opt == D_NORMAL) range(c, d, ","); 873*7c478bd9Sstevel@tonic-gate (void) printf("\n"); 874*7c478bd9Sstevel@tonic-gate break; 875*7c478bd9Sstevel@tonic-gate case D_REVERSE: 876*7c478bd9Sstevel@tonic-gate (void) putchar(a > b ? 'a' : c > d ? 'd' : 'c'); 877*7c478bd9Sstevel@tonic-gate range(a, b, " "); 878*7c478bd9Sstevel@tonic-gate (void) printf("\n"); 879*7c478bd9Sstevel@tonic-gate break; 880*7c478bd9Sstevel@tonic-gate case D_NREVERSE: 881*7c478bd9Sstevel@tonic-gate if (a > b) 882*7c478bd9Sstevel@tonic-gate (void) printf("a%d %d\n", b, d - c + 1); 883*7c478bd9Sstevel@tonic-gate else { 884*7c478bd9Sstevel@tonic-gate (void) printf("d%d %d\n", a, b - a + 1); 885*7c478bd9Sstevel@tonic-gate if (!(c > d)) 886*7c478bd9Sstevel@tonic-gate /* add changed lines */ 887*7c478bd9Sstevel@tonic-gate (void) printf("a%d %d\n", b, d - c + 1); 888*7c478bd9Sstevel@tonic-gate } 889*7c478bd9Sstevel@tonic-gate break; 890*7c478bd9Sstevel@tonic-gate } 891*7c478bd9Sstevel@tonic-gate if (opt == D_NORMAL || opt == D_IFDEF) { 892*7c478bd9Sstevel@tonic-gate fetch(ixold, a, b, 0, "< ", 1); 893*7c478bd9Sstevel@tonic-gate if (a <= b && c <= d && opt == D_NORMAL) 894*7c478bd9Sstevel@tonic-gate (void) prints("---\n"); 895*7c478bd9Sstevel@tonic-gate } 896*7c478bd9Sstevel@tonic-gate fetch(ixnew, c, d, 1, opt == D_NORMAL?"> ":empty, 0); 897*7c478bd9Sstevel@tonic-gate if ((opt == D_EDIT || opt == D_REVERSE) && c <= d) 898*7c478bd9Sstevel@tonic-gate (void) prints(".\n"); 899*7c478bd9Sstevel@tonic-gate if (inifdef) { 900*7c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "#endif /* %s */\n", endifname); 901*7c478bd9Sstevel@tonic-gate inifdef = 0; 902*7c478bd9Sstevel@tonic-gate } 903*7c478bd9Sstevel@tonic-gate } 904*7c478bd9Sstevel@tonic-gate 905*7c478bd9Sstevel@tonic-gate static void 906*7c478bd9Sstevel@tonic-gate range(int a, int b, char *separator) 907*7c478bd9Sstevel@tonic-gate { 908*7c478bd9Sstevel@tonic-gate (void) printf("%d", a > b ? b : a); 909*7c478bd9Sstevel@tonic-gate if (a < b) { 910*7c478bd9Sstevel@tonic-gate (void) printf("%s%d", separator, b); 911*7c478bd9Sstevel@tonic-gate } 912*7c478bd9Sstevel@tonic-gate } 913*7c478bd9Sstevel@tonic-gate 914*7c478bd9Sstevel@tonic-gate static void 915*7c478bd9Sstevel@tonic-gate fetch(long *f, int a, int b, int filen, char *s, int oldfile) 916*7c478bd9Sstevel@tonic-gate { 917*7c478bd9Sstevel@tonic-gate int i; 918*7c478bd9Sstevel@tonic-gate int col; 919*7c478bd9Sstevel@tonic-gate int nc; 920*7c478bd9Sstevel@tonic-gate int mlen = 0; 921*7c478bd9Sstevel@tonic-gate wint_t ch; 922*7c478bd9Sstevel@tonic-gate FILE *lb; 923*7c478bd9Sstevel@tonic-gate 924*7c478bd9Sstevel@tonic-gate lb = input[filen]; 925*7c478bd9Sstevel@tonic-gate /* 926*7c478bd9Sstevel@tonic-gate * When doing #ifdef's, copy down to current line 927*7c478bd9Sstevel@tonic-gate * if this is the first file, so that stuff makes it to output. 928*7c478bd9Sstevel@tonic-gate */ 929*7c478bd9Sstevel@tonic-gate if (opt == D_IFDEF && oldfile) { 930*7c478bd9Sstevel@tonic-gate long curpos = ftellbuf(filen); 931*7c478bd9Sstevel@tonic-gate /* print through if append (a>b), else to (nb: 0 vs 1 orig) */ 932*7c478bd9Sstevel@tonic-gate nc = f[(a > b) ? b : (a - 1) ] - curpos; 933*7c478bd9Sstevel@tonic-gate for (i = 0; i < nc; i += mlen) { 934*7c478bd9Sstevel@tonic-gate ch = getbufwchar(filen, &mlen); 935*7c478bd9Sstevel@tonic-gate if (ch == WEOF) { 936*7c478bd9Sstevel@tonic-gate (void) putchar('\n'); 937*7c478bd9Sstevel@tonic-gate break; 938*7c478bd9Sstevel@tonic-gate } else { 939*7c478bd9Sstevel@tonic-gate (void) wcput(ch); 940*7c478bd9Sstevel@tonic-gate } 941*7c478bd9Sstevel@tonic-gate } 942*7c478bd9Sstevel@tonic-gate } 943*7c478bd9Sstevel@tonic-gate if (a > b) 944*7c478bd9Sstevel@tonic-gate return; 945*7c478bd9Sstevel@tonic-gate if (opt == D_IFDEF) { 946*7c478bd9Sstevel@tonic-gate int oneflag = (*ifdef1 != '\0') != (*ifdef2 != '\0'); 947*7c478bd9Sstevel@tonic-gate if (inifdef) 948*7c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "#else /* %s%s */\n", 949*7c478bd9Sstevel@tonic-gate oneflag && oldfile == 1 ? "!" : "", ifdef2); 950*7c478bd9Sstevel@tonic-gate else { 951*7c478bd9Sstevel@tonic-gate if (oneflag) { 952*7c478bd9Sstevel@tonic-gate /* There was only one ifdef given */ 953*7c478bd9Sstevel@tonic-gate endifname = ifdef2; 954*7c478bd9Sstevel@tonic-gate if (oldfile) 955*7c478bd9Sstevel@tonic-gate (void) fprintf(stdout, 956*7c478bd9Sstevel@tonic-gate "#ifndef %s\n", endifname); 957*7c478bd9Sstevel@tonic-gate else 958*7c478bd9Sstevel@tonic-gate (void) fprintf(stdout, 959*7c478bd9Sstevel@tonic-gate "#ifdef %s\n", endifname); 960*7c478bd9Sstevel@tonic-gate } else { 961*7c478bd9Sstevel@tonic-gate endifname = oldfile ? ifdef1 : ifdef2; 962*7c478bd9Sstevel@tonic-gate (void) fprintf(stdout, 963*7c478bd9Sstevel@tonic-gate "#ifdef %s\n", endifname); 964*7c478bd9Sstevel@tonic-gate } 965*7c478bd9Sstevel@tonic-gate } 966*7c478bd9Sstevel@tonic-gate inifdef = 1 + oldfile; 967*7c478bd9Sstevel@tonic-gate } 968*7c478bd9Sstevel@tonic-gate 969*7c478bd9Sstevel@tonic-gate for (i = a; i <= b; i++) { 970*7c478bd9Sstevel@tonic-gate (void) fseek(lb, f[i - 1], SEEK_SET); 971*7c478bd9Sstevel@tonic-gate initbuf(lb, filen, f[i - 1]); 972*7c478bd9Sstevel@tonic-gate if (opt != D_IFDEF) 973*7c478bd9Sstevel@tonic-gate (void) prints(s); 974*7c478bd9Sstevel@tonic-gate col = 0; 975*7c478bd9Sstevel@tonic-gate while (ch = getbufwchar(filen, &mlen)) { 976*7c478bd9Sstevel@tonic-gate if (ch != '\n' && ch != WEOF) { 977*7c478bd9Sstevel@tonic-gate if (ch == '\t' && tflag) 978*7c478bd9Sstevel@tonic-gate do 979*7c478bd9Sstevel@tonic-gate (void) putchar(' '); 980*7c478bd9Sstevel@tonic-gate while (++col & 7); 981*7c478bd9Sstevel@tonic-gate else { 982*7c478bd9Sstevel@tonic-gate (void) wcput(ch); 983*7c478bd9Sstevel@tonic-gate col++; 984*7c478bd9Sstevel@tonic-gate } 985*7c478bd9Sstevel@tonic-gate } else 986*7c478bd9Sstevel@tonic-gate break; 987*7c478bd9Sstevel@tonic-gate } 988*7c478bd9Sstevel@tonic-gate (void) putchar('\n'); 989*7c478bd9Sstevel@tonic-gate } 990*7c478bd9Sstevel@tonic-gate } 991*7c478bd9Sstevel@tonic-gate 992*7c478bd9Sstevel@tonic-gate /* 993*7c478bd9Sstevel@tonic-gate * hashing has the effect of 994*7c478bd9Sstevel@tonic-gate * arranging line in 7-bit bytes and then 995*7c478bd9Sstevel@tonic-gate * summing 1-s complement in 16-bit hunks 996*7c478bd9Sstevel@tonic-gate */ 997*7c478bd9Sstevel@tonic-gate 998*7c478bd9Sstevel@tonic-gate static int 999*7c478bd9Sstevel@tonic-gate readhash(FILE *f, int filen, char *str) 1000*7c478bd9Sstevel@tonic-gate { 1001*7c478bd9Sstevel@tonic-gate long sum; 1002*7c478bd9Sstevel@tonic-gate unsigned int shift; 1003*7c478bd9Sstevel@tonic-gate int space; 1004*7c478bd9Sstevel@tonic-gate int t; 1005*7c478bd9Sstevel@tonic-gate wint_t wt; 1006*7c478bd9Sstevel@tonic-gate int mlen; 1007*7c478bd9Sstevel@tonic-gate 1008*7c478bd9Sstevel@tonic-gate sum = 1; 1009*7c478bd9Sstevel@tonic-gate space = 0; 1010*7c478bd9Sstevel@tonic-gate if (!bflag && !wflag) { 1011*7c478bd9Sstevel@tonic-gate if (iflag) 1012*7c478bd9Sstevel@tonic-gate if (mbcurmax == 1) { 1013*7c478bd9Sstevel@tonic-gate /* In this case, diff doesn't have to take */ 1014*7c478bd9Sstevel@tonic-gate /* care of multibyte characters. */ 1015*7c478bd9Sstevel@tonic-gate for (shift = 0; (t = getc(f)) != '\n'; 1016*7c478bd9Sstevel@tonic-gate shift += 7) { 1017*7c478bd9Sstevel@tonic-gate if (t == EOF) { 1018*7c478bd9Sstevel@tonic-gate if (shift) { 1019*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1020*7c478bd9Sstevel@tonic-gate gettext("Warning: missing newline at end of file %s\n"), str); 1021*7c478bd9Sstevel@tonic-gate break; 1022*7c478bd9Sstevel@tonic-gate } else 1023*7c478bd9Sstevel@tonic-gate return (0); 1024*7c478bd9Sstevel@tonic-gate } 1025*7c478bd9Sstevel@tonic-gate sum += (isupper(t) ? tolower(t) : t) << 1026*7c478bd9Sstevel@tonic-gate (shift &= HALFMASK); 1027*7c478bd9Sstevel@tonic-gate } 1028*7c478bd9Sstevel@tonic-gate } else { 1029*7c478bd9Sstevel@tonic-gate /* In this case, diff needs to take care of */ 1030*7c478bd9Sstevel@tonic-gate /* multibyte characters. */ 1031*7c478bd9Sstevel@tonic-gate for (shift = 0; 1032*7c478bd9Sstevel@tonic-gate (wt = getbufwchar(filen, &mlen)) != '\n'; 1033*7c478bd9Sstevel@tonic-gate shift += 7) { 1034*7c478bd9Sstevel@tonic-gate if (wt == WEOF) { 1035*7c478bd9Sstevel@tonic-gate if (shift) { 1036*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1037*7c478bd9Sstevel@tonic-gate gettext("Warning: missing newline at end of file %s\n"), str); 1038*7c478bd9Sstevel@tonic-gate break; 1039*7c478bd9Sstevel@tonic-gate } else 1040*7c478bd9Sstevel@tonic-gate return (0); 1041*7c478bd9Sstevel@tonic-gate } 1042*7c478bd9Sstevel@tonic-gate sum += NCCHRTRAN(wt) << 1043*7c478bd9Sstevel@tonic-gate (shift &= HALFMASK); 1044*7c478bd9Sstevel@tonic-gate } 1045*7c478bd9Sstevel@tonic-gate } 1046*7c478bd9Sstevel@tonic-gate else 1047*7c478bd9Sstevel@tonic-gate /* In this case, diff doesn't have to take care of */ 1048*7c478bd9Sstevel@tonic-gate /* multibyte characters. */ 1049*7c478bd9Sstevel@tonic-gate for (shift = 0; (t = getc(f)) != '\n'; shift += 7) { 1050*7c478bd9Sstevel@tonic-gate if (t == EOF) { 1051*7c478bd9Sstevel@tonic-gate if (shift) { 1052*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1053*7c478bd9Sstevel@tonic-gate gettext("Warning: missing newline at end of file %s\n"), str); 1054*7c478bd9Sstevel@tonic-gate break; 1055*7c478bd9Sstevel@tonic-gate } else 1056*7c478bd9Sstevel@tonic-gate return (0); 1057*7c478bd9Sstevel@tonic-gate } 1058*7c478bd9Sstevel@tonic-gate sum += (long)t << (shift &= HALFMASK); 1059*7c478bd9Sstevel@tonic-gate } 1060*7c478bd9Sstevel@tonic-gate } else { 1061*7c478bd9Sstevel@tonic-gate /* In this case, diff needs to take care of */ 1062*7c478bd9Sstevel@tonic-gate /* multibyte characters. */ 1063*7c478bd9Sstevel@tonic-gate for (shift = 0; ; ) { 1064*7c478bd9Sstevel@tonic-gate wt = getbufwchar(filen, &mlen); 1065*7c478bd9Sstevel@tonic-gate 1066*7c478bd9Sstevel@tonic-gate if (wt != '\n' && iswspace(wt)) { 1067*7c478bd9Sstevel@tonic-gate space++; 1068*7c478bd9Sstevel@tonic-gate continue; 1069*7c478bd9Sstevel@tonic-gate } else { 1070*7c478bd9Sstevel@tonic-gate switch (wt) { 1071*7c478bd9Sstevel@tonic-gate case WEOF: 1072*7c478bd9Sstevel@tonic-gate if (shift) { 1073*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1074*7c478bd9Sstevel@tonic-gate gettext("Warning: missing newline at end of file %s\n"), str); 1075*7c478bd9Sstevel@tonic-gate break; 1076*7c478bd9Sstevel@tonic-gate } else 1077*7c478bd9Sstevel@tonic-gate return (0); 1078*7c478bd9Sstevel@tonic-gate default: 1079*7c478bd9Sstevel@tonic-gate if (space && !wflag) { 1080*7c478bd9Sstevel@tonic-gate shift += 7; 1081*7c478bd9Sstevel@tonic-gate space = 0; 1082*7c478bd9Sstevel@tonic-gate } 1083*7c478bd9Sstevel@tonic-gate sum += CHRTRAN(wt) << 1084*7c478bd9Sstevel@tonic-gate (shift &= HALFMASK); 1085*7c478bd9Sstevel@tonic-gate shift += 7; 1086*7c478bd9Sstevel@tonic-gate continue; 1087*7c478bd9Sstevel@tonic-gate case L'\n': 1088*7c478bd9Sstevel@tonic-gate break; 1089*7c478bd9Sstevel@tonic-gate } 1090*7c478bd9Sstevel@tonic-gate } 1091*7c478bd9Sstevel@tonic-gate break; 1092*7c478bd9Sstevel@tonic-gate } 1093*7c478bd9Sstevel@tonic-gate } 1094*7c478bd9Sstevel@tonic-gate return (sum); 1095*7c478bd9Sstevel@tonic-gate } 1096*7c478bd9Sstevel@tonic-gate 1097*7c478bd9Sstevel@tonic-gate 1098*7c478bd9Sstevel@tonic-gate /* dump accumulated "context" diff changes */ 1099*7c478bd9Sstevel@tonic-gate static void 1100*7c478bd9Sstevel@tonic-gate dump_context_vec(void) 1101*7c478bd9Sstevel@tonic-gate { 1102*7c478bd9Sstevel@tonic-gate int a, b, c, d; 1103*7c478bd9Sstevel@tonic-gate char ch; 1104*7c478bd9Sstevel@tonic-gate struct context_vec *cvp = context_vec_start; 1105*7c478bd9Sstevel@tonic-gate int lowa, upb, lowc, upd; 1106*7c478bd9Sstevel@tonic-gate int do_output; 1107*7c478bd9Sstevel@tonic-gate 1108*7c478bd9Sstevel@tonic-gate if (cvp > context_vec_ptr) 1109*7c478bd9Sstevel@tonic-gate return; 1110*7c478bd9Sstevel@tonic-gate 1111*7c478bd9Sstevel@tonic-gate lowa = max(1, cvp->a - context); 1112*7c478bd9Sstevel@tonic-gate upb = min(len[0], context_vec_ptr->b + context); 1113*7c478bd9Sstevel@tonic-gate lowc = max(1, cvp->c - context); 1114*7c478bd9Sstevel@tonic-gate upd = min(len[1], context_vec_ptr->d + context); 1115*7c478bd9Sstevel@tonic-gate 1116*7c478bd9Sstevel@tonic-gate if (uflag) { 1117*7c478bd9Sstevel@tonic-gate (void) printf("@@ -%d,%d +%d,%d @@\n", 1118*7c478bd9Sstevel@tonic-gate lowa, upb - lowa + 1, 1119*7c478bd9Sstevel@tonic-gate lowc, upd - lowc + 1); 1120*7c478bd9Sstevel@tonic-gate } else { 1121*7c478bd9Sstevel@tonic-gate (void) printf("***************\n*** "); 1122*7c478bd9Sstevel@tonic-gate range(lowa, upb, ","); 1123*7c478bd9Sstevel@tonic-gate (void) printf(" ****\n"); 1124*7c478bd9Sstevel@tonic-gate } 1125*7c478bd9Sstevel@tonic-gate 1126*7c478bd9Sstevel@tonic-gate /* 1127*7c478bd9Sstevel@tonic-gate * output changes to the "old" file. The first loop suppresses 1128*7c478bd9Sstevel@tonic-gate * output if there were no changes to the "old" file (we'll see 1129*7c478bd9Sstevel@tonic-gate * the "old" lines as context in the "new" list). 1130*7c478bd9Sstevel@tonic-gate */ 1131*7c478bd9Sstevel@tonic-gate if (uflag) 1132*7c478bd9Sstevel@tonic-gate do_output = 1; 1133*7c478bd9Sstevel@tonic-gate else 1134*7c478bd9Sstevel@tonic-gate for (do_output = 0; cvp <= context_vec_ptr; cvp++) 1135*7c478bd9Sstevel@tonic-gate if (cvp->a <= cvp->b) { 1136*7c478bd9Sstevel@tonic-gate cvp = context_vec_start; 1137*7c478bd9Sstevel@tonic-gate do_output++; 1138*7c478bd9Sstevel@tonic-gate break; 1139*7c478bd9Sstevel@tonic-gate } 1140*7c478bd9Sstevel@tonic-gate 1141*7c478bd9Sstevel@tonic-gate if (do_output) { 1142*7c478bd9Sstevel@tonic-gate while (cvp <= context_vec_ptr) { 1143*7c478bd9Sstevel@tonic-gate a = cvp->a; b = cvp->b; c = cvp->c; d = cvp->d; 1144*7c478bd9Sstevel@tonic-gate 1145*7c478bd9Sstevel@tonic-gate if (a <= b && c <= d) 1146*7c478bd9Sstevel@tonic-gate ch = 'c'; 1147*7c478bd9Sstevel@tonic-gate else 1148*7c478bd9Sstevel@tonic-gate ch = (a <= b) ? 'd' : 'a'; 1149*7c478bd9Sstevel@tonic-gate 1150*7c478bd9Sstevel@tonic-gate if (ch == 'a') { 1151*7c478bd9Sstevel@tonic-gate /* The last argument should not affect */ 1152*7c478bd9Sstevel@tonic-gate /* the behavior of fetch() */ 1153*7c478bd9Sstevel@tonic-gate fetch(ixold, lowa, b, 0, uflag ? " " : " ", 1); 1154*7c478bd9Sstevel@tonic-gate if (uflag) 1155*7c478bd9Sstevel@tonic-gate fetch(ixnew, c, d, 1, "+", 0); 1156*7c478bd9Sstevel@tonic-gate } else if (ch == 'd') { 1157*7c478bd9Sstevel@tonic-gate fetch(ixold, lowa, a - 1, 0, uflag ? " " : 1158*7c478bd9Sstevel@tonic-gate " ", 1); 1159*7c478bd9Sstevel@tonic-gate fetch(ixold, a, b, 0, uflag ? "-" : "- ", 1); 1160*7c478bd9Sstevel@tonic-gate } else { 1161*7c478bd9Sstevel@tonic-gate /* The last argument should not affect */ 1162*7c478bd9Sstevel@tonic-gate /* the behavior of fetch() */ 1163*7c478bd9Sstevel@tonic-gate fetch(ixold, lowa, a-1, 0, uflag ? " " : " ", 1164*7c478bd9Sstevel@tonic-gate 1); 1165*7c478bd9Sstevel@tonic-gate if (uflag) { 1166*7c478bd9Sstevel@tonic-gate fetch(ixold, a, b, 0, "-", 1); 1167*7c478bd9Sstevel@tonic-gate fetch(ixnew, c, d, 1, "+", 0); 1168*7c478bd9Sstevel@tonic-gate } else 1169*7c478bd9Sstevel@tonic-gate fetch(ixold, a, b, 0, "! ", 1); 1170*7c478bd9Sstevel@tonic-gate } 1171*7c478bd9Sstevel@tonic-gate lowa = b + 1; 1172*7c478bd9Sstevel@tonic-gate cvp++; 1173*7c478bd9Sstevel@tonic-gate } 1174*7c478bd9Sstevel@tonic-gate /* The last argument should not affect the behavior */ 1175*7c478bd9Sstevel@tonic-gate /* of fetch() */ 1176*7c478bd9Sstevel@tonic-gate fetch(ixold, b+1, upb, 0, uflag ? " " : " ", 1); 1177*7c478bd9Sstevel@tonic-gate } 1178*7c478bd9Sstevel@tonic-gate 1179*7c478bd9Sstevel@tonic-gate if (uflag) { 1180*7c478bd9Sstevel@tonic-gate context_vec_ptr = context_vec_start - 1; 1181*7c478bd9Sstevel@tonic-gate return; 1182*7c478bd9Sstevel@tonic-gate } 1183*7c478bd9Sstevel@tonic-gate 1184*7c478bd9Sstevel@tonic-gate /* output changes to the "new" file */ 1185*7c478bd9Sstevel@tonic-gate (void) printf("--- "); 1186*7c478bd9Sstevel@tonic-gate range(lowc, upd, ","); 1187*7c478bd9Sstevel@tonic-gate (void) printf(" ----\n"); 1188*7c478bd9Sstevel@tonic-gate 1189*7c478bd9Sstevel@tonic-gate do_output = 0; 1190*7c478bd9Sstevel@tonic-gate for (cvp = context_vec_start; cvp <= context_vec_ptr; cvp++) 1191*7c478bd9Sstevel@tonic-gate if (cvp->c <= cvp->d) { 1192*7c478bd9Sstevel@tonic-gate cvp = context_vec_start; 1193*7c478bd9Sstevel@tonic-gate do_output++; 1194*7c478bd9Sstevel@tonic-gate break; 1195*7c478bd9Sstevel@tonic-gate } 1196*7c478bd9Sstevel@tonic-gate 1197*7c478bd9Sstevel@tonic-gate if (do_output) { 1198*7c478bd9Sstevel@tonic-gate while (cvp <= context_vec_ptr) { 1199*7c478bd9Sstevel@tonic-gate a = cvp->a; b = cvp->b; c = cvp->c; d = cvp->d; 1200*7c478bd9Sstevel@tonic-gate 1201*7c478bd9Sstevel@tonic-gate if (a <= b && c <= d) 1202*7c478bd9Sstevel@tonic-gate ch = 'c'; 1203*7c478bd9Sstevel@tonic-gate else 1204*7c478bd9Sstevel@tonic-gate ch = (a <= b) ? 'd' : 'a'; 1205*7c478bd9Sstevel@tonic-gate 1206*7c478bd9Sstevel@tonic-gate if (ch == 'd') 1207*7c478bd9Sstevel@tonic-gate /* The last argument should not affect */ 1208*7c478bd9Sstevel@tonic-gate /* the behavior of fetch() */ 1209*7c478bd9Sstevel@tonic-gate fetch(ixnew, lowc, d, 1, " ", 0); 1210*7c478bd9Sstevel@tonic-gate else { 1211*7c478bd9Sstevel@tonic-gate /* The last argument should not affect */ 1212*7c478bd9Sstevel@tonic-gate /* the behavior of fetch() */ 1213*7c478bd9Sstevel@tonic-gate fetch(ixnew, lowc, c - 1, 1, " ", 0); 1214*7c478bd9Sstevel@tonic-gate fetch(ixnew, c, d, 1, 1215*7c478bd9Sstevel@tonic-gate ch == 'c' ? "! " : "+ ", 0); 1216*7c478bd9Sstevel@tonic-gate } 1217*7c478bd9Sstevel@tonic-gate lowc = d + 1; 1218*7c478bd9Sstevel@tonic-gate cvp++; 1219*7c478bd9Sstevel@tonic-gate } 1220*7c478bd9Sstevel@tonic-gate /* The last argument should not affect the behavior */ 1221*7c478bd9Sstevel@tonic-gate /* of fetch() */ 1222*7c478bd9Sstevel@tonic-gate fetch(ixnew, d + 1, upd, 1, " ", 0); 1223*7c478bd9Sstevel@tonic-gate } 1224*7c478bd9Sstevel@tonic-gate context_vec_ptr = context_vec_start - 1; 1225*7c478bd9Sstevel@tonic-gate } 1226*7c478bd9Sstevel@tonic-gate 1227*7c478bd9Sstevel@tonic-gate 1228*7c478bd9Sstevel@tonic-gate 1229*7c478bd9Sstevel@tonic-gate /* 1230*7c478bd9Sstevel@tonic-gate * diff - directory comparison 1231*7c478bd9Sstevel@tonic-gate */ 1232*7c478bd9Sstevel@tonic-gate 1233*7c478bd9Sstevel@tonic-gate struct dir *setupdir(); 1234*7c478bd9Sstevel@tonic-gate int header; 1235*7c478bd9Sstevel@tonic-gate char title[2 * BUFSIZ], *etitle; 1236*7c478bd9Sstevel@tonic-gate 1237*7c478bd9Sstevel@tonic-gate static void 1238*7c478bd9Sstevel@tonic-gate diffdir(char **argv) 1239*7c478bd9Sstevel@tonic-gate { 1240*7c478bd9Sstevel@tonic-gate struct dir *d1, *d2; 1241*7c478bd9Sstevel@tonic-gate struct dir *dir1, *dir2; 1242*7c478bd9Sstevel@tonic-gate int i; 1243*7c478bd9Sstevel@tonic-gate int cmp; 1244*7c478bd9Sstevel@tonic-gate int result, dirstatus; 1245*7c478bd9Sstevel@tonic-gate 1246*7c478bd9Sstevel@tonic-gate if (opt == D_IFDEF) 1247*7c478bd9Sstevel@tonic-gate error(gettext("cannot specify -D with directories")); 1248*7c478bd9Sstevel@tonic-gate 1249*7c478bd9Sstevel@tonic-gate if (opt == D_EDIT && (sflag || lflag)) { 1250*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "diff: "); 1251*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 1252*7c478bd9Sstevel@tonic-gate "warning: should not give -s or -l with -e\n")); 1253*7c478bd9Sstevel@tonic-gate } 1254*7c478bd9Sstevel@tonic-gate dirstatus = 0; 1255*7c478bd9Sstevel@tonic-gate title[0] = 0; 1256*7c478bd9Sstevel@tonic-gate (void) strcpy(title, "diff "); 1257*7c478bd9Sstevel@tonic-gate for (i = 1; diffargv[i + 2]; i++) { 1258*7c478bd9Sstevel@tonic-gate if (strcmp(diffargv[i], "-") == 0) { 1259*7c478bd9Sstevel@tonic-gate continue; /* Skip -S and its argument */ 1260*7c478bd9Sstevel@tonic-gate } 1261*7c478bd9Sstevel@tonic-gate (void) strcat(title, diffargv[i]); 1262*7c478bd9Sstevel@tonic-gate (void) strcat(title, " "); 1263*7c478bd9Sstevel@tonic-gate } 1264*7c478bd9Sstevel@tonic-gate for (etitle = title; *etitle; etitle++) 1265*7c478bd9Sstevel@tonic-gate ; 1266*7c478bd9Sstevel@tonic-gate setfile(&file1, &efile1, file1); 1267*7c478bd9Sstevel@tonic-gate setfile(&file2, &efile2, file2); 1268*7c478bd9Sstevel@tonic-gate argv[0] = file1; 1269*7c478bd9Sstevel@tonic-gate argv[1] = file2; 1270*7c478bd9Sstevel@tonic-gate dir1 = setupdir(file1); 1271*7c478bd9Sstevel@tonic-gate dir2 = setupdir(file2); 1272*7c478bd9Sstevel@tonic-gate d1 = dir1; d2 = dir2; 1273*7c478bd9Sstevel@tonic-gate while (d1->d_entry != 0 || d2->d_entry != 0) { 1274*7c478bd9Sstevel@tonic-gate if (d1->d_entry && useless(d1->d_entry)) { 1275*7c478bd9Sstevel@tonic-gate d1++; 1276*7c478bd9Sstevel@tonic-gate continue; 1277*7c478bd9Sstevel@tonic-gate } 1278*7c478bd9Sstevel@tonic-gate if (d2->d_entry && useless(d2->d_entry)) { 1279*7c478bd9Sstevel@tonic-gate d2++; 1280*7c478bd9Sstevel@tonic-gate continue; 1281*7c478bd9Sstevel@tonic-gate } 1282*7c478bd9Sstevel@tonic-gate if (d1->d_entry == 0) 1283*7c478bd9Sstevel@tonic-gate cmp = 1; 1284*7c478bd9Sstevel@tonic-gate else if (d2->d_entry == 0) 1285*7c478bd9Sstevel@tonic-gate cmp = -1; 1286*7c478bd9Sstevel@tonic-gate else 1287*7c478bd9Sstevel@tonic-gate cmp = strcmp(d1->d_entry, d2->d_entry); 1288*7c478bd9Sstevel@tonic-gate if (cmp < 0) { 1289*7c478bd9Sstevel@tonic-gate if (lflag) 1290*7c478bd9Sstevel@tonic-gate d1->d_flags |= ONLY; 1291*7c478bd9Sstevel@tonic-gate else if (opt == 0 || opt == 2) 1292*7c478bd9Sstevel@tonic-gate only(d1, 1); 1293*7c478bd9Sstevel@tonic-gate d1++; 1294*7c478bd9Sstevel@tonic-gate if (dirstatus == 0) 1295*7c478bd9Sstevel@tonic-gate dirstatus = 1; 1296*7c478bd9Sstevel@tonic-gate } else if (cmp == 0) { 1297*7c478bd9Sstevel@tonic-gate result = compare(d1); 1298*7c478bd9Sstevel@tonic-gate if (result > dirstatus) 1299*7c478bd9Sstevel@tonic-gate dirstatus = result; 1300*7c478bd9Sstevel@tonic-gate d1++; 1301*7c478bd9Sstevel@tonic-gate d2++; 1302*7c478bd9Sstevel@tonic-gate } else { 1303*7c478bd9Sstevel@tonic-gate if (lflag) 1304*7c478bd9Sstevel@tonic-gate d2->d_flags |= ONLY; 1305*7c478bd9Sstevel@tonic-gate else if (opt == 0 || opt == 2) 1306*7c478bd9Sstevel@tonic-gate only(d2, 2); 1307*7c478bd9Sstevel@tonic-gate d2++; 1308*7c478bd9Sstevel@tonic-gate if (dirstatus == 0) 1309*7c478bd9Sstevel@tonic-gate dirstatus = 1; 1310*7c478bd9Sstevel@tonic-gate } 1311*7c478bd9Sstevel@tonic-gate } 1312*7c478bd9Sstevel@tonic-gate if (lflag) { 1313*7c478bd9Sstevel@tonic-gate scanpr(dir1, ONLY, 1314*7c478bd9Sstevel@tonic-gate gettext("Only in %.*s"), file1, efile1, 0, 0); 1315*7c478bd9Sstevel@tonic-gate scanpr(dir2, ONLY, 1316*7c478bd9Sstevel@tonic-gate gettext("Only in %.*s"), file2, efile2, 0, 0); 1317*7c478bd9Sstevel@tonic-gate scanpr(dir1, SAME, 1318*7c478bd9Sstevel@tonic-gate gettext("Common identical files in %.*s and %.*s"), 1319*7c478bd9Sstevel@tonic-gate file1, efile1, file2, efile2); 1320*7c478bd9Sstevel@tonic-gate scanpr(dir1, DIFFER, 1321*7c478bd9Sstevel@tonic-gate gettext("Binary files which differ in %.*s and %.*s"), 1322*7c478bd9Sstevel@tonic-gate file1, efile1, file2, efile2); 1323*7c478bd9Sstevel@tonic-gate scanpr(dir1, DIRECT, 1324*7c478bd9Sstevel@tonic-gate gettext("Common subdirectories of %.*s and %.*s"), 1325*7c478bd9Sstevel@tonic-gate file1, efile1, file2, efile2); 1326*7c478bd9Sstevel@tonic-gate } 1327*7c478bd9Sstevel@tonic-gate if (rflag) { 1328*7c478bd9Sstevel@tonic-gate if (header && lflag) 1329*7c478bd9Sstevel@tonic-gate (void) printf("\f"); 1330*7c478bd9Sstevel@tonic-gate for (d1 = dir1; d1->d_entry; d1++) { 1331*7c478bd9Sstevel@tonic-gate if ((d1->d_flags & DIRECT) == 0) 1332*7c478bd9Sstevel@tonic-gate continue; 1333*7c478bd9Sstevel@tonic-gate (void) strcpy(efile1, d1->d_entry); 1334*7c478bd9Sstevel@tonic-gate (void) strcpy(efile2, d1->d_entry); 1335*7c478bd9Sstevel@tonic-gate result = calldiff((char *)0); 1336*7c478bd9Sstevel@tonic-gate if (result > dirstatus) 1337*7c478bd9Sstevel@tonic-gate dirstatus = result; 1338*7c478bd9Sstevel@tonic-gate } 1339*7c478bd9Sstevel@tonic-gate } 1340*7c478bd9Sstevel@tonic-gate status = dirstatus; 1341*7c478bd9Sstevel@tonic-gate } 1342*7c478bd9Sstevel@tonic-gate 1343*7c478bd9Sstevel@tonic-gate static void 1344*7c478bd9Sstevel@tonic-gate setfile(char **fpp, char **epp, char *file) 1345*7c478bd9Sstevel@tonic-gate { 1346*7c478bd9Sstevel@tonic-gate char *cp; 1347*7c478bd9Sstevel@tonic-gate 1348*7c478bd9Sstevel@tonic-gate *fpp = (char *)malloc(BUFSIZ); 1349*7c478bd9Sstevel@tonic-gate if (*fpp == 0) { 1350*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "diff: "); 1351*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("out of memory\n")); 1352*7c478bd9Sstevel@tonic-gate exit(1); 1353*7c478bd9Sstevel@tonic-gate } 1354*7c478bd9Sstevel@tonic-gate (void) strcpy(*fpp, file); 1355*7c478bd9Sstevel@tonic-gate for (cp = *fpp; *cp; cp++) 1356*7c478bd9Sstevel@tonic-gate continue; 1357*7c478bd9Sstevel@tonic-gate *cp++ = '/'; 1358*7c478bd9Sstevel@tonic-gate *cp = 0; 1359*7c478bd9Sstevel@tonic-gate *epp = cp; 1360*7c478bd9Sstevel@tonic-gate } 1361*7c478bd9Sstevel@tonic-gate 1362*7c478bd9Sstevel@tonic-gate static void 1363*7c478bd9Sstevel@tonic-gate scanpr(struct dir *dp, int test, 1364*7c478bd9Sstevel@tonic-gate char *title, char *file1, char *efile1, char *file2, char *efile2) 1365*7c478bd9Sstevel@tonic-gate { 1366*7c478bd9Sstevel@tonic-gate int titled = 0; 1367*7c478bd9Sstevel@tonic-gate 1368*7c478bd9Sstevel@tonic-gate for (; dp->d_entry; dp++) { 1369*7c478bd9Sstevel@tonic-gate if ((dp->d_flags & test) == 0) 1370*7c478bd9Sstevel@tonic-gate continue; 1371*7c478bd9Sstevel@tonic-gate if (titled == 0) { 1372*7c478bd9Sstevel@tonic-gate if (header == 0) 1373*7c478bd9Sstevel@tonic-gate header = 1; 1374*7c478bd9Sstevel@tonic-gate else 1375*7c478bd9Sstevel@tonic-gate (void) printf("\n"); 1376*7c478bd9Sstevel@tonic-gate (void) printf(title, 1377*7c478bd9Sstevel@tonic-gate efile1 - file1 - 1, file1, 1378*7c478bd9Sstevel@tonic-gate efile2 - file2 - 1, file2); 1379*7c478bd9Sstevel@tonic-gate (void) printf(":\n"); 1380*7c478bd9Sstevel@tonic-gate titled = 1; 1381*7c478bd9Sstevel@tonic-gate } 1382*7c478bd9Sstevel@tonic-gate (void) printf("\t%s\n", dp->d_entry); 1383*7c478bd9Sstevel@tonic-gate } 1384*7c478bd9Sstevel@tonic-gate } 1385*7c478bd9Sstevel@tonic-gate 1386*7c478bd9Sstevel@tonic-gate static void 1387*7c478bd9Sstevel@tonic-gate only(struct dir *dp, int which) 1388*7c478bd9Sstevel@tonic-gate { 1389*7c478bd9Sstevel@tonic-gate char *file = which == 1 ? file1 : file2; 1390*7c478bd9Sstevel@tonic-gate char *efile = which == 1 ? efile1 : efile2; 1391*7c478bd9Sstevel@tonic-gate 1392*7c478bd9Sstevel@tonic-gate (void) printf(gettext("Only in %.*s: %s\n"), efile - file - 1, file, 1393*7c478bd9Sstevel@tonic-gate dp->d_entry); 1394*7c478bd9Sstevel@tonic-gate } 1395*7c478bd9Sstevel@tonic-gate 1396*7c478bd9Sstevel@tonic-gate int entcmp(); 1397*7c478bd9Sstevel@tonic-gate 1398*7c478bd9Sstevel@tonic-gate static struct dir * 1399*7c478bd9Sstevel@tonic-gate setupdir(char *cp) 1400*7c478bd9Sstevel@tonic-gate { 1401*7c478bd9Sstevel@tonic-gate struct dir *dp = 0, *ep; 1402*7c478bd9Sstevel@tonic-gate struct dirent64 *rp; 1403*7c478bd9Sstevel@tonic-gate int nitems; 1404*7c478bd9Sstevel@tonic-gate int size; 1405*7c478bd9Sstevel@tonic-gate DIR *dirp; 1406*7c478bd9Sstevel@tonic-gate 1407*7c478bd9Sstevel@tonic-gate dirp = opendir(cp); 1408*7c478bd9Sstevel@tonic-gate if (dirp == NULL) { 1409*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "diff: "); 1410*7c478bd9Sstevel@tonic-gate perror(cp); 1411*7c478bd9Sstevel@tonic-gate done(); 1412*7c478bd9Sstevel@tonic-gate } 1413*7c478bd9Sstevel@tonic-gate nitems = 0; 1414*7c478bd9Sstevel@tonic-gate dp = (struct dir *)malloc(sizeof (struct dir)); 1415*7c478bd9Sstevel@tonic-gate if (dp == 0) 1416*7c478bd9Sstevel@tonic-gate error(gettext(NO_MEM_ERR)); 1417*7c478bd9Sstevel@tonic-gate 1418*7c478bd9Sstevel@tonic-gate while (rp = readdir64(dirp)) { 1419*7c478bd9Sstevel@tonic-gate ep = &dp[nitems++]; 1420*7c478bd9Sstevel@tonic-gate ep->d_reclen = rp->d_reclen; 1421*7c478bd9Sstevel@tonic-gate ep->d_entry = 0; 1422*7c478bd9Sstevel@tonic-gate ep->d_flags = 0; 1423*7c478bd9Sstevel@tonic-gate size = strlen(rp->d_name); 1424*7c478bd9Sstevel@tonic-gate if (size > 0) { 1425*7c478bd9Sstevel@tonic-gate ep->d_entry = (char *)malloc(size + 1); 1426*7c478bd9Sstevel@tonic-gate if (ep->d_entry == 0) 1427*7c478bd9Sstevel@tonic-gate error(gettext(NO_MEM_ERR)); 1428*7c478bd9Sstevel@tonic-gate 1429*7c478bd9Sstevel@tonic-gate (void) strcpy(ep->d_entry, rp->d_name); 1430*7c478bd9Sstevel@tonic-gate } 1431*7c478bd9Sstevel@tonic-gate dp = (struct dir *)realloc((char *)dp, 1432*7c478bd9Sstevel@tonic-gate (nitems + 1) * sizeof (struct dir)); 1433*7c478bd9Sstevel@tonic-gate if (dp == 0) 1434*7c478bd9Sstevel@tonic-gate error(gettext(NO_MEM_ERR)); 1435*7c478bd9Sstevel@tonic-gate } 1436*7c478bd9Sstevel@tonic-gate dp[nitems].d_entry = 0; /* delimiter */ 1437*7c478bd9Sstevel@tonic-gate (void) closedir(dirp); 1438*7c478bd9Sstevel@tonic-gate qsort(dp, nitems, sizeof (struct dir), 1439*7c478bd9Sstevel@tonic-gate (int (*)(const void *, const void *))entcmp); 1440*7c478bd9Sstevel@tonic-gate return (dp); 1441*7c478bd9Sstevel@tonic-gate } 1442*7c478bd9Sstevel@tonic-gate 1443*7c478bd9Sstevel@tonic-gate static int 1444*7c478bd9Sstevel@tonic-gate entcmp(struct dir *d1, struct dir *d2) 1445*7c478bd9Sstevel@tonic-gate { 1446*7c478bd9Sstevel@tonic-gate return (strcmp(d1->d_entry, d2->d_entry)); 1447*7c478bd9Sstevel@tonic-gate } 1448*7c478bd9Sstevel@tonic-gate 1449*7c478bd9Sstevel@tonic-gate static int 1450*7c478bd9Sstevel@tonic-gate compare(struct dir *dp) 1451*7c478bd9Sstevel@tonic-gate { 1452*7c478bd9Sstevel@tonic-gate int i, j; 1453*7c478bd9Sstevel@tonic-gate int f1 = -1, f2 = -1; 1454*7c478bd9Sstevel@tonic-gate mode_t fmt1, fmt2; 1455*7c478bd9Sstevel@tonic-gate struct stat stb1, stb2; 1456*7c478bd9Sstevel@tonic-gate char buf1[BUFSIZ], buf2[BUFSIZ]; 1457*7c478bd9Sstevel@tonic-gate int result; 1458*7c478bd9Sstevel@tonic-gate 1459*7c478bd9Sstevel@tonic-gate (void) strcpy(efile1, dp->d_entry); 1460*7c478bd9Sstevel@tonic-gate (void) strcpy(efile2, dp->d_entry); 1461*7c478bd9Sstevel@tonic-gate 1462*7c478bd9Sstevel@tonic-gate if (stat(file1, &stb1) == -1) { 1463*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "diff: "); 1464*7c478bd9Sstevel@tonic-gate perror(file1); 1465*7c478bd9Sstevel@tonic-gate return (2); 1466*7c478bd9Sstevel@tonic-gate } 1467*7c478bd9Sstevel@tonic-gate if (stat(file2, &stb2) == -1) { 1468*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "diff: "); 1469*7c478bd9Sstevel@tonic-gate perror(file2); 1470*7c478bd9Sstevel@tonic-gate return (2); 1471*7c478bd9Sstevel@tonic-gate } 1472*7c478bd9Sstevel@tonic-gate 1473*7c478bd9Sstevel@tonic-gate fmt1 = stb1.st_mode & S_IFMT; 1474*7c478bd9Sstevel@tonic-gate fmt2 = stb2.st_mode & S_IFMT; 1475*7c478bd9Sstevel@tonic-gate 1476*7c478bd9Sstevel@tonic-gate if (fmt1 == S_IFREG) { 1477*7c478bd9Sstevel@tonic-gate f1 = open(file1, O_RDONLY); 1478*7c478bd9Sstevel@tonic-gate if (f1 < 0) { 1479*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "diff: "); 1480*7c478bd9Sstevel@tonic-gate perror(file1); 1481*7c478bd9Sstevel@tonic-gate return (2); 1482*7c478bd9Sstevel@tonic-gate } 1483*7c478bd9Sstevel@tonic-gate } 1484*7c478bd9Sstevel@tonic-gate 1485*7c478bd9Sstevel@tonic-gate if (fmt2 == S_IFREG) { 1486*7c478bd9Sstevel@tonic-gate f2 = open(file2, O_RDONLY); 1487*7c478bd9Sstevel@tonic-gate if (f2 < 0) { 1488*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "diff: "); 1489*7c478bd9Sstevel@tonic-gate perror(file2); 1490*7c478bd9Sstevel@tonic-gate (void) close(f1); 1491*7c478bd9Sstevel@tonic-gate return (2); 1492*7c478bd9Sstevel@tonic-gate } 1493*7c478bd9Sstevel@tonic-gate } 1494*7c478bd9Sstevel@tonic-gate 1495*7c478bd9Sstevel@tonic-gate if (fmt1 != S_IFREG || fmt2 != S_IFREG) { 1496*7c478bd9Sstevel@tonic-gate if (fmt1 == fmt2) { 1497*7c478bd9Sstevel@tonic-gate switch (fmt1) { 1498*7c478bd9Sstevel@tonic-gate 1499*7c478bd9Sstevel@tonic-gate case S_IFDIR: 1500*7c478bd9Sstevel@tonic-gate dp->d_flags = DIRECT; 1501*7c478bd9Sstevel@tonic-gate if (lflag || opt == D_EDIT) 1502*7c478bd9Sstevel@tonic-gate goto closem; 1503*7c478bd9Sstevel@tonic-gate (void) printf(gettext( 1504*7c478bd9Sstevel@tonic-gate "Common subdirectories: %s and %s\n"), 1505*7c478bd9Sstevel@tonic-gate file1, file2); 1506*7c478bd9Sstevel@tonic-gate goto closem; 1507*7c478bd9Sstevel@tonic-gate 1508*7c478bd9Sstevel@tonic-gate case S_IFCHR: 1509*7c478bd9Sstevel@tonic-gate case S_IFBLK: 1510*7c478bd9Sstevel@tonic-gate if (stb1.st_rdev == stb2.st_rdev) 1511*7c478bd9Sstevel@tonic-gate goto same; 1512*7c478bd9Sstevel@tonic-gate (void) printf(gettext( 1513*7c478bd9Sstevel@tonic-gate "Special files %s and %s differ\n"), 1514*7c478bd9Sstevel@tonic-gate file1, file2); 1515*7c478bd9Sstevel@tonic-gate break; 1516*7c478bd9Sstevel@tonic-gate 1517*7c478bd9Sstevel@tonic-gate case S_IFLNK: 1518*7c478bd9Sstevel@tonic-gate if ((i = readlink(file1, buf1, BUFSIZ)) == -1) { 1519*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 1520*7c478bd9Sstevel@tonic-gate "diff: cannot read link\n")); 1521*7c478bd9Sstevel@tonic-gate return (2); 1522*7c478bd9Sstevel@tonic-gate } 1523*7c478bd9Sstevel@tonic-gate 1524*7c478bd9Sstevel@tonic-gate if ((j = readlink(file2, buf2, BUFSIZ)) == -1) { 1525*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 1526*7c478bd9Sstevel@tonic-gate "diff: cannot read link\n")); 1527*7c478bd9Sstevel@tonic-gate return (2); 1528*7c478bd9Sstevel@tonic-gate } 1529*7c478bd9Sstevel@tonic-gate 1530*7c478bd9Sstevel@tonic-gate if (i == j) { 1531*7c478bd9Sstevel@tonic-gate if (strncmp(buf1, buf2, i) == 0) 1532*7c478bd9Sstevel@tonic-gate goto same; 1533*7c478bd9Sstevel@tonic-gate } 1534*7c478bd9Sstevel@tonic-gate 1535*7c478bd9Sstevel@tonic-gate (void) printf(gettext( 1536*7c478bd9Sstevel@tonic-gate "Symbolic links %s and %s differ\n"), 1537*7c478bd9Sstevel@tonic-gate file1, file2); 1538*7c478bd9Sstevel@tonic-gate break; 1539*7c478bd9Sstevel@tonic-gate 1540*7c478bd9Sstevel@tonic-gate case S_IFIFO: 1541*7c478bd9Sstevel@tonic-gate if (stb1.st_ino == stb2.st_ino) 1542*7c478bd9Sstevel@tonic-gate goto same; 1543*7c478bd9Sstevel@tonic-gate (void) printf(gettext( 1544*7c478bd9Sstevel@tonic-gate "Named pipes %s and %s differ\n"), 1545*7c478bd9Sstevel@tonic-gate file1, file2); 1546*7c478bd9Sstevel@tonic-gate break; 1547*7c478bd9Sstevel@tonic-gate } 1548*7c478bd9Sstevel@tonic-gate } else { 1549*7c478bd9Sstevel@tonic-gate if (lflag) 1550*7c478bd9Sstevel@tonic-gate dp->d_flags |= DIFFER; 1551*7c478bd9Sstevel@tonic-gate else if (opt == D_NORMAL || opt == D_CONTEXT) { 1552*7c478bd9Sstevel@tonic-gate /* 1553*7c478bd9Sstevel@tonic-gate * TRANSLATION_NOTE 1554*7c478bd9Sstevel@tonic-gate * The second and fourth parameters will take the gettext'ed string 1555*7c478bd9Sstevel@tonic-gate * of one of the following: 1556*7c478bd9Sstevel@tonic-gate * a directory 1557*7c478bd9Sstevel@tonic-gate * a character special file 1558*7c478bd9Sstevel@tonic-gate * a block special file 1559*7c478bd9Sstevel@tonic-gate * a plain file 1560*7c478bd9Sstevel@tonic-gate * a named pipe 1561*7c478bd9Sstevel@tonic-gate * a socket 1562*7c478bd9Sstevel@tonic-gate * a door 1563*7c478bd9Sstevel@tonic-gate * an event port 1564*7c478bd9Sstevel@tonic-gate * an unknown type 1565*7c478bd9Sstevel@tonic-gate */ 1566*7c478bd9Sstevel@tonic-gate (void) printf( 1567*7c478bd9Sstevel@tonic-gate gettext("File %s is %s while file %s is %s\n"), 1568*7c478bd9Sstevel@tonic-gate file1, pfiletype(fmt1), 1569*7c478bd9Sstevel@tonic-gate file2, pfiletype(fmt2)); 1570*7c478bd9Sstevel@tonic-gate } 1571*7c478bd9Sstevel@tonic-gate } 1572*7c478bd9Sstevel@tonic-gate (void) close(f1); (void) close(f2); 1573*7c478bd9Sstevel@tonic-gate return (1); 1574*7c478bd9Sstevel@tonic-gate } 1575*7c478bd9Sstevel@tonic-gate if (stb1.st_size != stb2.st_size) 1576*7c478bd9Sstevel@tonic-gate goto notsame; 1577*7c478bd9Sstevel@tonic-gate for (;;) { 1578*7c478bd9Sstevel@tonic-gate i = read(f1, buf1, BUFSIZ); 1579*7c478bd9Sstevel@tonic-gate j = read(f2, buf2, BUFSIZ); 1580*7c478bd9Sstevel@tonic-gate if (i < 0 || j < 0) { 1581*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "diff: "); 1582*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Error reading ")); 1583*7c478bd9Sstevel@tonic-gate perror(i < 0 ? file1: file2); 1584*7c478bd9Sstevel@tonic-gate (void) close(f1); (void) close(f2); 1585*7c478bd9Sstevel@tonic-gate return (2); 1586*7c478bd9Sstevel@tonic-gate } 1587*7c478bd9Sstevel@tonic-gate if (i != j) 1588*7c478bd9Sstevel@tonic-gate goto notsame; 1589*7c478bd9Sstevel@tonic-gate if (i == 0 && j == 0) 1590*7c478bd9Sstevel@tonic-gate goto same; 1591*7c478bd9Sstevel@tonic-gate for (j = 0; j < i; j++) 1592*7c478bd9Sstevel@tonic-gate if (buf1[j] != buf2[j]) 1593*7c478bd9Sstevel@tonic-gate goto notsame; 1594*7c478bd9Sstevel@tonic-gate } 1595*7c478bd9Sstevel@tonic-gate same: 1596*7c478bd9Sstevel@tonic-gate if (sflag == 0) 1597*7c478bd9Sstevel@tonic-gate goto closem; 1598*7c478bd9Sstevel@tonic-gate if (lflag) 1599*7c478bd9Sstevel@tonic-gate dp->d_flags = SAME; 1600*7c478bd9Sstevel@tonic-gate else 1601*7c478bd9Sstevel@tonic-gate (void) printf(gettext("Files %s and %s are identical\n"), 1602*7c478bd9Sstevel@tonic-gate file1, file2); 1603*7c478bd9Sstevel@tonic-gate 1604*7c478bd9Sstevel@tonic-gate closem: 1605*7c478bd9Sstevel@tonic-gate (void) close(f1); (void) close(f2); 1606*7c478bd9Sstevel@tonic-gate return (0); 1607*7c478bd9Sstevel@tonic-gate 1608*7c478bd9Sstevel@tonic-gate notsame: 1609*7c478bd9Sstevel@tonic-gate if (binary(f1) || binary(f2)) { 1610*7c478bd9Sstevel@tonic-gate if (lflag) 1611*7c478bd9Sstevel@tonic-gate dp->d_flags |= DIFFER; 1612*7c478bd9Sstevel@tonic-gate else if (opt == D_NORMAL || opt == D_CONTEXT) 1613*7c478bd9Sstevel@tonic-gate (void) printf( 1614*7c478bd9Sstevel@tonic-gate gettext("Binary files %s and %s differ\n"), 1615*7c478bd9Sstevel@tonic-gate file1, file2); 1616*7c478bd9Sstevel@tonic-gate (void) close(f1); (void) close(f2); 1617*7c478bd9Sstevel@tonic-gate return (1); 1618*7c478bd9Sstevel@tonic-gate } 1619*7c478bd9Sstevel@tonic-gate (void) close(f1); (void) close(f2); 1620*7c478bd9Sstevel@tonic-gate anychange = 1; 1621*7c478bd9Sstevel@tonic-gate if (lflag) { 1622*7c478bd9Sstevel@tonic-gate result = calldiff(title); 1623*7c478bd9Sstevel@tonic-gate } else { 1624*7c478bd9Sstevel@tonic-gate if (opt == D_EDIT) 1625*7c478bd9Sstevel@tonic-gate (void) printf("ed - %s << '-*-END-*-'\n", dp->d_entry); 1626*7c478bd9Sstevel@tonic-gate else 1627*7c478bd9Sstevel@tonic-gate (void) printf("%s%s %s\n", title, file1, file2); 1628*7c478bd9Sstevel@tonic-gate result = calldiff((char *)0); 1629*7c478bd9Sstevel@tonic-gate if (opt == D_EDIT) 1630*7c478bd9Sstevel@tonic-gate (void) printf("w\nq\n-*-END-*-\n"); 1631*7c478bd9Sstevel@tonic-gate } 1632*7c478bd9Sstevel@tonic-gate return (result); 1633*7c478bd9Sstevel@tonic-gate } 1634*7c478bd9Sstevel@tonic-gate 1635*7c478bd9Sstevel@tonic-gate char *prargs[] = { "pr", "-h", 0, 0, 0 }; 1636*7c478bd9Sstevel@tonic-gate 1637*7c478bd9Sstevel@tonic-gate static int 1638*7c478bd9Sstevel@tonic-gate calldiff(char *wantpr) 1639*7c478bd9Sstevel@tonic-gate { 1640*7c478bd9Sstevel@tonic-gate pid_t pid; 1641*7c478bd9Sstevel@tonic-gate int diffstatus, pv[2]; 1642*7c478bd9Sstevel@tonic-gate 1643*7c478bd9Sstevel@tonic-gate prargs[2] = wantpr; 1644*7c478bd9Sstevel@tonic-gate (void) fflush(stdout); 1645*7c478bd9Sstevel@tonic-gate if (wantpr) { 1646*7c478bd9Sstevel@tonic-gate (void) sprintf(etitle, "%s %s", file1, file2); 1647*7c478bd9Sstevel@tonic-gate (void) pipe(pv); 1648*7c478bd9Sstevel@tonic-gate pid = fork(); 1649*7c478bd9Sstevel@tonic-gate if (pid == (pid_t)-1) 1650*7c478bd9Sstevel@tonic-gate error(gettext(NO_PROCS_ERR)); 1651*7c478bd9Sstevel@tonic-gate 1652*7c478bd9Sstevel@tonic-gate if (pid == 0) { 1653*7c478bd9Sstevel@tonic-gate (void) close(0); 1654*7c478bd9Sstevel@tonic-gate (void) dup(pv[0]); 1655*7c478bd9Sstevel@tonic-gate (void) close(pv[0]); 1656*7c478bd9Sstevel@tonic-gate (void) close(pv[1]); 1657*7c478bd9Sstevel@tonic-gate (void) execv(pr+5, prargs); 1658*7c478bd9Sstevel@tonic-gate (void) execv(pr, prargs); 1659*7c478bd9Sstevel@tonic-gate perror(pr); 1660*7c478bd9Sstevel@tonic-gate done(); 1661*7c478bd9Sstevel@tonic-gate } 1662*7c478bd9Sstevel@tonic-gate } 1663*7c478bd9Sstevel@tonic-gate pid = fork(); 1664*7c478bd9Sstevel@tonic-gate if (pid == (pid_t)-1) 1665*7c478bd9Sstevel@tonic-gate error(gettext(NO_PROCS_ERR)); 1666*7c478bd9Sstevel@tonic-gate 1667*7c478bd9Sstevel@tonic-gate if (pid == 0) { 1668*7c478bd9Sstevel@tonic-gate if (wantpr) { 1669*7c478bd9Sstevel@tonic-gate (void) close(1); 1670*7c478bd9Sstevel@tonic-gate (void) dup(pv[1]); 1671*7c478bd9Sstevel@tonic-gate (void) close(pv[0]); 1672*7c478bd9Sstevel@tonic-gate (void) close(pv[1]); 1673*7c478bd9Sstevel@tonic-gate } 1674*7c478bd9Sstevel@tonic-gate (void) execv(diff+5, diffargv); 1675*7c478bd9Sstevel@tonic-gate (void) execv(diff, diffargv); 1676*7c478bd9Sstevel@tonic-gate perror(diff); 1677*7c478bd9Sstevel@tonic-gate done(); 1678*7c478bd9Sstevel@tonic-gate } 1679*7c478bd9Sstevel@tonic-gate if (wantpr) { 1680*7c478bd9Sstevel@tonic-gate (void) close(pv[0]); 1681*7c478bd9Sstevel@tonic-gate (void) close(pv[1]); 1682*7c478bd9Sstevel@tonic-gate } 1683*7c478bd9Sstevel@tonic-gate while (wait(&diffstatus) != pid) 1684*7c478bd9Sstevel@tonic-gate continue; 1685*7c478bd9Sstevel@tonic-gate while (wait((int *)0) != (pid_t)-1) 1686*7c478bd9Sstevel@tonic-gate continue; 1687*7c478bd9Sstevel@tonic-gate if ((diffstatus&0177) != 0) 1688*7c478bd9Sstevel@tonic-gate return (2); 1689*7c478bd9Sstevel@tonic-gate else 1690*7c478bd9Sstevel@tonic-gate return ((diffstatus>>8) & 0377); 1691*7c478bd9Sstevel@tonic-gate } 1692*7c478bd9Sstevel@tonic-gate 1693*7c478bd9Sstevel@tonic-gate static char * 1694*7c478bd9Sstevel@tonic-gate pfiletype(mode_t fmt) 1695*7c478bd9Sstevel@tonic-gate { 1696*7c478bd9Sstevel@tonic-gate /* 1697*7c478bd9Sstevel@tonic-gate * TRANSLATION_NOTE 1698*7c478bd9Sstevel@tonic-gate * The following 9 messages will be used in the second and 1699*7c478bd9Sstevel@tonic-gate * the fourth parameters of the message 1700*7c478bd9Sstevel@tonic-gate * "File %s is %s while file %s is %s\n" 1701*7c478bd9Sstevel@tonic-gate */ 1702*7c478bd9Sstevel@tonic-gate switch (fmt) { 1703*7c478bd9Sstevel@tonic-gate 1704*7c478bd9Sstevel@tonic-gate case S_IFDIR: 1705*7c478bd9Sstevel@tonic-gate return (gettext("a directory")); 1706*7c478bd9Sstevel@tonic-gate break; 1707*7c478bd9Sstevel@tonic-gate 1708*7c478bd9Sstevel@tonic-gate case S_IFCHR: 1709*7c478bd9Sstevel@tonic-gate return (gettext("a character special file")); 1710*7c478bd9Sstevel@tonic-gate break; 1711*7c478bd9Sstevel@tonic-gate 1712*7c478bd9Sstevel@tonic-gate case S_IFBLK: 1713*7c478bd9Sstevel@tonic-gate return (gettext("a block special file")); 1714*7c478bd9Sstevel@tonic-gate break; 1715*7c478bd9Sstevel@tonic-gate 1716*7c478bd9Sstevel@tonic-gate case S_IFREG: 1717*7c478bd9Sstevel@tonic-gate return (gettext("a plain file")); 1718*7c478bd9Sstevel@tonic-gate break; 1719*7c478bd9Sstevel@tonic-gate 1720*7c478bd9Sstevel@tonic-gate case S_IFIFO: 1721*7c478bd9Sstevel@tonic-gate return (gettext("a named pipe")); 1722*7c478bd9Sstevel@tonic-gate break; 1723*7c478bd9Sstevel@tonic-gate 1724*7c478bd9Sstevel@tonic-gate case S_IFSOCK: 1725*7c478bd9Sstevel@tonic-gate return (gettext("a socket")); 1726*7c478bd9Sstevel@tonic-gate break; 1727*7c478bd9Sstevel@tonic-gate 1728*7c478bd9Sstevel@tonic-gate case S_IFDOOR: 1729*7c478bd9Sstevel@tonic-gate return (gettext("a door")); 1730*7c478bd9Sstevel@tonic-gate break; 1731*7c478bd9Sstevel@tonic-gate 1732*7c478bd9Sstevel@tonic-gate case S_IFPORT: 1733*7c478bd9Sstevel@tonic-gate return (gettext("an event port")); 1734*7c478bd9Sstevel@tonic-gate break; 1735*7c478bd9Sstevel@tonic-gate 1736*7c478bd9Sstevel@tonic-gate default: 1737*7c478bd9Sstevel@tonic-gate return (gettext("an unknown type")); 1738*7c478bd9Sstevel@tonic-gate break; 1739*7c478bd9Sstevel@tonic-gate } 1740*7c478bd9Sstevel@tonic-gate } 1741*7c478bd9Sstevel@tonic-gate 1742*7c478bd9Sstevel@tonic-gate static int 1743*7c478bd9Sstevel@tonic-gate binary(int f) 1744*7c478bd9Sstevel@tonic-gate { 1745*7c478bd9Sstevel@tonic-gate char buf[BUFSIZ]; 1746*7c478bd9Sstevel@tonic-gate int cnt; 1747*7c478bd9Sstevel@tonic-gate 1748*7c478bd9Sstevel@tonic-gate (void) lseek(f, (long)0, SEEK_SET); 1749*7c478bd9Sstevel@tonic-gate cnt = read(f, buf, BUFSIZ); 1750*7c478bd9Sstevel@tonic-gate if (cnt < 0) 1751*7c478bd9Sstevel@tonic-gate return (1); 1752*7c478bd9Sstevel@tonic-gate return (isbinary(buf, cnt)); 1753*7c478bd9Sstevel@tonic-gate } 1754*7c478bd9Sstevel@tonic-gate 1755*7c478bd9Sstevel@tonic-gate static int 1756*7c478bd9Sstevel@tonic-gate filebinary(FILE *f) 1757*7c478bd9Sstevel@tonic-gate { 1758*7c478bd9Sstevel@tonic-gate char buf[BUFSIZ]; 1759*7c478bd9Sstevel@tonic-gate int cnt; 1760*7c478bd9Sstevel@tonic-gate 1761*7c478bd9Sstevel@tonic-gate (void) fseek(f, (long)0, SEEK_SET); 1762*7c478bd9Sstevel@tonic-gate cnt = fread(buf, 1, BUFSIZ, f); 1763*7c478bd9Sstevel@tonic-gate if (ferror(f)) 1764*7c478bd9Sstevel@tonic-gate return (1); 1765*7c478bd9Sstevel@tonic-gate return (isbinary(buf, cnt)); 1766*7c478bd9Sstevel@tonic-gate } 1767*7c478bd9Sstevel@tonic-gate 1768*7c478bd9Sstevel@tonic-gate 1769*7c478bd9Sstevel@tonic-gate /* 1770*7c478bd9Sstevel@tonic-gate * We consider a "binary" file to be one that: 1771*7c478bd9Sstevel@tonic-gate * contains a null character ("diff" doesn't handle them correctly, and 1772*7c478bd9Sstevel@tonic-gate * neither do many other UNIX text-processing commands). 1773*7c478bd9Sstevel@tonic-gate * Characters with their 8th bit set do NOT make a file binary; they may be 1774*7c478bd9Sstevel@tonic-gate * legitimate text characters, or parts of same. 1775*7c478bd9Sstevel@tonic-gate */ 1776*7c478bd9Sstevel@tonic-gate static int 1777*7c478bd9Sstevel@tonic-gate isbinary(char *buf, int cnt) 1778*7c478bd9Sstevel@tonic-gate { 1779*7c478bd9Sstevel@tonic-gate char *cp; 1780*7c478bd9Sstevel@tonic-gate 1781*7c478bd9Sstevel@tonic-gate cp = buf; 1782*7c478bd9Sstevel@tonic-gate while (--cnt >= 0) 1783*7c478bd9Sstevel@tonic-gate if (*cp++ == '\0') 1784*7c478bd9Sstevel@tonic-gate return (1); 1785*7c478bd9Sstevel@tonic-gate return (0); 1786*7c478bd9Sstevel@tonic-gate } 1787*7c478bd9Sstevel@tonic-gate 1788*7c478bd9Sstevel@tonic-gate 1789*7c478bd9Sstevel@tonic-gate /* 1790*7c478bd9Sstevel@tonic-gate * THIS IS CRUDE. 1791*7c478bd9Sstevel@tonic-gate */ 1792*7c478bd9Sstevel@tonic-gate static int 1793*7c478bd9Sstevel@tonic-gate useless(char *cp) 1794*7c478bd9Sstevel@tonic-gate { 1795*7c478bd9Sstevel@tonic-gate 1796*7c478bd9Sstevel@tonic-gate if (cp[0] == '.') { 1797*7c478bd9Sstevel@tonic-gate if (cp[1] == '\0') 1798*7c478bd9Sstevel@tonic-gate return (1); /* directory "." */ 1799*7c478bd9Sstevel@tonic-gate if (cp[1] == '.' && cp[2] == '\0') 1800*7c478bd9Sstevel@tonic-gate return (1); /* directory ".." */ 1801*7c478bd9Sstevel@tonic-gate } 1802*7c478bd9Sstevel@tonic-gate if (start && strcmp(start, cp) > 0) 1803*7c478bd9Sstevel@tonic-gate return (1); 1804*7c478bd9Sstevel@tonic-gate return (0); 1805*7c478bd9Sstevel@tonic-gate } 1806*7c478bd9Sstevel@tonic-gate 1807*7c478bd9Sstevel@tonic-gate 1808*7c478bd9Sstevel@tonic-gate void 1809*7c478bd9Sstevel@tonic-gate sort(struct line *a, int n) /* shellsort CACM #201 */ 1810*7c478bd9Sstevel@tonic-gate { 1811*7c478bd9Sstevel@tonic-gate struct line w; 1812*7c478bd9Sstevel@tonic-gate int j, m; 1813*7c478bd9Sstevel@tonic-gate struct line *ai; 1814*7c478bd9Sstevel@tonic-gate struct line *aim; 1815*7c478bd9Sstevel@tonic-gate int k; 1816*7c478bd9Sstevel@tonic-gate 1817*7c478bd9Sstevel@tonic-gate for (j = 1, m = 0; j <= n; j *= 2) 1818*7c478bd9Sstevel@tonic-gate m = 2 * j - 1; 1819*7c478bd9Sstevel@tonic-gate for (m /= 2; m != 0; m /= 2) { 1820*7c478bd9Sstevel@tonic-gate k = n - m; 1821*7c478bd9Sstevel@tonic-gate for (j = 1; j <= k; j++) { 1822*7c478bd9Sstevel@tonic-gate for (ai = &a[j]; ai > a; ai -= m) { 1823*7c478bd9Sstevel@tonic-gate aim = &ai[m]; 1824*7c478bd9Sstevel@tonic-gate if (aim < ai) 1825*7c478bd9Sstevel@tonic-gate break; /* wraparound */ 1826*7c478bd9Sstevel@tonic-gate if (aim->value > ai[0].value || 1827*7c478bd9Sstevel@tonic-gate aim->value == ai[0].value && 1828*7c478bd9Sstevel@tonic-gate aim->serial > ai[0].serial) 1829*7c478bd9Sstevel@tonic-gate break; 1830*7c478bd9Sstevel@tonic-gate w.value = ai[0].value; 1831*7c478bd9Sstevel@tonic-gate ai[0].value = aim->value; 1832*7c478bd9Sstevel@tonic-gate aim->value = w.value; 1833*7c478bd9Sstevel@tonic-gate w.serial = ai[0].serial; 1834*7c478bd9Sstevel@tonic-gate ai[0].serial = aim->serial; 1835*7c478bd9Sstevel@tonic-gate aim->serial = w.serial; 1836*7c478bd9Sstevel@tonic-gate } 1837*7c478bd9Sstevel@tonic-gate } 1838*7c478bd9Sstevel@tonic-gate } 1839*7c478bd9Sstevel@tonic-gate } 1840*7c478bd9Sstevel@tonic-gate 1841*7c478bd9Sstevel@tonic-gate static void 1842*7c478bd9Sstevel@tonic-gate unsort(struct line *f, int l, int *b) 1843*7c478bd9Sstevel@tonic-gate { 1844*7c478bd9Sstevel@tonic-gate int *a; 1845*7c478bd9Sstevel@tonic-gate int i; 1846*7c478bd9Sstevel@tonic-gate 1847*7c478bd9Sstevel@tonic-gate a = (int *)talloc((l + 1) * sizeof (int)); 1848*7c478bd9Sstevel@tonic-gate for (i = 1; i <= l; i++) 1849*7c478bd9Sstevel@tonic-gate a[f[i].serial] = f[i].value; 1850*7c478bd9Sstevel@tonic-gate for (i = 1; i <= l; i++) 1851*7c478bd9Sstevel@tonic-gate b[i] = a[i]; 1852*7c478bd9Sstevel@tonic-gate free((char *)a); 1853*7c478bd9Sstevel@tonic-gate } 1854*7c478bd9Sstevel@tonic-gate 1855*7c478bd9Sstevel@tonic-gate static void 1856*7c478bd9Sstevel@tonic-gate filename(char **pa1, char **pa2, struct stat *st, char **ifile) 1857*7c478bd9Sstevel@tonic-gate { 1858*7c478bd9Sstevel@tonic-gate char *a1, *b1, *a2; 1859*7c478bd9Sstevel@tonic-gate 1860*7c478bd9Sstevel@tonic-gate a1 = *pa1; 1861*7c478bd9Sstevel@tonic-gate a2 = *pa2; 1862*7c478bd9Sstevel@tonic-gate 1863*7c478bd9Sstevel@tonic-gate if (strcmp(*pa1, "-") == 0) 1864*7c478bd9Sstevel@tonic-gate *ifile = strdup("-"); 1865*7c478bd9Sstevel@tonic-gate else 1866*7c478bd9Sstevel@tonic-gate *ifile = strdup(*pa1); 1867*7c478bd9Sstevel@tonic-gate 1868*7c478bd9Sstevel@tonic-gate if (*ifile == (char *)NULL) { 1869*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 1870*7c478bd9Sstevel@tonic-gate "no more memory - try again later\n")); 1871*7c478bd9Sstevel@tonic-gate status = 2; 1872*7c478bd9Sstevel@tonic-gate done(); 1873*7c478bd9Sstevel@tonic-gate } 1874*7c478bd9Sstevel@tonic-gate 1875*7c478bd9Sstevel@tonic-gate if ((st->st_mode & S_IFMT) == S_IFDIR) { 1876*7c478bd9Sstevel@tonic-gate b1 = *pa1 = (char *)malloc(PATH_MAX); 1877*7c478bd9Sstevel@tonic-gate while (*b1++ = *a1++) 1878*7c478bd9Sstevel@tonic-gate ; 1879*7c478bd9Sstevel@tonic-gate b1[-1] = '/'; 1880*7c478bd9Sstevel@tonic-gate a1 = b1; 1881*7c478bd9Sstevel@tonic-gate while (*a1++ = *a2++) 1882*7c478bd9Sstevel@tonic-gate if (*a2 && *a2 != '/' && a2[-1] == '/') 1883*7c478bd9Sstevel@tonic-gate a1 = b1; 1884*7c478bd9Sstevel@tonic-gate *ifile = strdup(*pa1); 1885*7c478bd9Sstevel@tonic-gate 1886*7c478bd9Sstevel@tonic-gate if (*ifile == (char *)NULL) { 1887*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 1888*7c478bd9Sstevel@tonic-gate "no more memory - try again later\n")); 1889*7c478bd9Sstevel@tonic-gate status = 2; 1890*7c478bd9Sstevel@tonic-gate done(); 1891*7c478bd9Sstevel@tonic-gate } 1892*7c478bd9Sstevel@tonic-gate 1893*7c478bd9Sstevel@tonic-gate if (stat(*pa1, st) < 0) { 1894*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "diff: "); 1895*7c478bd9Sstevel@tonic-gate perror(*pa1); 1896*7c478bd9Sstevel@tonic-gate done(); 1897*7c478bd9Sstevel@tonic-gate } 1898*7c478bd9Sstevel@tonic-gate } else if ((st->st_mode & S_IFMT) == S_IFCHR) 1899*7c478bd9Sstevel@tonic-gate *pa1 = copytemp(a1); 1900*7c478bd9Sstevel@tonic-gate else if (a1[0] == '-' && a1[1] == 0) { 1901*7c478bd9Sstevel@tonic-gate *pa1 = copytemp(a1); /* hack! */ 1902*7c478bd9Sstevel@tonic-gate if (stat(*pa1, st) < 0) { 1903*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "diff: "); 1904*7c478bd9Sstevel@tonic-gate perror(*pa1); 1905*7c478bd9Sstevel@tonic-gate done(); 1906*7c478bd9Sstevel@tonic-gate } 1907*7c478bd9Sstevel@tonic-gate } 1908*7c478bd9Sstevel@tonic-gate } 1909*7c478bd9Sstevel@tonic-gate 1910*7c478bd9Sstevel@tonic-gate static char * 1911*7c478bd9Sstevel@tonic-gate copytemp(char *fn) 1912*7c478bd9Sstevel@tonic-gate { 1913*7c478bd9Sstevel@tonic-gate int ifd, ofd; /* input and output file descriptors */ 1914*7c478bd9Sstevel@tonic-gate int i; 1915*7c478bd9Sstevel@tonic-gate char template[13]; /* template for temp file name */ 1916*7c478bd9Sstevel@tonic-gate char buf[BUFSIZ]; 1917*7c478bd9Sstevel@tonic-gate 1918*7c478bd9Sstevel@tonic-gate /* 1919*7c478bd9Sstevel@tonic-gate * a "-" file is interpreted as fd 0 for pre-/dev/fd systems 1920*7c478bd9Sstevel@tonic-gate * ... let's hope this goes away soon! 1921*7c478bd9Sstevel@tonic-gate */ 1922*7c478bd9Sstevel@tonic-gate if ((ifd = (strcmp(fn, "-") ? open(fn, 0) : 0)) < 0) { 1923*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "diff: "); 1924*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("cannot open %s\n"), fn); 1925*7c478bd9Sstevel@tonic-gate done(); 1926*7c478bd9Sstevel@tonic-gate } 1927*7c478bd9Sstevel@tonic-gate (void) signal(SIGHUP, (void (*)(int))done); 1928*7c478bd9Sstevel@tonic-gate (void) signal(SIGINT, (void (*)(int))done); 1929*7c478bd9Sstevel@tonic-gate (void) signal(SIGPIPE, (void (*)(int))done); 1930*7c478bd9Sstevel@tonic-gate (void) signal(SIGTERM, (void (*)(int))done); 1931*7c478bd9Sstevel@tonic-gate (void) strcpy(template, "/tmp/dXXXXXX"); 1932*7c478bd9Sstevel@tonic-gate if ((ofd = mkstemp(template)) < 0) { 1933*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "diff: "); 1934*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("cannot create %s\n"), template); 1935*7c478bd9Sstevel@tonic-gate done(); 1936*7c478bd9Sstevel@tonic-gate } 1937*7c478bd9Sstevel@tonic-gate (void) strcpy(tempfile[whichtemp++], template); 1938*7c478bd9Sstevel@tonic-gate while ((i = read(ifd, buf, BUFSIZ)) > 0) 1939*7c478bd9Sstevel@tonic-gate if (write(ofd, buf, i) != i) { 1940*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "diff: "); 1941*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1942*7c478bd9Sstevel@tonic-gate gettext("write failed %s\n"), template); 1943*7c478bd9Sstevel@tonic-gate done(); 1944*7c478bd9Sstevel@tonic-gate } 1945*7c478bd9Sstevel@tonic-gate (void) close(ifd); (void) close(ofd); 1946*7c478bd9Sstevel@tonic-gate return (tempfile[whichtemp-1]); 1947*7c478bd9Sstevel@tonic-gate } 1948*7c478bd9Sstevel@tonic-gate 1949*7c478bd9Sstevel@tonic-gate static void 1950*7c478bd9Sstevel@tonic-gate prepare(int i, char *arg) 1951*7c478bd9Sstevel@tonic-gate { 1952*7c478bd9Sstevel@tonic-gate struct line *p; 1953*7c478bd9Sstevel@tonic-gate int j, h; 1954*7c478bd9Sstevel@tonic-gate 1955*7c478bd9Sstevel@tonic-gate (void) fseek(input[i], (long)0, SEEK_SET); 1956*7c478bd9Sstevel@tonic-gate p = (struct line *)talloc(3 * sizeof (line)); 1957*7c478bd9Sstevel@tonic-gate for (j = 0; h = readhash(input[i], i, arg); ) { 1958*7c478bd9Sstevel@tonic-gate p = (struct line *)ralloc((void *)p, (++j + 3) * sizeof (line)); 1959*7c478bd9Sstevel@tonic-gate p[j].value = h; 1960*7c478bd9Sstevel@tonic-gate } 1961*7c478bd9Sstevel@tonic-gate len[i] = j; 1962*7c478bd9Sstevel@tonic-gate file[i] = p; 1963*7c478bd9Sstevel@tonic-gate } 1964*7c478bd9Sstevel@tonic-gate 1965*7c478bd9Sstevel@tonic-gate static void 1966*7c478bd9Sstevel@tonic-gate prune(void) 1967*7c478bd9Sstevel@tonic-gate { 1968*7c478bd9Sstevel@tonic-gate int i, j; 1969*7c478bd9Sstevel@tonic-gate 1970*7c478bd9Sstevel@tonic-gate for (pref = 0; pref < len[0] && pref < len[1] && 1971*7c478bd9Sstevel@tonic-gate file[0][pref + 1].value == file[1][pref + 1].value; 1972*7c478bd9Sstevel@tonic-gate pref++) 1973*7c478bd9Sstevel@tonic-gate ; 1974*7c478bd9Sstevel@tonic-gate for (suff = 0; (suff < len[0] - pref) && 1975*7c478bd9Sstevel@tonic-gate (suff < len[1] - pref) && 1976*7c478bd9Sstevel@tonic-gate (file[0][len[0] - suff].value == 1977*7c478bd9Sstevel@tonic-gate file[1][len[1] - suff].value); 1978*7c478bd9Sstevel@tonic-gate suff++) 1979*7c478bd9Sstevel@tonic-gate ; 1980*7c478bd9Sstevel@tonic-gate 1981*7c478bd9Sstevel@tonic-gate /* decremnt suff by 2 iff suff >= 2, ensure that suff is never < 0 */ 1982*7c478bd9Sstevel@tonic-gate if (suff >= 2) 1983*7c478bd9Sstevel@tonic-gate suff -= 2; 1984*7c478bd9Sstevel@tonic-gate 1985*7c478bd9Sstevel@tonic-gate for (j = 0; j < 2; j++) { 1986*7c478bd9Sstevel@tonic-gate sfile[j] = file[j] + pref; 1987*7c478bd9Sstevel@tonic-gate slen[j] = len[j] - pref - suff; 1988*7c478bd9Sstevel@tonic-gate for (i = 0; i <= slen[j]; i++) 1989*7c478bd9Sstevel@tonic-gate sfile[j][i].serial = i; 1990*7c478bd9Sstevel@tonic-gate } 1991*7c478bd9Sstevel@tonic-gate } 1992*7c478bd9Sstevel@tonic-gate 1993*7c478bd9Sstevel@tonic-gate static void 1994*7c478bd9Sstevel@tonic-gate equiv(struct line *a, int n, struct line *b, int m, int *c) 1995*7c478bd9Sstevel@tonic-gate { 1996*7c478bd9Sstevel@tonic-gate int i, j; 1997*7c478bd9Sstevel@tonic-gate i = j = 1; 1998*7c478bd9Sstevel@tonic-gate while (i <= n && j <= m) { 1999*7c478bd9Sstevel@tonic-gate if (a[i].value < b[j].value) 2000*7c478bd9Sstevel@tonic-gate a[i++].value = 0; 2001*7c478bd9Sstevel@tonic-gate else if (a[i].value == b[j].value) 2002*7c478bd9Sstevel@tonic-gate a[i++].value = j; 2003*7c478bd9Sstevel@tonic-gate else 2004*7c478bd9Sstevel@tonic-gate j++; 2005*7c478bd9Sstevel@tonic-gate } 2006*7c478bd9Sstevel@tonic-gate while (i <= n) 2007*7c478bd9Sstevel@tonic-gate a[i++].value = 0; 2008*7c478bd9Sstevel@tonic-gate b[m+1].value = 0; j = 0; 2009*7c478bd9Sstevel@tonic-gate while (++j <= m) { 2010*7c478bd9Sstevel@tonic-gate c[j] = -b[j].serial; 2011*7c478bd9Sstevel@tonic-gate while (b[j + 1].value == b[j].value) { 2012*7c478bd9Sstevel@tonic-gate j++; 2013*7c478bd9Sstevel@tonic-gate c[j] = b[j].serial; 2014*7c478bd9Sstevel@tonic-gate } 2015*7c478bd9Sstevel@tonic-gate } 2016*7c478bd9Sstevel@tonic-gate c[j] = -1; 2017*7c478bd9Sstevel@tonic-gate } 2018*7c478bd9Sstevel@tonic-gate 2019*7c478bd9Sstevel@tonic-gate static void 2020*7c478bd9Sstevel@tonic-gate done(void) 2021*7c478bd9Sstevel@tonic-gate { 2022*7c478bd9Sstevel@tonic-gate if (whichtemp) (void) unlink(tempfile[0]); 2023*7c478bd9Sstevel@tonic-gate if (whichtemp == 2) (void) unlink(tempfile[1]); 2024*7c478bd9Sstevel@tonic-gate exit(status); 2025*7c478bd9Sstevel@tonic-gate } 2026*7c478bd9Sstevel@tonic-gate 2027*7c478bd9Sstevel@tonic-gate static void 2028*7c478bd9Sstevel@tonic-gate noroom(void) 2029*7c478bd9Sstevel@tonic-gate { 2030*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "diff: "); 2031*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("files too big, try -h\n")); 2032*7c478bd9Sstevel@tonic-gate done(); 2033*7c478bd9Sstevel@tonic-gate } 2034*7c478bd9Sstevel@tonic-gate 2035*7c478bd9Sstevel@tonic-gate static void 2036*7c478bd9Sstevel@tonic-gate error(const char *s) 2037*7c478bd9Sstevel@tonic-gate { 2038*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "diff: "); 2039*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, s); 2040*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "\n"); 2041*7c478bd9Sstevel@tonic-gate done(); 2042*7c478bd9Sstevel@tonic-gate } 2043*7c478bd9Sstevel@tonic-gate 2044*7c478bd9Sstevel@tonic-gate static void 2045*7c478bd9Sstevel@tonic-gate usage(void) 2046*7c478bd9Sstevel@tonic-gate { 2047*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 2048*7c478bd9Sstevel@tonic-gate "usage: diff [-bitw] [-c | -e | -f | -h | -n | -u] file1 " 2049*7c478bd9Sstevel@tonic-gate "file2\n" 2050*7c478bd9Sstevel@tonic-gate " diff [-bitw] [-C number | -U number] file1 file2\n" 2051*7c478bd9Sstevel@tonic-gate " diff [-bitw] [-D string] file1 file2\n" 2052*7c478bd9Sstevel@tonic-gate " diff [-bitw] [-c | -e | -f | -h | -n | -u] [-l] [-r] " 2053*7c478bd9Sstevel@tonic-gate "[-s] [-S name] directory1 directory2\n")); 2054*7c478bd9Sstevel@tonic-gate status = 2; 2055*7c478bd9Sstevel@tonic-gate done(); 2056*7c478bd9Sstevel@tonic-gate } 2057*7c478bd9Sstevel@tonic-gate 2058*7c478bd9Sstevel@tonic-gate #define NW 1024 2059*7c478bd9Sstevel@tonic-gate struct buff { 2060*7c478bd9Sstevel@tonic-gate FILE *iop; /* I/O stream */ 2061*7c478bd9Sstevel@tonic-gate char buf[NW + MB_LEN_MAX]; /* buffer */ 2062*7c478bd9Sstevel@tonic-gate char *ptr; /* current pointer in the buffer */ 2063*7c478bd9Sstevel@tonic-gate int buffered; /* if non-zero, buffer has data */ 2064*7c478bd9Sstevel@tonic-gate long offset; /* offset in the file */ 2065*7c478bd9Sstevel@tonic-gate }; 2066*7c478bd9Sstevel@tonic-gate 2067*7c478bd9Sstevel@tonic-gate static struct buff bufwchar[2]; 2068*7c478bd9Sstevel@tonic-gate 2069*7c478bd9Sstevel@tonic-gate /* 2070*7c478bd9Sstevel@tonic-gate * Initializes the buff structure for specified 2071*7c478bd9Sstevel@tonic-gate * I/O stream. Also sets the specified offset 2072*7c478bd9Sstevel@tonic-gate */ 2073*7c478bd9Sstevel@tonic-gate static void 2074*7c478bd9Sstevel@tonic-gate initbuf(FILE *iop, int filen, long offset) 2075*7c478bd9Sstevel@tonic-gate { 2076*7c478bd9Sstevel@tonic-gate bufwchar[filen].iop = iop; 2077*7c478bd9Sstevel@tonic-gate bufwchar[filen].ptr = NULL; 2078*7c478bd9Sstevel@tonic-gate bufwchar[filen].buffered = 0; 2079*7c478bd9Sstevel@tonic-gate bufwchar[filen].offset = offset; 2080*7c478bd9Sstevel@tonic-gate } 2081*7c478bd9Sstevel@tonic-gate 2082*7c478bd9Sstevel@tonic-gate /* 2083*7c478bd9Sstevel@tonic-gate * Reset a buff structure, and rewind the associated file. 2084*7c478bd9Sstevel@tonic-gate */ 2085*7c478bd9Sstevel@tonic-gate static void 2086*7c478bd9Sstevel@tonic-gate resetbuf(int filen) 2087*7c478bd9Sstevel@tonic-gate { 2088*7c478bd9Sstevel@tonic-gate bufwchar[filen].ptr = NULL; 2089*7c478bd9Sstevel@tonic-gate bufwchar[filen].buffered = bufwchar[filen].offset = 0; 2090*7c478bd9Sstevel@tonic-gate rewind(bufwchar[filen].iop); 2091*7c478bd9Sstevel@tonic-gate } 2092*7c478bd9Sstevel@tonic-gate 2093*7c478bd9Sstevel@tonic-gate 2094*7c478bd9Sstevel@tonic-gate /* 2095*7c478bd9Sstevel@tonic-gate * Returns the current offset in the file 2096*7c478bd9Sstevel@tonic-gate */ 2097*7c478bd9Sstevel@tonic-gate static long 2098*7c478bd9Sstevel@tonic-gate ftellbuf(int filen) 2099*7c478bd9Sstevel@tonic-gate { 2100*7c478bd9Sstevel@tonic-gate return (bufwchar[filen].offset); 2101*7c478bd9Sstevel@tonic-gate } 2102*7c478bd9Sstevel@tonic-gate 2103*7c478bd9Sstevel@tonic-gate static wint_t 2104*7c478bd9Sstevel@tonic-gate wcput(wint_t wc) 2105*7c478bd9Sstevel@tonic-gate { 2106*7c478bd9Sstevel@tonic-gate char mbs[MB_LEN_MAX]; 2107*7c478bd9Sstevel@tonic-gate unsigned char *p; 2108*7c478bd9Sstevel@tonic-gate int n; 2109*7c478bd9Sstevel@tonic-gate 2110*7c478bd9Sstevel@tonic-gate n = wctomb(mbs, (wchar_t)wc); 2111*7c478bd9Sstevel@tonic-gate if (n > 0) { 2112*7c478bd9Sstevel@tonic-gate p = (unsigned char *)mbs; 2113*7c478bd9Sstevel@tonic-gate while (n--) { 2114*7c478bd9Sstevel@tonic-gate (void) putc((*p++), stdout); 2115*7c478bd9Sstevel@tonic-gate } 2116*7c478bd9Sstevel@tonic-gate return (wc); 2117*7c478bd9Sstevel@tonic-gate } else if (n < 0) { 2118*7c478bd9Sstevel@tonic-gate (void) putc((int)(wc & 0xff), stdout); 2119*7c478bd9Sstevel@tonic-gate return (wc & 0xff); 2120*7c478bd9Sstevel@tonic-gate } else { 2121*7c478bd9Sstevel@tonic-gate /* this should not happen */ 2122*7c478bd9Sstevel@tonic-gate return (WEOF); 2123*7c478bd9Sstevel@tonic-gate } 2124*7c478bd9Sstevel@tonic-gate } 2125*7c478bd9Sstevel@tonic-gate 2126*7c478bd9Sstevel@tonic-gate /* 2127*7c478bd9Sstevel@tonic-gate * Reads one wide-character from the file associated with filen. 2128*7c478bd9Sstevel@tonic-gate * If multibyte locales, the input is buffered. 2129*7c478bd9Sstevel@tonic-gate * 2130*7c478bd9Sstevel@tonic-gate * Input: filen the file number (0 or 1) 2131*7c478bd9Sstevel@tonic-gate * Output: *len number of bytes to make wide-character 2132*7c478bd9Sstevel@tonic-gate * Return: wide-character 2133*7c478bd9Sstevel@tonic-gate */ 2134*7c478bd9Sstevel@tonic-gate static wint_t 2135*7c478bd9Sstevel@tonic-gate getbufwchar(int filen, int *len) 2136*7c478bd9Sstevel@tonic-gate { 2137*7c478bd9Sstevel@tonic-gate 2138*7c478bd9Sstevel@tonic-gate int i, num, clen; 2139*7c478bd9Sstevel@tonic-gate wchar_t wc; 2140*7c478bd9Sstevel@tonic-gate size_t mxlen; 2141*7c478bd9Sstevel@tonic-gate 2142*7c478bd9Sstevel@tonic-gate if (mbcurmax == 1) { 2143*7c478bd9Sstevel@tonic-gate /* If sigle byte locale, use getc() */ 2144*7c478bd9Sstevel@tonic-gate int ch; 2145*7c478bd9Sstevel@tonic-gate 2146*7c478bd9Sstevel@tonic-gate ch = getc(bufwchar[filen].iop); 2147*7c478bd9Sstevel@tonic-gate bufwchar[filen].offset++; 2148*7c478bd9Sstevel@tonic-gate *len = 1; 2149*7c478bd9Sstevel@tonic-gate 2150*7c478bd9Sstevel@tonic-gate if (isascii(ch) || (ch == EOF)) { 2151*7c478bd9Sstevel@tonic-gate return ((wint_t)ch); 2152*7c478bd9Sstevel@tonic-gate } else { 2153*7c478bd9Sstevel@tonic-gate wchar_t wc; 2154*7c478bd9Sstevel@tonic-gate char str[2] = {0, 0}; 2155*7c478bd9Sstevel@tonic-gate 2156*7c478bd9Sstevel@tonic-gate str[0] = (char)ch; 2157*7c478bd9Sstevel@tonic-gate if (mbtowc(&wc, str, 1) > 0) { 2158*7c478bd9Sstevel@tonic-gate return ((wint_t)wc); 2159*7c478bd9Sstevel@tonic-gate } else { 2160*7c478bd9Sstevel@tonic-gate return ((wint_t)ch); 2161*7c478bd9Sstevel@tonic-gate } 2162*7c478bd9Sstevel@tonic-gate } 2163*7c478bd9Sstevel@tonic-gate } else { 2164*7c478bd9Sstevel@tonic-gate mxlen = mbcurmax; 2165*7c478bd9Sstevel@tonic-gate } 2166*7c478bd9Sstevel@tonic-gate 2167*7c478bd9Sstevel@tonic-gate if (bufwchar[filen].buffered == 0) { 2168*7c478bd9Sstevel@tonic-gate /* Not buffered */ 2169*7c478bd9Sstevel@tonic-gate bufwchar[filen].ptr = &(bufwchar[filen].buf[MB_LEN_MAX]); 2170*7c478bd9Sstevel@tonic-gate num = fread((void *)bufwchar[filen].ptr, 2171*7c478bd9Sstevel@tonic-gate sizeof (char), NW, bufwchar[filen].iop); 2172*7c478bd9Sstevel@tonic-gate if (ferror(bufwchar[filen].iop)) { 2173*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "diff: "); 2174*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Error reading ")); 2175*7c478bd9Sstevel@tonic-gate perror((filen == 0) ? file1 : file2); 2176*7c478bd9Sstevel@tonic-gate status = 2; 2177*7c478bd9Sstevel@tonic-gate done(); 2178*7c478bd9Sstevel@tonic-gate } 2179*7c478bd9Sstevel@tonic-gate if (num == 0) 2180*7c478bd9Sstevel@tonic-gate return (WEOF); 2181*7c478bd9Sstevel@tonic-gate bufwchar[filen].buffered = num; 2182*7c478bd9Sstevel@tonic-gate } 2183*7c478bd9Sstevel@tonic-gate 2184*7c478bd9Sstevel@tonic-gate if (bufwchar[filen].buffered < mbcurmax) { 2185*7c478bd9Sstevel@tonic-gate for (i = 0; i < bufwchar[filen].buffered; i++) { 2186*7c478bd9Sstevel@tonic-gate bufwchar[filen].buf[MB_LEN_MAX - 2187*7c478bd9Sstevel@tonic-gate (bufwchar[filen].buffered - i)] = 2188*7c478bd9Sstevel@tonic-gate *(bufwchar[filen].ptr + i); 2189*7c478bd9Sstevel@tonic-gate } 2190*7c478bd9Sstevel@tonic-gate bufwchar[filen].ptr = &(bufwchar[filen].buf[MB_LEN_MAX]); 2191*7c478bd9Sstevel@tonic-gate num = fread((void *)bufwchar[filen].ptr, 2192*7c478bd9Sstevel@tonic-gate sizeof (char), NW, bufwchar[filen].iop); 2193*7c478bd9Sstevel@tonic-gate if (ferror(bufwchar[filen].iop)) { 2194*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "diff: "); 2195*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Error reading ")); 2196*7c478bd9Sstevel@tonic-gate perror((filen == 0) ? file1 : file2); 2197*7c478bd9Sstevel@tonic-gate status = 2; 2198*7c478bd9Sstevel@tonic-gate done(); 2199*7c478bd9Sstevel@tonic-gate } 2200*7c478bd9Sstevel@tonic-gate bufwchar[filen].ptr = &(bufwchar[filen].buf[MB_LEN_MAX - 2201*7c478bd9Sstevel@tonic-gate bufwchar[filen].buffered]); 2202*7c478bd9Sstevel@tonic-gate bufwchar[filen].buffered += num; 2203*7c478bd9Sstevel@tonic-gate if (bufwchar[filen].buffered < mbcurmax) { 2204*7c478bd9Sstevel@tonic-gate mxlen = bufwchar[filen].buffered; 2205*7c478bd9Sstevel@tonic-gate } 2206*7c478bd9Sstevel@tonic-gate } 2207*7c478bd9Sstevel@tonic-gate 2208*7c478bd9Sstevel@tonic-gate clen = mbtowc(&wc, bufwchar[filen].ptr, mxlen); 2209*7c478bd9Sstevel@tonic-gate if (clen <= 0) { 2210*7c478bd9Sstevel@tonic-gate (bufwchar[filen].buffered)--; 2211*7c478bd9Sstevel@tonic-gate *len = 1; 2212*7c478bd9Sstevel@tonic-gate (bufwchar[filen].offset)++; 2213*7c478bd9Sstevel@tonic-gate wc = (wchar_t)((unsigned char)*bufwchar[filen].ptr++); 2214*7c478bd9Sstevel@tonic-gate return ((wint_t)wc); 2215*7c478bd9Sstevel@tonic-gate } else { 2216*7c478bd9Sstevel@tonic-gate bufwchar[filen].buffered -= clen; 2217*7c478bd9Sstevel@tonic-gate bufwchar[filen].ptr += clen; 2218*7c478bd9Sstevel@tonic-gate bufwchar[filen].offset += clen; 2219*7c478bd9Sstevel@tonic-gate *len = clen; 2220*7c478bd9Sstevel@tonic-gate return ((wint_t)wc); 2221*7c478bd9Sstevel@tonic-gate } 2222*7c478bd9Sstevel@tonic-gate } 2223