17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate */ 227c478bd9Sstevel@tonic-gate /* 23*78eb75caSchin * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 287c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate /* 317c478bd9Sstevel@tonic-gate * University Copyright- Copyright (c) 1982, 1986, 1988 327c478bd9Sstevel@tonic-gate * The Regents of the University of California 337c478bd9Sstevel@tonic-gate * All Rights Reserved 347c478bd9Sstevel@tonic-gate * 357c478bd9Sstevel@tonic-gate * University Acknowledgment- Portions of this document are derived from 367c478bd9Sstevel@tonic-gate * software developed by the University of California, Berkeley, and its 377c478bd9Sstevel@tonic-gate * contributors. 387c478bd9Sstevel@tonic-gate */ 397c478bd9Sstevel@tonic-gate 407c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 417c478bd9Sstevel@tonic-gate 427c478bd9Sstevel@tonic-gate /* 437c478bd9Sstevel@tonic-gate * diff - differential file comparison 447c478bd9Sstevel@tonic-gate * 457c478bd9Sstevel@tonic-gate * Uses an algorithm which finds 467c478bd9Sstevel@tonic-gate * a pair of longest identical subsequences in the two 477c478bd9Sstevel@tonic-gate * files. 487c478bd9Sstevel@tonic-gate * 497c478bd9Sstevel@tonic-gate * The major goal is to generate the match vector J. 507c478bd9Sstevel@tonic-gate * J[i] is the index of the line in file1 corresponding 517c478bd9Sstevel@tonic-gate * to line i file0. J[i] = 0 if there is no 527c478bd9Sstevel@tonic-gate * such line in file1. 537c478bd9Sstevel@tonic-gate * 547c478bd9Sstevel@tonic-gate * Lines are hashed so as to work in core. All potential 557c478bd9Sstevel@tonic-gate * matches are located by sorting the lines of each file 567c478bd9Sstevel@tonic-gate * on the hash (called value). In particular, this 577c478bd9Sstevel@tonic-gate * collects the equivalence classes in file1 together. 587c478bd9Sstevel@tonic-gate * Subroutine equiv replaces the value of each line in 597c478bd9Sstevel@tonic-gate * file0 by the index of the first element of its 607c478bd9Sstevel@tonic-gate * matching equivalence in (the reordered) file1. 617c478bd9Sstevel@tonic-gate * To save space equiv squeezes file1 into a single 627c478bd9Sstevel@tonic-gate * array member in which the equivalence classes 637c478bd9Sstevel@tonic-gate * are simply concatenated, except that their first 647c478bd9Sstevel@tonic-gate * members are flagged by changing sign. 657c478bd9Sstevel@tonic-gate * 667c478bd9Sstevel@tonic-gate * Next the indices that point into member are unsorted into 677c478bd9Sstevel@tonic-gate * array class according to the original order of file0. 687c478bd9Sstevel@tonic-gate * 697c478bd9Sstevel@tonic-gate * The cleverness lies in routine stone. This marches 707c478bd9Sstevel@tonic-gate * through the lines of file0, developing a vector klist 717c478bd9Sstevel@tonic-gate * of "k-candidates". At step i a k-candidate is a matched 727c478bd9Sstevel@tonic-gate * pair of lines x,y (x in file0 y in file1) such that 737c478bd9Sstevel@tonic-gate * there is a common subsequence of lenght k 747c478bd9Sstevel@tonic-gate * between the first i lines of file0 and the first y 757c478bd9Sstevel@tonic-gate * lines of file1, but there is no such subsequence for 767c478bd9Sstevel@tonic-gate * any smaller y. x is the earliest possible mate to y 777c478bd9Sstevel@tonic-gate * that occurs in such a subsequence. 787c478bd9Sstevel@tonic-gate * 797c478bd9Sstevel@tonic-gate * Whenever any of the members of the equivalence class of 807c478bd9Sstevel@tonic-gate * lines in file1 matable to a line in file0 has serial number 817c478bd9Sstevel@tonic-gate * less than the y of some k-candidate, that k-candidate 827c478bd9Sstevel@tonic-gate * with the smallest such y is replaced. The new 837c478bd9Sstevel@tonic-gate * k-candidate is chained (via pred) to the current 847c478bd9Sstevel@tonic-gate * k-1 candidate so that the actual subsequence can 857c478bd9Sstevel@tonic-gate * be recovered. When a member has serial number greater 867c478bd9Sstevel@tonic-gate * that the y of all k-candidates, the klist is extended. 877c478bd9Sstevel@tonic-gate * At the end, the longest subsequence is pulled out 887c478bd9Sstevel@tonic-gate * and placed in the array J by unravel. 897c478bd9Sstevel@tonic-gate * 907c478bd9Sstevel@tonic-gate * With J in hand, the matches there recorded are 917c478bd9Sstevel@tonic-gate * checked against reality to assure that no spurious 927c478bd9Sstevel@tonic-gate * matches have crept in due to hashing. If they have, 937c478bd9Sstevel@tonic-gate * they are broken, and "jackpot " is recorded--a harmless 947c478bd9Sstevel@tonic-gate * matter except that a true match for a spuriously 957c478bd9Sstevel@tonic-gate * mated line may now be unnecessarily reported as a change. 967c478bd9Sstevel@tonic-gate * 977c478bd9Sstevel@tonic-gate * Much of the complexity of the program comes simply 987c478bd9Sstevel@tonic-gate * from trying to minimize core utilization and 997c478bd9Sstevel@tonic-gate * maximize the range of doable problems by dynamically 1007c478bd9Sstevel@tonic-gate * allocating what is needed and reusing what is not. 1017c478bd9Sstevel@tonic-gate * The core requirements for problems larger than somewhat 1027c478bd9Sstevel@tonic-gate * are (in words) 2*length(file0) + length(file1) + 1037c478bd9Sstevel@tonic-gate * 3*(number of k-candidates installed), typically about 1047c478bd9Sstevel@tonic-gate * 6n words for files of length n. 1057c478bd9Sstevel@tonic-gate */ 1067c478bd9Sstevel@tonic-gate #include <stdio.h> 1077c478bd9Sstevel@tonic-gate #include <wchar.h> 1087c478bd9Sstevel@tonic-gate #include <ctype.h> 1097c478bd9Sstevel@tonic-gate #include <stdlib.h> 1107c478bd9Sstevel@tonic-gate #include <limits.h> 1117c478bd9Sstevel@tonic-gate #include <sys/types.h> 1127c478bd9Sstevel@tonic-gate #include <sys/stat.h> 1137c478bd9Sstevel@tonic-gate #include <sys/wait.h> 1147c478bd9Sstevel@tonic-gate #include <unistd.h> 1157c478bd9Sstevel@tonic-gate #include <signal.h> 1167c478bd9Sstevel@tonic-gate #include <fcntl.h> 1177c478bd9Sstevel@tonic-gate #include <dirent.h> 1187c478bd9Sstevel@tonic-gate #include <locale.h> 1197c478bd9Sstevel@tonic-gate #include <stdarg.h> 1207c478bd9Sstevel@tonic-gate #include <errno.h> 1217c478bd9Sstevel@tonic-gate #include <string.h> 1227c478bd9Sstevel@tonic-gate #include "diff.h" 1237c478bd9Sstevel@tonic-gate 1247c478bd9Sstevel@tonic-gate #define CHRTRAN(x) (iflag ? (iswupper(x) ? towlower(x) : (x)) : (x)) 1257c478bd9Sstevel@tonic-gate #define NCCHRTRAN(x) (iswupper(x) ? towlower(x) : (x)) 1267c478bd9Sstevel@tonic-gate #define max(a, b) ((a) < (b) ? (b) : (a)) 1277c478bd9Sstevel@tonic-gate #define min(a, b) ((a) > (b) ? (b) : (a)) 1287c478bd9Sstevel@tonic-gate 1297c478bd9Sstevel@tonic-gate int pref, suff; /* length of prefix and suffix */ 1307c478bd9Sstevel@tonic-gate int *class; /* will be overlaid on file[0] */ 1317c478bd9Sstevel@tonic-gate int *member; /* will be overlaid on file[1] */ 1327c478bd9Sstevel@tonic-gate int *klist; /* will be overlaid on file[0] after class */ 1337c478bd9Sstevel@tonic-gate struct cand *clist; /* merely a free storage pot for candidates */ 1347c478bd9Sstevel@tonic-gate int clen = 0; 1357c478bd9Sstevel@tonic-gate int *J; /* will be overlaid on class */ 1367c478bd9Sstevel@tonic-gate long *ixold; /* will be overlaid on klist */ 1377c478bd9Sstevel@tonic-gate long *ixnew; /* will be overlaid on file[1] */ 1387c478bd9Sstevel@tonic-gate 1397c478bd9Sstevel@tonic-gate static int mbcurmax; 1407c478bd9Sstevel@tonic-gate 1417c478bd9Sstevel@tonic-gate static void error(const char *); 1427c478bd9Sstevel@tonic-gate static void unravel(int); 1437c478bd9Sstevel@tonic-gate static void check(void); 1447c478bd9Sstevel@tonic-gate static void output(void); 1457c478bd9Sstevel@tonic-gate static void change(int, int, int, int); 1467c478bd9Sstevel@tonic-gate static void range(int, int, char *); 1477c478bd9Sstevel@tonic-gate static void fetch(long *, int, int, int, char *, int); 1487c478bd9Sstevel@tonic-gate static void dump_context_vec(void); 1497c478bd9Sstevel@tonic-gate static void diffdir(char **); 1507c478bd9Sstevel@tonic-gate static void setfile(char **, char **, char *); 1517c478bd9Sstevel@tonic-gate static void scanpr(struct dir *, int, char *, char *, 1527c478bd9Sstevel@tonic-gate char *, char *, char *); 1537c478bd9Sstevel@tonic-gate static void only(struct dir *, int); 1547c478bd9Sstevel@tonic-gate static void sort(struct line *, int); 1557c478bd9Sstevel@tonic-gate static void unsort(struct line *, int, int *); 1567c478bd9Sstevel@tonic-gate static void filename(char **, char **, struct stat *, char **); 1577c478bd9Sstevel@tonic-gate static void prepare(int, char *); 1587c478bd9Sstevel@tonic-gate static void prune(void); 1597c478bd9Sstevel@tonic-gate static void equiv(struct line *, int, struct line *, int, int *); 1607c478bd9Sstevel@tonic-gate static void done(void); 1617c478bd9Sstevel@tonic-gate static void noroom(void); 1627c478bd9Sstevel@tonic-gate static void usage(void); 1637c478bd9Sstevel@tonic-gate static void initbuf(FILE *, int, long); 1647c478bd9Sstevel@tonic-gate static void resetbuf(int); 1657c478bd9Sstevel@tonic-gate 1667c478bd9Sstevel@tonic-gate static int stone(int *, int, int *, int *); 1677c478bd9Sstevel@tonic-gate static int newcand(int, int, int); 1687c478bd9Sstevel@tonic-gate static int search(int *, int, int); 1697c478bd9Sstevel@tonic-gate static int skipline(int); 1707c478bd9Sstevel@tonic-gate static int readhash(FILE *, int, char *); 1717c478bd9Sstevel@tonic-gate static int entcmp(struct dir *, struct dir *); 1727c478bd9Sstevel@tonic-gate static int compare(struct dir *); 1737c478bd9Sstevel@tonic-gate static int calldiff(char *); 1747c478bd9Sstevel@tonic-gate static int binary(int); 1757c478bd9Sstevel@tonic-gate static int filebinary(FILE *); 1767c478bd9Sstevel@tonic-gate static int isbinary(char *, int); 1777c478bd9Sstevel@tonic-gate static int useless(char *); 1787c478bd9Sstevel@tonic-gate static char *copytemp(char *); 1797c478bd9Sstevel@tonic-gate static char *pfiletype(mode_t); 1807c478bd9Sstevel@tonic-gate static struct dir *setupdir(char *); 1817c478bd9Sstevel@tonic-gate static wint_t getbufwchar(int, int *); 1827c478bd9Sstevel@tonic-gate static wint_t wcput(wint_t); 1837c478bd9Sstevel@tonic-gate static long ftellbuf(int); 1847c478bd9Sstevel@tonic-gate 1857c478bd9Sstevel@tonic-gate 1867c478bd9Sstevel@tonic-gate /* 1877c478bd9Sstevel@tonic-gate * error message string constants 1887c478bd9Sstevel@tonic-gate */ 1897c478bd9Sstevel@tonic-gate #define BAD_MB_ERR "invalid multibyte character encountered" 1907c478bd9Sstevel@tonic-gate #define NO_PROCS_ERR "no more processes" 1917c478bd9Sstevel@tonic-gate #define NO_MEM_ERR "out of memory" 1927c478bd9Sstevel@tonic-gate 1937c478bd9Sstevel@tonic-gate static void * 1947c478bd9Sstevel@tonic-gate talloc(size_t n) 1957c478bd9Sstevel@tonic-gate { 1967c478bd9Sstevel@tonic-gate void *p; 1977c478bd9Sstevel@tonic-gate p = malloc(n); 1987c478bd9Sstevel@tonic-gate if (p == NULL) 1997c478bd9Sstevel@tonic-gate noroom(); 2007c478bd9Sstevel@tonic-gate return (p); 2017c478bd9Sstevel@tonic-gate } 2027c478bd9Sstevel@tonic-gate 2037c478bd9Sstevel@tonic-gate static void * 2047c478bd9Sstevel@tonic-gate ralloc(void *p, size_t n) /* compacting reallocation */ 2057c478bd9Sstevel@tonic-gate { 2067c478bd9Sstevel@tonic-gate void *q; 2077c478bd9Sstevel@tonic-gate #if 0 2087c478bd9Sstevel@tonic-gate free(p); 2097c478bd9Sstevel@tonic-gate #endif 2107c478bd9Sstevel@tonic-gate q = realloc(p, n); 2117c478bd9Sstevel@tonic-gate if (q == NULL) 2127c478bd9Sstevel@tonic-gate noroom(); 2137c478bd9Sstevel@tonic-gate return (q); 2147c478bd9Sstevel@tonic-gate } 2157c478bd9Sstevel@tonic-gate 2167c478bd9Sstevel@tonic-gate 217*78eb75caSchin int 2187c478bd9Sstevel@tonic-gate main(int argc, char **argv) 2197c478bd9Sstevel@tonic-gate { 2207c478bd9Sstevel@tonic-gate int k; 2217c478bd9Sstevel@tonic-gate char *argp; 2227c478bd9Sstevel@tonic-gate int flag; /* option flag read by getopt() */ 2237c478bd9Sstevel@tonic-gate int i, j; 2247c478bd9Sstevel@tonic-gate char buf1[BUFSIZ], buf2[BUFSIZ]; 2257c478bd9Sstevel@tonic-gate 2267c478bd9Sstevel@tonic-gate 2277c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 2287c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ 2297c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */ 2307c478bd9Sstevel@tonic-gate #endif 2317c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 2327c478bd9Sstevel@tonic-gate 2337c478bd9Sstevel@tonic-gate mbcurmax = MB_CUR_MAX; 2347c478bd9Sstevel@tonic-gate 2357c478bd9Sstevel@tonic-gate diffargv = argv; 2367c478bd9Sstevel@tonic-gate whichtemp = 0; 2377c478bd9Sstevel@tonic-gate while ((flag = getopt(argc, argv, "bitwcuefhnlrsC:D:S:U:")) != EOF) { 2387c478bd9Sstevel@tonic-gate switch (flag) { 2397c478bd9Sstevel@tonic-gate case 'D': 2407c478bd9Sstevel@tonic-gate opt = D_IFDEF; 2417c478bd9Sstevel@tonic-gate wantelses = 1; 2427c478bd9Sstevel@tonic-gate ifdef1 = ""; 2437c478bd9Sstevel@tonic-gate ifdef2 = optarg; 2447c478bd9Sstevel@tonic-gate break; 2457c478bd9Sstevel@tonic-gate 2467c478bd9Sstevel@tonic-gate case 'b': 2477c478bd9Sstevel@tonic-gate bflag = 1; 2487c478bd9Sstevel@tonic-gate break; 2497c478bd9Sstevel@tonic-gate 2507c478bd9Sstevel@tonic-gate case 'C': 2517c478bd9Sstevel@tonic-gate case 'U': 2527c478bd9Sstevel@tonic-gate opt = D_CONTEXT; 2537c478bd9Sstevel@tonic-gate argp = optarg; 2547c478bd9Sstevel@tonic-gate context = 0; 2557c478bd9Sstevel@tonic-gate while (*argp >= '0' && *argp <= '9') 2567c478bd9Sstevel@tonic-gate context *= 10, context += *argp++ - '0'; 2577c478bd9Sstevel@tonic-gate if (*argp) 2587c478bd9Sstevel@tonic-gate error(gettext("use [ -C num | -U num ]")); 2597c478bd9Sstevel@tonic-gate if (flag == 'U') 2607c478bd9Sstevel@tonic-gate uflag++; 2617c478bd9Sstevel@tonic-gate else 2627c478bd9Sstevel@tonic-gate uflag = 0; 2637c478bd9Sstevel@tonic-gate break; 2647c478bd9Sstevel@tonic-gate 2657c478bd9Sstevel@tonic-gate case 'c': 2667c478bd9Sstevel@tonic-gate case 'u': 2677c478bd9Sstevel@tonic-gate opt = D_CONTEXT; 2687c478bd9Sstevel@tonic-gate context = 3; 2697c478bd9Sstevel@tonic-gate if (flag == 'u') 2707c478bd9Sstevel@tonic-gate uflag++; 2717c478bd9Sstevel@tonic-gate else 2727c478bd9Sstevel@tonic-gate uflag = 0; 2737c478bd9Sstevel@tonic-gate break; 2747c478bd9Sstevel@tonic-gate 2757c478bd9Sstevel@tonic-gate case 'e': 2767c478bd9Sstevel@tonic-gate opt = D_EDIT; 2777c478bd9Sstevel@tonic-gate break; 2787c478bd9Sstevel@tonic-gate 2797c478bd9Sstevel@tonic-gate case 'f': 2807c478bd9Sstevel@tonic-gate opt = D_REVERSE; 2817c478bd9Sstevel@tonic-gate break; 2827c478bd9Sstevel@tonic-gate 2837c478bd9Sstevel@tonic-gate case 'h': 2847c478bd9Sstevel@tonic-gate hflag++; 2857c478bd9Sstevel@tonic-gate break; 2867c478bd9Sstevel@tonic-gate 2877c478bd9Sstevel@tonic-gate case 'i': 2887c478bd9Sstevel@tonic-gate iflag = 1; 2897c478bd9Sstevel@tonic-gate break; 2907c478bd9Sstevel@tonic-gate 2917c478bd9Sstevel@tonic-gate case 'l': 2927c478bd9Sstevel@tonic-gate lflag = 1; 2937c478bd9Sstevel@tonic-gate break; 2947c478bd9Sstevel@tonic-gate 2957c478bd9Sstevel@tonic-gate case 'n': 2967c478bd9Sstevel@tonic-gate opt = D_NREVERSE; 2977c478bd9Sstevel@tonic-gate break; 2987c478bd9Sstevel@tonic-gate 2997c478bd9Sstevel@tonic-gate case 'r': 3007c478bd9Sstevel@tonic-gate rflag = 1; 3017c478bd9Sstevel@tonic-gate break; 3027c478bd9Sstevel@tonic-gate 3037c478bd9Sstevel@tonic-gate case 'S': 3047c478bd9Sstevel@tonic-gate (void) strcpy(start, optarg); 3057c478bd9Sstevel@tonic-gate break; 3067c478bd9Sstevel@tonic-gate 3077c478bd9Sstevel@tonic-gate case 's': 3087c478bd9Sstevel@tonic-gate sflag = 1; 3097c478bd9Sstevel@tonic-gate break; 3107c478bd9Sstevel@tonic-gate 3117c478bd9Sstevel@tonic-gate case 't': 3127c478bd9Sstevel@tonic-gate tflag = 1; 3137c478bd9Sstevel@tonic-gate break; 3147c478bd9Sstevel@tonic-gate 3157c478bd9Sstevel@tonic-gate case 'w': 3167c478bd9Sstevel@tonic-gate wflag = 1; 3177c478bd9Sstevel@tonic-gate break; 3187c478bd9Sstevel@tonic-gate 3197c478bd9Sstevel@tonic-gate case '?': 3207c478bd9Sstevel@tonic-gate usage(); 3217c478bd9Sstevel@tonic-gate break; 3227c478bd9Sstevel@tonic-gate 3237c478bd9Sstevel@tonic-gate default: 3247c478bd9Sstevel@tonic-gate /* Not sure how it would get here, but just in case */ 3257c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "diff: "); 3267c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 3277c478bd9Sstevel@tonic-gate gettext("invalid option -%c\n"), flag); 3287c478bd9Sstevel@tonic-gate usage(); 3297c478bd9Sstevel@tonic-gate } 3307c478bd9Sstevel@tonic-gate } 3317c478bd9Sstevel@tonic-gate 3327c478bd9Sstevel@tonic-gate argc -= optind; 3337c478bd9Sstevel@tonic-gate argv = &argv[optind]; 3347c478bd9Sstevel@tonic-gate 3357c478bd9Sstevel@tonic-gate if (opt != D_CONTEXT && uflag) 3367c478bd9Sstevel@tonic-gate uflag = 0; 3377c478bd9Sstevel@tonic-gate 3387c478bd9Sstevel@tonic-gate if (argc != 2) 3397c478bd9Sstevel@tonic-gate error(gettext("two filename arguments required")); 3407c478bd9Sstevel@tonic-gate 3417c478bd9Sstevel@tonic-gate file1 = argv[0]; 3427c478bd9Sstevel@tonic-gate file2 = argv[1]; 3437c478bd9Sstevel@tonic-gate 3447c478bd9Sstevel@tonic-gate if (hflag) { 3457c478bd9Sstevel@tonic-gate if (opt) { 3467c478bd9Sstevel@tonic-gate error( 3477c478bd9Sstevel@tonic-gate gettext("-h doesn't support -e, -f, -n, -c, or -I")); 3487c478bd9Sstevel@tonic-gate } else { 3497c478bd9Sstevel@tonic-gate diffargv[0] = "diffh"; 3507c478bd9Sstevel@tonic-gate (void) execv(diffh, diffargv); 3517c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "diffh: "); 3527c478bd9Sstevel@tonic-gate perror(diffh); 3537c478bd9Sstevel@tonic-gate status = 2; 3547c478bd9Sstevel@tonic-gate done(); 3557c478bd9Sstevel@tonic-gate } 3567c478bd9Sstevel@tonic-gate 3577c478bd9Sstevel@tonic-gate } 3587c478bd9Sstevel@tonic-gate 3597c478bd9Sstevel@tonic-gate if (strcmp(file1, "-") == 0) { 3607c478bd9Sstevel@tonic-gate if (fstat(fileno(stdin), &stb1) == 0) 3617c478bd9Sstevel@tonic-gate stb1.st_mode = S_IFREG; 3627c478bd9Sstevel@tonic-gate else { 3637c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "diff: "); 3647c478bd9Sstevel@tonic-gate perror("stdin"); 3657c478bd9Sstevel@tonic-gate done(); 3667c478bd9Sstevel@tonic-gate } 3677c478bd9Sstevel@tonic-gate } else if (stat(file1, &stb1) < 0) { 3687c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "diff: "); 3697c478bd9Sstevel@tonic-gate perror(file1); 3707c478bd9Sstevel@tonic-gate done(); 3717c478bd9Sstevel@tonic-gate } 3727c478bd9Sstevel@tonic-gate 3737c478bd9Sstevel@tonic-gate if (strcmp(file2, "-") == 0) { 3747c478bd9Sstevel@tonic-gate if (strcmp(file1, "-") == 0) 3757c478bd9Sstevel@tonic-gate error(gettext("cannot specify - -")); 3767c478bd9Sstevel@tonic-gate else { 3777c478bd9Sstevel@tonic-gate if (fstat(fileno(stdin), &stb2) == 0) 3787c478bd9Sstevel@tonic-gate stb2.st_mode = S_IFREG; 3797c478bd9Sstevel@tonic-gate else { 3807c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "diff: "); 3817c478bd9Sstevel@tonic-gate perror("stdin"); 3827c478bd9Sstevel@tonic-gate done(); 3837c478bd9Sstevel@tonic-gate } 3847c478bd9Sstevel@tonic-gate } 3857c478bd9Sstevel@tonic-gate } else if (stat(file2, &stb2) < 0) { 3867c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "diff: "); 3877c478bd9Sstevel@tonic-gate perror(file2); 3887c478bd9Sstevel@tonic-gate done(); 3897c478bd9Sstevel@tonic-gate } 3907c478bd9Sstevel@tonic-gate 3917c478bd9Sstevel@tonic-gate if ((stb1.st_mode & S_IFMT) == S_IFDIR && 3927c478bd9Sstevel@tonic-gate (stb2.st_mode & S_IFMT) == S_IFDIR) { 3937c478bd9Sstevel@tonic-gate diffdir(argv); 3947c478bd9Sstevel@tonic-gate done(); 3957c478bd9Sstevel@tonic-gate } 3967c478bd9Sstevel@tonic-gate 3977c478bd9Sstevel@tonic-gate filename(&file1, &file2, &stb1, &input_file1); 3987c478bd9Sstevel@tonic-gate filename(&file2, &file1, &stb2, &input_file2); 3997c478bd9Sstevel@tonic-gate if ((input[0] = fopen(file1, "r")) == NULL) { 4007c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "diff: "); 4017c478bd9Sstevel@tonic-gate perror(file1); 4027c478bd9Sstevel@tonic-gate status = 2; 4037c478bd9Sstevel@tonic-gate done(); 4047c478bd9Sstevel@tonic-gate } 4057c478bd9Sstevel@tonic-gate initbuf(input[0], 0, 0); 4067c478bd9Sstevel@tonic-gate 4077c478bd9Sstevel@tonic-gate if ((input[1] = fopen(file2, "r")) == NULL) { 4087c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "diff: "); 4097c478bd9Sstevel@tonic-gate perror(file2); 4107c478bd9Sstevel@tonic-gate status = 2; 4117c478bd9Sstevel@tonic-gate done(); 4127c478bd9Sstevel@tonic-gate } 4137c478bd9Sstevel@tonic-gate initbuf(input[1], 1, 0); 4147c478bd9Sstevel@tonic-gate 4157c478bd9Sstevel@tonic-gate if (stb1.st_size != stb2.st_size) 4167c478bd9Sstevel@tonic-gate goto notsame; 4177c478bd9Sstevel@tonic-gate 4187c478bd9Sstevel@tonic-gate for (;;) { 4197c478bd9Sstevel@tonic-gate i = fread(buf1, 1, BUFSIZ, input[0]); 4207c478bd9Sstevel@tonic-gate j = fread(buf2, 1, BUFSIZ, input[1]); 4217c478bd9Sstevel@tonic-gate if (ferror(input[0]) || ferror(input[1])) { 4227c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "diff: "); 4237c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Error reading ")); 4247c478bd9Sstevel@tonic-gate perror(ferror(input[0])? file1:file2); 4257c478bd9Sstevel@tonic-gate (void) fclose(input[0]); 4267c478bd9Sstevel@tonic-gate (void) fclose(input[1]); 4277c478bd9Sstevel@tonic-gate status = 2; 4287c478bd9Sstevel@tonic-gate done(); 4297c478bd9Sstevel@tonic-gate } 4307c478bd9Sstevel@tonic-gate if (i != j) 4317c478bd9Sstevel@tonic-gate goto notsame; 4327c478bd9Sstevel@tonic-gate if (i == 0 && j == 0) { 4337c478bd9Sstevel@tonic-gate /* files are the same; diff -D needs to print one */ 4347c478bd9Sstevel@tonic-gate if (opt == D_IFDEF) { 4357c478bd9Sstevel@tonic-gate rewind(input[0]); 4367c478bd9Sstevel@tonic-gate while (i = fread(buf1, 1, BUFSIZ, input[0])) 4377c478bd9Sstevel@tonic-gate (void) fwrite(buf1, 1, i, stdout); 4387c478bd9Sstevel@tonic-gate } 4397c478bd9Sstevel@tonic-gate (void) fclose(input[0]); 4407c478bd9Sstevel@tonic-gate (void) fclose(input[1]); 4417c478bd9Sstevel@tonic-gate status = 0; 4427c478bd9Sstevel@tonic-gate goto same; /* files don't differ */ 4437c478bd9Sstevel@tonic-gate } 4447c478bd9Sstevel@tonic-gate for (j = 0; j < i; j++) 4457c478bd9Sstevel@tonic-gate if (buf1[j] != buf2[j]) 4467c478bd9Sstevel@tonic-gate goto notsame; 4477c478bd9Sstevel@tonic-gate } 4487c478bd9Sstevel@tonic-gate 4497c478bd9Sstevel@tonic-gate notsame: 4507c478bd9Sstevel@tonic-gate status = 1; 4517c478bd9Sstevel@tonic-gate if (filebinary(input[0]) || filebinary(input[1])) { 4527c478bd9Sstevel@tonic-gate if (ferror(input[0]) || ferror(input[1])) { 4537c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "diff: "); 4547c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Error reading ")); 4557c478bd9Sstevel@tonic-gate perror(ferror(input[0])? file1:file2); 4567c478bd9Sstevel@tonic-gate (void) fclose(input[0]); 4577c478bd9Sstevel@tonic-gate (void) fclose(input[1]); 4587c478bd9Sstevel@tonic-gate status = 2; 4597c478bd9Sstevel@tonic-gate done(); 4607c478bd9Sstevel@tonic-gate } 4617c478bd9Sstevel@tonic-gate (void) printf(gettext("Binary files %s and %s differ\n"), 4627c478bd9Sstevel@tonic-gate file1, file2); 4637c478bd9Sstevel@tonic-gate (void) fclose(input[0]); 4647c478bd9Sstevel@tonic-gate (void) fclose(input[1]); 4657c478bd9Sstevel@tonic-gate done(); 4667c478bd9Sstevel@tonic-gate } 4677c478bd9Sstevel@tonic-gate prepare(0, file1); 4687c478bd9Sstevel@tonic-gate prepare(1, file2); 4697c478bd9Sstevel@tonic-gate prune(); 4707c478bd9Sstevel@tonic-gate sort(sfile[0], slen[0]); 4717c478bd9Sstevel@tonic-gate sort(sfile[1], slen[1]); 4727c478bd9Sstevel@tonic-gate 4737c478bd9Sstevel@tonic-gate member = (int *)file[1]; 4747c478bd9Sstevel@tonic-gate equiv(sfile[0], slen[0], sfile[1], slen[1], member); 4757c478bd9Sstevel@tonic-gate member = (int *)ralloc((void *)member, (slen[1] + 2) * sizeof (int)); 4767c478bd9Sstevel@tonic-gate 4777c478bd9Sstevel@tonic-gate class = (int *)file[0]; 4787c478bd9Sstevel@tonic-gate unsort(sfile[0], slen[0], class); 4797c478bd9Sstevel@tonic-gate class = (int *)ralloc((void *)class, (slen[0] + 2) * sizeof (int)); 4807c478bd9Sstevel@tonic-gate 4817c478bd9Sstevel@tonic-gate klist = (int *)talloc((slen[0] + 2) * sizeof (int)); 4827c478bd9Sstevel@tonic-gate clist = (struct cand *)talloc(sizeof (cand)); 4837c478bd9Sstevel@tonic-gate k = stone(class, slen[0], member, klist); 4847c478bd9Sstevel@tonic-gate free((void *)member); 4857c478bd9Sstevel@tonic-gate free((void *)class); 4867c478bd9Sstevel@tonic-gate 4877c478bd9Sstevel@tonic-gate J = (int *)talloc((len[0] + 2) * sizeof (int)); 4887c478bd9Sstevel@tonic-gate unravel(klist[k]); 4897c478bd9Sstevel@tonic-gate free((char *)clist); 4907c478bd9Sstevel@tonic-gate free((char *)klist); 4917c478bd9Sstevel@tonic-gate 4927c478bd9Sstevel@tonic-gate ixold = (long *)talloc((len[0] + 2) * sizeof (long)); 4937c478bd9Sstevel@tonic-gate ixnew = (long *)talloc((len[1] + 2) * sizeof (long)); 4947c478bd9Sstevel@tonic-gate check(); 4957c478bd9Sstevel@tonic-gate output(); 4967c478bd9Sstevel@tonic-gate status = anychange; 4977c478bd9Sstevel@tonic-gate 4987c478bd9Sstevel@tonic-gate same: 4997c478bd9Sstevel@tonic-gate if (opt == D_CONTEXT && anychange == 0) 5007c478bd9Sstevel@tonic-gate (void) printf(gettext("No differences encountered\n")); 5017c478bd9Sstevel@tonic-gate done(); 5027c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 503*78eb75caSchin return (0); 5047c478bd9Sstevel@tonic-gate } 5057c478bd9Sstevel@tonic-gate 5067c478bd9Sstevel@tonic-gate static int 5077c478bd9Sstevel@tonic-gate stone(int *a, int n, int *b, int *c) 5087c478bd9Sstevel@tonic-gate { 5097c478bd9Sstevel@tonic-gate int i, k, y; 5107c478bd9Sstevel@tonic-gate int j, l; 5117c478bd9Sstevel@tonic-gate int oldc, tc; 5127c478bd9Sstevel@tonic-gate int oldl; 5137c478bd9Sstevel@tonic-gate 5147c478bd9Sstevel@tonic-gate k = 0; 5157c478bd9Sstevel@tonic-gate c[0] = newcand(0, 0, 0); 5167c478bd9Sstevel@tonic-gate for (i = 1; i <= n; i++) { 5177c478bd9Sstevel@tonic-gate j = a[i]; 5187c478bd9Sstevel@tonic-gate if (j == 0) 5197c478bd9Sstevel@tonic-gate continue; 5207c478bd9Sstevel@tonic-gate y = -b[j]; 5217c478bd9Sstevel@tonic-gate oldl = 0; 5227c478bd9Sstevel@tonic-gate oldc = c[0]; 5237c478bd9Sstevel@tonic-gate do { 5247c478bd9Sstevel@tonic-gate if (y <= clist[oldc].y) 5257c478bd9Sstevel@tonic-gate continue; 5267c478bd9Sstevel@tonic-gate l = search(c, k, y); 5277c478bd9Sstevel@tonic-gate if (l != oldl+1) 5287c478bd9Sstevel@tonic-gate oldc = c[l-1]; 5297c478bd9Sstevel@tonic-gate if (l <= k) { 5307c478bd9Sstevel@tonic-gate if (clist[c[l]].y <= y) 5317c478bd9Sstevel@tonic-gate continue; 5327c478bd9Sstevel@tonic-gate tc = c[l]; 5337c478bd9Sstevel@tonic-gate c[l] = newcand(i, y, oldc); 5347c478bd9Sstevel@tonic-gate oldc = tc; 5357c478bd9Sstevel@tonic-gate oldl = l; 5367c478bd9Sstevel@tonic-gate } else { 5377c478bd9Sstevel@tonic-gate c[l] = newcand(i, y, oldc); 5387c478bd9Sstevel@tonic-gate k++; 5397c478bd9Sstevel@tonic-gate break; 5407c478bd9Sstevel@tonic-gate } 5417c478bd9Sstevel@tonic-gate } while ((y = b[++j]) > 0); 5427c478bd9Sstevel@tonic-gate } 5437c478bd9Sstevel@tonic-gate return (k); 5447c478bd9Sstevel@tonic-gate } 5457c478bd9Sstevel@tonic-gate 5467c478bd9Sstevel@tonic-gate static int 5477c478bd9Sstevel@tonic-gate newcand(int x, int y, int pred) 5487c478bd9Sstevel@tonic-gate { 5497c478bd9Sstevel@tonic-gate struct cand *q; 5507c478bd9Sstevel@tonic-gate 5517c478bd9Sstevel@tonic-gate clist = (struct cand *)ralloc((void *)clist, ++clen * sizeof (cand)); 5527c478bd9Sstevel@tonic-gate q = clist + clen -1; 5537c478bd9Sstevel@tonic-gate q->x = x; 5547c478bd9Sstevel@tonic-gate q->y = y; 5557c478bd9Sstevel@tonic-gate q->pred = pred; 5567c478bd9Sstevel@tonic-gate return (clen - 1); 5577c478bd9Sstevel@tonic-gate } 5587c478bd9Sstevel@tonic-gate 5597c478bd9Sstevel@tonic-gate static int 5607c478bd9Sstevel@tonic-gate search(int *c, int k, int y) 5617c478bd9Sstevel@tonic-gate { 5627c478bd9Sstevel@tonic-gate int i, j, l; 5637c478bd9Sstevel@tonic-gate int t; 5647c478bd9Sstevel@tonic-gate 5657c478bd9Sstevel@tonic-gate if (clist[c[k]].y < y) /* quick look for typical case */ 5667c478bd9Sstevel@tonic-gate return (k + 1); 5677c478bd9Sstevel@tonic-gate i = 0; 5687c478bd9Sstevel@tonic-gate j = k+1; 5697c478bd9Sstevel@tonic-gate while ((l = (i + j) / 2) > i) { 5707c478bd9Sstevel@tonic-gate t = clist[c[l]].y; 5717c478bd9Sstevel@tonic-gate if (t > y) 5727c478bd9Sstevel@tonic-gate j = l; 5737c478bd9Sstevel@tonic-gate else if (t < y) 5747c478bd9Sstevel@tonic-gate i = l; 5757c478bd9Sstevel@tonic-gate else 5767c478bd9Sstevel@tonic-gate return (l); 5777c478bd9Sstevel@tonic-gate } 5787c478bd9Sstevel@tonic-gate return (l + 1); 5797c478bd9Sstevel@tonic-gate } 5807c478bd9Sstevel@tonic-gate 5817c478bd9Sstevel@tonic-gate static void 5827c478bd9Sstevel@tonic-gate unravel(int p) 5837c478bd9Sstevel@tonic-gate { 5847c478bd9Sstevel@tonic-gate int i; 5857c478bd9Sstevel@tonic-gate struct cand *q; 5867c478bd9Sstevel@tonic-gate 5877c478bd9Sstevel@tonic-gate for (i = 0; i <= len[0]; i++) 5887c478bd9Sstevel@tonic-gate J[i] = i <= pref ? i : 5897c478bd9Sstevel@tonic-gate i > len[0] - suff ? i + len[1] - len[0]: 5907c478bd9Sstevel@tonic-gate 0; 5917c478bd9Sstevel@tonic-gate for (q = clist + p; q->y != 0; q = clist + q->pred) 5927c478bd9Sstevel@tonic-gate J[q->x + pref] = q->y + pref; 5937c478bd9Sstevel@tonic-gate } 5947c478bd9Sstevel@tonic-gate 5957c478bd9Sstevel@tonic-gate /* 5967c478bd9Sstevel@tonic-gate * check does double duty: 5977c478bd9Sstevel@tonic-gate * 1. ferret out any fortuitous correspondences due to confounding by 5987c478bd9Sstevel@tonic-gate * hashing (which result in "jackpot") 5997c478bd9Sstevel@tonic-gate * 2. collect random access indexes to the two files 6007c478bd9Sstevel@tonic-gate */ 6017c478bd9Sstevel@tonic-gate 6027c478bd9Sstevel@tonic-gate static void 6037c478bd9Sstevel@tonic-gate check(void) 6047c478bd9Sstevel@tonic-gate { 6057c478bd9Sstevel@tonic-gate wint_t c, d; 6067c478bd9Sstevel@tonic-gate int i, j; 6077c478bd9Sstevel@tonic-gate /* int jackpot; */ 6087c478bd9Sstevel@tonic-gate int mlen; 6097c478bd9Sstevel@tonic-gate long ctold, ctnew; 6107c478bd9Sstevel@tonic-gate 6117c478bd9Sstevel@tonic-gate resetbuf(0); 6127c478bd9Sstevel@tonic-gate resetbuf(1); 6137c478bd9Sstevel@tonic-gate 6147c478bd9Sstevel@tonic-gate j = 1; 6157c478bd9Sstevel@tonic-gate ixold[0] = ixnew[0] = 0; 6167c478bd9Sstevel@tonic-gate /* jackpot = 0; */ 6177c478bd9Sstevel@tonic-gate 6187c478bd9Sstevel@tonic-gate /* 6197c478bd9Sstevel@tonic-gate * ctold and ctnew are byte positions within the file (suitable for 6207c478bd9Sstevel@tonic-gate * lseek()). After we get a character with getwc(), instead of 6217c478bd9Sstevel@tonic-gate * just incrementing the byte position by 1, we have to determine 6227c478bd9Sstevel@tonic-gate * how many bytes the character actually is. This is the reason for 6237c478bd9Sstevel@tonic-gate * the wctomb() calls here and in skipline(). 6247c478bd9Sstevel@tonic-gate */ 6257c478bd9Sstevel@tonic-gate ctold = ctnew = 0; 6267c478bd9Sstevel@tonic-gate for (i = 1; i <= len[0]; i++) { 6277c478bd9Sstevel@tonic-gate if (J[i] == 0) { 6287c478bd9Sstevel@tonic-gate ixold[i] = ctold += skipline(0); 6297c478bd9Sstevel@tonic-gate continue; 6307c478bd9Sstevel@tonic-gate } 6317c478bd9Sstevel@tonic-gate while (j < J[i]) { 6327c478bd9Sstevel@tonic-gate ixnew[j] = ctnew += skipline(1); 6337c478bd9Sstevel@tonic-gate j++; 6347c478bd9Sstevel@tonic-gate } 6357c478bd9Sstevel@tonic-gate if (bflag || wflag || iflag) { 6367c478bd9Sstevel@tonic-gate for (;;) { 6377c478bd9Sstevel@tonic-gate c = getbufwchar(0, &mlen); 6387c478bd9Sstevel@tonic-gate ctold += mlen; 6397c478bd9Sstevel@tonic-gate d = getbufwchar(1, &mlen); 6407c478bd9Sstevel@tonic-gate ctnew += mlen; 6417c478bd9Sstevel@tonic-gate 6427c478bd9Sstevel@tonic-gate if (bflag && iswspace(c) && iswspace(d)) { 6437c478bd9Sstevel@tonic-gate while (iswspace(c)) { 6447c478bd9Sstevel@tonic-gate if (c == '\n' || c == WEOF) 6457c478bd9Sstevel@tonic-gate break; 6467c478bd9Sstevel@tonic-gate 6477c478bd9Sstevel@tonic-gate c = getbufwchar(0, &mlen); 6487c478bd9Sstevel@tonic-gate ctold += mlen; 6497c478bd9Sstevel@tonic-gate } 6507c478bd9Sstevel@tonic-gate while (iswspace(d)) { 6517c478bd9Sstevel@tonic-gate if (d == '\n' || d == WEOF) 6527c478bd9Sstevel@tonic-gate break; 6537c478bd9Sstevel@tonic-gate 6547c478bd9Sstevel@tonic-gate d = getbufwchar(1, &mlen); 6557c478bd9Sstevel@tonic-gate ctnew += mlen; 6567c478bd9Sstevel@tonic-gate } 6577c478bd9Sstevel@tonic-gate } else if (wflag) { 6587c478bd9Sstevel@tonic-gate while (iswspace(c) && c != '\n') { 6597c478bd9Sstevel@tonic-gate c = getbufwchar(0, &mlen); 6607c478bd9Sstevel@tonic-gate ctold += mlen; 6617c478bd9Sstevel@tonic-gate } 6627c478bd9Sstevel@tonic-gate while (iswspace(d) && d != '\n') { 6637c478bd9Sstevel@tonic-gate d = getbufwchar(1, &mlen); 6647c478bd9Sstevel@tonic-gate ctnew += mlen; 6657c478bd9Sstevel@tonic-gate } 6667c478bd9Sstevel@tonic-gate } 6677c478bd9Sstevel@tonic-gate if (c == WEOF || d == WEOF) { 6687c478bd9Sstevel@tonic-gate if (c != d) { 6697c478bd9Sstevel@tonic-gate /* jackpot++; */ 6707c478bd9Sstevel@tonic-gate J[i] = 0; 6717c478bd9Sstevel@tonic-gate if (c != '\n' && c != WEOF) 6727c478bd9Sstevel@tonic-gate ctold += skipline(0); 6737c478bd9Sstevel@tonic-gate if (d != '\n' && d != WEOF) 6747c478bd9Sstevel@tonic-gate ctnew += skipline(1); 6757c478bd9Sstevel@tonic-gate break; 6767c478bd9Sstevel@tonic-gate } 6777c478bd9Sstevel@tonic-gate break; 6787c478bd9Sstevel@tonic-gate } else { 6797c478bd9Sstevel@tonic-gate if (CHRTRAN(c) != CHRTRAN(d)) { 6807c478bd9Sstevel@tonic-gate /* jackpot++; */ 6817c478bd9Sstevel@tonic-gate J[i] = 0; 6827c478bd9Sstevel@tonic-gate if (c != '\n') 6837c478bd9Sstevel@tonic-gate ctold += skipline(0); 6847c478bd9Sstevel@tonic-gate if (d != '\n') 6857c478bd9Sstevel@tonic-gate ctnew += skipline(1); 6867c478bd9Sstevel@tonic-gate break; 6877c478bd9Sstevel@tonic-gate } 6887c478bd9Sstevel@tonic-gate if (c == '\n') 6897c478bd9Sstevel@tonic-gate break; 6907c478bd9Sstevel@tonic-gate } 6917c478bd9Sstevel@tonic-gate } 6927c478bd9Sstevel@tonic-gate } else { 6937c478bd9Sstevel@tonic-gate for (;;) { 6947c478bd9Sstevel@tonic-gate c = getbufwchar(0, &mlen); 6957c478bd9Sstevel@tonic-gate ctold += mlen; 6967c478bd9Sstevel@tonic-gate d = getbufwchar(1, &mlen); 6977c478bd9Sstevel@tonic-gate ctnew += mlen; 6987c478bd9Sstevel@tonic-gate if (c != d) { 6997c478bd9Sstevel@tonic-gate /* jackpot++; */ 7007c478bd9Sstevel@tonic-gate J[i] = 0; 7017c478bd9Sstevel@tonic-gate if (c != '\n' && c != WEOF) 7027c478bd9Sstevel@tonic-gate ctold += skipline(0); 7037c478bd9Sstevel@tonic-gate if (d != '\n' && d != WEOF) 7047c478bd9Sstevel@tonic-gate ctnew += skipline(1); 7057c478bd9Sstevel@tonic-gate break; 7067c478bd9Sstevel@tonic-gate } 7077c478bd9Sstevel@tonic-gate if (c == '\n' || c == WEOF) 7087c478bd9Sstevel@tonic-gate break; 7097c478bd9Sstevel@tonic-gate } 7107c478bd9Sstevel@tonic-gate } 7117c478bd9Sstevel@tonic-gate ixold[i] = ctold; 7127c478bd9Sstevel@tonic-gate ixnew[j] = ctnew; 7137c478bd9Sstevel@tonic-gate j++; 7147c478bd9Sstevel@tonic-gate } 7157c478bd9Sstevel@tonic-gate for (; j <= len[1]; j++) { 7167c478bd9Sstevel@tonic-gate ixnew[j] = ctnew += skipline(1); 7177c478bd9Sstevel@tonic-gate } 7187c478bd9Sstevel@tonic-gate 7197c478bd9Sstevel@tonic-gate /* if(jackpot) */ 7207c478bd9Sstevel@tonic-gate /* fprintf(stderr, "diff: jackpot\n"); */ 7217c478bd9Sstevel@tonic-gate } 7227c478bd9Sstevel@tonic-gate 7237c478bd9Sstevel@tonic-gate static int 7247c478bd9Sstevel@tonic-gate skipline(int f) 7257c478bd9Sstevel@tonic-gate { 7267c478bd9Sstevel@tonic-gate int i; 7277c478bd9Sstevel@tonic-gate wint_t c; 7287c478bd9Sstevel@tonic-gate int mlen; 7297c478bd9Sstevel@tonic-gate 7307c478bd9Sstevel@tonic-gate for (i = 1; c = getbufwchar(f, &mlen); ) { 7317c478bd9Sstevel@tonic-gate if (c == '\n' || c == WEOF) 7327c478bd9Sstevel@tonic-gate return (i); 7337c478bd9Sstevel@tonic-gate i += mlen; 7347c478bd9Sstevel@tonic-gate } 7357c478bd9Sstevel@tonic-gate return (i); 7367c478bd9Sstevel@tonic-gate } 7377c478bd9Sstevel@tonic-gate 7387c478bd9Sstevel@tonic-gate static void 7397c478bd9Sstevel@tonic-gate output(void) 7407c478bd9Sstevel@tonic-gate { 7417c478bd9Sstevel@tonic-gate int m; 7427c478bd9Sstevel@tonic-gate wint_t wc; 7437c478bd9Sstevel@tonic-gate int i0, i1, j1; 7447c478bd9Sstevel@tonic-gate int j0; 7457c478bd9Sstevel@tonic-gate int mlen; 7467c478bd9Sstevel@tonic-gate 7477c478bd9Sstevel@tonic-gate resetbuf(0); 7487c478bd9Sstevel@tonic-gate resetbuf(1); 7497c478bd9Sstevel@tonic-gate 7507c478bd9Sstevel@tonic-gate m = len[0]; 7517c478bd9Sstevel@tonic-gate J[0] = 0; 7527c478bd9Sstevel@tonic-gate J[m + 1] = len[1] + 1; 7537c478bd9Sstevel@tonic-gate if (opt != D_EDIT) 7547c478bd9Sstevel@tonic-gate for (i0 = 1; i0 <= m; i0 = i1+1) { 7557c478bd9Sstevel@tonic-gate while (i0 <= m && J[i0] == J[i0 - 1] + 1) 7567c478bd9Sstevel@tonic-gate i0++; 7577c478bd9Sstevel@tonic-gate j0 = J[i0 - 1] + 1; 7587c478bd9Sstevel@tonic-gate i1 = i0 - 1; 7597c478bd9Sstevel@tonic-gate while (i1 < m && J[i1 + 1] == 0) 7607c478bd9Sstevel@tonic-gate i1++; 7617c478bd9Sstevel@tonic-gate j1 = J[i1 + 1] - 1; 7627c478bd9Sstevel@tonic-gate J[i1] = j1; 7637c478bd9Sstevel@tonic-gate change(i0, i1, j0, j1); 7647c478bd9Sstevel@tonic-gate } else for (i0 = m; i0 >= 1; i0 = i1 - 1) { 7657c478bd9Sstevel@tonic-gate while (i0 >= 1 && J[i0] == J[i0 + 1] - 1 && J[i0] != 0) 7667c478bd9Sstevel@tonic-gate i0--; 7677c478bd9Sstevel@tonic-gate j0 = J[i0 + 1] - 1; 7687c478bd9Sstevel@tonic-gate i1 = i0 + 1; 7697c478bd9Sstevel@tonic-gate while (i1 > 1 && J[i1 - 1] == 0) 7707c478bd9Sstevel@tonic-gate i1--; 7717c478bd9Sstevel@tonic-gate j1 = J[i1 - 1] + 1; 7727c478bd9Sstevel@tonic-gate J[i1] = j1; 7737c478bd9Sstevel@tonic-gate change(i1, i0, j1, j0); 7747c478bd9Sstevel@tonic-gate } 7757c478bd9Sstevel@tonic-gate if (m == 0) 7767c478bd9Sstevel@tonic-gate change(1, 0, 1, len[1]); 7777c478bd9Sstevel@tonic-gate if (opt == D_IFDEF) { 7787c478bd9Sstevel@tonic-gate for (;;) { 7797c478bd9Sstevel@tonic-gate wc = getbufwchar(0, &mlen); 7807c478bd9Sstevel@tonic-gate if (wc == WEOF) 7817c478bd9Sstevel@tonic-gate return; 7827c478bd9Sstevel@tonic-gate (void) wcput(wc); 7837c478bd9Sstevel@tonic-gate } 7847c478bd9Sstevel@tonic-gate } 7857c478bd9Sstevel@tonic-gate if (anychange && opt == D_CONTEXT) 7867c478bd9Sstevel@tonic-gate dump_context_vec(); 7877c478bd9Sstevel@tonic-gate } 7887c478bd9Sstevel@tonic-gate 7897c478bd9Sstevel@tonic-gate 7907c478bd9Sstevel@tonic-gate /* 7917c478bd9Sstevel@tonic-gate * indicate that there is a difference between lines a and b of the from file 7927c478bd9Sstevel@tonic-gate * to get to lines c to d of the to file. 7937c478bd9Sstevel@tonic-gate * If a is greater then b then there are no lines in the from file involved 7947c478bd9Sstevel@tonic-gate * and this means that there were lines appended (beginning at b). 7957c478bd9Sstevel@tonic-gate * If c is greater than d then there are lines missing from the to file. 7967c478bd9Sstevel@tonic-gate */ 7977c478bd9Sstevel@tonic-gate static void 7987c478bd9Sstevel@tonic-gate change(int a, int b, int c, int d) 7997c478bd9Sstevel@tonic-gate { 8007c478bd9Sstevel@tonic-gate char time_buf[BUFSIZ]; 8017c478bd9Sstevel@tonic-gate char *dcmsg; 8027c478bd9Sstevel@tonic-gate 8037c478bd9Sstevel@tonic-gate if (opt != D_IFDEF && a > b && c > d) 8047c478bd9Sstevel@tonic-gate return; 8057c478bd9Sstevel@tonic-gate if (anychange == 0) { 8067c478bd9Sstevel@tonic-gate anychange = 1; 8077c478bd9Sstevel@tonic-gate if (opt == D_CONTEXT) { 8087c478bd9Sstevel@tonic-gate /* 8097c478bd9Sstevel@tonic-gate * TRANSLATION_NOTE_FOR_DC 8107c478bd9Sstevel@tonic-gate * This message is the format of file 8117c478bd9Sstevel@tonic-gate * timestamps written with the -C and 8127c478bd9Sstevel@tonic-gate * -c options. 8137c478bd9Sstevel@tonic-gate * %a -- locale's abbreviated weekday name 8147c478bd9Sstevel@tonic-gate * %b -- locale's abbreviated month name 8157c478bd9Sstevel@tonic-gate * %e -- day of month [1,31] 8167c478bd9Sstevel@tonic-gate * %T -- Time as %H:%M:%S 8177c478bd9Sstevel@tonic-gate * %Y -- Year, including the century 8187c478bd9Sstevel@tonic-gate */ 8197c478bd9Sstevel@tonic-gate dcmsg = dcgettext(NULL, "%a %b %e %T %Y", LC_TIME); 8207c478bd9Sstevel@tonic-gate (void) cftime(time_buf, dcmsg, &stb1.st_mtime); 8217c478bd9Sstevel@tonic-gate if (uflag) 8227c478bd9Sstevel@tonic-gate (void) printf("--- %s %s\n", input_file1, 8237c478bd9Sstevel@tonic-gate time_buf); 8247c478bd9Sstevel@tonic-gate else 8257c478bd9Sstevel@tonic-gate (void) printf("*** %s %s\n", input_file1, 8267c478bd9Sstevel@tonic-gate time_buf); 8277c478bd9Sstevel@tonic-gate (void) cftime(time_buf, dcmsg, &stb2.st_mtime); 8287c478bd9Sstevel@tonic-gate if (uflag) 8297c478bd9Sstevel@tonic-gate (void) printf("+++ %s %s\n", input_file2, 8307c478bd9Sstevel@tonic-gate time_buf); 8317c478bd9Sstevel@tonic-gate else 8327c478bd9Sstevel@tonic-gate (void) printf("--- %s %s\n", input_file2, 8337c478bd9Sstevel@tonic-gate time_buf); 8347c478bd9Sstevel@tonic-gate 8357c478bd9Sstevel@tonic-gate context_vec_start = (struct context_vec *) 8367c478bd9Sstevel@tonic-gate malloc(MAX_CONTEXT * 8377c478bd9Sstevel@tonic-gate sizeof (struct context_vec)); 8387c478bd9Sstevel@tonic-gate if (context_vec_start == NULL) 8397c478bd9Sstevel@tonic-gate error(gettext(NO_MEM_ERR)); 8407c478bd9Sstevel@tonic-gate 8417c478bd9Sstevel@tonic-gate context_vec_end = context_vec_start + (MAX_CONTEXT - 1); 8427c478bd9Sstevel@tonic-gate context_vec_ptr = context_vec_start - 1; 8437c478bd9Sstevel@tonic-gate } 8447c478bd9Sstevel@tonic-gate } 8457c478bd9Sstevel@tonic-gate 8467c478bd9Sstevel@tonic-gate if (opt == D_CONTEXT) { 8477c478bd9Sstevel@tonic-gate /* 8487c478bd9Sstevel@tonic-gate * if this new change is within 'context' lines of 8497c478bd9Sstevel@tonic-gate * the previous change, just add it to the change 8507c478bd9Sstevel@tonic-gate * record. If the record is full or if this 8517c478bd9Sstevel@tonic-gate * change is more than 'context' lines from the previous 8527c478bd9Sstevel@tonic-gate * change, dump the record, reset it & add the new change. 8537c478bd9Sstevel@tonic-gate */ 8547c478bd9Sstevel@tonic-gate if (context_vec_ptr >= context_vec_end || 8557c478bd9Sstevel@tonic-gate (context_vec_ptr >= context_vec_start && 8567c478bd9Sstevel@tonic-gate a > (context_vec_ptr->b + 2 * context) && 8577c478bd9Sstevel@tonic-gate c > (context_vec_ptr->d + 2 * context))) 8587c478bd9Sstevel@tonic-gate dump_context_vec(); 8597c478bd9Sstevel@tonic-gate 8607c478bd9Sstevel@tonic-gate context_vec_ptr++; 8617c478bd9Sstevel@tonic-gate context_vec_ptr->a = a; 8627c478bd9Sstevel@tonic-gate context_vec_ptr->b = b; 8637c478bd9Sstevel@tonic-gate context_vec_ptr->c = c; 8647c478bd9Sstevel@tonic-gate context_vec_ptr->d = d; 8657c478bd9Sstevel@tonic-gate return; 8667c478bd9Sstevel@tonic-gate } 8677c478bd9Sstevel@tonic-gate 8687c478bd9Sstevel@tonic-gate switch (opt) { 8697c478bd9Sstevel@tonic-gate case D_NORMAL: 8707c478bd9Sstevel@tonic-gate case D_EDIT: 8717c478bd9Sstevel@tonic-gate range(a, b, ","); 8727c478bd9Sstevel@tonic-gate (void) putchar(a > b ? 'a' : c > d ? 'd' : 'c'); 8737c478bd9Sstevel@tonic-gate if (opt == D_NORMAL) range(c, d, ","); 8747c478bd9Sstevel@tonic-gate (void) printf("\n"); 8757c478bd9Sstevel@tonic-gate break; 8767c478bd9Sstevel@tonic-gate case D_REVERSE: 8777c478bd9Sstevel@tonic-gate (void) putchar(a > b ? 'a' : c > d ? 'd' : 'c'); 8787c478bd9Sstevel@tonic-gate range(a, b, " "); 8797c478bd9Sstevel@tonic-gate (void) printf("\n"); 8807c478bd9Sstevel@tonic-gate break; 8817c478bd9Sstevel@tonic-gate case D_NREVERSE: 8827c478bd9Sstevel@tonic-gate if (a > b) 8837c478bd9Sstevel@tonic-gate (void) printf("a%d %d\n", b, d - c + 1); 8847c478bd9Sstevel@tonic-gate else { 8857c478bd9Sstevel@tonic-gate (void) printf("d%d %d\n", a, b - a + 1); 8867c478bd9Sstevel@tonic-gate if (!(c > d)) 8877c478bd9Sstevel@tonic-gate /* add changed lines */ 8887c478bd9Sstevel@tonic-gate (void) printf("a%d %d\n", b, d - c + 1); 8897c478bd9Sstevel@tonic-gate } 8907c478bd9Sstevel@tonic-gate break; 8917c478bd9Sstevel@tonic-gate } 8927c478bd9Sstevel@tonic-gate if (opt == D_NORMAL || opt == D_IFDEF) { 8937c478bd9Sstevel@tonic-gate fetch(ixold, a, b, 0, "< ", 1); 8947c478bd9Sstevel@tonic-gate if (a <= b && c <= d && opt == D_NORMAL) 8957c478bd9Sstevel@tonic-gate (void) prints("---\n"); 8967c478bd9Sstevel@tonic-gate } 8977c478bd9Sstevel@tonic-gate fetch(ixnew, c, d, 1, opt == D_NORMAL?"> ":empty, 0); 8987c478bd9Sstevel@tonic-gate if ((opt == D_EDIT || opt == D_REVERSE) && c <= d) 8997c478bd9Sstevel@tonic-gate (void) prints(".\n"); 9007c478bd9Sstevel@tonic-gate if (inifdef) { 9017c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "#endif /* %s */\n", endifname); 9027c478bd9Sstevel@tonic-gate inifdef = 0; 9037c478bd9Sstevel@tonic-gate } 9047c478bd9Sstevel@tonic-gate } 9057c478bd9Sstevel@tonic-gate 9067c478bd9Sstevel@tonic-gate static void 9077c478bd9Sstevel@tonic-gate range(int a, int b, char *separator) 9087c478bd9Sstevel@tonic-gate { 9097c478bd9Sstevel@tonic-gate (void) printf("%d", a > b ? b : a); 9107c478bd9Sstevel@tonic-gate if (a < b) { 9117c478bd9Sstevel@tonic-gate (void) printf("%s%d", separator, b); 9127c478bd9Sstevel@tonic-gate } 9137c478bd9Sstevel@tonic-gate } 9147c478bd9Sstevel@tonic-gate 9157c478bd9Sstevel@tonic-gate static void 9167c478bd9Sstevel@tonic-gate fetch(long *f, int a, int b, int filen, char *s, int oldfile) 9177c478bd9Sstevel@tonic-gate { 9187c478bd9Sstevel@tonic-gate int i; 9197c478bd9Sstevel@tonic-gate int col; 9207c478bd9Sstevel@tonic-gate int nc; 9217c478bd9Sstevel@tonic-gate int mlen = 0; 9227c478bd9Sstevel@tonic-gate wint_t ch; 9237c478bd9Sstevel@tonic-gate FILE *lb; 9247c478bd9Sstevel@tonic-gate 9257c478bd9Sstevel@tonic-gate lb = input[filen]; 9267c478bd9Sstevel@tonic-gate /* 9277c478bd9Sstevel@tonic-gate * When doing #ifdef's, copy down to current line 9287c478bd9Sstevel@tonic-gate * if this is the first file, so that stuff makes it to output. 9297c478bd9Sstevel@tonic-gate */ 9307c478bd9Sstevel@tonic-gate if (opt == D_IFDEF && oldfile) { 9317c478bd9Sstevel@tonic-gate long curpos = ftellbuf(filen); 9327c478bd9Sstevel@tonic-gate /* print through if append (a>b), else to (nb: 0 vs 1 orig) */ 9337c478bd9Sstevel@tonic-gate nc = f[(a > b) ? b : (a - 1) ] - curpos; 9347c478bd9Sstevel@tonic-gate for (i = 0; i < nc; i += mlen) { 9357c478bd9Sstevel@tonic-gate ch = getbufwchar(filen, &mlen); 9367c478bd9Sstevel@tonic-gate if (ch == WEOF) { 9377c478bd9Sstevel@tonic-gate (void) putchar('\n'); 9387c478bd9Sstevel@tonic-gate break; 9397c478bd9Sstevel@tonic-gate } else { 9407c478bd9Sstevel@tonic-gate (void) wcput(ch); 9417c478bd9Sstevel@tonic-gate } 9427c478bd9Sstevel@tonic-gate } 9437c478bd9Sstevel@tonic-gate } 9447c478bd9Sstevel@tonic-gate if (a > b) 9457c478bd9Sstevel@tonic-gate return; 9467c478bd9Sstevel@tonic-gate if (opt == D_IFDEF) { 9477c478bd9Sstevel@tonic-gate int oneflag = (*ifdef1 != '\0') != (*ifdef2 != '\0'); 9487c478bd9Sstevel@tonic-gate if (inifdef) 9497c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "#else /* %s%s */\n", 9507c478bd9Sstevel@tonic-gate oneflag && oldfile == 1 ? "!" : "", ifdef2); 9517c478bd9Sstevel@tonic-gate else { 9527c478bd9Sstevel@tonic-gate if (oneflag) { 9537c478bd9Sstevel@tonic-gate /* There was only one ifdef given */ 9547c478bd9Sstevel@tonic-gate endifname = ifdef2; 9557c478bd9Sstevel@tonic-gate if (oldfile) 9567c478bd9Sstevel@tonic-gate (void) fprintf(stdout, 9577c478bd9Sstevel@tonic-gate "#ifndef %s\n", endifname); 9587c478bd9Sstevel@tonic-gate else 9597c478bd9Sstevel@tonic-gate (void) fprintf(stdout, 9607c478bd9Sstevel@tonic-gate "#ifdef %s\n", endifname); 9617c478bd9Sstevel@tonic-gate } else { 9627c478bd9Sstevel@tonic-gate endifname = oldfile ? ifdef1 : ifdef2; 9637c478bd9Sstevel@tonic-gate (void) fprintf(stdout, 9647c478bd9Sstevel@tonic-gate "#ifdef %s\n", endifname); 9657c478bd9Sstevel@tonic-gate } 9667c478bd9Sstevel@tonic-gate } 9677c478bd9Sstevel@tonic-gate inifdef = 1 + oldfile; 9687c478bd9Sstevel@tonic-gate } 9697c478bd9Sstevel@tonic-gate 9707c478bd9Sstevel@tonic-gate for (i = a; i <= b; i++) { 9717c478bd9Sstevel@tonic-gate (void) fseek(lb, f[i - 1], SEEK_SET); 9727c478bd9Sstevel@tonic-gate initbuf(lb, filen, f[i - 1]); 9737c478bd9Sstevel@tonic-gate if (opt != D_IFDEF) 9747c478bd9Sstevel@tonic-gate (void) prints(s); 9757c478bd9Sstevel@tonic-gate col = 0; 9767c478bd9Sstevel@tonic-gate while (ch = getbufwchar(filen, &mlen)) { 9777c478bd9Sstevel@tonic-gate if (ch != '\n' && ch != WEOF) { 9787c478bd9Sstevel@tonic-gate if (ch == '\t' && tflag) 9797c478bd9Sstevel@tonic-gate do 9807c478bd9Sstevel@tonic-gate (void) putchar(' '); 9817c478bd9Sstevel@tonic-gate while (++col & 7); 9827c478bd9Sstevel@tonic-gate else { 9837c478bd9Sstevel@tonic-gate (void) wcput(ch); 9847c478bd9Sstevel@tonic-gate col++; 9857c478bd9Sstevel@tonic-gate } 9867c478bd9Sstevel@tonic-gate } else 9877c478bd9Sstevel@tonic-gate break; 9887c478bd9Sstevel@tonic-gate } 9897c478bd9Sstevel@tonic-gate (void) putchar('\n'); 9907c478bd9Sstevel@tonic-gate } 9917c478bd9Sstevel@tonic-gate } 9927c478bd9Sstevel@tonic-gate 9937c478bd9Sstevel@tonic-gate /* 9947c478bd9Sstevel@tonic-gate * hashing has the effect of 9957c478bd9Sstevel@tonic-gate * arranging line in 7-bit bytes and then 9967c478bd9Sstevel@tonic-gate * summing 1-s complement in 16-bit hunks 9977c478bd9Sstevel@tonic-gate */ 9987c478bd9Sstevel@tonic-gate 9997c478bd9Sstevel@tonic-gate static int 10007c478bd9Sstevel@tonic-gate readhash(FILE *f, int filen, char *str) 10017c478bd9Sstevel@tonic-gate { 10027c478bd9Sstevel@tonic-gate long sum; 10037c478bd9Sstevel@tonic-gate unsigned int shift; 10047c478bd9Sstevel@tonic-gate int space; 10057c478bd9Sstevel@tonic-gate int t; 10067c478bd9Sstevel@tonic-gate wint_t wt; 10077c478bd9Sstevel@tonic-gate int mlen; 10087c478bd9Sstevel@tonic-gate 10097c478bd9Sstevel@tonic-gate sum = 1; 10107c478bd9Sstevel@tonic-gate space = 0; 10117c478bd9Sstevel@tonic-gate if (!bflag && !wflag) { 10127c478bd9Sstevel@tonic-gate if (iflag) 10137c478bd9Sstevel@tonic-gate if (mbcurmax == 1) { 10147c478bd9Sstevel@tonic-gate /* In this case, diff doesn't have to take */ 10157c478bd9Sstevel@tonic-gate /* care of multibyte characters. */ 10167c478bd9Sstevel@tonic-gate for (shift = 0; (t = getc(f)) != '\n'; 10177c478bd9Sstevel@tonic-gate shift += 7) { 10187c478bd9Sstevel@tonic-gate if (t == EOF) { 10197c478bd9Sstevel@tonic-gate if (shift) { 10207c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 10217c478bd9Sstevel@tonic-gate gettext("Warning: missing newline at end of file %s\n"), str); 10227c478bd9Sstevel@tonic-gate break; 10237c478bd9Sstevel@tonic-gate } else 10247c478bd9Sstevel@tonic-gate return (0); 10257c478bd9Sstevel@tonic-gate } 10267c478bd9Sstevel@tonic-gate sum += (isupper(t) ? tolower(t) : t) << 10277c478bd9Sstevel@tonic-gate (shift &= HALFMASK); 10287c478bd9Sstevel@tonic-gate } 10297c478bd9Sstevel@tonic-gate } else { 10307c478bd9Sstevel@tonic-gate /* In this case, diff needs to take care of */ 10317c478bd9Sstevel@tonic-gate /* multibyte characters. */ 10327c478bd9Sstevel@tonic-gate for (shift = 0; 10337c478bd9Sstevel@tonic-gate (wt = getbufwchar(filen, &mlen)) != '\n'; 10347c478bd9Sstevel@tonic-gate shift += 7) { 10357c478bd9Sstevel@tonic-gate if (wt == WEOF) { 10367c478bd9Sstevel@tonic-gate if (shift) { 10377c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 10387c478bd9Sstevel@tonic-gate gettext("Warning: missing newline at end of file %s\n"), str); 10397c478bd9Sstevel@tonic-gate break; 10407c478bd9Sstevel@tonic-gate } else 10417c478bd9Sstevel@tonic-gate return (0); 10427c478bd9Sstevel@tonic-gate } 10437c478bd9Sstevel@tonic-gate sum += NCCHRTRAN(wt) << 10447c478bd9Sstevel@tonic-gate (shift &= HALFMASK); 10457c478bd9Sstevel@tonic-gate } 10467c478bd9Sstevel@tonic-gate } 10477c478bd9Sstevel@tonic-gate else 10487c478bd9Sstevel@tonic-gate /* In this case, diff doesn't have to take care of */ 10497c478bd9Sstevel@tonic-gate /* multibyte characters. */ 10507c478bd9Sstevel@tonic-gate for (shift = 0; (t = getc(f)) != '\n'; shift += 7) { 10517c478bd9Sstevel@tonic-gate if (t == EOF) { 10527c478bd9Sstevel@tonic-gate if (shift) { 10537c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 10547c478bd9Sstevel@tonic-gate gettext("Warning: missing newline at end of file %s\n"), str); 10557c478bd9Sstevel@tonic-gate break; 10567c478bd9Sstevel@tonic-gate } else 10577c478bd9Sstevel@tonic-gate return (0); 10587c478bd9Sstevel@tonic-gate } 10597c478bd9Sstevel@tonic-gate sum += (long)t << (shift &= HALFMASK); 10607c478bd9Sstevel@tonic-gate } 10617c478bd9Sstevel@tonic-gate } else { 10627c478bd9Sstevel@tonic-gate /* In this case, diff needs to take care of */ 10637c478bd9Sstevel@tonic-gate /* multibyte characters. */ 10647c478bd9Sstevel@tonic-gate for (shift = 0; ; ) { 10657c478bd9Sstevel@tonic-gate wt = getbufwchar(filen, &mlen); 10667c478bd9Sstevel@tonic-gate 10677c478bd9Sstevel@tonic-gate if (wt != '\n' && iswspace(wt)) { 10687c478bd9Sstevel@tonic-gate space++; 10697c478bd9Sstevel@tonic-gate continue; 10707c478bd9Sstevel@tonic-gate } else { 10717c478bd9Sstevel@tonic-gate switch (wt) { 10727c478bd9Sstevel@tonic-gate case WEOF: 10737c478bd9Sstevel@tonic-gate if (shift) { 10747c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 10757c478bd9Sstevel@tonic-gate gettext("Warning: missing newline at end of file %s\n"), str); 10767c478bd9Sstevel@tonic-gate break; 10777c478bd9Sstevel@tonic-gate } else 10787c478bd9Sstevel@tonic-gate return (0); 10797c478bd9Sstevel@tonic-gate default: 10807c478bd9Sstevel@tonic-gate if (space && !wflag) { 10817c478bd9Sstevel@tonic-gate shift += 7; 10827c478bd9Sstevel@tonic-gate space = 0; 10837c478bd9Sstevel@tonic-gate } 10847c478bd9Sstevel@tonic-gate sum += CHRTRAN(wt) << 10857c478bd9Sstevel@tonic-gate (shift &= HALFMASK); 10867c478bd9Sstevel@tonic-gate shift += 7; 10877c478bd9Sstevel@tonic-gate continue; 10887c478bd9Sstevel@tonic-gate case L'\n': 10897c478bd9Sstevel@tonic-gate break; 10907c478bd9Sstevel@tonic-gate } 10917c478bd9Sstevel@tonic-gate } 10927c478bd9Sstevel@tonic-gate break; 10937c478bd9Sstevel@tonic-gate } 10947c478bd9Sstevel@tonic-gate } 10957c478bd9Sstevel@tonic-gate return (sum); 10967c478bd9Sstevel@tonic-gate } 10977c478bd9Sstevel@tonic-gate 10987c478bd9Sstevel@tonic-gate 10997c478bd9Sstevel@tonic-gate /* dump accumulated "context" diff changes */ 11007c478bd9Sstevel@tonic-gate static void 11017c478bd9Sstevel@tonic-gate dump_context_vec(void) 11027c478bd9Sstevel@tonic-gate { 11037c478bd9Sstevel@tonic-gate int a, b, c, d; 11047c478bd9Sstevel@tonic-gate char ch; 11057c478bd9Sstevel@tonic-gate struct context_vec *cvp = context_vec_start; 11067c478bd9Sstevel@tonic-gate int lowa, upb, lowc, upd; 11077c478bd9Sstevel@tonic-gate int do_output; 11087c478bd9Sstevel@tonic-gate 11097c478bd9Sstevel@tonic-gate if (cvp > context_vec_ptr) 11107c478bd9Sstevel@tonic-gate return; 11117c478bd9Sstevel@tonic-gate 11127c478bd9Sstevel@tonic-gate lowa = max(1, cvp->a - context); 11137c478bd9Sstevel@tonic-gate upb = min(len[0], context_vec_ptr->b + context); 11147c478bd9Sstevel@tonic-gate lowc = max(1, cvp->c - context); 11157c478bd9Sstevel@tonic-gate upd = min(len[1], context_vec_ptr->d + context); 11167c478bd9Sstevel@tonic-gate 11177c478bd9Sstevel@tonic-gate if (uflag) { 11187c478bd9Sstevel@tonic-gate (void) printf("@@ -%d,%d +%d,%d @@\n", 11197c478bd9Sstevel@tonic-gate lowa, upb - lowa + 1, 11207c478bd9Sstevel@tonic-gate lowc, upd - lowc + 1); 11217c478bd9Sstevel@tonic-gate } else { 11227c478bd9Sstevel@tonic-gate (void) printf("***************\n*** "); 11237c478bd9Sstevel@tonic-gate range(lowa, upb, ","); 11247c478bd9Sstevel@tonic-gate (void) printf(" ****\n"); 11257c478bd9Sstevel@tonic-gate } 11267c478bd9Sstevel@tonic-gate 11277c478bd9Sstevel@tonic-gate /* 11287c478bd9Sstevel@tonic-gate * output changes to the "old" file. The first loop suppresses 11297c478bd9Sstevel@tonic-gate * output if there were no changes to the "old" file (we'll see 11307c478bd9Sstevel@tonic-gate * the "old" lines as context in the "new" list). 11317c478bd9Sstevel@tonic-gate */ 11327c478bd9Sstevel@tonic-gate if (uflag) 11337c478bd9Sstevel@tonic-gate do_output = 1; 11347c478bd9Sstevel@tonic-gate else 11357c478bd9Sstevel@tonic-gate for (do_output = 0; cvp <= context_vec_ptr; cvp++) 11367c478bd9Sstevel@tonic-gate if (cvp->a <= cvp->b) { 11377c478bd9Sstevel@tonic-gate cvp = context_vec_start; 11387c478bd9Sstevel@tonic-gate do_output++; 11397c478bd9Sstevel@tonic-gate break; 11407c478bd9Sstevel@tonic-gate } 11417c478bd9Sstevel@tonic-gate 11427c478bd9Sstevel@tonic-gate if (do_output) { 11437c478bd9Sstevel@tonic-gate while (cvp <= context_vec_ptr) { 11447c478bd9Sstevel@tonic-gate a = cvp->a; b = cvp->b; c = cvp->c; d = cvp->d; 11457c478bd9Sstevel@tonic-gate 11467c478bd9Sstevel@tonic-gate if (a <= b && c <= d) 11477c478bd9Sstevel@tonic-gate ch = 'c'; 11487c478bd9Sstevel@tonic-gate else 11497c478bd9Sstevel@tonic-gate ch = (a <= b) ? 'd' : 'a'; 11507c478bd9Sstevel@tonic-gate 11517c478bd9Sstevel@tonic-gate if (ch == 'a') { 11527c478bd9Sstevel@tonic-gate /* The last argument should not affect */ 11537c478bd9Sstevel@tonic-gate /* the behavior of fetch() */ 11547c478bd9Sstevel@tonic-gate fetch(ixold, lowa, b, 0, uflag ? " " : " ", 1); 11557c478bd9Sstevel@tonic-gate if (uflag) 11567c478bd9Sstevel@tonic-gate fetch(ixnew, c, d, 1, "+", 0); 11577c478bd9Sstevel@tonic-gate } else if (ch == 'd') { 11587c478bd9Sstevel@tonic-gate fetch(ixold, lowa, a - 1, 0, uflag ? " " : 11597c478bd9Sstevel@tonic-gate " ", 1); 11607c478bd9Sstevel@tonic-gate fetch(ixold, a, b, 0, uflag ? "-" : "- ", 1); 11617c478bd9Sstevel@tonic-gate } else { 11627c478bd9Sstevel@tonic-gate /* The last argument should not affect */ 11637c478bd9Sstevel@tonic-gate /* the behavior of fetch() */ 11647c478bd9Sstevel@tonic-gate fetch(ixold, lowa, a-1, 0, uflag ? " " : " ", 11657c478bd9Sstevel@tonic-gate 1); 11667c478bd9Sstevel@tonic-gate if (uflag) { 11677c478bd9Sstevel@tonic-gate fetch(ixold, a, b, 0, "-", 1); 11687c478bd9Sstevel@tonic-gate fetch(ixnew, c, d, 1, "+", 0); 11697c478bd9Sstevel@tonic-gate } else 11707c478bd9Sstevel@tonic-gate fetch(ixold, a, b, 0, "! ", 1); 11717c478bd9Sstevel@tonic-gate } 11727c478bd9Sstevel@tonic-gate lowa = b + 1; 11737c478bd9Sstevel@tonic-gate cvp++; 11747c478bd9Sstevel@tonic-gate } 11757c478bd9Sstevel@tonic-gate /* The last argument should not affect the behavior */ 11767c478bd9Sstevel@tonic-gate /* of fetch() */ 11777c478bd9Sstevel@tonic-gate fetch(ixold, b+1, upb, 0, uflag ? " " : " ", 1); 11787c478bd9Sstevel@tonic-gate } 11797c478bd9Sstevel@tonic-gate 11807c478bd9Sstevel@tonic-gate if (uflag) { 11817c478bd9Sstevel@tonic-gate context_vec_ptr = context_vec_start - 1; 11827c478bd9Sstevel@tonic-gate return; 11837c478bd9Sstevel@tonic-gate } 11847c478bd9Sstevel@tonic-gate 11857c478bd9Sstevel@tonic-gate /* output changes to the "new" file */ 11867c478bd9Sstevel@tonic-gate (void) printf("--- "); 11877c478bd9Sstevel@tonic-gate range(lowc, upd, ","); 11887c478bd9Sstevel@tonic-gate (void) printf(" ----\n"); 11897c478bd9Sstevel@tonic-gate 11907c478bd9Sstevel@tonic-gate do_output = 0; 11917c478bd9Sstevel@tonic-gate for (cvp = context_vec_start; cvp <= context_vec_ptr; cvp++) 11927c478bd9Sstevel@tonic-gate if (cvp->c <= cvp->d) { 11937c478bd9Sstevel@tonic-gate cvp = context_vec_start; 11947c478bd9Sstevel@tonic-gate do_output++; 11957c478bd9Sstevel@tonic-gate break; 11967c478bd9Sstevel@tonic-gate } 11977c478bd9Sstevel@tonic-gate 11987c478bd9Sstevel@tonic-gate if (do_output) { 11997c478bd9Sstevel@tonic-gate while (cvp <= context_vec_ptr) { 12007c478bd9Sstevel@tonic-gate a = cvp->a; b = cvp->b; c = cvp->c; d = cvp->d; 12017c478bd9Sstevel@tonic-gate 12027c478bd9Sstevel@tonic-gate if (a <= b && c <= d) 12037c478bd9Sstevel@tonic-gate ch = 'c'; 12047c478bd9Sstevel@tonic-gate else 12057c478bd9Sstevel@tonic-gate ch = (a <= b) ? 'd' : 'a'; 12067c478bd9Sstevel@tonic-gate 12077c478bd9Sstevel@tonic-gate if (ch == 'd') 12087c478bd9Sstevel@tonic-gate /* The last argument should not affect */ 12097c478bd9Sstevel@tonic-gate /* the behavior of fetch() */ 12107c478bd9Sstevel@tonic-gate fetch(ixnew, lowc, d, 1, " ", 0); 12117c478bd9Sstevel@tonic-gate else { 12127c478bd9Sstevel@tonic-gate /* The last argument should not affect */ 12137c478bd9Sstevel@tonic-gate /* the behavior of fetch() */ 12147c478bd9Sstevel@tonic-gate fetch(ixnew, lowc, c - 1, 1, " ", 0); 12157c478bd9Sstevel@tonic-gate fetch(ixnew, c, d, 1, 12167c478bd9Sstevel@tonic-gate ch == 'c' ? "! " : "+ ", 0); 12177c478bd9Sstevel@tonic-gate } 12187c478bd9Sstevel@tonic-gate lowc = d + 1; 12197c478bd9Sstevel@tonic-gate cvp++; 12207c478bd9Sstevel@tonic-gate } 12217c478bd9Sstevel@tonic-gate /* The last argument should not affect the behavior */ 12227c478bd9Sstevel@tonic-gate /* of fetch() */ 12237c478bd9Sstevel@tonic-gate fetch(ixnew, d + 1, upd, 1, " ", 0); 12247c478bd9Sstevel@tonic-gate } 12257c478bd9Sstevel@tonic-gate context_vec_ptr = context_vec_start - 1; 12267c478bd9Sstevel@tonic-gate } 12277c478bd9Sstevel@tonic-gate 12287c478bd9Sstevel@tonic-gate 12297c478bd9Sstevel@tonic-gate 12307c478bd9Sstevel@tonic-gate /* 12317c478bd9Sstevel@tonic-gate * diff - directory comparison 12327c478bd9Sstevel@tonic-gate */ 12337c478bd9Sstevel@tonic-gate 12347c478bd9Sstevel@tonic-gate struct dir *setupdir(); 12357c478bd9Sstevel@tonic-gate int header; 12367c478bd9Sstevel@tonic-gate char title[2 * BUFSIZ], *etitle; 12377c478bd9Sstevel@tonic-gate 12387c478bd9Sstevel@tonic-gate static void 12397c478bd9Sstevel@tonic-gate diffdir(char **argv) 12407c478bd9Sstevel@tonic-gate { 12417c478bd9Sstevel@tonic-gate struct dir *d1, *d2; 12427c478bd9Sstevel@tonic-gate struct dir *dir1, *dir2; 12437c478bd9Sstevel@tonic-gate int i; 12447c478bd9Sstevel@tonic-gate int cmp; 12457c478bd9Sstevel@tonic-gate int result, dirstatus; 12467c478bd9Sstevel@tonic-gate 12477c478bd9Sstevel@tonic-gate if (opt == D_IFDEF) 12487c478bd9Sstevel@tonic-gate error(gettext("cannot specify -D with directories")); 12497c478bd9Sstevel@tonic-gate 12507c478bd9Sstevel@tonic-gate if (opt == D_EDIT && (sflag || lflag)) { 12517c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "diff: "); 12527c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 12537c478bd9Sstevel@tonic-gate "warning: should not give -s or -l with -e\n")); 12547c478bd9Sstevel@tonic-gate } 12557c478bd9Sstevel@tonic-gate dirstatus = 0; 12567c478bd9Sstevel@tonic-gate title[0] = 0; 12577c478bd9Sstevel@tonic-gate (void) strcpy(title, "diff "); 12587c478bd9Sstevel@tonic-gate for (i = 1; diffargv[i + 2]; i++) { 12597c478bd9Sstevel@tonic-gate if (strcmp(diffargv[i], "-") == 0) { 12607c478bd9Sstevel@tonic-gate continue; /* Skip -S and its argument */ 12617c478bd9Sstevel@tonic-gate } 12627c478bd9Sstevel@tonic-gate (void) strcat(title, diffargv[i]); 12637c478bd9Sstevel@tonic-gate (void) strcat(title, " "); 12647c478bd9Sstevel@tonic-gate } 12657c478bd9Sstevel@tonic-gate for (etitle = title; *etitle; etitle++) 12667c478bd9Sstevel@tonic-gate ; 12677c478bd9Sstevel@tonic-gate setfile(&file1, &efile1, file1); 12687c478bd9Sstevel@tonic-gate setfile(&file2, &efile2, file2); 12697c478bd9Sstevel@tonic-gate argv[0] = file1; 12707c478bd9Sstevel@tonic-gate argv[1] = file2; 12717c478bd9Sstevel@tonic-gate dir1 = setupdir(file1); 12727c478bd9Sstevel@tonic-gate dir2 = setupdir(file2); 12737c478bd9Sstevel@tonic-gate d1 = dir1; d2 = dir2; 12747c478bd9Sstevel@tonic-gate while (d1->d_entry != 0 || d2->d_entry != 0) { 12757c478bd9Sstevel@tonic-gate if (d1->d_entry && useless(d1->d_entry)) { 12767c478bd9Sstevel@tonic-gate d1++; 12777c478bd9Sstevel@tonic-gate continue; 12787c478bd9Sstevel@tonic-gate } 12797c478bd9Sstevel@tonic-gate if (d2->d_entry && useless(d2->d_entry)) { 12807c478bd9Sstevel@tonic-gate d2++; 12817c478bd9Sstevel@tonic-gate continue; 12827c478bd9Sstevel@tonic-gate } 12837c478bd9Sstevel@tonic-gate if (d1->d_entry == 0) 12847c478bd9Sstevel@tonic-gate cmp = 1; 12857c478bd9Sstevel@tonic-gate else if (d2->d_entry == 0) 12867c478bd9Sstevel@tonic-gate cmp = -1; 12877c478bd9Sstevel@tonic-gate else 12887c478bd9Sstevel@tonic-gate cmp = strcmp(d1->d_entry, d2->d_entry); 12897c478bd9Sstevel@tonic-gate if (cmp < 0) { 12907c478bd9Sstevel@tonic-gate if (lflag) 12917c478bd9Sstevel@tonic-gate d1->d_flags |= ONLY; 12927c478bd9Sstevel@tonic-gate else if (opt == 0 || opt == 2) 12937c478bd9Sstevel@tonic-gate only(d1, 1); 12947c478bd9Sstevel@tonic-gate d1++; 12957c478bd9Sstevel@tonic-gate if (dirstatus == 0) 12967c478bd9Sstevel@tonic-gate dirstatus = 1; 12977c478bd9Sstevel@tonic-gate } else if (cmp == 0) { 12987c478bd9Sstevel@tonic-gate result = compare(d1); 12997c478bd9Sstevel@tonic-gate if (result > dirstatus) 13007c478bd9Sstevel@tonic-gate dirstatus = result; 13017c478bd9Sstevel@tonic-gate d1++; 13027c478bd9Sstevel@tonic-gate d2++; 13037c478bd9Sstevel@tonic-gate } else { 13047c478bd9Sstevel@tonic-gate if (lflag) 13057c478bd9Sstevel@tonic-gate d2->d_flags |= ONLY; 13067c478bd9Sstevel@tonic-gate else if (opt == 0 || opt == 2) 13077c478bd9Sstevel@tonic-gate only(d2, 2); 13087c478bd9Sstevel@tonic-gate d2++; 13097c478bd9Sstevel@tonic-gate if (dirstatus == 0) 13107c478bd9Sstevel@tonic-gate dirstatus = 1; 13117c478bd9Sstevel@tonic-gate } 13127c478bd9Sstevel@tonic-gate } 13137c478bd9Sstevel@tonic-gate if (lflag) { 13147c478bd9Sstevel@tonic-gate scanpr(dir1, ONLY, 13157c478bd9Sstevel@tonic-gate gettext("Only in %.*s"), file1, efile1, 0, 0); 13167c478bd9Sstevel@tonic-gate scanpr(dir2, ONLY, 13177c478bd9Sstevel@tonic-gate gettext("Only in %.*s"), file2, efile2, 0, 0); 13187c478bd9Sstevel@tonic-gate scanpr(dir1, SAME, 13197c478bd9Sstevel@tonic-gate gettext("Common identical files in %.*s and %.*s"), 13207c478bd9Sstevel@tonic-gate file1, efile1, file2, efile2); 13217c478bd9Sstevel@tonic-gate scanpr(dir1, DIFFER, 13227c478bd9Sstevel@tonic-gate gettext("Binary files which differ in %.*s and %.*s"), 13237c478bd9Sstevel@tonic-gate file1, efile1, file2, efile2); 13247c478bd9Sstevel@tonic-gate scanpr(dir1, DIRECT, 13257c478bd9Sstevel@tonic-gate gettext("Common subdirectories of %.*s and %.*s"), 13267c478bd9Sstevel@tonic-gate file1, efile1, file2, efile2); 13277c478bd9Sstevel@tonic-gate } 13287c478bd9Sstevel@tonic-gate if (rflag) { 13297c478bd9Sstevel@tonic-gate if (header && lflag) 13307c478bd9Sstevel@tonic-gate (void) printf("\f"); 13317c478bd9Sstevel@tonic-gate for (d1 = dir1; d1->d_entry; d1++) { 13327c478bd9Sstevel@tonic-gate if ((d1->d_flags & DIRECT) == 0) 13337c478bd9Sstevel@tonic-gate continue; 13347c478bd9Sstevel@tonic-gate (void) strcpy(efile1, d1->d_entry); 13357c478bd9Sstevel@tonic-gate (void) strcpy(efile2, d1->d_entry); 13367c478bd9Sstevel@tonic-gate result = calldiff((char *)0); 13377c478bd9Sstevel@tonic-gate if (result > dirstatus) 13387c478bd9Sstevel@tonic-gate dirstatus = result; 13397c478bd9Sstevel@tonic-gate } 13407c478bd9Sstevel@tonic-gate } 13417c478bd9Sstevel@tonic-gate status = dirstatus; 13427c478bd9Sstevel@tonic-gate } 13437c478bd9Sstevel@tonic-gate 13447c478bd9Sstevel@tonic-gate static void 13457c478bd9Sstevel@tonic-gate setfile(char **fpp, char **epp, char *file) 13467c478bd9Sstevel@tonic-gate { 13477c478bd9Sstevel@tonic-gate char *cp; 13487c478bd9Sstevel@tonic-gate 13497c478bd9Sstevel@tonic-gate *fpp = (char *)malloc(BUFSIZ); 13507c478bd9Sstevel@tonic-gate if (*fpp == 0) { 13517c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "diff: "); 13527c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("out of memory\n")); 13537c478bd9Sstevel@tonic-gate exit(1); 13547c478bd9Sstevel@tonic-gate } 13557c478bd9Sstevel@tonic-gate (void) strcpy(*fpp, file); 13567c478bd9Sstevel@tonic-gate for (cp = *fpp; *cp; cp++) 13577c478bd9Sstevel@tonic-gate continue; 13587c478bd9Sstevel@tonic-gate *cp++ = '/'; 13597c478bd9Sstevel@tonic-gate *cp = 0; 13607c478bd9Sstevel@tonic-gate *epp = cp; 13617c478bd9Sstevel@tonic-gate } 13627c478bd9Sstevel@tonic-gate 13637c478bd9Sstevel@tonic-gate static void 13647c478bd9Sstevel@tonic-gate scanpr(struct dir *dp, int test, 13657c478bd9Sstevel@tonic-gate char *title, char *file1, char *efile1, char *file2, char *efile2) 13667c478bd9Sstevel@tonic-gate { 13677c478bd9Sstevel@tonic-gate int titled = 0; 13687c478bd9Sstevel@tonic-gate 13697c478bd9Sstevel@tonic-gate for (; dp->d_entry; dp++) { 13707c478bd9Sstevel@tonic-gate if ((dp->d_flags & test) == 0) 13717c478bd9Sstevel@tonic-gate continue; 13727c478bd9Sstevel@tonic-gate if (titled == 0) { 13737c478bd9Sstevel@tonic-gate if (header == 0) 13747c478bd9Sstevel@tonic-gate header = 1; 13757c478bd9Sstevel@tonic-gate else 13767c478bd9Sstevel@tonic-gate (void) printf("\n"); 13777c478bd9Sstevel@tonic-gate (void) printf(title, 13787c478bd9Sstevel@tonic-gate efile1 - file1 - 1, file1, 13797c478bd9Sstevel@tonic-gate efile2 - file2 - 1, file2); 13807c478bd9Sstevel@tonic-gate (void) printf(":\n"); 13817c478bd9Sstevel@tonic-gate titled = 1; 13827c478bd9Sstevel@tonic-gate } 13837c478bd9Sstevel@tonic-gate (void) printf("\t%s\n", dp->d_entry); 13847c478bd9Sstevel@tonic-gate } 13857c478bd9Sstevel@tonic-gate } 13867c478bd9Sstevel@tonic-gate 13877c478bd9Sstevel@tonic-gate static void 13887c478bd9Sstevel@tonic-gate only(struct dir *dp, int which) 13897c478bd9Sstevel@tonic-gate { 13907c478bd9Sstevel@tonic-gate char *file = which == 1 ? file1 : file2; 13917c478bd9Sstevel@tonic-gate char *efile = which == 1 ? efile1 : efile2; 13927c478bd9Sstevel@tonic-gate 13937c478bd9Sstevel@tonic-gate (void) printf(gettext("Only in %.*s: %s\n"), efile - file - 1, file, 13947c478bd9Sstevel@tonic-gate dp->d_entry); 13957c478bd9Sstevel@tonic-gate } 13967c478bd9Sstevel@tonic-gate 13977c478bd9Sstevel@tonic-gate int entcmp(); 13987c478bd9Sstevel@tonic-gate 13997c478bd9Sstevel@tonic-gate static struct dir * 14007c478bd9Sstevel@tonic-gate setupdir(char *cp) 14017c478bd9Sstevel@tonic-gate { 14027c478bd9Sstevel@tonic-gate struct dir *dp = 0, *ep; 14037c478bd9Sstevel@tonic-gate struct dirent64 *rp; 14047c478bd9Sstevel@tonic-gate int nitems; 14057c478bd9Sstevel@tonic-gate int size; 14067c478bd9Sstevel@tonic-gate DIR *dirp; 14077c478bd9Sstevel@tonic-gate 14087c478bd9Sstevel@tonic-gate dirp = opendir(cp); 14097c478bd9Sstevel@tonic-gate if (dirp == NULL) { 14107c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "diff: "); 14117c478bd9Sstevel@tonic-gate perror(cp); 14127c478bd9Sstevel@tonic-gate done(); 14137c478bd9Sstevel@tonic-gate } 14147c478bd9Sstevel@tonic-gate nitems = 0; 14157c478bd9Sstevel@tonic-gate dp = (struct dir *)malloc(sizeof (struct dir)); 14167c478bd9Sstevel@tonic-gate if (dp == 0) 14177c478bd9Sstevel@tonic-gate error(gettext(NO_MEM_ERR)); 14187c478bd9Sstevel@tonic-gate 14197c478bd9Sstevel@tonic-gate while (rp = readdir64(dirp)) { 14207c478bd9Sstevel@tonic-gate ep = &dp[nitems++]; 14217c478bd9Sstevel@tonic-gate ep->d_reclen = rp->d_reclen; 14227c478bd9Sstevel@tonic-gate ep->d_entry = 0; 14237c478bd9Sstevel@tonic-gate ep->d_flags = 0; 14247c478bd9Sstevel@tonic-gate size = strlen(rp->d_name); 14257c478bd9Sstevel@tonic-gate if (size > 0) { 14267c478bd9Sstevel@tonic-gate ep->d_entry = (char *)malloc(size + 1); 14277c478bd9Sstevel@tonic-gate if (ep->d_entry == 0) 14287c478bd9Sstevel@tonic-gate error(gettext(NO_MEM_ERR)); 14297c478bd9Sstevel@tonic-gate 14307c478bd9Sstevel@tonic-gate (void) strcpy(ep->d_entry, rp->d_name); 14317c478bd9Sstevel@tonic-gate } 14327c478bd9Sstevel@tonic-gate dp = (struct dir *)realloc((char *)dp, 14337c478bd9Sstevel@tonic-gate (nitems + 1) * sizeof (struct dir)); 14347c478bd9Sstevel@tonic-gate if (dp == 0) 14357c478bd9Sstevel@tonic-gate error(gettext(NO_MEM_ERR)); 14367c478bd9Sstevel@tonic-gate } 14377c478bd9Sstevel@tonic-gate dp[nitems].d_entry = 0; /* delimiter */ 14387c478bd9Sstevel@tonic-gate (void) closedir(dirp); 14397c478bd9Sstevel@tonic-gate qsort(dp, nitems, sizeof (struct dir), 14407c478bd9Sstevel@tonic-gate (int (*)(const void *, const void *))entcmp); 14417c478bd9Sstevel@tonic-gate return (dp); 14427c478bd9Sstevel@tonic-gate } 14437c478bd9Sstevel@tonic-gate 14447c478bd9Sstevel@tonic-gate static int 14457c478bd9Sstevel@tonic-gate entcmp(struct dir *d1, struct dir *d2) 14467c478bd9Sstevel@tonic-gate { 14477c478bd9Sstevel@tonic-gate return (strcmp(d1->d_entry, d2->d_entry)); 14487c478bd9Sstevel@tonic-gate } 14497c478bd9Sstevel@tonic-gate 14507c478bd9Sstevel@tonic-gate static int 14517c478bd9Sstevel@tonic-gate compare(struct dir *dp) 14527c478bd9Sstevel@tonic-gate { 14537c478bd9Sstevel@tonic-gate int i, j; 14547c478bd9Sstevel@tonic-gate int f1 = -1, f2 = -1; 14557c478bd9Sstevel@tonic-gate mode_t fmt1, fmt2; 14567c478bd9Sstevel@tonic-gate struct stat stb1, stb2; 14577c478bd9Sstevel@tonic-gate char buf1[BUFSIZ], buf2[BUFSIZ]; 14587c478bd9Sstevel@tonic-gate int result; 14597c478bd9Sstevel@tonic-gate 14607c478bd9Sstevel@tonic-gate (void) strcpy(efile1, dp->d_entry); 14617c478bd9Sstevel@tonic-gate (void) strcpy(efile2, dp->d_entry); 14627c478bd9Sstevel@tonic-gate 14637c478bd9Sstevel@tonic-gate if (stat(file1, &stb1) == -1) { 14647c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "diff: "); 14657c478bd9Sstevel@tonic-gate perror(file1); 14667c478bd9Sstevel@tonic-gate return (2); 14677c478bd9Sstevel@tonic-gate } 14687c478bd9Sstevel@tonic-gate if (stat(file2, &stb2) == -1) { 14697c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "diff: "); 14707c478bd9Sstevel@tonic-gate perror(file2); 14717c478bd9Sstevel@tonic-gate return (2); 14727c478bd9Sstevel@tonic-gate } 14737c478bd9Sstevel@tonic-gate 14747c478bd9Sstevel@tonic-gate fmt1 = stb1.st_mode & S_IFMT; 14757c478bd9Sstevel@tonic-gate fmt2 = stb2.st_mode & S_IFMT; 14767c478bd9Sstevel@tonic-gate 14777c478bd9Sstevel@tonic-gate if (fmt1 == S_IFREG) { 14787c478bd9Sstevel@tonic-gate f1 = open(file1, O_RDONLY); 14797c478bd9Sstevel@tonic-gate if (f1 < 0) { 14807c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "diff: "); 14817c478bd9Sstevel@tonic-gate perror(file1); 14827c478bd9Sstevel@tonic-gate return (2); 14837c478bd9Sstevel@tonic-gate } 14847c478bd9Sstevel@tonic-gate } 14857c478bd9Sstevel@tonic-gate 14867c478bd9Sstevel@tonic-gate if (fmt2 == S_IFREG) { 14877c478bd9Sstevel@tonic-gate f2 = open(file2, O_RDONLY); 14887c478bd9Sstevel@tonic-gate if (f2 < 0) { 14897c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "diff: "); 14907c478bd9Sstevel@tonic-gate perror(file2); 14917c478bd9Sstevel@tonic-gate (void) close(f1); 14927c478bd9Sstevel@tonic-gate return (2); 14937c478bd9Sstevel@tonic-gate } 14947c478bd9Sstevel@tonic-gate } 14957c478bd9Sstevel@tonic-gate 14967c478bd9Sstevel@tonic-gate if (fmt1 != S_IFREG || fmt2 != S_IFREG) { 14977c478bd9Sstevel@tonic-gate if (fmt1 == fmt2) { 14987c478bd9Sstevel@tonic-gate switch (fmt1) { 14997c478bd9Sstevel@tonic-gate 15007c478bd9Sstevel@tonic-gate case S_IFDIR: 15017c478bd9Sstevel@tonic-gate dp->d_flags = DIRECT; 15027c478bd9Sstevel@tonic-gate if (lflag || opt == D_EDIT) 15037c478bd9Sstevel@tonic-gate goto closem; 15047c478bd9Sstevel@tonic-gate (void) printf(gettext( 15057c478bd9Sstevel@tonic-gate "Common subdirectories: %s and %s\n"), 15067c478bd9Sstevel@tonic-gate file1, file2); 15077c478bd9Sstevel@tonic-gate goto closem; 15087c478bd9Sstevel@tonic-gate 15097c478bd9Sstevel@tonic-gate case S_IFCHR: 15107c478bd9Sstevel@tonic-gate case S_IFBLK: 15117c478bd9Sstevel@tonic-gate if (stb1.st_rdev == stb2.st_rdev) 15127c478bd9Sstevel@tonic-gate goto same; 15137c478bd9Sstevel@tonic-gate (void) printf(gettext( 15147c478bd9Sstevel@tonic-gate "Special files %s and %s differ\n"), 15157c478bd9Sstevel@tonic-gate file1, file2); 15167c478bd9Sstevel@tonic-gate break; 15177c478bd9Sstevel@tonic-gate 15187c478bd9Sstevel@tonic-gate case S_IFLNK: 15197c478bd9Sstevel@tonic-gate if ((i = readlink(file1, buf1, BUFSIZ)) == -1) { 15207c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 15217c478bd9Sstevel@tonic-gate "diff: cannot read link\n")); 15227c478bd9Sstevel@tonic-gate return (2); 15237c478bd9Sstevel@tonic-gate } 15247c478bd9Sstevel@tonic-gate 15257c478bd9Sstevel@tonic-gate if ((j = readlink(file2, buf2, BUFSIZ)) == -1) { 15267c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 15277c478bd9Sstevel@tonic-gate "diff: cannot read link\n")); 15287c478bd9Sstevel@tonic-gate return (2); 15297c478bd9Sstevel@tonic-gate } 15307c478bd9Sstevel@tonic-gate 15317c478bd9Sstevel@tonic-gate if (i == j) { 15327c478bd9Sstevel@tonic-gate if (strncmp(buf1, buf2, i) == 0) 15337c478bd9Sstevel@tonic-gate goto same; 15347c478bd9Sstevel@tonic-gate } 15357c478bd9Sstevel@tonic-gate 15367c478bd9Sstevel@tonic-gate (void) printf(gettext( 15377c478bd9Sstevel@tonic-gate "Symbolic links %s and %s differ\n"), 15387c478bd9Sstevel@tonic-gate file1, file2); 15397c478bd9Sstevel@tonic-gate break; 15407c478bd9Sstevel@tonic-gate 15417c478bd9Sstevel@tonic-gate case S_IFIFO: 15427c478bd9Sstevel@tonic-gate if (stb1.st_ino == stb2.st_ino) 15437c478bd9Sstevel@tonic-gate goto same; 15447c478bd9Sstevel@tonic-gate (void) printf(gettext( 15457c478bd9Sstevel@tonic-gate "Named pipes %s and %s differ\n"), 15467c478bd9Sstevel@tonic-gate file1, file2); 15477c478bd9Sstevel@tonic-gate break; 15487c478bd9Sstevel@tonic-gate } 15497c478bd9Sstevel@tonic-gate } else { 15507c478bd9Sstevel@tonic-gate if (lflag) 15517c478bd9Sstevel@tonic-gate dp->d_flags |= DIFFER; 15527c478bd9Sstevel@tonic-gate else if (opt == D_NORMAL || opt == D_CONTEXT) { 15537c478bd9Sstevel@tonic-gate /* 15547c478bd9Sstevel@tonic-gate * TRANSLATION_NOTE 15557c478bd9Sstevel@tonic-gate * The second and fourth parameters will take the gettext'ed string 15567c478bd9Sstevel@tonic-gate * of one of the following: 15577c478bd9Sstevel@tonic-gate * a directory 15587c478bd9Sstevel@tonic-gate * a character special file 15597c478bd9Sstevel@tonic-gate * a block special file 15607c478bd9Sstevel@tonic-gate * a plain file 15617c478bd9Sstevel@tonic-gate * a named pipe 15627c478bd9Sstevel@tonic-gate * a socket 15637c478bd9Sstevel@tonic-gate * a door 15647c478bd9Sstevel@tonic-gate * an event port 15657c478bd9Sstevel@tonic-gate * an unknown type 15667c478bd9Sstevel@tonic-gate */ 15677c478bd9Sstevel@tonic-gate (void) printf( 15687c478bd9Sstevel@tonic-gate gettext("File %s is %s while file %s is %s\n"), 15697c478bd9Sstevel@tonic-gate file1, pfiletype(fmt1), 15707c478bd9Sstevel@tonic-gate file2, pfiletype(fmt2)); 15717c478bd9Sstevel@tonic-gate } 15727c478bd9Sstevel@tonic-gate } 15737c478bd9Sstevel@tonic-gate (void) close(f1); (void) close(f2); 15747c478bd9Sstevel@tonic-gate return (1); 15757c478bd9Sstevel@tonic-gate } 15767c478bd9Sstevel@tonic-gate if (stb1.st_size != stb2.st_size) 15777c478bd9Sstevel@tonic-gate goto notsame; 15787c478bd9Sstevel@tonic-gate for (;;) { 15797c478bd9Sstevel@tonic-gate i = read(f1, buf1, BUFSIZ); 15807c478bd9Sstevel@tonic-gate j = read(f2, buf2, BUFSIZ); 15817c478bd9Sstevel@tonic-gate if (i < 0 || j < 0) { 15827c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "diff: "); 15837c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Error reading ")); 15847c478bd9Sstevel@tonic-gate perror(i < 0 ? file1: file2); 15857c478bd9Sstevel@tonic-gate (void) close(f1); (void) close(f2); 15867c478bd9Sstevel@tonic-gate return (2); 15877c478bd9Sstevel@tonic-gate } 15887c478bd9Sstevel@tonic-gate if (i != j) 15897c478bd9Sstevel@tonic-gate goto notsame; 15907c478bd9Sstevel@tonic-gate if (i == 0 && j == 0) 15917c478bd9Sstevel@tonic-gate goto same; 15927c478bd9Sstevel@tonic-gate for (j = 0; j < i; j++) 15937c478bd9Sstevel@tonic-gate if (buf1[j] != buf2[j]) 15947c478bd9Sstevel@tonic-gate goto notsame; 15957c478bd9Sstevel@tonic-gate } 15967c478bd9Sstevel@tonic-gate same: 15977c478bd9Sstevel@tonic-gate if (sflag == 0) 15987c478bd9Sstevel@tonic-gate goto closem; 15997c478bd9Sstevel@tonic-gate if (lflag) 16007c478bd9Sstevel@tonic-gate dp->d_flags = SAME; 16017c478bd9Sstevel@tonic-gate else 16027c478bd9Sstevel@tonic-gate (void) printf(gettext("Files %s and %s are identical\n"), 16037c478bd9Sstevel@tonic-gate file1, file2); 16047c478bd9Sstevel@tonic-gate 16057c478bd9Sstevel@tonic-gate closem: 16067c478bd9Sstevel@tonic-gate (void) close(f1); (void) close(f2); 16077c478bd9Sstevel@tonic-gate return (0); 16087c478bd9Sstevel@tonic-gate 16097c478bd9Sstevel@tonic-gate notsame: 16107c478bd9Sstevel@tonic-gate if (binary(f1) || binary(f2)) { 16117c478bd9Sstevel@tonic-gate if (lflag) 16127c478bd9Sstevel@tonic-gate dp->d_flags |= DIFFER; 16137c478bd9Sstevel@tonic-gate else if (opt == D_NORMAL || opt == D_CONTEXT) 16147c478bd9Sstevel@tonic-gate (void) printf( 16157c478bd9Sstevel@tonic-gate gettext("Binary files %s and %s differ\n"), 16167c478bd9Sstevel@tonic-gate file1, file2); 16177c478bd9Sstevel@tonic-gate (void) close(f1); (void) close(f2); 16187c478bd9Sstevel@tonic-gate return (1); 16197c478bd9Sstevel@tonic-gate } 16207c478bd9Sstevel@tonic-gate (void) close(f1); (void) close(f2); 16217c478bd9Sstevel@tonic-gate anychange = 1; 16227c478bd9Sstevel@tonic-gate if (lflag) { 16237c478bd9Sstevel@tonic-gate result = calldiff(title); 16247c478bd9Sstevel@tonic-gate } else { 16257c478bd9Sstevel@tonic-gate if (opt == D_EDIT) 16267c478bd9Sstevel@tonic-gate (void) printf("ed - %s << '-*-END-*-'\n", dp->d_entry); 16277c478bd9Sstevel@tonic-gate else 16287c478bd9Sstevel@tonic-gate (void) printf("%s%s %s\n", title, file1, file2); 16297c478bd9Sstevel@tonic-gate result = calldiff((char *)0); 16307c478bd9Sstevel@tonic-gate if (opt == D_EDIT) 16317c478bd9Sstevel@tonic-gate (void) printf("w\nq\n-*-END-*-\n"); 16327c478bd9Sstevel@tonic-gate } 16337c478bd9Sstevel@tonic-gate return (result); 16347c478bd9Sstevel@tonic-gate } 16357c478bd9Sstevel@tonic-gate 16367c478bd9Sstevel@tonic-gate char *prargs[] = { "pr", "-h", 0, 0, 0 }; 16377c478bd9Sstevel@tonic-gate 16387c478bd9Sstevel@tonic-gate static int 16397c478bd9Sstevel@tonic-gate calldiff(char *wantpr) 16407c478bd9Sstevel@tonic-gate { 16417c478bd9Sstevel@tonic-gate pid_t pid; 16427c478bd9Sstevel@tonic-gate int diffstatus, pv[2]; 16437c478bd9Sstevel@tonic-gate 16447c478bd9Sstevel@tonic-gate prargs[2] = wantpr; 16457c478bd9Sstevel@tonic-gate (void) fflush(stdout); 16467c478bd9Sstevel@tonic-gate if (wantpr) { 16477c478bd9Sstevel@tonic-gate (void) sprintf(etitle, "%s %s", file1, file2); 16487c478bd9Sstevel@tonic-gate (void) pipe(pv); 16497c478bd9Sstevel@tonic-gate pid = fork(); 16507c478bd9Sstevel@tonic-gate if (pid == (pid_t)-1) 16517c478bd9Sstevel@tonic-gate error(gettext(NO_PROCS_ERR)); 16527c478bd9Sstevel@tonic-gate 16537c478bd9Sstevel@tonic-gate if (pid == 0) { 16547c478bd9Sstevel@tonic-gate (void) close(0); 16557c478bd9Sstevel@tonic-gate (void) dup(pv[0]); 16567c478bd9Sstevel@tonic-gate (void) close(pv[0]); 16577c478bd9Sstevel@tonic-gate (void) close(pv[1]); 16587c478bd9Sstevel@tonic-gate (void) execv(pr+5, prargs); 16597c478bd9Sstevel@tonic-gate (void) execv(pr, prargs); 16607c478bd9Sstevel@tonic-gate perror(pr); 16617c478bd9Sstevel@tonic-gate done(); 16627c478bd9Sstevel@tonic-gate } 16637c478bd9Sstevel@tonic-gate } 16647c478bd9Sstevel@tonic-gate pid = fork(); 16657c478bd9Sstevel@tonic-gate if (pid == (pid_t)-1) 16667c478bd9Sstevel@tonic-gate error(gettext(NO_PROCS_ERR)); 16677c478bd9Sstevel@tonic-gate 16687c478bd9Sstevel@tonic-gate if (pid == 0) { 16697c478bd9Sstevel@tonic-gate if (wantpr) { 16707c478bd9Sstevel@tonic-gate (void) close(1); 16717c478bd9Sstevel@tonic-gate (void) dup(pv[1]); 16727c478bd9Sstevel@tonic-gate (void) close(pv[0]); 16737c478bd9Sstevel@tonic-gate (void) close(pv[1]); 16747c478bd9Sstevel@tonic-gate } 16757c478bd9Sstevel@tonic-gate (void) execv(diff+5, diffargv); 16767c478bd9Sstevel@tonic-gate (void) execv(diff, diffargv); 16777c478bd9Sstevel@tonic-gate perror(diff); 16787c478bd9Sstevel@tonic-gate done(); 16797c478bd9Sstevel@tonic-gate } 16807c478bd9Sstevel@tonic-gate if (wantpr) { 16817c478bd9Sstevel@tonic-gate (void) close(pv[0]); 16827c478bd9Sstevel@tonic-gate (void) close(pv[1]); 16837c478bd9Sstevel@tonic-gate } 16847c478bd9Sstevel@tonic-gate while (wait(&diffstatus) != pid) 16857c478bd9Sstevel@tonic-gate continue; 16867c478bd9Sstevel@tonic-gate while (wait((int *)0) != (pid_t)-1) 16877c478bd9Sstevel@tonic-gate continue; 16887c478bd9Sstevel@tonic-gate if ((diffstatus&0177) != 0) 16897c478bd9Sstevel@tonic-gate return (2); 16907c478bd9Sstevel@tonic-gate else 16917c478bd9Sstevel@tonic-gate return ((diffstatus>>8) & 0377); 16927c478bd9Sstevel@tonic-gate } 16937c478bd9Sstevel@tonic-gate 16947c478bd9Sstevel@tonic-gate static char * 16957c478bd9Sstevel@tonic-gate pfiletype(mode_t fmt) 16967c478bd9Sstevel@tonic-gate { 16977c478bd9Sstevel@tonic-gate /* 16987c478bd9Sstevel@tonic-gate * TRANSLATION_NOTE 16997c478bd9Sstevel@tonic-gate * The following 9 messages will be used in the second and 17007c478bd9Sstevel@tonic-gate * the fourth parameters of the message 17017c478bd9Sstevel@tonic-gate * "File %s is %s while file %s is %s\n" 17027c478bd9Sstevel@tonic-gate */ 17037c478bd9Sstevel@tonic-gate switch (fmt) { 17047c478bd9Sstevel@tonic-gate 17057c478bd9Sstevel@tonic-gate case S_IFDIR: 17067c478bd9Sstevel@tonic-gate return (gettext("a directory")); 17077c478bd9Sstevel@tonic-gate break; 17087c478bd9Sstevel@tonic-gate 17097c478bd9Sstevel@tonic-gate case S_IFCHR: 17107c478bd9Sstevel@tonic-gate return (gettext("a character special file")); 17117c478bd9Sstevel@tonic-gate break; 17127c478bd9Sstevel@tonic-gate 17137c478bd9Sstevel@tonic-gate case S_IFBLK: 17147c478bd9Sstevel@tonic-gate return (gettext("a block special file")); 17157c478bd9Sstevel@tonic-gate break; 17167c478bd9Sstevel@tonic-gate 17177c478bd9Sstevel@tonic-gate case S_IFREG: 17187c478bd9Sstevel@tonic-gate return (gettext("a plain file")); 17197c478bd9Sstevel@tonic-gate break; 17207c478bd9Sstevel@tonic-gate 17217c478bd9Sstevel@tonic-gate case S_IFIFO: 17227c478bd9Sstevel@tonic-gate return (gettext("a named pipe")); 17237c478bd9Sstevel@tonic-gate break; 17247c478bd9Sstevel@tonic-gate 17257c478bd9Sstevel@tonic-gate case S_IFSOCK: 17267c478bd9Sstevel@tonic-gate return (gettext("a socket")); 17277c478bd9Sstevel@tonic-gate break; 17287c478bd9Sstevel@tonic-gate 17297c478bd9Sstevel@tonic-gate case S_IFDOOR: 17307c478bd9Sstevel@tonic-gate return (gettext("a door")); 17317c478bd9Sstevel@tonic-gate break; 17327c478bd9Sstevel@tonic-gate 17337c478bd9Sstevel@tonic-gate case S_IFPORT: 17347c478bd9Sstevel@tonic-gate return (gettext("an event port")); 17357c478bd9Sstevel@tonic-gate break; 17367c478bd9Sstevel@tonic-gate 17377c478bd9Sstevel@tonic-gate default: 17387c478bd9Sstevel@tonic-gate return (gettext("an unknown type")); 17397c478bd9Sstevel@tonic-gate break; 17407c478bd9Sstevel@tonic-gate } 17417c478bd9Sstevel@tonic-gate } 17427c478bd9Sstevel@tonic-gate 17437c478bd9Sstevel@tonic-gate static int 17447c478bd9Sstevel@tonic-gate binary(int f) 17457c478bd9Sstevel@tonic-gate { 17467c478bd9Sstevel@tonic-gate char buf[BUFSIZ]; 17477c478bd9Sstevel@tonic-gate int cnt; 17487c478bd9Sstevel@tonic-gate 17497c478bd9Sstevel@tonic-gate (void) lseek(f, (long)0, SEEK_SET); 17507c478bd9Sstevel@tonic-gate cnt = read(f, buf, BUFSIZ); 17517c478bd9Sstevel@tonic-gate if (cnt < 0) 17527c478bd9Sstevel@tonic-gate return (1); 17537c478bd9Sstevel@tonic-gate return (isbinary(buf, cnt)); 17547c478bd9Sstevel@tonic-gate } 17557c478bd9Sstevel@tonic-gate 17567c478bd9Sstevel@tonic-gate static int 17577c478bd9Sstevel@tonic-gate filebinary(FILE *f) 17587c478bd9Sstevel@tonic-gate { 17597c478bd9Sstevel@tonic-gate char buf[BUFSIZ]; 17607c478bd9Sstevel@tonic-gate int cnt; 17617c478bd9Sstevel@tonic-gate 17627c478bd9Sstevel@tonic-gate (void) fseek(f, (long)0, SEEK_SET); 17637c478bd9Sstevel@tonic-gate cnt = fread(buf, 1, BUFSIZ, f); 17647c478bd9Sstevel@tonic-gate if (ferror(f)) 17657c478bd9Sstevel@tonic-gate return (1); 17667c478bd9Sstevel@tonic-gate return (isbinary(buf, cnt)); 17677c478bd9Sstevel@tonic-gate } 17687c478bd9Sstevel@tonic-gate 17697c478bd9Sstevel@tonic-gate 17707c478bd9Sstevel@tonic-gate /* 17717c478bd9Sstevel@tonic-gate * We consider a "binary" file to be one that: 17727c478bd9Sstevel@tonic-gate * contains a null character ("diff" doesn't handle them correctly, and 17737c478bd9Sstevel@tonic-gate * neither do many other UNIX text-processing commands). 17747c478bd9Sstevel@tonic-gate * Characters with their 8th bit set do NOT make a file binary; they may be 17757c478bd9Sstevel@tonic-gate * legitimate text characters, or parts of same. 17767c478bd9Sstevel@tonic-gate */ 17777c478bd9Sstevel@tonic-gate static int 17787c478bd9Sstevel@tonic-gate isbinary(char *buf, int cnt) 17797c478bd9Sstevel@tonic-gate { 17807c478bd9Sstevel@tonic-gate char *cp; 17817c478bd9Sstevel@tonic-gate 17827c478bd9Sstevel@tonic-gate cp = buf; 17837c478bd9Sstevel@tonic-gate while (--cnt >= 0) 17847c478bd9Sstevel@tonic-gate if (*cp++ == '\0') 17857c478bd9Sstevel@tonic-gate return (1); 17867c478bd9Sstevel@tonic-gate return (0); 17877c478bd9Sstevel@tonic-gate } 17887c478bd9Sstevel@tonic-gate 17897c478bd9Sstevel@tonic-gate 17907c478bd9Sstevel@tonic-gate /* 17917c478bd9Sstevel@tonic-gate * THIS IS CRUDE. 17927c478bd9Sstevel@tonic-gate */ 17937c478bd9Sstevel@tonic-gate static int 17947c478bd9Sstevel@tonic-gate useless(char *cp) 17957c478bd9Sstevel@tonic-gate { 17967c478bd9Sstevel@tonic-gate 17977c478bd9Sstevel@tonic-gate if (cp[0] == '.') { 17987c478bd9Sstevel@tonic-gate if (cp[1] == '\0') 17997c478bd9Sstevel@tonic-gate return (1); /* directory "." */ 18007c478bd9Sstevel@tonic-gate if (cp[1] == '.' && cp[2] == '\0') 18017c478bd9Sstevel@tonic-gate return (1); /* directory ".." */ 18027c478bd9Sstevel@tonic-gate } 18037c478bd9Sstevel@tonic-gate if (start && strcmp(start, cp) > 0) 18047c478bd9Sstevel@tonic-gate return (1); 18057c478bd9Sstevel@tonic-gate return (0); 18067c478bd9Sstevel@tonic-gate } 18077c478bd9Sstevel@tonic-gate 18087c478bd9Sstevel@tonic-gate 18097c478bd9Sstevel@tonic-gate void 18107c478bd9Sstevel@tonic-gate sort(struct line *a, int n) /* shellsort CACM #201 */ 18117c478bd9Sstevel@tonic-gate { 18127c478bd9Sstevel@tonic-gate struct line w; 18137c478bd9Sstevel@tonic-gate int j, m; 18147c478bd9Sstevel@tonic-gate struct line *ai; 18157c478bd9Sstevel@tonic-gate struct line *aim; 18167c478bd9Sstevel@tonic-gate int k; 18177c478bd9Sstevel@tonic-gate 18187c478bd9Sstevel@tonic-gate for (j = 1, m = 0; j <= n; j *= 2) 18197c478bd9Sstevel@tonic-gate m = 2 * j - 1; 18207c478bd9Sstevel@tonic-gate for (m /= 2; m != 0; m /= 2) { 18217c478bd9Sstevel@tonic-gate k = n - m; 18227c478bd9Sstevel@tonic-gate for (j = 1; j <= k; j++) { 18237c478bd9Sstevel@tonic-gate for (ai = &a[j]; ai > a; ai -= m) { 18247c478bd9Sstevel@tonic-gate aim = &ai[m]; 18257c478bd9Sstevel@tonic-gate if (aim < ai) 18267c478bd9Sstevel@tonic-gate break; /* wraparound */ 18277c478bd9Sstevel@tonic-gate if (aim->value > ai[0].value || 18287c478bd9Sstevel@tonic-gate aim->value == ai[0].value && 18297c478bd9Sstevel@tonic-gate aim->serial > ai[0].serial) 18307c478bd9Sstevel@tonic-gate break; 18317c478bd9Sstevel@tonic-gate w.value = ai[0].value; 18327c478bd9Sstevel@tonic-gate ai[0].value = aim->value; 18337c478bd9Sstevel@tonic-gate aim->value = w.value; 18347c478bd9Sstevel@tonic-gate w.serial = ai[0].serial; 18357c478bd9Sstevel@tonic-gate ai[0].serial = aim->serial; 18367c478bd9Sstevel@tonic-gate aim->serial = w.serial; 18377c478bd9Sstevel@tonic-gate } 18387c478bd9Sstevel@tonic-gate } 18397c478bd9Sstevel@tonic-gate } 18407c478bd9Sstevel@tonic-gate } 18417c478bd9Sstevel@tonic-gate 18427c478bd9Sstevel@tonic-gate static void 18437c478bd9Sstevel@tonic-gate unsort(struct line *f, int l, int *b) 18447c478bd9Sstevel@tonic-gate { 18457c478bd9Sstevel@tonic-gate int *a; 18467c478bd9Sstevel@tonic-gate int i; 18477c478bd9Sstevel@tonic-gate 18487c478bd9Sstevel@tonic-gate a = (int *)talloc((l + 1) * sizeof (int)); 18497c478bd9Sstevel@tonic-gate for (i = 1; i <= l; i++) 18507c478bd9Sstevel@tonic-gate a[f[i].serial] = f[i].value; 18517c478bd9Sstevel@tonic-gate for (i = 1; i <= l; i++) 18527c478bd9Sstevel@tonic-gate b[i] = a[i]; 18537c478bd9Sstevel@tonic-gate free((char *)a); 18547c478bd9Sstevel@tonic-gate } 18557c478bd9Sstevel@tonic-gate 18567c478bd9Sstevel@tonic-gate static void 18577c478bd9Sstevel@tonic-gate filename(char **pa1, char **pa2, struct stat *st, char **ifile) 18587c478bd9Sstevel@tonic-gate { 18597c478bd9Sstevel@tonic-gate char *a1, *b1, *a2; 18607c478bd9Sstevel@tonic-gate 18617c478bd9Sstevel@tonic-gate a1 = *pa1; 18627c478bd9Sstevel@tonic-gate a2 = *pa2; 18637c478bd9Sstevel@tonic-gate 18647c478bd9Sstevel@tonic-gate if (strcmp(*pa1, "-") == 0) 18657c478bd9Sstevel@tonic-gate *ifile = strdup("-"); 18667c478bd9Sstevel@tonic-gate else 18677c478bd9Sstevel@tonic-gate *ifile = strdup(*pa1); 18687c478bd9Sstevel@tonic-gate 18697c478bd9Sstevel@tonic-gate if (*ifile == (char *)NULL) { 18707c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 18717c478bd9Sstevel@tonic-gate "no more memory - try again later\n")); 18727c478bd9Sstevel@tonic-gate status = 2; 18737c478bd9Sstevel@tonic-gate done(); 18747c478bd9Sstevel@tonic-gate } 18757c478bd9Sstevel@tonic-gate 18767c478bd9Sstevel@tonic-gate if ((st->st_mode & S_IFMT) == S_IFDIR) { 18777c478bd9Sstevel@tonic-gate b1 = *pa1 = (char *)malloc(PATH_MAX); 18787c478bd9Sstevel@tonic-gate while (*b1++ = *a1++) 18797c478bd9Sstevel@tonic-gate ; 18807c478bd9Sstevel@tonic-gate b1[-1] = '/'; 18817c478bd9Sstevel@tonic-gate a1 = b1; 18827c478bd9Sstevel@tonic-gate while (*a1++ = *a2++) 18837c478bd9Sstevel@tonic-gate if (*a2 && *a2 != '/' && a2[-1] == '/') 18847c478bd9Sstevel@tonic-gate a1 = b1; 18857c478bd9Sstevel@tonic-gate *ifile = strdup(*pa1); 18867c478bd9Sstevel@tonic-gate 18877c478bd9Sstevel@tonic-gate if (*ifile == (char *)NULL) { 18887c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 18897c478bd9Sstevel@tonic-gate "no more memory - try again later\n")); 18907c478bd9Sstevel@tonic-gate status = 2; 18917c478bd9Sstevel@tonic-gate done(); 18927c478bd9Sstevel@tonic-gate } 18937c478bd9Sstevel@tonic-gate 18947c478bd9Sstevel@tonic-gate if (stat(*pa1, st) < 0) { 18957c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "diff: "); 18967c478bd9Sstevel@tonic-gate perror(*pa1); 18977c478bd9Sstevel@tonic-gate done(); 18987c478bd9Sstevel@tonic-gate } 18997c478bd9Sstevel@tonic-gate } else if ((st->st_mode & S_IFMT) == S_IFCHR) 19007c478bd9Sstevel@tonic-gate *pa1 = copytemp(a1); 19017c478bd9Sstevel@tonic-gate else if (a1[0] == '-' && a1[1] == 0) { 19027c478bd9Sstevel@tonic-gate *pa1 = copytemp(a1); /* hack! */ 19037c478bd9Sstevel@tonic-gate if (stat(*pa1, st) < 0) { 19047c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "diff: "); 19057c478bd9Sstevel@tonic-gate perror(*pa1); 19067c478bd9Sstevel@tonic-gate done(); 19077c478bd9Sstevel@tonic-gate } 19087c478bd9Sstevel@tonic-gate } 19097c478bd9Sstevel@tonic-gate } 19107c478bd9Sstevel@tonic-gate 19117c478bd9Sstevel@tonic-gate static char * 19127c478bd9Sstevel@tonic-gate copytemp(char *fn) 19137c478bd9Sstevel@tonic-gate { 19147c478bd9Sstevel@tonic-gate int ifd, ofd; /* input and output file descriptors */ 19157c478bd9Sstevel@tonic-gate int i; 19167c478bd9Sstevel@tonic-gate char template[13]; /* template for temp file name */ 19177c478bd9Sstevel@tonic-gate char buf[BUFSIZ]; 19187c478bd9Sstevel@tonic-gate 19197c478bd9Sstevel@tonic-gate /* 19207c478bd9Sstevel@tonic-gate * a "-" file is interpreted as fd 0 for pre-/dev/fd systems 19217c478bd9Sstevel@tonic-gate * ... let's hope this goes away soon! 19227c478bd9Sstevel@tonic-gate */ 19237c478bd9Sstevel@tonic-gate if ((ifd = (strcmp(fn, "-") ? open(fn, 0) : 0)) < 0) { 19247c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "diff: "); 19257c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("cannot open %s\n"), fn); 19267c478bd9Sstevel@tonic-gate done(); 19277c478bd9Sstevel@tonic-gate } 19287c478bd9Sstevel@tonic-gate (void) signal(SIGHUP, (void (*)(int))done); 19297c478bd9Sstevel@tonic-gate (void) signal(SIGINT, (void (*)(int))done); 19307c478bd9Sstevel@tonic-gate (void) signal(SIGPIPE, (void (*)(int))done); 19317c478bd9Sstevel@tonic-gate (void) signal(SIGTERM, (void (*)(int))done); 19327c478bd9Sstevel@tonic-gate (void) strcpy(template, "/tmp/dXXXXXX"); 19337c478bd9Sstevel@tonic-gate if ((ofd = mkstemp(template)) < 0) { 19347c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "diff: "); 19357c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("cannot create %s\n"), template); 19367c478bd9Sstevel@tonic-gate done(); 19377c478bd9Sstevel@tonic-gate } 19387c478bd9Sstevel@tonic-gate (void) strcpy(tempfile[whichtemp++], template); 19397c478bd9Sstevel@tonic-gate while ((i = read(ifd, buf, BUFSIZ)) > 0) 19407c478bd9Sstevel@tonic-gate if (write(ofd, buf, i) != i) { 19417c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "diff: "); 19427c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 19437c478bd9Sstevel@tonic-gate gettext("write failed %s\n"), template); 19447c478bd9Sstevel@tonic-gate done(); 19457c478bd9Sstevel@tonic-gate } 19467c478bd9Sstevel@tonic-gate (void) close(ifd); (void) close(ofd); 19477c478bd9Sstevel@tonic-gate return (tempfile[whichtemp-1]); 19487c478bd9Sstevel@tonic-gate } 19497c478bd9Sstevel@tonic-gate 19507c478bd9Sstevel@tonic-gate static void 19517c478bd9Sstevel@tonic-gate prepare(int i, char *arg) 19527c478bd9Sstevel@tonic-gate { 19537c478bd9Sstevel@tonic-gate struct line *p; 19547c478bd9Sstevel@tonic-gate int j, h; 19557c478bd9Sstevel@tonic-gate 19567c478bd9Sstevel@tonic-gate (void) fseek(input[i], (long)0, SEEK_SET); 19577c478bd9Sstevel@tonic-gate p = (struct line *)talloc(3 * sizeof (line)); 19587c478bd9Sstevel@tonic-gate for (j = 0; h = readhash(input[i], i, arg); ) { 19597c478bd9Sstevel@tonic-gate p = (struct line *)ralloc((void *)p, (++j + 3) * sizeof (line)); 19607c478bd9Sstevel@tonic-gate p[j].value = h; 19617c478bd9Sstevel@tonic-gate } 19627c478bd9Sstevel@tonic-gate len[i] = j; 19637c478bd9Sstevel@tonic-gate file[i] = p; 19647c478bd9Sstevel@tonic-gate } 19657c478bd9Sstevel@tonic-gate 19667c478bd9Sstevel@tonic-gate static void 19677c478bd9Sstevel@tonic-gate prune(void) 19687c478bd9Sstevel@tonic-gate { 19697c478bd9Sstevel@tonic-gate int i, j; 19707c478bd9Sstevel@tonic-gate 19717c478bd9Sstevel@tonic-gate for (pref = 0; pref < len[0] && pref < len[1] && 19727c478bd9Sstevel@tonic-gate file[0][pref + 1].value == file[1][pref + 1].value; 19737c478bd9Sstevel@tonic-gate pref++) 19747c478bd9Sstevel@tonic-gate ; 19757c478bd9Sstevel@tonic-gate for (suff = 0; (suff < len[0] - pref) && 19767c478bd9Sstevel@tonic-gate (suff < len[1] - pref) && 19777c478bd9Sstevel@tonic-gate (file[0][len[0] - suff].value == 19787c478bd9Sstevel@tonic-gate file[1][len[1] - suff].value); 19797c478bd9Sstevel@tonic-gate suff++) 19807c478bd9Sstevel@tonic-gate ; 19817c478bd9Sstevel@tonic-gate 19827c478bd9Sstevel@tonic-gate /* decremnt suff by 2 iff suff >= 2, ensure that suff is never < 0 */ 19837c478bd9Sstevel@tonic-gate if (suff >= 2) 19847c478bd9Sstevel@tonic-gate suff -= 2; 19857c478bd9Sstevel@tonic-gate 19867c478bd9Sstevel@tonic-gate for (j = 0; j < 2; j++) { 19877c478bd9Sstevel@tonic-gate sfile[j] = file[j] + pref; 19887c478bd9Sstevel@tonic-gate slen[j] = len[j] - pref - suff; 19897c478bd9Sstevel@tonic-gate for (i = 0; i <= slen[j]; i++) 19907c478bd9Sstevel@tonic-gate sfile[j][i].serial = i; 19917c478bd9Sstevel@tonic-gate } 19927c478bd9Sstevel@tonic-gate } 19937c478bd9Sstevel@tonic-gate 19947c478bd9Sstevel@tonic-gate static void 19957c478bd9Sstevel@tonic-gate equiv(struct line *a, int n, struct line *b, int m, int *c) 19967c478bd9Sstevel@tonic-gate { 19977c478bd9Sstevel@tonic-gate int i, j; 19987c478bd9Sstevel@tonic-gate i = j = 1; 19997c478bd9Sstevel@tonic-gate while (i <= n && j <= m) { 20007c478bd9Sstevel@tonic-gate if (a[i].value < b[j].value) 20017c478bd9Sstevel@tonic-gate a[i++].value = 0; 20027c478bd9Sstevel@tonic-gate else if (a[i].value == b[j].value) 20037c478bd9Sstevel@tonic-gate a[i++].value = j; 20047c478bd9Sstevel@tonic-gate else 20057c478bd9Sstevel@tonic-gate j++; 20067c478bd9Sstevel@tonic-gate } 20077c478bd9Sstevel@tonic-gate while (i <= n) 20087c478bd9Sstevel@tonic-gate a[i++].value = 0; 20097c478bd9Sstevel@tonic-gate b[m+1].value = 0; j = 0; 20107c478bd9Sstevel@tonic-gate while (++j <= m) { 20117c478bd9Sstevel@tonic-gate c[j] = -b[j].serial; 20127c478bd9Sstevel@tonic-gate while (b[j + 1].value == b[j].value) { 20137c478bd9Sstevel@tonic-gate j++; 20147c478bd9Sstevel@tonic-gate c[j] = b[j].serial; 20157c478bd9Sstevel@tonic-gate } 20167c478bd9Sstevel@tonic-gate } 20177c478bd9Sstevel@tonic-gate c[j] = -1; 20187c478bd9Sstevel@tonic-gate } 20197c478bd9Sstevel@tonic-gate 20207c478bd9Sstevel@tonic-gate static void 20217c478bd9Sstevel@tonic-gate done(void) 20227c478bd9Sstevel@tonic-gate { 20237c478bd9Sstevel@tonic-gate if (whichtemp) (void) unlink(tempfile[0]); 20247c478bd9Sstevel@tonic-gate if (whichtemp == 2) (void) unlink(tempfile[1]); 20257c478bd9Sstevel@tonic-gate exit(status); 20267c478bd9Sstevel@tonic-gate } 20277c478bd9Sstevel@tonic-gate 20287c478bd9Sstevel@tonic-gate static void 20297c478bd9Sstevel@tonic-gate noroom(void) 20307c478bd9Sstevel@tonic-gate { 20317c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "diff: "); 20327c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("files too big, try -h\n")); 20337c478bd9Sstevel@tonic-gate done(); 20347c478bd9Sstevel@tonic-gate } 20357c478bd9Sstevel@tonic-gate 20367c478bd9Sstevel@tonic-gate static void 20377c478bd9Sstevel@tonic-gate error(const char *s) 20387c478bd9Sstevel@tonic-gate { 20397c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "diff: "); 20407c478bd9Sstevel@tonic-gate (void) fprintf(stderr, s); 20417c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "\n"); 20427c478bd9Sstevel@tonic-gate done(); 20437c478bd9Sstevel@tonic-gate } 20447c478bd9Sstevel@tonic-gate 20457c478bd9Sstevel@tonic-gate static void 20467c478bd9Sstevel@tonic-gate usage(void) 20477c478bd9Sstevel@tonic-gate { 20487c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 20497c478bd9Sstevel@tonic-gate "usage: diff [-bitw] [-c | -e | -f | -h | -n | -u] file1 " 20507c478bd9Sstevel@tonic-gate "file2\n" 20517c478bd9Sstevel@tonic-gate " diff [-bitw] [-C number | -U number] file1 file2\n" 20527c478bd9Sstevel@tonic-gate " diff [-bitw] [-D string] file1 file2\n" 20537c478bd9Sstevel@tonic-gate " diff [-bitw] [-c | -e | -f | -h | -n | -u] [-l] [-r] " 20547c478bd9Sstevel@tonic-gate "[-s] [-S name] directory1 directory2\n")); 20557c478bd9Sstevel@tonic-gate status = 2; 20567c478bd9Sstevel@tonic-gate done(); 20577c478bd9Sstevel@tonic-gate } 20587c478bd9Sstevel@tonic-gate 20597c478bd9Sstevel@tonic-gate #define NW 1024 20607c478bd9Sstevel@tonic-gate struct buff { 20617c478bd9Sstevel@tonic-gate FILE *iop; /* I/O stream */ 20627c478bd9Sstevel@tonic-gate char buf[NW + MB_LEN_MAX]; /* buffer */ 20637c478bd9Sstevel@tonic-gate char *ptr; /* current pointer in the buffer */ 20647c478bd9Sstevel@tonic-gate int buffered; /* if non-zero, buffer has data */ 20657c478bd9Sstevel@tonic-gate long offset; /* offset in the file */ 20667c478bd9Sstevel@tonic-gate }; 20677c478bd9Sstevel@tonic-gate 20687c478bd9Sstevel@tonic-gate static struct buff bufwchar[2]; 20697c478bd9Sstevel@tonic-gate 20707c478bd9Sstevel@tonic-gate /* 20717c478bd9Sstevel@tonic-gate * Initializes the buff structure for specified 20727c478bd9Sstevel@tonic-gate * I/O stream. Also sets the specified offset 20737c478bd9Sstevel@tonic-gate */ 20747c478bd9Sstevel@tonic-gate static void 20757c478bd9Sstevel@tonic-gate initbuf(FILE *iop, int filen, long offset) 20767c478bd9Sstevel@tonic-gate { 20777c478bd9Sstevel@tonic-gate bufwchar[filen].iop = iop; 20787c478bd9Sstevel@tonic-gate bufwchar[filen].ptr = NULL; 20797c478bd9Sstevel@tonic-gate bufwchar[filen].buffered = 0; 20807c478bd9Sstevel@tonic-gate bufwchar[filen].offset = offset; 20817c478bd9Sstevel@tonic-gate } 20827c478bd9Sstevel@tonic-gate 20837c478bd9Sstevel@tonic-gate /* 20847c478bd9Sstevel@tonic-gate * Reset a buff structure, and rewind the associated file. 20857c478bd9Sstevel@tonic-gate */ 20867c478bd9Sstevel@tonic-gate static void 20877c478bd9Sstevel@tonic-gate resetbuf(int filen) 20887c478bd9Sstevel@tonic-gate { 20897c478bd9Sstevel@tonic-gate bufwchar[filen].ptr = NULL; 20907c478bd9Sstevel@tonic-gate bufwchar[filen].buffered = bufwchar[filen].offset = 0; 20917c478bd9Sstevel@tonic-gate rewind(bufwchar[filen].iop); 20927c478bd9Sstevel@tonic-gate } 20937c478bd9Sstevel@tonic-gate 20947c478bd9Sstevel@tonic-gate 20957c478bd9Sstevel@tonic-gate /* 20967c478bd9Sstevel@tonic-gate * Returns the current offset in the file 20977c478bd9Sstevel@tonic-gate */ 20987c478bd9Sstevel@tonic-gate static long 20997c478bd9Sstevel@tonic-gate ftellbuf(int filen) 21007c478bd9Sstevel@tonic-gate { 21017c478bd9Sstevel@tonic-gate return (bufwchar[filen].offset); 21027c478bd9Sstevel@tonic-gate } 21037c478bd9Sstevel@tonic-gate 21047c478bd9Sstevel@tonic-gate static wint_t 21057c478bd9Sstevel@tonic-gate wcput(wint_t wc) 21067c478bd9Sstevel@tonic-gate { 21077c478bd9Sstevel@tonic-gate char mbs[MB_LEN_MAX]; 21087c478bd9Sstevel@tonic-gate unsigned char *p; 21097c478bd9Sstevel@tonic-gate int n; 21107c478bd9Sstevel@tonic-gate 21117c478bd9Sstevel@tonic-gate n = wctomb(mbs, (wchar_t)wc); 21127c478bd9Sstevel@tonic-gate if (n > 0) { 21137c478bd9Sstevel@tonic-gate p = (unsigned char *)mbs; 21147c478bd9Sstevel@tonic-gate while (n--) { 21157c478bd9Sstevel@tonic-gate (void) putc((*p++), stdout); 21167c478bd9Sstevel@tonic-gate } 21177c478bd9Sstevel@tonic-gate return (wc); 21187c478bd9Sstevel@tonic-gate } else if (n < 0) { 21197c478bd9Sstevel@tonic-gate (void) putc((int)(wc & 0xff), stdout); 21207c478bd9Sstevel@tonic-gate return (wc & 0xff); 21217c478bd9Sstevel@tonic-gate } else { 21227c478bd9Sstevel@tonic-gate /* this should not happen */ 21237c478bd9Sstevel@tonic-gate return (WEOF); 21247c478bd9Sstevel@tonic-gate } 21257c478bd9Sstevel@tonic-gate } 21267c478bd9Sstevel@tonic-gate 21277c478bd9Sstevel@tonic-gate /* 21287c478bd9Sstevel@tonic-gate * Reads one wide-character from the file associated with filen. 21297c478bd9Sstevel@tonic-gate * If multibyte locales, the input is buffered. 21307c478bd9Sstevel@tonic-gate * 21317c478bd9Sstevel@tonic-gate * Input: filen the file number (0 or 1) 21327c478bd9Sstevel@tonic-gate * Output: *len number of bytes to make wide-character 21337c478bd9Sstevel@tonic-gate * Return: wide-character 21347c478bd9Sstevel@tonic-gate */ 21357c478bd9Sstevel@tonic-gate static wint_t 21367c478bd9Sstevel@tonic-gate getbufwchar(int filen, int *len) 21377c478bd9Sstevel@tonic-gate { 21387c478bd9Sstevel@tonic-gate 21397c478bd9Sstevel@tonic-gate int i, num, clen; 21407c478bd9Sstevel@tonic-gate wchar_t wc; 21417c478bd9Sstevel@tonic-gate size_t mxlen; 21427c478bd9Sstevel@tonic-gate 21437c478bd9Sstevel@tonic-gate if (mbcurmax == 1) { 21447c478bd9Sstevel@tonic-gate /* If sigle byte locale, use getc() */ 21457c478bd9Sstevel@tonic-gate int ch; 21467c478bd9Sstevel@tonic-gate 21477c478bd9Sstevel@tonic-gate ch = getc(bufwchar[filen].iop); 21487c478bd9Sstevel@tonic-gate bufwchar[filen].offset++; 21497c478bd9Sstevel@tonic-gate *len = 1; 21507c478bd9Sstevel@tonic-gate 21517c478bd9Sstevel@tonic-gate if (isascii(ch) || (ch == EOF)) { 21527c478bd9Sstevel@tonic-gate return ((wint_t)ch); 21537c478bd9Sstevel@tonic-gate } else { 21547c478bd9Sstevel@tonic-gate wchar_t wc; 21557c478bd9Sstevel@tonic-gate char str[2] = {0, 0}; 21567c478bd9Sstevel@tonic-gate 21577c478bd9Sstevel@tonic-gate str[0] = (char)ch; 21587c478bd9Sstevel@tonic-gate if (mbtowc(&wc, str, 1) > 0) { 21597c478bd9Sstevel@tonic-gate return ((wint_t)wc); 21607c478bd9Sstevel@tonic-gate } else { 21617c478bd9Sstevel@tonic-gate return ((wint_t)ch); 21627c478bd9Sstevel@tonic-gate } 21637c478bd9Sstevel@tonic-gate } 21647c478bd9Sstevel@tonic-gate } else { 21657c478bd9Sstevel@tonic-gate mxlen = mbcurmax; 21667c478bd9Sstevel@tonic-gate } 21677c478bd9Sstevel@tonic-gate 21687c478bd9Sstevel@tonic-gate if (bufwchar[filen].buffered == 0) { 21697c478bd9Sstevel@tonic-gate /* Not buffered */ 21707c478bd9Sstevel@tonic-gate bufwchar[filen].ptr = &(bufwchar[filen].buf[MB_LEN_MAX]); 21717c478bd9Sstevel@tonic-gate num = fread((void *)bufwchar[filen].ptr, 21727c478bd9Sstevel@tonic-gate sizeof (char), NW, bufwchar[filen].iop); 21737c478bd9Sstevel@tonic-gate if (ferror(bufwchar[filen].iop)) { 21747c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "diff: "); 21757c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Error reading ")); 21767c478bd9Sstevel@tonic-gate perror((filen == 0) ? file1 : file2); 21777c478bd9Sstevel@tonic-gate status = 2; 21787c478bd9Sstevel@tonic-gate done(); 21797c478bd9Sstevel@tonic-gate } 21807c478bd9Sstevel@tonic-gate if (num == 0) 21817c478bd9Sstevel@tonic-gate return (WEOF); 21827c478bd9Sstevel@tonic-gate bufwchar[filen].buffered = num; 21837c478bd9Sstevel@tonic-gate } 21847c478bd9Sstevel@tonic-gate 21857c478bd9Sstevel@tonic-gate if (bufwchar[filen].buffered < mbcurmax) { 21867c478bd9Sstevel@tonic-gate for (i = 0; i < bufwchar[filen].buffered; i++) { 21877c478bd9Sstevel@tonic-gate bufwchar[filen].buf[MB_LEN_MAX - 21887c478bd9Sstevel@tonic-gate (bufwchar[filen].buffered - i)] = 21897c478bd9Sstevel@tonic-gate *(bufwchar[filen].ptr + i); 21907c478bd9Sstevel@tonic-gate } 21917c478bd9Sstevel@tonic-gate bufwchar[filen].ptr = &(bufwchar[filen].buf[MB_LEN_MAX]); 21927c478bd9Sstevel@tonic-gate num = fread((void *)bufwchar[filen].ptr, 21937c478bd9Sstevel@tonic-gate sizeof (char), NW, bufwchar[filen].iop); 21947c478bd9Sstevel@tonic-gate if (ferror(bufwchar[filen].iop)) { 21957c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "diff: "); 21967c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Error reading ")); 21977c478bd9Sstevel@tonic-gate perror((filen == 0) ? file1 : file2); 21987c478bd9Sstevel@tonic-gate status = 2; 21997c478bd9Sstevel@tonic-gate done(); 22007c478bd9Sstevel@tonic-gate } 22017c478bd9Sstevel@tonic-gate bufwchar[filen].ptr = &(bufwchar[filen].buf[MB_LEN_MAX - 22027c478bd9Sstevel@tonic-gate bufwchar[filen].buffered]); 22037c478bd9Sstevel@tonic-gate bufwchar[filen].buffered += num; 22047c478bd9Sstevel@tonic-gate if (bufwchar[filen].buffered < mbcurmax) { 22057c478bd9Sstevel@tonic-gate mxlen = bufwchar[filen].buffered; 22067c478bd9Sstevel@tonic-gate } 22077c478bd9Sstevel@tonic-gate } 22087c478bd9Sstevel@tonic-gate 22097c478bd9Sstevel@tonic-gate clen = mbtowc(&wc, bufwchar[filen].ptr, mxlen); 22107c478bd9Sstevel@tonic-gate if (clen <= 0) { 22117c478bd9Sstevel@tonic-gate (bufwchar[filen].buffered)--; 22127c478bd9Sstevel@tonic-gate *len = 1; 22137c478bd9Sstevel@tonic-gate (bufwchar[filen].offset)++; 22147c478bd9Sstevel@tonic-gate wc = (wchar_t)((unsigned char)*bufwchar[filen].ptr++); 22157c478bd9Sstevel@tonic-gate return ((wint_t)wc); 22167c478bd9Sstevel@tonic-gate } else { 22177c478bd9Sstevel@tonic-gate bufwchar[filen].buffered -= clen; 22187c478bd9Sstevel@tonic-gate bufwchar[filen].ptr += clen; 22197c478bd9Sstevel@tonic-gate bufwchar[filen].offset += clen; 22207c478bd9Sstevel@tonic-gate *len = clen; 22217c478bd9Sstevel@tonic-gate return ((wint_t)wc); 22227c478bd9Sstevel@tonic-gate } 22237c478bd9Sstevel@tonic-gate } 2224