Diff
Not logged in

Differences From Artifact [d0a8b95693]:

To Artifact [e5973c7251]:


1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
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 $
 * 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
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_Interp *interp = infoPtr->interp;
    Interp *iPtr = (Interp *) interp;
    Tcl_DString cmdName;
    int objIndex;
    MathFunc *mathFuncPtr;
    Tcl_HashEntry *hPtr;
    Tcl_Token *tokenPtr, *afterSubexprPtr;
    int argCount;
    int code, i;

    int code = TCL_OK;
		       
    /*
     * Look up the MathFunc record for the function.
     * 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.
     */

    code = TCL_OK;
    Tcl_DStringInit( &cmdName );
    hPtr = Tcl_FindHashEntry(&iPtr->mathFuncTable, funcName);
    if (hPtr == NULL) {
	Tcl_AppendResult(interp, "unknown math function \"", funcName,
    Tcl_DStringAppend( &cmdName, "tcl::mathfunc::", -1 );
    Tcl_DStringAppend( &cmdName, funcName, -1 );
		"\"", (char *) NULL);
	code = TCL_ERROR;
    objIndex = TclRegisterNewNSLiteral( envPtr,
	goto done;
    }
    mathFuncPtr = (MathFunc *) Tcl_GetHashValue(hPtr);

					 Tcl_DStringValue( &cmdName ),
    /*
     * If not a builtin function, push an object with the function's name.
     */

					 Tcl_DStringLength( &cmdName ) );
    if (mathFuncPtr->builtinFuncIndex < 0) {
	TclEmitPush(TclRegisterNewLiteral(envPtr, funcName, -1), envPtr);
    TclEmitPush( objIndex, envPtr );
    }
    Tcl_DStringFree( &cmdName );

    /*
     * Compile any arguments for the function.
     */

    argCount = 1;
    tokenPtr = exprTokenPtr+2;
    afterSubexprPtr = exprTokenPtr + (exprTokenPtr->numComponents + 1);
    if (mathFuncPtr->numArgs > 0) {
	for (i = 0;  i < mathFuncPtr->numArgs;  i++) {
	    if (tokenPtr == afterSubexprPtr) {
    while (tokenPtr != afterSubexprPtr) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
		        "too few arguments for math function", -1));
	++argCount;
		code = TCL_ERROR;
		goto done;
	    }
	    code = CompileSubExpr(tokenPtr, infoPtr, envPtr);
	    if (code != TCL_OK) {
	code = CompileSubExpr(tokenPtr, infoPtr, envPtr);
	if (code != TCL_OK) {
		goto done;
	    }
	    tokenPtr += (tokenPtr->numComponents + 1);
	}
	    return code;
	}
	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.
    /* Invoke the function */
     */

    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 ( argCount < 255 ) {
	if (envPtr->maxStackDepth < envPtr->currStackDepth) {
	    envPtr->maxStackDepth = envPtr->currStackDepth;
	}
	TclEmitInstInt1(INST_CALL_BUILTIN_FUNC1,
	TclEmitInstInt1( INST_INVOKE_STK1, argCount, envPtr );
	        mathFuncPtr->builtinFuncIndex, envPtr);
	envPtr->currStackDepth -= mathFuncPtr->numArgs;
    } else {
	TclEmitInstInt1(INST_CALL_FUNC1, (mathFuncPtr->numArgs+1), envPtr);
	TclEmitInstInt4( INST_INVOKE_STK4, argCount, envPtr );
    }
    *endPtrPtr = afterSubexprPtr;

    done:
    return code;
    *endPtrPtr = afterSubexprPtr;
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * LogSyntaxError --
 *