fix case where very big negative integer could have two representations.

This commit is contained in:
Vítor Santos Costa 2009-01-12 15:08:26 +00:00
parent 76e521f3ff
commit 30e946cc30

View File

@ -56,8 +56,8 @@
#define my_islower(C) ( C >= 'a' && C <= 'z' ) #define my_islower(C) ( C >= 'a' && C <= 'z' )
STATIC_PROTO(int my_getch, (int (*) (int))); STATIC_PROTO(int my_getch, (int (*) (int)));
STATIC_PROTO(Term float_send, (char *)); STATIC_PROTO(Term float_send, (char *, int));
STATIC_PROTO(Term get_num, (int *, int *, int, int (*) (int), int (*) (int),char *,UInt)); STATIC_PROTO(Term get_num, (int *, int *, int, int (*) (int), int (*) (int),char *,UInt,int));
/* token table with some help from Richard O'Keefe's PD scanner */ /* token table with some help from Richard O'Keefe's PD scanner */
static char chtype0[NUMBER_OF_CHARS+1] = static char chtype0[NUMBER_OF_CHARS+1] =
@ -197,7 +197,7 @@ my_getch(int (*Nextch) (int))
extern double atof(const char *); extern double atof(const char *);
static Term static Term
float_send(char *s) float_send(char *s, int sign)
{ {
Float f = (Float)atof(s); Float f = (Float)atof(s);
#if HAVE_FINITE #if HAVE_FINITE
@ -208,12 +208,12 @@ float_send(char *s)
} }
} }
#endif #endif
return (MkEvalFl(f)); return (MkEvalFl(f*sign));
} }
/* we have an overflow at s */ /* we have an overflow at s */
static Term static Term
read_int_overflow(const char *s, Int base, Int val) read_int_overflow(const char *s, Int base, Int val, int sign)
{ {
#ifdef USE_GMP #ifdef USE_GMP
/* try to scan it as a bignum */ /* try to scan it as a bignum */
@ -221,6 +221,8 @@ read_int_overflow(const char *s, Int base, Int val)
Term t; Term t;
mpz_init_set_str (new, s, base); mpz_init_set_str (new, s, base);
if (sign < 0)
mpz_neg(new, new);
t = Yap_MkBigIntTerm(new); t = Yap_MkBigIntTerm(new);
mpz_clear(new); mpz_clear(new);
return t; return t;
@ -454,7 +456,7 @@ read_quoted_char(int *scan_nextp, int inp_stream, int (*QuotedNxtch)(int))
/* reads a number, either integer or float */ /* reads a number, either integer or float */
static Term static Term
get_num(int *chp, int *chbuffp, int inp_stream, int (*Nxtch) (int), int (*QuotedNxtch) (int), char *s, UInt max_size) get_num(int *chp, int *chbuffp, int inp_stream, int (*Nxtch) (int), int (*QuotedNxtch) (int), char *s, UInt max_size, int sign)
{ {
char *sp = s; char *sp = s;
int ch = *chp; int ch = *chp;
@ -499,6 +501,9 @@ get_num(int *chp, int *chbuffp, int inp_stream, int (*Nxtch) (int), int (*Quoted
/* a quick way to represent ASCII */ /* a quick way to represent ASCII */
if (scan_extra) if (scan_extra)
*chp = Nxtch(inp_stream); *chp = Nxtch(inp_stream);
if (sign == -1) {
return MkIntegerTerm(-ascii);
}
return MkIntegerTerm(ascii); return MkIntegerTerm(ascii);
} else if (base >= 10 && base <= 36) { } else if (base >= 10 && base <= 36) {
int upper_case = 'A' - 11 + base; int upper_case = 'A' - 11 + base;
@ -566,8 +571,11 @@ get_num(int *chp, int *chbuffp, int inp_stream, int (*Nxtch) (int), int (*Quoted
} }
*sp++ = ch; *sp++ = ch;
} }
if (ch - '0' >= base) if (ch - '0' >= base) {
if (sign == -1)
return MkIntegerTerm(-val);
return MkIntegerTerm(val); return MkIntegerTerm(val);
}
val = val * base + ch - '0'; val = val * base + ch - '0';
if (val/base != oval || val -oval*base != ch-'0') /* overflow */ if (val/base != oval || val -oval*base != ch-'0') /* overflow */
has_overflow = TRUE; has_overflow = TRUE;
@ -585,7 +593,9 @@ get_num(int *chp, int *chbuffp, int inp_stream, int (*Nxtch) (int), int (*Quoted
*chp = ch; *chp = ch;
*--sp = '\0'; *--sp = '\0';
if (has_overflow) if (has_overflow)
return read_int_overflow(s,base,val); return read_int_overflow(s,base,val,sign);
if (sign == -1)
return MkIntegerTerm(-val);
return MkIntegerTerm(val); return MkIntegerTerm(val);
} }
do { do {
@ -635,9 +645,9 @@ get_num(int *chp, int *chbuffp, int inp_stream, int (*Nxtch) (int), int (*Quoted
*sp0 = '\0'; *sp0 = '\0';
for (sp = s; sp < sp0; sp++) { for (sp = s; sp < sp0; sp++) {
if (*sp == '.') if (*sp == '.')
return float_send(s); return float_send(s,sign);
} }
return MkIntegerTerm(val); return MkIntegerTerm(sign*val);
} }
do { do {
if (--max_size == 0) { if (--max_size == 0) {
@ -649,21 +659,21 @@ get_num(int *chp, int *chbuffp, int inp_stream, int (*Nxtch) (int), int (*Quoted
} }
*sp = '\0'; *sp = '\0';
*chp = ch; *chp = ch;
return float_send(s); return float_send(s,sign);
} else if (has_overflow) { } else if (has_overflow) {
*sp = '\0'; *sp = '\0';
/* skip base */ /* skip base */
*chp = ch; *chp = ch;
if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X'))
return read_int_overflow(s+2,16,val); return read_int_overflow(s+2,16,val,sign);
if (s[1] == '\'') if (s[1] == '\'')
return read_int_overflow(s+2,base,val); return read_int_overflow(s+2,base,val,sign);
if (s[2] == '\'') if (s[2] == '\'')
return read_int_overflow(s+3,base,val); return read_int_overflow(s+3,base,val,sign);
return read_int_overflow(s,base,val); return read_int_overflow(s,base,val,sign);
} else { } else {
*chp = ch; *chp = ch;
return MkIntegerTerm(val); return MkIntegerTerm(val*sign);
} }
} }
@ -699,14 +709,8 @@ Yap_scan_num(int (*Nxtch) (int))
cherr = '\0'; cherr = '\0';
if (ASP-H < 1024) if (ASP-H < 1024)
return TermNil; return TermNil;
out = get_num(&ch, &cherr, -1, Nxtch, Nxtch, ptr, 4096); /* */ out = get_num(&ch, &cherr, -1, Nxtch, Nxtch, ptr, 4096, sign); /* */
PopScannerMemory(ptr, 4096); PopScannerMemory(ptr, 4096);
if (sign == -1) {
if (IsIntegerTerm(out))
out = MkIntegerTerm(-IntegerOfTerm(out));
else if (IsFloatTerm(out))
out = MkFloatTerm(-FloatOfTerm(out));
}
Yap_clean_tokenizer(NULL, NULL, NULL); Yap_clean_tokenizer(NULL, NULL, NULL);
if (Yap_ErrorMessage != NULL || ch != -1 || cherr) if (Yap_ErrorMessage != NULL || ch != -1 || cherr)
return TermNil; return TermNil;
@ -889,7 +893,7 @@ Yap_tokenizer(int inp_stream, Term *tposp)
/* serious error now */ /* serious error now */
return l; return l;
} }
if ((t->TokInfo = get_num(&cha,&cherr,inp_stream,Nxtch,QuotedNxtch,ptr,4096)) == 0L) { if ((t->TokInfo = get_num(&cha,&cherr,inp_stream,Nxtch,QuotedNxtch,ptr,4096,1)) == 0L) {
UNLOCK(Stream[inp_stream].streamlock); UNLOCK(Stream[inp_stream].streamlock);
if (p) if (p)
p->Tok = Ord(kind = eot_tok); p->Tok = Ord(kind = eot_tok);