diff --git a/src/error.c b/src/error.c index 0190418403a..ccffe236428 100644 --- a/src/error.c +++ b/src/error.c @@ -512,6 +512,19 @@ void ErrorMayQuit(const Char * msg, Int arg1, Int arg2) Panic("ErrorMayQuit must not return"); } +/**************************************************************************** +** +*F GetValidRNam( , ) . check if is a valid prec rnam +*/ +UInt GetValidRNam(const char * funcname, Obj rnam) +{ + RequirePositiveSmallInt(funcname, rnam, ""); + UInt val = INT_INTOBJ(rnam); + RequireArgumentCondition(funcname, rnam, IS_VALID_RNAM(val), + "must be a valid rnam"); + return val; +} + /**************************************************************************** ** *F CheckIsPossList( , ) . . . . . . . . . . check for poss list diff --git a/src/error.h b/src/error.h index 5b1bb461020..27136bce773 100644 --- a/src/error.h +++ b/src/error.h @@ -285,6 +285,14 @@ GetPositiveSmallIntEx(const char * funcname, Obj op, const char * argname) #define GetPositiveSmallInt(funcname, op) \ GetPositiveSmallIntEx(funcname, op, NICE_ARGNAME(op)) +/**************************************************************************** +** +*F GetValidRNam +** +** Check if is a valid prec rnam. Error if not. +** Returns the rnam, when it is valid. +*/ +UInt GetValidRNam(const char * funcname, Obj rnam); /**************************************************************************** ** diff --git a/src/records.c b/src/records.c index a14b4a14b21..05ad34a284f 100644 --- a/src/records.c +++ b/src/records.c @@ -33,6 +33,11 @@ static Obj HashRNam; static Obj NamesRNam; +extern inline Int IS_VALID_RNAM(UInt rnam) +{ + return rnam != 0 && rnam <= LEN_PLIST(NamesRNam); +} + extern inline Obj NAME_RNAM(UInt rnam) { return ELM_PLIST(NamesRNam, rnam); @@ -334,7 +339,7 @@ static Obj ElmRecOper; static Obj ElmRecHandler(Obj self, Obj rec, Obj rnam) { - return ELM_REC( rec, INT_INTOBJ(rnam) ); + return ELM_REC(rec, GetValidRNam("Record Element", rnam)); } static Obj ElmRecError(Obj rec, UInt rnam) @@ -368,7 +373,8 @@ static Obj IsbRecOper; static Obj IsbRecHandler(Obj self, Obj rec, Obj rnam) { - return (ISB_REC( rec, INT_INTOBJ(rnam) ) ? True : False); + return (ISB_REC(rec, GetValidRNam("Record IsBound", rnam)) ? True + : False); } static Int IsbRecError(Obj rec, UInt rnam) @@ -397,7 +403,7 @@ static Obj AssRecOper; static Obj AssRecHandler(Obj self, Obj rec, Obj rnam, Obj obj) { - ASS_REC( rec, INT_INTOBJ(rnam), obj ); + ASS_REC(rec, GetValidRNam("Record Assignment", rnam), obj); return 0; } @@ -426,7 +432,7 @@ static Obj UnbRecOper; static Obj UnbRecHandler(Obj self, Obj rec, Obj rnam) { - UNB_REC( rec, INT_INTOBJ(rnam) ); + UNB_REC(rec, GetValidRNam("Record Unbind", rnam)); return 0; } diff --git a/src/records.h b/src/records.h index 54d6b10d982..6641a5904da 100644 --- a/src/records.h +++ b/src/records.h @@ -18,11 +18,22 @@ #include "objects.h" +/**************************************************************************** +** +*F IS_VALID_RNAM() . . . . . . . . . . . . . check if is valid +** +** 'IS_VALID_RNAM' returns if is a valid record name. +*/ +Int IS_VALID_RNAM(UInt rnam); + /**************************************************************************** ** *F NAME_RNAM() . . . . . . . . . . . name for a record name as an Obj ** ** 'NAME_RNAM' returns the name (as an Obj) for the record name . +** +** This function should only be called for valid RNAMs (this can be checked +** with IS_VALID_RNAM). */ Obj NAME_RNAM(UInt rnam); diff --git a/tst/testinstall/recordname.tst b/tst/testinstall/recordname.tst index 674bb799057..5ae120271c7 100644 --- a/tst/testinstall/recordname.tst +++ b/tst/testinstall/recordname.tst @@ -71,4 +71,97 @@ Syntax error: Identifiers in GAP must consist of at most 1023 characters. in s\ tream:2 aaaxyz := 1; # 1024 chars ^^^^^ +gap> r := rec(y := 2); +rec( y := 2 ) +gap> \.(r, RNamObj("y")); +2 +gap> \.(r, RNamObj("x")); +Error, Record Element: '.x' must have an assigned value +gap> \.(r, 0); +Error, Record Element: must be a positive small integer (not the intege\ +r 0) +gap> \.(r, -1); +Error, Record Element: must be a positive small integer (not the intege\ +r -1) +gap> \.(r, 2^1000); +Error, Record Element: must be a positive small integer (not a large po\ +sitive integer) +gap> \.(r, "a"); +Error, Record Element: must be a positive small integer (not a list (st\ +ring)) +gap> \.(r, 1000000); +Error, Record Element: must be a valid rnam (not the integer 1000000) + +## +gap> IsBound\.(r, RNamObj("y")); +true +gap> IsBound\.(r, RNamObj("x")); +false +gap> IsBound\.(r, 0); +Error, Record IsBound: must be a positive small integer (not the intege\ +r 0) +gap> IsBound\.(r, -1); +Error, Record IsBound: must be a positive small integer (not the intege\ +r -1) +gap> IsBound\.(r, 2^1000); +Error, Record IsBound: must be a positive small integer (not a large po\ +sitive integer) +gap> IsBound\.(r, "a"); +Error, Record IsBound: must be a positive small integer (not a list (st\ +ring)) +gap> IsBound\.(r, 1000000); +Error, Record IsBound: must be a valid rnam (not the integer 1000000) + +## +gap> r; +rec( y := 2 ) +gap> Unbind\.(r, RNamObj("y")); +gap> r; +rec( ) +gap> Unbind\.(r, RNamObj("y")); +gap> r; +rec( ) +gap> Unbind\.(r, RNamObj("x")); +gap> Unbind\.(r, 0); +Error, Record Unbind: must be a positive small integer (not the integer\ + 0) +gap> Unbind\.(r, -1); +Error, Record Unbind: must be a positive small integer (not the integer\ + -1) +gap> Unbind\.(r, 2^1000); +Error, Record Unbind: must be a positive small integer (not a large pos\ +itive integer) +gap> Unbind\.(r, "a"); +Error, Record Unbind: must be a positive small integer (not a list (str\ +ing)) +gap> Unbind\.(r, 1000000); +Error, Record Unbind: must be a valid rnam (not the integer 1000000) + +## +gap> r; +rec( ) +gap> \.\:\=(r,RNamObj("y"), 2); +gap> r; +rec( y := 2 ) +gap> \.\:\=(r,RNamObj("y"), 4); +gap> r; +rec( y := 4 ) +gap> \.\:\=(r,RNamObj("x"), 5); +gap> r; +rec( x := 5, y := 4 ) +gap> \.\:\=(r, 0, 1); +Error, Record Assignment: must be a positive small integer (not the int\ +eger 0) +gap> \.\:\=(r, -1, 1); +Error, Record Assignment: must be a positive small integer (not the int\ +eger -1) +gap> \.\:\=(r, 2^1000, 1); +Error, Record Assignment: must be a positive small integer (not a large\ + positive integer) +gap> \.\:\=(r, "a", 1); +Error, Record Assignment: must be a positive small integer (not a list \ +(string)) +gap> \.\:\=(r, 1000000, 1); +Error, Record Assignment: must be a valid rnam (not the integer 1000000\ +) gap> STOP_TEST( "recordname.tst", 1);