os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/generic/tclParseExpr.c
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
/* 
sl@0
     2
 * tclParseExpr.c --
sl@0
     3
 *
sl@0
     4
 *	This file contains procedures that parse Tcl expressions. They
sl@0
     5
 *	do so in a general-purpose fashion that can be used for many
sl@0
     6
 *	different purposes, including compilation, direct execution,
sl@0
     7
 *	code analysis, etc.
sl@0
     8
 *
sl@0
     9
 * Copyright (c) 1997 Sun Microsystems, Inc.
sl@0
    10
 * Copyright (c) 1998-2000 by Scriptics Corporation.
sl@0
    11
 * Portions Copyright (c) 2007-2008 Nokia Corporation and/or its subsidiaries. All rights reserved.  
sl@0
    12
 * Contributions from Don Porter, NIST, 2002.  (not subject to US copyright)
sl@0
    13
 *
sl@0
    14
 * See the file "license.terms" for information on usage and redistribution
sl@0
    15
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
sl@0
    16
 *
sl@0
    17
 * RCS: @(#) $Id: tclParseExpr.c,v 1.17.2.2 2005/05/20 17:19:10 vasiljevic Exp $
sl@0
    18
 */
sl@0
    19
sl@0
    20
#include "tclInt.h"
sl@0
    21
sl@0
    22
/*
sl@0
    23
 * The stuff below is a bit of a hack so that this file can be used in
sl@0
    24
 * environments that include no UNIX, i.e. no errno: just arrange to use
sl@0
    25
 * the errno from tclExecute.c here.
sl@0
    26
 */
sl@0
    27
sl@0
    28
#ifndef TCL_GENERIC_ONLY
sl@0
    29
#include "tclPort.h"
sl@0
    30
#else
sl@0
    31
#define NO_ERRNO_H
sl@0
    32
#endif
sl@0
    33
sl@0
    34
#ifdef NO_ERRNO_H
sl@0
    35
extern int errno;			/* Use errno from tclExecute.c. */
sl@0
    36
#define ERANGE 34
sl@0
    37
#endif
sl@0
    38
sl@0
    39
/*
sl@0
    40
 * Boolean variable that controls whether expression parse tracing
sl@0
    41
 * is enabled.
sl@0
    42
 */
sl@0
    43
sl@0
    44
#ifdef TCL_COMPILE_DEBUG
sl@0
    45
static int traceParseExpr = 0;
sl@0
    46
#endif /* TCL_COMPILE_DEBUG */
sl@0
    47
sl@0
    48
/*
sl@0
    49
 * The ParseInfo structure holds state while parsing an expression.
sl@0
    50
 * A pointer to an ParseInfo record is passed among the routines in
sl@0
    51
 * this module.
sl@0
    52
 */
sl@0
    53
sl@0
    54
typedef struct ParseInfo {
sl@0
    55
    Tcl_Parse *parsePtr;	/* Points to structure to fill in with
sl@0
    56
				 * information about the expression. */
sl@0
    57
    int lexeme;			/* Type of last lexeme scanned in expr.
sl@0
    58
				 * See below for definitions. Corresponds to
sl@0
    59
				 * size characters beginning at start. */
sl@0
    60
    CONST char *start;		/* First character in lexeme. */
sl@0
    61
    int size;			/* Number of bytes in lexeme. */
sl@0
    62
    CONST char *next;		/* Position of the next character to be
sl@0
    63
				 * scanned in the expression string. */
sl@0
    64
    CONST char *prevEnd;	/* Points to the character just after the
sl@0
    65
				 * last one in the previous lexeme. Used to
sl@0
    66
				 * compute size of subexpression tokens. */
sl@0
    67
    CONST char *originalExpr;	/* Points to the start of the expression
sl@0
    68
				 * originally passed to Tcl_ParseExpr. */
sl@0
    69
    CONST char *lastChar;	/* Points just after last byte of expr. */
sl@0
    70
} ParseInfo;
sl@0
    71
sl@0
    72
/*
sl@0
    73
 * Definitions of the different lexemes that appear in expressions. The
sl@0
    74
 * order of these must match the corresponding entries in the
sl@0
    75
 * operatorStrings array below.
sl@0
    76
 *
sl@0
    77
 * Basic lexemes:
sl@0
    78
 */
sl@0
    79
sl@0
    80
#define LITERAL		0
sl@0
    81
#define FUNC_NAME	1
sl@0
    82
#define OPEN_BRACKET	2
sl@0
    83
#define OPEN_BRACE	3
sl@0
    84
#define OPEN_PAREN	4
sl@0
    85
#define CLOSE_PAREN	5
sl@0
    86
#define DOLLAR		6
sl@0
    87
#define QUOTE		7
sl@0
    88
#define COMMA		8
sl@0
    89
#define END		9
sl@0
    90
#define UNKNOWN		10
sl@0
    91
#define UNKNOWN_CHAR	11
sl@0
    92
sl@0
    93
/*
sl@0
    94
 * Binary numeric operators:
sl@0
    95
 */
sl@0
    96
sl@0
    97
#define MULT		12
sl@0
    98
#define DIVIDE		13
sl@0
    99
#define MOD		14
sl@0
   100
#define PLUS		15
sl@0
   101
#define MINUS		16
sl@0
   102
#define LEFT_SHIFT	17
sl@0
   103
#define RIGHT_SHIFT	18
sl@0
   104
#define LESS		19
sl@0
   105
#define GREATER		20
sl@0
   106
#define LEQ		21
sl@0
   107
#define GEQ		22
sl@0
   108
#define EQUAL		23
sl@0
   109
#define NEQ		24
sl@0
   110
#define BIT_AND		25
sl@0
   111
#define BIT_XOR		26
sl@0
   112
#define BIT_OR		27
sl@0
   113
#define AND		28
sl@0
   114
#define OR		29
sl@0
   115
#define QUESTY		30
sl@0
   116
#define COLON		31
sl@0
   117
sl@0
   118
/*
sl@0
   119
 * Unary operators. Unary minus and plus are represented by the (binary)
sl@0
   120
 * lexemes MINUS and PLUS.
sl@0
   121
 */
sl@0
   122
sl@0
   123
#define NOT		32
sl@0
   124
#define BIT_NOT		33
sl@0
   125
sl@0
   126
/*
sl@0
   127
 * Binary string operators:
sl@0
   128
 */
sl@0
   129
sl@0
   130
#define STREQ		34
sl@0
   131
#define STRNEQ		35
sl@0
   132
sl@0
   133
/*
sl@0
   134
 * Mapping from lexemes to strings; used for debugging messages. These
sl@0
   135
 * entries must match the order and number of the lexeme definitions above.
sl@0
   136
 */
sl@0
   137
sl@0
   138
static char *lexemeStrings[] = {
sl@0
   139
    "LITERAL", "FUNCNAME",
sl@0
   140
    "[", "{", "(", ")", "$", "\"", ",", "END", "UNKNOWN", "UNKNOWN_CHAR",
sl@0
   141
    "*", "/", "%", "+", "-",
sl@0
   142
    "<<", ">>", "<", ">", "<=", ">=", "==", "!=",
sl@0
   143
    "&", "^", "|", "&&", "||", "?", ":",
sl@0
   144
    "!", "~", "eq", "ne",
sl@0
   145
};
sl@0
   146
sl@0
   147
/*
sl@0
   148
 * Declarations for local procedures to this file:
sl@0
   149
 */
sl@0
   150
sl@0
   151
static int		GetLexeme _ANSI_ARGS_((ParseInfo *infoPtr));
sl@0
   152
static void		LogSyntaxError _ANSI_ARGS_((ParseInfo *infoPtr,
sl@0
   153
				CONST char *extraInfo));
sl@0
   154
static int		ParseAddExpr _ANSI_ARGS_((ParseInfo *infoPtr));
sl@0
   155
static int		ParseBitAndExpr _ANSI_ARGS_((ParseInfo *infoPtr));
sl@0
   156
static int		ParseBitOrExpr _ANSI_ARGS_((ParseInfo *infoPtr));
sl@0
   157
static int		ParseBitXorExpr _ANSI_ARGS_((ParseInfo *infoPtr));
sl@0
   158
static int		ParseCondExpr _ANSI_ARGS_((ParseInfo *infoPtr));
sl@0
   159
static int		ParseEqualityExpr _ANSI_ARGS_((ParseInfo *infoPtr));
sl@0
   160
static int		ParseLandExpr _ANSI_ARGS_((ParseInfo *infoPtr));
sl@0
   161
static int		ParseLorExpr _ANSI_ARGS_((ParseInfo *infoPtr));
sl@0
   162
static int		ParseMaxDoubleLength _ANSI_ARGS_((CONST char *string,
sl@0
   163
				CONST char *end));
sl@0
   164
static int		ParseMultiplyExpr _ANSI_ARGS_((ParseInfo *infoPtr));
sl@0
   165
static int		ParsePrimaryExpr _ANSI_ARGS_((ParseInfo *infoPtr));
sl@0
   166
static int		ParseRelationalExpr _ANSI_ARGS_((ParseInfo *infoPtr));
sl@0
   167
static int		ParseShiftExpr _ANSI_ARGS_((ParseInfo *infoPtr));
sl@0
   168
static int		ParseUnaryExpr _ANSI_ARGS_((ParseInfo *infoPtr));
sl@0
   169
static void		PrependSubExprTokens _ANSI_ARGS_((CONST char *op,
sl@0
   170
				int opBytes, CONST char *src, int srcBytes,
sl@0
   171
				int firstIndex, ParseInfo *infoPtr));
sl@0
   172
sl@0
   173
/*
sl@0
   174
 * Macro used to debug the execution of the recursive descent parser used
sl@0
   175
 * to parse expressions.
sl@0
   176
 */
sl@0
   177
sl@0
   178
#ifdef TCL_COMPILE_DEBUG
sl@0
   179
#define HERE(production, level) \
sl@0
   180
    if (traceParseExpr) { \
sl@0
   181
	fprintf(stderr, "%*s%s: lexeme=%s, next=\"%.20s\"\n", \
sl@0
   182
		(level), " ", (production), \
sl@0
   183
		lexemeStrings[infoPtr->lexeme], infoPtr->next); \
sl@0
   184
    }
sl@0
   185
#else
sl@0
   186
#define HERE(production, level)
sl@0
   187
#endif /* TCL_COMPILE_DEBUG */
sl@0
   188

sl@0
   189
/*
sl@0
   190
 *----------------------------------------------------------------------
sl@0
   191
 *
sl@0
   192
 * Tcl_ParseExpr --
sl@0
   193
 *
sl@0
   194
 *	Given a string, this procedure parses the first Tcl expression
sl@0
   195
 *	in the string and returns information about the structure of
sl@0
   196
 *	the expression. This procedure is the top-level interface to the
sl@0
   197
 *	the expression parsing module.  No more that numBytes bytes will
sl@0
   198
 *	be scanned.
sl@0
   199
 *
sl@0
   200
 * Results:
sl@0
   201
 *	The return value is TCL_OK if the command was parsed successfully
sl@0
   202
 *	and TCL_ERROR otherwise. If an error occurs and interp isn't NULL
sl@0
   203
 *	then an error message is left in its result. On a successful return,
sl@0
   204
 *	parsePtr is filled in with information about the expression that 
sl@0
   205
 *	was parsed.
sl@0
   206
 *
sl@0
   207
 * Side effects:
sl@0
   208
 *	If there is insufficient space in parsePtr to hold all the
sl@0
   209
 *	information about the expression, then additional space is
sl@0
   210
 *	malloc-ed. If the procedure returns TCL_OK then the caller must
sl@0
   211
 *	eventually invoke Tcl_FreeParse to release any additional space
sl@0
   212
 *	that was allocated.
sl@0
   213
 *
sl@0
   214
 *----------------------------------------------------------------------
sl@0
   215
 */
sl@0
   216
sl@0
   217
EXPORT_C int
sl@0
   218
Tcl_ParseExpr(interp, string, numBytes, parsePtr)
sl@0
   219
    Tcl_Interp *interp;		/* Used for error reporting. */
sl@0
   220
    CONST char *string;		/* The source string to parse. */
sl@0
   221
    int numBytes;		/* Number of bytes in string. If < 0, the
sl@0
   222
				 * string consists of all bytes up to the
sl@0
   223
				 * first null character. */
sl@0
   224
    Tcl_Parse *parsePtr;	/* Structure to fill with information about
sl@0
   225
				 * the parsed expression; any previous
sl@0
   226
				 * information in the structure is
sl@0
   227
				 * ignored. */
