xref: /original-bsd/usr.bin/join/join.c (revision 4b2c5e10)
1 static char *sccsid = "@(#)join.c	4.2 (Berkeley) 06/30/83";
2 /*	join F1 F2 on stuff */
3 
4 #include	<stdio.h>
5 #define F1 0
6 #define F2 1
7 #define	NFLD	20	/* max field per line */
8 #define comp() cmp(ppi[F1][j1],ppi[F2][j2])
9 
10 FILE *f[2];
11 char buf[2][BUFSIZ];	/*input lines */
12 char *ppi[2][NFLD];	/* pointers to fields in lines */
13 char *s1,*s2;
14 int	j1	= 1;	/* join of this field of file 1 */
15 int	j2	= 1;	/* join of this field of file 2 */
16 int	olist[2*NFLD];	/* output these fields */
17 int	olistf[2*NFLD];	/* from these files */
18 int	no;	/* number of entries in olist */
19 int	sep1	= ' ';	/* default field separator */
20 int	sep2	= '\t';
21 char*	null	= "";
22 int	unpub1;
23 int	unpub2;
24 int	aflg;
25 
26 main(argc, argv)
27 char *argv[];
28 {
29 	int i;
30 	int n1, n2;
31 	long top2, bot2;
32 	long ftell();
33 
34 	while (argc > 1 && argv[1][0] == '-') {
35 		if (argv[1][1] == '\0')
36 			break;
37 		switch (argv[1][1]) {
38 		case 'a':
39 			switch(argv[1][2]) {
40 			case '1':
41 				aflg |= 1;
42 				break;
43 			case '2':
44 				aflg |= 2;
45 				break;
46 			default:
47 				aflg |= 3;
48 			}
49 			break;
50 		case 'e':
51 			null = argv[2];
52 			argv++;
53 			argc--;
54 			break;
55 		case 't':
56 			sep1 = sep2 = argv[1][2];
57 			break;
58 		case 'o':
59 			for (no = 0; no < 2*NFLD; no++) {
60 				if (argv[2][0] == '1' && argv[2][1] == '.') {
61 					olistf[no] = F1;
62 					olist[no] = atoi(&argv[2][2]);
63 				} else if (argv[2][0] == '2' && argv[2][1] == '.') {
64 					olist[no] = atoi(&argv[2][2]);
65 					olistf[no] = F2;
66 				} else
67 					break;
68 				argc--;
69 				argv++;
70 			}
71 			break;
72 		case 'j':
73 			if (argv[1][2] == '1')
74 				j1 = atoi(argv[2]);
75 			else if (argv[1][2] == '2')
76 				j2 = atoi(argv[2]);
77 			else
78 				j1 = j2 = atoi(argv[2]);
79 			argc--;
80 			argv++;
81 			break;
82 		}
83 		argc--;
84 		argv++;
85 	}
86 	for (i = 0; i < no; i++)
87 		olist[i]--;	/* 0 origin */
88 	if (argc != 3)
89 error("usage: join [-an] [-estring] [-j1 x -j2 y] [-o list] [-tc] file1 file2");
90 	j1--;
91 	j2--;	/* everyone else believes in 0 origin */
92 	s1 = ppi[F1][j1];
93 	s2 = ppi[F2][j2];
94 	if (argv[1][0] == '-')
95 		f[F1] = stdin;
96 	else if ((f[F1] = fopen(argv[1], "r")) == NULL)
97 		error("can't open %s", argv[1]);
98 	if ((f[F2] = fopen(argv[2], "r")) == NULL)
99 		error("can't open %s", argv[2]);
100 
101 #define get1() n1=input(F1)
102 #define get2() n2=input(F2)
103 	get1();
104 	bot2 = ftell(f[F2]);
105 	get2();
106 	while(n1>0 && n2>0 || aflg!=0 && n1+n2>0) {
107 		if(n1>0 && n2>0 && comp()>0 || n1==0) {
108 			if(aflg&2) output(0, n2);
109 			bot2 = ftell(f[F2]);
110 			get2();
111 		} else if(n1>0 && n2>0 && comp()<0 || n2==0) {
112 			if(aflg&1) output(n1, 0);
113 			get1();
114 		} else /*(n1>0 && n2>0 && comp()==0)*/ {
115 			while(n2>0 && comp()==0) {
116 				output(n1, n2);
117 				top2 = ftell(f[F2]);
118 				get2();
119 			}
120 			fseek(f[F2], bot2, 0);
121 			get2();
122 			get1();
123 			for(;;) {
124 				if(n1>0 && n2>0 && comp()==0) {
125 					output(n1, n2);
126 					get2();
127 				} else if(n1>0 && n2>0 && comp()<0 || n2==0) {
128 					fseek(f[F2], bot2, 0);
129 					get2();
130 					get1();
131 				} else /*(n1>0 && n2>0 && comp()>0 || n1==0)*/{
132 					fseek(f[F2], top2, 0);
133 					bot2 = top2;
134 					get2();
135 					break;
136 				}
137 			}
138 		}
139 	}
140 	return(0);
141 }
142 
143 input(n)		/* get input line and split into fields */
144 {
145 	register int i, c;
146 	char *bp;
147 	char **pp;
148 
149 	bp = buf[n];
150 	pp = ppi[n];
151 	if (fgets(bp, BUFSIZ, f[n]) == NULL)
152 		return(0);
153 	for (i = 0; ; i++) {
154 		if (sep1 == ' ')	/* strip multiples */
155 			while ((c = *bp) == sep1 || c == sep2)
156 				bp++;	/* skip blanks */
157 		else
158 			c = *bp;
159 		if (c == '\n' || c == '\0')
160 			break;
161 		*pp++ = bp;	/* record beginning */
162 		while ((c = *bp) != sep1 && c != '\n' && c != sep2 && c != '\0')
163 			bp++;
164 		*bp++ = '\0';	/* mark end by overwriting blank */
165 			/* fails badly if string doesn't have \n at end */
166 	}
167 	*pp = 0;
168 	return(i);
169 }
170 
171 output(on1, on2)	/* print items from olist */
172 int on1, on2;
173 {
174 	int i;
175 	char *temp;
176 
177 	if (no <= 0) {	/* default case */
178 		printf("%s", on1? ppi[F1][j1]: ppi[F2][j2]);
179 		for (i = 0; i < on1; i++)
180 			if (i != j1)
181 				printf("%c%s", sep1, ppi[F1][i]);
182 		for (i = 0; i < on2; i++)
183 			if (i != j2)
184 				printf("%c%s", sep1, ppi[F2][i]);
185 		printf("\n");
186 	} else {
187 		for (i = 0; i < no; i++) {
188 			temp = ppi[olistf[i]][olist[i]];
189 			if(olistf[i]==F1 && on1<=olist[i] ||
190 			   olistf[i]==F2 && on2<=olist[i] ||
191 			   *temp==0)
192 				temp = null;
193 			printf("%s", temp);
194 			if (i == no - 1)
195 				printf("\n");
196 			else
197 				printf("%c", sep1);
198 		}
199 	}
200 }
201 
202 error(s1, s2, s3, s4, s5)
203 char *s1;
204 {
205 	fprintf(stderr, "join: ");
206 	fprintf(stderr, s1, s2, s3, s4, s5);
207 	fprintf(stderr, "\n");
208 	exit(1);
209 }
210 
211 cmp(s1, s2)
212 char *s1, *s2;
213 {
214 	return(strcmp(s1, s2));
215 }
216