2 // See C99 section 6.4.4.
4 #include <math.h> // for ldexp
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.
14 parseoctal(char *s
, char *e
, uint64
*value
, char **end
)
21 for(p
=s
; *p
&& (e
==nil
|| p
<e
); p
++){
22 if('0' <= *p
&& *p
<= '7')
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.
38 parsehexadecimal(char *s
, char *e
, uint64
*value
, char **end
)
45 for(p
=s
; *p
&& (e
==nil
|| p
<e
); p
++){
46 if('0' <= *p
&& *p
<= '9')
48 else if('a' <= *p
&& *p
<= 'f')
50 else if('A' <= *p
&& *p
<= 'F')
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.
66 parsedecimal(char *s
, char *e
, uint64
*value
, char **end
)
73 for(p
=s
; *p
&& (e
==nil
|| p
<e
); p
++){
74 if('0' <= *p
&& *p
<= '9')
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.)
91 parseinteger(char *s
, uint64
*value
)
101 if(s
[0] == '0' && (s
[1] == 'x' || s
[1] == 'X')){
102 parsehexadecimal(s
+2, nil
, &v
, &p
);
107 parseoctal(s
, nil
, &v
, &p
);
108 else if('1' <= s
[0] && s
[0] <= '9'){
110 parsedecimal(s
, nil
, &v
, &p
);
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
)
136 if(s
[0] == '0' && (s
[1] == 'x' || s
[1] == 'X')){
137 // Hexadecimal floating point constant.
141 // Integer portion of mantissa.
142 parsehexadecimal(s
+2, nil
, &iv
, &p
);
149 parsehexadecimal(p
, nil
, &fv
, &q
);
153 // Toss trailing zeros.
154 while(nfrac
> 0 && (fv
&1)){
159 // Skip any remaining zeros.
164 // Required to have exponent to avoid ambiguity of "0x0.1f".
169 if(*p
== '-' || *p
== '+'){
173 parsedecimal(p
, nil
, &exp
, &q
);
180 // Throw away low order bits of fraction.
181 while(((iv
<<nfrac
)>>nfrac
) != iv
){
187 // Convert from (iv + fv * 2^-nfrac) * 2^exp to iv * 2^exp.
188 iv
= (nfrac
<<iv
) + fv
;
191 while(iv
> 0 && (iv
&1) == 0){
197 // Try to fit less precise version into 64 bits.
198 while(!canfitfloat(iv
, exp
, 64)){
205 v
= ldexp(iv
, (int)exp
);
209 // Decimal floating point constant: check format.
212 while('0' <= *p
&& *p
<= '9')
217 while('0' <= *p
&& *p
<= '9')
219 // Can't have only a dot.
224 if(*p
== 'e' || *p
== 'E'){
227 if(*p
== '-' || *p
== '+')
229 if(*p
< '0' || *p
> '9')
231 while('0' <= *p
&& *p
<= '9')
238 // Parse and double-check agreement about endpoint.
239 // TOOD: fmtstrtod only returns a double, not long double.
240 v
= fmtstrtod(s
, &q
);
242 fprint(2, "fmtstrtod: %s (%d %d)", s
, (int)(p
-s
), (int)(q
-s
));
249 fprint(2, "lost precision in hexadecimal floating point constant: %s", s
);
258 // Can f * 2^e fit into a k-bit float?
260 canfitfloat(uint64 f
, int e
, int k
)
266 // IEEE 754 floating point sizes:
272 // 80-bit 63 15 16383
273 // 128-bit 112 15 16383 (not really supported here)
277 panic("canfitfloat %d", k
);
296 // Convert to e for 1 <= f < 2.
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
312 // Required characters in the source character set; C99 5.2.1.
313 static char* required
=
314 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
315 "abcdefghijklmnopqrstuvwxyz"
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.
329 parseuniversal(char *s
, uint64
*value
, char **end
)
341 parsehexadecimal(s
+1, s
+5, &v
, &p
);
346 parsehexadecimal(s
+1, s
+9, &v
, &p
);
353 if(0 <= v
&& v
<= 0x20)
355 if(0x7F <= v
&& v
<= 0x9F)
357 if(0xD800 <= v
&& v
<= 0xDFFF)
361 if(v
< 0x7F && strchr(required
, (char)v
))
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";
373 parseoctalchar(char *s
, uint64
*value
, char **end
)
377 parseoctal(s
+1, s
+4, value
, end
);
383 #define ISXDIGIT(c) (('0'<=c&&c<='9') || ('a'<=c&&c<='f') || ('A'<=c&&c<='F'))
386 parsehexchar(char *s
, uint64
*value
, char **end
)
390 if(*s
!= '\\' || *(s
+1) != 'x' || !ISXDIGIT(*(s
+2)))
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.
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
)
415 // Catch callers asleep at the wheel.
427 if('0' <= c
&& c
<= '7')
428 return parseoctalchar(s
, value
, end
);
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){
446 // String literals; C99 6.4.5.
449 cescapestring(char *s
, int len
, int q
)
461 if(0x20 <= *s
&& *s
< 0x7F && *s
!= '"' && *s
!= '\\' && *s
!= '\'')
463 else if((p
= strrchr(escape
, *s
)) != nil
&& (p
-escape
)%2 == 1){
465 fmtrune(&fmt
, *(p
-1));
467 // Use octal because it has a fixed maximum size: 3 digits.
468 // (Hexadecimal does not.)
469 fmtprint(&fmt
, "\\%03o", (uchar
)*s
);
473 return fmtstrflush(&fmt
);
477 cunescapestring(char *s
, int len
)
494 if((p
= strchr(escape
, *s
)) != nil
&& (p
-escape
)%2 == 0)
495 fmtrune(&fmt
, *(p
+1));
497 fprint(2, "bad escape: \\%c in \"%s\"\n", *s
, start
);
504 return fmtstrflush(&fmt
);