sl@0
   228
{
sl@0
   229
    ParseInfo info;
sl@0
   230
    int code;
sl@0
   231
sl@0
   232
    if (numBytes < 0) {
sl@0
   233
	numBytes = (string? strlen(string) : 0);
sl@0
   234
    }
sl@0
   235
#ifdef TCL_COMPILE_DEBUG
sl@0
   236
    if (traceParseExpr) {
sl@0
   237
	fprintf(stderr, "Tcl_ParseExpr: string=\"%.*s\"\n",
sl@0
   238
	        numBytes, string);
sl@0
   239
    }
sl@0
   240
#endif /* TCL_COMPILE_DEBUG */
sl@0
   241
    
sl@0
   242
    parsePtr->commentStart = NULL;
sl@0
   243
    parsePtr->commentSize = 0;
sl@0
   244
    parsePtr->commandStart = NULL;
sl@0
   245
    parsePtr->commandSize = 0;
sl@0
   246
    parsePtr->numWords = 0;
sl@0
   247
    parsePtr->tokenPtr = parsePtr->staticTokens;
sl@0
   248
    parsePtr->numTokens = 0;
sl@0
   249
    parsePtr->tokensAvailable = NUM_STATIC_TOKENS;
sl@0
   250
    parsePtr->string = string;
sl@0
   251
    parsePtr->end = (string + numBytes);
sl@0
   252
    parsePtr->interp = interp;
sl@0
   253
    parsePtr->term = string;
sl@0
   254
    parsePtr->incomplete = 0;
sl@0
   255
sl@0
   256
    /*
sl@0
   257
     * Initialize the ParseInfo structure that holds state while parsing
sl@0
   258
     * the expression.
sl@0
   259
     */
sl@0
   260
sl@0
   261
    info.parsePtr = parsePtr;
sl@0
   262
    info.lexeme = UNKNOWN;
sl@0
   263
    info.start = NULL;
sl@0
   264
    info.size = 0;
sl@0
   265
    info.next = string;
sl@0
   266
    info.prevEnd = string;
sl@0
   267
    info.originalExpr = string;
sl@0
   268
    info.lastChar = (string + numBytes); /* just after last char of expr */
sl@0
   269
sl@0
   270
    /*
sl@0
   271
     * Get the first lexeme then parse the expression.
sl@0
   272
     */
sl@0
   273
sl@0
   274
    code = GetLexeme(&info);
sl@0
   275
    if (code != TCL_OK) {
sl@0
   276
	goto error;
sl@0
   277
    }
sl@0
   278
    code = ParseCondExpr(&info);
sl@0
   279
    if (code != TCL_OK) {
sl@0
   280
	goto error;
sl@0
   281
    }
sl@0
   282
    if (info.lexeme != END) {
sl@0
   283
	LogSyntaxError(&info, "extra tokens at end of expression");
sl@0
   284
	goto error;
sl@0
   285
    }
sl@0
   286
    return TCL_OK;
sl@0
   287
    
sl@0
   288
    error:
sl@0
   289
    if (parsePtr->tokenPtr != parsePtr->staticTokens) {
sl@0
   290
	ckfree((char *) parsePtr->tokenPtr);
sl@0
   291
    }
sl@0
   292
    return TCL_ERROR;
sl@0
   293
}
sl@0
   294

sl@0
   295
/*
sl@0
   296
 *----------------------------------------------------------------------
sl@0
   297
 *
sl@0
   298
 * ParseCondExpr --
sl@0
   299
 *
sl@0
   300
 *	This procedure parses a Tcl conditional expression:
sl@0
   301
 *	condExpr ::= lorExpr ['?' condExpr ':' condExpr]
sl@0
   302
 *
sl@0
   303
 *	Note that this is the topmost recursive-descent parsing routine used
sl@0
   304
 *	by Tcl_ParseExpr to parse expressions. This avoids an extra procedure
sl@0
   305
 *	call since such a procedure would only return the result of calling
sl@0
   306
 *	ParseCondExpr. Other recursive-descent procedures that need to parse
sl@0
   307
 *	complete expressions also call ParseCondExpr.
sl@0
   308
 *
sl@0
   309
 * Results:
sl@0
   310
 *	The return value is TCL_OK on a successful parse and TCL_ERROR
sl@0
   311
 *	on failure. If TCL_ERROR is returned, then the interpreter's result
sl@0
   312
 *	contains an error message.
sl@0
   313
 *
sl@0
   314
 * Side effects:
sl@0
   315
 *	If there is insufficient space in parsePtr to hold all the
sl@0
   316
 *	information about the subexpression, then additional space is
sl@0
   317
 *	malloc-ed.
sl@0
   318
 *
sl@0
   319
 *----------------------------------------------------------------------
sl@0
   320
 */
sl@0
   321
sl@0
   322
static int
sl@0
   323
ParseCondExpr(infoPtr)
sl@0
   324
    ParseInfo *infoPtr;		/* Holds the parse state for the
sl@0
   325
				 * expression being parsed. */
sl@0
   326
{
sl@0
   327
    Tcl_Parse *parsePtr = infoPtr->parsePtr;
sl@0
   328
    Tcl_Token *tokenPtr, *firstTokenPtr, *condTokenPtr;
sl@0
   329
    int firstIndex, numToMove, code;
sl@0
   330
    CONST char *srcStart;
sl@0
   331
    
sl@0
   332
    HERE("condExpr", 1);
sl@0
   333
    srcStart = infoPtr->start;
sl@0
   334
    firstIndex = parsePtr->numTokens;
sl@0
   335
    
sl@0
   336
    code = ParseLorExpr(infoPtr);
sl@0
   337
    if (code != TCL_OK) {
sl@0
   338
	return code;
sl@0
   339
    }
sl@0
   340
    
sl@0
   341
    if (infoPtr->lexeme == QUESTY) {
sl@0
   342
	/*
sl@0
   343
	 * Emit two tokens: one TCL_TOKEN_SUB_EXPR token for the entire
sl@0
   344
	 * conditional expression, and a TCL_TOKEN_OPERATOR token for 
sl@0
   345
	 * the "?" operator. Note that these two tokens must be inserted
sl@0
   346
	 * before the LOR operand tokens generated above.
sl@0
   347
	 */
sl@0
   348
sl@0
   349
	if ((parsePtr->numTokens + 1) >= parsePtr->tokensAvailable) {
sl@0
   350
	    TclExpandTokenArray(parsePtr);
sl@0
   351
	}
sl@0
   352
	firstTokenPtr = &parsePtr->tokenPtr[firstIndex];
sl@0
   353
	tokenPtr = (firstTokenPtr + 2);
sl@0
   354
	numToMove = (parsePtr->numTokens - firstIndex);
sl@0
   355
	memmove((VOID *) tokenPtr, (VOID *) firstTokenPtr,
sl@0
   356
	        (size_t) (numToMove * sizeof(Tcl_Token)));
sl@0
   357
	parsePtr->numTokens += 2;
sl@0
   358
	
sl@0
   359
	tokenPtr = firstTokenPtr;
sl@0
   360
	tokenPtr->type = TCL_TOKEN_SUB_EXPR;
sl@0
   361
	tokenPtr->start = srcStart;
sl@0
   362
	
sl@0
   363
	tokenPtr++;
sl@0
   364
	tokenPtr->type = TCL_TOKEN_OPERATOR;
sl@0
   365
	tokenPtr->start = infoPtr->start;
sl@0
   366
	tokenPtr->size = 1;
sl@0
   367
	tokenPtr->numComponents = 0;
sl@0
   368
    
sl@0
   369
	/*
sl@0
   370
	 * Skip over the '?'.
sl@0
   371
	 */
sl@0
   372
	
sl@0
   373
	code = GetLexeme(infoPtr); 
sl@0
   374
	if (code != TCL_OK) {
sl@0
   375
	    return code;
sl@0
   376
	}
sl@0
   377
sl@0
   378
	/*
sl@0
   379
	 * Parse the "then" expression.
sl@0
   380
	 */
sl@0
   381
sl@0
   382
	code = ParseCondExpr(infoPtr);
sl@0
   383
	if (code != TCL_OK) {
sl@0
   384
	    return code;
sl@0
   385
	}
sl@0
   386
	if (infoPtr->lexeme != COLON) {
sl@0
   387
	    LogSyntaxError(infoPtr, "missing colon from ternary conditional");
sl@0
   388
	    return TCL_ERROR;
sl@0
   389
	}
sl@0
   390
	code = GetLexeme(infoPtr); /* skip over the ':' */
sl@0
   391
	if (code != TCL_OK) {
sl@0
   392
	    return code;
sl@0
   393
	}
sl@0
   394
sl@0
   395
	/*
sl@0
   396
	 * Parse the "else" expression.
sl@0
   397
	 */
sl@0
   398
sl@0
   399
	code = ParseCondExpr(infoPtr);
sl@0
   400
	if (code != TCL_OK) {
sl@0
   401
	    return code;
sl@0
   402
	}
sl@0
   403
sl@0
   404
	/*
sl@0
   405
	 * Now set the size-related fields in the '?' subexpression token.
sl@0
   406
	 */
sl@0
   407
sl@0
   408
	condTokenPtr = &parsePtr->tokenPtr[firstIndex];
sl@0
   409
	condTokenPtr->size = (infoPtr->prevEnd - srcStart);
sl@0
   410
	condTokenPtr->numComponents = parsePtr->numTokens - (firstIndex+1);
sl@0
   411
    }
sl@0
   412
    return TCL_OK;
sl@0
   413
}
sl@0
   414

sl@0
   415
/*
sl@0
   416
 *----------------------------------------------------------------------
sl@0
   417
 *
sl@0
   418
 * ParseLorExpr --
sl@0
   419
 *
sl@0
   420
 *	This procedure parses a Tcl logical or expression:
sl@0
   421
 *	lorExpr ::= landExpr {'||' landExpr}
sl@0
   422
 *
sl@0
   423
 * Results:
sl@0
   424
 *	The return value is TCL_OK on a successful parse and TCL_ERROR
sl@0
   425
 *	on failure. If TCL_ERROR is returned, then the interpreter's result
sl@0
   426
 *	contains an error message.
sl@0
   427
 *
sl@0
   428
 * Side effects:
sl@0
   429
 *	If there is insufficient space in parsePtr to hold all the
sl@0
   430
 *	information about the subexpression, then additional space is
sl@0
   431
 *	malloc-ed.
sl@0
   432
 *
sl@0
   433
 *----------------------------------------------------------------------
sl@0
   434
 */
sl@0
   435
sl@0
   436
static int
sl@0
   437
ParseLorExpr(infoPtr)
sl@0
   438
    ParseInfo *infoPtr;		/* Holds the parse state for the
sl@0
   439
				 * expression being parsed. */
sl@0
   440
{
sl@0
   441
    Tcl_Parse *parsePtr = infoPtr->parsePtr;
sl@0
   442
    int firstIndex, code;
sl@0
   443
    CONST char *srcStart, *operator;
sl@0
   444
    
sl@0
   445
    HERE("lorExpr", 2);
sl@0
   446
    srcStart = infoPtr->start;
sl@0
   447
    firstIndex = parsePtr->numTokens;
sl@0
   448
    
sl@0
   449
    code = ParseLandExpr(infoPtr);
sl@0
   450
    if (code != TCL_OK) {
sl@0
   451
	return code;
sl@0
   452
    }
sl@0
   453
sl@0
   454
    while (infoPtr->lexeme == OR) {
sl@0
   455
	operator = infoPtr->start;
sl@0
   456
	code = GetLexeme(infoPtr); /* skip over the '||' */
sl@0
   457
	if (code != TCL_OK) {
sl@0
   458
	    return code;
sl@0
   459
	}
sl@0
   460
	code = ParseLandExpr(infoPtr);
sl@0
   461
	if (code != TCL_OK) {
sl@0
   462
	    return code;
sl@0
   463
	}
sl@0
   464
sl@0
   465
	/*
sl@0
   466
	 * Generate tokens for the LOR subexpression and the '||' operator.
sl@0
   467
	 */
sl@0
   468
sl@0
   469
	PrependSubExprTokens(operator, 2, srcStart,
sl@0
   470
	        (infoPtr->prevEnd - srcStart), firstIndex, infoPtr);
sl@0
   471
    }
sl@0
   472
    return TCL_OK;
sl@0
   473
}
sl@0
   474

sl@0
   475
/*
sl@0
   476
 *----------------------------------------------------------------------
sl@0
   477
 *
sl@0
   478
 * ParseLandExpr --
sl@0
   479
 *
sl@0
   480
 *	This procedure parses a Tcl logical and expression:
sl@0
   481
 *	landExpr ::= bitOrExpr {'&&' bitOrExpr}
sl@0
   482
 *
sl@0
   483
 * Results:
sl@0
   484
 *	The return value is TCL_OK on a successful parse and TCL_ERROR
sl@0
   485
 *	on failure. If TCL_ERROR is returned, then the interpreter's result
sl@0
   486
 *	contains an error message.
sl@0
   487
 *
sl@0
   488
 * Side effects:
sl@0
   489
 *	If there is insufficient space in parsePtr to hold all the
sl@0
   490
 *	information about the subexpression, then additional space is
sl@0
   491
 *	malloc-ed.
sl@0
   492
 *
sl@0
   493
 *----------------------------------------------------------------------
sl@0
   494
 */
sl@0
   495
sl@0
   496
static int
sl@0
   497
ParseLandExpr(infoPtr)
sl@0
   498
    ParseInfo *infoPtr;		/* Holds the parse state for the
sl@0
   499
				 * expression being parsed. */
sl@0
   500
{
sl@0
   501
    Tcl_Parse *parsePtr = infoPtr->parsePtr;
sl@0
   502
    int firstIndex, code;
sl@0
   503
    CONST char *srcStart, *operator;
sl@0
   504
sl@0
   505
    HERE("landExpr", 3);
sl@0
   506
    srcStart = infoPtr->start;
sl@0
   507
    firstIndex = parsePtr->numTokens;
sl@0
   508
    
sl@0
   509
    code = ParseBitOrExpr(infoPtr);
sl@0
   510
    if (code != TCL_OK) {
sl@0
   511
	return code;
sl@0
   512
    }
sl@0
   513
sl@0
   514
    while (infoPtr->lexeme == AND) {
sl@0
   515
	operator = infoPtr->start;
sl@0
   516
	code = GetLexeme(infoPtr); /* skip over the '&&' */
sl@0
   517
	if (code != TCL_OK) {
sl@0
   518
	    return code;
sl@0
   519
	}
sl@0
   520
	code = ParseBitOrExpr(infoPtr);
sl@0
   521
	if (code != TCL_OK) {
sl@0
   522
	    return code;
sl@0
   523
	}
sl@0
   524
sl@0
   525
	/*
sl@0
   526
	 * Generate tokens for the LAND subexpression and the '&&' operator.
sl@0
   527
	 */
sl@0
   528
sl@0
   529
	PrependSubExprTokens(operator, 2, srcStart,
sl@0
   530
	        (infoPtr->prevEnd - srcStart), firstIndex, infoPtr);
sl@0
   531
    }
sl@0
   532
    return TCL_OK;
sl@0
   533
}
sl@0
   534

