Commit 27986381 authored by Alexander A. Maly's avatar Alexander A. Maly

Fix big integers input error

Fixing issue #2
Reenabling Qt4.
parent 318acbf0
Pipeline #697 passed with stages
in 4 minutes and 6 seconds
project(Kumir2)
cmake_minimum_required(VERSION 3.0)
find_package(PythonInterp 3.2.0 REQUIRED)
set(USE_QT 5) # No more Qt4 support!!!
message(STATUS "Cmake prefix path: ${CMAKE_PREFIX_PATH}")
# Query for version info and pass it as compile definitions
......
#ifndef KUMIRSTDLIB_H
#define KUMIRSTDLIB_H
#include <assert.h>
#include <sstream>
#include <set>
#include <vector>
......@@ -32,6 +33,7 @@
# include <string.h>
# include <errno.h>
#endif
#include <stdlib.h>
namespace VM { class Variable; }
......@@ -40,11 +42,7 @@ namespace Kumir {
typedef wchar_t Char;
typedef std::wstring String;
inline String & operator+(String & s, const /*ascii only*/ char c) {
Char uc = Char(c);
s.push_back(uc);
return s;
}
inline String & operator+(String &s1, const /*utf8*/ char * s2) {
EncodingError encodingError;
String us2 = Coder::decode(UTF8, std::string(s2), encodingError);
......@@ -54,11 +52,6 @@ inline String & operator+(String &s1, const /*utf8*/ char * s2) {
typedef double real;
inline String & operator+(String & s, const Char c) {
s.push_back(c);
return s;
}
struct FileType {
enum OpenMode { NotOpen, Read, Write, Append };
enum SpecialType { RegularFile, Console };
......@@ -351,51 +344,10 @@ public:
return !Inf && !NaN;
}
inline static bool isCorrectReal(real val) {
return isCorrectDouble(val);
}
inline static bool isCorrectIntegerConstant(const String & value) {
size_t start = 0;
if (value.length()<=start) return false;
bool isNegative = value.at(0)==Char('-');
if (isNegative) {
start = 1;
}
if (value.length()<=start) return false;
bool isHex = false;
if (value.length()-start >= 1) {
isHex = value.at(start)==Char('$');
if (isHex) start += 1;
}
if (!isHex && value.length()-start >= 2) {
isHex = value.at(start)==Char('0') && value.at(start+1)==Char('x');
if (isHex) start += 2;
}
if (value.length()<=start) return false;
while (start<value.length() && value.at(start)==Char('0'))
start += 1;
const String digits = value.substr(start);
static const String maxHex = Core::fromAscii("80000000");
static const String maxPositiveDecimal = Core::fromAscii("2147483647");
static const String maxNegativeDecimal = Core::fromAscii("2147483648");
if (isHex) {
if (digits.length()==maxHex.length())
return digits < maxHex;
else
return digits.length()<maxHex.length();
}
else {
const String & maxDecimal =
isNegative ? maxNegativeDecimal : maxPositiveDecimal;
if (digits.length()==maxDecimal.length())
return digits <= maxDecimal;
else
return digits.length()<maxDecimal.length();
}
}
inline static real abs(real x) { return ::fabs(x); }
inline static int imax(int x, int y) { return x>y? x : y; }
......@@ -548,7 +500,6 @@ public:
}
};
#include <stdlib.h>
class Random {
public:
inline static void init() {
......@@ -710,68 +661,77 @@ public:
return result;
}
static int parseInt(String word, char base, ParseError & error) {
error = NoError;
if (word.length()==0) {
static int parseInt(String word, unsigned int base, ParseError &error)
{
error = NoError;
size_t l = word.length(), pos = 0;
if (l == 0) {
error = EmptyWord;
return 0;
}
size_t pos = 0;
bool negative = false;
if (word.at(pos)==Char('-')) {
if (word.at(pos) == Char('-')) {
negative = true;
pos += 1;
}
else if (word.at(pos)==Char('+'))
} else if (word.at(pos) == Char('+')) {
pos += 1;
if (base==0) {
// Autodetect format
if (word.length()-pos>=1 && word.at(pos)==Char('$')) {
}
if (base == 0) {
if (pos < l && word.at(pos) == Char('$')) {
base = 16;
pos += 1;
}
else if (word.length()-pos>=2 && word.at(pos)==Char('0') && word.at(pos+1)==Char('x')) {
base = 16;
pos += 2;
}
else {
} else {
base = 10;
}
}
word = word.substr(pos, word.length()-pos);
if (word.length()==0) {
error = pos>0 ? EmptyWord : WrongHex;
return 0;
}
int result = 0;
for (size_t i=0; i<word.length(); i++) {
int power = Math::ipow(base, word.length()-i-1);
assert (base);
unsigned int maxabs = (1U << 31) - (negative ? 0 : 1);
unsigned int maxabsb = maxabs / base;
unsigned int result = 0;
bool overflow = false;
for (size_t i = pos; i < l; i++) {
Char ch = word.at(i);
char digit = 0;
bool wrongChar = false;
if (ch>='0' && ch<='9')
digit = static_cast<char>(ch)-'0';
else if (ch>='A' && ch<='Z')
digit = 10 + static_cast<char>(ch)-'A';
else if (ch>='a' && ch<='z')
digit = 10 + static_cast<char>(ch)-'a';
else
wrongChar = true;
if (digit > base)
wrongChar = true;
if (wrongChar) {
unsigned int digit = base;
if ('0' <= ch && ch <= '9') {
digit = (unsigned int)(ch) - '0';
} else if ('A' <= ch && ch <= 'Z') {
digit = 10 + (unsigned int)(ch) - 'A';
} else if ('a' <= ch && ch <= 'z') {
digit = 10 + (unsigned int)(ch) - 'a';
}
if (base <= digit) {
error = BadSymbol;
return 0;
}
result += power * digit;
overflow = overflow || (maxabsb < result);
result = result * base + digit;
overflow = overflow || (result < digit);
}
if (negative)
result *= -1;
if (NoError == error && !Math::isCorrectIntegerConstant(word)) {
overflow = overflow || (maxabs < result);
if (overflow) {
error = Overflow;
return 0;
}
return result;
return negative ? -result : result;
}
static bool isCorrectIntegerConstant(const String &v)
{
ParseError e = NoError;
parseInt(v, 0, e);
return e == NoError;
}
static real parseReal(String word, Char dot, ParseError & error) {
......@@ -2262,7 +2222,7 @@ public:
String word = readWord(is);
if (is.hasError()) return 0;
Converter::ParseError error = Converter::NoError;
int result = Converter::parseInt(word, 10, error);
int result = Converter::parseInt(word, 0, error);
if (error==Converter::EmptyWord) {
is.setError(Core::fromUtf8("Ошибка ввода целого числа: текст закончился"));
}
......
......@@ -4194,7 +4194,7 @@ QVariant SyntaxAnalizer::parseConstant(const std::list<LexemPtr> &constant,
bool isHex = false;
if (pt==AST::TypeInteger) {
integerOverflow = !Kumir::Math::isCorrectIntegerConstant(val.toStdWString());
integerOverflow = !Kumir::Converter::isCorrectIntegerConstant(val.toStdWString());
isHex = val.startsWith("$") || val.startsWith("-$") || val.startsWith("0x") || val.startsWith("-0x");
if (!isHex) {
// Check for leading zeroes
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment