xref: /netbsd-src/usr.bin/sort/append.c (revision 5aefcfdc06931dd97e76246d2fe0302f7b3fe094)
1 /*	$NetBSD: append.c,v 1.6 2000/10/17 15:22:57 jdolecek Exp $	*/
2 
3 /*-
4  * Copyright (c) 1993
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * This code is derived from software contributed to Berkeley by
8  * Peter McIlroy.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *	This product includes software developed by the University of
21  *	California, Berkeley and its contributors.
22  * 4. Neither the name of the University nor the names of its contributors
23  *    may be used to endorse or promote products derived from this software
24  *    without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36  * SUCH DAMAGE.
37  */
38 
39 #include "sort.h"
40 
41 #ifndef lint
42 __RCSID("$NetBSD: append.c,v 1.6 2000/10/17 15:22:57 jdolecek Exp $");
43 __SCCSID("@(#)append.c	8.1 (Berkeley) 6/6/93");
44 #endif /* not lint */
45 
46 #include <stdlib.h>
47 #include <string.h>
48 
49 #define OUTPUT {							\
50 	if ((n = cpos - ppos) > 1) {					\
51 		for (; ppos < cpos; ++ppos)				\
52 			*ppos -= odepth;				\
53 		ppos -= n;						\
54 		radixsort(ppos, n, wts1, REC_D);			\
55 		for (; ppos < cpos; ppos++) {				\
56 			prec = (const RECHEADER *) (*ppos - sizeof(TRECHEADER));\
57 			put(prec, fp);					\
58 		}							\
59 	} else put(prec, fp);						\
60 }
61 
62 /*
63  * copy sorted lines to output; check for uniqueness
64  */
65 void
66 append(keylist, nelem, depth, fp, put, ftbl)
67 	const u_char **keylist;
68 	int nelem;
69 	int depth;
70 	FILE *fp;
71 	void (*put)(const RECHEADER *, FILE *);
72 	struct field *ftbl;
73 {
74 	u_char *wts, *wts1;
75 	int n, odepth;
76 	const u_char **cpos, **ppos, **lastkey;
77 	const u_char *cend, *pend, *start;
78 	const struct recheader *crec, *prec;
79 
80 	if (*keylist == '\0' && UNIQUE)
81 		return;
82 	wts1 = wts = ftbl[0].weights;
83 	if ((!UNIQUE) && SINGL_FLD) {
84 		if (ftbl[0].flags & F && ftbl[0].flags & R)
85 			wts1 = Rascii;
86 		else if (ftbl[0].flags & F)
87 			wts1 = ascii;
88 		odepth = depth;
89 	}
90 	lastkey = keylist + nelem;
91 	depth += sizeof(TRECHEADER);
92 	if (SINGL_FLD && (UNIQUE || wts1 != wts)) {
93 		ppos = keylist;
94 		prec = (const RECHEADER *) (*ppos - depth);
95 		if (UNIQUE)
96 			put(prec, fp);
97 		for (cpos = &keylist[1]; cpos < lastkey; cpos++) {
98 			crec = (const RECHEADER *) (*cpos - depth);
99 			if (crec->length  == prec->length) {
100 				/*
101 				 * Set pend & cend so that trailing '\0' and
102 				 * record separator is ignored.
103 				 */
104 				pend = (const u_char *) &prec->data + prec->length - 2;
105 				cend = (const u_char *) &crec->data + crec->length - 2;
106 				for (start = *cpos; cend >= start; cend--) {
107 					if (wts[*cend] != wts[*pend])
108 						break;
109 					pend--;
110 				}
111 				if (pend + 1 != *ppos) {
112 					if (!UNIQUE) {
113 						OUTPUT;
114 					} else
115 						put(crec, fp);
116 					ppos = cpos;
117 					prec = crec;
118 				}
119 			} else {
120 				if (!UNIQUE) {
121 					OUTPUT;
122 				} else
123 					put(crec, fp);
124 				ppos = cpos;
125 				prec = crec;
126 			}
127 		}
128 		if (!UNIQUE)  { OUTPUT; }
129 	} else if (UNIQUE) {
130 		ppos = keylist;
131 		prec = (const RECHEADER *) (*ppos - depth);
132 		put(prec, fp);
133 		for (cpos = keylist+1; cpos < lastkey; cpos++) {
134 			crec = (const RECHEADER *) (*cpos - depth);
135 			if (crec->offset == prec->offset) {
136 				/*
137 				 * Set pend & cend so that trailing '\0' and
138 				 * record separator is ignored.
139 				 */
140 				pend = (const u_char *) &prec->data + prec->offset - 2;
141 				cend = (const u_char *) &crec->data + crec->offset - 2;
142 				for (start = *cpos; cend >= start; cend--) {
143 					if (wts[*cend] != wts[*pend])
144 						break;
145 					pend--;
146 				}
147 				if (pend + 1 != *ppos) {
148 					ppos = cpos;
149 					prec = crec;
150 					put(prec, fp);
151 				}
152 			} else {
153 				ppos = cpos;
154 				prec = crec;
155 				put(prec, fp);
156 			}
157 		}
158 	} else for (cpos = keylist; cpos < lastkey; cpos++) {
159 		crec = (const RECHEADER *) (*cpos - depth);
160 		put(crec, fp);
161 	}
162 }
163 
164 /*
165  * output the already sorted eol bin.
166  */
167 void
168 rd_append(binno, infl0, nfiles, outfp, buffer, bufend)
169 	u_char *buffer, *bufend;
170 	int binno, nfiles;
171 	union f_handle infl0;
172 	FILE *outfp;
173 {
174 	struct recheader *rec;
175 	rec = (RECHEADER *) buffer;
176 	if (!getnext(binno, infl0, nfiles, (RECHEADER *) buffer, bufend, 0)) {
177 		putline(rec, outfp);
178 		while (getnext(binno, infl0, nfiles, (RECHEADER *) buffer,
179 			bufend, 0) == 0) {
180 			if (!UNIQUE)
181 				putline(rec, outfp);
182 		}
183 	}
184 }
185 
186 /*
187  * append plain text--used after sorting the biggest bin.
188  */
189 void
190 concat(a, b)
191 	FILE *a, *b;
192 {
193         int nread;
194         char buffer[4096];
195 
196 	rewind(b);
197         while ((nread = fread(buffer, 1, 4096, b)) > 0)
198                 EWRITE(buffer, 1, nread, a);
199 }
200