sl@0
   535
/*
sl@0
   536
 *----------------------------------------------------------------------
sl@0
   537
 *
sl@0
   538
 * ParseBitOrExpr --
sl@0
   539
 *
sl@0
   540
 *	This procedure parses a Tcl bitwise or expression:
sl@0
   541
 *	bitOrExpr ::= bitXorExpr {'|' bitXorExpr}
sl@0
   542
 *
sl@0
   543
 * Results:
sl@0
   544
 *	The return value is TCL_OK on a successful parse and TCL_ERROR
sl@0
   545
 *	on failure. If TCL_ERROR is returned, then the interpreter's result
sl@0
   546
 *	contains an error message.
sl@0
   547
 *
sl@0
   548
 * Side effects:
sl@0
   549
 *	If there is insufficient space in parsePtr to hold all the
sl@0
   550
 *	information about the subexpression, then additional space is
sl@0
   551
 *	malloc-ed.
sl@0
   552
 *
sl@0
   553
 *----------------------------------------------------------------------
sl@0
   554
 */
sl@0
   555
sl@0
   556
static int
sl@0
   557
ParseBitOrExpr(infoPtr)
sl@0
   558
    ParseInfo *infoPtr;		/* Holds the parse state for the
sl@0
   559
				 * expression being parsed. */
sl@0
   560
{
sl@0
   561
    Tcl_Parse *parsePtr = infoPtr->parsePtr;
sl@0
   562
    int firstIndex, code;
sl@0
   563
    CONST char *srcStart, *operator;
sl@0
   564
sl@0
   565
    HERE("bitOrExpr", 4);
sl@0
   566
    srcStart = infoPtr->start;
sl@0
   567
    firstIndex = parsePtr->numTokens;
sl@0
   568
    
sl@0
   569
    code = ParseBitXorExpr(infoPtr);
sl@0
   570
    if (code != TCL_OK) {
sl@0
   571
	return code;
sl@0
   572
    }
sl@0
   573
    
sl@0
   574
    while (infoPtr->lexeme == BIT_OR) {
sl@0
   575
	operator = infoPtr->start;
sl@0
   576
	code = GetLexeme(infoPtr); /* skip over the '|' */
sl@0
   577
	if (code != TCL_OK) {
sl@0
   578
	    return code;
sl@0
   579
	}
sl@0
   580
sl@0
   581
	code = ParseBitXorExpr(infoPtr);
sl@0
   582
	if (code != TCL_OK) {
sl@0
   583
	    return code;
sl@0
   584
	}
sl@0
   585
	
sl@0
   586
	/*
sl@0
   587
	 * Generate tokens for the BITOR subexpression and the '|' operator.
sl@0
   588
	 */
sl@0
   589
sl@0
   590
	PrependSubExprTokens(operator, 1, srcStart,
sl@0
   591
	        (infoPtr->prevEnd - srcStart), firstIndex, infoPtr);
sl@0
   592
    }
sl@0
   593
    return TCL_OK;
sl@0
   594
}
sl@0
   595

sl@0
   596
/*
sl@0
   597
 *----------------------------------------------------------------------
sl@0
   598
 *
sl@0
   599
 * ParseBitXorExpr --
sl@0
   600
 *
sl@0
   601
 *	This procedure parses a Tcl bitwise exclusive or expression:
sl@0
   602
 *	bitXorExpr ::= bitAndExpr {'^' bitAndExpr}
sl@0
   603
 *
sl@0
   604
 * Results:
sl@0
   605
 *	The return value is TCL_OK on a successful parse and TCL_ERROR
sl@0
   606
 *	on failure. If TCL_ERROR is returned, then the interpreter's result
sl@0
   607
 *	contains an error message.
sl@0
   608
 *
sl@0
   609
 * Side effects:
sl@0
   610
 *	If there is insufficient space in parsePtr to hold all the
sl@0
   611
 *	information about the subexpression, then additional space is
sl@0
   612
 *	malloc-ed.
sl@0
   613
 *
sl@0
   614
 *----------------------------------------------------------------------
sl@0
   615
 */
sl@0
   616
sl@0
   617
static int
sl@0
   618
ParseBitXorExpr(infoPtr)
sl@0
   619
    ParseInfo *infoPtr;		/* Holds the parse state for the
sl@0
   620
				 * expression being parsed. */
sl@0
   621
{
sl@0
   622
    Tcl_Parse *parsePtr = infoPtr->parsePtr;
sl@0
   623
    int firstIndex, code;
sl@0
   624
    CONST char *srcStart, *operator;
sl@0
   625
sl@0
   626
    HERE("bitXorExpr", 5);
sl@0
   627
    srcStart = infoPtr->start;
sl@0
   628
    firstIndex = parsePtr->numTokens;
sl@0
   629
    
sl@0
   630
    code = ParseBitAndExpr(infoPtr);
sl@0
   631
    if (code != TCL_OK) {
sl@0
   632
	return code;
sl@0
   633
    }
sl@0
   634
    
sl@0
   635
    while (infoPtr->lexeme == BIT_XOR) {
sl@0
   636
	operator = infoPtr->start;
sl@0
   637
	code = GetLexeme(infoPtr); /* skip over the '^' */
sl@0
   638
	if (code != TCL_OK) {
sl@0
   639
	    return code;
sl@0
   640
	}
sl@0
   641
sl@0
   642
	code = ParseBitAndExpr(infoPtr);
sl@0
   643
	if (code != TCL_OK) {
sl@0
   644
	    return code;
sl@0
   645
	}
sl@0
   646
	
sl@0
   647
	/*
sl@0
   648
	 * Generate tokens for the XOR subexpression and the '^' operator.
sl@0
   649
	 */
sl@0
   650
sl@0
   651
	PrependSubExprTokens(operator, 1, srcStart,
sl@0
   652
	        (infoPtr->prevEnd - srcStart), firstIndex, infoPtr);
sl@0
   653
    }
sl@0
   654
    return TCL_OK;
sl@0
   655
}
sl@0
   656

sl@0
   657
/*
sl@0
   658
 *----------------------------------------------------------------------
sl@0
   659
 *
sl@0
   660
 * ParseBitAndExpr --
sl@0
   661
 *
sl@0
   662
 *	This procedure parses a Tcl bitwise and expression:
sl@0
   663
 *	bitAndExpr ::= equalityExpr {'&' equalityExpr}
sl@0
   664
 *
sl@0
   665
 * Results:
sl@0
   666
 *	The return value is TCL_OK on a successful parse and TCL_ERROR
sl@0
   667
 *	on failure. If TCL_ERROR is returned, then the interpreter's result
sl@0
   668
 *	contains an error message.
sl@0
   669
 *
sl@0
   670
 * Side effects:
sl@0
   671
 *	If there is insufficient space in parsePtr to hold all the
sl@0
   672
 *	information about the subexpression, then additional space is
sl@0
   673
 *	malloc-ed.
sl@0
   674
 *
sl@0
   675
 *----------------------------------------------------------------------
sl@0
   676
 */
sl@0
   677
sl@0
   678
static int
sl@0
   679
ParseBitAndExpr(infoPtr)
sl@0
   680
    ParseInfo *infoPtr;		/* Holds the parse state for the
sl@0
   681
				 * expression being parsed. */
sl@0
   682
{
sl@0
   683
    Tcl_Parse *parsePtr = infoPtr->parsePtr;
sl@0
   684
    int firstIndex, code;
sl@0
   685
    CONST char *srcStart, *operator;
sl@0
   686
sl@0
   687
    HERE("bitAndExpr", 6);
sl@0
   688
    srcStart = infoPtr->start;
sl@0
   689
    firstIndex = parsePtr->numTokens;
sl@0
   690
    
sl@0
   691
    code = ParseEqualityExpr(infoPtr);
sl@0
   692
    if (code != TCL_OK) {
sl@0
   693
	return code;
sl@0
   694
    }
sl@0
   695
    
sl@0
   696
    while (infoPtr->lexeme == BIT_AND) {
sl@0
   697
	operator = infoPtr->start;
sl@0
   698
	code = GetLexeme(infoPtr); /* skip over the '&' */
sl@0
   699
	if (code != TCL_OK) {
sl@0
   700
	    return code;
sl@0
   701
	}
sl@0
   702
	code = ParseEqualityExpr(infoPtr);
sl@0
   703
	if (code != TCL_OK) {
sl@0
   704
	    return code;
sl@0
   705
	}
sl@0
   706
	
sl@0
   707
	/*
sl@0
   708
	 * Generate tokens for the BITAND subexpression and '&' operator.
sl@0
   709
	 */
sl@0
   710
sl@0
   711
	PrependSubExprTokens(operator, 1, srcStart,
sl@0
   712
	        (infoPtr->prevEnd - srcStart), firstIndex, infoPtr);
sl@0
   713
    }
sl@0
   714
    return TCL_OK;
sl@0
   715
}
sl@0
   716

sl@0
   717
/*
sl@0
   718
 *----------------------------------------------------------------------
sl@0
   719
 *
sl@0
   720
 * ParseEqualityExpr --
sl@0
   721
 *
sl@0
   722
 *	This procedure parses a Tcl equality (inequality) expression:
sl@0
   723
 *	equalityExpr ::= relationalExpr
sl@0
   724
 *		{('==' | '!=' | 'ne' | 'eq') relationalExpr}
sl@0
   725
 *
sl@0
   726
 * Results:
sl@0
   727
 *	The return value is TCL_OK on a successful parse and TCL_ERROR
sl@0
   728
 *	on failure. If TCL_ERROR is returned, then the interpreter's result
sl@0
   729
 *	contains an error message.
sl@0
   730
 *
sl@0
   731
 * Side effects:
sl@0
   732
 *	If there is insufficient space in parsePtr to hold all the
sl@0
   733
 *	information about the subexpression, then additional space is
sl@0
   734
 *	malloc-ed.
sl@0
   735
 *
sl@0
   736
 *----------------------------------------------------------------------
sl@0
   737
 */
sl@0
   738
sl@0
   739
static int
sl@0
   740
ParseEqualityExpr(infoPtr)
sl@0
   741
    ParseInfo *infoPtr;		/* Holds the parse state for the
sl@0
   742
				 * expression being parsed. */
sl@0
   743
{
sl@0
   744
    Tcl_Parse *parsePtr = infoPtr->parsePtr;
sl@0
   745
    int firstIndex, lexeme, code;
sl@0
   746
    CONST char *srcStart, *operator;
sl@0
   747
sl@0
   748
    HERE("equalityExpr", 7);
sl@0
   749
    srcStart = infoPtr->start;
sl@0
   750
    firstIndex = parsePtr->numTokens;
sl@0
   751
    
sl@0
   752
    code = ParseRelationalExpr(infoPtr);
sl@0
   753
    if (code != TCL_OK) {
sl@0
   754
	return code;
sl@0
   755
    }
sl@0
   756
sl@0
   757
    lexeme = infoPtr->lexeme;
sl@0
   758
    while ((lexeme == EQUAL) || (lexeme == NEQ)
sl@0
   759
	    || (lexeme == STREQ) || (lexeme == STRNEQ)) {
sl@0
   760
	operator = infoPtr->start;
sl@0
   761
	code = GetLexeme(infoPtr); /* skip over ==, !=, 'eq' or 'ne'  */
sl@0
   762
	if (code != TCL_OK) {
sl@0
   763
	    return code;
sl@0
   764
	}
sl@0
   765
	code = ParseRelationalExpr(infoPtr);
sl@0
   766
	if (code != TCL_OK) {
sl@0
   767
	    return code;
sl@0
   768
	}
sl@0
   769
sl@0
   770
	/*
sl@0
   771
	 * Generate tokens for the subexpression and '==', '!=', 'eq' or 'ne'
sl@0
   772
	 * operator.
sl@0
   773
	 */
sl@0
   774
sl@0
   775
	PrependSubExprTokens(operator, 2, srcStart,
sl@0
   776
	        (infoPtr->prevEnd - srcStart), firstIndex, infoPtr);
sl@0
   777
	lexeme = infoPtr->lexeme;
sl@0
   778
    }
sl@0
   779
    return TCL_OK;
sl@0
   780
}
sl@0
   781

sl@0
   782
/*
sl@0
   783
 *----------------------------------------------------------------------
sl@0
   784
 *
sl@0
   785
 * ParseRelationalExpr --
sl@0
   786
 *
sl@0
   787
 *	This procedure parses a Tcl relational expression:
sl@0
   788
 *	relationalExpr ::= shiftExpr {('<' | '>' | '<=' | '>=') shiftExpr}
sl@0
   789
 *
sl@0
   790
 * Results:
sl@0
   791
 *	The return value is TCL_OK on a successful parse and TCL_ERROR
sl@0
   792
 *	on failure. If TCL_ERROR is returned, then the interpreter's result
sl@0
   793
 *	contains an error message.
sl@0
   794
 *
sl@0
   795
 * Side effects:
sl@0
   796
 *	If there is insufficient space in parsePtr to hold all the
sl@0
   797
 *	information about the subexpression, then additional space is
sl@0
   798
 *	malloc-ed.
sl@0
   799
 *
sl@0
   800
 *----------------------------------------------------------------------
sl@0
   801
 */
sl@0
   802
sl@0
   803
static int
sl@0
   804
ParseRelationalExpr(infoPtr)
sl@0
   805
    ParseInfo *infoPtr;		/* Holds the parse state for the
sl@0
   806
				 * expression being parsed. */
