Diff
Not logged in

Differences From Artifact [bf69a71406]:

To Artifact [002507a013]:


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.14.2.10 2005/10/18 20:46:18 dgp Exp $
 * RCS: @(#) $Id: tclCompExpr.c,v 1.14.2.11 2005/11/03 17:52:07 dgp Exp $
 */

#include "tclInt.h"
#include "tclCompile.h"

/*
 * Boolean variable that controls whether expression compilation tracing is
132
133
134
135
136
137
138
139

140
141
142


143
144
145
146
147



148
149
150


151
152
153


154
155
156
157
158
159
160
132
133
134
135
136
137
138

139
140


141
142
143
144



145
146
147



148
149



150
151
152
153
154
155
156
157
158







-
+

-
-
+
+


-
-
-
+
+
+
-
-
-
+
+
-
-
-
+
+








static Tcl_HashTable opHashTable;

/*
 * Declarations for local procedures to this file:
 */

static int		CompileCondExpr _ANSI_ARGS_((
static int		CompileCondExpr(
			    Tcl_Token *exprTokenPtr, ExprInfo *infoPtr,
			    CompileEnv *envPtr, Tcl_Token **endPtrPtr));
static int		CompileLandOrLorExpr _ANSI_ARGS_((
			    CompileEnv *envPtr, Tcl_Token **endPtrPtr);
static int		CompileLandOrLorExpr(
			    Tcl_Token *exprTokenPtr, int opIndex,
			    ExprInfo *infoPtr, CompileEnv *envPtr,
			    Tcl_Token **endPtrPtr));
static int		CompileMathFuncCall _ANSI_ARGS_((
			    Tcl_Token *exprTokenPtr, CONST char *funcName,
			    Tcl_Token **endPtrPtr);
static int		CompileMathFuncCall(Tcl_Token *exprTokenPtr,
			    CONST char *funcName, ExprInfo *infoPtr,
			    ExprInfo *infoPtr, CompileEnv *envPtr,
			    Tcl_Token **endPtrPtr));
static int		CompileSubExpr _ANSI_ARGS_((
			    CompileEnv *envPtr, Tcl_Token **endPtrPtr);
static int		CompileSubExpr(Tcl_Token *exprTokenPtr,
			    Tcl_Token *exprTokenPtr, ExprInfo *infoPtr,
			    CompileEnv *envPtr));
static void		LogSyntaxError _ANSI_ARGS_((ExprInfo *infoPtr));
			    ExprInfo *infoPtr, CompileEnv *envPtr);
static void		LogSyntaxError(ExprInfo *infoPtr);

/*
 * Macro used to debug the execution of the expression compiler.
 */

#ifdef TCL_COMPILE_DEBUG
#define TRACE(exprBytes, exprLength, tokenBytes, tokenLength) \
185
186
187
188
189
190
191
192
193
194
195




196
197
198

199
200
201
202
203
204
205
183
184
185
186
187
188
189




190
191
192
193
194
195

196
197
198
199
200
201
202
203







-
-
-
-
+
+
+
+


-
+







 * Side effects:
 *	Adds instructions to envPtr to evaluate the expression at runtime.
 *
 *----------------------------------------------------------------------
 */

int
TclCompileExpr(interp, script, numBytes, envPtr)
    Tcl_Interp *interp;		/* Used for error reporting. */
    CONST char *script;		/* The source script to compile. */
    int numBytes;		/* Number of bytes in script. If < 0, the
TclCompileExpr(
    Tcl_Interp *interp,		/* Used for error reporting. */
    CONST char *script,		/* The source script to compile. */
    int numBytes,		/* Number of bytes in script. If < 0, the
				 * string consists of all bytes up to the
				 * first null character. */
    CompileEnv *envPtr;		/* Holds resulting instructions. */
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    ExprInfo info;
    Tcl_Parse parse;
    Tcl_HashEntry *hPtr;
    int new, i, code;

    /*
282
283
284
285
286
287
288
289

290
291
292
293
294
295
296
280
281
282
283
284
285
286

287
288
289
290
291
292
293
294







-
+







 *	Cleans up the compilation environment. At the moment, just the table
 *	of expression operators is freed.
 *
 *----------------------------------------------------------------------
 */

void
TclFinalizeCompilation()
TclFinalizeCompilation(void)
{
    Tcl_MutexLock(&opMutex);
    if (opTableInitialized) {
	Tcl_DeleteHashTable(&opHashTable);
	opTableInitialized = 0;
    }
    Tcl_MutexUnlock(&opMutex);
313
314
315
316
317
318
319
320
321


322
323

324
325

326
327
328
329
330
331
332
311
312
313
314
315
316
317


318
319
320

321
322

323
324
325
326
327
328
329
330







-
-
+
+

-
+

-
+







 * Side effects:
 *	Adds instructions to envPtr to evaluate the subexpression.
 *
 *----------------------------------------------------------------------
 */

static int
CompileSubExpr(exprTokenPtr, infoPtr, envPtr)
    Tcl_Token *exprTokenPtr;	/* Points to TCL_TOKEN_SUB_EXPR token to
CompileSubExpr(
    Tcl_Token *exprTokenPtr,	/* Points to TCL_TOKEN_SUB_EXPR token to
				 * compile. */
    ExprInfo *infoPtr;		/* Describes the compilation state for the
    ExprInfo *infoPtr,		/* Describes the compilation state for the
				 * expression being compiled. */
    CompileEnv *envPtr;		/* Holds resulting instructions. */
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    Tcl_Interp *interp = infoPtr->interp;
    Tcl_Token *tokenPtr, *endPtr, *afterSubexprPtr;
    OperatorDesc *opDescPtr;
    Tcl_HashEntry *hPtr;
    CONST char *operator;
    Tcl_DString opBuf;
362
363
364
365
366
367
368
369

370
371
372
373
374
375
376
360
361
362
363
364
365
366

367
368
369
370
371
372
373
374







-
+







	    objIndex = TclRegisterNewLiteral(envPtr, "", 0);
	}
	TclEmitPush(objIndex, envPtr);
	tokenPtr += 1;
	break;
 
    case TCL_TOKEN_BS:
	length = Tcl_UtfBackslash(tokenPtr->start, (int *) NULL, buffer);
	length = Tcl_UtfBackslash(tokenPtr->start, NULL, buffer);
	if (length > 0) {
	    objIndex = TclRegisterNewLiteral(envPtr, buffer, length);
	} else {
	    objIndex = TclRegisterNewLiteral(envPtr, "", 0);
	}
	TclEmitPush(objIndex, envPtr);
	tokenPtr += 1;
550
551
552
553
554
555
556
557
558


559
560

561
562

563
564
565


566
567
568
569
570
571
572
548
549
550
551
552
553
554


555
556
557

558
559

560
561


562
563
564
565
566
567
568
569
570







-
-
+
+

-
+

-
+

-
-
+
+







 * Side effects:
 *	Adds instructions to envPtr to evaluate the expression at runtime.
 *
 *----------------------------------------------------------------------
 */

static int
CompileLandOrLorExpr(exprTokenPtr, opIndex, infoPtr, envPtr, endPtrPtr)
    Tcl_Token *exprTokenPtr;	/* Points to TCL_TOKEN_SUB_EXPR token
CompileLandOrLorExpr(
    Tcl_Token *exprTokenPtr,	/* Points to TCL_TOKEN_SUB_EXPR token
				 * containing the "&&" or "||" operator. */
    int opIndex;		/* A code describing the expression operator:
    int opIndex,		/* A code describing the expression operator:
				 * either OP_LAND or OP_LOR. */
    ExprInfo *infoPtr;		/* Describes the compilation state for the
    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
    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. */
{
    JumpFixup shortCircuitFixup;/* Used to fix up the short circuit jump after
				 * the first subexpression. */
    JumpFixup shortCircuitFixup2;
				/* Used to fix up the second jump to the
668
669
670
671
672
673
674
675
676


677
678

679
680
681


682
683
684
685
686
687
688
666
667
668
669
670
671
672


673
674
675

676
677


678
679
680
681
682
683
684
685
686







-
-
+
+

-
+

-
-
+
+







 * Side effects:
 *	Adds instructions to envPtr to evaluate the expression at runtime.
 *
 *----------------------------------------------------------------------
 */

static int
CompileCondExpr(exprTokenPtr, infoPtr, envPtr, endPtrPtr)
    Tcl_Token *exprTokenPtr;	/* Points to TCL_TOKEN_SUB_EXPR token
CompileCondExpr(
    Tcl_Token *exprTokenPtr,	/* Points to TCL_TOKEN_SUB_EXPR token
				 * containing the "?" operator. */
    ExprInfo *infoPtr;		/* Describes the compilation state for the
    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
    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. */
{
    JumpFixup jumpAroundThenFixup, jumpAroundElseFixup;
				/* Used to update or replace one-byte jumps
				 * around the then and else expressions when
				 * their target PCs are determined. */
793
794
795
796
797
798
799
800
801


802
803
804


805
806
807


808
809
810
811
812
813
814
791
792
793
794
795
796
797


798
799
800


801
802
803


804
805
806
807
808
809
810
811
812







-
-
+
+

-
-
+
+

-
-
+
+







 *	Adds instructions to envPtr to evaluate the math function at
 *	runtime.
 *
 *----------------------------------------------------------------------
 */

static int
CompileMathFuncCall(exprTokenPtr, funcName, infoPtr, envPtr, endPtrPtr)
    Tcl_Token *exprTokenPtr;	/* Points to TCL_TOKEN_SUB_EXPR token
CompileMathFuncCall(
    Tcl_Token *exprTokenPtr,	/* Points to TCL_TOKEN_SUB_EXPR token
				 * containing the math function call. */
    CONST char *funcName;	/* Name of the math function. */
    ExprInfo *infoPtr;		/* Describes the compilation state for the
    CONST char *funcName,	/* Name of the math function. */
    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
    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;
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
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







-
-
+
+




+













 *	Sets the interpreter result to an error message describing the
 *	expression that was being compiled when the error occurred.
 *
 *----------------------------------------------------------------------
 */

static void
LogSyntaxError(infoPtr)
    ExprInfo *infoPtr;		/* Describes the compilation state for the
LogSyntaxError(
    ExprInfo *infoPtr)		/* Describes the compilation state for the
				 * expression being compiled. */
{
    Tcl_Obj *result =
	    Tcl_NewStringObj("syntax error in expression \"", -1);

    TclAppendLimitedToObj(result, infoPtr->expr,
	    (int)(infoPtr->lastChar - infoPtr->expr), 60, "");
    Tcl_AppendToObj(result, "\"", -1);
    Tcl_SetObjResult(infoPtr->interp, result);
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */