|
|
1.1 root 1: /* Copyright 1990, AT&T Bell Labs */
2:
3: /* Canonicalize the number string pointed to by dp, of length
4: len. Put the result in kp.
5:
6: A field of length zero, or all blank, is regarded as 0.
7: Over/underflow is rendered as huge or zero and properly signed.
8: It happens 1e+-1022.
9:
10: Canonicalized strings may be compared as strings of unsigned
11: chars. For good measure, a canonical string has no zero bytes.
12:
13: Syntax: optionally signed floating point, with optional
14: leading spaces. A syntax deviation ends the number.
15:
16: Form of output: packed in 4-bit nibbles. First
17: 3 nibbles count the number N of significant digits
18: before the decimal point. The quantity actually stored
19: is 2048+sign(x)*(N+1024). Further nibbles contain
20: 1 decimal digit d each, stored as d+2 if x is positive
21: and as 10-d if x is negative. Leading and trailing
22: zeros are stripped, and a trailing "digit" d = -1
23: is appended. (The trailing digit handled like all others,
24: so encodes as 1 or 0xb according to the sign of x.)
25: An odd number of nibbles is padded with zero.
26:
27: Buglet: overflow is reported if output is exactly filled.
28:
29: */
30: #include "fsort.h"
31:
32: #define encode(x) (neg? 10-(x): (x)+2)
33: #define putdig(x) (nib? (*dig=encode(x)<<4, nib=0): \
34: (*dig++|=encode(x), nib=1))
35:
36: static int gflag;
37:
38: int
39: gcode(uchar *dp, uchar*kp, int len, struct field *f)
40: {
41: int ret;
42: gflag++;
43: ret = ncode(dp, kp, len, f);
44: gflag--;
45: return ret;
46: }
47:
48: int
49: ncode(uchar *dp, uchar*kp, int len, struct field *f)
50: {
51: uchar *dig = kp + 1; /* byte for next digit */
52: int nib = 0; /* high nibble 1, low nibble 0 */
53: uchar *cp = dp;
54: uchar *ep = cp + len; /* end pointer */
55: int zeros = 0; /* count zeros seen but not installed */
56: int sigdig = 1024;
57: int neg = f->rflag; /* 0 for +, 1 for - */
58: int decimal = 0;
59: int n, inv;
60:
61: kp[1] = 0;
62: for( ; cp<ep ; cp++) /* eat blanks */
63: if(*cp!=' ' && *cp!='\t')
64: break;
65: if(cp < ep) /* eat sign */
66: switch(*cp) {
67: case '-':
68: neg ^= 1;
69: case '+':
70: cp++;
71: }
72: for( ; cp<ep; cp++) /* eat leading zeros */
73: if(*cp != '0')
74: break;
75: if(*cp=='.' && cp<ep) { /* decimal point among lead zeros */
76: decimal++;
77: for(cp++; cp<ep; cp++) {
78: if(*cp != '0')
79: break;
80: sigdig--;
81: }
82: }
83: if(*cp>'9' || *cp<'0' || cp>=ep) { /* no sig digit*/
84: sigdig = 0;
85: neg = 0;
86: goto retzero;
87: }
88: for( ; cp<ep; cp++) {
89: switch(*cp) {
90: default:
91: goto out;
92: case '.':
93: if(decimal)
94: goto out;
95: decimal++;
96: continue;
97: case '0':
98: zeros++;
99: if(!decimal)
100: sigdig++;
101: continue;
102: case '1': case '2': case '3': case '4': case '5':
103: case '6': case '7': case '8': case '9':
104: for( ; zeros>0; zeros--)
105: putdig(0);
106: n = *cp - '0';
107: putdig(n);
108: if(!decimal)
109: sigdig++;
110: continue;
111: case 'e':
112: case 'E':
113: if(!gflag)
114: goto out;
115: inv = 1;
116: if(cp < ep) switch(*++cp) {
117: case '-':
118: inv = -1;
119: case '+':
120: cp++;
121: }
122: if(*cp>'9' || *cp<'0' || cp>=ep)
123: goto out;
124: for(n=0; cp<ep; cp++) {
125: int c = *cp;
126: if(c<'0' || c>'9')
127: break;
128: if((n = 10*n+c-'0') >= 0)
129: continue;
130: sigdig = 2047*inv;
131: goto out;
132: }
133: sigdig += n*inv;
134: goto out;
135: }
136: }
137: out:
138: if(sigdig<0 || sigdig>=2047) {
139: sigdig = sigdig<0? 0: 2047;
140: warn("numeric field overflow", (char*)dp, len);
141: dig = kp + 1;
142: *dig = 0;
143: nib = 0;
144: }
145: retzero:
146: if(neg)
147: sigdig = 2048 - sigdig;
148: else
149: sigdig = 2048 + sigdig;
150: kp[0] = sigdig >> 4;
151: kp[1] |= sigdig << 4;
152: putdig(-1);
153: return dig - kp + 1 - nib;
154: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.