os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/generic/tclCompExpr.c
Update contrib.
4 * This file contains the code to compile Tcl expressions.
6 * Copyright (c) 1997 Sun Microsystems, Inc.
7 * Copyright (c) 1998-2000 by Scriptics Corporation.
8 * Portions Copyright (c) 2007 Nokia Corporation and/or its subsidiaries. All rights reserved.
10 * See the file "license.terms" for information on usage and redistribution
11 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
13 * RCS: @(#) $Id: tclCompExpr.c,v 1.13.2.3 2006/11/28 22:20:00 andreas_kupries Exp $
17 #include "tclCompile.h"
18 #if defined(__SYMBIAN32__)
19 #include "tclSymbianGlobals.h"
23 * The stuff below is a bit of a hack so that this file can be used in
24 * environments that include no UNIX, i.e. no errno: just arrange to use
25 * the errno from tclExecute.c here.
28 #ifndef TCL_GENERIC_ONLY
35 extern int errno; /* Use errno from tclExecute.c. */
40 * Boolean variable that controls whether expression compilation tracing
44 #ifdef TCL_COMPILE_DEBUG
45 static int traceExprComp = 0;
46 #endif /* TCL_COMPILE_DEBUG */
49 * The ExprInfo structure describes the state of compiling an expression.
50 * A pointer to an ExprInfo record is passed among the routines in
54 typedef struct ExprInfo {
55 Tcl_Interp *interp; /* Used for error reporting. */
56 Tcl_Parse *parsePtr; /* Structure filled with information about
57 * the parsed expression. */
58 CONST char *expr; /* The expression that was originally passed
59 * to TclCompileExpr. */
60 CONST char *lastChar; /* Points just after last byte of expr. */
61 int hasOperators; /* Set 1 if the expr has operators; 0 if
62 * expr is only a primary. If 1 after
63 * compiling an expr, a tryCvtToNumeric
64 * instruction is emitted to convert the
65 * primary to a number if possible. */
69 * Definitions of numeric codes representing each expression operator.
70 * The order of these must match the entries in the operatorTable below.
71 * Also the codes for the relational operators (OP_LESS, OP_GREATER,
72 * OP_LE, OP_GE, OP_EQ, and OP_NE) must be consecutive and in that order.
73 * Note that OP_PLUS and OP_MINUS represent both unary and binary operators.
101 * Table describing the expression operators. Entries in this table must
102 * correspond to the definitions of numeric codes for operators just above.
104 #if !defined(__SYMBIAN32__) || !defined(__WINSCW__)
105 static int opTableInitialized = 0; /* 0 means not yet initialized. */
108 TCL_DECLARE_MUTEX(opMutex)
110 typedef struct OperatorDesc {
111 char *name; /* Name of the operator. */
112 int numOperands; /* Number of operands. 0 if the operator
113 * requires special handling. */
114 int instruction; /* Instruction opcode for the operator.
115 * Ignored if numOperands is 0. */
118 static OperatorDesc operatorTable[] = {
124 {"<<", 2, INST_LSHIFT},
125 {">>", 2, INST_RSHIFT},
132 {"&", 2, INST_BITAND},
133 {"^", 2, INST_BITXOR},
134 {"|", 2, INST_BITOR},
139 {"~", 1, INST_BITNOT},
140 {"eq", 2, INST_STR_EQ},
141 {"ne", 2, INST_STR_NEQ},
145 #if !defined(__SYMBIAN32__) || !defined(__WINSCW__)
147 * Hashtable used to map the names of expression operators to the index
148 * of their OperatorDesc description.
150 static Tcl_HashTable opHashTable;
154 * Declarations for local procedures to this file:
157 static int CompileCondExpr _ANSI_ARGS_((
158 Tcl_Token *exprTokenPtr, ExprInfo *infoPtr,
159 CompileEnv *envPtr, Tcl_Token **endPtrPtr));
160 static int CompileLandOrLorExpr _ANSI_ARGS_((
161 Tcl_Token *exprTokenPtr, int opIndex,
162 ExprInfo *infoPtr, CompileEnv *envPtr,
163 Tcl_Token **endPtrPtr));
164 static int CompileMathFuncCall _ANSI_ARGS_((
165 Tcl_Token *exprTokenPtr, CONST char *funcName,
166 ExprInfo *infoPtr, CompileEnv *envPtr,
167 Tcl_Token **endPtrPtr));
168 static int CompileSubExpr _ANSI_ARGS_((
169 Tcl_Token *exprTokenPtr, ExprInfo *infoPtr,
170 CompileEnv *envPtr));
171 static void LogSyntaxError _ANSI_ARGS_((ExprInfo *infoPtr));
174 * Macro used to debug the execution of the expression compiler.
177 #ifdef TCL_COMPILE_DEBUG
178 #define TRACE(exprBytes, exprLength, tokenBytes, tokenLength) \
179 if (traceExprComp) { \
180 fprintf(stderr, "CompileSubExpr: \"%.*s\", token \"%.*s\"\n", \
181 (exprLength), (exprBytes), (tokenLength), (tokenBytes)); \
184 #define TRACE(exprBytes, exprLength, tokenBytes, tokenLength)
185 #endif /* TCL_COMPILE_DEBUG */
188 *----------------------------------------------------------------------
192 * This procedure compiles a string containing a Tcl expression into
193 * Tcl bytecodes. This procedure is the top-level interface to the
194 * the expression compilation module, and is used by such public
195 * procedures as Tcl_ExprString, Tcl_ExprStringObj, Tcl_ExprLong,
196 * Tcl_ExprDouble, Tcl_ExprBoolean, and Tcl_ExprBooleanObj.
199 * The return value is TCL_OK on a successful compilation and TCL_ERROR
200 * on failure. If TCL_ERROR is returned, then the interpreter's result
201 * contains an error message.
204 * Adds instructions to envPtr to evaluate the expression at runtime.
206 *----------------------------------------------------------------------
210 TclCompileExpr(interp, script, numBytes, envPtr)
211 Tcl_Interp *interp; /* Used for error reporting. */
212 CONST char *script; /* The source script to compile. */
213 int numBytes; /* Number of bytes in script. If < 0, the
214 * string consists of all bytes up to the
215 * first null character. */
216 CompileEnv *envPtr; /* Holds resulting instructions. */
224 * If this is the first time we've been called, initialize the table
225 * of expression operators.
229 numBytes = (script? strlen(script) : 0);
231 if (!opTableInitialized) {
232 Tcl_MutexLock(&opMutex);
233 if (!opTableInitialized) {
234 Tcl_InitHashTable(&opHashTable, TCL_STRING_KEYS);
235 for (i = 0; operatorTable[i].name != NULL; i++) {
236 hPtr = Tcl_CreateHashEntry(&opHashTable,
237 operatorTable[i].name, &new);
239 Tcl_SetHashValue(hPtr, (ClientData) i);
242 opTableInitialized = 1;
244 Tcl_MutexUnlock(&opMutex);
248 * Initialize the structure containing information abvout this
249 * expression compilation.
252 info.interp = interp;
253 info.parsePtr = &parse;
255 info.lastChar = (script + numBytes);
256 info.hasOperators = 0;
259 * Parse the expression then compile it.
262 code = Tcl_ParseExpr(interp, script, numBytes, &parse);
263 if (code != TCL_OK) {
268 /* TIP #280 : Track Lines within the expression */
269 TclAdvanceLines (&envPtr->line, script, parse.tokenPtr->start);
272 code = CompileSubExpr(parse.tokenPtr, &info, envPtr);
273 if (code != TCL_OK) {
274 Tcl_FreeParse(&parse);
278 if (!info.hasOperators) {
280 * Attempt to convert the primary's object to an int or double.
281 * This is done in order to support Tcl's policy of interpreting
282 * operands if at all possible as first integers, else
283 * floating-point numbers.
286 TclEmitOpcode(INST_TRY_CVT_TO_NUMERIC, envPtr);
288 Tcl_FreeParse(&parse);
295 *----------------------------------------------------------------------
297 * TclFinalizeCompilation --
299 * Clean up the compilation environment so it can later be
300 * properly reinitialized. This procedure is called by Tcl_Finalize().
306 * Cleans up the compilation environment. At the moment, just the
307 * table of expression operators is freed.
309 *----------------------------------------------------------------------
313 TclFinalizeCompilation()
315 Tcl_MutexLock(&opMutex);
316 if (opTableInitialized) {
317 Tcl_DeleteHashTable(&opHashTable);
318 opTableInitialized = 0;
320 Tcl_MutexUnlock(&opMutex);
324 *----------------------------------------------------------------------
328 * Given a pointer to a TCL_TOKEN_SUB_EXPR token describing a
329 * subexpression, this procedure emits instructions to evaluate the
330 * subexpression at runtime.
333 * The return value is TCL_OK on a successful compilation and TCL_ERROR
334 * on failure. If TCL_ERROR is returned, then the interpreter's result
335 * contains an error message.
338 * Adds instructions to envPtr to evaluate the subexpression.
340 *----------------------------------------------------------------------
344 CompileSubExpr(exprTokenPtr, infoPtr, envPtr)
345 Tcl_Token *exprTokenPtr; /* Points to TCL_TOKEN_SUB_EXPR token
347 ExprInfo *infoPtr; /* Describes the compilation state for the
348 * expression being compiled. */
349 CompileEnv *envPtr; /* Holds resulting instructions. */
351 Tcl_Interp *interp = infoPtr->interp;
352 Tcl_Token *tokenPtr, *endPtr = NULL; /* silence gcc 4 warning */
353 Tcl_Token *afterSubexprPtr;
354 OperatorDesc *opDescPtr;
356 CONST char *operator;
358 int objIndex, opIndex, length, code;
359 char buffer[TCL_UTF_MAX];
361 if (exprTokenPtr->type != TCL_TOKEN_SUB_EXPR) {
362 panic("CompileSubExpr: token type %d not TCL_TOKEN_SUB_EXPR\n",
368 * Switch on the type of the first token after the subexpression token.
369 * After processing it, advance tokenPtr to point just after the
370 * subexpression's last token.
373 tokenPtr = exprTokenPtr+1;
374 TRACE(exprTokenPtr->start, exprTokenPtr->size,
375 tokenPtr->start, tokenPtr->size);
376 switch (tokenPtr->type) {
378 code = TclCompileTokens(interp, tokenPtr+1,
379 tokenPtr->numComponents, envPtr);
380 if (code != TCL_OK) {
383 tokenPtr += (tokenPtr->numComponents + 1);
387 if (tokenPtr->size > 0) {
388 objIndex = TclRegisterNewLiteral(envPtr, tokenPtr->start,
391 objIndex = TclRegisterNewLiteral(envPtr, "", 0);
393 TclEmitPush(objIndex, envPtr);
398 length = Tcl_UtfBackslash(tokenPtr->start, (int *) NULL,
401 objIndex = TclRegisterNewLiteral(envPtr, buffer, length);
403 objIndex = TclRegisterNewLiteral(envPtr, "", 0);
405 TclEmitPush(objIndex, envPtr);
409 case TCL_TOKEN_COMMAND:
410 code = TclCompileScript(interp, tokenPtr->start+1,
411 tokenPtr->size-2, /*nested*/ 0, envPtr);
412 if (code != TCL_OK) {
418 case TCL_TOKEN_VARIABLE:
419 code = TclCompileTokens(interp, tokenPtr, 1, envPtr);
420 if (code != TCL_OK) {
423 tokenPtr += (tokenPtr->numComponents + 1);
426 case TCL_TOKEN_SUB_EXPR:
427 code = CompileSubExpr(tokenPtr, infoPtr, envPtr);
428 if (code != TCL_OK) {
431 tokenPtr += (tokenPtr->numComponents + 1);
434 case TCL_TOKEN_OPERATOR:
436 * Look up the operator. If the operator isn't found, treat it
437 * as a math function.
439 Tcl_DStringInit(&opBuf);
440 operator = Tcl_DStringAppend(&opBuf,
441 tokenPtr->start, tokenPtr->size);
442 hPtr = Tcl_FindHashEntry(&opHashTable, operator);
444 code = CompileMathFuncCall(exprTokenPtr, operator, infoPtr,
446 Tcl_DStringFree(&opBuf);
447 if (code != TCL_OK) {
453 Tcl_DStringFree(&opBuf);
454 opIndex = (int) Tcl_GetHashValue(hPtr);
455 opDescPtr = &(operatorTable[opIndex]);
458 * If the operator is "normal", compile it using information
459 * from the operator table.
462 if (opDescPtr->numOperands > 0) {
464 code = CompileSubExpr(tokenPtr, infoPtr, envPtr);
465 if (code != TCL_OK) {
468 tokenPtr += (tokenPtr->numComponents + 1);
470 if (opDescPtr->numOperands == 2) {
471 code = CompileSubExpr(tokenPtr, infoPtr, envPtr);
472 if (code != TCL_OK) {
475 tokenPtr += (tokenPtr->numComponents + 1);
477 TclEmitOpcode(opDescPtr->instruction, envPtr);
478 infoPtr->hasOperators = 1;
483 * The operator requires special treatment, and is either
484 * "+" or "-", or one of "&&", "||" or "?".
491 code = CompileSubExpr(tokenPtr, infoPtr, envPtr);
492 if (code != TCL_OK) {
495 tokenPtr += (tokenPtr->numComponents + 1);
498 * Check whether the "+" or "-" is unary.
501 afterSubexprPtr = exprTokenPtr
502 + exprTokenPtr->numComponents+1;
503 if (tokenPtr == afterSubexprPtr) {
504 TclEmitOpcode(((opIndex==OP_PLUS)?
505 INST_UPLUS : INST_UMINUS),
511 * The "+" or "-" is binary.
514 code = CompileSubExpr(tokenPtr, infoPtr, envPtr);
515 if (code != TCL_OK) {
518 tokenPtr += (tokenPtr->numComponents + 1);
519 TclEmitOpcode(((opIndex==OP_PLUS)? INST_ADD : INST_SUB),
525 code = CompileLandOrLorExpr(exprTokenPtr, opIndex,
526 infoPtr, envPtr, &endPtr);
527 if (code != TCL_OK) {
534 code = CompileCondExpr(exprTokenPtr, infoPtr,
536 if (code != TCL_OK) {
543 panic("CompileSubExpr: unexpected operator %d requiring special treatment\n",
545 } /* end switch on operator requiring special treatment */
546 infoPtr->hasOperators = 1;
550 panic("CompileSubExpr: unexpected token type %d\n",
555 * Verify that the subexpression token had the required number of
556 * subtokens: that we've advanced tokenPtr just beyond the
557 * subexpression's last token. For example, a "*" subexpression must
558 * contain the tokens for exactly two operands.
561 if (tokenPtr != (exprTokenPtr + exprTokenPtr->numComponents+1)) {
562 LogSyntaxError(infoPtr);
571 *----------------------------------------------------------------------
573 * CompileLandOrLorExpr --
575 * This procedure compiles a Tcl logical and ("&&") or logical or
576 * ("||") subexpression.
579 * The return value is TCL_OK on a successful compilation and TCL_ERROR
580 * on failure. If TCL_OK is returned, a pointer to the token just after
581 * the last one in the subexpression is stored at the address in
582 * endPtrPtr. If TCL_ERROR is returned, then the interpreter's result
583 * contains an error message.
586 * Adds instructions to envPtr to evaluate the expression at runtime.
588 *----------------------------------------------------------------------
592 CompileLandOrLorExpr(exprTokenPtr, opIndex, infoPtr, envPtr, endPtrPtr)
593 Tcl_Token *exprTokenPtr; /* Points to TCL_TOKEN_SUB_EXPR token
594 * containing the "&&" or "||" operator. */
595 int opIndex; /* A code describing the expression
596 * operator: either OP_LAND or OP_LOR. */
597 ExprInfo *infoPtr; /* Describes the compilation state for the
598 * expression being compiled. */
599 CompileEnv *envPtr; /* Holds resulting instructions. */
600 Tcl_Token **endPtrPtr; /* If successful, a pointer to the token
601 * just after the last token in the
602 * subexpression is stored here. */
604 JumpFixup shortCircuitFixup; /* Used to fix up the short circuit jump
605 * after the first subexpression. */
606 JumpFixup lhsTrueFixup, lhsEndFixup;
607 /* Used to fix up jumps used to convert the
608 * first operand to 0 or 1. */
611 int savedStackDepth = envPtr->currStackDepth;
614 * Emit code for the first operand.
617 tokenPtr = exprTokenPtr+2;
618 code = CompileSubExpr(tokenPtr, infoPtr, envPtr);
619 if (code != TCL_OK) {
622 tokenPtr += (tokenPtr->numComponents + 1);
625 * Convert the first operand to the result that Tcl requires:
626 * "0" or "1". Eventually we'll use a new instruction for this.
629 TclEmitForwardJump(envPtr, TCL_TRUE_JUMP, &lhsTrueFixup);
630 TclEmitPush(TclRegisterNewLiteral(envPtr, "0", 1), envPtr);
631 TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP, &lhsEndFixup);
632 dist = (envPtr->codeNext - envPtr->codeStart) - lhsTrueFixup.codeOffset;
633 if (TclFixupForwardJump(envPtr, &lhsTrueFixup, dist, 127)) {
635 panic("CompileLandOrLorExpr: bad jump distance %d\n", dist);
637 envPtr->currStackDepth = savedStackDepth;
638 TclEmitPush(TclRegisterNewLiteral(envPtr, "1", 1), envPtr);
639 dist = (envPtr->codeNext - envPtr->codeStart) - lhsEndFixup.codeOffset;
640 if (TclFixupForwardJump(envPtr, &lhsEndFixup, dist, 127)) {
645 * Emit the "short circuit" jump around the rest of the expression.
646 * Duplicate the "0" or "1" on top of the stack first to keep the
647 * jump from consuming it.
650 TclEmitOpcode(INST_DUP, envPtr);
651 TclEmitForwardJump(envPtr,
652 ((opIndex==OP_LAND)? TCL_FALSE_JUMP : TCL_TRUE_JUMP),
656 * Emit code for the second operand.
659 code = CompileSubExpr(tokenPtr, infoPtr, envPtr);
660 if (code != TCL_OK) {
663 tokenPtr += (tokenPtr->numComponents + 1);
666 * Emit a "logical and" or "logical or" instruction. This does not try
667 * to "short- circuit" the evaluation of both operands, but instead
668 * ensures that we either have a "1" or a "0" result.
671 TclEmitOpcode(((opIndex==OP_LAND)? INST_LAND : INST_LOR), envPtr);
674 * Now that we know the target of the forward jump, update it with the
678 dist = (envPtr->codeNext - envPtr->codeStart)
679 - shortCircuitFixup.codeOffset;
680 TclFixupForwardJump(envPtr, &shortCircuitFixup, dist, 127);
681 *endPtrPtr = tokenPtr;
684 envPtr->currStackDepth = savedStackDepth + 1;
689 *----------------------------------------------------------------------
693 * This procedure compiles a Tcl conditional expression:
694 * condExpr ::= lorExpr ['?' condExpr ':' condExpr]
697 * The return value is TCL_OK on a successful compilation and TCL_ERROR
698 * on failure. If TCL_OK is returned, a pointer to the token just after
699 * the last one in the subexpression is stored at the address in
700 * endPtrPtr. If TCL_ERROR is returned, then the interpreter's result
701 * contains an error message.
704 * Adds instructions to envPtr to evaluate the expression at runtime.
706 *----------------------------------------------------------------------
710 CompileCondExpr(exprTokenPtr, infoPtr, envPtr, endPtrPtr)
711 Tcl_Token *exprTokenPtr; /* Points to TCL_TOKEN_SUB_EXPR token
712 * containing the "?" operator. */
713 ExprInfo *infoPtr; /* Describes the compilation state for the
714 * expression being compiled. */
715 CompileEnv *envPtr; /* Holds resulting instructions. */
716 Tcl_Token **endPtrPtr; /* If successful, a pointer to the token
717 * just after the last token in the
718 * subexpression is stored here. */
720 JumpFixup jumpAroundThenFixup, jumpAroundElseFixup;
721 /* Used to update or replace one-byte jumps
722 * around the then and else expressions when
723 * their target PCs are determined. */
725 int elseCodeOffset, dist, code;
726 int savedStackDepth = envPtr->currStackDepth;
729 * Emit code for the test.
732 tokenPtr = exprTokenPtr+2;
733 code = CompileSubExpr(tokenPtr, infoPtr, envPtr);
734 if (code != TCL_OK) {
737 tokenPtr += (tokenPtr->numComponents + 1);
740 * Emit the jump to the "else" expression if the test was false.
743 TclEmitForwardJump(envPtr, TCL_FALSE_JUMP, &jumpAroundThenFixup);
746 * Compile the "then" expression. Note that if a subexpression is only
747 * a primary, we need to try to convert it to numeric. We do this to
748 * support Tcl's policy of interpreting operands if at all possible as
749 * first integers, else floating-point numbers.
752 infoPtr->hasOperators = 0;
753 code = CompileSubExpr(tokenPtr, infoPtr, envPtr);
754 if (code != TCL_OK) {
757 tokenPtr += (tokenPtr->numComponents + 1);
758 if (!infoPtr->hasOperators) {
759 TclEmitOpcode(INST_TRY_CVT_TO_NUMERIC, envPtr);
763 * Emit an unconditional jump around the "else" condExpr.
766 TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP,
767 &jumpAroundElseFixup);
770 * Compile the "else" expression.
773 envPtr->currStackDepth = savedStackDepth;
774 elseCodeOffset = (envPtr->codeNext - envPtr->codeStart);
775 infoPtr->hasOperators = 0;
776 code = CompileSubExpr(tokenPtr, infoPtr, envPtr);
777 if (code != TCL_OK) {
780 tokenPtr += (tokenPtr->numComponents + 1);
781 if (!infoPtr->hasOperators) {
782 TclEmitOpcode(INST_TRY_CVT_TO_NUMERIC, envPtr);
786 * Fix up the second jump around the "else" expression.
789 dist = (envPtr->codeNext - envPtr->codeStart)
790 - jumpAroundElseFixup.codeOffset;
791 if (TclFixupForwardJump(envPtr, &jumpAroundElseFixup, dist, 127)) {
793 * Update the else expression's starting code offset since it
794 * moved down 3 bytes too.
801 * Fix up the first jump to the "else" expression if the test was false.
804 dist = (elseCodeOffset - jumpAroundThenFixup.codeOffset);
805 TclFixupForwardJump(envPtr, &jumpAroundThenFixup, dist, 127);
806 *endPtrPtr = tokenPtr;
809 envPtr->currStackDepth = savedStackDepth + 1;
814 *----------------------------------------------------------------------
816 * CompileMathFuncCall --
818 * This procedure compiles a call on a math function in an expression:
819 * mathFuncCall ::= funcName '(' [condExpr {',' condExpr}] ')'
822 * The return value is TCL_OK on a successful compilation and TCL_ERROR
823 * on failure. If TCL_OK is returned, a pointer to the token just after
824 * the last one in the subexpression is stored at the address in
825 * endPtrPtr. If TCL_ERROR is returned, then the interpreter's result
826 * contains an error message.
829 * Adds instructions to envPtr to evaluate the math function at
832 *----------------------------------------------------------------------
836 CompileMathFuncCall(exprTokenPtr, funcName, infoPtr, envPtr, endPtrPtr)
837 Tcl_Token *exprTokenPtr; /* Points to TCL_TOKEN_SUB_EXPR token
838 * containing the math function call. */
839 CONST char *funcName; /* Name of the math function. */
840 ExprInfo *infoPtr; /* Describes the compilation state for the
841 * expression being compiled. */
842 CompileEnv *envPtr; /* Holds resulting instructions. */
843 Tcl_Token **endPtrPtr; /* If successful, a pointer to the token
844 * just after the last token in the
845 * subexpression is stored here. */
847 Tcl_Interp *interp = infoPtr->interp;
848 Interp *iPtr = (Interp *) interp;
849 MathFunc *mathFuncPtr;
851 Tcl_Token *tokenPtr, *afterSubexprPtr;
855 * Look up the MathFunc record for the function.
859 hPtr = Tcl_FindHashEntry(&iPtr->mathFuncTable, funcName);
861 Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
862 "unknown math function \"", funcName, "\"", (char *) NULL);
866 mathFuncPtr = (MathFunc *) Tcl_GetHashValue(hPtr);
869 * If not a builtin function, push an object with the function's name.
872 if (mathFuncPtr->builtinFuncIndex < 0) {
873 TclEmitPush(TclRegisterNewLiteral(envPtr, funcName, -1), envPtr);
877 * Compile any arguments for the function.
880 tokenPtr = exprTokenPtr+2;
881 afterSubexprPtr = exprTokenPtr + (exprTokenPtr->numComponents + 1);
882 if (mathFuncPtr->numArgs > 0) {
883 for (i = 0; i < mathFuncPtr->numArgs; i++) {
884 if (tokenPtr == afterSubexprPtr) {
885 Tcl_ResetResult(interp);
886 Tcl_AppendToObj(Tcl_GetObjResult(interp),
887 "too few arguments for math function", -1);
891 code = CompileSubExpr(tokenPtr, infoPtr, envPtr);
892 if (code != TCL_OK) {
895 tokenPtr += (tokenPtr->numComponents + 1);
897 if (tokenPtr != afterSubexprPtr) {
898 Tcl_ResetResult(interp);
899 Tcl_AppendToObj(Tcl_GetObjResult(interp),
900 "too many arguments for math function", -1);
904 } else if (tokenPtr != afterSubexprPtr) {
905 Tcl_ResetResult(interp);
906 Tcl_AppendToObj(Tcl_GetObjResult(interp),
907 "too many arguments for math function", -1);
913 * Compile the call on the math function. Note that the "objc" argument
914 * count for non-builtin functions is incremented by 1 to include the
915 * function name itself.
918 if (mathFuncPtr->builtinFuncIndex >= 0) { /* a builtin function */
920 * Adjust the current stack depth by the number of arguments
921 * of the builtin function. This cannot be handled by the
922 * TclEmitInstInt1 macro as the number of arguments is not
923 * passed as an operand.
926 if (envPtr->maxStackDepth < envPtr->currStackDepth) {
927 envPtr->maxStackDepth = envPtr->currStackDepth;
929 TclEmitInstInt1(INST_CALL_BUILTIN_FUNC1,
930 mathFuncPtr->builtinFuncIndex, envPtr);
931 envPtr->currStackDepth -= mathFuncPtr->numArgs;
933 TclEmitInstInt1(INST_CALL_FUNC1, (mathFuncPtr->numArgs+1), envPtr);
935 *endPtrPtr = afterSubexprPtr;
942 *----------------------------------------------------------------------
946 * This procedure is invoked after an error occurs when compiling an
947 * expression. It sets the interpreter result to an error message
948 * describing the error.
954 * Sets the interpreter result to an error message describing the
955 * expression that was being compiled when the error occurred.
957 *----------------------------------------------------------------------
961 LogSyntaxError(infoPtr)
962 ExprInfo *infoPtr; /* Describes the compilation state for the
963 * expression being compiled. */
965 int numBytes = (infoPtr->lastChar - infoPtr->expr);
968 sprintf(buffer, "syntax error in expression \"%.*s\"",
969 ((numBytes > 60)? 60 : numBytes), infoPtr->expr);
970 Tcl_ResetResult(infoPtr->interp);
971 Tcl_AppendStringsToObj(Tcl_GetObjResult(infoPtr->interp),
972 buffer, (char *) NULL);