/*
 * $Copyright:	$
 * Copyright (c) 1984, 1985, 1986, 1987, 1988, 1989, 1990 
 * Sequent Computer Systems, Inc.   All rights reserved.
 *  
 * This software is furnished under a license and may be used
 * only in accordance with the terms of that license and with the
 * inclusion of the above copyright notice.   This software may not
 * be provided or otherwise made available to, or used by, any
 * other person.  No title to or ownership of the software is
 * hereby transferred.
 *
 */

/*	Copyright (c) 1984 AT&T	*/
/*	  All Rights Reserved  	*/

/*	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T	*/
/*	The copyright notice above does not evidence any   	*/
/*	actual or intended publication of such source code.	*/

#ident	"$Header: join.c 1.6 90/02/24 $@(#)join:join.c	1.4"

/*	join F1 F2 on stuff */

#include	<stdio.h>
#define F1 0
#define F2 1
#define	NFLD	20	/* max field per line */
#define comp() cmp(ppi[F1][j1],ppi[F2][j2])
#define putfield(string) if(*string == NULL) fputs(null, stdout); \
			else fputs(string, stdout)

#include	<euc.h>
#include	<getwidth.h>

FILE *f[2];
char buf[2][8*BUFSIZ];	/*input lines */
char *ppi[2][NFLD];	/* pointers to fields in lines */
char *s1,*s2;
int	j1	= 1;	/* join of this field of file 1 */
int	j2	= 1;	/* join of this field of file 2 */
int	olist[2*NFLD];	/* output these fields */
int	olistf[2*NFLD];	/* from these files */
int	no;	/* number of entries in olist */
int	sep1	= ' ';	/* default field separator */
int	sep2	= '\t';
char*	null	= "";
int	unpub1;
int	unpub2;
int	aflg;

char	*msep1	= " ";		/* default field separator on */
char	*msep2	= "\t";		/*  multibyte language system */
int	sepwidth = 1;		/* field separator width */
eucwidth_t	wp;

main(argc, argv)
char *argv[];
{
	int i;
	int n1, n2;
	long top2, bot2;
	long ftell();

	getwidth(&wp);
	wp._eucw2++;
	wp._eucw3++;

	while (argc > 1 && argv[1][0] == '-') {
		if (argv[1][1] == '\0')
			break;
		switch (argv[1][1]) {
		case 'a':
			switch(argv[1][2]) {
			case '1':
				aflg |= 1;
				break;
			case '2':
				aflg |= 2;
				break;
			default:
				aflg |= 3;
			}
			break;
		case 'e':
			null = argv[2];
			argv++;
			argc--;
			break;
		case 't':
			msep1 = msep2 = &argv[1][2];
			if (NOTASCII(*msep1)) {
				if (ISSET2(*msep1))
					sepwidth = wp._eucw2;
				else
				if (ISSET3(*msep1))
					sepwidth = wp._eucw3;
				else
					sepwidth = wp._eucw1;
			}
			break;
		case 'o':
			for (no = 0; no < 2*NFLD; no++) {
				if (argv[2][0] == '1' && argv[2][1] == '.') {
					olistf[no] = F1;
					olist[no] = atoi(&argv[2][2]);
				} else if (argv[2][0] == '2' && argv[2][1] == '.') {
					olist[no] = atoi(&argv[2][2]);
					olistf[no] = F2;
				} else
					break;
				argc--;
				argv++;
			}
			break;
		case 'j':
			if (argv[1][2] == '1')
				j1 = atoi(argv[2]);
			else if (argv[1][2] == '2')
				j2 = atoi(argv[2]);
			else
				j1 = j2 = atoi(argv[2]);
			argc--;
			argv++;
			break;
		}
		argc--;
		argv++;
	}
	for (i = 0; i < no; i++)
		olist[i]--;	/* 0 origin */
	if (argc != 3)
		error(gettxt("join:1", "usage: join [-an] [-e s] [-jn m] [-tc] [-o list] file1 file2"));
	j1--;
	j2--;	/* everyone else believes in 0 origin */
	s1 = ppi[F1][j1];
	s2 = ppi[F2][j2];
	if (argv[1][0] == '-')
		f[F1] = stdin;
	else if ((f[F1] = fopen(argv[1], "r")) == NULL)
		error(gettxt("join:2", "can't open %s"), argv[1]);
	if ((f[F2] = fopen(argv[2], "r")) == NULL)
		error(gettxt("join:2", "can't open %s"), argv[2]);

#define get1() n1=input(F1)
#define get2() n2=input(F2)
	get1();
	bot2 = ftell(f[F2]);
	get2();
	while(n1>0 && n2>0 || aflg!=0 && n1+n2>0) {
		if(n1>0 && n2>0 && comp()>0 || n1==0) {
			if(aflg&2) output(0, n2);
			bot2 = ftell(f[F2]);
			get2();
		} else if(n1>0 && n2>0 && comp()<0 || n2==0) {
			if(aflg&1) output(n1, 0);
			get1();
		} else /*(n1>0 && n2>0 && comp()==0)*/ {
			while(n2>0 && comp()==0) {
				output(n1, n2);
				top2 = ftell(f[F2]);
				get2();
			}
			fseek(f[F2], bot2, 0);
			get2();
			get1();
			for(;;) {
				if(n1>0 && n2>0 && comp()==0) {
					output(n1, n2);
					get2();
				} else if(n1>0 && n2>0 && comp()<0 || n2==0) {
					fseek(f[F2], bot2, 0);
					get2();
					get1();
				} else /*(n1>0 && n2>0 && comp()>0 || n1==0)*/{
					fseek(f[F2], top2, 0);
					bot2 = top2;
					get2();
					break;
				}
			}
		}
	}
	return(0);
}

