Home | History | Annotate | Download | only in comm
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License, Version 1.0 only
      6  * (the "License").  You may not use this file except in compliance
      7  * with the License.
      8  *
      9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
     10  * or http://www.opensolaris.org/os/licensing.
     11  * See the License for the specific language governing permissions
     12  * and limitations under the License.
     13  *
     14  * When distributing Covered Code, include this CDDL HEADER in each
     15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     16  * If applicable, add the following below this CDDL HEADER, with the
     17  * fields enclosed by brackets "[]" replaced with your own identifying
     18  * information: Portions Copyright [yyyy] [name of copyright owner]
     19  *
     20  * CDDL HEADER END
     21  */
     22 /*
     23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
     28 /*	  All Rights Reserved  	*/
     29 
     30 
     31 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     32 
     33 /*
     34  *	process common lines of two files
     35  */
     36 
     37 #include 	<locale.h>
     38 #include	<stdio.h>
     39 #include	<stdlib.h>
     40 #include	<string.h>
     41 
     42 static int compare(char *, char *);
     43 static int rd(FILE *, char *);
     44 static FILE *openfil(char *);
     45 static void copy(FILE *, char *, int);
     46 static void usage(void);
     47 static void wr(char *, int);
     48 
     49 #define	LB	2050	/* P1003.2 minimum (2048) + 2 */
     50 
     51 #define	RDTWO(ib1, lb1, ib2, lb2) \
     52 	{ \
     53 		if (rd(ib1, lb1) < 0) { \
     54 			if (rd(ib2, lb2) < 0) \
     55 				exit(0); \
     56 			copy(ib2, lb2, 2); \
     57 		} \
     58 		if (rd(ib2, lb2) < 0) \
     59 			copy(ib1, lb1, 1); \
     60 	}
     61 
     62 static int	one;
     63 static int	two;
     64 static int	three;
     65 
     66 static char	ldr[3][3] = {"", "\t", "\t\t"};
     67 
     68 static FILE	*ib1;
     69 static FILE	*ib2;
     70 static int	is_c_locale;
     71 
     72 int
     73 main(int argc, char **argv)
     74 {
     75 	int	l = 1;
     76 	int	c;		/* used for getopt() */
     77 	char	lb1[LB], lb2[LB], *collate;
     78 
     79 	(void) setlocale(LC_ALL, "");
     80 #if !defined(TEXT_DOMAIN)	/* Should be defined by cc -D */
     81 #define	TEXT_DOMAIN "SYS_TEST"	/* Use this only if it weren't */
     82 #endif
     83 	(void) textdomain(TEXT_DOMAIN);
     84 
     85 	if ((collate = setlocale(LC_COLLATE, NULL)) == NULL) {
     86 		(void) fprintf(stderr,
     87 			gettext("Query of LC_COLLATE category failed\n"));
     88 		exit(4);
     89 	}
     90 
     91 	is_c_locale = (strcmp("C", collate) == 0) ? 1 : 0;
     92 	while ((c = getopt(argc, argv, "123")) != EOF)
     93 		switch (c) {
     94 		case '1':
     95 			if (!one) {
     96 				one = 1;
     97 				ldr[1][0] = ldr[2][l--] = '\0';
     98 			}
     99 			break;
    100 		case '2':
    101 			if (!two) {
    102 				two = 1;
    103 				ldr[2][l--] = '\0';
    104 			}
    105 			break;
    106 		case '3':
    107 			three = 1;
    108 			break;
    109 
    110 		default:
    111 			usage();
    112 		}
    113 
    114 	argc -= optind;
    115 	argv  = &argv[optind];
    116 
    117 	if (argc != 2)
    118 		usage();
    119 	ib1 = openfil(argv[0]);
    120 	ib2 = openfil(argv[1]);
    121 	RDTWO(ib1, lb1, ib2, lb2);
    122 	for (;;) {
    123 		switch (compare(lb1, lb2)) {
    124 			case 0:
    125 				wr(lb1, 3);
    126 				RDTWO(ib1, lb1, ib2, lb2);
    127 				continue;
    128 
    129 			case 1:
    130 				wr(lb1, 1);
    131 				if (rd(ib1, lb1) < 0)
    132 					copy(ib2, lb2, 2);
    133 				continue;
    134 
    135 			case 2:
    136 				wr(lb2, 2);
    137 				if (rd(ib2, lb2) < 0)
    138 					copy(ib1, lb1, 1);
    139 				continue;
    140 			/*
    141 			 * case "3" means lines are equal in collation,
    142 			 * but not identical (not very likely)
    143 			 */
    144 			case 3:
    145 				wr(lb1, 1);
    146 				wr(lb2, 2);
    147 				RDTWO(ib1, lb1, ib2, lb2);
    148 				continue;
    149 		}
    150 	}
    151 	/* NOTREACHED */
    152 	return (0);
    153 }
    154 
    155 static int
    156 rd(file, buf)
    157 FILE *file;
    158 char *buf;
    159 {
    160 	register int i, j;
    161 	i = j = 0;
    162 	while ((j = getc(file)) != EOF) {
    163 		*buf = (char)j;
    164 		if (*buf == '\n' || i > LB-2) {
    165 			*buf = '\0';
    166 			return (0);
    167 		}
    168 		i++;
    169 		buf++;
    170 	}
    171 	return (-1);
    172 }
    173 
    174 static void
    175 wr(str, n)
    176 char *str;
    177 int n;
    178 {
    179 	switch (n) {
    180 		case 1:
    181 			if (one)
    182 				return;
    183 			break;
    184 
    185 		case 2:
    186 			if (two)
    187 				return;
    188 			break;
    189 
    190 		case 3:
    191 			if (three)
    192 				return;
    193 	}
    194 	(void) printf("%s%s\n", ldr[n-1], str);
    195 }
    196 
    197 static void
    198 copy(ibuf, lbuf, n)
    199 FILE *ibuf;
    200 char *lbuf;
    201 int n;
    202 {
    203 	do {
    204 		wr(lbuf, n);
    205 	} while (rd(ibuf, lbuf) >= 0);
    206 
    207 	exit(0);
    208 }
    209 
    210 static int
    211 compare(a, b)
    212 char *a, *b;
    213 {
    214 	register char *ra, *rb;
    215 	int ret;
    216 
    217 	ra = a - 1;
    218 	rb = b - 1;
    219 	while (*++ra == *++rb)
    220 		if (*ra == '\0')
    221 			return (0);
    222 
    223 	/* For "C" locale, just compare bytes */
    224 	if (is_c_locale) {
    225 		if (*ra < *rb)
    226 			return (1);
    227 		return (2);
    228 	}
    229 	/* For other locales, call locale-sensitive compare routine */
    230 	else {
    231 		ret = strcoll(a, b);
    232 		return (ret == 0 ? 3 : (ret < 0 ? 1 : 2));
    233 	}
    234 }
    235 
    236 static FILE *
    237 openfil(s)
    238 char *s;
    239 {
    240 	FILE *b;
    241 	if (s[0] == '-' && s[1] == 0)
    242 		b = stdin;
    243 	else if ((b = fopen(s, "r")) == NULL) {
    244 		(void) fprintf(stderr, "comm: ");
    245 		perror(s);
    246 		exit(2);
    247 	}
    248 	return (b);
    249 }
    250 
    251 static void
    252 usage()
    253 {
    254 	(void) fprintf(stderr, gettext("usage: comm [-123] file1 file2\n"));
    255 	exit(2);
    256 }
    257