sl@0
   807
{
sl@0
   808
    Tcl_Parse *parsePtr = infoPtr->parsePtr;
sl@0
   809
    int firstIndex, lexeme, operatorSize, code;
sl@0
   810
    CONST char *srcStart, *operator;
sl@0
   811
sl@0
   812
    HERE("relationalExpr", 8);
sl@0
   813
    srcStart = infoPtr->start;
sl@0
   814
    firstIndex = parsePtr->numTokens;
sl@0
   815
    
sl@0
   816
    code = ParseShiftExpr(infoPtr);
sl@0
   817
    if (code != TCL_OK) {
sl@0
   818
	return code;
sl@0
   819
    }
sl@0
   820
sl@0
   821
    lexeme = infoPtr->lexeme;
sl@0
   822
    while ((lexeme == LESS) || (lexeme == GREATER) || (lexeme == LEQ)
sl@0
   823
            || (lexeme == GEQ)) {
sl@0
   824
	operator = infoPtr->start;
sl@0
   825
	if ((lexeme == LEQ) || (lexeme == GEQ)) {
sl@0
   826
	    operatorSize = 2;
sl@0
   827
	} else {
sl@0
   828
	    operatorSize = 1;
sl@0
   829
	}
sl@0
   830
	code = GetLexeme(infoPtr); /* skip over the operator */
sl@0
   831
	if (code != TCL_OK) {
sl@0
   832
	    return code;
sl@0
   833
	}
sl@0
   834
	code = ParseShiftExpr(infoPtr);
sl@0
   835
	if (code != TCL_OK) {
sl@0
   836
	    return code;
sl@0
   837
	}
sl@0
   838
sl@0
   839
	/*
sl@0
   840
	 * Generate tokens for the subexpression and the operator.
sl@0
   841
	 */
sl@0
   842
sl@0
   843
	PrependSubExprTokens(operator, operatorSize, srcStart,
sl@0
   844
	        (infoPtr->prevEnd - srcStart), firstIndex, infoPtr);
sl@0
   845
	lexeme = infoPtr->lexeme;
sl@0
   846
    }
sl@0
   847
    return TCL_OK;
sl@0
   848
}
sl@0
   849

sl@0
   850
/*
sl@0
   851
 *----------------------------------------------------------------------
sl@0
   852
 *
sl@0
   853
 * ParseShiftExpr --
sl@0
   854
 *
sl@0
   855
 *	This procedure parses a Tcl shift expression:
sl@0
   856
 *	shiftExpr ::= addExpr {('<<' | '>>') addExpr}
sl@0
   857
 *
sl@0
   858
 * Results:
sl@0
   859
 *	The return value is TCL_OK on a successful parse and TCL_ERROR
sl@0
   860
 *	on failure. If TCL_ERROR is returned, then the interpreter's result
sl@0
   861
 *	contains an error message.
sl@0
   862
 *
sl@0
   863
 * Side effects:
sl@0
   864
 *	If there is insufficient space in parsePtr to hold all the
sl@0
   865
 *	information about the subexpression, then additional space is
sl@0
   866
 *	malloc-ed.
sl@0
   867
 *
sl@0
   868
 *----------------------------------------------------------------------
sl@0
   869
 */
sl@0
   870
sl@0
   871
static int
sl@0
   872
ParseShiftExpr(infoPtr)
sl@0
   873
    ParseInfo *infoPtr;		/* Holds the parse state for the
sl@0
   874
				 * expression being parsed. */
sl@0
   875
{
sl@0
   876
    Tcl_Parse *parsePtr = infoPtr->parsePtr;
sl@0
   877
    int firstIndex, lexeme, code;
sl@0
   878
    CONST char *srcStart, *operator;
sl@0
   879
sl@0
   880
    HERE("shiftExpr", 9);
sl@0
   881
    srcStart = infoPtr->start;
sl@0
   882
    firstIndex = parsePtr->numTokens;
sl@0
   883
    
sl@0
   884
    code = ParseAddExpr(infoPtr);
sl@0
   885
    if (code != TCL_OK) {
sl@0
   886
	return code;
sl@0
   887
    }
sl@0
   888
sl@0
   889
    lexeme = infoPtr->lexeme;
sl@0
   890
    while ((lexeme == LEFT_SHIFT) || (lexeme == RIGHT_SHIFT)) {
sl@0
   891
	operator = infoPtr->start;
sl@0
   892
	code = GetLexeme(infoPtr); /* skip over << or >> */
sl@0
   893
	if (code != TCL_OK) {
sl@0
   894
	    return code;
sl@0
   895
	}
sl@0
   896
	code = ParseAddExpr(infoPtr);
sl@0
   897
	if (code != TCL_OK) {
sl@0
   898
	    return code;
sl@0
   899
	}
sl@0
   900
sl@0
   901
	/*
sl@0
   902
	 * Generate tokens for the subexpression and '<<' or '>>' operator.
sl@0
   903
	 */
sl@0
   904
sl@0
   905
	PrependSubExprTokens(operator, 2, srcStart,
sl@0
   906
	        (infoPtr->prevEnd - srcStart), firstIndex, infoPtr);
sl@0
   907
	lexeme = infoPtr->lexeme;
sl@0
   908
    }
sl@0
   909
    return TCL_OK;
sl@0
   910
}
sl@0
   911

sl@0
   912
/*
sl@0
   913
 *----------------------------------------------------------------------
sl@0
   914
 *
sl@0
   915
 * ParseAddExpr --
sl@0
   916
 *
sl@0
   917
 *	This procedure parses a Tcl addition expression:
sl@0
   918
 *	addExpr ::= multiplyExpr {('+' | '-') multiplyExpr}
sl@0
   919
 *
sl@0
   920
 * Results:
sl@0
   921
 *	The return value is TCL_OK on a successful parse and TCL_ERROR
sl@0
   922
 *	on failure. If TCL_ERROR is returned, then the interpreter's result
sl@0
   923
 *	contains an error message.
sl@0
   924
 *
sl@0
   925
 * Side effects:
sl@0
   926
 *	If there is insufficient space in parsePtr to hold all the
sl@0
   927
 *	information about the subexpression, then additional space is
sl@0
   928
 *	malloc-ed.
sl@0
   929
 *
sl@0
   930
 *----------------------------------------------------------------------
sl@0
   931
 */
sl@0
   932
sl@0
   933
static int
sl@0
   934
ParseAddExpr(infoPtr)
sl@0
   935
    ParseInfo *infoPtr;		/* Holds the parse state for the
sl@0
   936
				 * expression being parsed. */
sl@0
   937
{
sl@0
   938
    Tcl_Parse *parsePtr = infoPtr->parsePtr;
sl@0
   939
    int firstIndex, lexeme, code;
sl@0
   940
    CONST char *srcStart, *operator;
sl@0
   941
sl@0
   942
    HERE("addExpr", 10);
sl@0
   943
    srcStart = infoPtr->start;
sl@0
   944
    firstIndex = parsePtr->numTokens;
sl@0
   945
    
sl@0
   946
    code = ParseMultiplyExpr(infoPtr);
sl@0
   947
    if (code != TCL_OK) {
sl@0
   948
	return code;
sl@0
   949
    }
sl@0
   950
sl@0
   951
    lexeme = infoPtr->lexeme;
sl@0
   952
    while ((lexeme == PLUS) || (lexeme == MINUS)) {
sl@0
   953
	operator = infoPtr->start;
sl@0
   954
	code = GetLexeme(infoPtr); /* skip over + or - */
sl@0
   955
	if (code != TCL_OK) {
sl@0
   956
	    return code;
sl@0
   957
	}
sl@0
   958
	code = ParseMultiplyExpr(infoPtr);
sl@0
   959
	if (code != TCL_OK) {
sl@0
   960
	    return code;
sl@0
   961
	}
sl@0
   962
sl@0
   963
	/*
sl@0
   964
	 * Generate tokens for the subexpression and '+' or '-' operator.
sl@0
   965
	 */
sl@0
   966
sl@0
   967
	PrependSubExprTokens(operator, 1, srcStart,
sl@0
   968
	        (infoPtr->prevEnd - srcStart), firstIndex, infoPtr);
sl@0
   969
	lexeme = infoPtr->lexeme;
sl@0
   970
    }
sl@0
   971
    return TCL_OK;
sl@0
   972
}
sl@0
   973

sl@0
   974
/*
sl@0
   975
 *----------------------------------------------------------------------
sl@0
   976
 *
sl@0
   977
 * ParseMultiplyExpr --
sl@0
   978
 *
sl@0
   979
 *	This procedure parses a Tcl multiply expression:
sl@0
   980
 *	multiplyExpr ::= unaryExpr {('*' | '/' | '%') unaryExpr}
sl@0
   981
 *
sl@0
   982
 * Results:
sl@0
   983
 *	The return value is TCL_OK on a successful parse and TCL_ERROR
sl@0
   984
 *	on failure. If TCL_ERROR is returned, then the interpreter's result
sl@0
   985
 *	contains an error message.
sl@0
   986
 *
sl@0
   987
 * Side effects:
sl@0
   988
 *	If there is insufficient space in parsePtr to hold all the
sl@0
   989
 *	information about the subexpression, then additional space is
sl@0
   990
 *	malloc-ed.
sl@0
   991
 *
sl@0
   992
 *----------------------------------------------------------------------
sl@0
   993
 */
sl@0
   994
sl@0
   995
static int
sl@0
   996
ParseMultiplyExpr(infoPtr)
sl@0
   997
    ParseInfo *infoPtr;		/* Holds the parse state for the
sl@0
   998
				 * expression being parsed. */
sl@0
   999
{
sl@0
  1000
    Tcl_Parse *parsePtr = infoPtr->parsePtr;
sl@0
  1001
    int firstIndex, lexeme, code;
sl@0
  1002
    CONST char *srcStart, *operator;
sl@0
  1003
sl@0
  1004
    HERE("multiplyExpr", 11);
sl@0
  1005
    srcStart = infoPtr->start;
sl@0
  1006
    firstIndex = parsePtr->numTokens;
sl@0
  1007
    
sl@0
  1008
    code = ParseUnaryExpr(infoPtr);
sl@0
  1009
    if (code != TCL_OK) {
sl@0
  1010
	return code;
sl@0
  1011
    }
sl@0
  1012
sl@0
  1013
    lexeme = infoPtr->lexeme;
sl@0
  1014
    while ((lexeme == MULT) || (lexeme == DIVIDE) || (lexeme == MOD)) {
sl@0
  1015
	operator = infoPtr->start;
sl@0
  1016
	code = GetLexeme(infoPtr); /* skip over * or / or % */
sl@0
  1017
	if (code != TCL_OK) {
sl@0
  1018
	    return code;
sl@0
  1019
	}
sl@0
  1020
	code = ParseUnaryExpr(infoPtr);
sl@0
  1021
	if (code != TCL_OK) {
sl@0
  1022
	    return code;
sl@0
  1023
	}
sl@0
  1024
sl@0
  1025
	/*
sl@0
  1026
	 * Generate tokens for the subexpression and * or / or % operator.
sl@0
  1027
	 */
sl@0
  1028
sl@0
  1029
	PrependSubExprTokens(operator, 1, srcStart,
sl@0
  1030
	        (infoPtr->prevEnd - srcStart), firstIndex, infoPtr);
sl@0
  1031
	lexeme = infoPtr->lexeme;
sl@0
  1032
    }
sl@0
  1033
    return TCL_OK;
sl@0
  1034
}
sl@0
  1035

sl@0
  1036
/*
sl@0
  1037
 *----------------------------------------------------------------------
sl@0
  1038
 *
sl@0
  1039
 * ParseUnaryExpr --
sl@0
  1040
 *
sl@0
  1041
 *	This procedure parses a Tcl unary expression:
sl@0
  1042
 *	unaryExpr ::= ('+' | '-' | '~' | '!') unaryExpr | primaryExpr
sl@0
  1043
 *
sl@0
  1044
 * Results:
sl@0
  1045
 *	The return value is TCL_OK on a successful parse and TCL_ERROR
sl@0
  1046
 *	on failure. If TCL_ERROR is returned, then the interpreter's result
sl@0
  1047
 *	contains an error message.
sl@0
  1048
 *
sl@0
  1049
 * Side effects:
sl@0
  1050
 *	If there is insufficient space in parsePtr to hold all the
sl@0
  1051
 *	information about the subexpression, then additional space is
sl@0
  1052
 *	malloc-ed.
sl@0
  1053
 *
sl@0
  1054
 *----------------------------------------------------------------------
sl@0
  1055
 */
sl@0
  1056
sl@0
  1057
static int
sl@0
  1058
ParseUnaryExpr(infoPtr)
sl@0
  1059
    ParseInfo *infoPtr;		/* Holds the parse state for the
sl@0
  1060
				 * expression being parsed. */
sl@0
  1061
{
sl@0
  1062
    Tcl_Parse *parsePtr = infoPtr->parsePtr;
sl@0
  1063
    int firstIndex, lexeme, code;
sl@0
  1064
    CONST char *srcStart, *operator;
sl@0
  1065
sl@0
  1066
    HERE("unaryExpr", 12);
sl@0
  1067
    srcStart = infoPtr->start;
sl@0
  1068
    firstIndex = parsePtr->numTokens;
sl@0
  1069
    
sl@0
  1070
    lexeme = infoPtr->lexeme;
sl@0
  1071
    if ((lexeme == PLUS) || (lexeme == MINUS) || (lexeme == BIT_NOT)
sl@0
  1072
            || (lexeme == NOT)) {
sl@0
  1073
	operator = infoPtr->start;
sl@0
  1074
	code = GetLexeme(infoPtr); /* skip over the unary operator */
sl@0
  1075
	if (code != TCL_OK) {
sl@0
  1076
	    return code;
sl@0
  1077
	}
sl@0
  1078
	code = ParseUnaryExpr(infoPtr);
sl@0
  1079
	if (code != TCL_OK) {
sl@0
  1080
	    return code;
sl@0
  1081
	}
sl@0
  1082
sl@0
  1083
	/*
sl@0
  1084
	 * Generate tokens for the subexpression and the operator.
sl@0
  1085
	 */
sl@0
  1086
sl@0
  1087
	PrependSubExprTokens(operator, 1, srcStart,
sl@0
  1088
	        (infoPtr->prevEnd - srcStart), firstIndex, infoPtr);
sl@0
  1089
    } else {			/* must be a primaryExpr */
sl@0
  1090
	code = ParsePrimaryExpr(infoPtr);
sl@0
  1091
	if (code != TCL_OK) {
sl@0
  1092
	    return code;
sl@0
  1093
	}
sl@0
  1094
    }
sl@0
  1095
    return TCL_OK;
sl@0
  1096
}
sl@0
  1097

