kern: Make sure gcc47 - gcc50 don't check for set-not-used
[dragonfly.git] / usr.bin / sort / fields.c
1 /*      $NetBSD: fields.c,v 1.31 2009/11/06 18:34:22 joerg Exp $        */
2
3 /*-
4  * Copyright (c) 2000-2003 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Ben Harris and Jaromir Dolecek.
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  *
19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31
32 /*-
33  * Copyright (c) 1993
34  *      The Regents of the University of California.  All rights reserved.
35  *
36  * This code is derived from software contributed to Berkeley by
37  * Peter McIlroy.
38  *
39  * Redistribution and use in source and binary forms, with or without
40  * modification, are permitted provided that the following conditions
41  * are met:
42  * 1. Redistributions of source code must retain the above copyright
43  *    notice, this list of conditions and the following disclaimer.
44  * 2. Redistributions in binary form must reproduce the above copyright
45  *    notice, this list of conditions and the following disclaimer in the
46  *    documentation and/or other materials provided with the distribution.
47  * 3. Neither the name of the University nor the names of its contributors
48  *    may be used to endorse or promote products derived from this software
49  *    without specific prior written permission.
50  *
51  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
52  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
53  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
54  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
55  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
56  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
57  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
59  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
60  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
61  * SUCH DAMAGE.
62  */
63
64 /* Subroutines to generate sort keys. */
65
66 #include "sort.h"
67
68 #define SKIP_BLANKS(ptr) {                                      \
69         if (BLANK & d_mask[*(ptr)])                             \
70                 while (BLANK & d_mask[*(++(ptr))]);             \
71 }
72
73 #define NEXTCOL(pos) {                                          \
74         if (!SEP_FLAG)                                          \
75                 while (BLANK & l_d_mask[*(++pos)]);             \
76         while ((*(pos+1) != '\0') && !((FLD_D | REC_D_F) & l_d_mask[*++pos]));\
77 }
78                 
79 static u_char *enterfield(u_char *, const u_char *, struct field *, int);
80 static u_char *number(u_char *, const u_char *, u_char *, u_char *, int);
81 static u_char *length(u_char *, const u_char *, u_char *, u_char *, int);
82
83 #define DECIMAL_POINT '.'
84
85 /*
86  * constructs sort key with leading recheader, followed by the key,
87  * followed by the original line.
88  */
89 length_t
90 enterkey(RECHEADER *keybuf, const u_char *keybuf_end, u_char *line_data,
91     size_t line_size, struct field fieldtable[])
92         /* keybuf:       pointer to start of key */
93 {
94         int i;
95         u_char *l_d_mask;
96         u_char *lineend, *pos;
97         const u_char *endkey;
98         u_char *keypos;
99         struct coldesc *clpos;
100         int col = 1;
101         struct field *ftpos;
102
103         l_d_mask = d_mask;
104         pos = line_data - 1;
105         lineend = line_data + line_size-1;
106                                 /* don't include rec_delimiter */
107
108         for (i = 0; i < ncols; i++) {
109                 clpos = clist + i;
110                 for (; (col < clpos->num) && (pos < lineend); col++) {
111                         NEXTCOL(pos);
112                 }
113                 if (pos >= lineend)
114                         break;
115                 clpos->start = SEP_FLAG ? pos + 1 : pos;
116                 NEXTCOL(pos);
117                 clpos->end = pos;
118                 col++;
119                 if (pos >= lineend) {
120                         clpos->end = lineend;
121                         i++;
122                         break;
123                 }
124         }
125         for (; i <= ncols; i++)
126                 clist[i].start = clist[i].end = lineend;
127         if (clist[0].start < line_data)
128                 clist[0].start++;
129
130         /*
131          * We write the sort keys (concatenated) followed by the
132          * original line data (for output) as the 'keybuf' data.
133          * keybuf->length is the number of key bytes + data bytes.
134          * keybuf->offset is the number of key bytes.
135          * We add a record separator weight after the key in case
136          * (as is usual) we need to preserve the order of equal lines,
137          * and for 'sort -u'.
138          * The key itself will have had the correct weight applied.
139          */
140         keypos = keybuf->data;
141         endkey = keybuf_end - line_size - 1;
142         if (endkey <= keypos)
143                 /* No room for any key bytes */
144                 return 1;
145
146         for (ftpos = fieldtable + 1; ftpos->icol.num; ftpos++) {
147                 if ((keypos = enterfield(keypos, endkey, ftpos,
148                     fieldtable->flags)) == NULL)
149                         return (1);
150         }
151
152         keybuf->offset = keypos - keybuf->data;
153         keybuf->length = keybuf->offset + line_size;
154
155         /*
156          * Posix requires that equal keys be further sorted by the
157          * entire original record.
158          * NetBSD has (at least for some time) kept equal keys in
159          * their original order.
160          * For 'sort -u' posix_sort is unset.
161          */
162         keybuf->keylen = posix_sort ? keybuf->length : keybuf->offset;
163
164         memcpy(keypos, line_data, line_size);
165         return (0);
166 }
167
168 /*
169  * constructs a field (as defined by -k) within a key
170  */
171 static u_char *
172 enterfield(u_char *tablepos, const u_char *endkey, struct field *cur_fld,
173     int __attribute__ ((unused)) gflags)
174 {
175         u_char *start, *end, *lineend, *mask, *lweight;
176         struct column icol, tcol;
177         u_int flags;
178
179         icol = cur_fld->icol;
180         tcol = cur_fld->tcol;
181         flags = cur_fld->flags;
182         start = icol.p->start;
183         lineend = clist[ncols].end;
184         if (flags & BI)
185                 SKIP_BLANKS(start);
186         start += icol.indent;
187         start = min(start, lineend);
188
189         if (!tcol.num)
190                 end = lineend;
191         else {
192                 if (tcol.indent) {
193                         end = tcol.p->start;
194                         if (flags & BT)
195                                 SKIP_BLANKS(end);
196                         end += tcol.indent;
197                         end = min(end, lineend);
198                 } else
199                         end = tcol.p->end;
200         }
201
202         if (flags & L)
203                 return length(tablepos, endkey, start, end, flags);
204         if (flags & N)
205                 return number(tablepos, endkey, start, end, flags);
206
207         /* Bound check space - assuming nothing is skipped */
208         if (tablepos + (end - start) + 1 >= endkey)
209                 return NULL;
210
211         mask = cur_fld->mask;
212         lweight = cur_fld->weights;     
213         for (; start < end; start++) {
214                 if (!mask || mask[*start]) {
215                         *tablepos++ = lweight[*start];
216                 }
217         }
218         /* Add extra byte (absent from lweight) to sort short keys correctly */
219         *tablepos++ = lweight[REC_D];
220         return tablepos;
221 }
222
223 /*
224  * Numbers are converted to a floating point format (exponent & mantissa)
225  * so that they compare correctly as sequence of unsigned bytes.
226  * Bytes 0x00 and 0xff are used to terminate positive and negative numbers
227  * to ensure that 0.123 sorts after 0.12 and -0.123 sorts before -0.12.
228  *
229  * The first byte contain the overall sign, exponent sign and some of the
230  * exponent. These have to be ordered (-ve value, decreasing exponent),
231  * zero, (+ve value, increasing exponent).
232  *
233  * The first byte is 0x80 for zero, 0xc0 for +ve with exponent 0.
234  * -ve values are the 1's compliments (so 0x7f isn't used!).
235  *
236  * This only leaves 63 byte values for +ve exponents - which isn't enough.
237  * The largest 4 exponent values are used to hold a byte count of the
238  * number of following bytes that contain 8 exponent bits per byte,
239  * This lets us sort exponents from -2^31 to +2^31.
240  *
241  * The mantissa is stored 2 digits per byte offset by 0x40, for negative
242  * numbers the order must be reversed (they are bit inverted).
243  *
244  * Reverse sorts are done by inverting the sign of the number.
245  */
246 #define MAX_EXP_ENC  ((int)sizeof(int))
247
248 static u_char *
249 number(u_char *pos, const u_char *bufend, u_char *line, u_char *lineend,
250     int reverse)
251 {
252         int exponent = -1;
253         int had_dp = 0;
254         u_char *tline;
255         char ch;
256         unsigned int val;
257         u_char *last_nz_pos;
258         u_char negate;
259
260         if (reverse & R)
261                 negate = 0xff;
262         else
263                 negate = 0;
264
265         /* Give ourselves space for the key terminator */
266         bufend--;
267
268         /* Ensure we have enough space for the exponent */
269         if (pos + 1 + MAX_EXP_ENC > bufend)
270                 return (NULL);
271
272         SKIP_BLANKS(line);
273         if (*line == '-') {     /* set the sign */
274                 negate ^= 0xff;
275                 line++;
276         }
277         /* eat initial zeroes */
278         for (; *line == '0' && line < lineend; line++)
279                 continue;
280
281         /* calculate exponents */
282         if (*line == DECIMAL_POINT) {
283                 /* Decimal fraction */
284                 had_dp = 1;
285                 while (*++line == '0' && line < lineend)
286                         exponent--;
287         } else {
288                 /* Large (absolute) value, count digits */
289                 for (tline = line; *tline >= '0' && 
290                     *tline <= '9' && tline < lineend; tline++)
291                         exponent++;
292         }
293
294         /* If the first/next character isn't a digit, value is zero */
295         if (*line < '1' || *line > '9' || line >= lineend) {
296                 /* This may be "0", "0.00", "000" or "fubar" but sorts as 0 */
297                 /* XXX what about NaN, NAN, inf and INF */
298                 *pos++ = 0x80;
299                 return pos;
300         }
301
302         /* Maybe here we should allow for e+12 (etc) */
303
304         if (exponent < 0x40 - MAX_EXP_ENC && -exponent < 0x40 - MAX_EXP_ENC) {
305                 /* Value ok for simple encoding */
306                 /* exponent 0 is 0xc0 for +ve numbers and 0x40 for -ve ones */
307                 exponent += 0xc0;
308                 *pos++ = negate ^ exponent;
309         } else {
310                 /* Out or range for a single byte */
311                 int c, t;
312                 t = exponent > 0 ? exponent : -exponent;
313                 /* Count how many 8-bit bytes are needed */
314                 for (c = 0; ; c++) {
315                         t >>= 8;
316                         if (t == 0)
317                                 break;
318                 }
319                 /* 'c' better be 0..3 here - but probably 0..1 */
320                 /* Offset just outside valid range */
321                 t = c + 0x40 - MAX_EXP_ENC;
322                 if (exponent < 0)
323                         t = -t;
324                 *pos++ = negate ^ (t + 0xc0);
325                 /* now add each byte, most significant first */
326                 for (; c >= 0; c--)
327                         *pos++ = negate ^ (exponent >> (c * 8));
328         }
329
330         /* Finally add mantissa, 2 digits per byte */
331         for (last_nz_pos = pos; line < lineend; ) {
332                 if (pos >= bufend)
333                         return NULL;
334                 ch = *line++;
335                 val = (ch - '0') * 10;
336                 if (val > 90) {
337                         if (ch == DECIMAL_POINT && !had_dp) {
338                                 had_dp = 1;
339                                 continue;
340                         }
341                         break;
342                 }
343                 while (line < lineend) {
344                         ch = *line++;
345                         if (ch == DECIMAL_POINT && !had_dp) {
346                                 had_dp = 1;
347                                 continue;
348                         }
349                         if (ch < '0' || ch > '9')
350                                 line = lineend;
351                         else
352                                 val += ch - '0';
353                         break;
354                 }
355                 *pos++ = negate ^ (val + 0x40);
356                 if (val != 0)
357                         last_nz_pos = pos;
358         }
359
360         /* Add key terminator, deleting any trailing "00" */
361         *last_nz_pos++ = negate;
362
363         return (last_nz_pos);
364 }
365
366 static u_char *
367 length(u_char *pos, const u_char *bufend, u_char *line, u_char *lineend,
368     int flag)
369 {
370         u_char buf[32];
371         int l;
372         SKIP_BLANKS(line);
373         l = snprintf((char *)buf, sizeof(buf), "%td", lineend - line);
374         return number(pos, bufend, buf, buf + l, flag);
375 }