}
// Portable implementation of strtoll().
-inline int64_t StringToInt(const char *str, int base = 10) {
+inline int64_t StringToInt(const char *str, char **endptr = nullptr, int base = 10) {
#ifdef _MSC_VER
- return _strtoi64(str, nullptr, base);
+ return _strtoi64(str, endptr, base);
#else
- return strtoll(str, nullptr, base);
+ return strtoll(str, endptr, base);
#endif
}
// Portable implementation of strtoull().
-inline int64_t StringToUInt(const char *str, int base = 10) {
+inline int64_t StringToUInt(const char *str, char **endptr = nullptr, int base = 10) {
#ifdef _MSC_VER
- return _strtoui64(str, nullptr, base);
+ return _strtoui64(str, endptr, base);
#else
- return strtoull(str, nullptr, base);
+ return strtoull(str, endptr, base);
#endif
}
return Error("escape code must be followed by " + NumToString(nibbles) +
" hex digits");
std::string target(cursor_, cursor_ + nibbles);
- *val = StringToUInt(target.c_str(), 16);
+ *val = StringToUInt(target.c_str(), nullptr, 16);
cursor_ += nibbles;
return NoError();
}
cursor_++;
while (isxdigit(static_cast<unsigned char>(*cursor_))) cursor_++;
attribute_.append(start + 2, cursor_);
- attribute_ = NumToString(StringToUInt(attribute_.c_str(), 16));
+ attribute_ = NumToString(StringToUInt(attribute_.c_str(), nullptr, 16));
token_ = kTokenIntegerConstant;
return NoError();
}
NEXT();
} else { // Numeric constant in string.
if (IsInteger(e.type.base_type)) {
- // TODO(wvo): do we want to check for garbage after the number?
- e.constant = NumToString(StringToInt(attribute_.c_str()));
+ char *end;
+ e.constant = NumToString(StringToInt(attribute_.c_str(), &end));
+ if (*end)
+ return Error("invalid integer: " + attribute_);
} else if (IsFloat(e.type.base_type)) {
- e.constant = NumToString(strtod(attribute_.c_str(), nullptr));
+ char *end;
+ e.constant = NumToString(strtod(attribute_.c_str(), &end));
+ if (*end)
+ return Error("invalid float: " + attribute_);
} else {
assert(0); // Shouldn't happen, we covered all types.
e.constant = "0";