sl@0
  1098
/*
sl@0
  1099
 *----------------------------------------------------------------------
sl@0
  1100
 *
sl@0
  1101
 * ParsePrimaryExpr --
sl@0
  1102
 *
sl@0
  1103
 *	This procedure parses a Tcl primary expression:
sl@0
  1104
 *	primaryExpr ::= literal | varReference | quotedString |
sl@0
  1105
 *			'[' command ']' | mathFuncCall | '(' condExpr ')'
sl@0
  1106
 *
sl@0
  1107
 * Results:
sl@0
  1108
 *	The return value is TCL_OK on a successful parse and TCL_ERROR
sl@0
  1109
 *	on failure. If TCL_ERROR is returned, then the interpreter's result
sl@0
  1110
 *	contains an error message.
sl@0
  1111
 *
sl@0
  1112
 * Side effects:
sl@0
  1113
 *	If there is insufficient space in parsePtr to hold all the
sl@0
  1114
 *	information about the subexpression, then additional space is
sl@0
  1115
 *	malloc-ed.
sl@0
  1116
 *
sl@0
  1117
 *----------------------------------------------------------------------
sl@0
  1118
 */
sl@0
  1119
sl@0
  1120
static int
sl@0
  1121
ParsePrimaryExpr(infoPtr)
sl@0
  1122
    ParseInfo *infoPtr;		/* Holds the parse state for the
sl@0
  1123
				 * expression being parsed. */
sl@0
  1124
{
sl@0
  1125
    Tcl_Parse *parsePtr = infoPtr->parsePtr;
sl@0
  1126
    Tcl_Interp *interp = parsePtr->interp;
sl@0
  1127
    Tcl_Token *tokenPtr, *exprTokenPtr;
sl@0
  1128
    Tcl_Parse nested;
sl@0
  1129
    CONST char *dollarPtr, *stringStart, *termPtr, *src;
sl@0
  1130
    int lexeme, exprIndex, firstIndex, numToMove, code;
sl@0
  1131
sl@0
  1132
    /*
sl@0
  1133
     * We simply recurse on parenthesized subexpressions.
sl@0
  1134
     */
sl@0
  1135
sl@0
  1136
    HERE("primaryExpr", 13);
sl@0
  1137
    lexeme = infoPtr->lexeme;
sl@0
  1138
    if (lexeme == OPEN_PAREN) {
sl@0
  1139
	code = GetLexeme(infoPtr); /* skip over the '(' */
sl@0
  1140
	if (code != TCL_OK) {
sl@0
  1141
	    return code;
sl@0
  1142
	}
sl@0
  1143
	code = ParseCondExpr(infoPtr);
sl@0
  1144
	if (code != TCL_OK) {
sl@0
  1145
	    return code;
sl@0
  1146
	}
sl@0
  1147
	if (infoPtr->lexeme != CLOSE_PAREN) {
sl@0
  1148
	    LogSyntaxError(infoPtr, "looking for close parenthesis");
sl@0
  1149
	    return TCL_ERROR;
sl@0
  1150
	}
sl@0
  1151
	code = GetLexeme(infoPtr); /* skip over the ')' */
sl@0
  1152
	if (code != TCL_OK) {
sl@0
  1153
	    return code;
sl@0
  1154
	}
sl@0
  1155
	return TCL_OK;
sl@0
  1156
    }
sl@0
  1157
sl@0
  1158
    /*
sl@0
  1159
     * Start a TCL_TOKEN_SUB_EXPR token for the primary.
sl@0
  1160
     */
sl@0
  1161
sl@0
  1162
    if (parsePtr->numTokens == parsePtr->tokensAvailable) {
sl@0
  1163
	TclExpandTokenArray(parsePtr);
sl@0
  1164
    }
sl@0
  1165
    exprIndex = parsePtr->numTokens;
sl@0
  1166
    exprTokenPtr = &parsePtr->tokenPtr[exprIndex];
sl@0
  1167
    exprTokenPtr->type = TCL_TOKEN_SUB_EXPR;
sl@0
  1168
    exprTokenPtr->start = infoPtr->start;
sl@0
  1169
    parsePtr->numTokens++;
sl@0
  1170
sl@0
  1171
    /*
sl@0
  1172
     * Process the primary then finish setting the fields of the
sl@0
  1173
     * TCL_TOKEN_SUB_EXPR token. Note that we can't use the pointer now
sl@0
  1174
     * stored in "exprTokenPtr" in the code below since the token array
sl@0
  1175
     * might be reallocated.
sl@0
  1176
     */
sl@0
  1177
sl@0
  1178
    firstIndex = parsePtr->numTokens;
sl@0
  1179
    switch (lexeme) {
sl@0
  1180
    case LITERAL:
sl@0
  1181
	/*
sl@0
  1182
	 * Int or double number.
sl@0
  1183
	 */
sl@0
  1184
	
sl@0
  1185
	tokenizeLiteral:
sl@0
  1186
	if (parsePtr->numTokens == parsePtr->tokensAvailable) {
sl@0
  1187
	    TclExpandTokenArray(parsePtr);
sl@0
  1188
	}
sl@0
  1189
	tokenPtr = &parsePtr->tokenPtr[parsePtr->numTokens];
sl@0
  1190
	tokenPtr->type = TCL_TOKEN_TEXT;
sl@0
  1191
	tokenPtr->start = infoPtr->start;
sl@0
  1192
	tokenPtr->size = infoPtr->size;
sl@0
  1193
	tokenPtr->numComponents = 0;
sl@0
  1194
	parsePtr->numTokens++;
sl@0
  1195
sl@0
  1196
	exprTokenPtr = &parsePtr->tokenPtr[exprIndex];
sl@0
  1197
	exprTokenPtr->size = infoPtr->size;
sl@0
  1198
	exprTokenPtr->numComponents = 1;
sl@0
  1199
	break;
sl@0
  1200
sl@0
  1201
    case DOLLAR:
sl@0
  1202
	/*
sl@0
  1203
	 * $var variable reference.
sl@0
  1204
	 */
sl@0
  1205
	
sl@0
  1206
	dollarPtr = (infoPtr->next - 1);
sl@0
  1207
	code = Tcl_ParseVarName(interp, dollarPtr,
sl@0
  1208
	        (infoPtr->lastChar - dollarPtr), parsePtr, 1);
sl@0
  1209
	if (code != TCL_OK) {
sl@0
  1210
	    return code;
sl@0
  1211
	}
sl@0
  1212
	infoPtr->next = dollarPtr + parsePtr->tokenPtr[firstIndex].size;
sl@0
  1213
sl@0
  1214
	exprTokenPtr = &parsePtr->tokenPtr[exprIndex];
sl@0
  1215
	exprTokenPtr->size = parsePtr->tokenPtr[firstIndex].size;
sl@0
  1216
	exprTokenPtr->numComponents =
sl@0
  1217
	        (parsePtr->tokenPtr[firstIndex].numComponents + 1);
sl@0
  1218
	break;
sl@0
  1219
	
sl@0
  1220
    case QUOTE:
sl@0
  1221
	/*
sl@0
  1222
	 * '"' string '"'
sl@0
  1223
	 */
sl@0
  1224
	
sl@0
  1225
	stringStart = infoPtr->next;
sl@0
  1226
	code = Tcl_ParseQuotedString(interp, infoPtr->start,
sl@0
  1227
	        (infoPtr->lastChar - stringStart), parsePtr, 1, &termPtr);
sl@0
  1228
	if (code != TCL_OK) {
sl@0
  1229
	    return code;
sl@0
  1230
	}
sl@0
  1231
	infoPtr->next = termPtr;
sl@0
  1232
sl@0
  1233
	exprTokenPtr = &parsePtr->tokenPtr[exprIndex];
sl@0
  1234
	exprTokenPtr->size = (termPtr - exprTokenPtr->start);
sl@0
  1235
	exprTokenPtr->numComponents = parsePtr->numTokens - firstIndex;
sl@0
  1236
sl@0
  1237
	/*
sl@0
  1238
	 * If parsing the quoted string resulted in more than one token,
sl@0
  1239
	 * insert a TCL_TOKEN_WORD token before them. This indicates that
sl@0
  1240
	 * the quoted string represents a concatenation of multiple tokens.
sl@0
  1241
	 */
sl@0
  1242
sl@0
  1243
	if (exprTokenPtr->numComponents > 1) {
sl@0
  1244
	    if (parsePtr->numTokens >= parsePtr->tokensAvailable) {
sl@0
  1245
		TclExpandTokenArray(parsePtr);
sl@0
  1246
	    }
sl@0
  1247
	    tokenPtr = &parsePtr->tokenPtr[firstIndex];
sl@0
  1248
	    numToMove = (parsePtr->numTokens - firstIndex);
sl@0
  1249
	    memmove((VOID *) (tokenPtr + 1), (VOID *) tokenPtr,
sl@0
  1250
	            (size_t) (numToMove * sizeof(Tcl_Token)));
sl@0
  1251
	    parsePtr->numTokens++;
sl@0
  1252
sl@0
  1253
	    exprTokenPtr = &parsePtr->tokenPtr[exprIndex];
sl@0
  1254
	    exprTokenPtr->numComponents++;
sl@0
  1255
sl@0
  1256
	    tokenPtr->type = TCL_TOKEN_WORD;
sl@0
  1257
	    tokenPtr->start = exprTokenPtr->start;
sl@0
  1258
	    tokenPtr->size = exprTokenPtr->size;
sl@0
  1259
	    tokenPtr->numComponents = (exprTokenPtr->numComponents - 1);
sl@0
  1260
	}
sl@0
  1261
	break;
sl@0
  1262
	
sl@0
  1263
    case OPEN_BRACKET:
sl@0
  1264
	/*
sl@0
  1265
	 * '[' command {command} ']'
sl@0
  1266
	 */
sl@0
  1267
sl@0
  1268
	if (parsePtr->numTokens == parsePtr->tokensAvailable) {
sl@0
  1269
	    TclExpandTokenArray(parsePtr);
sl@0
  1270
	}
sl@0
  1271
	tokenPtr = &parsePtr->tokenPtr[parsePtr->numTokens];
sl@0
  1272
	tokenPtr->type = TCL_TOKEN_COMMAND;
sl@0
  1273
	tokenPtr->start = infoPtr->start;
sl@0
  1274
	tokenPtr->numComponents = 0;
sl@0
  1275
	parsePtr->numTokens++;
sl@0
  1276
sl@0
  1277
	/*
sl@0
  1278
	 * Call Tcl_ParseCommand repeatedly to parse the nested command(s)
sl@0
  1279
	 * to find their end, then throw away that parse information.
sl@0
  1280
	 */
sl@0
  1281
	
sl@0
  1282
	src = infoPtr->next;
sl@0
  1283
	while (1) {
sl@0
  1284
	    if (Tcl_ParseCommand(interp, src, (parsePtr->end - src), 1,
sl@0
  1285
		    &nested) != TCL_OK) {
sl@0
  1286
		parsePtr->term = nested.term;
sl@0
  1287
		parsePtr->errorType = nested.errorType;
sl@0
  1288
		parsePtr->incomplete = nested.incomplete;
sl@0
  1289
		return TCL_ERROR;
sl@0
  1290
	    }
sl@0
  1291
	    src = (nested.commandStart + nested.commandSize);
sl@0
  1292
sl@0
  1293
	    /*
sl@0
  1294
	     * This is equivalent to Tcl_FreeParse(&nested), but
sl@0
  1295
	     * presumably inlined here for sake of runtime optimization
sl@0
  1296
	     */
sl@0
  1297
sl@0
  1298
	    if (nested.tokenPtr != nested.staticTokens) {
sl@0
  1299
		ckfree((char *) nested.tokenPtr);
sl@0
  1300
	    }
sl@0
  1301
sl@0
  1302
	    /*
sl@0
  1303
	     * Check for the closing ']' that ends the command substitution.
sl@0
  1304
	     * It must have been the last character of the parsed command.
sl@0
  1305
	     */
sl@0
  1306
sl@0
  1307
	    if ((nested.term < parsePtr->end) && (*nested.term == ']') 
sl@0
  1308
		    && !nested.incomplete) {
sl@0
  1309
		break;
sl@0
  1310
	    }
sl@0
  1311
	    if (src == parsePtr->end) {
sl@0
  1312
		if (parsePtr->interp != NULL) {
sl@0
  1313
		    Tcl_SetResult(interp, "missing close-bracket",
sl@0
  1314
			    TCL_STATIC);
sl@0
  1315
		}
sl@0
  1316
		parsePtr->term = tokenPtr->start;
sl@0
  1317
		parsePtr->errorType = TCL_PARSE_MISSING_BRACKET;
sl@0
  1318
		parsePtr->incomplete = 1;
sl@0
  1319
		return TCL_ERROR;
sl@0
  1320
	    }
sl@0
  1321
	}
sl@0
  1322
	tokenPtr->size = (src - tokenPtr->start);
sl@0
  1323
	infoPtr->next = src;
sl@0
  1324
sl@0
  1325
	exprTokenPtr = &parsePtr->tokenPtr[exprIndex];
sl@0
  1326
	exprTokenPtr->size = (src - tokenPtr->start);
sl@0
  1327
	exprTokenPtr->numComponents = 1;
sl@0
  1328
	break;
sl@0
  1329
sl@0
  1330
    case OPEN_BRACE:
sl@0
  1331
	/*
sl@0
  1332
	 * '{' string '}'
sl@0
  1333
	 */
sl@0
  1334
sl@0
  1335
	code = Tcl_ParseBraces(interp, infoPtr->start,
sl@0
  1336
	        (infoPtr->lastChar - infoPtr->start), parsePtr, 1,
sl@0
  1337
		&termPtr);
sl@0
  1338
	if (code != TCL_OK) {
sl@0
  1339
	    return code;
sl@0
  1340
	}
sl@0
  1341
	infoPtr->next = termPtr;
sl@0
  1342
sl@0
  1343
	exprTokenPtr = &parsePtr->tokenPtr[exprIndex];
sl@0
  1344
	exprTokenPtr->size = (termPtr - infoPtr->start);
sl@0
  1345
	exprTokenPtr->numComponents = parsePtr->numTokens - firstIndex;
sl@0
  1346
sl@0
  1347
	/*
sl@0
  1348
	 * If parsing the braced string resulted in more than one token,
sl@0
  1349
	 * insert a TCL_TOKEN_WORD token before them. This indicates that
sl@0
  1350
	 * the braced string represents a concatenation of multiple tokens.
sl@0
  1351
	 */
sl@0
  1352
sl@0
  1353
	if (exprTokenPtr->numComponents > 1) {
sl@0
  1354
	    if (parsePtr->numTokens >= parsePtr->tokensAvailable) {
sl@0
  1355
		TclExpandTokenArray(parsePtr);
sl@0
  1356
	    }
sl@0
  1357
	    tokenPtr = &parsePtr->tokenPtr[firstIndex];
sl@0
  1358
	    numToMove = (parsePtr->numTokens - firstIndex);
sl@0
  1359
	    memmove((VOID *) (tokenPtr + 1), (VOID *) tokenPtr,
sl@0
  1360
	            (size_t) (numToMove * sizeof(Tcl_Token)));
sl@0
  1361
	    parsePtr->numTokens++;
sl@0
  1362
sl@0
  1363
	    exprTokenPtr = &parsePtr->tokenPtr[exprIndex];
sl@0
  1364
	    exprTokenPtr->numComponents++;
sl@0
  1365
	    
sl@0
  1366
	    tokenPtr->type = TCL_TOKEN_WORD;
sl@0
  1367
	    tokenPtr->start = exprTokenPtr->start;
sl@0
  1368
	    tokenPtr->size = exprTokenPtr->size;
sl@0
  1369
	    tokenPtr->numComponents = exprTokenPtr->numComponents-1;
sl@0
  1370
	}
sl@0
  1371
	break;
sl@0
  1372
	
sl@0
  1373
    case STREQ:
sl@0
  1374
    case STRNEQ:
sl@0
  1375
    case FUNC_NAME: {
sl@0
  1376
	/*
sl@0
  1377
	 * math_func '(' expr {',' expr} ')'
sl@0
  1378
	 */
sl@0
  1379
sl@0
  1380
	ParseInfo savedInfo = *infoPtr;
sl@0
  1381
	
sl@0
  1382
	code = GetLexeme(infoPtr); /* skip over function name */
sl@0
  1383
	if (code != TCL_OK) {
sl@0
  1384
	    return code;
sl@0
  1385
	}
sl@0
  1386
	if (infoPtr->lexeme != OPEN_PAREN) {
sl@0
  1387
	    int code;
sl@0
  1388
	    Tcl_DString functionName;
sl@0
  1389
	    Tcl_HashEntry *hPtr;
sl@0
  1390
	    Interp *iPtr = (Interp *) infoPtr->parsePtr->interp;
sl@0
  1391
	    Tcl_Obj *objPtr = Tcl_NewStringObj(savedInfo.start, savedInfo.size);
sl@0
  1392
sl@0
  1393
	    /* Check for boolean literals (true, false, yes, no, on, off) */
sl@0
  1394
	    Tcl_IncrRefCount(objPtr);
sl@0
  1395
	    code = Tcl_ConvertToType(NULL, objPtr, &tclBooleanType);
sl@0
  1396
	    Tcl_DecrRefCount(objPtr);
sl@0
  1397
	    if (code == TCL_OK) {
sl@0
  1398
		*infoPtr = savedInfo;
sl@0
  1399
		goto tokenizeLiteral;
sl@0
  1400
	    }
sl@0
  1401
sl@0
  1402
	    /*
sl@0
  1403
	     * Guess what kind of error we have by trying to tell
sl@0
  1404
	     * whether we have a function or variable name here.
sl@0
  1405
	     * Alas, this makes the parser more tightly bound with the
sl@0
  1406
	     * rest of the interpreter, but that is the only way to
sl@0
  1407
	     * give a sensible message here.  Still, it is not too
sl@0
  1408
	     * serious as this is only done when generating an error.
sl@0
  1409
	     */
sl@0
  1410
sl@0
  1411
	    /*
sl@0
  1412
	     * Look up the name as a function name.  We need a writable
sl@0
  1413
	     * copy (DString) so we can terminate it with a NULL for
sl@0
  1414
	     * the benefit of Tcl_FindHashEntry which operates on
sl@0
  1415
	     * NULL-terminated string keys.
sl@0
  1416
	     */
sl@0
  1417
	    Tcl_DStringInit(&functionName);
sl@0
  1418
	    hPtr = Tcl_FindHashEntry(&iPtr->mathFuncTable, 
sl@0
  1419
	    	Tcl_DStringAppend(&functionName,
sl@0
  1420
			savedInfo.start, savedInfo.size));
sl@0
  1421
	    Tcl_DStringFree(&functionName);
sl@0
  1422
sl@0
  1423
	    /*
sl@0
  1424
	     * Assume that we have an attempted variable reference
sl@0
  1425
	     * unless we've got a function name, as the set of
sl@0
  1426
	     * potential function names is typically much smaller.
sl@0
  1427
	     */
sl@0
  1428
	    if (hPtr != NULL) {
sl@0
  1429
		LogSyntaxError(infoPtr,
sl@0
  1430
			"expected parenthesis enclosing function arguments");
sl@0
  1431
	    } else {
sl@0
  1432
		LogSyntaxError(infoPtr,
sl@0
  1433
			"variable references require preceding $");
sl@0
  1434
	    }
sl@0
  1435
	    return TCL_ERROR;
sl@0
  1436
	}
sl@0
  1437
sl@0
  1438
	if (parsePtr->numTokens == parsePtr->tokensAvailable) {
sl@0
  1439
	    TclExpandTokenArray(parsePtr);
sl@0
  1440
	}
sl@0
  1441
	tokenPtr = &parsePtr->tokenPtr[parsePtr->numTokens];
sl@0
  1442
	tokenPtr->type = TCL_TOKEN_OPERATOR;
sl@0
  1443
	tokenPtr->start = savedInfo.start;
sl@0
  1444
	tokenPtr->size = savedInfo.size;
sl@0
  1445
	tokenPtr->numComponents = 0;
sl@0
  1446
	parsePtr->numTokens++;
sl@0
  1447
	
sl@0
  1448
	code = GetLexeme(infoPtr); /* skip over '(' */
sl@0
  1449
	if (code != TCL_OK) {
sl@0
  1450
	    return code;
sl@0
  1451
	}
sl@0
  1452
sl@0
  1453
	while (infoPtr->lexeme != CLOSE_PAREN) {
sl@0
  1454
	    code = ParseCondExpr(infoPtr);
sl@0
  1455
	    if (code != TCL_OK) {
sl@0
  1456
		return code;
sl@0
  1457
	    }
sl@0
  1458
	    
sl@0
  1459
	    if (infoPtr->lexeme == COMMA) {
sl@0
  1460
		code = GetLexeme(infoPtr); /* skip over , */
sl@0
  1461
		if (code != TCL_OK) {
sl@0
  1462
		    return code;
sl@0
  1463
		}
sl@0
  1464
	    } else if (infoPtr->lexeme != CLOSE_PAREN) {
sl@0
  1465
		LogSyntaxError(infoPtr,
sl@0
  1466
			"missing close parenthesis at end of function call");
sl@0
  1467
		return TCL_ERROR;
sl@0
  1468
	    }
sl@0
  1469
	}
sl@0
  1470
sl@0
  1471
	exprTokenPtr = &parsePtr->tokenPtr[exprIndex];
sl@0
  1472
	exprTokenPtr->size = (infoPtr->next - exprTokenPtr->start);
sl@0
  1473
	exprTokenPtr->numComponents = parsePtr->numTokens - firstIndex;
sl@0
  1474
	break;
sl@0
  1475
    }
sl@0
  1476
sl@0
  1477
    case COMMA:
sl@0
  1478
	LogSyntaxError(infoPtr,
sl@0
  1479
		"commas can only separate function arguments");
sl@0
  1480
	return TCL_ERROR;
sl@0
  1481
    case END:
sl@0
  1482
	LogSyntaxError(infoPtr, "premature end of expression");
sl@0
  1483
	return TCL_ERROR;
sl@0
  1484
    case UNKNOWN:
sl@0
  1485
	LogSyntaxError(infoPtr, "single equality character not legal in expressions");
sl@0
  1486
	return TCL_ERROR;
sl@0
  1487
    case UNKNOWN_CHAR:
sl@0
  1488
	LogSyntaxError(infoPtr, "character not legal in expressions");
sl@0
  1489
	return TCL_ERROR;
sl@0
  1490
    case QUESTY:
sl@0
  1491
	LogSyntaxError(infoPtr, "unexpected ternary 'then' separator");
sl@0
  1492
	return TCL_ERROR;
sl@0
  1493
    case COLON:
sl@0
  1494
	LogSyntaxError(infoPtr, "unexpected ternary 'else' separator");
sl@0
  1495
	return TCL_ERROR;
sl@0
  1496
    case CLOSE_PAREN:
sl@0
  1497
	LogSyntaxError(infoPtr, "unexpected close parenthesis");
sl@0
  1498
	return TCL_ERROR;
sl@0
  1499
sl@0
  1500
    default: {
sl@0
  1501
	char buf[64];
sl@0
  1502
sl@0
  1503
	sprintf(buf, "unexpected operator %s", lexemeStrings[lexeme]);
sl@0
  1504
	LogSyntaxError(infoPtr, buf);
sl@0
  1505
	return TCL_ERROR;
sl@0
  1506
	}
sl@0
  1507
    }
sl@0
  1508
sl@0
  1509
    /*
sl@0
  1510
     * Advance to the next lexeme before returning.
sl@0
  1511
     */
sl@0
  1512
    
sl@0
  1513
    code = GetLexeme(infoPtr);
sl@0
  1514
    if (code != TCL_OK) {
sl@0
  1515
	return code;
sl@0
  1516
    }
sl@0
  1517
    parsePtr->term = infoPtr->next;
sl@0
  1518
    return TCL_OK;
sl@0
  1519
}
sl@0
  1520

