From ae37f9b450b457ba32bf5e217d37ff30fac41799 Mon Sep 17 00:00:00 2001 From: sebres Date: Wed, 12 Jun 2024 19:01:35 +0000 Subject: more fixes for [f05f5ef759c1f7f9]: don't swallow expr errors, further code review and simplification --- generic/tclCmdIL.c | 173 ++++++++++++++++++++++++----------------------------- tests/lseq.test | 13 +++- 2 files changed, 87 insertions(+), 99 deletions(-) diff --git a/generic/tclCmdIL.c b/generic/tclCmdIL.c index 135ee28..19bc596 100644 --- a/generic/tclCmdIL.c +++ b/generic/tclCmdIL.c @@ -101,11 +101,11 @@ typedef struct { static const char *const seq_operations[] = { "..", "to", "count", "by", NULL }; -typedef enum Sequence_Operators { +typedef enum { LSEQ_DOTS, LSEQ_TO, LSEQ_COUNT, LSEQ_BY } SequenceOperators; -typedef enum Sequence_Decoded { - NoneArg, NumericArg, RangeKeywordArg +typedef enum { + NoneArg, NumericArg, RangeKeywordArg, ErrArg, LastArg = 8 } SequenceDecoded; /* @@ -4020,47 +4020,54 @@ static SequenceDecoded SequenceIdentifyArgument( Tcl_Interp *interp, /* for error reporting */ Tcl_Obj *argPtr, /* Argument to decode */ + int allowedArgs, /* Flags if keyword or numeric allowed. */ Tcl_Obj **numValuePtr, /* Return numeric value */ int *keywordIndexPtr) /* Return keyword enum */ { - int result; + int result = TCL_ERROR; SequenceOperators opmode; void *internalPtr; - result = Tcl_GetNumberFromObj(NULL, argPtr, &internalPtr, keywordIndexPtr); - if (result == TCL_OK) { - *numValuePtr = argPtr; - Tcl_IncrRefCount(argPtr); - return NumericArg; + if (allowedArgs & NumericArg) { + result = Tcl_GetNumberFromObj(NULL, argPtr, &internalPtr, keywordIndexPtr); + if (result == TCL_OK) { + *numValuePtr = argPtr; + Tcl_IncrRefCount(argPtr); + return NumericArg; + } + } + if (allowedArgs & RangeKeywordArg) { + result = Tcl_GetIndexFromObj(NULL, argPtr, seq_operations, + "range operation", 0, &opmode); } - - result = Tcl_GetIndexFromObj(NULL, argPtr, seq_operations, - "range operation", 0, &opmode); if (result == TCL_OK) { + if (allowedArgs & LastArg) { + /* keyword found, but no followed number */ + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "missing \"%s\" value.", TclGetString(argPtr))); + return ErrArg; + } *keywordIndexPtr = opmode; return RangeKeywordArg; } else { - /* Check for an index expression */ - SequenceDecoded ret = NoneArg; Tcl_Obj *exprValueObj; + if (!(allowedArgs & NumericArg)) { + return NoneArg; + } + /* Check for an index expression */ int keyword; - Tcl_InterpState savedstate; - savedstate = Tcl_SaveInterpState(interp, result); if (Tcl_ExprObj(interp, argPtr, &exprValueObj) != TCL_OK) { - goto done; + return ErrArg; } /* Determine if result of expression is double or int */ - if (Tcl_GetNumberFromObj(NULL, exprValueObj, &internalPtr, + if (Tcl_GetNumberFromObj(interp, exprValueObj, &internalPtr, &keyword) != TCL_OK ) { - goto done; + return ErrArg; } *numValuePtr = exprValueObj; /* incremented in Tcl_ExprObj */ *keywordIndexPtr = keyword; /* type of expression result */ - ret = NumericArg; - done: - (void)Tcl_RestoreInterpState(interp, savedstate); - return ret; + return NumericArg; } } @@ -4112,7 +4119,8 @@ Tcl_LseqObjCmd( Tcl_WideInt values[5]; Tcl_Obj *numValues[5]; Tcl_Obj *numberObj; - int status, keyword, useDoubles = 0; + int status, keyword, useDoubles = 0, allowedArgs = NumericArg; + int remNums = 3; Tcl_Obj *arithSeriesPtr; SequenceOperators opmode; SequenceDecoded decoded; @@ -4127,42 +4135,50 @@ Tcl_LseqObjCmd( * digit. */ if (objc > 6) { - /* Too many arguments */ - arg_key=0; - } else for (i=1; i