13bbe3f67SBaptiste Daroussin /* $OpenBSD: diffreg.c,v 1.91 2016/03/01 20:57:35 natano Exp $ */ 23bbe3f67SBaptiste Daroussin 33bbe3f67SBaptiste Daroussin /* 43bbe3f67SBaptiste Daroussin * Copyright (C) Caldera International Inc. 2001-2002. 53bbe3f67SBaptiste Daroussin * All rights reserved. 63bbe3f67SBaptiste Daroussin * 73bbe3f67SBaptiste Daroussin * Redistribution and use in source and binary forms, with or without 83bbe3f67SBaptiste Daroussin * modification, are permitted provided that the following conditions 93bbe3f67SBaptiste Daroussin * are met: 103bbe3f67SBaptiste Daroussin * 1. Redistributions of source code and documentation must retain the above 113bbe3f67SBaptiste Daroussin * copyright notice, this list of conditions and the following disclaimer. 123bbe3f67SBaptiste Daroussin * 2. Redistributions in binary form must reproduce the above copyright 133bbe3f67SBaptiste Daroussin * notice, this list of conditions and the following disclaimer in the 143bbe3f67SBaptiste Daroussin * documentation and/or other materials provided with the distribution. 153bbe3f67SBaptiste Daroussin * 3. All advertising materials mentioning features or use of this software 163bbe3f67SBaptiste Daroussin * must display the following acknowledgement: 173bbe3f67SBaptiste Daroussin * This product includes software developed or owned by Caldera 183bbe3f67SBaptiste Daroussin * International, Inc. 193bbe3f67SBaptiste Daroussin * 4. Neither the name of Caldera International, Inc. nor the names of other 203bbe3f67SBaptiste Daroussin * contributors may be used to endorse or promote products derived from 213bbe3f67SBaptiste Daroussin * this software without specific prior written permission. 223bbe3f67SBaptiste Daroussin * 233bbe3f67SBaptiste Daroussin * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA 243bbe3f67SBaptiste Daroussin * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR 253bbe3f67SBaptiste Daroussin * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 263bbe3f67SBaptiste Daroussin * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 273bbe3f67SBaptiste Daroussin * IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE FOR ANY DIRECT, 283bbe3f67SBaptiste Daroussin * INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 293bbe3f67SBaptiste Daroussin * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 303bbe3f67SBaptiste Daroussin * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 313bbe3f67SBaptiste Daroussin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 323bbe3f67SBaptiste Daroussin * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 333bbe3f67SBaptiste Daroussin * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 343bbe3f67SBaptiste Daroussin * POSSIBILITY OF SUCH DAMAGE. 353bbe3f67SBaptiste Daroussin */ 363bbe3f67SBaptiste Daroussin /*- 373bbe3f67SBaptiste Daroussin * Copyright (c) 1991, 1993 383bbe3f67SBaptiste Daroussin * The Regents of the University of California. All rights reserved. 393bbe3f67SBaptiste Daroussin * 403bbe3f67SBaptiste Daroussin * Redistribution and use in source and binary forms, with or without 413bbe3f67SBaptiste Daroussin * modification, are permitted provided that the following conditions 423bbe3f67SBaptiste Daroussin * are met: 433bbe3f67SBaptiste Daroussin * 1. Redistributions of source code must retain the above copyright 443bbe3f67SBaptiste Daroussin * notice, this list of conditions and the following disclaimer. 453bbe3f67SBaptiste Daroussin * 2. Redistributions in binary form must reproduce the above copyright 463bbe3f67SBaptiste Daroussin * notice, this list of conditions and the following disclaimer in the 473bbe3f67SBaptiste Daroussin * documentation and/or other materials provided with the distribution. 483bbe3f67SBaptiste Daroussin * 3. Neither the name of the University nor the names of its contributors 493bbe3f67SBaptiste Daroussin * may be used to endorse or promote products derived from this software 503bbe3f67SBaptiste Daroussin * without specific prior written permission. 513bbe3f67SBaptiste Daroussin * 523bbe3f67SBaptiste Daroussin * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 533bbe3f67SBaptiste Daroussin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 543bbe3f67SBaptiste Daroussin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 553bbe3f67SBaptiste Daroussin * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 563bbe3f67SBaptiste Daroussin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 573bbe3f67SBaptiste Daroussin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 583bbe3f67SBaptiste Daroussin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 593bbe3f67SBaptiste Daroussin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 603bbe3f67SBaptiste Daroussin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 613bbe3f67SBaptiste Daroussin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 623bbe3f67SBaptiste Daroussin * SUCH DAMAGE. 633bbe3f67SBaptiste Daroussin * 643bbe3f67SBaptiste Daroussin * @(#)diffreg.c 8.1 (Berkeley) 6/6/93 653bbe3f67SBaptiste Daroussin */ 663bbe3f67SBaptiste Daroussin 673bbe3f67SBaptiste Daroussin #include <sys/cdefs.h> 683bbe3f67SBaptiste Daroussin __FBSDID("$FreeBSD$"); 693bbe3f67SBaptiste Daroussin 703bbe3f67SBaptiste Daroussin #include <sys/capsicum.h> 713bbe3f67SBaptiste Daroussin #include <sys/procdesc.h> 723bbe3f67SBaptiste Daroussin #include <sys/stat.h> 733bbe3f67SBaptiste Daroussin #include <sys/types.h> 743bbe3f67SBaptiste Daroussin #include <sys/event.h> 753bbe3f67SBaptiste Daroussin #include <sys/wait.h> 763bbe3f67SBaptiste Daroussin 773bbe3f67SBaptiste Daroussin #include <capsicum_helpers.h> 783bbe3f67SBaptiste Daroussin #include <ctype.h> 793bbe3f67SBaptiste Daroussin #include <err.h> 803bbe3f67SBaptiste Daroussin #include <errno.h> 813bbe3f67SBaptiste Daroussin #include <fcntl.h> 823bbe3f67SBaptiste Daroussin #include <paths.h> 837752043cSBaptiste Daroussin #include <regex.h> 843bbe3f67SBaptiste Daroussin #include <stddef.h> 853bbe3f67SBaptiste Daroussin #include <stdint.h> 863bbe3f67SBaptiste Daroussin #include <stdio.h> 873bbe3f67SBaptiste Daroussin #include <stdlib.h> 883bbe3f67SBaptiste Daroussin #include <string.h> 893bbe3f67SBaptiste Daroussin #include <unistd.h> 903bbe3f67SBaptiste Daroussin #include <limits.h> 913bbe3f67SBaptiste Daroussin #include <signal.h> 923bbe3f67SBaptiste Daroussin 933bbe3f67SBaptiste Daroussin #include "diff.h" 943bbe3f67SBaptiste Daroussin #include "xmalloc.h" 953bbe3f67SBaptiste Daroussin 963bbe3f67SBaptiste Daroussin #define _PATH_PR "/usr/bin/pr" 973bbe3f67SBaptiste Daroussin 983bbe3f67SBaptiste Daroussin /* 993bbe3f67SBaptiste Daroussin * diff - compare two files. 1003bbe3f67SBaptiste Daroussin */ 1013bbe3f67SBaptiste Daroussin 1023bbe3f67SBaptiste Daroussin /* 1033bbe3f67SBaptiste Daroussin * Uses an algorithm due to Harold Stone, which finds 1043bbe3f67SBaptiste Daroussin * a pair of longest identical subsequences in the two 1053bbe3f67SBaptiste Daroussin * files. 1063bbe3f67SBaptiste Daroussin * 1073bbe3f67SBaptiste Daroussin * The major goal is to generate the match vector J. 1083bbe3f67SBaptiste Daroussin * J[i] is the index of the line in file1 corresponding 1093bbe3f67SBaptiste Daroussin * to line i file0. J[i] = 0 if there is no 1103bbe3f67SBaptiste Daroussin * such line in file1. 1113bbe3f67SBaptiste Daroussin * 1123bbe3f67SBaptiste Daroussin * Lines are hashed so as to work in core. All potential 1133bbe3f67SBaptiste Daroussin * matches are located by sorting the lines of each file 1143bbe3f67SBaptiste Daroussin * on the hash (called ``value''). In particular, this 1153bbe3f67SBaptiste Daroussin * collects the equivalence classes in file1 together. 1163bbe3f67SBaptiste Daroussin * Subroutine equiv replaces the value of each line in 1173bbe3f67SBaptiste Daroussin * file0 by the index of the first element of its 1183bbe3f67SBaptiste Daroussin * matching equivalence in (the reordered) file1. 1193bbe3f67SBaptiste Daroussin * To save space equiv squeezes file1 into a single 1203bbe3f67SBaptiste Daroussin * array member in which the equivalence classes 1213bbe3f67SBaptiste Daroussin * are simply concatenated, except that their first 1223bbe3f67SBaptiste Daroussin * members are flagged by changing sign. 1233bbe3f67SBaptiste Daroussin * 1243bbe3f67SBaptiste Daroussin * Next the indices that point into member are unsorted into 1253bbe3f67SBaptiste Daroussin * array class according to the original order of file0. 1263bbe3f67SBaptiste Daroussin * 1273bbe3f67SBaptiste Daroussin * The cleverness lies in routine stone. This marches 1283bbe3f67SBaptiste Daroussin * through the lines of file0, developing a vector klist 1293bbe3f67SBaptiste Daroussin * of "k-candidates". At step i a k-candidate is a matched 1303bbe3f67SBaptiste Daroussin * pair of lines x,y (x in file0 y in file1) such that 1313bbe3f67SBaptiste Daroussin * there is a common subsequence of length k 1323bbe3f67SBaptiste Daroussin * between the first i lines of file0 and the first y 1333bbe3f67SBaptiste Daroussin * lines of file1, but there is no such subsequence for 1343bbe3f67SBaptiste Daroussin * any smaller y. x is the earliest possible mate to y 1353bbe3f67SBaptiste Daroussin * that occurs in such a subsequence. 1363bbe3f67SBaptiste Daroussin * 1373bbe3f67SBaptiste Daroussin * Whenever any of the members of the equivalence class of 1383bbe3f67SBaptiste Daroussin * lines in file1 matable to a line in file0 has serial number 1393bbe3f67SBaptiste Daroussin * less than the y of some k-candidate, that k-candidate 1403bbe3f67SBaptiste Daroussin * with the smallest such y is replaced. The new 1413bbe3f67SBaptiste Daroussin * k-candidate is chained (via pred) to the current 1423bbe3f67SBaptiste Daroussin * k-1 candidate so that the actual subsequence can 1433bbe3f67SBaptiste Daroussin * be recovered. When a member has serial number greater 1443bbe3f67SBaptiste Daroussin * that the y of all k-candidates, the klist is extended. 1453bbe3f67SBaptiste Daroussin * At the end, the longest subsequence is pulled out 1463bbe3f67SBaptiste Daroussin * and placed in the array J by unravel 1473bbe3f67SBaptiste Daroussin * 1483bbe3f67SBaptiste Daroussin * With J in hand, the matches there recorded are 1493bbe3f67SBaptiste Daroussin * check'ed against reality to assure that no spurious 1503bbe3f67SBaptiste Daroussin * matches have crept in due to hashing. If they have, 1513bbe3f67SBaptiste Daroussin * they are broken, and "jackpot" is recorded--a harmless 1523bbe3f67SBaptiste Daroussin * matter except that a true match for a spuriously 1533bbe3f67SBaptiste Daroussin * mated line may now be unnecessarily reported as a change. 1543bbe3f67SBaptiste Daroussin * 1553bbe3f67SBaptiste Daroussin * Much of the complexity of the program comes simply 1563bbe3f67SBaptiste Daroussin * from trying to minimize core utilization and 1573bbe3f67SBaptiste Daroussin * maximize the range of doable problems by dynamically 1583bbe3f67SBaptiste Daroussin * allocating what is needed and reusing what is not. 1593bbe3f67SBaptiste Daroussin * The core requirements for problems larger than somewhat 1603bbe3f67SBaptiste Daroussin * are (in words) 2*length(file0) + length(file1) + 1613bbe3f67SBaptiste Daroussin * 3*(number of k-candidates installed), typically about 1623bbe3f67SBaptiste Daroussin * 6n words for files of length n. 1633bbe3f67SBaptiste Daroussin */ 1643bbe3f67SBaptiste Daroussin 1653bbe3f67SBaptiste Daroussin struct cand { 1663bbe3f67SBaptiste Daroussin int x; 1673bbe3f67SBaptiste Daroussin int y; 1683bbe3f67SBaptiste Daroussin int pred; 1693bbe3f67SBaptiste Daroussin }; 1703bbe3f67SBaptiste Daroussin 1713bbe3f67SBaptiste Daroussin static struct line { 1723bbe3f67SBaptiste Daroussin int serial; 1733bbe3f67SBaptiste Daroussin int value; 1743bbe3f67SBaptiste Daroussin } *file[2]; 1753bbe3f67SBaptiste Daroussin 1763bbe3f67SBaptiste Daroussin /* 1773bbe3f67SBaptiste Daroussin * The following struct is used to record change information when 1783bbe3f67SBaptiste Daroussin * doing a "context" or "unified" diff. (see routine "change" to 1793bbe3f67SBaptiste Daroussin * understand the highly mnemonic field names) 1803bbe3f67SBaptiste Daroussin */ 1813bbe3f67SBaptiste Daroussin struct context_vec { 1823bbe3f67SBaptiste Daroussin int a; /* start line in old file */ 1833bbe3f67SBaptiste Daroussin int b; /* end line in old file */ 1843bbe3f67SBaptiste Daroussin int c; /* start line in new file */ 1853bbe3f67SBaptiste Daroussin int d; /* end line in new file */ 1863bbe3f67SBaptiste Daroussin }; 1873bbe3f67SBaptiste Daroussin 1883bbe3f67SBaptiste Daroussin #define diff_output printf 189ff807815SBaptiste Daroussin static FILE *opentemp(const char *); 1903bbe3f67SBaptiste Daroussin static void output(char *, FILE *, char *, FILE *, int); 1913bbe3f67SBaptiste Daroussin static void check(FILE *, FILE *, int); 1923bbe3f67SBaptiste Daroussin static void range(int, int, const char *); 1933bbe3f67SBaptiste Daroussin static void uni_range(int, int); 1943bbe3f67SBaptiste Daroussin static void dump_context_vec(FILE *, FILE *, int); 1953bbe3f67SBaptiste Daroussin static void dump_unified_vec(FILE *, FILE *, int); 196d5b187aeSBaptiste Daroussin static void prepare(int, FILE *, size_t, int); 1973bbe3f67SBaptiste Daroussin static void prune(void); 1983bbe3f67SBaptiste Daroussin static void equiv(struct line *, int, struct line *, int, int *); 1993bbe3f67SBaptiste Daroussin static void unravel(int); 2003bbe3f67SBaptiste Daroussin static void unsort(struct line *, int, int *); 2013bbe3f67SBaptiste Daroussin static void change(char *, FILE *, char *, FILE *, int, int, int, int, int *); 2023bbe3f67SBaptiste Daroussin static void sort(struct line *, int); 2033bbe3f67SBaptiste Daroussin static void print_header(const char *, const char *); 2043bbe3f67SBaptiste Daroussin static int ignoreline(char *); 2053bbe3f67SBaptiste Daroussin static int asciifile(FILE *); 2063bbe3f67SBaptiste Daroussin static int fetch(long *, int, int, FILE *, int, int, int); 2073bbe3f67SBaptiste Daroussin static int newcand(int, int, int); 2083bbe3f67SBaptiste Daroussin static int search(int *, int, int); 2093bbe3f67SBaptiste Daroussin static int skipline(FILE *); 2103bbe3f67SBaptiste Daroussin static int isqrt(int); 2113bbe3f67SBaptiste Daroussin static int stone(int *, int, int *, int *, int); 2123bbe3f67SBaptiste Daroussin static int readhash(FILE *, int); 2133bbe3f67SBaptiste Daroussin static int files_differ(FILE *, FILE *, int); 2143bbe3f67SBaptiste Daroussin static char *match_function(const long *, int, FILE *); 2153bbe3f67SBaptiste Daroussin static char *preadline(int, size_t, off_t); 2163bbe3f67SBaptiste Daroussin 2173bbe3f67SBaptiste Daroussin static int *J; /* will be overlaid on class */ 2183bbe3f67SBaptiste Daroussin static int *class; /* will be overlaid on file[0] */ 2193bbe3f67SBaptiste Daroussin static int *klist; /* will be overlaid on file[0] after class */ 2203bbe3f67SBaptiste Daroussin static int *member; /* will be overlaid on file[1] */ 2213bbe3f67SBaptiste Daroussin static int clen; 2223bbe3f67SBaptiste Daroussin static int inifdef; /* whether or not we are in a #ifdef block */ 2233bbe3f67SBaptiste Daroussin static int len[2]; 2243bbe3f67SBaptiste Daroussin static int pref, suff; /* length of prefix and suffix */ 2253bbe3f67SBaptiste Daroussin static int slen[2]; 2263bbe3f67SBaptiste Daroussin static int anychange; 2273bbe3f67SBaptiste Daroussin static long *ixnew; /* will be overlaid on file[1] */ 2283bbe3f67SBaptiste Daroussin static long *ixold; /* will be overlaid on klist */ 2293bbe3f67SBaptiste Daroussin static struct cand *clist; /* merely a free storage pot for candidates */ 2303bbe3f67SBaptiste Daroussin static int clistlen; /* the length of clist */ 2313bbe3f67SBaptiste Daroussin static struct line *sfile[2]; /* shortened by pruning common prefix/suffix */ 2323bbe3f67SBaptiste Daroussin static u_char *chrtran; /* translation table for case-folding */ 2333bbe3f67SBaptiste Daroussin static struct context_vec *context_vec_start; 2343bbe3f67SBaptiste Daroussin static struct context_vec *context_vec_end; 2353bbe3f67SBaptiste Daroussin static struct context_vec *context_vec_ptr; 2363bbe3f67SBaptiste Daroussin 2373bbe3f67SBaptiste Daroussin #define FUNCTION_CONTEXT_SIZE 55 2383bbe3f67SBaptiste Daroussin static char lastbuf[FUNCTION_CONTEXT_SIZE]; 2393bbe3f67SBaptiste Daroussin static int lastline; 2403bbe3f67SBaptiste Daroussin static int lastmatchline; 2413bbe3f67SBaptiste Daroussin 2423bbe3f67SBaptiste Daroussin 2433bbe3f67SBaptiste Daroussin /* 2443bbe3f67SBaptiste Daroussin * chrtran points to one of 2 translation tables: cup2low if folding upper to 2453bbe3f67SBaptiste Daroussin * lower case clow2low if not folding case 2463bbe3f67SBaptiste Daroussin */ 2473bbe3f67SBaptiste Daroussin static u_char clow2low[256] = { 2483bbe3f67SBaptiste Daroussin 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 2493bbe3f67SBaptiste Daroussin 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 2503bbe3f67SBaptiste Daroussin 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 2513bbe3f67SBaptiste Daroussin 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 2523bbe3f67SBaptiste Daroussin 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 2533bbe3f67SBaptiste Daroussin 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 2543bbe3f67SBaptiste Daroussin 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 2553bbe3f67SBaptiste Daroussin 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 2563bbe3f67SBaptiste Daroussin 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 2573bbe3f67SBaptiste Daroussin 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 2583bbe3f67SBaptiste Daroussin 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 2593bbe3f67SBaptiste Daroussin 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 2603bbe3f67SBaptiste Daroussin 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 2613bbe3f67SBaptiste Daroussin 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 2623bbe3f67SBaptiste Daroussin 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 2633bbe3f67SBaptiste Daroussin 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 2643bbe3f67SBaptiste Daroussin 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 2653bbe3f67SBaptiste Daroussin 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 2663bbe3f67SBaptiste Daroussin 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 2673bbe3f67SBaptiste Daroussin 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 2683bbe3f67SBaptiste Daroussin 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 2693bbe3f67SBaptiste Daroussin 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 2703bbe3f67SBaptiste Daroussin 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 2713bbe3f67SBaptiste Daroussin 0xfd, 0xfe, 0xff 2723bbe3f67SBaptiste Daroussin }; 2733bbe3f67SBaptiste Daroussin 2743bbe3f67SBaptiste Daroussin static u_char cup2low[256] = { 2753bbe3f67SBaptiste Daroussin 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 2763bbe3f67SBaptiste Daroussin 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 2773bbe3f67SBaptiste Daroussin 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 2783bbe3f67SBaptiste Daroussin 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 2793bbe3f67SBaptiste Daroussin 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 2803bbe3f67SBaptiste Daroussin 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x60, 0x61, 2813bbe3f67SBaptiste Daroussin 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 2823bbe3f67SBaptiste Daroussin 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 2833bbe3f67SBaptiste Daroussin 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x60, 0x61, 0x62, 2843bbe3f67SBaptiste Daroussin 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 2853bbe3f67SBaptiste Daroussin 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 2863bbe3f67SBaptiste Daroussin 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 2873bbe3f67SBaptiste Daroussin 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 2883bbe3f67SBaptiste Daroussin 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 2893bbe3f67SBaptiste Daroussin 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 2903bbe3f67SBaptiste Daroussin 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 2913bbe3f67SBaptiste Daroussin 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 2923bbe3f67SBaptiste Daroussin 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 2933bbe3f67SBaptiste Daroussin 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 2943bbe3f67SBaptiste Daroussin 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 2953bbe3f67SBaptiste Daroussin 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 2963bbe3f67SBaptiste Daroussin 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 2973bbe3f67SBaptiste Daroussin 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 2983bbe3f67SBaptiste Daroussin 0xfd, 0xfe, 0xff 2993bbe3f67SBaptiste Daroussin }; 3003bbe3f67SBaptiste Daroussin 3013bbe3f67SBaptiste Daroussin int 3023bbe3f67SBaptiste Daroussin diffreg(char *file1, char *file2, int flags, int capsicum) 3033bbe3f67SBaptiste Daroussin { 3043bbe3f67SBaptiste Daroussin FILE *f1, *f2; 3053bbe3f67SBaptiste Daroussin int i, rval; 3063bbe3f67SBaptiste Daroussin int ostdout = -1; 3073bbe3f67SBaptiste Daroussin int pr_pd, kq; 3083bbe3f67SBaptiste Daroussin struct kevent *e; 3093bbe3f67SBaptiste Daroussin cap_rights_t rights_ro; 3103bbe3f67SBaptiste Daroussin 311d5b187aeSBaptiste Daroussin e = NULL; 312d5b187aeSBaptiste Daroussin kq = -1; 3133bbe3f67SBaptiste Daroussin f1 = f2 = NULL; 3143bbe3f67SBaptiste Daroussin rval = D_SAME; 3153bbe3f67SBaptiste Daroussin anychange = 0; 3163bbe3f67SBaptiste Daroussin lastline = 0; 3173bbe3f67SBaptiste Daroussin lastmatchline = 0; 3183bbe3f67SBaptiste Daroussin context_vec_ptr = context_vec_start - 1; 3193bbe3f67SBaptiste Daroussin if (flags & D_IGNORECASE) 3203bbe3f67SBaptiste Daroussin chrtran = cup2low; 3213bbe3f67SBaptiste Daroussin else 3223bbe3f67SBaptiste Daroussin chrtran = clow2low; 3233bbe3f67SBaptiste Daroussin if (S_ISDIR(stb1.st_mode) != S_ISDIR(stb2.st_mode)) 3243bbe3f67SBaptiste Daroussin return (S_ISDIR(stb1.st_mode) ? D_MISMATCH1 : D_MISMATCH2); 3253bbe3f67SBaptiste Daroussin if (strcmp(file1, "-") == 0 && strcmp(file2, "-") == 0) 3263bbe3f67SBaptiste Daroussin goto closem; 3273bbe3f67SBaptiste Daroussin 3283bbe3f67SBaptiste Daroussin if (flags & D_EMPTY1) 3293bbe3f67SBaptiste Daroussin f1 = fopen(_PATH_DEVNULL, "r"); 3303bbe3f67SBaptiste Daroussin else { 331ff807815SBaptiste Daroussin if (!S_ISREG(stb1.st_mode)) { 332ff807815SBaptiste Daroussin if ((f1 = opentemp(file1)) == NULL || 333ff807815SBaptiste Daroussin fstat(fileno(f1), &stb1) < 0) { 334ff807815SBaptiste Daroussin warn("%s", file1); 335ff807815SBaptiste Daroussin status |= 2; 336ff807815SBaptiste Daroussin goto closem; 337ff807815SBaptiste Daroussin } 338ff807815SBaptiste Daroussin } else if (strcmp(file1, "-") == 0) 3393bbe3f67SBaptiste Daroussin f1 = stdin; 3403bbe3f67SBaptiste Daroussin else 3413bbe3f67SBaptiste Daroussin f1 = fopen(file1, "r"); 3423bbe3f67SBaptiste Daroussin } 3433bbe3f67SBaptiste Daroussin if (f1 == NULL) { 3443bbe3f67SBaptiste Daroussin warn("%s", file1); 3453bbe3f67SBaptiste Daroussin status |= 2; 3463bbe3f67SBaptiste Daroussin goto closem; 3473bbe3f67SBaptiste Daroussin } 3483bbe3f67SBaptiste Daroussin 3493bbe3f67SBaptiste Daroussin if (flags & D_EMPTY2) 3503bbe3f67SBaptiste Daroussin f2 = fopen(_PATH_DEVNULL, "r"); 3513bbe3f67SBaptiste Daroussin else { 352ff807815SBaptiste Daroussin if (!S_ISREG(stb2.st_mode)) { 353ff807815SBaptiste Daroussin if ((f2 = opentemp(file2)) == NULL || 354ff807815SBaptiste Daroussin fstat(fileno(f2), &stb2) < 0) { 355ff807815SBaptiste Daroussin warn("%s", file2); 356ff807815SBaptiste Daroussin status |= 2; 357ff807815SBaptiste Daroussin goto closem; 358ff807815SBaptiste Daroussin } 359ff807815SBaptiste Daroussin } else if (strcmp(file2, "-") == 0) 3603bbe3f67SBaptiste Daroussin f2 = stdin; 3613bbe3f67SBaptiste Daroussin else 3623bbe3f67SBaptiste Daroussin f2 = fopen(file2, "r"); 3633bbe3f67SBaptiste Daroussin } 3643bbe3f67SBaptiste Daroussin if (f2 == NULL) { 3653bbe3f67SBaptiste Daroussin warn("%s", file2); 3663bbe3f67SBaptiste Daroussin status |= 2; 3673bbe3f67SBaptiste Daroussin goto closem; 3683bbe3f67SBaptiste Daroussin } 3693bbe3f67SBaptiste Daroussin 3703bbe3f67SBaptiste Daroussin if (lflag) { 3713bbe3f67SBaptiste Daroussin /* redirect stdout to pr */ 3723bbe3f67SBaptiste Daroussin int pfd[2]; 3733bbe3f67SBaptiste Daroussin pid_t pid; 3743bbe3f67SBaptiste Daroussin char *header; 3753bbe3f67SBaptiste Daroussin 3763bbe3f67SBaptiste Daroussin xasprintf(&header, "%s %s %s", diffargs, file1, file2); 3773bbe3f67SBaptiste Daroussin signal(SIGPIPE, SIG_IGN); 3783bbe3f67SBaptiste Daroussin fflush(stdout); 3793bbe3f67SBaptiste Daroussin rewind(stdout); 3803bbe3f67SBaptiste Daroussin pipe(pfd); 3813bbe3f67SBaptiste Daroussin switch ((pid = pdfork(&pr_pd, PD_CLOEXEC))) { 3823bbe3f67SBaptiste Daroussin case -1: 3833bbe3f67SBaptiste Daroussin status |= 2; 3843bbe3f67SBaptiste Daroussin free(header); 3853bbe3f67SBaptiste Daroussin err(2, "No more processes"); 3863bbe3f67SBaptiste Daroussin case 0: 3873bbe3f67SBaptiste Daroussin /* child */ 3883bbe3f67SBaptiste Daroussin if (pfd[0] != STDIN_FILENO) { 3893bbe3f67SBaptiste Daroussin dup2(pfd[0], STDIN_FILENO); 3903bbe3f67SBaptiste Daroussin close(pfd[0]); 3913bbe3f67SBaptiste Daroussin } 3923bbe3f67SBaptiste Daroussin close(pfd[1]); 3933bbe3f67SBaptiste Daroussin execl(_PATH_PR, _PATH_PR, "-h", header, (char *)0); 3943bbe3f67SBaptiste Daroussin _exit(127); 3953bbe3f67SBaptiste Daroussin default: 3963bbe3f67SBaptiste Daroussin 3973bbe3f67SBaptiste Daroussin /* parent */ 3983bbe3f67SBaptiste Daroussin if (pfd[1] != STDOUT_FILENO) { 3993bbe3f67SBaptiste Daroussin ostdout = dup(STDOUT_FILENO); 4003bbe3f67SBaptiste Daroussin dup2(pfd[1], STDOUT_FILENO); 4013bbe3f67SBaptiste Daroussin close(pfd[1]); 4023bbe3f67SBaptiste Daroussin } 4033bbe3f67SBaptiste Daroussin close(pfd[0]); 4043bbe3f67SBaptiste Daroussin rewind(stdout); 4053bbe3f67SBaptiste Daroussin free(header); 4063bbe3f67SBaptiste Daroussin kq = kqueue(); 4073bbe3f67SBaptiste Daroussin if (kq == -1) 4083bbe3f67SBaptiste Daroussin err(2, "kqueue"); 4093bbe3f67SBaptiste Daroussin e = xmalloc(sizeof(struct kevent)); 4103bbe3f67SBaptiste Daroussin EV_SET(e, pr_pd, EVFILT_PROCDESC, EV_ADD, NOTE_EXIT, 0, 4113bbe3f67SBaptiste Daroussin NULL); 4123bbe3f67SBaptiste Daroussin if (kevent(kq, e, 1, NULL, 0, NULL) == -1) 4133bbe3f67SBaptiste Daroussin err(2, "kevent"); 4143bbe3f67SBaptiste Daroussin } 4153bbe3f67SBaptiste Daroussin } 4163bbe3f67SBaptiste Daroussin 4173bbe3f67SBaptiste Daroussin if (capsicum) { 4183bbe3f67SBaptiste Daroussin cap_rights_init(&rights_ro, CAP_READ, CAP_FSTAT, CAP_SEEK); 41978f6a0c1SBaptiste Daroussin if (cap_rights_limit(fileno(f1), &rights_ro) < 0 42078f6a0c1SBaptiste Daroussin && errno != ENOSYS) 4213bbe3f67SBaptiste Daroussin err(2, "unable to limit rights on: %s", file1); 42278f6a0c1SBaptiste Daroussin if (cap_rights_limit(fileno(f2), &rights_ro) < 0 && 42378f6a0c1SBaptiste Daroussin errno != ENOSYS) 4243bbe3f67SBaptiste Daroussin err(2, "unable to limit rights on: %s", file2); 4253bbe3f67SBaptiste Daroussin if (fileno(f1) == STDIN_FILENO || fileno(f2) == STDIN_FILENO) { 4263bbe3f67SBaptiste Daroussin /* stding has already been limited */ 4273bbe3f67SBaptiste Daroussin if (caph_limit_stderr() == -1) 4283bbe3f67SBaptiste Daroussin err(2, "unable to limit stderr"); 4293bbe3f67SBaptiste Daroussin if (caph_limit_stdout() == -1) 4303bbe3f67SBaptiste Daroussin err(2, "unable to limit stdout"); 4313bbe3f67SBaptiste Daroussin } else if (caph_limit_stdio() == -1) 4323bbe3f67SBaptiste Daroussin err(2, "unable to limit stdio"); 4333bbe3f67SBaptiste Daroussin 4343bbe3f67SBaptiste Daroussin caph_cache_catpages(); 4355bbffb00SBaptiste Daroussin caph_cache_tzdata(); 4363bbe3f67SBaptiste Daroussin if (cap_enter() < 0 && errno != ENOSYS) 4373bbe3f67SBaptiste Daroussin err(2, "unable to enter capability mode"); 4383bbe3f67SBaptiste Daroussin } 4393bbe3f67SBaptiste Daroussin 4403bbe3f67SBaptiste Daroussin switch (files_differ(f1, f2, flags)) { 4413bbe3f67SBaptiste Daroussin case 0: 4423bbe3f67SBaptiste Daroussin goto closem; 4433bbe3f67SBaptiste Daroussin case 1: 4443bbe3f67SBaptiste Daroussin break; 4453bbe3f67SBaptiste Daroussin default: 4463bbe3f67SBaptiste Daroussin /* error */ 4473bbe3f67SBaptiste Daroussin status |= 2; 4483bbe3f67SBaptiste Daroussin goto closem; 4493bbe3f67SBaptiste Daroussin } 4503bbe3f67SBaptiste Daroussin 4513bbe3f67SBaptiste Daroussin if ((flags & D_FORCEASCII) == 0 && 4523bbe3f67SBaptiste Daroussin (!asciifile(f1) || !asciifile(f2))) { 4533bbe3f67SBaptiste Daroussin rval = D_BINARY; 4543bbe3f67SBaptiste Daroussin status |= 1; 4553bbe3f67SBaptiste Daroussin goto closem; 4563bbe3f67SBaptiste Daroussin } 4573bbe3f67SBaptiste Daroussin prepare(0, f1, stb1.st_size, flags); 4583bbe3f67SBaptiste Daroussin prepare(1, f2, stb2.st_size, flags); 4593bbe3f67SBaptiste Daroussin 4603bbe3f67SBaptiste Daroussin prune(); 4613bbe3f67SBaptiste Daroussin sort(sfile[0], slen[0]); 4623bbe3f67SBaptiste Daroussin sort(sfile[1], slen[1]); 4633bbe3f67SBaptiste Daroussin 4643bbe3f67SBaptiste Daroussin member = (int *)file[1]; 4653bbe3f67SBaptiste Daroussin equiv(sfile[0], slen[0], sfile[1], slen[1], member); 4663bbe3f67SBaptiste Daroussin member = xreallocarray(member, slen[1] + 2, sizeof(*member)); 4673bbe3f67SBaptiste Daroussin 4683bbe3f67SBaptiste Daroussin class = (int *)file[0]; 4693bbe3f67SBaptiste Daroussin unsort(sfile[0], slen[0], class); 4703bbe3f67SBaptiste Daroussin class = xreallocarray(class, slen[0] + 2, sizeof(*class)); 4713bbe3f67SBaptiste Daroussin 4723bbe3f67SBaptiste Daroussin klist = xcalloc(slen[0] + 2, sizeof(*klist)); 4733bbe3f67SBaptiste Daroussin clen = 0; 4743bbe3f67SBaptiste Daroussin clistlen = 100; 4753bbe3f67SBaptiste Daroussin clist = xcalloc(clistlen, sizeof(*clist)); 4763bbe3f67SBaptiste Daroussin i = stone(class, slen[0], member, klist, flags); 4773bbe3f67SBaptiste Daroussin free(member); 4783bbe3f67SBaptiste Daroussin free(class); 4793bbe3f67SBaptiste Daroussin 4803bbe3f67SBaptiste Daroussin J = xreallocarray(J, len[0] + 2, sizeof(*J)); 4813bbe3f67SBaptiste Daroussin unravel(klist[i]); 4823bbe3f67SBaptiste Daroussin free(clist); 4833bbe3f67SBaptiste Daroussin free(klist); 4843bbe3f67SBaptiste Daroussin 4853bbe3f67SBaptiste Daroussin ixold = xreallocarray(ixold, len[0] + 2, sizeof(*ixold)); 4863bbe3f67SBaptiste Daroussin ixnew = xreallocarray(ixnew, len[1] + 2, sizeof(*ixnew)); 4873bbe3f67SBaptiste Daroussin check(f1, f2, flags); 4883bbe3f67SBaptiste Daroussin output(file1, f1, file2, f2, flags); 489d5b187aeSBaptiste Daroussin if (ostdout != -1 && e != NULL) { 4903bbe3f67SBaptiste Daroussin /* close the pipe to pr and restore stdout */ 4913bbe3f67SBaptiste Daroussin int wstatus; 4923bbe3f67SBaptiste Daroussin 4933bbe3f67SBaptiste Daroussin fflush(stdout); 4943bbe3f67SBaptiste Daroussin if (ostdout != STDOUT_FILENO) { 4953bbe3f67SBaptiste Daroussin close(STDOUT_FILENO); 4963bbe3f67SBaptiste Daroussin dup2(ostdout, STDOUT_FILENO); 4973bbe3f67SBaptiste Daroussin close(ostdout); 4983bbe3f67SBaptiste Daroussin } 4993bbe3f67SBaptiste Daroussin if (kevent(kq, NULL, 0, e, 1, NULL) == -1) 5003bbe3f67SBaptiste Daroussin err(2, "kevent"); 5013bbe3f67SBaptiste Daroussin wstatus = e[0].data; 5023bbe3f67SBaptiste Daroussin close(kq); 5033bbe3f67SBaptiste Daroussin if (WIFEXITED(wstatus) && WEXITSTATUS(wstatus) != 0) 5043bbe3f67SBaptiste Daroussin errx(2, "pr exited abnormally"); 5053bbe3f67SBaptiste Daroussin else if (WIFSIGNALED(wstatus)) 5063bbe3f67SBaptiste Daroussin errx(2, "pr killed by signal %d", 5073bbe3f67SBaptiste Daroussin WTERMSIG(wstatus)); 5083bbe3f67SBaptiste Daroussin } 5093bbe3f67SBaptiste Daroussin 5103bbe3f67SBaptiste Daroussin closem: 5113bbe3f67SBaptiste Daroussin if (anychange) { 5123bbe3f67SBaptiste Daroussin status |= 1; 5133bbe3f67SBaptiste Daroussin if (rval == D_SAME) 5143bbe3f67SBaptiste Daroussin rval = D_DIFFER; 5153bbe3f67SBaptiste Daroussin } 5163bbe3f67SBaptiste Daroussin if (f1 != NULL) 5173bbe3f67SBaptiste Daroussin fclose(f1); 5183bbe3f67SBaptiste Daroussin if (f2 != NULL) 5193bbe3f67SBaptiste Daroussin fclose(f2); 5203bbe3f67SBaptiste Daroussin 5213bbe3f67SBaptiste Daroussin return (rval); 5223bbe3f67SBaptiste Daroussin } 5233bbe3f67SBaptiste Daroussin 5243bbe3f67SBaptiste Daroussin /* 5253bbe3f67SBaptiste Daroussin * Check to see if the given files differ. 5263bbe3f67SBaptiste Daroussin * Returns 0 if they are the same, 1 if different, and -1 on error. 5273bbe3f67SBaptiste Daroussin * XXX - could use code from cmp(1) [faster] 5283bbe3f67SBaptiste Daroussin */ 5293bbe3f67SBaptiste Daroussin static int 5303bbe3f67SBaptiste Daroussin files_differ(FILE *f1, FILE *f2, int flags) 5313bbe3f67SBaptiste Daroussin { 5323bbe3f67SBaptiste Daroussin char buf1[BUFSIZ], buf2[BUFSIZ]; 5333bbe3f67SBaptiste Daroussin size_t i, j; 5343bbe3f67SBaptiste Daroussin 5353bbe3f67SBaptiste Daroussin if ((flags & (D_EMPTY1|D_EMPTY2)) || stb1.st_size != stb2.st_size || 5363bbe3f67SBaptiste Daroussin (stb1.st_mode & S_IFMT) != (stb2.st_mode & S_IFMT)) 5373bbe3f67SBaptiste Daroussin return (1); 5383bbe3f67SBaptiste Daroussin for (;;) { 5393bbe3f67SBaptiste Daroussin i = fread(buf1, 1, sizeof(buf1), f1); 5403bbe3f67SBaptiste Daroussin j = fread(buf2, 1, sizeof(buf2), f2); 5413bbe3f67SBaptiste Daroussin if ((!i && ferror(f1)) || (!j && ferror(f2))) 5423bbe3f67SBaptiste Daroussin return (-1); 5433bbe3f67SBaptiste Daroussin if (i != j) 5443bbe3f67SBaptiste Daroussin return (1); 5453bbe3f67SBaptiste Daroussin if (i == 0) 5463bbe3f67SBaptiste Daroussin return (0); 5473bbe3f67SBaptiste Daroussin if (memcmp(buf1, buf2, i) != 0) 5483bbe3f67SBaptiste Daroussin return (1); 5493bbe3f67SBaptiste Daroussin } 5503bbe3f67SBaptiste Daroussin } 5513bbe3f67SBaptiste Daroussin 552ff807815SBaptiste Daroussin static FILE * 553ff807815SBaptiste Daroussin opentemp(const char *f) 554ff807815SBaptiste Daroussin { 555ff807815SBaptiste Daroussin char buf[BUFSIZ], tempfile[PATH_MAX]; 556ff807815SBaptiste Daroussin ssize_t nread; 557ff807815SBaptiste Daroussin int ifd, ofd; 558ff807815SBaptiste Daroussin 559ff807815SBaptiste Daroussin if (strcmp(f, "-") == 0) 560ff807815SBaptiste Daroussin ifd = STDIN_FILENO; 561ff807815SBaptiste Daroussin else if ((ifd = open(f, O_RDONLY, 0644)) < 0) 562ff807815SBaptiste Daroussin return (NULL); 563ff807815SBaptiste Daroussin 564ff807815SBaptiste Daroussin (void)strlcpy(tempfile, _PATH_TMP "/diff.XXXXXXXX", sizeof(tempfile)); 565ff807815SBaptiste Daroussin 566ff807815SBaptiste Daroussin if ((ofd = mkstemp(tempfile)) < 0) { 567ff807815SBaptiste Daroussin close(ifd); 568ff807815SBaptiste Daroussin return (NULL); 569ff807815SBaptiste Daroussin } 570ff807815SBaptiste Daroussin unlink(tempfile); 571ff807815SBaptiste Daroussin while ((nread = read(ifd, buf, BUFSIZ)) > 0) { 572ff807815SBaptiste Daroussin if (write(ofd, buf, nread) != nread) { 573ff807815SBaptiste Daroussin close(ifd); 574ff807815SBaptiste Daroussin close(ofd); 575ff807815SBaptiste Daroussin return (NULL); 576ff807815SBaptiste Daroussin } 577ff807815SBaptiste Daroussin } 578ff807815SBaptiste Daroussin close(ifd); 579ff807815SBaptiste Daroussin lseek(ofd, (off_t)0, SEEK_SET); 580ff807815SBaptiste Daroussin return (fdopen(ofd, "r")); 581ff807815SBaptiste Daroussin } 582ff807815SBaptiste Daroussin 5833bbe3f67SBaptiste Daroussin char * 5843bbe3f67SBaptiste Daroussin splice(char *dir, char *path) 5853bbe3f67SBaptiste Daroussin { 5863bbe3f67SBaptiste Daroussin char *tail, *buf; 5873bbe3f67SBaptiste Daroussin size_t dirlen; 5883bbe3f67SBaptiste Daroussin 5893bbe3f67SBaptiste Daroussin dirlen = strlen(dir); 5903bbe3f67SBaptiste Daroussin while (dirlen != 0 && dir[dirlen - 1] == '/') 5913bbe3f67SBaptiste Daroussin dirlen--; 5923bbe3f67SBaptiste Daroussin if ((tail = strrchr(path, '/')) == NULL) 5933bbe3f67SBaptiste Daroussin tail = path; 5943bbe3f67SBaptiste Daroussin else 5953bbe3f67SBaptiste Daroussin tail++; 5963bbe3f67SBaptiste Daroussin xasprintf(&buf, "%.*s/%s", (int)dirlen, dir, tail); 5973bbe3f67SBaptiste Daroussin return (buf); 5983bbe3f67SBaptiste Daroussin } 5993bbe3f67SBaptiste Daroussin 6003bbe3f67SBaptiste Daroussin static void 601d5b187aeSBaptiste Daroussin prepare(int i, FILE *fd, size_t filesize, int flags) 6023bbe3f67SBaptiste Daroussin { 6033bbe3f67SBaptiste Daroussin struct line *p; 6043bbe3f67SBaptiste Daroussin int h; 6053bbe3f67SBaptiste Daroussin size_t sz, j; 6063bbe3f67SBaptiste Daroussin 6073bbe3f67SBaptiste Daroussin rewind(fd); 6083bbe3f67SBaptiste Daroussin 6096b8059c4SBaptiste Daroussin sz = MIN(filesize, SIZE_MAX) / 25; 6103bbe3f67SBaptiste Daroussin if (sz < 100) 6113bbe3f67SBaptiste Daroussin sz = 100; 6123bbe3f67SBaptiste Daroussin 6133bbe3f67SBaptiste Daroussin p = xcalloc(sz + 3, sizeof(*p)); 6143bbe3f67SBaptiste Daroussin for (j = 0; (h = readhash(fd, flags));) { 6153bbe3f67SBaptiste Daroussin if (j == sz) { 6163bbe3f67SBaptiste Daroussin sz = sz * 3 / 2; 6173bbe3f67SBaptiste Daroussin p = xreallocarray(p, sz + 3, sizeof(*p)); 6183bbe3f67SBaptiste Daroussin } 6193bbe3f67SBaptiste Daroussin p[++j].value = h; 6203bbe3f67SBaptiste Daroussin } 6213bbe3f67SBaptiste Daroussin len[i] = j; 6223bbe3f67SBaptiste Daroussin file[i] = p; 6233bbe3f67SBaptiste Daroussin } 6243bbe3f67SBaptiste Daroussin 6253bbe3f67SBaptiste Daroussin static void 6263bbe3f67SBaptiste Daroussin prune(void) 6273bbe3f67SBaptiste Daroussin { 6283bbe3f67SBaptiste Daroussin int i, j; 6293bbe3f67SBaptiste Daroussin 6303bbe3f67SBaptiste Daroussin for (pref = 0; pref < len[0] && pref < len[1] && 6313bbe3f67SBaptiste Daroussin file[0][pref + 1].value == file[1][pref + 1].value; 6323bbe3f67SBaptiste Daroussin pref++) 6333bbe3f67SBaptiste Daroussin ; 6343bbe3f67SBaptiste Daroussin for (suff = 0; suff < len[0] - pref && suff < len[1] - pref && 6353bbe3f67SBaptiste Daroussin file[0][len[0] - suff].value == file[1][len[1] - suff].value; 6363bbe3f67SBaptiste Daroussin suff++) 6373bbe3f67SBaptiste Daroussin ; 6383bbe3f67SBaptiste Daroussin for (j = 0; j < 2; j++) { 6393bbe3f67SBaptiste Daroussin sfile[j] = file[j] + pref; 6403bbe3f67SBaptiste Daroussin slen[j] = len[j] - pref - suff; 6413bbe3f67SBaptiste Daroussin for (i = 0; i <= slen[j]; i++) 6423bbe3f67SBaptiste Daroussin sfile[j][i].serial = i; 6433bbe3f67SBaptiste Daroussin } 6443bbe3f67SBaptiste Daroussin } 6453bbe3f67SBaptiste Daroussin 6463bbe3f67SBaptiste Daroussin static void 6473bbe3f67SBaptiste Daroussin equiv(struct line *a, int n, struct line *b, int m, int *c) 6483bbe3f67SBaptiste Daroussin { 6493bbe3f67SBaptiste Daroussin int i, j; 6503bbe3f67SBaptiste Daroussin 6513bbe3f67SBaptiste Daroussin i = j = 1; 6523bbe3f67SBaptiste Daroussin while (i <= n && j <= m) { 6533bbe3f67SBaptiste Daroussin if (a[i].value < b[j].value) 6543bbe3f67SBaptiste Daroussin a[i++].value = 0; 6553bbe3f67SBaptiste Daroussin else if (a[i].value == b[j].value) 6563bbe3f67SBaptiste Daroussin a[i++].value = j; 6573bbe3f67SBaptiste Daroussin else 6583bbe3f67SBaptiste Daroussin j++; 6593bbe3f67SBaptiste Daroussin } 6603bbe3f67SBaptiste Daroussin while (i <= n) 6613bbe3f67SBaptiste Daroussin a[i++].value = 0; 6623bbe3f67SBaptiste Daroussin b[m + 1].value = 0; 6633bbe3f67SBaptiste Daroussin j = 0; 6643bbe3f67SBaptiste Daroussin while (++j <= m) { 6653bbe3f67SBaptiste Daroussin c[j] = -b[j].serial; 6663bbe3f67SBaptiste Daroussin while (b[j + 1].value == b[j].value) { 6673bbe3f67SBaptiste Daroussin j++; 6683bbe3f67SBaptiste Daroussin c[j] = b[j].serial; 6693bbe3f67SBaptiste Daroussin } 6703bbe3f67SBaptiste Daroussin } 6713bbe3f67SBaptiste Daroussin c[j] = -1; 6723bbe3f67SBaptiste Daroussin } 6733bbe3f67SBaptiste Daroussin 6743bbe3f67SBaptiste Daroussin /* Code taken from ping.c */ 6753bbe3f67SBaptiste Daroussin static int 6763bbe3f67SBaptiste Daroussin isqrt(int n) 6773bbe3f67SBaptiste Daroussin { 6783bbe3f67SBaptiste Daroussin int y, x = 1; 6793bbe3f67SBaptiste Daroussin 6803bbe3f67SBaptiste Daroussin if (n == 0) 6813bbe3f67SBaptiste Daroussin return (0); 6823bbe3f67SBaptiste Daroussin 6833bbe3f67SBaptiste Daroussin do { /* newton was a stinker */ 6843bbe3f67SBaptiste Daroussin y = x; 6853bbe3f67SBaptiste Daroussin x = n / x; 6863bbe3f67SBaptiste Daroussin x += y; 6873bbe3f67SBaptiste Daroussin x /= 2; 6883bbe3f67SBaptiste Daroussin } while ((x - y) > 1 || (x - y) < -1); 6893bbe3f67SBaptiste Daroussin 6903bbe3f67SBaptiste Daroussin return (x); 6913bbe3f67SBaptiste Daroussin } 6923bbe3f67SBaptiste Daroussin 6933bbe3f67SBaptiste Daroussin static int 6943bbe3f67SBaptiste Daroussin stone(int *a, int n, int *b, int *c, int flags) 6953bbe3f67SBaptiste Daroussin { 6963bbe3f67SBaptiste Daroussin int i, k, y, j, l; 6973bbe3f67SBaptiste Daroussin int oldc, tc, oldl, sq; 6983bbe3f67SBaptiste Daroussin u_int numtries, bound; 6993bbe3f67SBaptiste Daroussin 7003bbe3f67SBaptiste Daroussin if (flags & D_MINIMAL) 7013bbe3f67SBaptiste Daroussin bound = UINT_MAX; 7023bbe3f67SBaptiste Daroussin else { 7033bbe3f67SBaptiste Daroussin sq = isqrt(n); 70442c88c41SBaptiste Daroussin bound = MAX(256, sq); 7053bbe3f67SBaptiste Daroussin } 7063bbe3f67SBaptiste Daroussin 7073bbe3f67SBaptiste Daroussin k = 0; 7083bbe3f67SBaptiste Daroussin c[0] = newcand(0, 0, 0); 7093bbe3f67SBaptiste Daroussin for (i = 1; i <= n; i++) { 7103bbe3f67SBaptiste Daroussin j = a[i]; 7113bbe3f67SBaptiste Daroussin if (j == 0) 7123bbe3f67SBaptiste Daroussin continue; 7133bbe3f67SBaptiste Daroussin y = -b[j]; 7143bbe3f67SBaptiste Daroussin oldl = 0; 7153bbe3f67SBaptiste Daroussin oldc = c[0]; 7163bbe3f67SBaptiste Daroussin numtries = 0; 7173bbe3f67SBaptiste Daroussin do { 7183bbe3f67SBaptiste Daroussin if (y <= clist[oldc].y) 7193bbe3f67SBaptiste Daroussin continue; 7203bbe3f67SBaptiste Daroussin l = search(c, k, y); 7213bbe3f67SBaptiste Daroussin if (l != oldl + 1) 7223bbe3f67SBaptiste Daroussin oldc = c[l - 1]; 7233bbe3f67SBaptiste Daroussin if (l <= k) { 7243bbe3f67SBaptiste Daroussin if (clist[c[l]].y <= y) 7253bbe3f67SBaptiste Daroussin continue; 7263bbe3f67SBaptiste Daroussin tc = c[l]; 7273bbe3f67SBaptiste Daroussin c[l] = newcand(i, y, oldc); 7283bbe3f67SBaptiste Daroussin oldc = tc; 7293bbe3f67SBaptiste Daroussin oldl = l; 7303bbe3f67SBaptiste Daroussin numtries++; 7313bbe3f67SBaptiste Daroussin } else { 7323bbe3f67SBaptiste Daroussin c[l] = newcand(i, y, oldc); 7333bbe3f67SBaptiste Daroussin k++; 7343bbe3f67SBaptiste Daroussin break; 7353bbe3f67SBaptiste Daroussin } 7363bbe3f67SBaptiste Daroussin } while ((y = b[++j]) > 0 && numtries < bound); 7373bbe3f67SBaptiste Daroussin } 7383bbe3f67SBaptiste Daroussin return (k); 7393bbe3f67SBaptiste Daroussin } 7403bbe3f67SBaptiste Daroussin 7413bbe3f67SBaptiste Daroussin static int 7423bbe3f67SBaptiste Daroussin newcand(int x, int y, int pred) 7433bbe3f67SBaptiste Daroussin { 7443bbe3f67SBaptiste Daroussin struct cand *q; 7453bbe3f67SBaptiste Daroussin 7463bbe3f67SBaptiste Daroussin if (clen == clistlen) { 7473bbe3f67SBaptiste Daroussin clistlen = clistlen * 11 / 10; 7483bbe3f67SBaptiste Daroussin clist = xreallocarray(clist, clistlen, sizeof(*clist)); 7493bbe3f67SBaptiste Daroussin } 7503bbe3f67SBaptiste Daroussin q = clist + clen; 7513bbe3f67SBaptiste Daroussin q->x = x; 7523bbe3f67SBaptiste Daroussin q->y = y; 7533bbe3f67SBaptiste Daroussin q->pred = pred; 7543bbe3f67SBaptiste Daroussin return (clen++); 7553bbe3f67SBaptiste Daroussin } 7563bbe3f67SBaptiste Daroussin 7573bbe3f67SBaptiste Daroussin static int 7583bbe3f67SBaptiste Daroussin search(int *c, int k, int y) 7593bbe3f67SBaptiste Daroussin { 7603bbe3f67SBaptiste Daroussin int i, j, l, t; 7613bbe3f67SBaptiste Daroussin 7623bbe3f67SBaptiste Daroussin if (clist[c[k]].y < y) /* quick look for typical case */ 7633bbe3f67SBaptiste Daroussin return (k + 1); 7643bbe3f67SBaptiste Daroussin i = 0; 7653bbe3f67SBaptiste Daroussin j = k + 1; 7663bbe3f67SBaptiste Daroussin for (;;) { 7673bbe3f67SBaptiste Daroussin l = (i + j) / 2; 7683bbe3f67SBaptiste Daroussin if (l <= i) 7693bbe3f67SBaptiste Daroussin break; 7703bbe3f67SBaptiste Daroussin t = clist[c[l]].y; 7713bbe3f67SBaptiste Daroussin if (t > y) 7723bbe3f67SBaptiste Daroussin j = l; 7733bbe3f67SBaptiste Daroussin else if (t < y) 7743bbe3f67SBaptiste Daroussin i = l; 7753bbe3f67SBaptiste Daroussin else 7763bbe3f67SBaptiste Daroussin return (l); 7773bbe3f67SBaptiste Daroussin } 7783bbe3f67SBaptiste Daroussin return (l + 1); 7793bbe3f67SBaptiste Daroussin } 7803bbe3f67SBaptiste Daroussin 7813bbe3f67SBaptiste Daroussin static void 7823bbe3f67SBaptiste Daroussin unravel(int p) 7833bbe3f67SBaptiste Daroussin { 7843bbe3f67SBaptiste Daroussin struct cand *q; 7853bbe3f67SBaptiste Daroussin int i; 7863bbe3f67SBaptiste Daroussin 7873bbe3f67SBaptiste Daroussin for (i = 0; i <= len[0]; i++) 7883bbe3f67SBaptiste Daroussin J[i] = i <= pref ? i : 7893bbe3f67SBaptiste Daroussin i > len[0] - suff ? i + len[1] - len[0] : 0; 7903bbe3f67SBaptiste Daroussin for (q = clist + p; q->y != 0; q = clist + q->pred) 7913bbe3f67SBaptiste Daroussin J[q->x + pref] = q->y + pref; 7923bbe3f67SBaptiste Daroussin } 7933bbe3f67SBaptiste Daroussin 7943bbe3f67SBaptiste Daroussin /* 7953bbe3f67SBaptiste Daroussin * Check does double duty: 7963bbe3f67SBaptiste Daroussin * 1. ferret out any fortuitous correspondences due 7973bbe3f67SBaptiste Daroussin * to confounding by hashing (which result in "jackpot") 7983bbe3f67SBaptiste Daroussin * 2. collect random access indexes to the two files 7993bbe3f67SBaptiste Daroussin */ 8003bbe3f67SBaptiste Daroussin static void 8013bbe3f67SBaptiste Daroussin check(FILE *f1, FILE *f2, int flags) 8023bbe3f67SBaptiste Daroussin { 8033bbe3f67SBaptiste Daroussin int i, j, jackpot, c, d; 8043bbe3f67SBaptiste Daroussin long ctold, ctnew; 8053bbe3f67SBaptiste Daroussin 8063bbe3f67SBaptiste Daroussin rewind(f1); 8073bbe3f67SBaptiste Daroussin rewind(f2); 8083bbe3f67SBaptiste Daroussin j = 1; 8093bbe3f67SBaptiste Daroussin ixold[0] = ixnew[0] = 0; 8103bbe3f67SBaptiste Daroussin jackpot = 0; 8113bbe3f67SBaptiste Daroussin ctold = ctnew = 0; 8123bbe3f67SBaptiste Daroussin for (i = 1; i <= len[0]; i++) { 8133bbe3f67SBaptiste Daroussin if (J[i] == 0) { 8143bbe3f67SBaptiste Daroussin ixold[i] = ctold += skipline(f1); 8153bbe3f67SBaptiste Daroussin continue; 8163bbe3f67SBaptiste Daroussin } 8173bbe3f67SBaptiste Daroussin while (j < J[i]) { 8183bbe3f67SBaptiste Daroussin ixnew[j] = ctnew += skipline(f2); 8193bbe3f67SBaptiste Daroussin j++; 8203bbe3f67SBaptiste Daroussin } 8213bbe3f67SBaptiste Daroussin if (flags & (D_FOLDBLANKS|D_IGNOREBLANKS|D_IGNORECASE|D_STRIPCR)) { 8223bbe3f67SBaptiste Daroussin for (;;) { 8233bbe3f67SBaptiste Daroussin c = getc(f1); 8243bbe3f67SBaptiste Daroussin d = getc(f2); 8253bbe3f67SBaptiste Daroussin /* 8263bbe3f67SBaptiste Daroussin * GNU diff ignores a missing newline 8273bbe3f67SBaptiste Daroussin * in one file for -b or -w. 8283bbe3f67SBaptiste Daroussin */ 8293bbe3f67SBaptiste Daroussin if (flags & (D_FOLDBLANKS|D_IGNOREBLANKS)) { 8303bbe3f67SBaptiste Daroussin if (c == EOF && d == '\n') { 8313bbe3f67SBaptiste Daroussin ctnew++; 8323bbe3f67SBaptiste Daroussin break; 8333bbe3f67SBaptiste Daroussin } else if (c == '\n' && d == EOF) { 8343bbe3f67SBaptiste Daroussin ctold++; 8353bbe3f67SBaptiste Daroussin break; 8363bbe3f67SBaptiste Daroussin } 8373bbe3f67SBaptiste Daroussin } 8383bbe3f67SBaptiste Daroussin ctold++; 8393bbe3f67SBaptiste Daroussin ctnew++; 8403bbe3f67SBaptiste Daroussin if (flags & D_STRIPCR) { 8413bbe3f67SBaptiste Daroussin if (c == '\r') { 8423bbe3f67SBaptiste Daroussin if ((c = getc(f1)) == '\n') { 8433bbe3f67SBaptiste Daroussin ctnew++; 8443bbe3f67SBaptiste Daroussin break; 8453bbe3f67SBaptiste Daroussin } 8463bbe3f67SBaptiste Daroussin } 8473bbe3f67SBaptiste Daroussin if (d == '\r') { 8483bbe3f67SBaptiste Daroussin if ((d = getc(f2)) == '\n') { 8493bbe3f67SBaptiste Daroussin ctold++; 8503bbe3f67SBaptiste Daroussin break; 8513bbe3f67SBaptiste Daroussin } 8523bbe3f67SBaptiste Daroussin } 8533bbe3f67SBaptiste Daroussin } 8543bbe3f67SBaptiste Daroussin if ((flags & D_FOLDBLANKS) && isspace(c) && 8553bbe3f67SBaptiste Daroussin isspace(d)) { 8563bbe3f67SBaptiste Daroussin do { 8573bbe3f67SBaptiste Daroussin if (c == '\n') 8583bbe3f67SBaptiste Daroussin break; 8593bbe3f67SBaptiste Daroussin ctold++; 8603bbe3f67SBaptiste Daroussin } while (isspace(c = getc(f1))); 8613bbe3f67SBaptiste Daroussin do { 8623bbe3f67SBaptiste Daroussin if (d == '\n') 8633bbe3f67SBaptiste Daroussin break; 8643bbe3f67SBaptiste Daroussin ctnew++; 8653bbe3f67SBaptiste Daroussin } while (isspace(d = getc(f2))); 8663bbe3f67SBaptiste Daroussin } else if ((flags & D_IGNOREBLANKS)) { 8673bbe3f67SBaptiste Daroussin while (isspace(c) && c != '\n') { 8683bbe3f67SBaptiste Daroussin c = getc(f1); 8693bbe3f67SBaptiste Daroussin ctold++; 8703bbe3f67SBaptiste Daroussin } 8713bbe3f67SBaptiste Daroussin while (isspace(d) && d != '\n') { 8723bbe3f67SBaptiste Daroussin d = getc(f2); 8733bbe3f67SBaptiste Daroussin ctnew++; 8743bbe3f67SBaptiste Daroussin } 8753bbe3f67SBaptiste Daroussin } 8763bbe3f67SBaptiste Daroussin if (chrtran[c] != chrtran[d]) { 8773bbe3f67SBaptiste Daroussin jackpot++; 8783bbe3f67SBaptiste Daroussin J[i] = 0; 8793bbe3f67SBaptiste Daroussin if (c != '\n' && c != EOF) 8803bbe3f67SBaptiste Daroussin ctold += skipline(f1); 8813bbe3f67SBaptiste Daroussin if (d != '\n' && c != EOF) 8823bbe3f67SBaptiste Daroussin ctnew += skipline(f2); 8833bbe3f67SBaptiste Daroussin break; 8843bbe3f67SBaptiste Daroussin } 8853bbe3f67SBaptiste Daroussin if (c == '\n' || c == EOF) 8863bbe3f67SBaptiste Daroussin break; 8873bbe3f67SBaptiste Daroussin } 8883bbe3f67SBaptiste Daroussin } else { 8893bbe3f67SBaptiste Daroussin for (;;) { 8903bbe3f67SBaptiste Daroussin ctold++; 8913bbe3f67SBaptiste Daroussin ctnew++; 8923bbe3f67SBaptiste Daroussin if ((c = getc(f1)) != (d = getc(f2))) { 8933bbe3f67SBaptiste Daroussin /* jackpot++; */ 8943bbe3f67SBaptiste Daroussin J[i] = 0; 8953bbe3f67SBaptiste Daroussin if (c != '\n' && c != EOF) 8963bbe3f67SBaptiste Daroussin ctold += skipline(f1); 8973bbe3f67SBaptiste Daroussin if (d != '\n' && c != EOF) 8983bbe3f67SBaptiste Daroussin ctnew += skipline(f2); 8993bbe3f67SBaptiste Daroussin break; 9003bbe3f67SBaptiste Daroussin } 9013bbe3f67SBaptiste Daroussin if (c == '\n' || c == EOF) 9023bbe3f67SBaptiste Daroussin break; 9033bbe3f67SBaptiste Daroussin } 9043bbe3f67SBaptiste Daroussin } 9053bbe3f67SBaptiste Daroussin ixold[i] = ctold; 9063bbe3f67SBaptiste Daroussin ixnew[j] = ctnew; 9073bbe3f67SBaptiste Daroussin j++; 9083bbe3f67SBaptiste Daroussin } 9093bbe3f67SBaptiste Daroussin for (; j <= len[1]; j++) { 9103bbe3f67SBaptiste Daroussin ixnew[j] = ctnew += skipline(f2); 9113bbe3f67SBaptiste Daroussin } 9123bbe3f67SBaptiste Daroussin /* 9133bbe3f67SBaptiste Daroussin * if (jackpot) 9143bbe3f67SBaptiste Daroussin * fprintf(stderr, "jackpot\n"); 9153bbe3f67SBaptiste Daroussin */ 9163bbe3f67SBaptiste Daroussin } 9173bbe3f67SBaptiste Daroussin 9183bbe3f67SBaptiste Daroussin /* shellsort CACM #201 */ 9193bbe3f67SBaptiste Daroussin static void 9203bbe3f67SBaptiste Daroussin sort(struct line *a, int n) 9213bbe3f67SBaptiste Daroussin { 9223bbe3f67SBaptiste Daroussin struct line *ai, *aim, w; 9233bbe3f67SBaptiste Daroussin int j, m = 0, k; 9243bbe3f67SBaptiste Daroussin 9253bbe3f67SBaptiste Daroussin if (n == 0) 9263bbe3f67SBaptiste Daroussin return; 9273bbe3f67SBaptiste Daroussin for (j = 1; j <= n; j *= 2) 9283bbe3f67SBaptiste Daroussin m = 2 * j - 1; 9293bbe3f67SBaptiste Daroussin for (m /= 2; m != 0; m /= 2) { 9303bbe3f67SBaptiste Daroussin k = n - m; 9313bbe3f67SBaptiste Daroussin for (j = 1; j <= k; j++) { 9323bbe3f67SBaptiste Daroussin for (ai = &a[j]; ai > a; ai -= m) { 9333bbe3f67SBaptiste Daroussin aim = &ai[m]; 9343bbe3f67SBaptiste Daroussin if (aim < ai) 9353bbe3f67SBaptiste Daroussin break; /* wraparound */ 9363bbe3f67SBaptiste Daroussin if (aim->value > ai[0].value || 9373bbe3f67SBaptiste Daroussin (aim->value == ai[0].value && 9383bbe3f67SBaptiste Daroussin aim->serial > ai[0].serial)) 9393bbe3f67SBaptiste Daroussin break; 9403bbe3f67SBaptiste Daroussin w.value = ai[0].value; 9413bbe3f67SBaptiste Daroussin ai[0].value = aim->value; 9423bbe3f67SBaptiste Daroussin aim->value = w.value; 9433bbe3f67SBaptiste Daroussin w.serial = ai[0].serial; 9443bbe3f67SBaptiste Daroussin ai[0].serial = aim->serial; 9453bbe3f67SBaptiste Daroussin aim->serial = w.serial; 9463bbe3f67SBaptiste Daroussin } 9473bbe3f67SBaptiste Daroussin } 9483bbe3f67SBaptiste Daroussin } 9493bbe3f67SBaptiste Daroussin } 9503bbe3f67SBaptiste Daroussin 9513bbe3f67SBaptiste Daroussin static void 9523bbe3f67SBaptiste Daroussin unsort(struct line *f, int l, int *b) 9533bbe3f67SBaptiste Daroussin { 9543bbe3f67SBaptiste Daroussin int *a, i; 9553bbe3f67SBaptiste Daroussin 9563bbe3f67SBaptiste Daroussin a = xcalloc(l + 1, sizeof(*a)); 9573bbe3f67SBaptiste Daroussin for (i = 1; i <= l; i++) 9583bbe3f67SBaptiste Daroussin a[f[i].serial] = f[i].value; 9593bbe3f67SBaptiste Daroussin for (i = 1; i <= l; i++) 9603bbe3f67SBaptiste Daroussin b[i] = a[i]; 9613bbe3f67SBaptiste Daroussin free(a); 9623bbe3f67SBaptiste Daroussin } 9633bbe3f67SBaptiste Daroussin 9643bbe3f67SBaptiste Daroussin static int 9653bbe3f67SBaptiste Daroussin skipline(FILE *f) 9663bbe3f67SBaptiste Daroussin { 9673bbe3f67SBaptiste Daroussin int i, c; 9683bbe3f67SBaptiste Daroussin 9693bbe3f67SBaptiste Daroussin for (i = 1; (c = getc(f)) != '\n' && c != EOF; i++) 9703bbe3f67SBaptiste Daroussin continue; 9713bbe3f67SBaptiste Daroussin return (i); 9723bbe3f67SBaptiste Daroussin } 9733bbe3f67SBaptiste Daroussin 9743bbe3f67SBaptiste Daroussin static void 9753bbe3f67SBaptiste Daroussin output(char *file1, FILE *f1, char *file2, FILE *f2, int flags) 9763bbe3f67SBaptiste Daroussin { 9773bbe3f67SBaptiste Daroussin int m, i0, i1, j0, j1; 9783bbe3f67SBaptiste Daroussin 9793bbe3f67SBaptiste Daroussin rewind(f1); 9803bbe3f67SBaptiste Daroussin rewind(f2); 9813bbe3f67SBaptiste Daroussin m = len[0]; 9823bbe3f67SBaptiste Daroussin J[0] = 0; 9833bbe3f67SBaptiste Daroussin J[m + 1] = len[1] + 1; 9843bbe3f67SBaptiste Daroussin if (diff_format != D_EDIT) { 9853bbe3f67SBaptiste Daroussin for (i0 = 1; i0 <= m; i0 = i1 + 1) { 9863bbe3f67SBaptiste Daroussin while (i0 <= m && J[i0] == J[i0 - 1] + 1) 9873bbe3f67SBaptiste Daroussin i0++; 9883bbe3f67SBaptiste Daroussin j0 = J[i0 - 1] + 1; 9893bbe3f67SBaptiste Daroussin i1 = i0 - 1; 9903bbe3f67SBaptiste Daroussin while (i1 < m && J[i1 + 1] == 0) 9913bbe3f67SBaptiste Daroussin i1++; 9923bbe3f67SBaptiste Daroussin j1 = J[i1 + 1] - 1; 9933bbe3f67SBaptiste Daroussin J[i1] = j1; 9943bbe3f67SBaptiste Daroussin change(file1, f1, file2, f2, i0, i1, j0, j1, &flags); 9953bbe3f67SBaptiste Daroussin } 9963bbe3f67SBaptiste Daroussin } else { 9973bbe3f67SBaptiste Daroussin for (i0 = m; i0 >= 1; i0 = i1 - 1) { 9983bbe3f67SBaptiste Daroussin while (i0 >= 1 && J[i0] == J[i0 + 1] - 1 && J[i0] != 0) 9993bbe3f67SBaptiste Daroussin i0--; 10003bbe3f67SBaptiste Daroussin j0 = J[i0 + 1] - 1; 10013bbe3f67SBaptiste Daroussin i1 = i0 + 1; 10023bbe3f67SBaptiste Daroussin while (i1 > 1 && J[i1 - 1] == 0) 10033bbe3f67SBaptiste Daroussin i1--; 10043bbe3f67SBaptiste Daroussin j1 = J[i1 - 1] + 1; 10053bbe3f67SBaptiste Daroussin J[i1] = j1; 10063bbe3f67SBaptiste Daroussin change(file1, f1, file2, f2, i1, i0, j1, j0, &flags); 10073bbe3f67SBaptiste Daroussin } 10083bbe3f67SBaptiste Daroussin } 10093bbe3f67SBaptiste Daroussin if (m == 0) 10103bbe3f67SBaptiste Daroussin change(file1, f1, file2, f2, 1, 0, 1, len[1], &flags); 1011fddcb7b8SBaptiste Daroussin if (diff_format == D_IFDEF || diff_format == D_GFORMAT) { 10123bbe3f67SBaptiste Daroussin for (;;) { 10133bbe3f67SBaptiste Daroussin #define c i0 10143bbe3f67SBaptiste Daroussin if ((c = getc(f1)) == EOF) 10153bbe3f67SBaptiste Daroussin return; 10163bbe3f67SBaptiste Daroussin diff_output("%c", c); 10173bbe3f67SBaptiste Daroussin } 10183bbe3f67SBaptiste Daroussin #undef c 10193bbe3f67SBaptiste Daroussin } 10203bbe3f67SBaptiste Daroussin if (anychange != 0) { 10213bbe3f67SBaptiste Daroussin if (diff_format == D_CONTEXT) 10223bbe3f67SBaptiste Daroussin dump_context_vec(f1, f2, flags); 10233bbe3f67SBaptiste Daroussin else if (diff_format == D_UNIFIED) 10243bbe3f67SBaptiste Daroussin dump_unified_vec(f1, f2, flags); 10253bbe3f67SBaptiste Daroussin } 10263bbe3f67SBaptiste Daroussin } 10273bbe3f67SBaptiste Daroussin 10283bbe3f67SBaptiste Daroussin static void 10293bbe3f67SBaptiste Daroussin range(int a, int b, const char *separator) 10303bbe3f67SBaptiste Daroussin { 10313bbe3f67SBaptiste Daroussin diff_output("%d", a > b ? b : a); 10323bbe3f67SBaptiste Daroussin if (a < b) 10333bbe3f67SBaptiste Daroussin diff_output("%s%d", separator, b); 10343bbe3f67SBaptiste Daroussin } 10353bbe3f67SBaptiste Daroussin 10363bbe3f67SBaptiste Daroussin static void 10373bbe3f67SBaptiste Daroussin uni_range(int a, int b) 10383bbe3f67SBaptiste Daroussin { 10393bbe3f67SBaptiste Daroussin if (a < b) 10403bbe3f67SBaptiste Daroussin diff_output("%d,%d", a, b - a + 1); 10413bbe3f67SBaptiste Daroussin else if (a == b) 10423bbe3f67SBaptiste Daroussin diff_output("%d", b); 10433bbe3f67SBaptiste Daroussin else 10443bbe3f67SBaptiste Daroussin diff_output("%d,0", b); 10453bbe3f67SBaptiste Daroussin } 10463bbe3f67SBaptiste Daroussin 10473bbe3f67SBaptiste Daroussin static char * 10483bbe3f67SBaptiste Daroussin preadline(int fd, size_t rlen, off_t off) 10493bbe3f67SBaptiste Daroussin { 10503bbe3f67SBaptiste Daroussin char *line; 10513bbe3f67SBaptiste Daroussin ssize_t nr; 10523bbe3f67SBaptiste Daroussin 10533bbe3f67SBaptiste Daroussin line = xmalloc(rlen + 1); 10543bbe3f67SBaptiste Daroussin if ((nr = pread(fd, line, rlen, off)) < 0) 10553bbe3f67SBaptiste Daroussin err(2, "preadline"); 10563bbe3f67SBaptiste Daroussin if (nr > 0 && line[nr-1] == '\n') 10573bbe3f67SBaptiste Daroussin nr--; 10583bbe3f67SBaptiste Daroussin line[nr] = '\0'; 10593bbe3f67SBaptiste Daroussin return (line); 10603bbe3f67SBaptiste Daroussin } 10613bbe3f67SBaptiste Daroussin 10623bbe3f67SBaptiste Daroussin static int 10633bbe3f67SBaptiste Daroussin ignoreline(char *line) 10643bbe3f67SBaptiste Daroussin { 10653bbe3f67SBaptiste Daroussin int ret; 10663bbe3f67SBaptiste Daroussin 10673bbe3f67SBaptiste Daroussin ret = regexec(&ignore_re, line, 0, NULL, 0); 10683bbe3f67SBaptiste Daroussin free(line); 10693bbe3f67SBaptiste Daroussin return (ret == 0); /* if it matched, it should be ignored. */ 10703bbe3f67SBaptiste Daroussin } 10713bbe3f67SBaptiste Daroussin 10723bbe3f67SBaptiste Daroussin /* 10733bbe3f67SBaptiste Daroussin * Indicate that there is a difference between lines a and b of the from file 10743bbe3f67SBaptiste Daroussin * to get to lines c to d of the to file. If a is greater then b then there 10753bbe3f67SBaptiste Daroussin * are no lines in the from file involved and this means that there were 10763bbe3f67SBaptiste Daroussin * lines appended (beginning at b). If c is greater than d then there are 10773bbe3f67SBaptiste Daroussin * lines missing from the to file. 10783bbe3f67SBaptiste Daroussin */ 10793bbe3f67SBaptiste Daroussin static void 10803bbe3f67SBaptiste Daroussin change(char *file1, FILE *f1, char *file2, FILE *f2, int a, int b, int c, int d, 10813bbe3f67SBaptiste Daroussin int *pflags) 10823bbe3f67SBaptiste Daroussin { 10833bbe3f67SBaptiste Daroussin static size_t max_context = 64; 1084fddcb7b8SBaptiste Daroussin long curpos; 10857ef35d05SDimitry Andric int i, nc, f; 1086fddcb7b8SBaptiste Daroussin const char *walk; 10873bbe3f67SBaptiste Daroussin 10883bbe3f67SBaptiste Daroussin restart: 1089fddcb7b8SBaptiste Daroussin if ((diff_format != D_IFDEF || diff_format == D_GFORMAT) && 1090fddcb7b8SBaptiste Daroussin a > b && c > d) 10913bbe3f67SBaptiste Daroussin return; 10923bbe3f67SBaptiste Daroussin if (ignore_pats != NULL) { 10933bbe3f67SBaptiste Daroussin char *line; 10943bbe3f67SBaptiste Daroussin /* 10953bbe3f67SBaptiste Daroussin * All lines in the change, insert, or delete must 10963bbe3f67SBaptiste Daroussin * match an ignore pattern for the change to be 10973bbe3f67SBaptiste Daroussin * ignored. 10983bbe3f67SBaptiste Daroussin */ 10993bbe3f67SBaptiste Daroussin if (a <= b) { /* Changes and deletes. */ 11003bbe3f67SBaptiste Daroussin for (i = a; i <= b; i++) { 11013bbe3f67SBaptiste Daroussin line = preadline(fileno(f1), 11023bbe3f67SBaptiste Daroussin ixold[i] - ixold[i - 1], ixold[i - 1]); 11033bbe3f67SBaptiste Daroussin if (!ignoreline(line)) 11043bbe3f67SBaptiste Daroussin goto proceed; 11053bbe3f67SBaptiste Daroussin } 11063bbe3f67SBaptiste Daroussin } 11073bbe3f67SBaptiste Daroussin if (a > b || c <= d) { /* Changes and inserts. */ 11083bbe3f67SBaptiste Daroussin for (i = c; i <= d; i++) { 11093bbe3f67SBaptiste Daroussin line = preadline(fileno(f2), 11103bbe3f67SBaptiste Daroussin ixnew[i] - ixnew[i - 1], ixnew[i - 1]); 11113bbe3f67SBaptiste Daroussin if (!ignoreline(line)) 11123bbe3f67SBaptiste Daroussin goto proceed; 11133bbe3f67SBaptiste Daroussin } 11143bbe3f67SBaptiste Daroussin } 11153bbe3f67SBaptiste Daroussin return; 11163bbe3f67SBaptiste Daroussin } 11173bbe3f67SBaptiste Daroussin proceed: 1118*4d8c5790SEnji Cooper if (*pflags & D_HEADER && diff_format != D_BRIEF) { 11193bbe3f67SBaptiste Daroussin diff_output("%s %s %s\n", diffargs, file1, file2); 11203bbe3f67SBaptiste Daroussin *pflags &= ~D_HEADER; 11213bbe3f67SBaptiste Daroussin } 11223bbe3f67SBaptiste Daroussin if (diff_format == D_CONTEXT || diff_format == D_UNIFIED) { 11233bbe3f67SBaptiste Daroussin /* 11243bbe3f67SBaptiste Daroussin * Allocate change records as needed. 11253bbe3f67SBaptiste Daroussin */ 11263bbe3f67SBaptiste Daroussin if (context_vec_ptr == context_vec_end - 1) { 11273bbe3f67SBaptiste Daroussin ptrdiff_t offset = context_vec_ptr - context_vec_start; 11283bbe3f67SBaptiste Daroussin max_context <<= 1; 11293bbe3f67SBaptiste Daroussin context_vec_start = xreallocarray(context_vec_start, 11303bbe3f67SBaptiste Daroussin max_context, sizeof(*context_vec_start)); 11313bbe3f67SBaptiste Daroussin context_vec_end = context_vec_start + max_context; 11323bbe3f67SBaptiste Daroussin context_vec_ptr = context_vec_start + offset; 11333bbe3f67SBaptiste Daroussin } 11343bbe3f67SBaptiste Daroussin if (anychange == 0) { 11353bbe3f67SBaptiste Daroussin /* 11363bbe3f67SBaptiste Daroussin * Print the context/unidiff header first time through. 11373bbe3f67SBaptiste Daroussin */ 11383bbe3f67SBaptiste Daroussin print_header(file1, file2); 11393bbe3f67SBaptiste Daroussin anychange = 1; 11403bbe3f67SBaptiste Daroussin } else if (a > context_vec_ptr->b + (2 * diff_context) + 1 && 11413bbe3f67SBaptiste Daroussin c > context_vec_ptr->d + (2 * diff_context) + 1) { 11423bbe3f67SBaptiste Daroussin /* 11433bbe3f67SBaptiste Daroussin * If this change is more than 'diff_context' lines from the 11443bbe3f67SBaptiste Daroussin * previous change, dump the record and reset it. 11453bbe3f67SBaptiste Daroussin */ 11463bbe3f67SBaptiste Daroussin if (diff_format == D_CONTEXT) 11473bbe3f67SBaptiste Daroussin dump_context_vec(f1, f2, *pflags); 11483bbe3f67SBaptiste Daroussin else 11493bbe3f67SBaptiste Daroussin dump_unified_vec(f1, f2, *pflags); 11503bbe3f67SBaptiste Daroussin } 11513bbe3f67SBaptiste Daroussin context_vec_ptr++; 11523bbe3f67SBaptiste Daroussin context_vec_ptr->a = a; 11533bbe3f67SBaptiste Daroussin context_vec_ptr->b = b; 11543bbe3f67SBaptiste Daroussin context_vec_ptr->c = c; 11553bbe3f67SBaptiste Daroussin context_vec_ptr->d = d; 11563bbe3f67SBaptiste Daroussin return; 11573bbe3f67SBaptiste Daroussin } 11583bbe3f67SBaptiste Daroussin if (anychange == 0) 11593bbe3f67SBaptiste Daroussin anychange = 1; 11603bbe3f67SBaptiste Daroussin switch (diff_format) { 11613bbe3f67SBaptiste Daroussin case D_BRIEF: 11623bbe3f67SBaptiste Daroussin return; 11633bbe3f67SBaptiste Daroussin case D_NORMAL: 11643bbe3f67SBaptiste Daroussin case D_EDIT: 11653bbe3f67SBaptiste Daroussin range(a, b, ","); 11663bbe3f67SBaptiste Daroussin diff_output("%c", a > b ? 'a' : c > d ? 'd' : 'c'); 11673bbe3f67SBaptiste Daroussin if (diff_format == D_NORMAL) 11683bbe3f67SBaptiste Daroussin range(c, d, ","); 11693bbe3f67SBaptiste Daroussin diff_output("\n"); 11703bbe3f67SBaptiste Daroussin break; 11713bbe3f67SBaptiste Daroussin case D_REVERSE: 11723bbe3f67SBaptiste Daroussin diff_output("%c", a > b ? 'a' : c > d ? 'd' : 'c'); 11733bbe3f67SBaptiste Daroussin range(a, b, " "); 11743bbe3f67SBaptiste Daroussin diff_output("\n"); 11753bbe3f67SBaptiste Daroussin break; 11763bbe3f67SBaptiste Daroussin case D_NREVERSE: 11773bbe3f67SBaptiste Daroussin if (a > b) 11783bbe3f67SBaptiste Daroussin diff_output("a%d %d\n", b, d - c + 1); 11793bbe3f67SBaptiste Daroussin else { 11803bbe3f67SBaptiste Daroussin diff_output("d%d %d\n", a, b - a + 1); 11813bbe3f67SBaptiste Daroussin if (!(c > d)) 11823bbe3f67SBaptiste Daroussin /* add changed lines */ 11833bbe3f67SBaptiste Daroussin diff_output("a%d %d\n", b, d - c + 1); 11843bbe3f67SBaptiste Daroussin } 11853bbe3f67SBaptiste Daroussin break; 11863bbe3f67SBaptiste Daroussin } 1187fddcb7b8SBaptiste Daroussin if (diff_format == D_GFORMAT) { 1188fddcb7b8SBaptiste Daroussin curpos = ftell(f1); 1189fddcb7b8SBaptiste Daroussin /* print through if append (a>b), else to (nb: 0 vs 1 orig) */ 1190fddcb7b8SBaptiste Daroussin nc = ixold[a > b ? b : a - 1] - curpos; 1191fddcb7b8SBaptiste Daroussin for (i = 0; i < nc; i++) 1192fddcb7b8SBaptiste Daroussin diff_output("%c", getc(f1)); 1193fddcb7b8SBaptiste Daroussin for (walk = group_format; *walk != '\0'; walk++) { 1194fddcb7b8SBaptiste Daroussin if (*walk == '%') { 1195fddcb7b8SBaptiste Daroussin walk++; 1196fddcb7b8SBaptiste Daroussin switch (*walk) { 1197fddcb7b8SBaptiste Daroussin case '<': 1198fddcb7b8SBaptiste Daroussin fetch(ixold, a, b, f1, '<', 1, *pflags); 1199fddcb7b8SBaptiste Daroussin break; 1200fddcb7b8SBaptiste Daroussin case '>': 1201fddcb7b8SBaptiste Daroussin fetch(ixnew, c, d, f2, '>', 0, *pflags); 1202fddcb7b8SBaptiste Daroussin break; 1203fddcb7b8SBaptiste Daroussin default: 1204fddcb7b8SBaptiste Daroussin diff_output("%%%c", *walk); 1205fddcb7b8SBaptiste Daroussin break; 1206fddcb7b8SBaptiste Daroussin } 1207fddcb7b8SBaptiste Daroussin continue; 1208fddcb7b8SBaptiste Daroussin } 1209fddcb7b8SBaptiste Daroussin diff_output("%c", *walk); 1210fddcb7b8SBaptiste Daroussin } 1211fddcb7b8SBaptiste Daroussin } 12123bbe3f67SBaptiste Daroussin if (diff_format == D_NORMAL || diff_format == D_IFDEF) { 12133bbe3f67SBaptiste Daroussin fetch(ixold, a, b, f1, '<', 1, *pflags); 12143bbe3f67SBaptiste Daroussin if (a <= b && c <= d && diff_format == D_NORMAL) 12153bbe3f67SBaptiste Daroussin diff_output("---\n"); 12163bbe3f67SBaptiste Daroussin } 12177ef35d05SDimitry Andric f = 0; 1218fddcb7b8SBaptiste Daroussin if (diff_format != D_GFORMAT) 12197ef35d05SDimitry Andric f = fetch(ixnew, c, d, f2, diff_format == D_NORMAL ? '>' : '\0', 0, *pflags); 12207ef35d05SDimitry Andric if (f != 0 && diff_format == D_EDIT) { 12213bbe3f67SBaptiste Daroussin /* 12223bbe3f67SBaptiste Daroussin * A non-zero return value for D_EDIT indicates that the 12233bbe3f67SBaptiste Daroussin * last line printed was a bare dot (".") that has been 12243bbe3f67SBaptiste Daroussin * escaped as ".." to prevent ed(1) from misinterpreting 12253bbe3f67SBaptiste Daroussin * it. We have to add a substitute command to change this 12263bbe3f67SBaptiste Daroussin * back and restart where we left off. 12273bbe3f67SBaptiste Daroussin */ 12283bbe3f67SBaptiste Daroussin diff_output(".\n"); 12297ef35d05SDimitry Andric diff_output("%ds/.//\n", a + f - 1); 12307ef35d05SDimitry Andric b = a + f - 1; 12313bbe3f67SBaptiste Daroussin a = b + 1; 12327ef35d05SDimitry Andric c += f; 12333bbe3f67SBaptiste Daroussin goto restart; 12343bbe3f67SBaptiste Daroussin } 12353bbe3f67SBaptiste Daroussin if ((diff_format == D_EDIT || diff_format == D_REVERSE) && c <= d) 12363bbe3f67SBaptiste Daroussin diff_output(".\n"); 12373bbe3f67SBaptiste Daroussin if (inifdef) { 12383bbe3f67SBaptiste Daroussin diff_output("#endif /* %s */\n", ifdefname); 12393bbe3f67SBaptiste Daroussin inifdef = 0; 12403bbe3f67SBaptiste Daroussin } 12413bbe3f67SBaptiste Daroussin } 12423bbe3f67SBaptiste Daroussin 12433bbe3f67SBaptiste Daroussin static int 12443bbe3f67SBaptiste Daroussin fetch(long *f, int a, int b, FILE *lb, int ch, int oldfile, int flags) 12453bbe3f67SBaptiste Daroussin { 12463bbe3f67SBaptiste Daroussin int i, j, c, lastc, col, nc; 12473bbe3f67SBaptiste Daroussin int newcol; 12483bbe3f67SBaptiste Daroussin 12493bbe3f67SBaptiste Daroussin /* 12503bbe3f67SBaptiste Daroussin * When doing #ifdef's, copy down to current line 12513bbe3f67SBaptiste Daroussin * if this is the first file, so that stuff makes it to output. 12523bbe3f67SBaptiste Daroussin */ 1253fddcb7b8SBaptiste Daroussin if ((diff_format == D_IFDEF) && oldfile) { 12543bbe3f67SBaptiste Daroussin long curpos = ftell(lb); 12553bbe3f67SBaptiste Daroussin /* print through if append (a>b), else to (nb: 0 vs 1 orig) */ 12563bbe3f67SBaptiste Daroussin nc = f[a > b ? b : a - 1] - curpos; 12573bbe3f67SBaptiste Daroussin for (i = 0; i < nc; i++) 12583bbe3f67SBaptiste Daroussin diff_output("%c", getc(lb)); 12593bbe3f67SBaptiste Daroussin } 12603bbe3f67SBaptiste Daroussin if (a > b) 12613bbe3f67SBaptiste Daroussin return (0); 12623bbe3f67SBaptiste Daroussin if (diff_format == D_IFDEF) { 12633bbe3f67SBaptiste Daroussin if (inifdef) { 12643bbe3f67SBaptiste Daroussin diff_output("#else /* %s%s */\n", 12653bbe3f67SBaptiste Daroussin oldfile == 1 ? "!" : "", ifdefname); 12663bbe3f67SBaptiste Daroussin } else { 12673bbe3f67SBaptiste Daroussin if (oldfile) 12683bbe3f67SBaptiste Daroussin diff_output("#ifndef %s\n", ifdefname); 12693bbe3f67SBaptiste Daroussin else 12703bbe3f67SBaptiste Daroussin diff_output("#ifdef %s\n", ifdefname); 12713bbe3f67SBaptiste Daroussin } 12723bbe3f67SBaptiste Daroussin inifdef = 1 + oldfile; 12733bbe3f67SBaptiste Daroussin } 12743bbe3f67SBaptiste Daroussin for (i = a; i <= b; i++) { 12753bbe3f67SBaptiste Daroussin fseek(lb, f[i - 1], SEEK_SET); 12763bbe3f67SBaptiste Daroussin nc = f[i] - f[i - 1]; 1277fddcb7b8SBaptiste Daroussin if ((diff_format != D_IFDEF && diff_format != D_GFORMAT) && 1278fddcb7b8SBaptiste Daroussin ch != '\0') { 12793bbe3f67SBaptiste Daroussin diff_output("%c", ch); 12803bbe3f67SBaptiste Daroussin if (Tflag && (diff_format == D_NORMAL || diff_format == D_CONTEXT 12813bbe3f67SBaptiste Daroussin || diff_format == D_UNIFIED)) 12823bbe3f67SBaptiste Daroussin diff_output("\t"); 12833bbe3f67SBaptiste Daroussin else if (diff_format != D_UNIFIED) 12843bbe3f67SBaptiste Daroussin diff_output(" "); 12853bbe3f67SBaptiste Daroussin } 12863bbe3f67SBaptiste Daroussin col = 0; 12873bbe3f67SBaptiste Daroussin for (j = 0, lastc = '\0'; j < nc; j++, lastc = c) { 12883bbe3f67SBaptiste Daroussin if ((c = getc(lb)) == EOF) { 12893bbe3f67SBaptiste Daroussin if (diff_format == D_EDIT || diff_format == D_REVERSE || 12903bbe3f67SBaptiste Daroussin diff_format == D_NREVERSE) 12913bbe3f67SBaptiste Daroussin warnx("No newline at end of file"); 12923bbe3f67SBaptiste Daroussin else 12933bbe3f67SBaptiste Daroussin diff_output("\n\\ No newline at end of " 12943bbe3f67SBaptiste Daroussin "file\n"); 12953bbe3f67SBaptiste Daroussin return (0); 12963bbe3f67SBaptiste Daroussin } 12973bbe3f67SBaptiste Daroussin if (c == '\t' && (flags & D_EXPANDTABS)) { 12983bbe3f67SBaptiste Daroussin newcol = ((col/tabsize)+1)*tabsize; 12993bbe3f67SBaptiste Daroussin do { 13003bbe3f67SBaptiste Daroussin diff_output(" "); 13013bbe3f67SBaptiste Daroussin } while (++col < newcol); 13023bbe3f67SBaptiste Daroussin } else { 13033bbe3f67SBaptiste Daroussin if (diff_format == D_EDIT && j == 1 && c == '\n' 13043bbe3f67SBaptiste Daroussin && lastc == '.') { 13053bbe3f67SBaptiste Daroussin /* 13063bbe3f67SBaptiste Daroussin * Don't print a bare "." line 13073bbe3f67SBaptiste Daroussin * since that will confuse ed(1). 13083bbe3f67SBaptiste Daroussin * Print ".." instead and return, 13093bbe3f67SBaptiste Daroussin * giving the caller an offset 13103bbe3f67SBaptiste Daroussin * from which to restart. 13113bbe3f67SBaptiste Daroussin */ 13123bbe3f67SBaptiste Daroussin diff_output(".\n"); 13133bbe3f67SBaptiste Daroussin return (i - a + 1); 13143bbe3f67SBaptiste Daroussin } 13153bbe3f67SBaptiste Daroussin diff_output("%c", c); 13163bbe3f67SBaptiste Daroussin col++; 13173bbe3f67SBaptiste Daroussin } 13183bbe3f67SBaptiste Daroussin } 13193bbe3f67SBaptiste Daroussin } 13203bbe3f67SBaptiste Daroussin return (0); 13213bbe3f67SBaptiste Daroussin } 13223bbe3f67SBaptiste Daroussin 13233bbe3f67SBaptiste Daroussin /* 13243bbe3f67SBaptiste Daroussin * Hash function taken from Robert Sedgewick, Algorithms in C, 3d ed., p 578. 13253bbe3f67SBaptiste Daroussin */ 13263bbe3f67SBaptiste Daroussin static int 13273bbe3f67SBaptiste Daroussin readhash(FILE *f, int flags) 13283bbe3f67SBaptiste Daroussin { 13293bbe3f67SBaptiste Daroussin int i, t, space; 13303bbe3f67SBaptiste Daroussin int sum; 13313bbe3f67SBaptiste Daroussin 13323bbe3f67SBaptiste Daroussin sum = 1; 13333bbe3f67SBaptiste Daroussin space = 0; 13343bbe3f67SBaptiste Daroussin if ((flags & (D_FOLDBLANKS|D_IGNOREBLANKS)) == 0) { 13353bbe3f67SBaptiste Daroussin if (flags & D_IGNORECASE) 13363bbe3f67SBaptiste Daroussin for (i = 0; (t = getc(f)) != '\n'; i++) { 13373bbe3f67SBaptiste Daroussin if (flags & D_STRIPCR && t == '\r') { 13383bbe3f67SBaptiste Daroussin t = getc(f); 13393bbe3f67SBaptiste Daroussin if (t == '\n') 13403bbe3f67SBaptiste Daroussin break; 13413bbe3f67SBaptiste Daroussin ungetc(t, f); 13423bbe3f67SBaptiste Daroussin } 13433bbe3f67SBaptiste Daroussin if (t == EOF) { 13443bbe3f67SBaptiste Daroussin if (i == 0) 13453bbe3f67SBaptiste Daroussin return (0); 13463bbe3f67SBaptiste Daroussin break; 13473bbe3f67SBaptiste Daroussin } 13483bbe3f67SBaptiste Daroussin sum = sum * 127 + chrtran[t]; 13493bbe3f67SBaptiste Daroussin } 13503bbe3f67SBaptiste Daroussin else 13513bbe3f67SBaptiste Daroussin for (i = 0; (t = getc(f)) != '\n'; i++) { 13523bbe3f67SBaptiste Daroussin if (flags & D_STRIPCR && t == '\r') { 13533bbe3f67SBaptiste Daroussin t = getc(f); 13543bbe3f67SBaptiste Daroussin if (t == '\n') 13553bbe3f67SBaptiste Daroussin break; 13563bbe3f67SBaptiste Daroussin ungetc(t, f); 13573bbe3f67SBaptiste Daroussin } 13583bbe3f67SBaptiste Daroussin if (t == EOF) { 13593bbe3f67SBaptiste Daroussin if (i == 0) 13603bbe3f67SBaptiste Daroussin return (0); 13613bbe3f67SBaptiste Daroussin break; 13623bbe3f67SBaptiste Daroussin } 13633bbe3f67SBaptiste Daroussin sum = sum * 127 + t; 13643bbe3f67SBaptiste Daroussin } 13653bbe3f67SBaptiste Daroussin } else { 13663bbe3f67SBaptiste Daroussin for (i = 0;;) { 13673bbe3f67SBaptiste Daroussin switch (t = getc(f)) { 13683bbe3f67SBaptiste Daroussin case '\r': 13693bbe3f67SBaptiste Daroussin case '\t': 13703bbe3f67SBaptiste Daroussin case '\v': 13713bbe3f67SBaptiste Daroussin case '\f': 13723bbe3f67SBaptiste Daroussin case ' ': 13733bbe3f67SBaptiste Daroussin space++; 13743bbe3f67SBaptiste Daroussin continue; 13753bbe3f67SBaptiste Daroussin default: 13763bbe3f67SBaptiste Daroussin if (space && (flags & D_IGNOREBLANKS) == 0) { 13773bbe3f67SBaptiste Daroussin i++; 13783bbe3f67SBaptiste Daroussin space = 0; 13793bbe3f67SBaptiste Daroussin } 13803bbe3f67SBaptiste Daroussin sum = sum * 127 + chrtran[t]; 13813bbe3f67SBaptiste Daroussin i++; 13823bbe3f67SBaptiste Daroussin continue; 13833bbe3f67SBaptiste Daroussin case EOF: 13843bbe3f67SBaptiste Daroussin if (i == 0) 13853bbe3f67SBaptiste Daroussin return (0); 13863bbe3f67SBaptiste Daroussin /* FALLTHROUGH */ 13873bbe3f67SBaptiste Daroussin case '\n': 13883bbe3f67SBaptiste Daroussin break; 13893bbe3f67SBaptiste Daroussin } 13903bbe3f67SBaptiste Daroussin break; 13913bbe3f67SBaptiste Daroussin } 13923bbe3f67SBaptiste Daroussin } 13933bbe3f67SBaptiste Daroussin /* 13943bbe3f67SBaptiste Daroussin * There is a remote possibility that we end up with a zero sum. 13953bbe3f67SBaptiste Daroussin * Zero is used as an EOF marker, so return 1 instead. 13963bbe3f67SBaptiste Daroussin */ 13973bbe3f67SBaptiste Daroussin return (sum == 0 ? 1 : sum); 13983bbe3f67SBaptiste Daroussin } 13993bbe3f67SBaptiste Daroussin 14003bbe3f67SBaptiste Daroussin static int 14013bbe3f67SBaptiste Daroussin asciifile(FILE *f) 14023bbe3f67SBaptiste Daroussin { 14033bbe3f67SBaptiste Daroussin unsigned char buf[BUFSIZ]; 14043bbe3f67SBaptiste Daroussin size_t cnt; 14053bbe3f67SBaptiste Daroussin 14063bbe3f67SBaptiste Daroussin if (f == NULL) 14073bbe3f67SBaptiste Daroussin return (1); 14083bbe3f67SBaptiste Daroussin 14093bbe3f67SBaptiste Daroussin rewind(f); 14103bbe3f67SBaptiste Daroussin cnt = fread(buf, 1, sizeof(buf), f); 14113bbe3f67SBaptiste Daroussin return (memchr(buf, '\0', cnt) == NULL); 14123bbe3f67SBaptiste Daroussin } 14133bbe3f67SBaptiste Daroussin 14143bbe3f67SBaptiste Daroussin #define begins_with(s, pre) (strncmp(s, pre, sizeof(pre)-1) == 0) 14153bbe3f67SBaptiste Daroussin 14163bbe3f67SBaptiste Daroussin static char * 14173bbe3f67SBaptiste Daroussin match_function(const long *f, int pos, FILE *fp) 14183bbe3f67SBaptiste Daroussin { 14193bbe3f67SBaptiste Daroussin unsigned char buf[FUNCTION_CONTEXT_SIZE]; 14203bbe3f67SBaptiste Daroussin size_t nc; 14213bbe3f67SBaptiste Daroussin int last = lastline; 14223bbe3f67SBaptiste Daroussin const char *state = NULL; 14233bbe3f67SBaptiste Daroussin 14243bbe3f67SBaptiste Daroussin lastline = pos; 14253bbe3f67SBaptiste Daroussin while (pos > last) { 14263bbe3f67SBaptiste Daroussin fseek(fp, f[pos - 1], SEEK_SET); 14273bbe3f67SBaptiste Daroussin nc = f[pos] - f[pos - 1]; 14283bbe3f67SBaptiste Daroussin if (nc >= sizeof(buf)) 14293bbe3f67SBaptiste Daroussin nc = sizeof(buf) - 1; 14303bbe3f67SBaptiste Daroussin nc = fread(buf, 1, nc, fp); 14313bbe3f67SBaptiste Daroussin if (nc > 0) { 14323bbe3f67SBaptiste Daroussin buf[nc] = '\0'; 14333bbe3f67SBaptiste Daroussin buf[strcspn(buf, "\n")] = '\0'; 14343bbe3f67SBaptiste Daroussin if (isalpha(buf[0]) || buf[0] == '_' || buf[0] == '$') { 14353bbe3f67SBaptiste Daroussin if (begins_with(buf, "private:")) { 14363bbe3f67SBaptiste Daroussin if (!state) 14373bbe3f67SBaptiste Daroussin state = " (private)"; 14383bbe3f67SBaptiste Daroussin } else if (begins_with(buf, "protected:")) { 14393bbe3f67SBaptiste Daroussin if (!state) 14403bbe3f67SBaptiste Daroussin state = " (protected)"; 14413bbe3f67SBaptiste Daroussin } else if (begins_with(buf, "public:")) { 14423bbe3f67SBaptiste Daroussin if (!state) 14433bbe3f67SBaptiste Daroussin state = " (public)"; 14443bbe3f67SBaptiste Daroussin } else { 14453bbe3f67SBaptiste Daroussin strlcpy(lastbuf, buf, sizeof lastbuf); 14463bbe3f67SBaptiste Daroussin if (state) 14473bbe3f67SBaptiste Daroussin strlcat(lastbuf, state, 14483bbe3f67SBaptiste Daroussin sizeof lastbuf); 14493bbe3f67SBaptiste Daroussin lastmatchline = pos; 14503bbe3f67SBaptiste Daroussin return lastbuf; 14513bbe3f67SBaptiste Daroussin } 14523bbe3f67SBaptiste Daroussin } 14533bbe3f67SBaptiste Daroussin } 14543bbe3f67SBaptiste Daroussin pos--; 14553bbe3f67SBaptiste Daroussin } 14563bbe3f67SBaptiste Daroussin return lastmatchline > 0 ? lastbuf : NULL; 14573bbe3f67SBaptiste Daroussin } 14583bbe3f67SBaptiste Daroussin 14593bbe3f67SBaptiste Daroussin /* dump accumulated "context" diff changes */ 14603bbe3f67SBaptiste Daroussin static void 14613bbe3f67SBaptiste Daroussin dump_context_vec(FILE *f1, FILE *f2, int flags) 14623bbe3f67SBaptiste Daroussin { 14633bbe3f67SBaptiste Daroussin struct context_vec *cvp = context_vec_start; 14643bbe3f67SBaptiste Daroussin int lowa, upb, lowc, upd, do_output; 14653bbe3f67SBaptiste Daroussin int a, b, c, d; 14663bbe3f67SBaptiste Daroussin char ch, *f; 14673bbe3f67SBaptiste Daroussin 14683bbe3f67SBaptiste Daroussin if (context_vec_start > context_vec_ptr) 14693bbe3f67SBaptiste Daroussin return; 14703bbe3f67SBaptiste Daroussin 14713bbe3f67SBaptiste Daroussin b = d = 0; /* gcc */ 147242c88c41SBaptiste Daroussin lowa = MAX(1, cvp->a - diff_context); 147342c88c41SBaptiste Daroussin upb = MIN(len[0], context_vec_ptr->b + diff_context); 147442c88c41SBaptiste Daroussin lowc = MAX(1, cvp->c - diff_context); 147542c88c41SBaptiste Daroussin upd = MIN(len[1], context_vec_ptr->d + diff_context); 14763bbe3f67SBaptiste Daroussin 14773bbe3f67SBaptiste Daroussin diff_output("***************"); 14783bbe3f67SBaptiste Daroussin if ((flags & D_PROTOTYPE)) { 14793bbe3f67SBaptiste Daroussin f = match_function(ixold, lowa-1, f1); 14803bbe3f67SBaptiste Daroussin if (f != NULL) 14813bbe3f67SBaptiste Daroussin diff_output(" %s", f); 14823bbe3f67SBaptiste Daroussin } 14833bbe3f67SBaptiste Daroussin diff_output("\n*** "); 14843bbe3f67SBaptiste Daroussin range(lowa, upb, ","); 14853bbe3f67SBaptiste Daroussin diff_output(" ****\n"); 14863bbe3f67SBaptiste Daroussin 14873bbe3f67SBaptiste Daroussin /* 14883bbe3f67SBaptiste Daroussin * Output changes to the "old" file. The first loop suppresses 14893bbe3f67SBaptiste Daroussin * output if there were no changes to the "old" file (we'll see 14903bbe3f67SBaptiste Daroussin * the "old" lines as context in the "new" list). 14913bbe3f67SBaptiste Daroussin */ 14923bbe3f67SBaptiste Daroussin do_output = 0; 14933bbe3f67SBaptiste Daroussin for (; cvp <= context_vec_ptr; cvp++) 14943bbe3f67SBaptiste Daroussin if (cvp->a <= cvp->b) { 14953bbe3f67SBaptiste Daroussin cvp = context_vec_start; 14963bbe3f67SBaptiste Daroussin do_output++; 14973bbe3f67SBaptiste Daroussin break; 14983bbe3f67SBaptiste Daroussin } 14993bbe3f67SBaptiste Daroussin if (do_output) { 15003bbe3f67SBaptiste Daroussin while (cvp <= context_vec_ptr) { 15013bbe3f67SBaptiste Daroussin a = cvp->a; 15023bbe3f67SBaptiste Daroussin b = cvp->b; 15033bbe3f67SBaptiste Daroussin c = cvp->c; 15043bbe3f67SBaptiste Daroussin d = cvp->d; 15053bbe3f67SBaptiste Daroussin 15063bbe3f67SBaptiste Daroussin if (a <= b && c <= d) 15073bbe3f67SBaptiste Daroussin ch = 'c'; 15083bbe3f67SBaptiste Daroussin else 15093bbe3f67SBaptiste Daroussin ch = (a <= b) ? 'd' : 'a'; 15103bbe3f67SBaptiste Daroussin 15113bbe3f67SBaptiste Daroussin if (ch == 'a') 15123bbe3f67SBaptiste Daroussin fetch(ixold, lowa, b, f1, ' ', 0, flags); 15133bbe3f67SBaptiste Daroussin else { 15143bbe3f67SBaptiste Daroussin fetch(ixold, lowa, a - 1, f1, ' ', 0, flags); 15153bbe3f67SBaptiste Daroussin fetch(ixold, a, b, f1, 15163bbe3f67SBaptiste Daroussin ch == 'c' ? '!' : '-', 0, flags); 15173bbe3f67SBaptiste Daroussin } 15183bbe3f67SBaptiste Daroussin lowa = b + 1; 15193bbe3f67SBaptiste Daroussin cvp++; 15203bbe3f67SBaptiste Daroussin } 15213bbe3f67SBaptiste Daroussin fetch(ixold, b + 1, upb, f1, ' ', 0, flags); 15223bbe3f67SBaptiste Daroussin } 15233bbe3f67SBaptiste Daroussin /* output changes to the "new" file */ 15243bbe3f67SBaptiste Daroussin diff_output("--- "); 15253bbe3f67SBaptiste Daroussin range(lowc, upd, ","); 15263bbe3f67SBaptiste Daroussin diff_output(" ----\n"); 15273bbe3f67SBaptiste Daroussin 15283bbe3f67SBaptiste Daroussin do_output = 0; 15293bbe3f67SBaptiste Daroussin for (cvp = context_vec_start; cvp <= context_vec_ptr; cvp++) 15303bbe3f67SBaptiste Daroussin if (cvp->c <= cvp->d) { 15313bbe3f67SBaptiste Daroussin cvp = context_vec_start; 15323bbe3f67SBaptiste Daroussin do_output++; 15333bbe3f67SBaptiste Daroussin break; 15343bbe3f67SBaptiste Daroussin } 15353bbe3f67SBaptiste Daroussin if (do_output) { 15363bbe3f67SBaptiste Daroussin while (cvp <= context_vec_ptr) { 15373bbe3f67SBaptiste Daroussin a = cvp->a; 15383bbe3f67SBaptiste Daroussin b = cvp->b; 15393bbe3f67SBaptiste Daroussin c = cvp->c; 15403bbe3f67SBaptiste Daroussin d = cvp->d; 15413bbe3f67SBaptiste Daroussin 15423bbe3f67SBaptiste Daroussin if (a <= b && c <= d) 15433bbe3f67SBaptiste Daroussin ch = 'c'; 15443bbe3f67SBaptiste Daroussin else 15453bbe3f67SBaptiste Daroussin ch = (a <= b) ? 'd' : 'a'; 15463bbe3f67SBaptiste Daroussin 15473bbe3f67SBaptiste Daroussin if (ch == 'd') 15483bbe3f67SBaptiste Daroussin fetch(ixnew, lowc, d, f2, ' ', 0, flags); 15493bbe3f67SBaptiste Daroussin else { 15503bbe3f67SBaptiste Daroussin fetch(ixnew, lowc, c - 1, f2, ' ', 0, flags); 15513bbe3f67SBaptiste Daroussin fetch(ixnew, c, d, f2, 15523bbe3f67SBaptiste Daroussin ch == 'c' ? '!' : '+', 0, flags); 15533bbe3f67SBaptiste Daroussin } 15543bbe3f67SBaptiste Daroussin lowc = d + 1; 15553bbe3f67SBaptiste Daroussin cvp++; 15563bbe3f67SBaptiste Daroussin } 15573bbe3f67SBaptiste Daroussin fetch(ixnew, d + 1, upd, f2, ' ', 0, flags); 15583bbe3f67SBaptiste Daroussin } 15593bbe3f67SBaptiste Daroussin context_vec_ptr = context_vec_start - 1; 15603bbe3f67SBaptiste Daroussin } 15613bbe3f67SBaptiste Daroussin 15623bbe3f67SBaptiste Daroussin /* dump accumulated "unified" diff changes */ 15633bbe3f67SBaptiste Daroussin static void 15643bbe3f67SBaptiste Daroussin dump_unified_vec(FILE *f1, FILE *f2, int flags) 15653bbe3f67SBaptiste Daroussin { 15663bbe3f67SBaptiste Daroussin struct context_vec *cvp = context_vec_start; 15673bbe3f67SBaptiste Daroussin int lowa, upb, lowc, upd; 15683bbe3f67SBaptiste Daroussin int a, b, c, d; 15693bbe3f67SBaptiste Daroussin char ch, *f; 15703bbe3f67SBaptiste Daroussin 15713bbe3f67SBaptiste Daroussin if (context_vec_start > context_vec_ptr) 15723bbe3f67SBaptiste Daroussin return; 15733bbe3f67SBaptiste Daroussin 15743bbe3f67SBaptiste Daroussin b = d = 0; /* gcc */ 157542c88c41SBaptiste Daroussin lowa = MAX(1, cvp->a - diff_context); 157642c88c41SBaptiste Daroussin upb = MIN(len[0], context_vec_ptr->b + diff_context); 157742c88c41SBaptiste Daroussin lowc = MAX(1, cvp->c - diff_context); 157842c88c41SBaptiste Daroussin upd = MIN(len[1], context_vec_ptr->d + diff_context); 15793bbe3f67SBaptiste Daroussin 15803bbe3f67SBaptiste Daroussin diff_output("@@ -"); 15813bbe3f67SBaptiste Daroussin uni_range(lowa, upb); 15823bbe3f67SBaptiste Daroussin diff_output(" +"); 15833bbe3f67SBaptiste Daroussin uni_range(lowc, upd); 15843bbe3f67SBaptiste Daroussin diff_output(" @@"); 15853bbe3f67SBaptiste Daroussin if ((flags & D_PROTOTYPE)) { 15863bbe3f67SBaptiste Daroussin f = match_function(ixold, lowa-1, f1); 15873bbe3f67SBaptiste Daroussin if (f != NULL) 15883bbe3f67SBaptiste Daroussin diff_output(" %s", f); 15893bbe3f67SBaptiste Daroussin } 15903bbe3f67SBaptiste Daroussin diff_output("\n"); 15913bbe3f67SBaptiste Daroussin 15923bbe3f67SBaptiste Daroussin /* 15933bbe3f67SBaptiste Daroussin * Output changes in "unified" diff format--the old and new lines 15943bbe3f67SBaptiste Daroussin * are printed together. 15953bbe3f67SBaptiste Daroussin */ 15963bbe3f67SBaptiste Daroussin for (; cvp <= context_vec_ptr; cvp++) { 15973bbe3f67SBaptiste Daroussin a = cvp->a; 15983bbe3f67SBaptiste Daroussin b = cvp->b; 15993bbe3f67SBaptiste Daroussin c = cvp->c; 16003bbe3f67SBaptiste Daroussin d = cvp->d; 16013bbe3f67SBaptiste Daroussin 16023bbe3f67SBaptiste Daroussin /* 16033bbe3f67SBaptiste Daroussin * c: both new and old changes 16043bbe3f67SBaptiste Daroussin * d: only changes in the old file 16053bbe3f67SBaptiste Daroussin * a: only changes in the new file 16063bbe3f67SBaptiste Daroussin */ 16073bbe3f67SBaptiste Daroussin if (a <= b && c <= d) 16083bbe3f67SBaptiste Daroussin ch = 'c'; 16093bbe3f67SBaptiste Daroussin else 16103bbe3f67SBaptiste Daroussin ch = (a <= b) ? 'd' : 'a'; 16113bbe3f67SBaptiste Daroussin 16123bbe3f67SBaptiste Daroussin switch (ch) { 16133bbe3f67SBaptiste Daroussin case 'c': 16143bbe3f67SBaptiste Daroussin fetch(ixold, lowa, a - 1, f1, ' ', 0, flags); 16153bbe3f67SBaptiste Daroussin fetch(ixold, a, b, f1, '-', 0, flags); 16163bbe3f67SBaptiste Daroussin fetch(ixnew, c, d, f2, '+', 0, flags); 16173bbe3f67SBaptiste Daroussin break; 16183bbe3f67SBaptiste Daroussin case 'd': 16193bbe3f67SBaptiste Daroussin fetch(ixold, lowa, a - 1, f1, ' ', 0, flags); 16203bbe3f67SBaptiste Daroussin fetch(ixold, a, b, f1, '-', 0, flags); 16213bbe3f67SBaptiste Daroussin break; 16223bbe3f67SBaptiste Daroussin case 'a': 16233bbe3f67SBaptiste Daroussin fetch(ixnew, lowc, c - 1, f2, ' ', 0, flags); 16243bbe3f67SBaptiste Daroussin fetch(ixnew, c, d, f2, '+', 0, flags); 16253bbe3f67SBaptiste Daroussin break; 16263bbe3f67SBaptiste Daroussin } 16273bbe3f67SBaptiste Daroussin lowa = b + 1; 16283bbe3f67SBaptiste Daroussin lowc = d + 1; 16293bbe3f67SBaptiste Daroussin } 16303bbe3f67SBaptiste Daroussin fetch(ixnew, d + 1, upd, f2, ' ', 0, flags); 16313bbe3f67SBaptiste Daroussin 16323bbe3f67SBaptiste Daroussin context_vec_ptr = context_vec_start - 1; 16333bbe3f67SBaptiste Daroussin } 16343bbe3f67SBaptiste Daroussin 16353bbe3f67SBaptiste Daroussin static void 16363bbe3f67SBaptiste Daroussin print_header(const char *file1, const char *file2) 16373bbe3f67SBaptiste Daroussin { 16383bbe3f67SBaptiste Daroussin const char *time_format; 16393bbe3f67SBaptiste Daroussin char buf1[256]; 16403bbe3f67SBaptiste Daroussin char buf2[256]; 16413bbe3f67SBaptiste Daroussin char end1[10]; 16423bbe3f67SBaptiste Daroussin char end2[10]; 164358cf4d86SJilles Tjoelker struct tm tm1, tm2, *tm_ptr1, *tm_ptr2; 1644385a67dcSJilles Tjoelker int nsec1 = stb1.st_mtim.tv_nsec; 1645385a67dcSJilles Tjoelker int nsec2 = stb2.st_mtim.tv_nsec; 16463bbe3f67SBaptiste Daroussin 16473bbe3f67SBaptiste Daroussin time_format = "%Y-%m-%d %H:%M:%S"; 16483bbe3f67SBaptiste Daroussin 16493bbe3f67SBaptiste Daroussin if (cflag) 16503bbe3f67SBaptiste Daroussin time_format = "%c"; 165158cf4d86SJilles Tjoelker tm_ptr1 = localtime_r(&stb1.st_mtime, &tm1); 165258cf4d86SJilles Tjoelker tm_ptr2 = localtime_r(&stb2.st_mtime, &tm2); 16533bbe3f67SBaptiste Daroussin strftime(buf1, 256, time_format, tm_ptr1); 16543bbe3f67SBaptiste Daroussin strftime(buf2, 256, time_format, tm_ptr2); 16553bbe3f67SBaptiste Daroussin if (!cflag) { 16563bbe3f67SBaptiste Daroussin strftime(end1, 10, "%z", tm_ptr1); 16573bbe3f67SBaptiste Daroussin strftime(end2, 10, "%z", tm_ptr2); 16583bbe3f67SBaptiste Daroussin sprintf(buf1, "%s.%.9d %s", buf1, nsec1, end1); 16593bbe3f67SBaptiste Daroussin sprintf(buf2, "%s.%.9d %s", buf2, nsec2, end2); 16603bbe3f67SBaptiste Daroussin } 16613bbe3f67SBaptiste Daroussin if (label[0] != NULL) 16623bbe3f67SBaptiste Daroussin diff_output("%s %s\n", diff_format == D_CONTEXT ? "***" : "---", 16633bbe3f67SBaptiste Daroussin label[0]); 16643bbe3f67SBaptiste Daroussin else 16653bbe3f67SBaptiste Daroussin diff_output("%s %s\t%s\n", diff_format == D_CONTEXT ? "***" : "---", 16663bbe3f67SBaptiste Daroussin file1, buf1); 16673bbe3f67SBaptiste Daroussin if (label[1] != NULL) 16683bbe3f67SBaptiste Daroussin diff_output("%s %s\n", diff_format == D_CONTEXT ? "---" : "+++", 16693bbe3f67SBaptiste Daroussin label[1]); 16703bbe3f67SBaptiste Daroussin else 16713bbe3f67SBaptiste Daroussin diff_output("%s %s\t%s\n", diff_format == D_CONTEXT ? "---" : "+++", 16723bbe3f67SBaptiste Daroussin file2, buf2); 16733bbe3f67SBaptiste Daroussin } 1674