1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
/*
* tclCompExpr.c --
*
* This file contains the code to compile Tcl expressions.
*
* Copyright (c) 1997 Sun Microsystems, Inc.
* Copyright (c) 1998-2000 by Scriptics Corporation.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
* RCS: @(#) $Id: tclCompExpr.c,v 1.25 2004/10/08 15:39:52 dkf Exp $
*/
#include "tclInt.h"
#include "tclCompile.h"
/*
* The stuff below is a bit of a hack so that this file can be used in
|
|
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
/*
* tclCompExpr.c --
*
* This file contains the code to compile Tcl expressions.
*
* Copyright (c) 1997 Sun Microsystems, Inc.
* Copyright (c) 1998-2000 by Scriptics Corporation.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
* RCS: @(#) $Id: tclCompExpr.c,v 1.26 2005/05/10 18:34:11 kennykb Exp $
*/
#include "tclInt.h"
#include "tclCompile.h"
/*
* The stuff below is a bit of a hack so that this file can be used in
|
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
|
ExprInfo *infoPtr; /* Describes the compilation state for the
* expression being compiled. */
CompileEnv *envPtr; /* Holds resulting instructions. */
Tcl_Token **endPtrPtr; /* If successful, a pointer to the token
* just after the last token in the
* subexpression is stored here. */
{
Tcl_Interp *interp = infoPtr->interp;
Interp *iPtr = (Interp *) interp;
MathFunc *mathFuncPtr;
Tcl_HashEntry *hPtr;
Tcl_Token *tokenPtr, *afterSubexprPtr;
int code, i;
/*
* Look up the MathFunc record for the function.
*/
code = TCL_OK;
hPtr = Tcl_FindHashEntry(&iPtr->mathFuncTable, funcName);
if (hPtr == NULL) {
Tcl_AppendResult(interp, "unknown math function \"", funcName,
"\"", (char *) NULL);
code = TCL_ERROR;
goto done;
}
mathFuncPtr = (MathFunc *) Tcl_GetHashValue(hPtr);
/*
* If not a builtin function, push an object with the function's name.
*/
if (mathFuncPtr->builtinFuncIndex < 0) {
TclEmitPush(TclRegisterNewLiteral(envPtr, funcName, -1), envPtr);
}
/*
* Compile any arguments for the function.
*/
tokenPtr = exprTokenPtr+2;
afterSubexprPtr = exprTokenPtr + (exprTokenPtr->numComponents + 1);
if (mathFuncPtr->numArgs > 0) {
for (i = 0; i < mathFuncPtr->numArgs; i++) {
if (tokenPtr == afterSubexprPtr) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"too few arguments for math function", -1));
code = TCL_ERROR;
goto done;
}
code = CompileSubExpr(tokenPtr, infoPtr, envPtr);
if (code != TCL_OK) {
goto done;
}
tokenPtr += (tokenPtr->numComponents + 1);
}
if (tokenPtr != afterSubexprPtr) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"too many arguments for math function", -1));
code = TCL_ERROR;
goto done;
}
} else if (tokenPtr != afterSubexprPtr) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"too many arguments for math function", -1));
code = TCL_ERROR;
goto done;
}
/*
* Compile the call on the math function. Note that the "objc" argument
* count for non-builtin functions is incremented by 1 to include the
* function name itself.
*/
if (mathFuncPtr->builtinFuncIndex >= 0) { /* a builtin function */
/*
* Adjust the current stack depth by the number of arguments
* of the builtin function. This cannot be handled by the
* TclEmitInstInt1 macro as the number of arguments is not
* passed as an operand.
*/
if (envPtr->maxStackDepth < envPtr->currStackDepth) {
envPtr->maxStackDepth = envPtr->currStackDepth;
}
TclEmitInstInt1(INST_CALL_BUILTIN_FUNC1,
mathFuncPtr->builtinFuncIndex, envPtr);
envPtr->currStackDepth -= mathFuncPtr->numArgs;
} else {
TclEmitInstInt1(INST_CALL_FUNC1, (mathFuncPtr->numArgs+1), envPtr);
}
*endPtrPtr = afterSubexprPtr;
done:
return code;
}
/*
*----------------------------------------------------------------------
*
* LogSyntaxError --
*
|
|
|
<
<
>
|
|
|
>
>
>
|
<
<
>
|
<
|
<
<
<
|
<
<
<
|
<
|
<
>
>
<
<
|
<
|
<
<
<
|
|
<
>
|
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
|
<
<
<
|
<
<
|
<
<
>
|
|
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
|
ExprInfo *infoPtr; /* Describes the compilation state for the
* expression being compiled. */
CompileEnv *envPtr; /* Holds resulting instructions. */
Tcl_Token **endPtrPtr; /* If successful, a pointer to the token
* just after the last token in the
* subexpression is stored here. */
{
Tcl_DString cmdName;
int objIndex;
Tcl_Token *tokenPtr, *afterSubexprPtr;
int argCount;
int code = TCL_OK;
/*
* Prepend "tcl::mathfunc::" to the function name, to produce the
* name of a command that evaluates the function. Push that
* command name on the stack, in a literal registered to the
* namespace so that resolution can be cached.
*/
Tcl_DStringInit( &cmdName );
Tcl_DStringAppend( &cmdName, "tcl::mathfunc::", -1 );
Tcl_DStringAppend( &cmdName, funcName, -1 );
objIndex = TclRegisterNewNSLiteral( envPtr,
Tcl_DStringValue( &cmdName ),
Tcl_DStringLength( &cmdName ) );
TclEmitPush( objIndex, envPtr );
Tcl_DStringFree( &cmdName );
/*
* Compile any arguments for the function.
*/
argCount = 1;
tokenPtr = exprTokenPtr+2;
afterSubexprPtr = exprTokenPtr + (exprTokenPtr->numComponents + 1);
while (tokenPtr != afterSubexprPtr) {
++argCount;
code = CompileSubExpr(tokenPtr, infoPtr, envPtr);
if (code != TCL_OK) {
return code;
}
tokenPtr += (tokenPtr->numComponents + 1);
}
/* Invoke the function */
if ( argCount < 255 ) {
TclEmitInstInt1( INST_INVOKE_STK1, argCount, envPtr );
} else {
TclEmitInstInt4( INST_INVOKE_STK4, argCount, envPtr );
}
*endPtrPtr = afterSubexprPtr;
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* LogSyntaxError --
*
|