int luaO_str2d (const char *s, size_t len, lua_Number *result) { char *endptr; if (strpbrk(s, "nN")) /* reject 'inf' and 'nan' */ return 0; else if (strpbrk(s, "xX")) /* hexa? */ *result = lua_strx2number(s, &endptr); else *result = lua_str2number(s, &endptr); if (endptr == s) return 0; /* nothing recognized */ while (lisspace(cast_uchar(*endptr))) endptr++; return (endptr == s + len); /* OK if no trailing characters */ }
/* ** convert an hexadecimal numeric string to a number, following ** C99 specification for 'strtod' */ static lua_Number lua_strx2number (const char *s, char **endptr) { lua_Number r = 0.0; /* result (accumulator) */ int sigdig = 0; /* number of significant digits */ int nosigdig = 0; /* number of non-significant digits */ int e = 0; /* exponent correction */ int neg = 0; /* 1 if number is negative */ int dot = 0; /* true after seen a dot */ *endptr = cast(char *, s); /* nothing is valid yet */ while (lisspace(cast_uchar(*s))) s++; /* skip initial spaces */ neg = isneg(&s); /* check signal */ if (!(*s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X'))) /* check '0x' */ return 0.0; /* invalid format (no '0x') */ for (s += 2; ; s++) { /* skip '0x' and read numeral */ if (*s == '.') { if (dot) break; /* second dot? stop loop */ else dot = 1; } else if (lisxdigit(cast_uchar(*s))) { if (sigdig == 0 && *s == '0') { /* non-significant zero? */ nosigdig++; if (dot) e--; /* zero after dot? correct exponent */ } else { if (++sigdig <= MAXSIGDIG) { /* can read it without overflow? */ r = (r * cast_num(16.0)) + luaO_hexavalue(cast_uchar(*s)); if (dot) e--; /* decimal digit */ } else /* too many digits; ignore */ if (!dot) e++; /* still count it for exponent */ } } else break; /* neither a dot nor a digit */ } if (nosigdig + sigdig == 0) /* no digits? */ return 0.0; /* invalid format */ *endptr = cast(char *, s); /* valid up to here */ e *= 4; /* each digit multiplies/divides value by 2^4 */ if (*s == 'p' || *s == 'P') { /* exponent part? */ int exp1 = 0; /* exponent value */ int neg1; /* exponent signal */ s++; /* skip 'p' */ neg1 = isneg(&s); /* signal */ if (!lisdigit(cast_uchar(*s))) return 0.0; /* invalid; must have at least one digit */ while (lisdigit(cast_uchar(*s))) /* read exponent */ exp1 = exp1 * 10 + *(s++) - '0'; if (neg1) exp1 = -exp1; e += exp1; *endptr = cast(char *, s); /* valid up to here */ }
static lua_Number lua_strb2number (const char *s, char **endptr) { lua_Number r = 0.0; int i = 0; int f = 0; *endptr = cast(char *, s); /* nothing is valid yet */ while (lisspace(cast_uchar(*s))) s++; /* skip initial spaces */ if (!(*s == '0' && (*(s + 1) == 'b' || *(s + 1) == 'B'))) /* check '0b' */ return 0.0; /* invalid format (no '0b') */ s += 2; /* skip '0b' */ while ((*s == '0') || (*s == '1')) { f = 0; r *= 2.0; if (*s == '1') r += 1.0; i++; s++; while (*s == '_') {s++; f = 1;} } if ((i == 0) || (f > 0)) return 0.0; /* invalid format */ *endptr = cast(char *, s); /* valid up to here */ return r; }
/* ** convert an hexadecimal numeric string to a number, following ** C99 specification for 'strtod' */ static lua_Number lua_strx2number (const char *s, char **endptr) { lua_Number r = 0.0; int e = 0, i = 0; int neg = 0; /* 1 if number is negative */ *endptr = cast(char *, s); /* nothing is valid yet */ while (lisspace(cast_uchar(*s))) s++; /* skip initial spaces */ neg = isneg(&s); /* check signal */ if (!(*s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X'))) /* check '0x' */ return 0.0; /* invalid format (no '0x') */ s += 2; /* skip '0x' */ r = readhexa(&s, r, &i); /* read integer part */ if (*s == '.') { s++; /* skip dot */ r = readhexa(&s, r, &e); /* read fractional part */ } if (i == 0 && e == 0) return 0.0; /* invalid format (no digit) */ e *= -4; /* each fractional digit divides value by 2^-4 */ *endptr = cast(char *, s); /* valid up to here */ if (*s == 'p' || *s == 'P') { /* exponent part? */ int exp1 = 0; int neg1; s++; /* skip 'p' */ neg1 = isneg(&s); /* signal */ if (!lisdigit(cast_uchar(*s))) goto ret; /* must have at least one digit */ while (lisdigit(cast_uchar(*s))) /* read exponent */ exp1 = exp1 * 10 + *(s++) - '0'; if (neg1) exp1 = -exp1; e += exp1; } *endptr = cast(char *, s); /* valid up to here */ ret: if (neg) r = -r; return l_mathop(ldexp)(r, e); }
static void read_string (LexState *ls, int del, SemInfo *seminfo) { save_and_next(ls); /* keep delimiter (for error messages) */ while (ls->current != del) { switch (ls->current) { case EOZ: lexerror(ls, "unfinished string", TK_EOS); break; /* to avoid warnings */ case '\n': case '\r': lexerror(ls, "unfinished string", TK_STRING); break; /* to avoid warnings */ case '\\': { /* escape sequences */ int c; /* final character to be saved */ save_and_next(ls); /* keep '\\' for error messages */ switch (ls->current) { case 'a': c = '\a'; goto read_save; case 'b': c = '\b'; goto read_save; case 'f': c = '\f'; goto read_save; case 'n': c = '\n'; goto read_save; case 'r': c = '\r'; goto read_save; case 't': c = '\t'; goto read_save; case 'v': c = '\v'; goto read_save; case 'x': c = readhexaesc(ls); goto read_save; case 'u': utf8esc(ls); goto no_save; case '\n': case '\r': inclinenumber(ls); c = '\n'; goto only_save; case '\\': case '\"': case '\'': c = ls->current; goto read_save; case EOZ: goto no_save; /* will raise an error next loop */ case 'z': { /* zap following span of spaces */ luaZ_buffremove(ls->buff, 1); /* remove '\\' */ next(ls); /* skip the 'z' */ while (lisspace(ls->current)) { if (currIsNewline(ls)) inclinenumber(ls); else next(ls); } goto no_save; } default: { esccheck(ls, lisdigit(ls->current), "invalid escape sequence"); c = readdecesc(ls); /* digital escape '\ddd' */ goto only_save; } } read_save: next(ls); /* go through */ only_save: luaZ_buffremove(ls->buff, 1); /* remove '\\' */ save(ls, c); /* go through */ no_save: break; } default: save_and_next(ls); } } save_and_next(ls); /* skip delimiter */ seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + 1, luaZ_bufflen(ls->buff) - 2); }