improve exit status handling for program map code
[unix-history] / usr / src / contrib / sort / files.c
CommitLineData
3b4896ec 1/*-
57c92088
KB
2 * Copyright (c) 1993
3 * The Regents of the University of California. All rights reserved.
3b4896ec
KB
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
57c92088 12static char sccsid[] = "@(#)files.c 8.1 (Berkeley) %G%";
3b4896ec
KB
13#endif /* not lint */
14
15#include "sort.h"
16#include "fsort.h"
17
18#include <string.h>
19
20/*
21 * this is the subroutine for file management for fsort().
22 * It keeps the buffers for all temporary files.
23 */
24int
25getnext(binno, infl0, nfiles, pos, end, dummy)
26 int binno, nfiles;
27 union f_handle infl0;
28 register struct recheader *pos;
29 register u_char *end;
30 struct field *dummy;
31{
32 register int i;
33 register u_char *hp;
34 static long nleft = 0;
35 static int cnt = 0, flag = -1;
36 static u_char maxb = 0;
37 static FILE *fd;
38
39 if (nleft == 0) {
40 if (binno < 0) /* reset files. */ {
41 for (i = 0; i < nfiles; i++) {
42 rewind(fstack[infl0.top + i].fd);
43 fstack[infl0.top + i].max_o = 0;
44 }
45 flag = -1;
46 nleft = cnt = 0;
47 return(-1);
48 }
49 maxb = fstack[infl0.top].maxb;
50 for (; nleft == 0; cnt++) {
51 if (cnt >= nfiles) {
52 cnt = 0;
53 return (EOF);
54 }
55 fd = fstack[infl0.top + cnt].fd;
56 hp = (u_char *) &nleft;
57 for (i = sizeof(TRECHEADER); i; --i)
58 *hp++ = getc(fd);
59 if (binno < maxb)
60 fstack[infl0.top+cnt].max_o
61 += sizeof(nleft) + nleft;
62 else if (binno == maxb) {
63 if (binno != fstack[infl0.top].lastb) {
64 fseek(fd, fstack[infl0.top+
65 cnt].max_o, SEEK_SET);
66 fread(&nleft, sizeof(nleft), 1, fd);
67 }
68 if (nleft == 0)
69 fclose(fd);
70 } else if (binno == maxb + 1) { /* skip a bin */
71 fseek(fd, nleft, SEEK_CUR);
72 fread(&nleft, sizeof(nleft), 1, fd);
73 flag = cnt;
74 }
75 }
76 }
77 if ((u_char *) pos > end - sizeof(TRECHEADER))
78 return (BUFFEND);
79 hp = (u_char *) pos;
80 for (i = sizeof(TRECHEADER); i ; --i)
81 *hp++ = (u_char) getc(fd);
82 if (end - pos->data < pos->length) {
83 for (i = sizeof(TRECHEADER); i ; i--)
84 ungetc(*--hp, fd);
85 return (BUFFEND);
86 }
87 fread(pos->data, pos->length, 1, fd);
88 nleft -= pos->length + sizeof(TRECHEADER);
89 if (nleft == 0 && binno == fstack[infl0.top].maxb)
90 fclose(fd);
91 return (0);
92}
93
94/*
95 * this is called when there is no special key. It's only called
96 * in the first fsort pass.
97 */
98int
99makeline(flno, filelist, nfiles, buffer, bufend, dummy2)
100 int flno, nfiles;
101 union f_handle filelist;
102 struct recheader *buffer;
103 u_char *bufend;
104 struct field *dummy2;
105{
106 static char *opos;
107 register char *end, *pos;
108 static int fileno = 0, overflow = 0;
109 static FILE *fd = 0;
110 register int c;
111
112 pos = (char *) buffer->data;
113 end = min((char *) bufend, pos + MAXLLEN);
114 if (overflow) {
115 memmove(pos, opos, bufend - (u_char *) opos);
116 pos += ((char *) bufend - opos);
117 overflow = 0;
118 }
119 for (;;) {
120 if (flno >= 0) {
121 if (!(fd = fstack[flno].fd))
122 return (EOF);
123 } else if (!fd) {
124 if (fileno >= nfiles) return(EOF);
125 if (!(fd = fopen(filelist.names[fileno], "r")))
126 err(2, "%s", filelist.names[fileno]);
127 ++fileno;
128 }
129 while ((pos < end) && ((c = getc(fd)) != EOF)) {
130 if ((*pos++ = c) == REC_D) {
131 buffer->offset = 0;
132 buffer->length = pos - (char *) buffer->data;
133 return (0);
134 }
135 }
136 if (pos >= end && end == (char *) bufend) {
137 if ((char *) buffer->data < end) {
138 overflow = 1;
139 opos = (char *) buffer->data;
140 }
141 return (BUFFEND);
142 } else if (c == EOF) {
143 if (buffer->data != (u_char *) pos) {
144 warnx("last character not record delimiter");
145 *pos++ = REC_D;
146 buffer->offset = 0;
147 buffer->length = pos - (char *) buffer->data;
148 return(0);
149 }
150 FCLOSE(fd);
151 fd = 0;
152 if(flno >= 0) fstack[flno].fd = 0;
153 } else {
154 buffer->data[100] = '\000';
155 warnx("line too long:ignoring %s...", buffer->data);
156 }
157 }
158}
159
160/*
161 * This generates keys. It's only called in the first fsort pass
162 */
163int
164makekey(flno, filelist, nfiles, buffer, bufend, ftbl)
165 int flno, nfiles;
166 union f_handle filelist;
167 struct recheader *buffer;
168 u_char *bufend;
169 struct field *ftbl;
170{
171 static int (*get)();
172 static int fileno = 0;
173 static FILE *dbdesc = 0;
174 static DBT dbkey[1], line[1];
175 static int overflow = 0;
176 int c;
177 if (overflow) {
178 overflow = 0;
179 enterkey(buffer, line, bufend - (u_char *) buffer, ftbl);
180 return (0);
181 }
182 for (;;) {
183 if (flno >= 0) {
184 get = seq;
185 if (!(dbdesc = fstack[flno].fd))
186 return(EOF);
187 } else if (!dbdesc) {
188 if (fileno >= nfiles)
189 return (EOF);
190 dbdesc = fopen(filelist.names[fileno], "r");
191 if (!dbdesc)
192 err(2, "%s", filelist.names[fileno]);
193 ++fileno;
194 get = seq;
195 }
196 if (!(c = get(dbdesc, line, dbkey))) {
197 if ((signed)line->size > bufend - buffer->data)
198 overflow = 1;
199 else
200 overflow = enterkey(buffer, line,
201 bufend - (u_char *) buffer, ftbl);
202 if (overflow)
203 return (BUFFEND);
204 else
205 return (0);
206 }
207 if (c == EOF) {
208 FCLOSE(dbdesc);
209 dbdesc = 0;
210 if (flno >= 0) fstack[flno].fd = 0;
211 } else {
212
213 ((char *) line->data)[60] = '\000';
214 warnx("line too long: ignoring %.100s...",
215 (char *)line->data);
216 }
217
218 }
219}
220
221/*
222 * get a key/line pair from fd
223 */
224int
225seq(fd, line, key)
226 FILE *fd;
227 DBT *key, *line;
228{
229 static char *buf, flag = 1;
230 register char *end, *pos;
231 register int c;
232 if (flag) {
233 flag = 0;
234 buf = (char *) linebuf;
235 end = buf + MAXLLEN;
236 line->data = buf;
237 }
238 pos = buf;
239 while ((c = getc(fd)) != EOF) {
240 if ((*pos++ = c) == REC_D) {
241 line->size = pos - buf;
242 return (0);
243 }
244 if (pos == end) {
245 line->size = MAXLLEN;
246 *--pos = REC_D;
247 while ((c = getc(fd)) != EOF) {
248 if (c == REC_D)
249 return (BUFFEND);
250 }
251 }
252 }
253 if (pos != buf) {
254 warnx("last character not record delimiter");
255 *pos++ = REC_D;
256 line->size = pos - buf;
257 return (0);
258 } else
259 return (EOF);
260}
261
262/*
263 * write a key/line pair to a temporary file
264 */
265void
266putrec(rec, fd)
267 register struct recheader *rec;
268 register FILE *fd;
269{
270 EWRITE(rec, 1, rec->length + sizeof(TRECHEADER), fd);
271}
272
273/*
274 * write a line to output
275 */
276void
277putline(rec, fd)
278 register struct recheader *rec;
279 register FILE *fd;
280{
281 EWRITE(rec->data+rec->offset, 1, rec->length - rec->offset, fd);
282}
283
284/*
285 * get a record from a temporary file. (Used by merge sort.)
286 */
287int
288geteasy(flno, filelist, nfiles, rec, end, dummy2)
289 int flno, nfiles;
290 union f_handle filelist;
291 register struct recheader *rec;
292 register u_char *end;
293 struct field *dummy2;
294{
295 int i;
296 FILE *fd;
297 fd = fstack[flno].fd;
298 if ((u_char *) rec > end - sizeof(TRECHEADER))
299 return (BUFFEND);
300 if (!fread(rec, 1, sizeof(TRECHEADER), fd)) {
301 fclose(fd);
302 fstack[flno].fd = 0;
303 return (EOF);
304 }
305 if (end - rec->data < rec->length) {
306 for (i = sizeof(TRECHEADER) - 1; i >= 0; i--)
307 ungetc(*((char *) rec + i), fd);
308 return (BUFFEND);
309 }
310 fread(rec->data, rec->length, 1, fd);
311 return (0);
312}