msort.c revision 1.18.6.1 1 1.18.6.1 sborrill /* $NetBSD: msort.c,v 1.18.6.1 2009/10/14 20:41:53 sborrill Exp $ */
2 1.14 jdolecek
3 1.14 jdolecek /*-
4 1.14 jdolecek * Copyright (c) 2000-2003 The NetBSD Foundation, Inc.
5 1.14 jdolecek * All rights reserved.
6 1.14 jdolecek *
7 1.14 jdolecek * This code is derived from software contributed to The NetBSD Foundation
8 1.14 jdolecek * by Ben Harris and Jaromir Dolecek.
9 1.14 jdolecek *
10 1.14 jdolecek * Redistribution and use in source and binary forms, with or without
11 1.14 jdolecek * modification, are permitted provided that the following conditions
12 1.14 jdolecek * are met:
13 1.14 jdolecek * 1. Redistributions of source code must retain the above copyright
14 1.14 jdolecek * notice, this list of conditions and the following disclaimer.
15 1.14 jdolecek * 2. Redistributions in binary form must reproduce the above copyright
16 1.14 jdolecek * notice, this list of conditions and the following disclaimer in the
17 1.14 jdolecek * documentation and/or other materials provided with the distribution.
18 1.14 jdolecek *
19 1.14 jdolecek * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 1.14 jdolecek * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 1.14 jdolecek * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 1.14 jdolecek * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 1.14 jdolecek * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 1.14 jdolecek * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 1.14 jdolecek * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 1.14 jdolecek * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 1.14 jdolecek * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 1.14 jdolecek * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 1.14 jdolecek * POSSIBILITY OF SUCH DAMAGE.
30 1.14 jdolecek */
31 1.2 bjh21
32 1.1 bjh21 /*-
33 1.1 bjh21 * Copyright (c) 1993
34 1.1 bjh21 * The Regents of the University of California. All rights reserved.
35 1.1 bjh21 *
36 1.1 bjh21 * This code is derived from software contributed to Berkeley by
37 1.1 bjh21 * Peter McIlroy.
38 1.1 bjh21 *
39 1.1 bjh21 * Redistribution and use in source and binary forms, with or without
40 1.1 bjh21 * modification, are permitted provided that the following conditions
41 1.1 bjh21 * are met:
42 1.1 bjh21 * 1. Redistributions of source code must retain the above copyright
43 1.1 bjh21 * notice, this list of conditions and the following disclaimer.
44 1.1 bjh21 * 2. Redistributions in binary form must reproduce the above copyright
45 1.1 bjh21 * notice, this list of conditions and the following disclaimer in the
46 1.1 bjh21 * documentation and/or other materials provided with the distribution.
47 1.13 agc * 3. Neither the name of the University nor the names of its contributors
48 1.1 bjh21 * may be used to endorse or promote products derived from this software
49 1.1 bjh21 * without specific prior written permission.
50 1.1 bjh21 *
51 1.1 bjh21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
52 1.1 bjh21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
53 1.1 bjh21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
54 1.1 bjh21 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
55 1.1 bjh21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
56 1.1 bjh21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
57 1.1 bjh21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58 1.1 bjh21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
59 1.1 bjh21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
60 1.1 bjh21 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
61 1.1 bjh21 * SUCH DAMAGE.
62 1.1 bjh21 */
63 1.1 bjh21
64 1.2 bjh21 #include "sort.h"
65 1.2 bjh21 #include "fsort.h"
66 1.2 bjh21
67 1.1 bjh21 #ifndef lint
68 1.18.6.1 sborrill __RCSID("$NetBSD: msort.c,v 1.18.6.1 2009/10/14 20:41:53 sborrill Exp $");
69 1.2 bjh21 __SCCSID("@(#)msort.c 8.1 (Berkeley) 6/6/93");
70 1.1 bjh21 #endif /* not lint */
71 1.1 bjh21
72 1.1 bjh21 #include <stdlib.h>
73 1.1 bjh21 #include <string.h>
74 1.1 bjh21 #include <unistd.h>
75 1.18.6.1 sborrill #include <util.h>
76 1.1 bjh21
77 1.1 bjh21 /* Subroutines using comparisons: merge sort and check order */
78 1.1 bjh21 #define DELETE (1)
79 1.8 jdolecek
80 1.1 bjh21 typedef struct mfile {
81 1.18.6.1 sborrill FILE *fp;
82 1.18.6.1 sborrill get_func_t get;
83 1.18.6.1 sborrill RECHEADER *rec;
84 1.18.6.1 sborrill u_char *end;
85 1.1 bjh21 } MFILE;
86 1.8 jdolecek
87 1.18.6.1 sborrill static int cmp(RECHEADER *, RECHEADER *);
88 1.18.6.1 sborrill static int insert(struct mfile **, struct mfile *, int, int);
89 1.18.6.1 sborrill static void merge_sort_fstack(FILE *, put_func_t, struct field *);
90 1.1 bjh21
91 1.18.6.1 sborrill /*
92 1.18.6.1 sborrill * Number of files merge() can merge in one pass.
93 1.18.6.1 sborrill */
94 1.18.6.1 sborrill #define MERGE_FNUM 16
95 1.18.6.1 sborrill
96 1.18.6.1 sborrill static struct mfile fstack[MERGE_FNUM];
97 1.18.6.1 sborrill static struct mfile fstack_1[MERGE_FNUM];
98 1.18.6.1 sborrill static struct mfile fstack_2[MERGE_FNUM];
99 1.18.6.1 sborrill static int fstack_count, fstack_1_count, fstack_2_count;
100 1.1 bjh21
101 1.1 bjh21 void
102 1.18.6.1 sborrill save_for_merge(FILE *fp, get_func_t get, struct field *ftbl)
103 1.1 bjh21 {
104 1.18.6.1 sborrill FILE *mfp, *mfp1, *mfp2;
105 1.1 bjh21
106 1.18.6.1 sborrill if (fstack_count == MERGE_FNUM) {
107 1.18.6.1 sborrill /* Must reduce the number of temporary files */
108 1.18.6.1 sborrill mfp = ftmp();
109 1.18.6.1 sborrill merge_sort_fstack(mfp, putrec, ftbl);
110 1.18.6.1 sborrill /* Save output in next layer */
111 1.18.6.1 sborrill if (fstack_1_count == MERGE_FNUM) {
112 1.18.6.1 sborrill mfp1 = ftmp();
113 1.18.6.1 sborrill memcpy(fstack, fstack_1, sizeof fstack);
114 1.18.6.1 sborrill merge_sort_fstack(mfp1, putrec, ftbl);
115 1.18.6.1 sborrill if (fstack_2_count == MERGE_FNUM) {
116 1.18.6.1 sborrill /* More than 4096 files! */
117 1.18.6.1 sborrill mfp2 = ftmp();
118 1.18.6.1 sborrill memcpy(fstack, fstack_2, sizeof fstack);
119 1.18.6.1 sborrill merge_sort_fstack(mfp2, putrec, ftbl);
120 1.18.6.1 sborrill fstack_2[0].fp = mfp2;
121 1.18.6.1 sborrill fstack_2_count = 1;
122 1.1 bjh21 }
123 1.18.6.1 sborrill fstack_2[fstack_2_count].fp = mfp1;
124 1.18.6.1 sborrill fstack_2[fstack_2_count].get = geteasy;
125 1.18.6.1 sborrill fstack_2_count++;
126 1.18.6.1 sborrill fstack_1_count = 0;
127 1.18.6.1 sborrill }
128 1.18.6.1 sborrill fstack_1[fstack_1_count].fp = mfp;
129 1.18.6.1 sborrill fstack_1[fstack_1_count].get = geteasy;
130 1.18.6.1 sborrill fstack_1_count++;
131 1.18.6.1 sborrill fstack_count = 0;
132 1.1 bjh21 }
133 1.18.6.1 sborrill
134 1.18.6.1 sborrill fstack[fstack_count].fp = fp;
135 1.18.6.1 sborrill fstack[fstack_count++].get = get;
136 1.1 bjh21 }
137 1.1 bjh21
138 1.18.6.1 sborrill void
139 1.18.6.1 sborrill fmerge(struct filelist *filelist, int nfiles, FILE *outfp, struct field *ftbl)
140 1.1 bjh21 {
141 1.18.6.1 sborrill get_func_t get = SINGL_FLD ? makeline : makekey;
142 1.18.6.1 sborrill FILE *fp;
143 1.18.6.1 sborrill int i;
144 1.18.6.1 sborrill
145 1.18.6.1 sborrill for (i = 0; i < nfiles; i++) {
146 1.18.6.1 sborrill fp = fopen(filelist->names[i], "r");
147 1.18.6.1 sborrill if (fp == NULL)
148 1.18.6.1 sborrill err(2, "%s", filelist->names[i]);
149 1.18.6.1 sborrill save_for_merge(fp, get, ftbl);
150 1.18.6.1 sborrill }
151 1.9 jdolecek
152 1.18.6.1 sborrill merge_sort(outfp, putline, ftbl);
153 1.18.6.1 sborrill }
154 1.18.6.1 sborrill
155 1.18.6.1 sborrill void
156 1.18.6.1 sborrill merge_sort(FILE *outfp, put_func_t put, struct field *ftbl)
157 1.18.6.1 sborrill {
158 1.18.6.1 sborrill int count = fstack_1_count + fstack_2_count;
159 1.18.6.1 sborrill FILE *mfp;
160 1.18.6.1 sborrill int i;
161 1.18.6.1 sborrill
162 1.18.6.1 sborrill if (count == 0) {
163 1.18.6.1 sborrill /* All files in initial array */
164 1.18.6.1 sborrill merge_sort_fstack(outfp, put, ftbl);
165 1.18.6.1 sborrill return;
166 1.18.6.1 sborrill }
167 1.18.6.1 sborrill
168 1.18.6.1 sborrill count += fstack_count;
169 1.9 jdolecek
170 1.18.6.1 sborrill /* Too many files for one merge sort */
171 1.18.6.1 sborrill for (;;) {
172 1.18.6.1 sborrill /* Sort latest 16 files */
173 1.18.6.1 sborrill i = count;
174 1.18.6.1 sborrill if (i > MERGE_FNUM)
175 1.18.6.1 sborrill i = MERGE_FNUM;
176 1.18.6.1 sborrill while (fstack_count > 0)
177 1.18.6.1 sborrill fstack[--i] = fstack[--fstack_count];
178 1.18.6.1 sborrill while (i > 0 && fstack_1_count > 0)
179 1.18.6.1 sborrill fstack[--i] = fstack_1[--fstack_1_count];
180 1.18.6.1 sborrill while (i > 0)
181 1.18.6.1 sborrill fstack[--i] = fstack_2[--fstack_2_count];
182 1.18.6.1 sborrill if (count <= MERGE_FNUM) {
183 1.18.6.1 sborrill /* Got all the data */
184 1.18.6.1 sborrill fstack_count = count;
185 1.18.6.1 sborrill merge_sort_fstack(outfp, put, ftbl);
186 1.18.6.1 sborrill return;
187 1.18.6.1 sborrill }
188 1.18.6.1 sborrill mfp = ftmp();
189 1.18.6.1 sborrill fstack_count = count > MERGE_FNUM ? MERGE_FNUM : count;
190 1.18.6.1 sborrill merge_sort_fstack(mfp, putrec, ftbl);
191 1.18.6.1 sborrill fstack[0].fp = mfp;
192 1.18.6.1 sborrill fstack[0].get = geteasy;
193 1.18.6.1 sborrill fstack_count = 1;
194 1.18.6.1 sborrill count -= MERGE_FNUM - 1;
195 1.9 jdolecek }
196 1.18.6.1 sborrill }
197 1.8 jdolecek
198 1.18.6.1 sborrill static void
199 1.18.6.1 sborrill merge_sort_fstack(FILE *outfp, put_func_t put, struct field *ftbl)
200 1.18.6.1 sborrill {
201 1.18.6.1 sborrill struct mfile *flistb[MERGE_FNUM], **flist = flistb, *cfile;
202 1.18.6.1 sborrill RECHEADER *new_rec;
203 1.18.6.1 sborrill u_char *new_end;
204 1.18.6.1 sborrill void *tmp;
205 1.18.6.1 sborrill int c, i, nfiles;
206 1.18.6.1 sborrill size_t sz;
207 1.18.6.1 sborrill
208 1.18.6.1 sborrill /* Read one record from each file (read again if a duplicate) */
209 1.18.6.1 sborrill for (nfiles = i = 0; i < fstack_count; i++) {
210 1.18.6.1 sborrill cfile = &fstack[i];
211 1.18.6.1 sborrill if (cfile->rec == NULL) {
212 1.18.6.1 sborrill cfile->rec = emalloc(DEFLLEN);
213 1.18.6.1 sborrill cfile->end = (u_char *)cfile->rec + DEFLLEN;
214 1.18.6.1 sborrill }
215 1.18.6.1 sborrill rewind(cfile->fp);
216 1.18.6.1 sborrill
217 1.18.6.1 sborrill for (;;) {
218 1.18.6.1 sborrill c = cfile->get(cfile->fp, cfile->rec, cfile->end, ftbl);
219 1.18.6.1 sborrill if (c == EOF)
220 1.1 bjh21 break;
221 1.9 jdolecek
222 1.9 jdolecek if (c == BUFFEND) {
223 1.18.6.1 sborrill /* Double buffer size */
224 1.18.6.1 sborrill sz = (cfile->end - (u_char *)cfile->rec) * 2;
225 1.18.6.1 sborrill cfile->rec = erealloc(cfile->rec, sz);
226 1.18.6.1 sborrill cfile->end = (u_char *)cfile->rec + sz;
227 1.9 jdolecek continue;
228 1.9 jdolecek }
229 1.9 jdolecek
230 1.18.6.1 sborrill if (nfiles != 0) {
231 1.18.6.1 sborrill if (insert(flist, cfile, nfiles, !DELETE))
232 1.18.6.1 sborrill /* Duplicate removed */
233 1.18.6.1 sborrill continue;
234 1.18.6.1 sborrill } else
235 1.1 bjh21 flist[0] = cfile;
236 1.18.6.1 sborrill nfiles++;
237 1.18.6.1 sborrill break;
238 1.1 bjh21 }
239 1.1 bjh21 }
240 1.9 jdolecek
241 1.18.6.1 sborrill if (nfiles == 0)
242 1.18.6.1 sborrill return;
243 1.18.6.1 sborrill
244 1.18.6.1 sborrill /*
245 1.18.6.1 sborrill * We now loop reading a new record from the file with the
246 1.18.6.1 sborrill * 'sorted first' existing record.
247 1.18.6.1 sborrill * As each record is added, the 'first' record is written to the
248 1.18.6.1 sborrill * output file - maintaining one record from each file in the sorted
249 1.18.6.1 sborrill * list.
250 1.18.6.1 sborrill */
251 1.18.6.1 sborrill new_rec = emalloc(DEFLLEN);
252 1.18.6.1 sborrill new_end = (u_char *)new_rec + DEFLLEN;
253 1.18.6.1 sborrill for (;;) {
254 1.18.6.1 sborrill cfile = flist[0];
255 1.18.6.1 sborrill c = cfile->get(cfile->fp, new_rec, new_end, ftbl);
256 1.18.6.1 sborrill if (c == EOF) {
257 1.18.6.1 sborrill /* Write out last record from now-empty input */
258 1.18.6.1 sborrill put(cfile->rec, outfp);
259 1.18.6.1 sborrill if (--nfiles == 0)
260 1.1 bjh21 break;
261 1.18.6.1 sborrill /* Replace from file with now-first sorted record. */
262 1.18.6.1 sborrill /* (Moving base 'flist' saves copying everything!) */
263 1.18.6.1 sborrill flist++;
264 1.18.6.1 sborrill continue;
265 1.18.6.1 sborrill }
266 1.18.6.1 sborrill if (c == BUFFEND) {
267 1.18.6.1 sborrill /* Buffer not large enough - double in size */
268 1.18.6.1 sborrill sz = (new_end - (u_char *)new_rec) * 2;
269 1.18.6.1 sborrill new_rec = erealloc(new_rec, sz);
270 1.18.6.1 sborrill new_end = (u_char *)new_rec +sz;
271 1.18.6.1 sborrill continue;
272 1.18.6.1 sborrill }
273 1.9 jdolecek
274 1.18.6.1 sborrill /* Swap in new buffer, saving old */
275 1.18.6.1 sborrill tmp = cfile->rec;
276 1.18.6.1 sborrill cfile->rec = new_rec;
277 1.18.6.1 sborrill new_rec = tmp;
278 1.18.6.1 sborrill tmp = cfile->end;
279 1.18.6.1 sborrill cfile->end = new_end;
280 1.18.6.1 sborrill new_end = tmp;
281 1.18.6.1 sborrill
282 1.18.6.1 sborrill /* Add into sort, removing the original first entry */
283 1.18.6.1 sborrill c = insert(flist, cfile, nfiles, DELETE);
284 1.18.6.1 sborrill if (c != 0 || (UNIQUE && cfile == flist[0]
285 1.18.6.1 sborrill && cmp(new_rec, cfile->rec) == 0)) {
286 1.18.6.1 sborrill /* Was an unwanted duplicate, restore buffer */
287 1.18.6.1 sborrill tmp = cfile->rec;
288 1.18.6.1 sborrill cfile->rec = new_rec;
289 1.18.6.1 sborrill new_rec = tmp;
290 1.18.6.1 sborrill tmp = cfile->end;
291 1.18.6.1 sborrill cfile->end = new_end;
292 1.18.6.1 sborrill new_end = tmp;
293 1.18.6.1 sborrill continue;
294 1.18.6.1 sborrill }
295 1.18.6.1 sborrill
296 1.18.6.1 sborrill /* Write out 'old' record */
297 1.18.6.1 sborrill put(new_rec, outfp);
298 1.9 jdolecek }
299 1.18.6.1 sborrill
300 1.18.6.1 sborrill free(new_rec);
301 1.1 bjh21 }
302 1.1 bjh21
303 1.1 bjh21 /*
304 1.18.6.1 sborrill * if delete: inserts rec in flist, deletes flist[0];
305 1.1 bjh21 * otherwise just inserts *rec in flist.
306 1.18.6.1 sborrill * Returns 1 if record is a duplicate to be ignored.
307 1.10 jdolecek */
308 1.1 bjh21 static int
309 1.18.6.1 sborrill insert(struct mfile **flist, struct mfile *rec, int ttop, int delete)
310 1.1 bjh21 {
311 1.8 jdolecek int mid, top = ttop, bot = 0, cmpv = 1;
312 1.8 jdolecek
313 1.16 itojun for (mid = top / 2; bot + 1 != top; mid = (bot + top) / 2) {
314 1.18.6.1 sborrill cmpv = cmp(rec->rec, flist[mid]->rec);
315 1.18.6.1 sborrill if (cmpv == 0 ) {
316 1.18.6.1 sborrill if (UNIQUE)
317 1.18.6.1 sborrill /* Duplicate key, read another record */
318 1.18.6.1 sborrill /* NB: This doesn't guarantee to keep any
319 1.18.6.1 sborrill * particular record. */
320 1.18.6.1 sborrill return 1;
321 1.18.6.1 sborrill /*
322 1.18.6.1 sborrill * Apply sort by input file order.
323 1.18.6.1 sborrill * We could truncate the sort is the fileno are
324 1.18.6.1 sborrill * adjacent - but that is all too hard!
325 1.18.6.1 sborrill * The fileno cannot be equal, since we only have one
326 1.18.6.1 sborrill * record from each file (+ flist[0] which never
327 1.18.6.1 sborrill * comes here).
328 1.18.6.1 sborrill */
329 1.18.6.1 sborrill cmpv = rec < flist[mid] ? -1 : 1;
330 1.18.6.1 sborrill if (REVERSE)
331 1.18.6.1 sborrill cmpv = -cmpv;
332 1.18.6.1 sborrill }
333 1.1 bjh21 if (cmpv < 0)
334 1.1 bjh21 top = mid;
335 1.18.6.1 sborrill else
336 1.1 bjh21 bot = mid;
337 1.18.6.1 sborrill }
338 1.8 jdolecek
339 1.18.6.1 sborrill /* At this point we haven't yet compared against flist[0] */
340 1.8 jdolecek
341 1.18.6.1 sborrill if (delete) {
342 1.18.6.1 sborrill /* flist[0] is ourselves, only the caller knows the old data */
343 1.18.6.1 sborrill if (bot != 0) {
344 1.18.6.1 sborrill memmove(flist, flist + 1, bot * sizeof(MFILE *));
345 1.18.6.1 sborrill flist[bot] = rec;
346 1.1 bjh21 }
347 1.18.6.1 sborrill return 0;
348 1.1 bjh21 }
349 1.8 jdolecek
350 1.18.6.1 sborrill /* Inserting original set of records */
351 1.18.6.1 sborrill
352 1.18.6.1 sborrill if (bot == 0 && cmpv != 0) {
353 1.18.6.1 sborrill /* Doesn't match flist[1], must compare with flist[0] */
354 1.18.6.1 sborrill cmpv = cmp(rec->rec, flist[0]->rec);
355 1.18.6.1 sborrill if (cmpv == 0 && UNIQUE)
356 1.18.6.1 sborrill return 1;
357 1.18.6.1 sborrill /* Add matching keys in file order (ie new is later) */
358 1.18.6.1 sborrill if (cmpv < 0)
359 1.18.6.1 sborrill bot = -1;
360 1.1 bjh21 }
361 1.18.6.1 sborrill bot++;
362 1.18.6.1 sborrill memmove(flist + bot + 1, flist + bot, (ttop - bot) * sizeof(MFILE *));
363 1.18.6.1 sborrill flist[bot] = rec;
364 1.18.6.1 sborrill return 0;
365 1.1 bjh21 }
366 1.1 bjh21
367 1.1 bjh21 /*
368 1.1 bjh21 * check order on one file
369 1.1 bjh21 */
370 1.1 bjh21 void
371 1.18.6.1 sborrill order(struct filelist *filelist, struct field *ftbl)
372 1.1 bjh21 {
373 1.18.6.1 sborrill get_func_t get = SINGL_FLD ? makeline : makekey;
374 1.18.6.1 sborrill RECHEADER *crec, *prec, *trec;
375 1.6 jdolecek u_char *crec_end, *prec_end, *trec_end;
376 1.18.6.1 sborrill FILE *fp;
377 1.1 bjh21 int c;
378 1.1 bjh21
379 1.18.6.1 sborrill fp = fopen(filelist->names[0], "r");
380 1.18.6.1 sborrill if (fp == NULL)
381 1.18.6.1 sborrill err(2, "%s", filelist->names[0]);
382 1.18.6.1 sborrill
383 1.18.6.1 sborrill crec = malloc(offsetof(RECHEADER, data[DEFLLEN]));
384 1.18.6.1 sborrill crec_end = crec->data + DEFLLEN;
385 1.18.6.1 sborrill prec = malloc(offsetof(RECHEADER, data[DEFLLEN]));
386 1.18.6.1 sborrill prec_end = prec->data + DEFLLEN;
387 1.18.6.1 sborrill
388 1.18.6.1 sborrill /* XXX this does exit(0) for overlong lines */
389 1.18.6.1 sborrill if (get(fp, prec, prec_end, ftbl) != 0)
390 1.18.6.1 sborrill exit(0);
391 1.18.6.1 sborrill while (get(fp, crec, crec_end, ftbl) == 0) {
392 1.1 bjh21 if (0 < (c = cmp(prec, crec))) {
393 1.1 bjh21 crec->data[crec->length-1] = 0;
394 1.1 bjh21 errx(1, "found disorder: %s", crec->data+crec->offset);
395 1.1 bjh21 }
396 1.1 bjh21 if (UNIQUE && !c) {
397 1.1 bjh21 crec->data[crec->length-1] = 0;
398 1.1 bjh21 errx(1, "found non-uniqueness: %s",
399 1.1 bjh21 crec->data+crec->offset);
400 1.1 bjh21 }
401 1.6 jdolecek /*
402 1.6 jdolecek * Swap pointers so that this record is on place pointed
403 1.6 jdolecek * to by prec and new record is read to place pointed to by
404 1.6 jdolecek * crec.
405 1.6 jdolecek */
406 1.1 bjh21 trec = prec;
407 1.1 bjh21 prec = crec;
408 1.1 bjh21 crec = trec;
409 1.6 jdolecek trec_end = prec_end;
410 1.6 jdolecek prec_end = crec_end;
411 1.6 jdolecek crec_end = trec_end;
412 1.1 bjh21 }
413 1.1 bjh21 exit(0);
414 1.1 bjh21 }
415 1.1 bjh21
416 1.1 bjh21 static int
417 1.18.6.1 sborrill cmp(RECHEADER *rec1, RECHEADER *rec2)
418 1.1 bjh21 {
419 1.18.6.1 sborrill int len;
420 1.4 jdolecek int r;
421 1.8 jdolecek
422 1.18.6.1 sborrill /* key is weights */
423 1.18.6.1 sborrill len = min(rec1->keylen, rec2->keylen);
424 1.18.6.1 sborrill r = memcmp(rec1->data, rec2->data, len);
425 1.18.6.1 sborrill if (r == 0)
426 1.18.6.1 sborrill r = rec1->keylen - rec2->keylen;
427 1.18.6.1 sborrill if (REVERSE)
428 1.18.6.1 sborrill r = -r;
429 1.18.6.1 sborrill return r;
430 1.1 bjh21 }
431