diff options
author | sebres <sebres@users.sourceforge.net> | 2024-06-12 19:17:01 (GMT) |
---|---|---|
committer | sebres <sebres@users.sourceforge.net> | 2024-06-12 19:17:01 (GMT) |
commit | e2a30b162b9d0b8a4751eeae177ebd3dfadc2f75 (patch) | |
tree | badd4c6a1bdb3a4f2f01e375a3cf0c1bc1af1d38 /generic | |
parent | d25acf4fe1b750bbb6934d1d6e1824a9ff7d17a1 (diff) | |
parent | c0602af1ad679af5d001d79c58d9811ef9cc476a (diff) | |
download | tcl-e2a30b162b9d0b8a4751eeae177ebd3dfadc2f75.zip tcl-e2a30b162b9d0b8a4751eeae177ebd3dfadc2f75.tar.gz tcl-e2a30b162b9d0b8a4751eeae177ebd3dfadc2f75.tar.bz2 |
merge 8.7
Diffstat (limited to 'generic')
-rw-r--r-- | generic/tclCmdIL.c | 175 | ||||
-rw-r--r-- | generic/tclExecute.c | 10 | ||||
-rw-r--r-- | generic/tclInt.h | 1 |
3 files changed, 88 insertions, 98 deletions
diff --git a/generic/tclCmdIL.c b/generic/tclCmdIL.c index ad8eb94..836b859 100644 --- a/generic/tclCmdIL.c +++ b/generic/tclCmdIL.c @@ -102,11 +102,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; /* @@ -4030,47 +4030,59 @@ 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) { + /* speed-up a bit (and avoid shimmer for compiled expressions) */ + if (TclHasInternalRep(argPtr, &tclExprCodeType)) { + goto doExpr; + } + 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; + } + doExpr: + /* 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; } } @@ -4122,7 +4134,8 @@ Tcl_LseqObjCmd( Tcl_WideInt values[5]; Tcl_Obj *numValues[5]; Tcl_Obj *numberObj; - int status = TCL_ERROR, keyword, useDoubles = 0; + int status = TCL_ERROR, keyword, useDoubles = 0, allowedArgs = NumericArg; + int remNums = 3; Tcl_Obj *arithSeriesPtr; SequenceOperators opmode; SequenceDecoded decoded; @@ -4137,42 +4150,50 @@ Tcl_LseqObjCmd( * digit. */ if (objc > 6) { - /* Too many arguments */ - arg_key=0; - } else for (i=1; i<objc; i++) { - arg_key = (arg_key * 10); - numValues[value_i] = NULL; - decoded = SequenceIdentifyArgument(interp, objv[i], &numberObj, &keyword); - switch (decoded) { - - case NoneArg: - /* - * Unrecognizable argument - * Reproduce operation error message - */ - status = Tcl_GetIndexFromObj(interp, objv[i], seq_operations, - "operation", 0, &opmode); - goto done; - - case NumericArg: - arg_key += NumericArg; - numValues[value_i] = numberObj; - values[value_i] = keyword; // This is the TCL_NUMBER_* value - useDoubles = useDoubles ? useDoubles : keyword == TCL_NUMBER_DOUBLE; - value_i++; - break; - - case RangeKeywordArg: - arg_key += RangeKeywordArg; - values[value_i] = keyword; - value_i++; - break; - - default: - arg_key += 9; // Error state - value_i++; - break; - } + /* Too many arguments */ + goto syntax; + } + for (i = 1; i < objc; i++) { + arg_key = (arg_key * 10); + numValues[value_i] = NULL; + decoded = SequenceIdentifyArgument(interp, objv[i], + allowedArgs | (i == objc-1 ? LastArg : 0), + &numberObj, &keyword); + switch (decoded) { + case NoneArg: + /* + * Unrecognizable argument + * Reproduce operation error message + */ + status = Tcl_GetIndexFromObj(interp, objv[i], seq_operations, + "operation", 0, &opmode); + goto done; + + case NumericArg: + remNums--; + arg_key += NumericArg; + allowedArgs = RangeKeywordArg; + /* if last number but 2 arguments remain, next is not numeric */ + if ((remNums != 1) || ((objc-1-i) != 2)) { + allowedArgs |= NumericArg; + } + numValues[value_i] = numberObj; + values[value_i] = keyword; /* TCL_NUMBER_* */ + useDoubles |= (keyword == TCL_NUMBER_DOUBLE) ? 1 : 0; + value_i++; + break; + + case RangeKeywordArg: + arg_key += RangeKeywordArg; + allowedArgs = NumericArg; /* after keyword always numeric only */ + values[value_i] = keyword; /* SequenceOperators */ + value_i++; + break; + + default: /* Error state */ + status = TCL_ERROR; + goto done; + } } /* @@ -4181,13 +4202,6 @@ Tcl_LseqObjCmd( */ switch (arg_key) { -/* No argument */ - case 0: - Tcl_WrongNumArgs(interp, 1, objv, - "n ??op? n ??by? n??"); - goto done; - break; - /* lseq n */ case 1: start = zero; @@ -4309,34 +4323,9 @@ Tcl_LseqObjCmd( } break; -/* Error cases: incomplete arguments */ - case 12: - opmode = (SequenceOperators)values[1]; goto KeywordError; break; - case 112: - opmode = (SequenceOperators)values[2]; goto KeywordError; break; - case 1212: - opmode = (SequenceOperators)values[3]; goto KeywordError; break; - KeywordError: - switch (opmode) { - case LSEQ_DOTS: - case LSEQ_TO: - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "missing \"to\" value.")); - break; - case LSEQ_COUNT: - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "missing \"count\" value.")); - break; - case LSEQ_BY: - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "missing \"by\" value.")); - break; - } - goto done; - break; - /* All other argument errors */ default: + syntax: Tcl_WrongNumArgs(interp, 1, objv, "n ??op? n ??by? n??"); goto done; break; diff --git a/generic/tclExecute.c b/generic/tclExecute.c index 5d4bff3..fab8590 100644 --- a/generic/tclExecute.c +++ b/generic/tclExecute.c @@ -659,7 +659,7 @@ static Tcl_NRPostProc TEBCresume; * compiled bytecode for Tcl expressions. */ -static const Tcl_ObjType exprCodeType = { +const Tcl_ObjType tclExprCodeType = { "exprcode", FreeExprCodeInternalRep, /* freeIntRepProc */ DupExprCodeInternalRep, /* dupIntRepProc */ @@ -1417,7 +1417,7 @@ CompileExprObj( * is valid in the current context. */ - ByteCodeGetInternalRep(objPtr, &exprCodeType, codePtr); + ByteCodeGetInternalRep(objPtr, &tclExprCodeType, codePtr); if (codePtr != NULL) { Namespace *namespacePtr = iPtr->varFramePtr->nsPtr; @@ -1427,7 +1427,7 @@ CompileExprObj( || (codePtr->nsPtr != namespacePtr) || (codePtr->nsEpoch != namespacePtr->resolverEpoch) || (codePtr->localCachePtr != iPtr->varFramePtr->localCachePtr)) { - Tcl_StoreInternalRep(objPtr, &exprCodeType, NULL); + Tcl_StoreInternalRep(objPtr, &tclExprCodeType, NULL); codePtr = NULL; } } @@ -1460,7 +1460,7 @@ CompileExprObj( */ TclEmitOpcode(INST_DONE, &compEnv); - codePtr = TclInitByteCodeObj(objPtr, &exprCodeType, &compEnv); + codePtr = TclInitByteCodeObj(objPtr, &tclExprCodeType, &compEnv); TclFreeCompileEnv(&compEnv); if (iPtr->varFramePtr->localCachePtr) { codePtr->localCachePtr = iPtr->varFramePtr->localCachePtr; @@ -1529,7 +1529,7 @@ FreeExprCodeInternalRep( Tcl_Obj *objPtr) { ByteCode *codePtr; - ByteCodeGetInternalRep(objPtr, &exprCodeType, codePtr); + ByteCodeGetInternalRep(objPtr, &tclExprCodeType, codePtr); assert(codePtr != NULL); TclReleaseByteCode(codePtr); diff --git a/generic/tclInt.h b/generic/tclInt.h index 70bc4b8..ae91625 100644 --- a/generic/tclInt.h +++ b/generic/tclInt.h @@ -3109,6 +3109,7 @@ MODULE_SCOPE const Tcl_ObjType tclBignumType; MODULE_SCOPE const Tcl_ObjType tclBooleanType; MODULE_SCOPE const Tcl_ObjType tclByteCodeType; MODULE_SCOPE const Tcl_ObjType tclDoubleType; +MODULE_SCOPE const Tcl_ObjType tclExprCodeType; MODULE_SCOPE const Tcl_ObjType tclIntType; MODULE_SCOPE const Tcl_ObjType tclIndexType; MODULE_SCOPE const Tcl_ObjType tclListType; |