diffh.c (10259B)
1 /* 2 * This code contains changes by 3 * Gunnar Ritter, Freiburg i. Br., Germany, March 2003. All rights reserved. 4 * 5 * Conditions 1, 2, and 4 and the no-warranty notice below apply 6 * to these changes. 7 * 8 * 9 * Copyright (c) 1991 10 * The Regents of the University of California. All rights reserved. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. All advertising materials mentioning features or use of this software 21 * must display the following acknowledgement: 22 * This product includes software developed by the University of 23 * California, Berkeley and its contributors. 24 * 4. Neither the name of the University nor the names of its contributors 25 * may be used to endorse or promote products derived from this software 26 * without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38 * SUCH DAMAGE. 39 * 40 * 41 * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved. 42 * 43 * Redistribution and use in source and binary forms, with or without 44 * modification, are permitted provided that the following conditions 45 * are met: 46 * Redistributions of source code and documentation must retain the 47 * above copyright notice, this list of conditions and the following 48 * disclaimer. 49 * Redistributions in binary form must reproduce the above copyright 50 * notice, this list of conditions and the following disclaimer in the 51 * documentation and/or other materials provided with the distribution. 52 * All advertising materials mentioning features or use of this software 53 * must display the following acknowledgement: 54 * This product includes software developed or owned by Caldera 55 * International, Inc. 56 * Neither the name of Caldera International, Inc. nor the names of 57 * other contributors may be used to endorse or promote products 58 * derived from this software without specific prior written permission. 59 * 60 * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA 61 * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR 62 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 63 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 64 * ARE DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE 65 * LIABLE FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR 66 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 67 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 68 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 69 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 70 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 71 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 72 */ 73 74 #if __GNUC__ >= 3 && __GNUC_MINOR__ >= 4 || __GNUC__ >= 4 75 #define USED __attribute__ ((used)) 76 #elif defined __GNUC__ 77 #define USED __attribute__ ((unused)) 78 #else 79 #define USED 80 #endif 81 static const char sccsid[] USED = "@(#)diffh.sl 1.11 (gritter) 5/29/05"; 82 83 /* from 4.3BSD diffh.c 4.4 11/27/85> */ 84 85 #include <stdio.h> 86 #include <ctype.h> 87 #include <sys/types.h> 88 #include <sys/stat.h> 89 #include <stdlib.h> 90 #include <string.h> 91 #include <limits.h> 92 #include <unistd.h> 93 #include <locale.h> 94 #include <wchar.h> 95 #include <wctype.h> 96 97 #include <iblok.h> 98 #include <mbtowi.h> 99 100 #define C 3 101 #define RANGE 30 102 #define INF 16384 103 104 #define next(wc, s, n) (*(s) & 0200 ? ((n) = mbtowi(&(wc), (s), mb_cur_max), \ 105 (n) = ((n) > 0 ? (n) : (n) < 0 ? (wc=WEOF, 1) : 1)) :\ 106 ((wc) = *(s) & 0377, (n) = 1)) 107 108 static char *text[2][RANGE]; 109 static size_t size[2][RANGE]; 110 static long long lineno[2] = {1, 1}; /*no. of 1st stored line in each file*/ 111 static int ntext[2]; /*number of stored lines in each*/ 112 static long long n0,n1; /*scan pointer in each*/ 113 static int bflag; 114 static int mb_cur_max; 115 static int debug = 0; 116 static struct iblok *file[2]; 117 static int eof[2]; 118 119 static char *getl(int, long long); 120 static void clrl(int, long long); 121 static void movstr(int, int, int); 122 static int easysynch(void); 123 static int output(int, int); 124 static void change(long long, int, long long, int, const char *); 125 static void range(long long, int); 126 static int cmp(const char *, const char *); 127 static struct iblok *dopen(const char *, const char *); 128 static void progerr(const char *); 129 static void error(const char *, const char *); 130 static int hardsynch(void); 131 static void *lrealloc(void *, size_t); 132 133 /* return pointer to line n of file f*/ 134 static char * 135 getl(int f, long long n) 136 { 137 register int delta, nt; 138 size_t len; 139 140 delta = n - lineno[f]; 141 nt = ntext[f]; 142 if(delta<0) 143 progerr("1"); 144 if(delta<nt) 145 return(text[f][delta]); 146 if(delta>nt) 147 progerr("2"); 148 if(nt>=RANGE) 149 progerr("3"); 150 if(eof[f]) 151 return(NULL); 152 len = ib_getlin(file[f], &text[f][nt], &size[f][nt], lrealloc); 153 if (len != 0) { 154 ntext[f]++; 155 return(text[f][nt]); 156 } else { 157 eof[f]++; 158 return NULL; 159 } 160 } 161 162 /*remove thru line n of file f from storage*/ 163 static void 164 clrl(int f,long long n) 165 { 166 register long long i,j; 167 j = n-lineno[f]+1; 168 for(i=0;i+j<ntext[f];i++) 169 movstr(f, i+j, i); 170 lineno[f] = n+1; 171 ntext[f] -= j; 172 } 173 174 static void 175 movstr(register int f, register int i, register int j) 176 { 177 free(text[f][j]); 178 text[f][j] = text[f][i]; 179 size[f][j] = size[f][i]; 180 text[f][i] = 0; 181 size[f][i] = 0; 182 } 183 184 int 185 main(int argc,char **argv) 186 { 187 char *s0,*s1; 188 register int c, status = 0; 189 190 setlocale(LC_CTYPE, ""); 191 mb_cur_max = MB_CUR_MAX; 192 while((c=getopt(argc,argv,":b")) != EOF) { 193 switch (c) { 194 case 'b': 195 bflag++; 196 break; 197 } 198 } 199 if(argc-optind!=2) 200 error("must have 2 file arguments",""); 201 file[0] = dopen(argv[optind],argv[optind+1]); 202 file[1] = dopen(argv[optind+1],argv[optind]); 203 for(;;) { 204 s0 = getl(0,++n0); 205 s1 = getl(1,++n1); 206 if(s0==NULL||s1==NULL) 207 break; 208 if(cmp(s0,s1)!=0) { 209 if(!easysynch()&&!hardsynch()) 210 progerr("5"); 211 status = 1; 212 } else { 213 clrl(0,n0); 214 clrl(1,n1); 215 } 216 } 217 if(s0==NULL&&s1==NULL) 218 exit(status); 219 if(s0==NULL) 220 output(-1,INF); 221 if(s1==NULL) 222 output(INF,-1); 223 return (1); 224 } 225 226 /* synch on C successive matches*/ 227 static int 228 easysynch(void) 229 { 230 int i,j; 231 register int k,m; 232 char *s0,*s1; 233 for(i=j=1;i<RANGE&&j<RANGE;i++,j++) { 234 s0 = getl(0,n0+i); 235 if(s0==NULL) 236 return(output(INF,INF)); 237 for(k=C-1;k<j;k++) { 238 for(m=0;m<C;m++) 239 if(cmp(getl(0,n0+i-m), 240 getl(1,n1+k-m))!=0) 241 goto cont1; 242 return(output(i-C,k-C)); 243 cont1: ; 244 } 245 s1 = getl(1,n1+j); 246 if(s1==NULL) 247 return(output(INF,INF)); 248 for(k=C-1;k<=i;k++) { 249 for(m=0;m<C;m++) 250 if(cmp(getl(0,n0+k-m), 251 getl(1,n1+j-m))!=0) 252 goto cont2; 253 return(output(k-C,j-C)); 254 cont2: ; 255 } 256 } 257 return(0); 258 } 259 260 static int 261 output(int a,int b) 262 { 263 register int i; 264 char *s; 265 if(a<0) 266 change(n0-1,0,n1,b,"a"); 267 else if(b<0) 268 change(n0,a,n1-1,0,"d"); 269 else 270 change(n0,a,n1,b,"c"); 271 for(i=0;i<=a;i++) { 272 s = getl(0,n0+i); 273 if(s==NULL) 274 break; 275 printf("< %s",s); 276 clrl(0,n0+i); 277 } 278 n0 += i-1; 279 if(a>=0&&b>=0) 280 printf("---\n"); 281 for(i=0;i<=b;i++) { 282 s = getl(1,n1+i); 283 if(s==NULL) 284 break; 285 printf("> %s",s); 286 clrl(1,n1+i); 287 } 288 n1 += i-1; 289 return(1); 290 } 291 292 static void 293 change(long long a,int b,long long c,int d,const char *s) 294 { 295 range(a,b); 296 printf("%s",s); 297 range(c,d); 298 printf("\n"); 299 } 300 301 static void 302 range(long long a,int b) 303 { 304 if(b==INF) 305 printf("%lld,$",a); 306 else if(b==0) 307 printf("%lld",a); 308 else 309 printf("%lld,%lld",a,a+b); 310 } 311 312 static int 313 cmp(const char *s,const char *t) 314 { 315 if(debug) 316 printf("%s:%s\n",s,t); 317 for(;;){ 318 if(bflag) { 319 if (mb_cur_max > 1) { 320 wint_t wc, wd; 321 int n, m; 322 323 if (next(wc, s, n), next(wd, t, m), 324 iswspace(wc) && iswspace(wd)) { 325 while (s += n, next(wc, s, n), 326 iswspace(wc)); 327 while (t += m, next(wd, t, m), 328 iswspace(wd)); 329 } 330 } else { 331 if (isspace(*s)&&isspace(*t)) { 332 while(isspace(*++s)) ; 333 while(isspace(*++t)) ; 334 } 335 } 336 } 337 if(*s!=*t||*s==0) 338 break; 339 s++; 340 t++; 341 } 342 return((*s&0377)-(*t&0377)); 343 } 344 345 static struct iblok * 346 dopen(const char *f1,const char *f2) 347 { 348 struct iblok *ip; 349 char *b=0,*bptr; 350 const char *eptr; 351 struct stat statbuf; 352 if(cmp(f1,"-")==0) 353 if(cmp(f2,"-")==0) 354 error("can't do - -",""); 355 else 356 return(ib_alloc(0, 0)); 357 if(stat(f1,&statbuf)==-1) 358 error("can't access ",f1); 359 if((statbuf.st_mode&S_IFMT)==S_IFDIR) { 360 b = lrealloc(0, strlen(f1) + strlen(f2) + 2); 361 for(bptr=b;*bptr= *f1++;bptr++) ; 362 *bptr++ = '/'; 363 for(eptr=f2;*eptr;eptr++) 364 if(*eptr=='/'&&eptr[1]!=0&&eptr[1]!='/') 365 f2 = eptr+1; 366 while(*bptr++= *f2++) ; 367 f1 = b; 368 } 369 ip = ib_open(f1,0); 370 if(ip==NULL) 371 error("can't open",f1); 372 if (b) 373 free(b); 374 return(ip); 375 } 376 377 static void 378 progerr(const char *s) 379 { 380 error("program error ",s); 381 } 382 383 static void 384 error(const char *s,const char *t) 385 { 386 fprintf(stderr,"diffh: %s%s\n",s,t); 387 exit(2); 388 } 389 390 /*stub for resychronization beyond limits of text buf*/ 391 static int 392 hardsynch(void) 393 { 394 change(n0,INF,n1,INF,"c"); 395 printf("---change record omitted\n"); 396 error("can't resynchronize",""); 397 return(0); 398 } 399 400 static void * 401 lrealloc(void *op, size_t size) 402 { 403 void *np; 404 405 if ((np = realloc(op, size)) == NULL) { 406 write(2, "diffh: line too long\n", 21); 407 _exit(1); 408 } 409 return np; 410 }