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 } |