input(n)		/* get input line and split into fields */
{
	register int i, c;
	char *bp;
	char **pp;
	register int sepc;		/* separater count */
	register int mltwidth = 1;	/* multi byte character width */
	int sepflag = 1;		/* if saparater then 1 else 0 */

	bp = buf[n];
	pp = ppi[n];
	if (fgets(bp, 8*BUFSIZ, f[n]) == NULL)
		return(0);
	i = 0;
	do {
		i++;
		if (*msep1 == ' ')	/* strip multiples */
			while ((c = *bp) == *msep1 || c == *msep2)
				bp++;	/* skip blanks */
		else
			c = *bp;
		*pp++ = bp;	/* record beginning */
		while ((c = *bp) != '\n' && c != '\0') {
			if ((c == *msep1) || (c == *msep2)) {
				if (c == *msep1) {
					for (sepc = 0; sepc < sepwidth ; sepc++) {
						if (c != msep1[sepc]) {
							sepflag = 0;
							break;
						}
						c = *(++bp);
					}
				}
				else if (c == *msep2) {
					break;
				}
				if (sepflag) {
					bp -= sepwidth;
					break;
				} else {
					sepflag = 1;
					bp -= sepc;
				}
			}
			if (NOTASCII(c)) {
				if (ISSET2(c))
					mltwidth = wp._eucw2;
				else
				if (ISSET3(c))
					mltwidth = wp._eucw3;
				else
					mltwidth = wp._eucw1;
			} else
				mltwidth = 1;
			bp += mltwidth;
		}
		*bp++ = '\0';	/* mark end by overwriting blank */
		bp += (sepwidth-1);	/* add pointer for multi byte separater */
	} while (c != '\n' && c != '\0');

	*pp = 0;
	return(i);
}

output(on1, on2)	/* print items from olist */
int on1, on2;
{
	int i;
	int sepc;	/* separater count */

	if (no <= 0) {	/* default case */
		if (on1)
			putfield(ppi[F1][j1]);
		else
			putfield(ppi[F2][j2]);
		for (i = 0; i < on1; i++)
			if (i != j1) {
				for (sepc = 0; sepc < sepwidth ; sepc++)
					putchar(msep1[sepc]);
				putfield(ppi[F1][i]);
			}
		for (i = 0; i < on2; i++)
			if (i != j2) {
				for (sepc = 0; sepc < sepwidth ; sepc++)
					putchar(msep1[sepc]);
				putfield(ppi[F2][i]);
			}
		putchar('\n');
	} else {
		for (i = 0; i < no; i++) {
			if(olistf[i]==F1 && on1<=olist[i] ||
			   olistf[i]==F2 && on2<=olist[i])
				fputs(null, stdout);
			else
				putfield(ppi[olistf[i]][olist[i]]);
			if (i < no - 1)
				for (sepc = 0; sepc < sepwidth ; sepc++)
					putchar(msep1[sepc]);
			else
				putchar('\n');
		}
	}
}

error(s1, s2, s3, s4, s5)
char *s1;
{
	fprintf(stderr, gettxt("colon:27", "join: "));
	fprintf(stderr, s1, s2, s3, s4, s5);
	fprintf(stderr, "\n");
	exit(1);
}

cmp(s1, s2)
char *s1, *s2;
{
	return(strcoll(s1, s2));
}
