diff --git a/src/lexer.h b/src/lexer.h index ec20723eeb0c4c07e11c387e1db1be07ce8fc146..ac317fc47973578a58550e97a912553921d75c0a 100644 --- a/src/lexer.h +++ b/src/lexer.h @@ -1,5 +1,5 @@ /* - * $Id: lexer.h,v 1.8 1999/10/23 06:51:28 hubbe Exp $ + * $Id: lexer.h,v 1.9 1999/10/26 17:52:47 noring Exp $ * * Lexical analyzer template. * Based on lex.c 1.62 @@ -413,19 +413,30 @@ static int low_yylex(YYSTYPE *yylval) return c; case '0': - if(GOBBLE('x') || GOBBLE('X')) + { + int base = 0; + + if(GOBBLE('b') || GOBBLE('B')) { + base = 2; + goto read_based_number; + } + else if(GOBBLE('x') || GOBBLE('X')) + { + base = 16; + read_based_number: debug_malloc_pass( yylval->n=mkintnode(0) ); wide_string_to_svalue_inumber(&yylval->n->u.sval, lex.pos, (void **)&lex.pos, - 16, + base, 0, SHIFT); free_string(yylval->n->type); yylval->n->type=get_type_of_svalue(&yylval->n->u.sval); return F_NUMBER; } + } case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': diff --git a/src/modules/Gmp/mpz_glue.c b/src/modules/Gmp/mpz_glue.c index 98e4130207eeec99044bf440f972125aca5c3f69..7da2aa91d7c7505ee4cb5bcf7349ae064e35f75a 100644 --- a/src/modules/Gmp/mpz_glue.c +++ b/src/modules/Gmp/mpz_glue.c @@ -4,7 +4,7 @@ ||| See the files COPYING and DISCLAIMER for more information. \*/ #include "global.h" -RCSID("$Id: mpz_glue.c,v 1.57 1999/10/26 06:30:49 hubbe Exp $"); +RCSID("$Id: mpz_glue.c,v 1.58 1999/10/26 17:52:52 noring Exp $"); #include "gmp_machine.h" #if defined(HAVE_GMP2_GMP_H) && defined(HAVE_LIBGMP2) @@ -64,8 +64,32 @@ static void get_mpz_from_digits(MP_INT *tmp, { if(!base || ((base >= 2) && (base <= 36))) { - if (mpz_set_str(tmp, digits->str, base)) + int offset = 0; + + /* We need to fix the case with binary 0b101... and -0b101... numbers. */ + if(base == 0 && digits->len > 2) + { + if(INDEX_CHARP(digits->str, 0, digits->size_shift) == '-') + offset += 1; + if((INDEX_CHARP(digits->str, offset, digits->size_shift) == '0') && + ((INDEX_CHARP(digits->str, offset+1, digits->size_shift) == 'b') || + (INDEX_CHARP(digits->str, offset+1, digits->size_shift) == 'B'))) + { + offset += 2; + base = 2; + } + else + offset = 0; + } + + if (mpz_set_str(tmp, digits->str + offset, base)) error("invalid digits, cannot convert to mpz"); + + if(offset == 3) + { + /* This means a negative binary number. */ + mpz_neg(tmp, tmp); + } } else if(base == 256) { @@ -310,8 +334,12 @@ static void mpzmod__sprintf(INT32 args) mask_shift += 1; /* Fall-through. */ case 'o': - base += 8; - mask_shift += 3; + base += 6; + mask_shift += 2; + /* Fall-through. */ + case 'b': + base += 2; + mask_shift += 1; if(precision > 0) { @@ -392,8 +420,18 @@ static void mpzmod_cast(INT32 args) case 'i': if(!strncmp(s->str, "int", 3)) { +#ifdef AUTO_BIGNUM_XXXX + /* FIXME 1: Do we need to free the string? Looking + at the case with 'o' makes this confusing... + + FIXME 2: The run-time cast checking does not work + properly with bignums. Take a look at row 209 and + 226 in opcodes.c for more examples on this. */ + push_object(this_object()); +#else free_string(s); mpzmod_get_int(0); +#endif /* AUTO_BIGNUM */ return; } break; diff --git a/src/opcodes.c b/src/opcodes.c index fc230943cd0d1f29f8c3a1e578847d8264ace699..7752a66e27e20ab5f036b46a15e0ea391703b3c0 100644 --- a/src/opcodes.c +++ b/src/opcodes.c @@ -25,7 +25,7 @@ #include "security.h" #include "bignum.h" -RCSID("$Id: opcodes.c,v 1.51 1999/10/25 10:18:46 hubbe Exp $"); +RCSID("$Id: opcodes.c,v 1.52 1999/10/26 17:52:48 noring Exp $"); void index_no_free(struct svalue *to,struct svalue *what,struct svalue *ind) { @@ -903,6 +903,7 @@ static INT32 really_low_sscanf(char *input, } break; + case 'b': case 'o': case 'd': case 'x': @@ -920,6 +921,7 @@ static INT32 really_low_sscanf(char *input, switch(match[cnt]) { + case 'b': base = 2; break; case 'o': base = 8; break; case 'd': base = 10; break; case 'x': base = 16; break; diff --git a/src/stralloc.c b/src/stralloc.c index e4ef4d28cba90b08854e9219986c8912537da2ac..61cfa6a431618a6935ca62ba62afe6fe6dca4be2 100644 --- a/src/stralloc.c +++ b/src/stralloc.c @@ -25,7 +25,7 @@ #define HUGE HUGE_VAL #endif /*!HUGE*/ -RCSID("$Id: stralloc.c,v 1.71 1999/10/24 01:08:39 noring Exp $"); +RCSID("$Id: stralloc.c,v 1.72 1999/10/26 17:52:49 noring Exp $"); #define BEGIN_HASH_SIZE 997 #define MAX_AVG_LINK_LENGTH 3 @@ -1888,6 +1888,8 @@ int pcharp_to_svalue_inumber(struct svalue *r, base = 10; else if(INDEX_PCHARP(str,1) == 'x' || INDEX_PCHARP(str,1) == 'X') base = 16; + else if(INDEX_PCHARP(str,1) == 'b' || INDEX_PCHARP(str,1) == 'B') + base = 2; else base = 8; } @@ -1899,10 +1901,11 @@ int pcharp_to_svalue_inumber(struct svalue *r, if(!isalnum(c) || (xx = DIGIT(c)) >= base) return 0; /* No number formed. */ - if(implicit_base && base == 16 && c == '0' && + if(implicit_base && c == '0' && INDEX_PCHARP(str,2) < 256 && /* Don't trust isxdigit... */ isxdigit(INDEX_PCHARP(str,2)) && - (INDEX_PCHARP(str,1) == 'x' || INDEX_PCHARP(str,1) == 'X')) + ((base==16 && (INDEX_PCHARP(str,1)=='x' || INDEX_PCHARP(str,1)=='X')) || + (base==2 && (INDEX_PCHARP(str,1)=='b' || INDEX_PCHARP(str,1)=='B')))) { /* Skip over leading "0x" or "0X". */ INC_PCHARP(str,2); diff --git a/src/testsuite.in b/src/testsuite.in index 6445a9120faa9b4602845a6a698d66b026b05a96..aebba107e41b7eacbbe680a0a652aeb062ee50cc 100644 --- a/src/testsuite.in +++ b/src/testsuite.in @@ -1,4 +1,4 @@ -test_true([["$Id: testsuite.in,v 1.208 1999/10/25 10:26:25 hubbe Exp $"]]) +test_true([["$Id: testsuite.in,v 1.209 1999/10/26 17:52:50 noring Exp $"]]) cond([[all_constants()->_verify_internals]], [[ @@ -26,6 +26,11 @@ bar"]],[["foo\nbar"]]) test_true([[stringp(#string "Makefile")]]) test_any([[class Bar { array(int) foo = ({}); }; class Foo { inherit Bar; array(int) foo = ({1}); }; return sizeof(Foo()->foo);]],1) +test_eq(8, 0b1000) +test_eq(-8, -0b1000) +test_eq(16, 0b10000) +test_eq(-16, -0b10000) + test_eval_error([[mixed x; return mkmapping(x,x)]]) test_any([[return class Z { @@ -1314,6 +1319,9 @@ cond([[ sizeof( cpp("__AUTO_BIGNUM__")/"__AUTO_BIGNUM__" ) == 1 ]], test_eq("-335812727629498640265", [[ (string)-0x123456789123456789 ]]) test_eq("718046312823", [[ (string)012345671234567 ]]) test_eq("-718046312823", [[ (string)-012345671234567 ]]) + test_eq("", [[ (string)012345671234567 ]]) + test_eq("1125899906842624", [[ (string)0b100000000000000000000000000000000000000000000000000 ]]) + test_eq("-1125899906842624", [[ (string)-0b100000000000000000000000000000000000000000000000000 ]]) // These numbers should be ordinary integers. test_false([[ objectp(-0x80000000) ]]) @@ -1410,6 +1418,10 @@ cond([[ sizeof( cpp("__AUTO_BIGNUM__")/"__AUTO_BIGNUM__" ) == 1 ]], [[ (string)array_sscanf("1234567012345670", "%o")[0] ]]) test_eq("45954944846776", [[ (string)array_sscanf("01234567012345670", "%i")[0] ]]) + test_eq("11", [[ (string)array_sscanf("1011", "%b")[0] ]]) + test_eq("1125968643114208", [[ (string)array_sscanf("100000000000001000000000001000000000100010011100000", "%b")[0] ]]) + test_eq("11", [[ (string)array_sscanf("0b1011", "%i")[0] ]]) + test_eq("1125968643114208", [[ (string)array_sscanf("0b100000000000001000000000001000000000100010011100000", "%i")[0] ]]) test_eq("-12345678901234567890", [[ (string)array_sscanf("-12345678901234567890", "%d")[0] ]]) @@ -1421,10 +1433,17 @@ cond([[ sizeof( cpp("__AUTO_BIGNUM__")/"__AUTO_BIGNUM__" ) == 1 ]], [[ (string)array_sscanf("-1234567012345670", "%o")[0] ]]) test_eq("-45954944846776", [[ (string)array_sscanf("-01234567012345670", "%i")[0] ]]) + test_eq("-11", [[ (string)array_sscanf("-1011", "%b")[0] ]]) + test_eq("-1125968643114208", [[ (string)array_sscanf("-100000000000001000000000001000000000100010011100000", "%b")[0] ]]) + test_eq("-11", [[ (string)array_sscanf("-0b1011", "%i")[0] ]]) + test_eq("-1125968643114208", [[ (string)array_sscanf("-0b100000000000001000000000001000000000100010011100000", "%i")[0] ]]) test_equal([[ ({ 0, 118 }) ]], [[ array_sscanf("0x76", "%xx%x") ]]) test_equal([[ ({ 0, 557239244978618154304871 }) ]], [[ array_sscanf("0x76000000000001234567", "%xx%x") ]]) + + test_equal(471100000000000000000000000000000000000000000000042, + (int)(mixed)471100000000000000000000000000000000000000000000042) ]]) cond([[ sizeof( cpp("__AUTO_BIGNUM__")/"__AUTO_BIGNUM__" ) == 1 ]],