10fbbaa43SLionel Sambuc /* $NetBSD: fields.c,v 1.32 2010/12/18 23:09:48 christos Exp $ */ 20fbbaa43SLionel Sambuc 30fbbaa43SLionel Sambuc /*- 40fbbaa43SLionel Sambuc * Copyright (c) 2000-2003 The NetBSD Foundation, Inc. 50fbbaa43SLionel Sambuc * All rights reserved. 60fbbaa43SLionel Sambuc * 70fbbaa43SLionel Sambuc * This code is derived from software contributed to The NetBSD Foundation 80fbbaa43SLionel Sambuc * by Ben Harris and Jaromir Dolecek. 90fbbaa43SLionel Sambuc * 100fbbaa43SLionel Sambuc * Redistribution and use in source and binary forms, with or without 110fbbaa43SLionel Sambuc * modification, are permitted provided that the following conditions 120fbbaa43SLionel Sambuc * are met: 130fbbaa43SLionel Sambuc * 1. Redistributions of source code must retain the above copyright 140fbbaa43SLionel Sambuc * notice, this list of conditions and the following disclaimer. 150fbbaa43SLionel Sambuc * 2. Redistributions in binary form must reproduce the above copyright 160fbbaa43SLionel Sambuc * notice, this list of conditions and the following disclaimer in the 170fbbaa43SLionel Sambuc * documentation and/or other materials provided with the distribution. 180fbbaa43SLionel Sambuc * 190fbbaa43SLionel Sambuc * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 200fbbaa43SLionel Sambuc * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 210fbbaa43SLionel Sambuc * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 220fbbaa43SLionel Sambuc * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 230fbbaa43SLionel Sambuc * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 240fbbaa43SLionel Sambuc * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 250fbbaa43SLionel Sambuc * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 260fbbaa43SLionel Sambuc * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 270fbbaa43SLionel Sambuc * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 280fbbaa43SLionel Sambuc * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 290fbbaa43SLionel Sambuc * POSSIBILITY OF SUCH DAMAGE. 300fbbaa43SLionel Sambuc */ 310fbbaa43SLionel Sambuc 320fbbaa43SLionel Sambuc /*- 330fbbaa43SLionel Sambuc * Copyright (c) 1993 340fbbaa43SLionel Sambuc * The Regents of the University of California. All rights reserved. 350fbbaa43SLionel Sambuc * 360fbbaa43SLionel Sambuc * This code is derived from software contributed to Berkeley by 370fbbaa43SLionel Sambuc * Peter McIlroy. 380fbbaa43SLionel Sambuc * 390fbbaa43SLionel Sambuc * Redistribution and use in source and binary forms, with or without 400fbbaa43SLionel Sambuc * modification, are permitted provided that the following conditions 410fbbaa43SLionel Sambuc * are met: 420fbbaa43SLionel Sambuc * 1. Redistributions of source code must retain the above copyright 430fbbaa43SLionel Sambuc * notice, this list of conditions and the following disclaimer. 440fbbaa43SLionel Sambuc * 2. Redistributions in binary form must reproduce the above copyright 450fbbaa43SLionel Sambuc * notice, this list of conditions and the following disclaimer in the 460fbbaa43SLionel Sambuc * documentation and/or other materials provided with the distribution. 470fbbaa43SLionel Sambuc * 3. Neither the name of the University nor the names of its contributors 480fbbaa43SLionel Sambuc * may be used to endorse or promote products derived from this software 490fbbaa43SLionel Sambuc * without specific prior written permission. 500fbbaa43SLionel Sambuc * 510fbbaa43SLionel Sambuc * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 520fbbaa43SLionel Sambuc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 530fbbaa43SLionel Sambuc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 540fbbaa43SLionel Sambuc * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 550fbbaa43SLionel Sambuc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 560fbbaa43SLionel Sambuc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 570fbbaa43SLionel Sambuc * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 580fbbaa43SLionel Sambuc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 590fbbaa43SLionel Sambuc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 600fbbaa43SLionel Sambuc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 610fbbaa43SLionel Sambuc * SUCH DAMAGE. 620fbbaa43SLionel Sambuc */ 630fbbaa43SLionel Sambuc 640fbbaa43SLionel Sambuc /* Subroutines to generate sort keys. */ 650fbbaa43SLionel Sambuc 660fbbaa43SLionel Sambuc #include "sort.h" 670fbbaa43SLionel Sambuc 680fbbaa43SLionel Sambuc __RCSID("$NetBSD: fields.c,v 1.32 2010/12/18 23:09:48 christos Exp $"); 690fbbaa43SLionel Sambuc 700fbbaa43SLionel Sambuc #define SKIP_BLANKS(ptr) { \ 710fbbaa43SLionel Sambuc if (BLANK & d_mask[*(ptr)]) \ 720fbbaa43SLionel Sambuc while (BLANK & d_mask[*(++(ptr))]); \ 730fbbaa43SLionel Sambuc } 740fbbaa43SLionel Sambuc 750fbbaa43SLionel Sambuc #define NEXTCOL(pos) { \ 760fbbaa43SLionel Sambuc if (!SEP_FLAG) \ 770fbbaa43SLionel Sambuc while (BLANK & l_d_mask[*(++pos)]); \ 780fbbaa43SLionel Sambuc while ((*(pos+1) != '\0') && !((FLD_D | REC_D_F) & l_d_mask[*++pos]));\ 790fbbaa43SLionel Sambuc } 800fbbaa43SLionel Sambuc 810fbbaa43SLionel Sambuc static u_char *enterfield(u_char *, const u_char *, struct field *, int); 820fbbaa43SLionel Sambuc static u_char *number(u_char *, const u_char *, u_char *, u_char *, int); 830fbbaa43SLionel Sambuc static u_char *length(u_char *, const u_char *, u_char *, u_char *, int); 840fbbaa43SLionel Sambuc 85*e286ccc0SBen Gras #ifdef __minix 86*e286ccc0SBen Gras static u_char *numhex(u_char *, const u_char *, u_char *, u_char *, int); 87*e286ccc0SBen Gras #endif 88*e286ccc0SBen Gras 890fbbaa43SLionel Sambuc #define DECIMAL_POINT '.' 900fbbaa43SLionel Sambuc 910fbbaa43SLionel Sambuc /* 920fbbaa43SLionel Sambuc * constructs sort key with leading recheader, followed by the key, 930fbbaa43SLionel Sambuc * followed by the original line. 940fbbaa43SLionel Sambuc */ 950fbbaa43SLionel Sambuc length_t 960fbbaa43SLionel Sambuc enterkey(RECHEADER *keybuf, const u_char *keybuf_end, u_char *line_data, 970fbbaa43SLionel Sambuc size_t line_size, struct field fieldtable[]) 980fbbaa43SLionel Sambuc /* keybuf: pointer to start of key */ 990fbbaa43SLionel Sambuc { 1000fbbaa43SLionel Sambuc int i; 1010fbbaa43SLionel Sambuc u_char *l_d_mask; 1020fbbaa43SLionel Sambuc u_char *lineend, *pos; 1030fbbaa43SLionel Sambuc const u_char *endkey; 1040fbbaa43SLionel Sambuc u_char *keypos; 1050fbbaa43SLionel Sambuc struct coldesc *clpos; 1060fbbaa43SLionel Sambuc int col = 1; 1070fbbaa43SLionel Sambuc struct field *ftpos; 1080fbbaa43SLionel Sambuc 1090fbbaa43SLionel Sambuc l_d_mask = d_mask; 1100fbbaa43SLionel Sambuc pos = line_data - 1; 1110fbbaa43SLionel Sambuc lineend = line_data + line_size-1; 1120fbbaa43SLionel Sambuc /* don't include rec_delimiter */ 1130fbbaa43SLionel Sambuc 1140fbbaa43SLionel Sambuc for (i = 0; i < ncols; i++) { 1150fbbaa43SLionel Sambuc clpos = clist + i; 1160fbbaa43SLionel Sambuc for (; (col < clpos->num) && (pos < lineend); col++) { 1170fbbaa43SLionel Sambuc NEXTCOL(pos); 1180fbbaa43SLionel Sambuc } 1190fbbaa43SLionel Sambuc if (pos >= lineend) 1200fbbaa43SLionel Sambuc break; 1210fbbaa43SLionel Sambuc clpos->start = SEP_FLAG ? pos + 1 : pos; 1220fbbaa43SLionel Sambuc NEXTCOL(pos); 1230fbbaa43SLionel Sambuc clpos->end = pos; 1240fbbaa43SLionel Sambuc col++; 1250fbbaa43SLionel Sambuc if (pos >= lineend) { 1260fbbaa43SLionel Sambuc clpos->end = lineend; 1270fbbaa43SLionel Sambuc i++; 1280fbbaa43SLionel Sambuc break; 1290fbbaa43SLionel Sambuc } 1300fbbaa43SLionel Sambuc } 1310fbbaa43SLionel Sambuc for (; i <= ncols; i++) 1320fbbaa43SLionel Sambuc clist[i].start = clist[i].end = lineend; 1330fbbaa43SLionel Sambuc if (clist[0].start < line_data) 1340fbbaa43SLionel Sambuc clist[0].start++; 1350fbbaa43SLionel Sambuc 1360fbbaa43SLionel Sambuc /* 1370fbbaa43SLionel Sambuc * We write the sort keys (concatenated) followed by the 1380fbbaa43SLionel Sambuc * original line data (for output) as the 'keybuf' data. 1390fbbaa43SLionel Sambuc * keybuf->length is the number of key bytes + data bytes. 1400fbbaa43SLionel Sambuc * keybuf->offset is the number of key bytes. 1410fbbaa43SLionel Sambuc * We add a record separator weight after the key in case 1420fbbaa43SLionel Sambuc * (as is usual) we need to preserve the order of equal lines, 1430fbbaa43SLionel Sambuc * and for 'sort -u'. 1440fbbaa43SLionel Sambuc * The key itself will have had the correct weight applied. 1450fbbaa43SLionel Sambuc */ 1460fbbaa43SLionel Sambuc keypos = keybuf->data; 1470fbbaa43SLionel Sambuc endkey = keybuf_end - line_size - 1; 1480fbbaa43SLionel Sambuc if (endkey <= keypos) 1490fbbaa43SLionel Sambuc /* No room for any key bytes */ 1500fbbaa43SLionel Sambuc return 1; 1510fbbaa43SLionel Sambuc 1520fbbaa43SLionel Sambuc for (ftpos = fieldtable + 1; ftpos->icol.num; ftpos++) { 1530fbbaa43SLionel Sambuc if ((keypos = enterfield(keypos, endkey, ftpos, 1540fbbaa43SLionel Sambuc fieldtable->flags)) == NULL) 1550fbbaa43SLionel Sambuc return (1); 1560fbbaa43SLionel Sambuc } 1570fbbaa43SLionel Sambuc 1580fbbaa43SLionel Sambuc keybuf->offset = keypos - keybuf->data; 1590fbbaa43SLionel Sambuc keybuf->length = keybuf->offset + line_size; 1600fbbaa43SLionel Sambuc 1610fbbaa43SLionel Sambuc /* 1620fbbaa43SLionel Sambuc * Posix requires that equal keys be further sorted by the 1630fbbaa43SLionel Sambuc * entire original record. 1640fbbaa43SLionel Sambuc * NetBSD has (at least for some time) kept equal keys in 1650fbbaa43SLionel Sambuc * their original order. 1660fbbaa43SLionel Sambuc * For 'sort -u' posix_sort is unset. 1670fbbaa43SLionel Sambuc */ 1680fbbaa43SLionel Sambuc keybuf->keylen = posix_sort ? keybuf->length : keybuf->offset; 1690fbbaa43SLionel Sambuc 1700fbbaa43SLionel Sambuc memcpy(keypos, line_data, line_size); 1710fbbaa43SLionel Sambuc return (0); 1720fbbaa43SLionel Sambuc } 1730fbbaa43SLionel Sambuc 1740fbbaa43SLionel Sambuc /* 1750fbbaa43SLionel Sambuc * constructs a field (as defined by -k) within a key 1760fbbaa43SLionel Sambuc */ 1770fbbaa43SLionel Sambuc static u_char * 1780fbbaa43SLionel Sambuc enterfield(u_char *tablepos, const u_char *endkey, struct field *cur_fld, 1790fbbaa43SLionel Sambuc int gflags) 1800fbbaa43SLionel Sambuc { 1810fbbaa43SLionel Sambuc u_char *start, *end, *lineend, *mask, *lweight; 1820fbbaa43SLionel Sambuc struct column icol, tcol; 1830fbbaa43SLionel Sambuc u_int flags; 1840fbbaa43SLionel Sambuc 1850fbbaa43SLionel Sambuc icol = cur_fld->icol; 1860fbbaa43SLionel Sambuc tcol = cur_fld->tcol; 1870fbbaa43SLionel Sambuc flags = cur_fld->flags; 1880fbbaa43SLionel Sambuc start = icol.p->start; 1890fbbaa43SLionel Sambuc lineend = clist[ncols].end; 1900fbbaa43SLionel Sambuc if (flags & BI) 1910fbbaa43SLionel Sambuc SKIP_BLANKS(start); 1920fbbaa43SLionel Sambuc start += icol.indent; 1930fbbaa43SLionel Sambuc start = min(start, lineend); 1940fbbaa43SLionel Sambuc 1950fbbaa43SLionel Sambuc if (!tcol.num) 1960fbbaa43SLionel Sambuc end = lineend; 1970fbbaa43SLionel Sambuc else { 1980fbbaa43SLionel Sambuc if (tcol.indent) { 1990fbbaa43SLionel Sambuc end = tcol.p->start; 2000fbbaa43SLionel Sambuc if (flags & BT) 2010fbbaa43SLionel Sambuc SKIP_BLANKS(end); 2020fbbaa43SLionel Sambuc end += tcol.indent; 2030fbbaa43SLionel Sambuc end = min(end, lineend); 2040fbbaa43SLionel Sambuc } else 2050fbbaa43SLionel Sambuc end = tcol.p->end; 2060fbbaa43SLionel Sambuc } 2070fbbaa43SLionel Sambuc 2080fbbaa43SLionel Sambuc if (flags & L) 2090fbbaa43SLionel Sambuc return length(tablepos, endkey, start, end, flags); 2100fbbaa43SLionel Sambuc if (flags & N) 2110fbbaa43SLionel Sambuc return number(tablepos, endkey, start, end, flags); 212*e286ccc0SBen Gras #ifdef __minix 213*e286ccc0SBen Gras if (flags & X) 214*e286ccc0SBen Gras return numhex(tablepos, endkey, start, end, flags); 215*e286ccc0SBen Gras #endif 2160fbbaa43SLionel Sambuc 2170fbbaa43SLionel Sambuc /* Bound check space - assuming nothing is skipped */ 2180fbbaa43SLionel Sambuc if (tablepos + (end - start) + 1 >= endkey) 2190fbbaa43SLionel Sambuc return NULL; 2200fbbaa43SLionel Sambuc 2210fbbaa43SLionel Sambuc mask = cur_fld->mask; 2220fbbaa43SLionel Sambuc lweight = cur_fld->weights; 2230fbbaa43SLionel Sambuc for (; start < end; start++) { 2240fbbaa43SLionel Sambuc if (!mask || mask[*start]) { 2250fbbaa43SLionel Sambuc *tablepos++ = lweight[*start]; 2260fbbaa43SLionel Sambuc } 2270fbbaa43SLionel Sambuc } 2280fbbaa43SLionel Sambuc /* Add extra byte (absent from lweight) to sort short keys correctly */ 2290fbbaa43SLionel Sambuc *tablepos++ = lweight[REC_D]; 2300fbbaa43SLionel Sambuc return tablepos; 2310fbbaa43SLionel Sambuc } 2320fbbaa43SLionel Sambuc 2330fbbaa43SLionel Sambuc /* 2340fbbaa43SLionel Sambuc * Numbers are converted to a floating point format (exponent & mantissa) 2350fbbaa43SLionel Sambuc * so that they compare correctly as sequence of unsigned bytes. 2360fbbaa43SLionel Sambuc * Bytes 0x00 and 0xff are used to terminate positive and negative numbers 2370fbbaa43SLionel Sambuc * to ensure that 0.123 sorts after 0.12 and -0.123 sorts before -0.12. 2380fbbaa43SLionel Sambuc * 2390fbbaa43SLionel Sambuc * The first byte contain the overall sign, exponent sign and some of the 2400fbbaa43SLionel Sambuc * exponent. These have to be ordered (-ve value, decreasing exponent), 2410fbbaa43SLionel Sambuc * zero, (+ve value, increasing exponent). 2420fbbaa43SLionel Sambuc * 2430fbbaa43SLionel Sambuc * The first byte is 0x80 for zero, 0xc0 for +ve with exponent 0. 2440fbbaa43SLionel Sambuc * -ve values are the 1's compliments (so 0x7f isn't used!). 2450fbbaa43SLionel Sambuc * 2460fbbaa43SLionel Sambuc * This only leaves 63 byte values for +ve exponents - which isn't enough. 2470fbbaa43SLionel Sambuc * The largest 4 exponent values are used to hold a byte count of the 2480fbbaa43SLionel Sambuc * number of following bytes that contain 8 exponent bits per byte, 2490fbbaa43SLionel Sambuc * This lets us sort exponents from -2^31 to +2^31. 2500fbbaa43SLionel Sambuc * 2510fbbaa43SLionel Sambuc * The mantissa is stored 2 digits per byte offset by 0x40, for negative 2520fbbaa43SLionel Sambuc * numbers the order must be reversed (they are bit inverted). 2530fbbaa43SLionel Sambuc * 2540fbbaa43SLionel Sambuc * Reverse sorts are done by inverting the sign of the number. 2550fbbaa43SLionel Sambuc */ 2560fbbaa43SLionel Sambuc #define MAX_EXP_ENC ((int)sizeof(int)) 2570fbbaa43SLionel Sambuc 2580fbbaa43SLionel Sambuc static u_char * 2590fbbaa43SLionel Sambuc number(u_char *pos, const u_char *bufend, u_char *line, u_char *lineend, 2600fbbaa43SLionel Sambuc int reverse) 2610fbbaa43SLionel Sambuc { 2620fbbaa43SLionel Sambuc int exponent = -1; 2630fbbaa43SLionel Sambuc int had_dp = 0; 2640fbbaa43SLionel Sambuc u_char *tline; 2650fbbaa43SLionel Sambuc char ch; 2660fbbaa43SLionel Sambuc unsigned int val; 2670fbbaa43SLionel Sambuc u_char *last_nz_pos; 2680fbbaa43SLionel Sambuc u_char negate; 2690fbbaa43SLionel Sambuc 2700fbbaa43SLionel Sambuc if (reverse & R) 2710fbbaa43SLionel Sambuc negate = 0xff; 2720fbbaa43SLionel Sambuc else 2730fbbaa43SLionel Sambuc negate = 0; 2740fbbaa43SLionel Sambuc 2750fbbaa43SLionel Sambuc /* Give ourselves space for the key terminator */ 2760fbbaa43SLionel Sambuc bufend--; 2770fbbaa43SLionel Sambuc 2780fbbaa43SLionel Sambuc /* Ensure we have enough space for the exponent */ 2790fbbaa43SLionel Sambuc if (pos + 1 + MAX_EXP_ENC > bufend) 2800fbbaa43SLionel Sambuc return (NULL); 2810fbbaa43SLionel Sambuc 2820fbbaa43SLionel Sambuc SKIP_BLANKS(line); 2830fbbaa43SLionel Sambuc if (*line == '-') { /* set the sign */ 2840fbbaa43SLionel Sambuc negate ^= 0xff; 2850fbbaa43SLionel Sambuc line++; 2860fbbaa43SLionel Sambuc } 2870fbbaa43SLionel Sambuc /* eat initial zeroes */ 2880fbbaa43SLionel Sambuc for (; *line == '0' && line < lineend; line++) 2890fbbaa43SLionel Sambuc continue; 2900fbbaa43SLionel Sambuc 2910fbbaa43SLionel Sambuc /* calculate exponents */ 2920fbbaa43SLionel Sambuc if (*line == DECIMAL_POINT) { 2930fbbaa43SLionel Sambuc /* Decimal fraction */ 2940fbbaa43SLionel Sambuc had_dp = 1; 2950fbbaa43SLionel Sambuc while (*++line == '0' && line < lineend) 2960fbbaa43SLionel Sambuc exponent--; 2970fbbaa43SLionel Sambuc } else { 2980fbbaa43SLionel Sambuc /* Large (absolute) value, count digits */ 2990fbbaa43SLionel Sambuc for (tline = line; *tline >= '0' && 3000fbbaa43SLionel Sambuc *tline <= '9' && tline < lineend; tline++) 3010fbbaa43SLionel Sambuc exponent++; 3020fbbaa43SLionel Sambuc } 3030fbbaa43SLionel Sambuc 3040fbbaa43SLionel Sambuc /* If the first/next character isn't a digit, value is zero */ 3050fbbaa43SLionel Sambuc if (*line < '1' || *line > '9' || line >= lineend) { 3060fbbaa43SLionel Sambuc /* This may be "0", "0.00", "000" or "fubar" but sorts as 0 */ 3070fbbaa43SLionel Sambuc /* XXX what about NaN, NAN, inf and INF */ 3080fbbaa43SLionel Sambuc *pos++ = 0x80; 3090fbbaa43SLionel Sambuc return pos; 3100fbbaa43SLionel Sambuc } 3110fbbaa43SLionel Sambuc 3120fbbaa43SLionel Sambuc /* Maybe here we should allow for e+12 (etc) */ 3130fbbaa43SLionel Sambuc 3140fbbaa43SLionel Sambuc if (exponent < 0x40 - MAX_EXP_ENC && -exponent < 0x40 - MAX_EXP_ENC) { 3150fbbaa43SLionel Sambuc /* Value ok for simple encoding */ 3160fbbaa43SLionel Sambuc /* exponent 0 is 0xc0 for +ve numbers and 0x40 for -ve ones */ 3170fbbaa43SLionel Sambuc exponent += 0xc0; 3180fbbaa43SLionel Sambuc *pos++ = negate ^ exponent; 3190fbbaa43SLionel Sambuc } else { 3200fbbaa43SLionel Sambuc /* Out or range for a single byte */ 3210fbbaa43SLionel Sambuc int c, t; 3220fbbaa43SLionel Sambuc t = exponent > 0 ? exponent : -exponent; 3230fbbaa43SLionel Sambuc /* Count how many 8-bit bytes are needed */ 3240fbbaa43SLionel Sambuc for (c = 0; ; c++) { 3250fbbaa43SLionel Sambuc t >>= 8; 3260fbbaa43SLionel Sambuc if (t == 0) 3270fbbaa43SLionel Sambuc break; 3280fbbaa43SLionel Sambuc } 3290fbbaa43SLionel Sambuc /* 'c' better be 0..3 here - but probably 0..1 */ 3300fbbaa43SLionel Sambuc /* Offset just outside valid range */ 3310fbbaa43SLionel Sambuc t = c + 0x40 - MAX_EXP_ENC; 3320fbbaa43SLionel Sambuc if (exponent < 0) 3330fbbaa43SLionel Sambuc t = -t; 3340fbbaa43SLionel Sambuc *pos++ = negate ^ (t + 0xc0); 3350fbbaa43SLionel Sambuc /* now add each byte, most significant first */ 3360fbbaa43SLionel Sambuc for (; c >= 0; c--) 3370fbbaa43SLionel Sambuc *pos++ = negate ^ (exponent >> (c * 8)); 3380fbbaa43SLionel Sambuc } 3390fbbaa43SLionel Sambuc 3400fbbaa43SLionel Sambuc /* Finally add mantissa, 2 digits per byte */ 3410fbbaa43SLionel Sambuc for (last_nz_pos = pos; line < lineend; ) { 3420fbbaa43SLionel Sambuc if (pos >= bufend) 3430fbbaa43SLionel Sambuc return NULL; 3440fbbaa43SLionel Sambuc ch = *line++; 3450fbbaa43SLionel Sambuc val = (ch - '0') * 10; 3460fbbaa43SLionel Sambuc if (val > 90) { 3470fbbaa43SLionel Sambuc if (ch == DECIMAL_POINT && !had_dp) { 3480fbbaa43SLionel Sambuc had_dp = 1; 3490fbbaa43SLionel Sambuc continue; 3500fbbaa43SLionel Sambuc } 3510fbbaa43SLionel Sambuc break; 3520fbbaa43SLionel Sambuc } 3530fbbaa43SLionel Sambuc while (line < lineend) { 3540fbbaa43SLionel Sambuc ch = *line++; 3550fbbaa43SLionel Sambuc if (ch == DECIMAL_POINT && !had_dp) { 3560fbbaa43SLionel Sambuc had_dp = 1; 3570fbbaa43SLionel Sambuc continue; 3580fbbaa43SLionel Sambuc } 3590fbbaa43SLionel Sambuc if (ch < '0' || ch > '9') 3600fbbaa43SLionel Sambuc line = lineend; 3610fbbaa43SLionel Sambuc else 3620fbbaa43SLionel Sambuc val += ch - '0'; 3630fbbaa43SLionel Sambuc break; 3640fbbaa43SLionel Sambuc } 3650fbbaa43SLionel Sambuc *pos++ = negate ^ (val + 0x40); 3660fbbaa43SLionel Sambuc if (val != 0) 3670fbbaa43SLionel Sambuc last_nz_pos = pos; 3680fbbaa43SLionel Sambuc } 3690fbbaa43SLionel Sambuc 3700fbbaa43SLionel Sambuc /* Add key terminator, deleting any trailing "00" */ 3710fbbaa43SLionel Sambuc *last_nz_pos++ = negate; 3720fbbaa43SLionel Sambuc 3730fbbaa43SLionel Sambuc return (last_nz_pos); 3740fbbaa43SLionel Sambuc } 3750fbbaa43SLionel Sambuc 3760fbbaa43SLionel Sambuc static u_char * 3770fbbaa43SLionel Sambuc length(u_char *pos, const u_char *bufend, u_char *line, u_char *lineend, 3780fbbaa43SLionel Sambuc int flag) 3790fbbaa43SLionel Sambuc { 3800fbbaa43SLionel Sambuc u_char buf[32]; 3810fbbaa43SLionel Sambuc int l; 3820fbbaa43SLionel Sambuc SKIP_BLANKS(line); 3830fbbaa43SLionel Sambuc l = snprintf((char *)buf, sizeof(buf), "%td", lineend - line); 3840fbbaa43SLionel Sambuc return number(pos, bufend, buf, buf + l, flag); 3850fbbaa43SLionel Sambuc } 386*e286ccc0SBen Gras 387*e286ccc0SBen Gras #ifdef __minix 388*e286ccc0SBen Gras static u_char * 389*e286ccc0SBen Gras numhex(u_char *pos, const u_char *bufend, u_char *line, u_char *lineend, 390*e286ccc0SBen Gras int flag) 391*e286ccc0SBen Gras { 392*e286ccc0SBen Gras u_char buf[32]; 393*e286ccc0SBen Gras int64_t n = 0; 394*e286ccc0SBen Gras int l; 395*e286ccc0SBen Gras SKIP_BLANKS(line); 396*e286ccc0SBen Gras sscanf((const char *) pos, "%lx", &n); 397*e286ccc0SBen Gras l = snprintf((char *)buf, sizeof(buf), "%lld", n); 398*e286ccc0SBen Gras return number(pos, bufend, buf, buf + l, flag); 399*e286ccc0SBen Gras } 400*e286ccc0SBen Gras #endif 401