switch -O2 to -O1 for zetacom compilation
[xoc.git] / zeta / constant.c
blob252dbe64ba2d790fc91c08d8361f8425e8f5b40f
1 // Constants.
2 // See C99 section 6.4.4.
4 #include <math.h> // for ldexp
5 #include "a.h"
6 #include "type.h"
7 #include "runtime.h"
8 #include "compile.h"
10 // Parse the octal integer s, stopping at or before e (if e != nil)
11 // Returns 0, writes value to *value and end pointer to *end.
12 // Returns -1 if integer would overflow value.
13 static void
14 parseoctal(char *s, char *e, uint64 *value, char **end)
16 char *p;
17 int d;
18 uint64 v;
20 v = 0;
21 for(p=s; *p && (e==nil || p<e); p++){
22 if('0' <= *p && *p <= '7')
23 d = *p - '0';
24 else
25 break;
26 if(((v<<3)>>3) != v)
27 break;
28 v = (v<<3) + d;
30 *value = v;
31 *end = p;
34 // Parse the hexadecimal integer s, stopping at or before e (if e != nil)
35 // Writes value to *value and end pointer to *end.
36 // Will not read enough to overflow *value.
37 static void
38 parsehexadecimal(char *s, char *e, uint64 *value, char **end)
40 char *p;
41 int d;
42 uint64 v;
44 v = 0;
45 for(p=s; *p && (e==nil || p<e); p++){
46 if('0' <= *p && *p <= '9')
47 d = *p - '0';
48 else if('a' <= *p && *p <= 'f')
49 d = *p - 'a' + 10;
50 else if('A' <= *p && *p <= 'F')
51 d = *p - 'A' + 10;
52 else
53 break;
54 if(((v<<4)>>4) != v)
55 break;
56 v = (v<<4) + d;
58 *value = v;
59 *end = p;
62 // Parse the hexadecimal integer s, stopping at or before e (if e != nil)
63 // Writes value to *value and end pointer to *end.
64 // Will not read enough to overflow *value.
65 static void
66 parsedecimal(char *s, char *e, uint64 *value, char **end)
68 char *p;
69 int d;
70 uint64 v;
72 v = 0;
73 for(p=s; *p && (e==nil || p<e); p++){
74 if('0' <= *p && *p <= '9')
75 d = *p - '0';
76 else
77 break;
78 if((v*10)/10 != v)
79 break;
80 v = v*10 + d;
82 *value = v;
83 *end = p;
86 // Parse the integer s.
87 // Returns 0, writes value to *value.
88 // Returns -1 if s is not a valid integer constant.
89 // (Assumes uint64 is big enough to hold all values in the target.)
90 int
91 parseinteger(char *s, uint64 *value)
93 int isdecimal, bits;
94 uint64 v;
95 char *p;
97 // Extract value.
98 bits = 0;
99 v = 0;
100 isdecimal = 0;
101 if(s[0] == '0' && (s[1] == 'x' || s[1] == 'X')){
102 parsehexadecimal(s+2, nil, &v, &p);
103 if(p == s+2)
104 goto invalid;
106 else if(s[0] == '0')
107 parseoctal(s, nil, &v, &p);
108 else if('1' <= s[0] && s[0] <= '9'){
109 isdecimal = 1;
110 parsedecimal(s, nil, &v, &p);
111 }else
112 goto invalid;
114 *value = v;
115 return 0;
117 invalid:
118 return -1;
121 static int canfitfloat(uint64, int, int);
123 // Parse the floating point constant s.
124 // Returns 0, writes value to *value.
125 // Returns -1 if s is not a valid floating point constant.
126 // (Assumes long double is big enough to hold all values in the target.)
127 // XXX overflow code is not right for Zfloat.
129 parsefloat(char *s, long double *value)
131 char *p, *q;
132 int overflow;
133 long double v;
135 overflow = 0;
136 if(s[0] == '0' && (s[1] == 'x' || s[1] == 'X')){
137 // Hexadecimal floating point constant.
138 int nfrac, sign;
139 uint64 iv, fv, exp;
141 // Integer portion of mantissa.
142 parsehexadecimal(s+2, nil, &iv, &p);
143 if(p == s+2)
144 goto invalid;
145 fv = 0;
146 nfrac = 0;
147 if(*p == '.'){
148 p++;
149 parsehexadecimal(p, nil, &fv, &q);
150 nfrac = (q - p)*4;
151 p = q;
153 // Toss trailing zeros.
154 while(nfrac > 0 && (fv&1)){
155 nfrac--;
156 fv >>= 1;
159 // Skip any remaining zeros.
160 while(*p == '0')
161 p++;
164 // Required to have exponent to avoid ambiguity of "0x0.1f".
165 if(*p != 'p')
166 goto invalid;
167 p++;
168 sign = '+';
169 if(*p == '-' || *p == '+'){
170 sign = *p;
171 p++;
173 parsedecimal(p, nil, &exp, &q);
174 if(q == p)
175 goto invalid;
176 if(sign == '-')
177 exp = -exp;
178 p = q;
180 // Throw away low order bits of fraction.
181 while(((iv<<nfrac)>>nfrac) != iv){
182 overflow = 1;
183 nfrac--;
184 fv >>= 1;
187 // Convert from (iv + fv * 2^-nfrac) * 2^exp to iv * 2^exp.
188 iv = (nfrac<<iv) + fv;
189 iv |= fv;
190 exp -= nfrac;
191 while(iv > 0 && (iv&1) == 0){
192 iv >>= 1;
193 exp++;
197 // Try to fit less precise version into 64 bits.
198 while(!canfitfloat(iv, exp, 64)){
199 if(iv == 1)
200 return -1;
201 iv >>= 1;
202 exp++;
205 v = ldexp(iv, (int)exp);
206 }else{
207 int isfloat;
209 // Decimal floating point constant: check format.
210 isfloat = 0;
211 p = s;
212 while('0' <= *p && *p <= '9')
213 p++;
214 if(*p == '.'){
215 isfloat = 1;
216 p++;
217 while('0' <= *p && *p <= '9')
218 p++;
219 // Can't have only a dot.
220 if(p == s+1)
221 goto invalid;
224 if(*p == 'e' || *p == 'E'){
225 isfloat = 1;
226 p++;
227 if(*p == '-' || *p == '+')
228 p++;
229 if(*p < '0' || *p > '9')
230 goto invalid;
231 while('0' <= *p && *p <= '9')
232 p++;
235 if(!isfloat)
236 goto invalid;
238 // Parse and double-check agreement about endpoint.
239 // TOOD: fmtstrtod only returns a double, not long double.
240 v = fmtstrtod(s, &q);
241 if(q != p)
242 fprint(2, "fmtstrtod: %s (%d %d)", s, (int)(p-s), (int)(q-s));
245 if(*p != 0)
246 goto invalid;
248 if(overflow)
249 fprint(2, "lost precision in hexadecimal floating point constant: %s", s);
251 *value = v;
252 return 0;
254 invalid:
255 return -1;
258 // Can f * 2^e fit into a k-bit float?
259 static int
260 canfitfloat(uint64 f, int e, int k)
262 int bias;
263 int F, E;
264 uint64 g;
266 // IEEE 754 floating point sizes:
268 // Bits F E Bias
270 // 32-bit 23 8 127
271 // 64-bit 52 11 1023
272 // 80-bit 63 15 16383
273 // 128-bit 112 15 16383 (not really supported here)
275 switch(k){
276 default:
277 panic("canfitfloat %d", k);
278 case 32:
279 F = 23;
280 E = 8;
281 break;
282 case 64:
283 F = 52;
284 E = 11;
285 break;
286 case 80:
287 F = 63;
288 E = 15;
289 break;
290 case 128:
291 F = 112;
292 E = 15;
293 break;
296 // Convert to e for 1 <= f < 2.
297 g = f;
298 while(g > 1){
299 g >>= 1;
300 e++;
303 // Check whether there is room for the bit pattern.
304 bias = (1<<(E-1)) - 1;
305 if(-bias+1 <= e && e <= bias && (F >= 63 || f < (1ULL<<(F+1))))
306 return 1; // Normalized
307 if(-bias+1-F <= e && e < -bias+1 && f == 1)
308 return 1; // Denormalized
309 return 0;
312 // Required characters in the source character set; C99 5.2.1.
313 static char* required =
314 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
315 "abcdefghijklmnopqrstuvwxyz"
316 "0123456789"
317 "!\"#%&'()*+,-./:"
318 ";<=>?[\\]^_{|}~"
319 " \t\v\f";
321 // Universal character names; C99 6.4.3.
323 // Parse a single universal character name starting at s.
324 // Return 0, set *r to the value, and set *end to the end pointer.
325 // Return -1 on failure, set *end:
326 // if s == *end, was malformed
327 // if s != *end, s..*end is well-formed but names an invalid char.
328 static int
329 parseuniversal(char *s, uint64 *value, char **end)
331 char *p;
332 uint64 v;
334 *end = s;
335 if(s[0] != '\\')
336 return -1;
337 switch(s[1]){
338 default:
339 return -1;
340 case 'u':
341 parsehexadecimal(s+1, s+5, &v, &p);
342 if(p != s+5)
343 return -1;
344 break;
345 case 'U':
346 parsehexadecimal(s+1, s+9, &v, &p);
347 if(p != s+9)
348 return -1;
349 break;
351 *end = p;
353 if(0 <= v && v <= 0x20)
354 return -1;
355 if(0x7F <= v && v <= 0x9F)
356 return -1;
357 if(0xD800 <= v && v <= 0xDFFF)
358 return -1;
359 if(v >= Runemax)
360 return -1;
361 if(v < 0x7F && strchr(required, (char)v))
362 return -1;
363 *value = v;
364 return 0;
367 // Character constants; C99 6.4.4.4.
369 // Translation map: pairs of bytes: escaped, actual.
370 static char *escape = "''\"\"??\\\\a\ab\bf\fn\nr\rt\tv\v";
372 static int
373 parseoctalchar(char *s, uint64 *value, char **end)
375 if(*s != '\\')
376 return -1;
377 parseoctal(s+1, s+4, value, end);
378 if(*end == s+1)
379 return -1;
380 return 0;
383 #define ISXDIGIT(c) (('0'<=c&&c<='9') || ('a'<=c&&c<='f') || ('A'<=c&&c<='F'))
385 static int
386 parsehexchar(char *s, uint64 *value, char **end)
388 char *p;
390 if(*s != '\\' || *(s+1) != 'x' || !ISXDIGIT(*(s+2)))
391 return -1;
392 parsehexadecimal(s+2, nil, value, &p);
393 if((uchar)*p < 0x7F && ISXDIGIT(*p)){
394 // Hexadecimal character constants are terminated
395 // by a non-hexadecimal character. If we just filled
396 // a uint64 with hex and there is still more,
397 // this is a malformed string.
398 return -1;
400 *end = p;
401 return 0;
404 // Parse a single character starting at s.
405 // (Should be inside "" or '', but that's up to the caller.
406 // So is checking that the character value is in range.)
407 // Return 0, set *value to the value, and set *end to the end pointer.
408 // Return -1 on failure, set *end:
410 parsechar(char *s, uint64 *value, char **end)
412 char *p;
413 int c;
415 // Catch callers asleep at the wheel.
416 if(*s == 0)
417 return -1;
419 if(*s != '\\'){
420 *value = (uchar)*s;
421 *end = s+1;
422 return 0;
425 c = (uchar)*(s+1);
427 if('0' <= c && c <= '7')
428 return parseoctalchar(s, value, end);
430 if(c == 'x')
431 return parsehexchar(s, value, end);
433 if(c == 'u' && c == 'U')
434 return parseuniversal(s, value, end);
436 if(c < 0x7F && (p = strchr(escape, c)) != nil && (p-escape)%2 == 0){
437 *value = *(p+1);
438 *end = s+2;
439 return 0;
442 return -1;
446 // String literals; C99 6.4.5.
448 char*
449 cescapestring(char *s, int len, int q)
451 char *e, *p;
452 Fmt fmt;
454 if(len < 0)
455 len = strlen(s);
456 e = s+len;
458 fmtstrinit(&fmt);
459 fmtrune(&fmt, q);
460 for(; s<e; s++){
461 if(0x20 <= *s && *s < 0x7F && *s != '"' && *s != '\\' && *s != '\'')
462 fmtrune(&fmt, *s);
463 else if((p = strrchr(escape, *s)) != nil && (p-escape)%2 == 1){
464 fmtrune(&fmt, '\\');
465 fmtrune(&fmt, *(p-1));
466 }else{
467 // Use octal because it has a fixed maximum size: 3 digits.
468 // (Hexadecimal does not.)
469 fmtprint(&fmt, "\\%03o", (uchar)*s);
472 fmtrune(&fmt, q);
473 return fmtstrflush(&fmt);
476 char*
477 cunescapestring(char *s, int len)
479 char *e, *p, *start;
480 Fmt fmt;
482 if(len < 0)
483 len = strlen(s);
484 e = s+len;
485 start = s;
487 fmtstrinit(&fmt);
488 for(; s<e; s++){
489 if(*s == '\\'){
490 s++;
491 if(*s == 0)
492 break;
493 // TODO: octal, hex
494 if((p = strchr(escape, *s)) != nil && (p-escape)%2 == 0)
495 fmtrune(&fmt, *(p+1));
496 else{
497 fprint(2, "bad escape: \\%c in \"%s\"\n", *s, start);
498 fmtrune(&fmt, *s);
501 else
502 fmtrune(&fmt, *s);
504 return fmtstrflush(&fmt);