sl@0
  1521
/*
sl@0
  1522
 *----------------------------------------------------------------------
sl@0
  1523
 *
sl@0
  1524
 * GetLexeme --
sl@0
  1525
 *
sl@0
  1526
 *	Lexical scanner for Tcl expressions: scans a single operator or
sl@0
  1527
 *	other syntactic element from an expression string.
sl@0
  1528
 *
sl@0
  1529
 * Results:
sl@0
  1530
 *	TCL_OK is returned unless an error occurred. In that case a standard
sl@0
  1531
 *	Tcl error code is returned and, if infoPtr->parsePtr->interp is
sl@0
  1532
 *	non-NULL, the interpreter's result is set to hold an error
sl@0
  1533
 *	message. TCL_ERROR is returned if an integer overflow, or a
sl@0
  1534
 *	floating-point overflow or underflow occurred while reading in a
sl@0
  1535
 *	number. If the lexical analysis is successful, infoPtr->lexeme
sl@0
  1536
 *	refers to the next symbol in the expression string, and
sl@0
  1537
 *	infoPtr->next is advanced past the lexeme. Also, if the lexeme is a
sl@0
  1538
 *	LITERAL or FUNC_NAME, then infoPtr->start is set to the first
sl@0
  1539
 *	character of the lexeme; otherwise it is set NULL.
sl@0
  1540
 *
sl@0
  1541
 * Side effects:
sl@0
  1542
 *	If there is insufficient space in parsePtr to hold all the
sl@0
  1543
 *	information about the subexpression, then additional space is
sl@0
  1544
 *	malloc-ed..
sl@0
  1545
 *
sl@0
  1546
 *----------------------------------------------------------------------
sl@0
  1547
 */
sl@0
  1548
sl@0
  1549
static int
sl@0
  1550
GetLexeme(infoPtr)
sl@0
  1551
    ParseInfo *infoPtr;		/* Holds state needed to parse the expr,
sl@0
  1552
				 * including the resulting lexeme. */
