xref: /original-bsd/contrib/sort/append.c (revision c3e32dec)
1 /*-
2  * Copyright (c) 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Peter McIlroy.
7  *
8  * %sccs.include.redist.c%
9  */
10 
11 #ifndef lint
12 static char sccsid[] = "@(#)append.c	8.1 (Berkeley) 06/06/93";
13 #endif /* not lint */
14 
15 #include "sort.h"
16 
17 #include <stdlib.h>
18 #include <string.h>
19 
20 #define OUTPUT {							\
21 	if ((n = cpos - ppos) > 1) {					\
22 		for (; ppos < cpos; ++ppos)				\
23 			*ppos -= odepth;				\
24 		ppos -= n;						\
25 		radixsort(ppos, n, wts1, REC_D);			\
26 		for (; ppos < cpos; ppos++) {				\
27 			prec = (RECHEADER *) (*ppos - sizeof(TRECHEADER));\
28 			put(prec, fd);					\
29 		}							\
30 	} else put(prec, fd);						\
31 }
32 
33 /*
34  * copy sorted lines to output; check for uniqueness
35  */
36 void
37 append(keylist, nelem, depth, fd, put, ftbl)
38 	u_char **keylist;
39 	int nelem;
40 	register int depth;
41 	FILE *fd;
42 	void (*put)(RECHEADER *, FILE *);
43 	struct field *ftbl;
44 {
45 	register u_char *wts, *wts1;
46 	register n, odepth;
47 	register u_char **cpos, **ppos, **lastkey;
48 	register u_char *cend, *pend, *start;
49 	register struct recheader *crec, *prec;
50 
51 	if (*keylist == '\0' && UNIQUE)
52 		return;
53 	wts1 = wts = ftbl[0].weights;
54 	if ((!UNIQUE) && SINGL_FLD) {
55 		if (ftbl[0].flags & F && ftbl[0].flags & R)
56 			wts1 = Rascii;
57 		else if (ftbl[0].flags & F)
58 			wts1 = ascii;
59 		odepth = depth;
60 	}
61 	lastkey = keylist + nelem;
62 	depth += sizeof(TRECHEADER);
63 	if (SINGL_FLD && (UNIQUE || wts1 != wts)) {
64 		ppos = keylist;
65 		prec = (RECHEADER *) (*ppos - depth);
66 		if (UNIQUE)
67 			put(prec, fd);
68 		for (cpos = keylist+1; cpos < lastkey; cpos++) {
69 			crec = (RECHEADER *) (*cpos - depth);
70 			if (crec->length  == prec->length) {
71 				pend = (u_char *) &prec->offset + prec->length;
72 				cend = (u_char *) &crec->offset + crec->length;
73 				for (start = *cpos; cend >= start; cend--) {
74 					if (wts[*cend] != wts[*pend])
75 						break;
76 					pend--;
77 				}
78 				if (pend + 1 != *ppos) {
79 					if (!UNIQUE) {
80 						OUTPUT;
81 					} else
82 						put(crec, fd);
83 					ppos = cpos;
84 					prec = crec;
85 				}
86 			} else {
87 				if (!UNIQUE) {
88 					OUTPUT;
89 				} else
90 					put(crec, fd);
91 				ppos = cpos;
92 				prec = crec;
93 			}
94 		}
95 		if (!UNIQUE)  { OUTPUT; }
96 	} else if (UNIQUE) {
97 		ppos = keylist;
98 		prec = (RECHEADER *) (*ppos - depth);
99 		put(prec, fd);
100 		for (cpos = keylist+1; cpos < lastkey; cpos++) {
101 			crec = (RECHEADER *) (*cpos - depth);
102 			if (crec->offset == prec->offset) {
103 				pend = (u_char *) &prec->offset + prec->offset;
104 				cend = (u_char *) &crec->offset + crec->offset;
105 				for (start = *cpos; cend >= start; cend--) {
106 					if (wts[*cend] != wts[*pend])
107 						break;
108 					pend--;
109 				}
110 				if (pend + 1 != *ppos) {
111 					ppos = cpos;
112 					prec = crec;
113 					put(prec, fd);
114 				}
115 			} else {
116 				ppos = cpos;
117 				prec = crec;
118 				put(prec, fd);
119 			}
120 		}
121 	} else for (cpos = keylist; cpos < lastkey; cpos++) {
122 		crec = (RECHEADER *) (*cpos - depth);
123 		put(crec, fd);
124 	}
125 }
126 
127 /*
128  * output the already sorted eol bin.
129  */
130 void
131 rd_append(binno, infl0, nfiles, outfd, buffer, bufend)
132 	u_char *buffer, *bufend;
133 	int binno, nfiles;
134 	union f_handle infl0;
135 	FILE *outfd;
136 {
137 	struct recheader *rec;
138 	rec = (RECHEADER *) buffer;
139 	if (!getnext(binno, infl0, nfiles, (RECHEADER *) buffer, bufend, 0)) {
140 		putline(rec, outfd);
141 		while (getnext(binno, infl0, nfiles, (RECHEADER *) buffer,
142 			bufend, 0) == 0) {
143 			if (!UNIQUE)
144 				putline(rec, outfd);
145 		}
146 	}
147 }
148 
149 /*
150  * append plain text--used after sorting the biggest bin.
151  */
152 void
153 concat(a, b)
154 	FILE *a, *b;
155 {
156         int nread;
157         char buffer[4096];
158 
159 	rewind(b);
160         while ((nread = fread(buffer, 1, 4096, b)) > 0)
161                 EWRITE(buffer, 1, nread, a);
162 }
163