| 9 |
9 |
| 10 #define MAX_MANTISSA 10 /* should be enough for our needs */ |
10 #define MAX_MANTISSA 10 /* should be enough for our needs */ |
| 11 #define ULONG_SIZE (sizeof(ulong)*8) |
11 #define ULONG_SIZE (sizeof(ulong)*8) |
| 12 |
12 |
| 13 enum{ |
13 enum{ |
| 14 NPNUM_INT, |
14 NPNUM_INT, |
| 15 NPNUM_FLOAT |
15 NPNUM_FLOAT |
| 16 }; |
16 }; |
| 17 |
17 |
| 18 #ifdef NP_SIMPLE_IMPL |
18 #ifdef NP_SIMPLE_IMPL |
| 19 |
19 |
| 20 typedef struct _NPNum{ |
20 typedef struct _NPNum{ |
| 21 int type; |
21 int type; |
| 22 int base; |
22 int base; |
| 23 bool negative; |
23 bool negative; |
| 24 double fval; |
24 double fval; |
| 25 ulong ival; |
25 ulong ival; |
| 26 } NPNum; |
26 } NPNum; |
| 27 |
27 |
| 28 #define NUM_INIT {0, 0, 0, 0.0, 0} |
28 #define NUM_INIT {0, 0, 0, 0.0, 0} |
| 29 |
29 |
| 30 static int npnum_mulbase_add(NPNum *num, long base, long v) |
30 static int npnum_mulbase_add(NPNum *num, long base, long v) |
| 31 { |
31 { |
| 32 double iold=num->ival; |
32 double iold=num->ival; |
| 33 |
33 |
| 34 num->fval=num->fval*base+(double)v; |
34 num->fval=num->fval*base+(double)v; |
| 35 |
35 |
| 36 num->ival*=base; |
36 num->ival*=base; |
| 37 |
37 |
| 38 if(num->ival<iold) |
38 if(num->ival<iold) |
| 39 num->type=NPNUM_FLOAT; |
39 num->type=NPNUM_FLOAT; |
| 40 |
40 |
| 41 num->ival+=v; |
41 num->ival+=v; |
| 42 |
42 |
| 43 return 0; |
43 return 0; |
| 44 } |
44 } |
| 45 |
45 |
| 46 #else /* NP_SIMPLE_IMPL */ |
46 #else /* NP_SIMPLE_IMPL */ |
| 47 |
47 |
| 48 typedef struct _NPNum{ |
48 typedef struct _NPNum{ |
| 49 unsigned char nmantissa; |
49 unsigned char nmantissa; |
| 50 int type; |
50 int type; |
| 51 int base; |
51 int base; |
| 52 bool negative; |
52 bool negative; |
| 53 ulong mantissa[MAX_MANTISSA]; |
53 ulong mantissa[MAX_MANTISSA]; |
| 54 long exponent; |
54 long exponent; |
| 55 } NPNum; |
55 } NPNum; |
| 56 |
56 |
| 57 #define NUM_INIT {0, 0, 0, 0, {0,}, 0} |
57 #define NUM_INIT {0, 0, 0, 0, {0,}, 0} |
| 58 |
58 |
| 59 #define ADD_EXP(NUM, X) (NUM)->exponent+=(X); |
59 #define ADD_EXP(NUM, X) (NUM)->exponent+=(X); |
| 62 #define NP_I386_ASM |
62 #define NP_I386_ASM |
| 63 #endif |
63 #endif |
| 64 |
64 |
| 65 static int npnum_mulbase_add(NPNum *num, long base, long v) |
65 static int npnum_mulbase_add(NPNum *num, long base, long v) |
| 66 { |
66 { |
| 67 long i, j; |
67 long i, j; |
| 68 ulong overflow; |
68 ulong overflow; |
| 69 #ifndef NP_I386_ASM |
69 #ifndef NP_I386_ASM |
| 70 ulong val; |
70 ulong val; |
| 71 #endif |
71 #endif |
| 72 |
72 |
| 73 for(i=num->nmantissa;i>=0;i--){ |
73 for(i=num->nmantissa;i>=0;i--){ |
| 74 #ifdef NP_I386_ASM |
74 #ifdef NP_I386_ASM |
| 75 __asm__("mul %4\n" |
75 __asm__("mul %4\n" |
| 76 : "=a" (num->mantissa[i]), "=d" (overflow) |
76 : "=a" (num->mantissa[i]), "=d" (overflow) |
| 77 : "0" (num->mantissa[i]), "1" (0), "q" (base) |
77 : "0" (num->mantissa[i]), "1" (0), "q" (base) |
| 78 : "eax", "edx"); |
78 : "eax", "edx"); |
| 79 #else |
79 #else |
| 80 overflow=0; |
80 overflow=0; |
| 81 val=num->mantissa[i]; |
81 val=num->mantissa[i]; |
| 82 |
82 |
| 83 if(val<ULONG_MAX/base){ |
83 if(val<ULONG_MAX/base){ |
| 84 val*=base; |
84 val*=base; |
| 85 }else if(val){ |
85 }else if(val){ |
| 86 ulong tmp=val; |
86 ulong tmp=val; |
| 87 ulong old=val; |
87 ulong old=val; |
| 88 for(j=0; j<base; j++){ |
88 for(j=0; j<base; j++){ |
| 89 val+=tmp; |
89 val+=tmp; |
| 90 if(val<=old) |
90 if(val<=old) |
| 91 overflow++; |
91 overflow++; |
| 92 old=val; |
92 old=val; |
| 93 } |
93 } |
| 94 } |
94 } |
| 95 num->mantissa[i]=val; |
95 num->mantissa[i]=val; |
| 96 #endif |
96 #endif |
| 97 if(overflow){ |
97 if(overflow){ |
| 98 if(i==num->nmantissa){ |
98 if(i==num->nmantissa){ |
| 99 if(num->nmantissa==MAX_MANTISSA) |
99 if(num->nmantissa==MAX_MANTISSA) |
| 100 return E_TOKZ_TOOBIG; |
100 return E_TOKZ_TOOBIG; |
| 101 num->nmantissa++; |
101 num->nmantissa++; |
| 102 } |
102 } |
| 103 num->mantissa[i+1]+=overflow; |
103 num->mantissa[i+1]+=overflow; |
| 104 } |
104 } |
| 105 } |
105 } |
| 106 num->mantissa[0]+=v; |
106 num->mantissa[0]+=v; |
| 107 |
107 |
| 108 return 0; |
108 return 0; |
| 109 } |
109 } |
| 110 |
110 |
| 111 #undef NP_I386_ASM |
111 #undef NP_I386_ASM |
| 112 |
112 |
| 113 #endif /* NP_SIMPLE_IMPL */ |
113 #endif /* NP_SIMPLE_IMPL */ |
| 116 /* */ |
116 /* */ |
| 117 |
117 |
| 118 |
118 |
| 119 static bool is_end(int c) |
119 static bool is_end(int c) |
| 120 { |
120 { |
| 121 /* oops... EOF was missing */ |
121 /* oops... EOF was missing */ |
| 122 return (c==EOF || (c!='.' && ispunct(c)) || isspace(c) || iscntrl(c)); |
122 return (c==EOF || (c!='.' && ispunct(c)) || isspace(c) || iscntrl(c)); |
| 123 } |
123 } |
| 124 |
124 |
| 125 |
125 |
| 126 /* */ |
126 /* */ |
| 127 |
127 |
| 128 |
128 |
| 129 static int parse_exponent(NPNum *num, Tokenizer *tokz, int c) |
129 static int parse_exponent(NPNum *num, Tokenizer *tokz, int c) |
| 130 { |
130 { |
| 131 long exp=0; |
131 long exp=0; |
| 132 bool neg=FALSE; |
132 bool neg=FALSE; |
| 133 int err=0; |
133 int err=0; |
| 134 |
134 |
| 135 c=GETCH(); |
135 c=GETCH(); |
| 136 |
136 |
| 137 if(c=='-' || c=='+'){ |
137 if(c=='-' || c=='+'){ |
| 138 if(c=='-') |
138 if(c=='-') |
| 139 neg=TRUE; |
139 neg=TRUE; |
| 140 c=GETCH(); |
140 c=GETCH(); |
| 141 } |
141 } |
| 142 |
142 |
| 143 for(; 1; c=GETCH()){ |
143 for(; 1; c=GETCH()){ |
| 144 if(isdigit(c)){ |
144 if(isdigit(c)){ |
| 145 exp*=10; |
145 exp*=10; |
| 146 exp+=c-'0'; |
146 exp+=c-'0'; |
| 147 }else if(is_end(c)){ |
147 }else if(is_end(c)){ |
| 148 UNGETCH(c); |
148 UNGETCH(c); |
| 149 break; |
149 break; |
| 150 }else{ |
150 }else{ |
| 151 err=E_TOKZ_NUMFMT; |
151 err=E_TOKZ_NUMFMT; |
| 152 } |
152 } |
| 153 } |
153 } |
| 154 |
154 |
| 155 if(neg) |
155 if(neg) |
| 156 exp*=-1; |
156 exp*=-1; |
| 157 |
157 |
| 158 #ifndef NP_SIMPLE_IMPL |
158 #ifndef NP_SIMPLE_IMPL |
| 159 ADD_EXP(num, exp); |
159 ADD_EXP(num, exp); |
| 160 #else |
160 #else |
| 161 num->fval*=pow(num->base, exp); |
161 num->fval*=pow(num->base, exp); |
| 162 #endif |
162 #endif |
| 163 return err; |
163 return err; |
| 164 } |
164 } |
| 165 |
165 |
| 166 |
166 |
| 167 static int parse_number(NPNum *num, Tokenizer *tokz, int c) |
167 static int parse_number(NPNum *num, Tokenizer *tokz, int c) |
| 168 { |
168 { |
| 169 int base=10; |
169 int base=10; |
| 170 int dm=1; |
170 int dm=1; |
| 171 int err=0; |
171 int err=0; |
| 172 int tmp; |
172 int tmp; |
| 173 #ifdef NP_SIMPLE_IMPL |
173 #ifdef NP_SIMPLE_IMPL |
| 174 double divisor=base; |
174 double divisor=base; |
| 175 #endif |
175 #endif |
| 176 |
176 |
| 177 if(c=='-' || c=='+'){ |
177 if(c=='-' || c=='+'){ |
| 178 if(c=='-') |
178 if(c=='-') |
| 179 num->negative=TRUE; |
179 num->negative=TRUE; |
| 180 c=GETCH(); |
180 c=GETCH(); |
| 181 if(!isdigit(c)) |
181 if(!isdigit(c)) |
| 182 err=E_TOKZ_NUMFMT; |
182 err=E_TOKZ_NUMFMT; |
| 183 } |
183 } |
| 184 |
184 |
| 185 if(c=='0'){ |
185 if(c=='0'){ |
| 186 dm=0; |
186 dm=0; |
| 187 c=GETCH(); |
187 c=GETCH(); |
| 188 if(c=='x' || c=='X'){ |
188 if(c=='x' || c=='X'){ |
| 189 base=16; |
189 base=16; |
| 190 c=GETCH(); |
190 c=GETCH(); |
| 191 }else if(c=='b' || c=='B'){ |
191 }else if(c=='b' || c=='B'){ |
| 192 base=2; |
192 base=2; |
| 193 c=GETCH(); |
193 c=GETCH(); |
| 194 }else if('0'<=c && c<='7'){ |
194 }else if('0'<=c && c<='7'){ |
| 195 base=8; |
195 base=8; |
| 196 }else{ |
196 }else{ |
| 197 dm=2; |
197 dm=2; |
| 198 } |
198 } |
| 199 } |
199 } |
| 200 |
200 |
| 201 num->base=base; |
201 num->base=base; |
| 202 |
202 |
| 203 for(; 1; c=GETCH()){ |
203 for(; 1; c=GETCH()){ |
| 204 if((c=='e' || c=='E') && dm!=0){ |
204 if((c=='e' || c=='E') && dm!=0){ |
| 205 if(dm<2){ |
205 if(dm<2){ |
| 206 err=E_TOKZ_NUMFMT; |
206 err=E_TOKZ_NUMFMT; |
| 207 continue; |
207 continue; |
| 208 } |
208 } |
| 209 tmp=parse_exponent(num, tokz, c); |
209 tmp=parse_exponent(num, tokz, c); |
| 210 if(err==0) |
210 if(err==0) |
| 211 err=tmp; |
211 err=tmp; |
| 212 break; |
212 break; |
| 213 } |
213 } |
| 214 |
214 |
| 215 if(isxdigit(c)){ |
215 if(isxdigit(c)){ |
| 216 if('0'<=c && c<='9') |
216 if('0'<=c && c<='9') |
| 217 c-='0'; |
217 c-='0'; |
| 218 else if(isupper(c)) |
218 else if(isupper(c)) |
| 219 c-='A'-10; |
219 c-='A'-10; |
| 220 else |
220 else |
| 221 c-='a'-10; |
221 c-='a'-10; |
| 222 |
222 |
| 223 if(c>=base) |
223 if(c>=base) |
| 224 err=E_TOKZ_NUMFMT; |
224 err=E_TOKZ_NUMFMT; |
| 225 |
225 |
| 226 #ifdef NP_SIMPLE_IMPL |
226 #ifdef NP_SIMPLE_IMPL |
| 227 if(dm==3){ |
227 if(dm==3){ |
| 228 num->fval+=(double)c/divisor; |
228 num->fval+=(double)c/divisor; |
| 229 divisor*=base; |
229 divisor*=base; |
| 230 }else |
230 }else |
| 231 #endif |
231 #endif |
| 232 { |
232 { |
| 233 tmp=npnum_mulbase_add(num, base, c); |
233 tmp=npnum_mulbase_add(num, base, c); |
| 234 if(err==0) |
234 if(err==0) |
| 235 err=tmp; |
235 err=tmp; |
| 236 } |
236 } |
| 237 |
237 |
| 238 if(dm==1) |
238 if(dm==1) |
| 239 dm=2; |
239 dm=2; |
| 240 #ifndef NP_SIMPLE_IMPL |
240 #ifndef NP_SIMPLE_IMPL |
| 241 else if(dm==3) |
241 else if(dm==3) |
| 242 ADD_EXP(num, -1); |
242 ADD_EXP(num, -1); |
| 243 #endif |
243 #endif |
| 244 continue; |
244 continue; |
| 245 } |
245 } |
| 246 |
246 |
| 247 if(c=='.'){ |
247 if(c=='.'){ |
| 248 if(dm!=2){ |
248 if(dm!=2){ |
| 249 err=E_TOKZ_NUMFMT; |
249 err=E_TOKZ_NUMFMT; |
| 250 } |
250 } |
| 251 dm=3; |
251 dm=3; |
| 252 #ifdef NP_SIMPLE_IMPL |
252 #ifdef NP_SIMPLE_IMPL |
| 253 num->type=NPNUM_FLOAT; |
253 num->type=NPNUM_FLOAT; |
| 254 divisor=base; |
254 divisor=base; |
| 255 #endif |
255 #endif |
| 256 continue; |
256 continue; |
| 257 } |
257 } |
| 258 |
258 |
| 259 if(is_end(c)){ |
259 if(is_end(c)){ |
| 260 UNGETCH(c); |
260 UNGETCH(c); |
| 261 break; |
261 break; |
| 262 } |
262 } |
| 263 |
263 |
| 264 err=E_TOKZ_NUMFMT; |
264 err=E_TOKZ_NUMFMT; |
| 265 } |
265 } |
| 266 |
266 |
| 267 #ifndef NP_SIMPLE_IMPL |
267 #ifndef NP_SIMPLE_IMPL |
| 268 num->type=(num->exponent==0 ? NPNUM_INT : NPNUM_FLOAT); |
268 num->type=(num->exponent==0 ? NPNUM_INT : NPNUM_FLOAT); |
| 269 #endif |
269 #endif |
| 270 |
270 |
| 271 return err; |
271 return err; |
| 272 } |
272 } |