sl@0
  1553
{
sl@0
  1554
    register CONST char *src;	/* Points to current source char. */
sl@0
  1555
    char c;
sl@0
  1556
    int offset, length, numBytes;
sl@0
  1557
    Tcl_Parse *parsePtr = infoPtr->parsePtr;
sl@0
  1558
    Tcl_Interp *interp = parsePtr->interp;
sl@0
  1559
    Tcl_UniChar ch;
sl@0
  1560
sl@0
  1561
    /*
sl@0
  1562
     * Record where the previous lexeme ended. Since we always read one
sl@0
  1563
     * lexeme ahead during parsing, this helps us know the source length of
sl@0
  1564
     * subexpression tokens.
sl@0
  1565
     */
sl@0
  1566
sl@0
  1567
    infoPtr->prevEnd = infoPtr->next;
sl@0
  1568
sl@0
  1569
    /*
sl@0
  1570
     * Scan over leading white space at the start of a lexeme. 
sl@0
  1571
     */
sl@0
  1572
sl@0
  1573
    src = infoPtr->next;
sl@0
  1574
    numBytes = parsePtr->end - src;
sl@0
  1575
    do {
sl@0
  1576
	char type;
sl@0
  1577
	int scanned = TclParseWhiteSpace(src, numBytes, parsePtr, &type);
sl@0
  1578
	src += scanned; numBytes -= scanned;
sl@0
  1579
    } while  (numBytes && (*src == '\n') && (src++,numBytes--));
sl@0
  1580
    parsePtr->term = src;
sl@0
  1581
    if (numBytes == 0) {
sl@0
  1582
	infoPtr->lexeme = END;
sl@0
  1583
	infoPtr->next = src;
sl@0
  1584
	return TCL_OK;
sl@0
  1585
    }
sl@0
  1586
sl@0
  1587
    /*
sl@0
  1588
     * Try to parse the lexeme first as an integer or floating-point
sl@0
  1589
     * number. Don't check for a number if the first character c is
sl@0
  1590
     * "+" or "-". If we did, we might treat a binary operator as unary
sl@0
  1591
     * by mistake, which would eventually cause a syntax error.
sl@0
  1592
     */
sl@0
  1593
sl@0
  1594
    c = *src;
sl@0
  1595
    if ((c != '+') && (c != '-')) {
sl@0
  1596
	CONST char *end = infoPtr->lastChar;
sl@0
  1597
	if ((length = TclParseInteger(src, (end - src)))) {
sl@0
  1598
	    /*
sl@0
  1599
	     * First length bytes look like an integer.  Verify by
sl@0
  1600
	     * attempting the conversion to the largest integer we have.
sl@0
  1601
	     */
sl@0
  1602
	    int code;
sl@0
  1603
	    Tcl_WideInt wide;
sl@0
  1604
	    Tcl_Obj *value = Tcl_NewStringObj(src, length);
sl@0
  1605
sl@0
  1606
	    Tcl_IncrRefCount(value);
sl@0
  1607
	    code = Tcl_GetWideIntFromObj(interp, value, &wide);
sl@0
  1608
	    Tcl_DecrRefCount(value);
sl@0
  1609
	    if (code == TCL_ERROR) {
sl@0
  1610
		parsePtr->errorType = TCL_PARSE_BAD_NUMBER;
sl@0
  1611
		return TCL_ERROR;
sl@0
  1612
	    }
sl@0
  1613
            infoPtr->lexeme = LITERAL;
sl@0
  1614
	    infoPtr->start = src;
sl@0
  1615
	    infoPtr->size = length;
sl@0
  1616
            infoPtr->next = (src + length);
sl@0
  1617
	    parsePtr->term = infoPtr->next;
sl@0
  1618
            return TCL_OK;
sl@0
  1619
	} else if ((length = ParseMaxDoubleLength(src, end))) {
sl@0
  1620
	    /*
sl@0
  1621
	     * There are length characters that could be a double.
sl@0
  1622
	     * Let strtod() tells us for sure.  Need a writable copy
sl@0
  1623
	     * so we can set an terminating NULL to keep strtod from
sl@0
  1624
	     * scanning too far.
sl@0
  1625
	     */
sl@0
  1626
	    char *startPtr, *termPtr;
sl@0
  1627
	    double doubleValue;
sl@0
  1628
	    Tcl_DString toParse;
sl@0
  1629
sl@0
  1630
	    errno = 0;
sl@0
  1631
	    Tcl_DStringInit(&toParse);
sl@0
  1632
	    startPtr = Tcl_DStringAppend(&toParse, src, length);
sl@0
  1633
	    doubleValue = strtod(startPtr, &termPtr);
sl@0
  1634
	    Tcl_DStringFree(&toParse);
sl@0
  1635
	    if (termPtr != startPtr) {
sl@0
  1636
		if (errno != 0) {
sl@0
  1637
		    if (interp != NULL) {
sl@0
  1638
			TclExprFloatError(interp, doubleValue);
sl@0
  1639
		    }
sl@0
  1640
		    parsePtr->errorType = TCL_PARSE_BAD_NUMBER;
sl@0
  1641
		    return TCL_ERROR;
sl@0
  1642
		}
sl@0
  1643
		
sl@0
  1644
		/*
sl@0
  1645
                 * startPtr was the start of a valid double, copied
sl@0
  1646
		 * from src.
sl@0
  1647
                 */
sl@0
  1648
		
sl@0
  1649
		infoPtr->lexeme = LITERAL;
sl@0
  1650
		infoPtr->start = src;
sl@0
  1651
		if ((termPtr - startPtr) > length) {
sl@0
  1652
		    infoPtr->size = length;
sl@0
  1653
		} else {
sl@0
  1654
		    infoPtr->size = (termPtr - startPtr);
sl@0
  1655
		}
sl@0
  1656
		infoPtr->next = src + infoPtr->size;
sl@0
  1657
		parsePtr->term = infoPtr->next;
sl@0
  1658
		return TCL_OK;
sl@0
  1659
	    }
sl@0
  1660
	}
sl@0
  1661
    }
sl@0
  1662
sl@0
  1663
    /*
sl@0
  1664
     * Not an integer or double literal. Initialize the lexeme's fields
sl@0
  1665
     * assuming the common case of a single character lexeme.
sl@0
  1666
     */
sl@0
  1667
sl@0
  1668
    infoPtr->start = src;
sl@0
  1669
    infoPtr->size = 1;
sl@0
  1670
    infoPtr->next = src+1;
sl@0
  1671
    parsePtr->term = infoPtr->next;
sl@0
  1672
    
sl@0
  1673
    switch (*src) {
sl@0
  1674
	case '[':
sl@0
  1675
	    infoPtr->lexeme = OPEN_BRACKET;
sl@0
  1676
	    return TCL_OK;
sl@0
  1677
sl@0
  1678
        case '{':
sl@0
  1679
	    infoPtr->lexeme = OPEN_BRACE;
sl@0
  1680
	    return TCL_OK;
sl@0
  1681
sl@0
  1682
	case '(':
sl@0
  1683
	    infoPtr->lexeme = OPEN_PAREN;
sl@0
  1684
	    return TCL_OK;
sl@0
  1685
sl@0
  1686
	case ')':
sl@0
  1687
	    infoPtr->lexeme = CLOSE_PAREN;
sl@0
  1688
	    return TCL_OK;
sl@0
  1689
sl@0
  1690
	case '$':
sl@0
  1691
	    infoPtr->lexeme = DOLLAR;
sl@0
  1692
	    return TCL_OK;
sl@0
  1693
sl@0
  1694
	case '\"':
sl@0
  1695
	    infoPtr->lexeme = QUOTE;
sl@0
  1696
	    return TCL_OK;
sl@0
  1697
sl@0
  1698
	case ',':
sl@0
  1699
	    infoPtr->lexeme = COMMA;
sl@0
  1700
	    return TCL_OK;
sl@0
  1701
sl@0
  1702
	case '*':
sl@0
  1703
	    infoPtr->lexeme = MULT;
sl@0
  1704
	    return TCL_OK;
sl@0
  1705
sl@0
  1706
	case '/':
sl@0
  1707
	    infoPtr->lexeme = DIVIDE;
sl@0
  1708
	    return TCL_OK;
sl@0
  1709
sl@0
  1710
	case '%':
sl@0
  1711
	    infoPtr->lexeme = MOD;
sl@0
  1712
	    return TCL_OK;
sl@0
  1713
sl@0
  1714
	case '+':
sl@0
  1715
	    infoPtr->lexeme = PLUS;
sl@0
  1716
	    return TCL_OK;
sl@0
  1717
sl@0
  1718
	case '-':
sl@0
  1719
	    infoPtr->lexeme = MINUS;
sl@0
  1720
	    return TCL_OK;
sl@0
  1721
sl@0
  1722
	case '?':
sl@0
  1723
	    infoPtr->lexeme = QUESTY;
sl@0
  1724
	    return TCL_OK;
sl@0
  1725
sl@0
  1726
	case ':':
sl@0
  1727
	    infoPtr->lexeme = COLON;
sl@0
  1728
	    return TCL_OK;
sl@0
  1729
sl@0
  1730
	case '<':
sl@0
  1731
	    infoPtr->lexeme = LESS;
sl@0
  1732
	    if ((infoPtr->lastChar - src) > 1) {
sl@0
  1733
		switch (src[1]) {
sl@0
  1734
		    case '<':
sl@0
  1735
			infoPtr->lexeme = LEFT_SHIFT;
sl@0
  1736
			infoPtr->size = 2;
sl@0
  1737
			infoPtr->next = src+2;
sl@0
  1738
			break;
sl@0
  1739
		    case '=':
sl@0
  1740
			infoPtr->lexeme = LEQ;
sl@0
  1741
			infoPtr->size = 2;
sl@0
  1742
			infoPtr->next = src+2;
sl@0
  1743
			break;
sl@0
  1744
		}
sl@0
  1745
	    }
sl@0
  1746
	    parsePtr->term = infoPtr->next;
sl@0
  1747
	    return TCL_OK;
sl@0
  1748
sl@0
  1749
	case '>':
sl@0
  1750
	    infoPtr->lexeme = GREATER;
sl@0
  1751
	    if ((infoPtr->lastChar - src) > 1) {
sl@0
  1752
		switch (src[1]) {
sl@0
  1753
		    case '>':
sl@0
  1754
			infoPtr->lexeme = RIGHT_SHIFT;
sl@0
  1755
			infoPtr->size = 2;
sl@0
  1756
			infoPtr->next = src+2;
sl@0
  1757
			break;
sl@0
  1758
		    case '=':
sl@0
  1759
			infoPtr->lexeme = GEQ;
sl@0
  1760
			infoPtr->size = 2;
sl@0
  1761
			infoPtr->next = src+2;
sl@0
  1762
			break;
sl@0
  1763
		}
sl@0
  1764
	    }
sl@0
  1765
	    parsePtr->term = infoPtr->next;
sl@0
  1766
	    return TCL_OK;
sl@0
  1767
sl@0
  1768
	case '=':
sl@0
  1769
	    infoPtr->lexeme = UNKNOWN;
sl@0
  1770
	    if ((src[1] == '=') && ((infoPtr->lastChar - src) > 1)) {
sl@0
  1771
		infoPtr->lexeme = EQUAL;
sl@0
  1772
		infoPtr->size = 2;
sl@0
  1773
		infoPtr->next = src+2;
sl@0
  1774
	    }
sl@0
  1775
	    parsePtr->term = infoPtr->next;
sl@0
  1776
	    return TCL_OK;
sl@0
  1777
sl@0
  1778
	case '!':
sl@0
  1779
	    infoPtr->lexeme = NOT;
sl@0
  1780
	    if ((src[1] == '=') && ((infoPtr->lastChar - src) > 1)) {
sl@0
  1781
		infoPtr->lexeme = NEQ;
sl@0
  1782
		infoPtr->size = 2;
sl@0
  1783
		infoPtr->next = src+2;
sl@0
  1784
	    }
sl@0
  1785
	    parsePtr->term = infoPtr->next;
sl@0
  1786
	    return TCL_OK;
sl@0
  1787
sl@0
  1788
	case '&':
sl@0
  1789
	    infoPtr->lexeme = BIT_AND;
sl@0
  1790
	    if ((src[1] == '&') && ((infoPtr->lastChar - src) > 1)) {
sl@0
  1791
		infoPtr->lexeme = AND;
sl@0
  1792
		infoPtr->size = 2;
sl@0
  1793
		infoPtr->next = src+2;
sl@0
  1794
	    }
sl@0
  1795
	    parsePtr->term = infoPtr->next;
sl@0
  1796
	    return TCL_OK;
sl@0
  1797
sl@0
  1798
	case '^':
sl@0
  1799
	    infoPtr->lexeme = BIT_XOR;
sl@0
  1800
	    return TCL_OK;
sl@0
  1801
sl@0
  1802
	case '|':
sl@0
  1803
	    infoPtr->lexeme = BIT_OR;
sl@0
  1804
	    if ((src[1] == '|') && ((infoPtr->lastChar - src) > 1)) {
sl@0
  1805
		infoPtr->lexeme = OR;
sl@0
  1806
		infoPtr->size = 2;
sl@0
  1807
		infoPtr->next = src+2;
sl@0
  1808
	    }
sl@0
  1809
	    parsePtr->term = infoPtr->next;
sl@0
  1810
	    return TCL_OK;
sl@0
  1811
sl@0
  1812
	case '~':
sl@0
  1813
	    infoPtr->lexeme = BIT_NOT;
sl@0
  1814
	    return TCL_OK;
sl@0
  1815
sl@0
  1816
	case 'e':
sl@0
  1817
	    if ((src[1] == 'q') && ((infoPtr->lastChar - src) > 1)) {
sl@0
  1818
		infoPtr->lexeme = STREQ;
sl@0
  1819
		infoPtr->size = 2;
sl@0
  1820
		infoPtr->next = src+2;
sl@0
  1821
		parsePtr->term = infoPtr->next;
sl@0
  1822
		return TCL_OK;
sl@0
  1823
	    } else {
sl@0
  1824
		goto checkFuncName;
sl@0
  1825
	    }
sl@0
  1826
sl@0
  1827
	case 'n':
sl@0
  1828
	    if ((src[1] == 'e') && ((infoPtr->lastChar - src) > 1)) {
sl@0
  1829
		infoPtr->lexeme = STRNEQ;
sl@0
  1830
		infoPtr->size = 2;
sl@0
  1831
		infoPtr->next = src+2;
sl@0
  1832
		parsePtr->term = infoPtr->next;
sl@0
  1833
		return TCL_OK;
sl@0
  1834
	    } else {
sl@0
  1835
		goto checkFuncName;
sl@0
  1836
	    }
sl@0
  1837
sl@0
  1838
	default:
sl@0
  1839
	checkFuncName:
sl@0
  1840
	    length = (infoPtr->lastChar - src);
sl@0
  1841
	    if (Tcl_UtfCharComplete(src, length)) {
sl@0
  1842
		offset = Tcl_UtfToUniChar(src, &ch);
sl@0
  1843
	    } else {
sl@0
  1844
		char utfBytes[TCL_UTF_MAX];
sl@0
  1845
		memcpy(utfBytes, src, (size_t) length);
sl@0
  1846
		utfBytes[length] = '\0';
sl@0
  1847
		offset = Tcl_UtfToUniChar(utfBytes, &ch);
sl@0
  1848
	    }
sl@0
  1849
	    c = UCHAR(ch);
sl@0
  1850
	    if (isalpha(UCHAR(c))) {	/* INTL: ISO only. */
sl@0
  1851
		infoPtr->lexeme = FUNC_NAME;
sl@0
  1852
		while (isalnum(UCHAR(c)) || (c == '_')) { /* INTL: ISO only. */
sl@0
  1853
		    src += offset; length -= offset;
sl@0
  1854
		    if (Tcl_UtfCharComplete(src, length)) {
sl@0
  1855
			offset = Tcl_UtfToUniChar(src, &ch);
sl@0
  1856
		    } else {
sl@0
  1857
			char utfBytes[TCL_UTF_MAX];
sl@0
  1858
			memcpy(utfBytes, src, (size_t) length);
sl@0
  1859
			utfBytes[length] = '\0';
sl@0
  1860
			offset = Tcl_UtfToUniChar(utfBytes, &ch);
sl@0
  1861
		    }
sl@0
  1862
		    c = UCHAR(ch);
sl@0
  1863
		}
sl@0
  1864
		infoPtr->size = (src - infoPtr->start);
sl@0
  1865
		infoPtr->next = src;
sl@0
  1866
		parsePtr->term = infoPtr->next;
sl@0
  1867
		return TCL_OK;
sl@0
  1868
	    }
sl@0
  1869
	    infoPtr->lexeme = UNKNOWN_CHAR;
sl@0
  1870
	    return TCL_OK;
sl@0
  1871
    }
sl@0
  1872
}
sl@0
  1873

