From 50ae8fdcf6340dd85f832fb31b363e767f9430f8 Mon Sep 17 00:00:00 2001 From: dgp Date: Fri, 19 Oct 2018 19:18:30 +0000 Subject: [d1d05d1c7a] Tests and fix for bignums in end-offset index value parsing. --- generic/tclUtil.c | 46 ++++++++++++++++++++++++---------------------- tests/util.test | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 22 deletions(-) diff --git a/generic/tclUtil.c b/generic/tclUtil.c index 4ea9c2e..d3136e2 100644 --- a/generic/tclUtil.c +++ b/generic/tclUtil.c @@ -3660,10 +3660,12 @@ TclFormatInt( * GetWideForIndex -- * * This function produces a wide integer value corresponding to the - * list index held in *objPtr. The parsing supports all values + * index value held in *objPtr. The parsing supports all values * recognized as any size of integer, and the syntaxes end[-+]$integer * and $integer[-+]$integer. The argument endValue is used to give - * the meaning of the literal index value "end". + * the meaning of the literal index value "end". Index arithmetic + * on arguments outside the wide integer range are only accepted + * when interp is a working interpreter, not NULL. * * Results: * When parsing of *objPtr successfully recognizes an index value, @@ -3994,6 +3996,8 @@ SetEndOffsetFromAny( bytes = TclGetStringFromObj(objPtr, &length); if ((*bytes != 'e') || (strncmp(bytes, "end", (size_t)((length > 3) ? 3 : length)) != 0)) { + + badIndexFormat: if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "bad index \"%s\": must be end?[+-]integer?", bytes)); @@ -4013,35 +4017,33 @@ SetEndOffsetFromAny( * This is our limited string expression evaluator. Pass everything * after "end-" to TclParseNumber. */ + ClientData cd; + int t; if (TclIsSpaceProc(bytes[4])) { goto badIndexFormat; } if (TclParseNumber(NULL, objPtr, NULL, bytes+4, length-4, NULL, TCL_PARSE_INTEGER_ONLY) != TCL_OK) { - return TCL_ERROR; - } - if (objPtr->typePtr != &tclIntType) { - goto badIndexFormat; + goto badIndexFormat; } - offset = objPtr->internalRep.wideValue; - if (bytes[3] == '-') { - - /* TODO: Review overflow concerns here! */ - offset = -offset; + TclGetNumberFromObj(NULL, objPtr, &cd, &t); + if (t == TCL_NUMBER_BIG) { + /* Truncate to the signed wide range. */ + if (mp_isneg((mp_int *)cd)) { + offset = (bytes[3] == '-') ? LLONG_MAX : LLONG_MIN; + } else { + offset = (bytes[3] == '-') ? LLONG_MIN : LLONG_MAX; + } + } else { + /* assert (t == TCL_NUMBER_INT); */ + offset = (*(Tcl_WideInt *)cd); + if (bytes[3] == '-') { + offset = (offset == LLONG_MIN) ? LLONG_MAX : -offset; + } } } else { - /* - * Conversion failed. Report the error. - */ - - badIndexFormat: - if (interp != NULL) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "bad index \"%s\": must be end?[+-]integer?", bytes)); - Tcl_SetErrorCode(interp, "TCL", "VALUE", "INDEX", NULL); - } - return TCL_ERROR; + goto badIndexFormat; } /* diff --git a/tests/util.test b/tests/util.test index 34113c0..9422fc3 100644 --- a/tests/util.test +++ b/tests/util.test @@ -735,6 +735,43 @@ test util-9.45 {TclGetIntForIndex} { test util-9.46 {TclGetIntForIndex} { string index abcd end+4294967294 } {} +# TIP 502 +test util-9.47 {TclGetIntForIndex} { + string index abcd 0x10000000000000000 +} {} +test util-9.48 {TclGetIntForIndex} { + string index abcd -0x10000000000000000 +} {} +test util-9.49 {TclGetIntForIndex} -body { + string index abcd end*1 +} -returnCodes error -match glob -result * +test util-9.50 {TclGetIntForIndex} -body { + string index abcd {end- 1} +} -returnCodes error -match glob -result * +test util-9.51 {TclGetIntForIndex} -body { + string index abcd end-end +} -returnCodes error -match glob -result * +test util-9.52 {TclGetIntForIndex} -body { + string index abcd end-x +} -returnCodes error -match glob -result * +test util-9.53 {TclGetIntForIndex} -body { + string index abcd end-0.1 +} -returnCodes error -match glob -result * +test util-9.54 {TclGetIntForIndex} { + string index abcd end-0x10000000000000000 +} {} +test util-9.55 {TclGetIntForIndex} { + string index abcd end+0x10000000000000000 +} {} +test util-9.56 {TclGetIntForIndex} { + string index abcd end--0x10000000000000000 +} {} +test util-9.57 {TclGetIntForIndex} { + string index abcd end+-0x10000000000000000 +} {} +test util-9.58 {TclGetIntForIndex} { + string index abcd end--0x8000000000000000 +} {} test util-10.1 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} { convertDouble 0x0000000000000000 -- cgit v0.12 From 4ad4d79d418768a1f827cb9a42297c5a8a4737a9 Mon Sep 17 00:00:00 2001 From: dgp Date: Tue, 23 Oct 2018 18:24:50 +0000 Subject: The "end-offset" type is unregistered. No need for a setFromAnyProc. Remove and simplify. --- generic/tclUtil.c | 30 +++++++++--------------------- 1 file changed, 9 insertions(+), 21 deletions(-) diff --git a/generic/tclUtil.c b/generic/tclUtil.c index fca9b75..451167c 100644 --- a/generic/tclUtil.c +++ b/generic/tclUtil.c @@ -113,8 +113,7 @@ static int GetEndOffsetFromObj(Tcl_Obj *objPtr, static Tcl_HashTable * GetThreadHash(Tcl_ThreadDataKey *keyPtr); static int GetWideForIndex(Tcl_Interp *interp, Tcl_Obj *objPtr, Tcl_WideInt endValue, Tcl_WideInt *widePtr); -static int SetEndOffsetFromAny(Tcl_Interp *interp, - Tcl_Obj *objPtr); +static int SetEndOffsetFromAny(Tcl_Obj *objPtr); static int FindElement(Tcl_Interp *interp, const char *string, int stringLength, const char *typeStr, const char *typeCode, const char **elementPtr, @@ -127,7 +126,8 @@ static int FindElement(Tcl_Interp *interp, const char *string, * stored directly in the wideValue, so no memory management is required * for it. This is a caching intrep, keeping the result of a parse * around. This type is only created from a pre-existing string, so an - * updateStringProc will never be called and need not exist. + * updateStringProc will never be called and need not exist. The type + * is unregistered, so has no need of a setFromAnyProc either. */ static const Tcl_ObjType endOffsetType = { @@ -135,7 +135,7 @@ static const Tcl_ObjType endOffsetType = { NULL, /* freeIntRepProc */ NULL, /* dupIntRepProc */ NULL, /* updateStringProc */ - SetEndOffsetFromAny + NULL /* setFromAnyProc */ }; /* @@ -3930,7 +3930,7 @@ GetEndOffsetFromObj( Tcl_WideInt *widePtr) /* Location filled in with an integer * representing an index. */ { - if (SetEndOffsetFromAny(NULL, objPtr) == TCL_OK) { + if (SetEndOffsetFromAny(objPtr) == TCL_OK) { Tcl_WideInt offset = objPtr->internalRep.wideValue; if ((endValue ^ offset) < 0) { @@ -3965,19 +3965,14 @@ GetEndOffsetFromObj( * Results: * Returns TCL_OK if ok, TCL_ERROR if the string was badly formed. * - * Side effects: - * If interp is not NULL, stores an error message in the interpreter - * result. - * *---------------------------------------------------------------------- */ static int SetEndOffsetFromAny( - Tcl_Interp *interp, /* Tcl interpreter or NULL */ Tcl_Obj *objPtr) /* Pointer to the object to parse */ { - Tcl_WideInt offset; /* Offset in the "end-offset" expression */ + Tcl_WideInt offset; /* Offset in the "end-offset" expression */ register const char *bytes; /* String rep of the object */ int length; /* Length of the object's string rep */ @@ -3996,13 +3991,6 @@ SetEndOffsetFromAny( bytes = TclGetStringFromObj(objPtr, &length); if ((*bytes != 'e') || (strncmp(bytes, "end", (size_t)((length > 3) ? 3 : length)) != 0)) { - - badIndexFormat: - if (interp != NULL) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "bad index \"%s\": must be end?[+-]integer?", bytes)); - Tcl_SetErrorCode(interp, "TCL", "VALUE", "INDEX", NULL); - } return TCL_ERROR; } @@ -4021,11 +4009,11 @@ SetEndOffsetFromAny( int t; if (TclIsSpaceProc(bytes[4])) { - goto badIndexFormat; + return TCL_ERROR; } if (TclParseNumber(NULL, objPtr, NULL, bytes+4, length-4, NULL, TCL_PARSE_INTEGER_ONLY) != TCL_OK) { - goto badIndexFormat; + return TCL_ERROR; } TclGetNumberFromObj(NULL, objPtr, &cd, &t); if (t == TCL_NUMBER_BIG) { @@ -4043,7 +4031,7 @@ SetEndOffsetFromAny( } } } else { - goto badIndexFormat; + return TCL_ERROR; } /* -- cgit v0.12 From a883ddbe3e214ba2ffa048e61a6f4641519c460b Mon Sep 17 00:00:00 2001 From: dgp Date: Tue, 23 Oct 2018 18:49:36 +0000 Subject: Refactor the SetEndOffsetFromAny() routine into its only caller. --- generic/tclUtil.c | 161 ++++++++++++++++++++---------------------------------- 1 file changed, 59 insertions(+), 102 deletions(-) diff --git a/generic/tclUtil.c b/generic/tclUtil.c index 451167c..954caff 100644 --- a/generic/tclUtil.c +++ b/generic/tclUtil.c @@ -113,7 +113,6 @@ static int GetEndOffsetFromObj(Tcl_Obj *objPtr, static Tcl_HashTable * GetThreadHash(Tcl_ThreadDataKey *keyPtr); static int GetWideForIndex(Tcl_Interp *interp, Tcl_Obj *objPtr, Tcl_WideInt endValue, Tcl_WideInt *widePtr); -static int SetEndOffsetFromAny(Tcl_Obj *objPtr); static int FindElement(Tcl_Interp *interp, const char *string, int stringLength, const char *typeStr, const char *typeCode, const char **elementPtr, @@ -3930,119 +3929,77 @@ GetEndOffsetFromObj( Tcl_WideInt *widePtr) /* Location filled in with an integer * representing an index. */ { - if (SetEndOffsetFromAny(objPtr) == TCL_OK) { - Tcl_WideInt offset = objPtr->internalRep.wideValue; - - if ((endValue ^ offset) < 0) { - /* Different signs, sum cannot overflow */ - *widePtr = endValue + offset; - } else if (endValue >= 0) { - if (endValue < LLONG_MAX - offset) { - *widePtr = endValue + offset; - } else { - *widePtr = LLONG_MAX; - } - } else { - if (endValue > LLONG_MIN - offset) { - *widePtr = endValue + offset; - } else { - *widePtr = LLONG_MIN; - } - } - return TCL_OK; - } - return TCL_ERROR; -} - -/* - *---------------------------------------------------------------------- - * - * SetEndOffsetFromAny -- - * - * Look for a string of the form "end[+-]offset" and convert it to an - * internal representation holding the offset. - * - * Results: - * Returns TCL_OK if ok, TCL_ERROR if the string was badly formed. - * - *---------------------------------------------------------------------- - */ - -static int -SetEndOffsetFromAny( - Tcl_Obj *objPtr) /* Pointer to the object to parse */ -{ Tcl_WideInt offset; /* Offset in the "end-offset" expression */ - register const char *bytes; /* String rep of the object */ - int length; /* Length of the object's string rep */ - - /* - * If it's already the right type, we're fine. - */ - - if (objPtr->typePtr == &endOffsetType) { - return TCL_OK; - } - - /* - * Check for a string rep of the right form. - */ - - bytes = TclGetStringFromObj(objPtr, &length); - if ((*bytes != 'e') || (strncmp(bytes, "end", - (size_t)((length > 3) ? 3 : length)) != 0)) { - return TCL_ERROR; - } - - /* - * Convert the string rep. - */ - if (length <= 3) { - offset = 0; - } else if ((length > 4) && ((bytes[3] == '-') || (bytes[3] == '+'))) { - /* - * This is our limited string expression evaluator. Pass everything - * after "end-" to TclParseNumber. - */ - ClientData cd; - int t; + if (objPtr->typePtr != &endOffsetType) { + int length; + const char *bytes = TclGetStringFromObj(objPtr, &length); - if (TclIsSpaceProc(bytes[4])) { - return TCL_ERROR; - } - if (TclParseNumber(NULL, objPtr, NULL, bytes+4, length-4, NULL, - TCL_PARSE_INTEGER_ONLY) != TCL_OK) { + if ((*bytes != 'e') || (strncmp(bytes, "end", + (size_t)((length > 3) ? 3 : length)) != 0)) { return TCL_ERROR; } - TclGetNumberFromObj(NULL, objPtr, &cd, &t); - if (t == TCL_NUMBER_BIG) { - /* Truncate to the signed wide range. */ - if (mp_isneg((mp_int *)cd)) { - offset = (bytes[3] == '-') ? LLONG_MAX : LLONG_MIN; + + if (length <= 3) { + offset = 0; + } else if ((length > 4) && ((bytes[3] == '-') || (bytes[3] == '+'))) { + /* + * This is our limited string expression evaluator. Pass everything + * after "end-" to TclParseNumber. + */ + ClientData cd; + int t; + + if (TclIsSpaceProc(bytes[4])) { + return TCL_ERROR; + } + if (TclParseNumber(NULL, objPtr, NULL, bytes+4, length-4, NULL, + TCL_PARSE_INTEGER_ONLY) != TCL_OK) { + return TCL_ERROR; + } + TclGetNumberFromObj(NULL, objPtr, &cd, &t); + if (t == TCL_NUMBER_BIG) { + /* Truncate to the signed wide range. */ + if (mp_isneg((mp_int *)cd)) { + offset = (bytes[3] == '-') ? LLONG_MAX : LLONG_MIN; + } else { + offset = (bytes[3] == '-') ? LLONG_MIN : LLONG_MAX; + } } else { - offset = (bytes[3] == '-') ? LLONG_MIN : LLONG_MAX; + /* assert (t == TCL_NUMBER_INT); */ + offset = (*(Tcl_WideInt *)cd); + if (bytes[3] == '-') { + offset = (offset == LLONG_MIN) ? LLONG_MAX : -offset; + } } } else { - /* assert (t == TCL_NUMBER_INT); */ - offset = (*(Tcl_WideInt *)cd); - if (bytes[3] == '-') { - offset = (offset == LLONG_MIN) ? LLONG_MAX : -offset; - } + return TCL_ERROR; } - } else { - return TCL_ERROR; - } - /* - * The conversion succeeded. Free the old internal rep and set the new - * one. - */ + /* Success. Free the old internal rep and set the new one. */ + TclFreeIntRep(objPtr); + objPtr->internalRep.wideValue = offset; + objPtr->typePtr = &endOffsetType; + } - TclFreeIntRep(objPtr); - objPtr->internalRep.wideValue = offset; - objPtr->typePtr = &endOffsetType; + offset = objPtr->internalRep.wideValue; + if ((endValue ^ offset) < 0) { + /* Different signs, sum cannot overflow */ + *widePtr = endValue + offset; + } else if (endValue >= 0) { + if (endValue < LLONG_MAX - offset) { + *widePtr = endValue + offset; + } else { + *widePtr = LLONG_MAX; + } + } else { + if (endValue > LLONG_MIN - offset) { + *widePtr = endValue + offset; + } else { + *widePtr = LLONG_MIN; + } + } return TCL_OK; } -- cgit v0.12 From 9db751daebe489baa4dd45c402a87af1428b439c Mon Sep 17 00:00:00 2001 From: dgp Date: Tue, 23 Oct 2018 19:01:55 +0000 Subject: End the deprecated practice of accepting "e" and "en" as valid index values. --- generic/tclUtil.c | 8 +++++--- tests/util.test | 8 ++++---- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/generic/tclUtil.c b/generic/tclUtil.c index 954caff..7996703 100644 --- a/generic/tclUtil.c +++ b/generic/tclUtil.c @@ -3935,12 +3935,14 @@ GetEndOffsetFromObj( int length; const char *bytes = TclGetStringFromObj(objPtr, &length); - if ((*bytes != 'e') || (strncmp(bytes, "end", - (size_t)((length > 3) ? 3 : length)) != 0)) { + if ((length < 3) || (length == 4)) { + return TCL_ERROR; + } + if ((*bytes != 'e') || (strncmp(bytes, "end", 3) != 0)) { return TCL_ERROR; } - if (length <= 3) { + if (length == 3) { offset = 0; } else if ((length > 4) && ((bytes[3] == '-') || (bytes[3] == '+'))) { /* diff --git a/tests/util.test b/tests/util.test index 9422fc3..5079a89 100644 --- a/tests/util.test +++ b/tests/util.test @@ -586,14 +586,14 @@ test util-9.2.1 {TclGetIntForIndex} -body { test util-9.2.2 {TclGetIntForIndex} -body { string index abcd {end } } -returnCodes error -match glob -result * -test util-9.3 {TclGetIntForIndex} { +test util-9.3 {TclGetIntForIndex} -body { # Deprecated string index abcd en -} d -test util-9.4 {TclGetIntForIndex} { +} -returnCodes error -match glob -result * +test util-9.4 {TclGetIntForIndex} -body { # Deprecated string index abcd e -} d +} -returnCodes error -match glob -result * test util-9.5.0 {TclGetIntForIndex} { string index abcd end-1 } c -- cgit v0.12 From 7e4b0ec8523a556113f2fa662ed0b0b053d325b8 Mon Sep 17 00:00:00 2001 From: dgp Date: Tue, 23 Oct 2018 19:11:13 +0000 Subject: rework the logic a bit --- generic/tclUtil.c | 57 ++++++++++++++++++++++++++----------------------------- 1 file changed, 27 insertions(+), 30 deletions(-) diff --git a/generic/tclUtil.c b/generic/tclUtil.c index 7996703..6197790 100644 --- a/generic/tclUtil.c +++ b/generic/tclUtil.c @@ -3929,7 +3929,7 @@ GetEndOffsetFromObj( Tcl_WideInt *widePtr) /* Location filled in with an integer * representing an index. */ { - Tcl_WideInt offset; /* Offset in the "end-offset" expression */ + Tcl_WideInt offset = 0; /* Offset in the "end-offset" expression */ if (objPtr->typePtr != &endOffsetType) { int length; @@ -3942,40 +3942,37 @@ GetEndOffsetFromObj( return TCL_ERROR; } - if (length == 3) { - offset = 0; - } else if ((length > 4) && ((bytes[3] == '-') || (bytes[3] == '+'))) { - /* - * This is our limited string expression evaluator. Pass everything - * after "end-" to TclParseNumber. - */ - ClientData cd; - int t; + if (length > 4) { + if ((bytes[3] == '-') || (bytes[3] == '+')) { + ClientData cd; + int t; - if (TclIsSpaceProc(bytes[4])) { - return TCL_ERROR; - } - if (TclParseNumber(NULL, objPtr, NULL, bytes+4, length-4, NULL, - TCL_PARSE_INTEGER_ONLY) != TCL_OK) { - return TCL_ERROR; - } - TclGetNumberFromObj(NULL, objPtr, &cd, &t); - if (t == TCL_NUMBER_BIG) { - /* Truncate to the signed wide range. */ - if (mp_isneg((mp_int *)cd)) { - offset = (bytes[3] == '-') ? LLONG_MAX : LLONG_MIN; + /* Pass everything after "end-" to TclParseNumber. */ + if (TclIsSpaceProc(bytes[4])) { + return TCL_ERROR; + } + if (TCL_OK != TclParseNumber(NULL, objPtr, NULL, + bytes+4, length-4, NULL, TCL_PARSE_INTEGER_ONLY)) { + return TCL_ERROR; + } + TclGetNumberFromObj(NULL, objPtr, &cd, &t); + if (t == TCL_NUMBER_BIG) { + /* Truncate to the signed wide range. */ + if (mp_isneg((mp_int *)cd)) { + offset = (bytes[3] == '-') ? LLONG_MAX : LLONG_MIN; + } else { + offset = (bytes[3] == '-') ? LLONG_MIN : LLONG_MAX; + } } else { - offset = (bytes[3] == '-') ? LLONG_MIN : LLONG_MAX; + /* assert (t == TCL_NUMBER_INT); */ + offset = (*(Tcl_WideInt *)cd); + if (bytes[3] == '-') { + offset = (offset == LLONG_MIN) ? LLONG_MAX : -offset; + } } } else { - /* assert (t == TCL_NUMBER_INT); */ - offset = (*(Tcl_WideInt *)cd); - if (bytes[3] == '-') { - offset = (offset == LLONG_MIN) ? LLONG_MAX : -offset; - } + return TCL_ERROR; } - } else { - return TCL_ERROR; } /* Success. Free the old internal rep and set the new one. */ -- cgit v0.12 From 6457b295e175efa7dd344fc28355da283b64bcbc Mon Sep 17 00:00:00 2001 From: dgp Date: Tue, 23 Oct 2018 23:09:48 +0000 Subject: Streamline and comment combined routine. --- generic/tclUtil.c | 58 ++++++++++++++++++++++++++++++++----------------------- 1 file changed, 34 insertions(+), 24 deletions(-) diff --git a/generic/tclUtil.c b/generic/tclUtil.c index 6197790..fa8c925 100644 --- a/generic/tclUtil.c +++ b/generic/tclUtil.c @@ -3936,42 +3936,52 @@ GetEndOffsetFromObj( const char *bytes = TclGetStringFromObj(objPtr, &length); if ((length < 3) || (length == 4)) { + /* Too short to be "end" or to be "end-$integer" */ return TCL_ERROR; } if ((*bytes != 'e') || (strncmp(bytes, "end", 3) != 0)) { + /* Value doesn't start with "end" */ return TCL_ERROR; } if (length > 4) { - if ((bytes[3] == '-') || (bytes[3] == '+')) { - ClientData cd; - int t; + ClientData cd; + int t; - /* Pass everything after "end-" to TclParseNumber. */ - if (TclIsSpaceProc(bytes[4])) { - return TCL_ERROR; - } - if (TCL_OK != TclParseNumber(NULL, objPtr, NULL, + /* Parse for the "end-..." or "end+..." formats */ + + if ((bytes[3] != '-') && (bytes[3] != '+')) { + /* No operator where we need one */ + return TCL_ERROR; + } + if (TclIsSpaceProc(bytes[4])) { + /* Space after + or - not permitted. */ + return TCL_ERROR; + } + + /* Parse the integer offset */ + if (TCL_OK != TclParseNumber(NULL, objPtr, NULL, bytes+4, length-4, NULL, TCL_PARSE_INTEGER_ONLY)) { - return TCL_ERROR; - } - TclGetNumberFromObj(NULL, objPtr, &cd, &t); - if (t == TCL_NUMBER_BIG) { - /* Truncate to the signed wide range. */ - if (mp_isneg((mp_int *)cd)) { - offset = (bytes[3] == '-') ? LLONG_MAX : LLONG_MIN; - } else { - offset = (bytes[3] == '-') ? LLONG_MIN : LLONG_MAX; - } + /* Not a recognized integer format */ + return TCL_ERROR; + } + + /* Got an integer offset; pull it from where parser left it. */ + TclGetNumberFromObj(NULL, objPtr, &cd, &t); + + if (t == TCL_NUMBER_BIG) { + /* Truncate to the signed wide range. */ + if (mp_isneg((mp_int *)cd)) { + offset = (bytes[3] == '-') ? LLONG_MAX : LLONG_MIN; } else { - /* assert (t == TCL_NUMBER_INT); */ - offset = (*(Tcl_WideInt *)cd); - if (bytes[3] == '-') { - offset = (offset == LLONG_MIN) ? LLONG_MAX : -offset; - } + offset = (bytes[3] == '-') ? LLONG_MIN : LLONG_MAX; } } else { - return TCL_ERROR; + /* assert (t == TCL_NUMBER_INT); */ + offset = (*(Tcl_WideInt *)cd); + if (bytes[3] == '-') { + offset = (offset == LLONG_MIN) ? LLONG_MAX : -offset; + } } } -- cgit v0.12