sl@0
  1874
/*
sl@0
  1875
 *----------------------------------------------------------------------
sl@0
  1876
 *
sl@0
  1877
 * TclParseInteger --
sl@0
  1878
 *
sl@0
  1879
 *	Scans up to numBytes bytes starting at src, and checks whether
sl@0
  1880
 *	the leading bytes look like an integer's string representation.
sl@0
  1881
 *
sl@0
  1882
 * Results:
sl@0
  1883
 *	Returns 0 if the leading bytes do not look like an integer.
sl@0
  1884
 *	Otherwise, returns the number of bytes examined that look
sl@0
  1885
 *	like an integer.  This may be less than numBytes if the integer
sl@0
  1886
 *	is only the leading part of the string.
sl@0
  1887
 *
sl@0
  1888
 * Side effects:
sl@0
  1889
 *	None.
sl@0
  1890
 *
sl@0
  1891
 *----------------------------------------------------------------------
sl@0
  1892
 */
sl@0
  1893
sl@0
  1894
int
sl@0
  1895
TclParseInteger(string, numBytes)
sl@0
  1896
    register CONST char *string;/* The string to examine. */
sl@0
  1897
    register int numBytes;	/* Max number of bytes to scan. */
sl@0
  1898
{
sl@0
  1899
    register CONST char *p = string;
sl@0
  1900
sl@0
  1901
    /* Take care of introductory "0x" */
sl@0
  1902
    if ((numBytes > 1) && (p[0] == '0') && ((p[1] == 'x') || (p[1] == 'X'))) {
sl@0
  1903
	int scanned;
sl@0
  1904
	Tcl_UniChar ch;
sl@0
  1905
	p+=2; numBytes -= 2;
sl@0
  1906
 	scanned = TclParseHex(p, numBytes, &ch);
sl@0
  1907
	if (scanned) {
sl@0
  1908
	    return scanned + 2;
sl@0
  1909
	}
sl@0
  1910
sl@0
  1911
	/* Recognize the 0 as valid integer, but x is left behind */
sl@0
  1912
	return 1;
sl@0
  1913
    }
sl@0
  1914
    while (numBytes && isdigit(UCHAR(*p))) {	/* INTL: digit */
sl@0
  1915
	numBytes--; p++;
sl@0
  1916
    }
sl@0
  1917
    if (numBytes == 0) {
sl@0
  1918
        return (p - string);
sl@0
  1919
    }
sl@0
  1920
    if ((*p != '.') && (*p != 'e') && (*p != 'E')) {
sl@0
  1921
        return (p - string);
sl@0
  1922
    }
sl@0
  1923
    return 0;
sl@0
  1924
}
sl@0
  1925

sl@0
  1926
/*
sl@0
  1927
 *----------------------------------------------------------------------
sl@0
  1928
 *
sl@0
  1929
 * ParseMaxDoubleLength --
sl@0
  1930
 *
sl@0
  1931
 *      Scans a sequence of bytes checking that the characters could
sl@0
  1932
 *	be in a string rep of a double.
sl@0
  1933
 *
sl@0
  1934
 * Results:
sl@0
  1935
 *	Returns the number of bytes starting with string, runing to, but
sl@0
  1936
 *	not including end, all of which could be part of a string rep.
sl@0
  1937
 *	of a double.  Only character identity is used, no actual
sl@0
  1938
 *	parsing is done.
sl@0
  1939
 *
sl@0
  1940
 *	The legal bytes are '0' - '9', 'A' - 'F', 'a' - 'f', 
sl@0
  1941
 *	'.', '+', '-', 'i', 'I', 'n', 'N', 'p', 'P', 'x',  and 'X'.
sl@0
  1942
 *	This covers the values "Inf" and "Nan" as well as the
sl@0
  1943
 *	decimal and hexadecimal representations recognized by a
sl@0
  1944
 *	C99-compliant strtod().
sl@0
  1945
 *
sl@0
  1946
 * Side effects:
sl@0
  1947
 *	None.
sl@0
  1948
 *
sl@0
  1949
 *----------------------------------------------------------------------
sl@0
  1950
 */
sl@0
  1951
sl@0
  1952
static int
sl@0
  1953
ParseMaxDoubleLength(string, end)
sl@0
  1954
    register CONST char *string;/* The string to examine. */
sl@0
  1955
    CONST char *end;		/* Point to the first character past the end
sl@0
  1956
				 * of the string we are examining. */
sl@0
  1957
{
sl@0
  1958
    CONST char *p = string;
sl@0
  1959
    while (p < end) {
sl@0
  1960
	switch (*p) {
sl@0
  1961
	    case '0': case '1': case '2': case '3': case '4': case '5':
sl@0
  1962
	    case '6': case '7': case '8': case '9': case 'A': case 'B':
sl@0
  1963
	    case 'C': case 'D': case 'E': case 'F': case 'I': case 'N':
sl@0
  1964
	    case 'P': case 'X': case 'a': case 'b': case 'c': case 'd':
sl@0
  1965
	    case 'e': case 'f': case 'i': case 'n': case 'p': case 'x':
sl@0
  1966
	    case '.': case '+': case '-':
sl@0
  1967
		p++;
sl@0
  1968
		break;
sl@0
  1969
	    default:
sl@0
  1970
		goto done;
sl@0
  1971
	}
sl@0
  1972
    }
sl@0
  1973
    done:
sl@0
  1974
    return (p - string);
sl@0
  1975
}
sl@0
  1976

sl@0
  1977
/*
sl@0
  1978
 *----------------------------------------------------------------------
sl@0
  1979
 *
sl@0
  1980
 * PrependSubExprTokens --
sl@0
  1981
 *
sl@0
  1982
 *	This procedure is called after the operands of an subexpression have
sl@0
  1983
 *	been parsed. It generates two tokens: a TCL_TOKEN_SUB_EXPR token for
sl@0
  1984
 *	the subexpression, and a TCL_TOKEN_OPERATOR token for its operator.
sl@0
  1985
 *	These two tokens are inserted before the operand tokens.
sl@0
  1986
 *
sl@0
  1987
 * Results:
sl@0
  1988
 *	None.
sl@0
  1989
 *
sl@0
  1990
 * Side effects:
sl@0
  1991
 *	If there is insufficient space in parsePtr to hold the new tokens,
sl@0
  1992
 *	additional space is malloc-ed.
sl@0
  1993
 *
sl@0
  1994
 *----------------------------------------------------------------------
sl@0
  1995
 */
sl@0
  1996
sl@0
  1997
static void
sl@0
  1998
PrependSubExprTokens(op, opBytes, src, srcBytes, firstIndex, infoPtr)
sl@0
  1999
    CONST char *op;		/* Points to first byte of the operator
sl@0
  2000
				 * in the source script. */
sl@0
  2001
    int opBytes;		/* Number of bytes in the operator. */
sl@0
  2002
    CONST char *src;		/* Points to first byte of the subexpression
sl@0
  2003
				 * in the source script. */
sl@0
  2004
    int srcBytes;		/* Number of bytes in subexpression's
sl@0
  2005
				 * source. */
sl@0
  2006
    int firstIndex;		/* Index of first token already emitted for
sl@0
  2007
				 * operator's first (or only) operand. */
sl@0
  2008
    ParseInfo *infoPtr;		/* Holds the parse state for the
sl@0
  2009
				 * expression being parsed. */
sl@0
  2010
{
sl@0
  2011
    Tcl_Parse *parsePtr = infoPtr->parsePtr;
sl@0
  2012
    Tcl_Token *tokenPtr, *firstTokenPtr;
sl@0
  2013
    int numToMove;
sl@0
  2014
sl@0
  2015
    if ((parsePtr->numTokens + 1) >= parsePtr->tokensAvailable) {
sl@0
  2016
	TclExpandTokenArray(parsePtr);
sl@0
  2017
    }
sl@0
  2018
    firstTokenPtr = &parsePtr->tokenPtr[firstIndex];
sl@0
  2019
    tokenPtr = (firstTokenPtr + 2);
sl@0
  2020
    numToMove = (parsePtr->numTokens - firstIndex);
sl@0
  2021
    memmove((VOID *) tokenPtr, (VOID *) firstTokenPtr,
sl@0
  2022
            (size_t) (numToMove * sizeof(Tcl_Token)));
sl@0
  2023
    parsePtr->numTokens += 2;
sl@0
  2024
    
sl@0
  2025
    tokenPtr = firstTokenPtr;
sl@0
  2026
    tokenPtr->type = TCL_TOKEN_SUB_EXPR;
sl@0
  2027
    tokenPtr->start = src;
sl@0
  2028
    tokenPtr->size = srcBytes;
sl@0
  2029
    tokenPtr->numComponents = parsePtr->numTokens - (firstIndex + 1);
sl@0
  2030
    
sl@0
  2031
    tokenPtr++;
sl@0
  2032
    tokenPtr->type = TCL_TOKEN_OPERATOR;
sl@0
  2033
    tokenPtr->start = op;
sl@0
  2034
    tokenPtr->size = opBytes;
sl@0
  2035
    tokenPtr->numComponents = 0;
sl@0
  2036
}
sl@0
  2037

sl@0
  2038
/*
sl@0
  2039
 *----------------------------------------------------------------------
sl@0
  2040
 *
sl@0
  2041
 * LogSyntaxError --
sl@0
  2042
 *
sl@0
  2043
 *	This procedure is invoked after an error occurs when parsing an
sl@0
  2044
 *	expression. It sets the interpreter result to an error message
sl@0
  2045
 *	describing the error.
sl@0
  2046
 *
sl@0
  2047
 * Results:
sl@0
  2048
 *	None.
sl@0
  2049
 *
sl@0
  2050
 * Side effects:
sl@0
  2051
 *	Sets the interpreter result to an error message describing the
sl@0
  2052
 *	expression that was being parsed when the error occurred, and why
sl@0
  2053
 *	the parser considers that to be a syntax error at all.
sl@0
  2054
 *
sl@0
  2055
 *----------------------------------------------------------------------
sl@0
  2056
 */
sl@0
  2057
sl@0
  2058
static void
sl@0
  2059
LogSyntaxError(infoPtr, extraInfo)
sl@0
  2060
    ParseInfo *infoPtr;		/* Holds the parse state for the
sl@0
  2061
				 * expression being parsed. */
sl@0
  2062
    CONST char *extraInfo;	/* String to provide extra information
sl@0
  2063
				 * about the syntax error. */
sl@0
  2064
{
sl@0
  2065
    int numBytes = (infoPtr->lastChar - infoPtr->originalExpr);
sl@0
  2066
    char buffer[100];
sl@0
  2067
sl@0
  2068
    if (numBytes > 60) {
sl@0
  2069
	sprintf(buffer, "syntax error in expression \"%.60s...\"",
sl@0
  2070
		infoPtr->originalExpr);
sl@0
  2071
    } else {
sl@0
  2072
	sprintf(buffer, "syntax error in expression \"%.*s\"",
sl@0
  2073
		numBytes, infoPtr->originalExpr);
sl@0
  2074
    }
sl@0
  2075
    Tcl_ResetResult(infoPtr->parsePtr->interp);
sl@0
  2076
    Tcl_AppendStringsToObj(Tcl_GetObjResult(infoPtr->parsePtr->interp),
sl@0
  2077
	    buffer, ": ", extraInfo, (char *) NULL);
sl@0
  2078
    infoPtr->parsePtr->errorType = TCL_PARSE_SYNTAX;
sl@0
  2079
    infoPtr->parsePtr->term = infoPtr->start;
sl@0
  2080
}