os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/generic/tclParseExpr.c
First public contribution.
4 * This file contains procedures that parse Tcl expressions. They
5 * do so in a general-purpose fashion that can be used for many
6 * different purposes, including compilation, direct execution,
9 * Copyright (c) 1997 Sun Microsystems, Inc.
10 * Copyright (c) 1998-2000 by Scriptics Corporation.
11 * Portions Copyright (c) 2007-2008 Nokia Corporation and/or its subsidiaries. All rights reserved.
12 * Contributions from Don Porter, NIST, 2002. (not subject to US copyright)
14 * See the file "license.terms" for information on usage and redistribution
15 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
17 * RCS: @(#) $Id: tclParseExpr.c,v 1.17.2.2 2005/05/20 17:19:10 vasiljevic Exp $
23 * The stuff below is a bit of a hack so that this file can be used in
24 * environments that include no UNIX, i.e. no errno: just arrange to use
25 * the errno from tclExecute.c here.
28 #ifndef TCL_GENERIC_ONLY
35 extern int errno; /* Use errno from tclExecute.c. */
40 * Boolean variable that controls whether expression parse tracing
44 #ifdef TCL_COMPILE_DEBUG
45 static int traceParseExpr = 0;
46 #endif /* TCL_COMPILE_DEBUG */
49 * The ParseInfo structure holds state while parsing an expression.
50 * A pointer to an ParseInfo record is passed among the routines in
54 typedef struct ParseInfo {
55 Tcl_Parse *parsePtr; /* Points to structure to fill in with
56 * information about the expression. */
57 int lexeme; /* Type of last lexeme scanned in expr.
58 * See below for definitions. Corresponds to
59 * size characters beginning at start. */
60 CONST char *start; /* First character in lexeme. */
61 int size; /* Number of bytes in lexeme. */
62 CONST char *next; /* Position of the next character to be
63 * scanned in the expression string. */
64 CONST char *prevEnd; /* Points to the character just after the
65 * last one in the previous lexeme. Used to
66 * compute size of subexpression tokens. */
67 CONST char *originalExpr; /* Points to the start of the expression
68 * originally passed to Tcl_ParseExpr. */
69 CONST char *lastChar; /* Points just after last byte of expr. */
73 * Definitions of the different lexemes that appear in expressions. The
74 * order of these must match the corresponding entries in the
75 * operatorStrings array below.
82 #define OPEN_BRACKET 2
91 #define UNKNOWN_CHAR 11
94 * Binary numeric operators:
102 #define LEFT_SHIFT 17
103 #define RIGHT_SHIFT 18
119 * Unary operators. Unary minus and plus are represented by the (binary)
120 * lexemes MINUS and PLUS.
127 * Binary string operators:
134 * Mapping from lexemes to strings; used for debugging messages. These
135 * entries must match the order and number of the lexeme definitions above.
138 static char *lexemeStrings[] = {
139 "LITERAL", "FUNCNAME",
140 "[", "{", "(", ")", "$", "\"", ",", "END", "UNKNOWN", "UNKNOWN_CHAR",
141 "*", "/", "%", "+", "-",
142 "<<", ">>", "<", ">", "<=", ">=", "==", "!=",
143 "&", "^", "|", "&&", "||", "?", ":",
144 "!", "~", "eq", "ne",
148 * Declarations for local procedures to this file:
151 static int GetLexeme _ANSI_ARGS_((ParseInfo *infoPtr));
152 static void LogSyntaxError _ANSI_ARGS_((ParseInfo *infoPtr,
153 CONST char *extraInfo));
154 static int ParseAddExpr _ANSI_ARGS_((ParseInfo *infoPtr));
155 static int ParseBitAndExpr _ANSI_ARGS_((ParseInfo *infoPtr));
156 static int ParseBitOrExpr _ANSI_ARGS_((ParseInfo *infoPtr));
157 static int ParseBitXorExpr _ANSI_ARGS_((ParseInfo *infoPtr));
158 static int ParseCondExpr _ANSI_ARGS_((ParseInfo *infoPtr));
159 static int ParseEqualityExpr _ANSI_ARGS_((ParseInfo *infoPtr));
160 static int ParseLandExpr _ANSI_ARGS_((ParseInfo *infoPtr));
161 static int ParseLorExpr _ANSI_ARGS_((ParseInfo *infoPtr));
162 static int ParseMaxDoubleLength _ANSI_ARGS_((CONST char *string,
164 static int ParseMultiplyExpr _ANSI_ARGS_((ParseInfo *infoPtr));
165 static int ParsePrimaryExpr _ANSI_ARGS_((ParseInfo *infoPtr));
166 static int ParseRelationalExpr _ANSI_ARGS_((ParseInfo *infoPtr));
167 static int ParseShiftExpr _ANSI_ARGS_((ParseInfo *infoPtr));
168 static int ParseUnaryExpr _ANSI_ARGS_((ParseInfo *infoPtr));
169 static void PrependSubExprTokens _ANSI_ARGS_((CONST char *op,
170 int opBytes, CONST char *src, int srcBytes,
171 int firstIndex, ParseInfo *infoPtr));
174 * Macro used to debug the execution of the recursive descent parser used
175 * to parse expressions.
178 #ifdef TCL_COMPILE_DEBUG
179 #define HERE(production, level) \
180 if (traceParseExpr) { \
181 fprintf(stderr, "%*s%s: lexeme=%s, next=\"%.20s\"\n", \
182 (level), " ", (production), \
183 lexemeStrings[infoPtr->lexeme], infoPtr->next); \
186 #define HERE(production, level)
187 #endif /* TCL_COMPILE_DEBUG */
190 *----------------------------------------------------------------------
194 * Given a string, this procedure parses the first Tcl expression
195 * in the string and returns information about the structure of
196 * the expression. This procedure is the top-level interface to the
197 * the expression parsing module. No more that numBytes bytes will
201 * The return value is TCL_OK if the command was parsed successfully
202 * and TCL_ERROR otherwise. If an error occurs and interp isn't NULL
203 * then an error message is left in its result. On a successful return,
204 * parsePtr is filled in with information about the expression that
208 * If there is insufficient space in parsePtr to hold all the
209 * information about the expression, then additional space is
210 * malloc-ed. If the procedure returns TCL_OK then the caller must
211 * eventually invoke Tcl_FreeParse to release any additional space
212 * that was allocated.
214 *----------------------------------------------------------------------
218 Tcl_ParseExpr(interp, string, numBytes, parsePtr)
219 Tcl_Interp *interp; /* Used for error reporting. */
220 CONST char *string; /* The source string to parse. */
221 int numBytes; /* Number of bytes in string. If < 0, the
222 * string consists of all bytes up to the
223 * first null character. */
224 Tcl_Parse *parsePtr; /* Structure to fill with information about
225 * the parsed expression; any previous
226 * information in the structure is
233 numBytes = (string? strlen(string) : 0);
235 #ifdef TCL_COMPILE_DEBUG
236 if (traceParseExpr) {
237 fprintf(stderr, "Tcl_ParseExpr: string=\"%.*s\"\n",
240 #endif /* TCL_COMPILE_DEBUG */
242 parsePtr->commentStart = NULL;
243 parsePtr->commentSize = 0;
244 parsePtr->commandStart = NULL;
245 parsePtr->commandSize = 0;
246 parsePtr->numWords = 0;
247 parsePtr->tokenPtr = parsePtr->staticTokens;
248 parsePtr->numTokens = 0;
249 parsePtr->tokensAvailable = NUM_STATIC_TOKENS;
250 parsePtr->string = string;
251 parsePtr->end = (string + numBytes);
252 parsePtr->interp = interp;
253 parsePtr->term = string;
254 parsePtr->incomplete = 0;
257 * Initialize the ParseInfo structure that holds state while parsing
261 info.parsePtr = parsePtr;
262 info.lexeme = UNKNOWN;
266 info.prevEnd = string;
267 info.originalExpr = string;
268 info.lastChar = (string + numBytes); /* just after last char of expr */
271 * Get the first lexeme then parse the expression.
274 code = GetLexeme(&info);
275 if (code != TCL_OK) {
278 code = ParseCondExpr(&info);
279 if (code != TCL_OK) {
282 if (info.lexeme != END) {
283 LogSyntaxError(&info, "extra tokens at end of expression");
289 if (parsePtr->tokenPtr != parsePtr->staticTokens) {
290 ckfree((char *) parsePtr->tokenPtr);
296 *----------------------------------------------------------------------
300 * This procedure parses a Tcl conditional expression:
301 * condExpr ::= lorExpr ['?' condExpr ':' condExpr]
303 * Note that this is the topmost recursive-descent parsing routine used
304 * by Tcl_ParseExpr to parse expressions. This avoids an extra procedure
305 * call since such a procedure would only return the result of calling
306 * ParseCondExpr. Other recursive-descent procedures that need to parse
307 * complete expressions also call ParseCondExpr.
310 * The return value is TCL_OK on a successful parse and TCL_ERROR
311 * on failure. If TCL_ERROR is returned, then the interpreter's result
312 * contains an error message.
315 * If there is insufficient space in parsePtr to hold all the
316 * information about the subexpression, then additional space is
319 *----------------------------------------------------------------------
323 ParseCondExpr(infoPtr)
324 ParseInfo *infoPtr; /* Holds the parse state for the
325 * expression being parsed. */
327 Tcl_Parse *parsePtr = infoPtr->parsePtr;
328 Tcl_Token *tokenPtr, *firstTokenPtr, *condTokenPtr;
329 int firstIndex, numToMove, code;
330 CONST char *srcStart;
333 srcStart = infoPtr->start;
334 firstIndex = parsePtr->numTokens;
336 code = ParseLorExpr(infoPtr);
337 if (code != TCL_OK) {
341 if (infoPtr->lexeme == QUESTY) {
343 * Emit two tokens: one TCL_TOKEN_SUB_EXPR token for the entire
344 * conditional expression, and a TCL_TOKEN_OPERATOR token for
345 * the "?" operator. Note that these two tokens must be inserted
346 * before the LOR operand tokens generated above.
349 if ((parsePtr->numTokens + 1) >= parsePtr->tokensAvailable) {
350 TclExpandTokenArray(parsePtr);
352 firstTokenPtr = &parsePtr->tokenPtr[firstIndex];
353 tokenPtr = (firstTokenPtr + 2);
354 numToMove = (parsePtr->numTokens - firstIndex);
355 memmove((VOID *) tokenPtr, (VOID *) firstTokenPtr,
356 (size_t) (numToMove * sizeof(Tcl_Token)));
357 parsePtr->numTokens += 2;
359 tokenPtr = firstTokenPtr;
360 tokenPtr->type = TCL_TOKEN_SUB_EXPR;
361 tokenPtr->start = srcStart;
364 tokenPtr->type = TCL_TOKEN_OPERATOR;
365 tokenPtr->start = infoPtr->start;
367 tokenPtr->numComponents = 0;
373 code = GetLexeme(infoPtr);
374 if (code != TCL_OK) {
379 * Parse the "then" expression.
382 code = ParseCondExpr(infoPtr);
383 if (code != TCL_OK) {
386 if (infoPtr->lexeme != COLON) {
387 LogSyntaxError(infoPtr, "missing colon from ternary conditional");
390 code = GetLexeme(infoPtr); /* skip over the ':' */
391 if (code != TCL_OK) {
396 * Parse the "else" expression.
399 code = ParseCondExpr(infoPtr);
400 if (code != TCL_OK) {
405 * Now set the size-related fields in the '?' subexpression token.
408 condTokenPtr = &parsePtr->tokenPtr[firstIndex];
409 condTokenPtr->size = (infoPtr->prevEnd - srcStart);
410 condTokenPtr->numComponents = parsePtr->numTokens - (firstIndex+1);
416 *----------------------------------------------------------------------
420 * This procedure parses a Tcl logical or expression:
421 * lorExpr ::= landExpr {'||' landExpr}
424 * The return value is TCL_OK on a successful parse and TCL_ERROR
425 * on failure. If TCL_ERROR is returned, then the interpreter's result
426 * contains an error message.
429 * If there is insufficient space in parsePtr to hold all the
430 * information about the subexpression, then additional space is
433 *----------------------------------------------------------------------
437 ParseLorExpr(infoPtr)
438 ParseInfo *infoPtr; /* Holds the parse state for the
439 * expression being parsed. */
441 Tcl_Parse *parsePtr = infoPtr->parsePtr;
442 int firstIndex, code;
443 CONST char *srcStart, *operator;
446 srcStart = infoPtr->start;
447 firstIndex = parsePtr->numTokens;
449 code = ParseLandExpr(infoPtr);
450 if (code != TCL_OK) {
454 while (infoPtr->lexeme == OR) {
455 operator = infoPtr->start;
456 code = GetLexeme(infoPtr); /* skip over the '||' */
457 if (code != TCL_OK) {
460 code = ParseLandExpr(infoPtr);
461 if (code != TCL_OK) {
466 * Generate tokens for the LOR subexpression and the '||' operator.
469 PrependSubExprTokens(operator, 2, srcStart,
470 (infoPtr->prevEnd - srcStart), firstIndex, infoPtr);
476 *----------------------------------------------------------------------
480 * This procedure parses a Tcl logical and expression:
481 * landExpr ::= bitOrExpr {'&&' bitOrExpr}
484 * The return value is TCL_OK on a successful parse and TCL_ERROR
485 * on failure. If TCL_ERROR is returned, then the interpreter's result
486 * contains an error message.
489 * If there is insufficient space in parsePtr to hold all the
490 * information about the subexpression, then additional space is
493 *----------------------------------------------------------------------
497 ParseLandExpr(infoPtr)
498 ParseInfo *infoPtr; /* Holds the parse state for the
499 * expression being parsed. */
501 Tcl_Parse *parsePtr = infoPtr->parsePtr;
502 int firstIndex, code;
503 CONST char *srcStart, *operator;
506 srcStart = infoPtr->start;
507 firstIndex = parsePtr->numTokens;
509 code = ParseBitOrExpr(infoPtr);
510 if (code != TCL_OK) {
514 while (infoPtr->lexeme == AND) {
515 operator = infoPtr->start;
516 code = GetLexeme(infoPtr); /* skip over the '&&' */
517 if (code != TCL_OK) {
520 code = ParseBitOrExpr(infoPtr);
521 if (code != TCL_OK) {
526 * Generate tokens for the LAND subexpression and the '&&' operator.
529 PrependSubExprTokens(operator, 2, srcStart,
530 (infoPtr->prevEnd - srcStart), firstIndex, infoPtr);
536 *----------------------------------------------------------------------
540 * This procedure parses a Tcl bitwise or expression:
541 * bitOrExpr ::= bitXorExpr {'|' bitXorExpr}
544 * The return value is TCL_OK on a successful parse and TCL_ERROR
545 * on failure. If TCL_ERROR is returned, then the interpreter's result
546 * contains an error message.
549 * If there is insufficient space in parsePtr to hold all the
550 * information about the subexpression, then additional space is
553 *----------------------------------------------------------------------
557 ParseBitOrExpr(infoPtr)
558 ParseInfo *infoPtr; /* Holds the parse state for the
559 * expression being parsed. */
561 Tcl_Parse *parsePtr = infoPtr->parsePtr;
562 int firstIndex, code;
563 CONST char *srcStart, *operator;
565 HERE("bitOrExpr", 4);
566 srcStart = infoPtr->start;
567 firstIndex = parsePtr->numTokens;
569 code = ParseBitXorExpr(infoPtr);
570 if (code != TCL_OK) {
574 while (infoPtr->lexeme == BIT_OR) {
575 operator = infoPtr->start;
576 code = GetLexeme(infoPtr); /* skip over the '|' */
577 if (code != TCL_OK) {
581 code = ParseBitXorExpr(infoPtr);
582 if (code != TCL_OK) {
587 * Generate tokens for the BITOR subexpression and the '|' operator.
590 PrependSubExprTokens(operator, 1, srcStart,
591 (infoPtr->prevEnd - srcStart), firstIndex, infoPtr);
597 *----------------------------------------------------------------------
601 * This procedure parses a Tcl bitwise exclusive or expression:
602 * bitXorExpr ::= bitAndExpr {'^' bitAndExpr}
605 * The return value is TCL_OK on a successful parse and TCL_ERROR
606 * on failure. If TCL_ERROR is returned, then the interpreter's result
607 * contains an error message.
610 * If there is insufficient space in parsePtr to hold all the
611 * information about the subexpression, then additional space is
614 *----------------------------------------------------------------------
618 ParseBitXorExpr(infoPtr)
619 ParseInfo *infoPtr; /* Holds the parse state for the
620 * expression being parsed. */
622 Tcl_Parse *parsePtr = infoPtr->parsePtr;
623 int firstIndex, code;
624 CONST char *srcStart, *operator;
626 HERE("bitXorExpr", 5);
627 srcStart = infoPtr->start;
628 firstIndex = parsePtr->numTokens;
630 code = ParseBitAndExpr(infoPtr);
631 if (code != TCL_OK) {
635 while (infoPtr->lexeme == BIT_XOR) {
636 operator = infoPtr->start;
637 code = GetLexeme(infoPtr); /* skip over the '^' */
638 if (code != TCL_OK) {
642 code = ParseBitAndExpr(infoPtr);
643 if (code != TCL_OK) {
648 * Generate tokens for the XOR subexpression and the '^' operator.
651 PrependSubExprTokens(operator, 1, srcStart,
652 (infoPtr->prevEnd - srcStart), firstIndex, infoPtr);
658 *----------------------------------------------------------------------
662 * This procedure parses a Tcl bitwise and expression:
663 * bitAndExpr ::= equalityExpr {'&' equalityExpr}
666 * The return value is TCL_OK on a successful parse and TCL_ERROR
667 * on failure. If TCL_ERROR is returned, then the interpreter's result
668 * contains an error message.
671 * If there is insufficient space in parsePtr to hold all the
672 * information about the subexpression, then additional space is
675 *----------------------------------------------------------------------
679 ParseBitAndExpr(infoPtr)
680 ParseInfo *infoPtr; /* Holds the parse state for the
681 * expression being parsed. */
683 Tcl_Parse *parsePtr = infoPtr->parsePtr;
684 int firstIndex, code;
685 CONST char *srcStart, *operator;
687 HERE("bitAndExpr", 6);
688 srcStart = infoPtr->start;
689 firstIndex = parsePtr->numTokens;
691 code = ParseEqualityExpr(infoPtr);
692 if (code != TCL_OK) {
696 while (infoPtr->lexeme == BIT_AND) {
697 operator = infoPtr->start;
698 code = GetLexeme(infoPtr); /* skip over the '&' */
699 if (code != TCL_OK) {
702 code = ParseEqualityExpr(infoPtr);
703 if (code != TCL_OK) {
708 * Generate tokens for the BITAND subexpression and '&' operator.
711 PrependSubExprTokens(operator, 1, srcStart,
712 (infoPtr->prevEnd - srcStart), firstIndex, infoPtr);
718 *----------------------------------------------------------------------
720 * ParseEqualityExpr --
722 * This procedure parses a Tcl equality (inequality) expression:
723 * equalityExpr ::= relationalExpr
724 * {('==' | '!=' | 'ne' | 'eq') relationalExpr}
727 * The return value is TCL_OK on a successful parse and TCL_ERROR
728 * on failure. If TCL_ERROR is returned, then the interpreter's result
729 * contains an error message.
732 * If there is insufficient space in parsePtr to hold all the
733 * information about the subexpression, then additional space is
736 *----------------------------------------------------------------------
740 ParseEqualityExpr(infoPtr)
741 ParseInfo *infoPtr; /* Holds the parse state for the
742 * expression being parsed. */
744 Tcl_Parse *parsePtr = infoPtr->parsePtr;
745 int firstIndex, lexeme, code;
746 CONST char *srcStart, *operator;
748 HERE("equalityExpr", 7);
749 srcStart = infoPtr->start;
750 firstIndex = parsePtr->numTokens;
752 code = ParseRelationalExpr(infoPtr);
753 if (code != TCL_OK) {
757 lexeme = infoPtr->lexeme;
758 while ((lexeme == EQUAL) || (lexeme == NEQ)
759 || (lexeme == STREQ) || (lexeme == STRNEQ)) {
760 operator = infoPtr->start;
761 code = GetLexeme(infoPtr); /* skip over ==, !=, 'eq' or 'ne' */
762 if (code != TCL_OK) {
765 code = ParseRelationalExpr(infoPtr);
766 if (code != TCL_OK) {
771 * Generate tokens for the subexpression and '==', '!=', 'eq' or 'ne'
775 PrependSubExprTokens(operator, 2, srcStart,
776 (infoPtr->prevEnd - srcStart), firstIndex, infoPtr);
777 lexeme = infoPtr->lexeme;
783 *----------------------------------------------------------------------
785 * ParseRelationalExpr --
787 * This procedure parses a Tcl relational expression:
788 * relationalExpr ::= shiftExpr {('<' | '>' | '<=' | '>=') shiftExpr}
791 * The return value is TCL_OK on a successful parse and TCL_ERROR
792 * on failure. If TCL_ERROR is returned, then the interpreter's result
793 * contains an error message.
796 * If there is insufficient space in parsePtr to hold all the
797 * information about the subexpression, then additional space is
800 *----------------------------------------------------------------------
804 ParseRelationalExpr(infoPtr)
805 ParseInfo *infoPtr; /* Holds the parse state for the
806 * expression being parsed. */
808 Tcl_Parse *parsePtr = infoPtr->parsePtr;
809 int firstIndex, lexeme, operatorSize, code;
810 CONST char *srcStart, *operator;
812 HERE("relationalExpr", 8);
813 srcStart = infoPtr->start;
814 firstIndex = parsePtr->numTokens;
816 code = ParseShiftExpr(infoPtr);
817 if (code != TCL_OK) {
821 lexeme = infoPtr->lexeme;
822 while ((lexeme == LESS) || (lexeme == GREATER) || (lexeme == LEQ)
823 || (lexeme == GEQ)) {
824 operator = infoPtr->start;
825 if ((lexeme == LEQ) || (lexeme == GEQ)) {
830 code = GetLexeme(infoPtr); /* skip over the operator */
831 if (code != TCL_OK) {
834 code = ParseShiftExpr(infoPtr);
835 if (code != TCL_OK) {
840 * Generate tokens for the subexpression and the operator.
843 PrependSubExprTokens(operator, operatorSize, srcStart,
844 (infoPtr->prevEnd - srcStart), firstIndex, infoPtr);
845 lexeme = infoPtr->lexeme;
851 *----------------------------------------------------------------------
855 * This procedure parses a Tcl shift expression:
856 * shiftExpr ::= addExpr {('<<' | '>>') addExpr}
859 * The return value is TCL_OK on a successful parse and TCL_ERROR
860 * on failure. If TCL_ERROR is returned, then the interpreter's result
861 * contains an error message.
864 * If there is insufficient space in parsePtr to hold all the
865 * information about the subexpression, then additional space is
868 *----------------------------------------------------------------------
872 ParseShiftExpr(infoPtr)
873 ParseInfo *infoPtr; /* Holds the parse state for the
874 * expression being parsed. */
876 Tcl_Parse *parsePtr = infoPtr->parsePtr;
877 int firstIndex, lexeme, code;
878 CONST char *srcStart, *operator;
880 HERE("shiftExpr", 9);
881 srcStart = infoPtr->start;
882 firstIndex = parsePtr->numTokens;
884 code = ParseAddExpr(infoPtr);
885 if (code != TCL_OK) {
889 lexeme = infoPtr->lexeme;
890 while ((lexeme == LEFT_SHIFT) || (lexeme == RIGHT_SHIFT)) {
891 operator = infoPtr->start;
892 code = GetLexeme(infoPtr); /* skip over << or >> */
893 if (code != TCL_OK) {
896 code = ParseAddExpr(infoPtr);
897 if (code != TCL_OK) {
902 * Generate tokens for the subexpression and '<<' or '>>' operator.
905 PrependSubExprTokens(operator, 2, srcStart,
906 (infoPtr->prevEnd - srcStart), firstIndex, infoPtr);
907 lexeme = infoPtr->lexeme;
913 *----------------------------------------------------------------------
917 * This procedure parses a Tcl addition expression:
918 * addExpr ::= multiplyExpr {('+' | '-') multiplyExpr}
921 * The return value is TCL_OK on a successful parse and TCL_ERROR
922 * on failure. If TCL_ERROR is returned, then the interpreter's result
923 * contains an error message.
926 * If there is insufficient space in parsePtr to hold all the
927 * information about the subexpression, then additional space is
930 *----------------------------------------------------------------------
934 ParseAddExpr(infoPtr)
935 ParseInfo *infoPtr; /* Holds the parse state for the
936 * expression being parsed. */
938 Tcl_Parse *parsePtr = infoPtr->parsePtr;
939 int firstIndex, lexeme, code;
940 CONST char *srcStart, *operator;
943 srcStart = infoPtr->start;
944 firstIndex = parsePtr->numTokens;
946 code = ParseMultiplyExpr(infoPtr);
947 if (code != TCL_OK) {
951 lexeme = infoPtr->lexeme;
952 while ((lexeme == PLUS) || (lexeme == MINUS)) {
953 operator = infoPtr->start;
954 code = GetLexeme(infoPtr); /* skip over + or - */
955 if (code != TCL_OK) {
958 code = ParseMultiplyExpr(infoPtr);
959 if (code != TCL_OK) {
964 * Generate tokens for the subexpression and '+' or '-' operator.
967 PrependSubExprTokens(operator, 1, srcStart,
968 (infoPtr->prevEnd - srcStart), firstIndex, infoPtr);
969 lexeme = infoPtr->lexeme;
975 *----------------------------------------------------------------------
977 * ParseMultiplyExpr --
979 * This procedure parses a Tcl multiply expression:
980 * multiplyExpr ::= unaryExpr {('*' | '/' | '%') unaryExpr}
983 * The return value is TCL_OK on a successful parse and TCL_ERROR
984 * on failure. If TCL_ERROR is returned, then the interpreter's result
985 * contains an error message.
988 * If there is insufficient space in parsePtr to hold all the
989 * information about the subexpression, then additional space is
992 *----------------------------------------------------------------------
996 ParseMultiplyExpr(infoPtr)
997 ParseInfo *infoPtr; /* Holds the parse state for the
998 * expression being parsed. */
1000 Tcl_Parse *parsePtr = infoPtr->parsePtr;
1001 int firstIndex, lexeme, code;
1002 CONST char *srcStart, *operator;
1004 HERE("multiplyExpr", 11);
1005 srcStart = infoPtr->start;
1006 firstIndex = parsePtr->numTokens;
1008 code = ParseUnaryExpr(infoPtr);
1009 if (code != TCL_OK) {
1013 lexeme = infoPtr->lexeme;
1014 while ((lexeme == MULT) || (lexeme == DIVIDE) || (lexeme == MOD)) {
1015 operator = infoPtr->start;
1016 code = GetLexeme(infoPtr); /* skip over * or / or % */
1017 if (code != TCL_OK) {
1020 code = ParseUnaryExpr(infoPtr);
1021 if (code != TCL_OK) {
1026 * Generate tokens for the subexpression and * or / or % operator.
1029 PrependSubExprTokens(operator, 1, srcStart,
1030 (infoPtr->prevEnd - srcStart), firstIndex, infoPtr);
1031 lexeme = infoPtr->lexeme;
1037 *----------------------------------------------------------------------
1041 * This procedure parses a Tcl unary expression:
1042 * unaryExpr ::= ('+' | '-' | '~' | '!') unaryExpr | primaryExpr
1045 * The return value is TCL_OK on a successful parse and TCL_ERROR
1046 * on failure. If TCL_ERROR is returned, then the interpreter's result
1047 * contains an error message.
1050 * If there is insufficient space in parsePtr to hold all the
1051 * information about the subexpression, then additional space is
1054 *----------------------------------------------------------------------
1058 ParseUnaryExpr(infoPtr)
1059 ParseInfo *infoPtr; /* Holds the parse state for the
1060 * expression being parsed. */
1062 Tcl_Parse *parsePtr = infoPtr->parsePtr;
1063 int firstIndex, lexeme, code;
1064 CONST char *srcStart, *operator;
1066 HERE("unaryExpr", 12);
1067 srcStart = infoPtr->start;
1068 firstIndex = parsePtr->numTokens;
1070 lexeme = infoPtr->lexeme;
1071 if ((lexeme == PLUS) || (lexeme == MINUS) || (lexeme == BIT_NOT)
1072 || (lexeme == NOT)) {
1073 operator = infoPtr->start;
1074 code = GetLexeme(infoPtr); /* skip over the unary operator */
1075 if (code != TCL_OK) {
1078 code = ParseUnaryExpr(infoPtr);
1079 if (code != TCL_OK) {
1084 * Generate tokens for the subexpression and the operator.
1087 PrependSubExprTokens(operator, 1, srcStart,
1088 (infoPtr->prevEnd - srcStart), firstIndex, infoPtr);
1089 } else { /* must be a primaryExpr */
1090 code = ParsePrimaryExpr(infoPtr);
1091 if (code != TCL_OK) {
1099 *----------------------------------------------------------------------
1101 * ParsePrimaryExpr --
1103 * This procedure parses a Tcl primary expression:
1104 * primaryExpr ::= literal | varReference | quotedString |
1105 * '[' command ']' | mathFuncCall | '(' condExpr ')'
1108 * The return value is TCL_OK on a successful parse and TCL_ERROR
1109 * on failure. If TCL_ERROR is returned, then the interpreter's result
1110 * contains an error message.
1113 * If there is insufficient space in parsePtr to hold all the
1114 * information about the subexpression, then additional space is
1117 *----------------------------------------------------------------------
1121 ParsePrimaryExpr(infoPtr)
1122 ParseInfo *infoPtr; /* Holds the parse state for the
1123 * expression being parsed. */
1125 Tcl_Parse *parsePtr = infoPtr->parsePtr;
1126 Tcl_Interp *interp = parsePtr->interp;
1127 Tcl_Token *tokenPtr, *exprTokenPtr;
1129 CONST char *dollarPtr, *stringStart, *termPtr, *src;
1130 int lexeme, exprIndex, firstIndex, numToMove, code;
1133 * We simply recurse on parenthesized subexpressions.
1136 HERE("primaryExpr", 13);
1137 lexeme = infoPtr->lexeme;
1138 if (lexeme == OPEN_PAREN) {
1139 code = GetLexeme(infoPtr); /* skip over the '(' */
1140 if (code != TCL_OK) {
1143 code = ParseCondExpr(infoPtr);
1144 if (code != TCL_OK) {
1147 if (infoPtr->lexeme != CLOSE_PAREN) {
1148 LogSyntaxError(infoPtr, "looking for close parenthesis");
1151 code = GetLexeme(infoPtr); /* skip over the ')' */
1152 if (code != TCL_OK) {
1159 * Start a TCL_TOKEN_SUB_EXPR token for the primary.
1162 if (parsePtr->numTokens == parsePtr->tokensAvailable) {
1163 TclExpandTokenArray(parsePtr);
1165 exprIndex = parsePtr->numTokens;
1166 exprTokenPtr = &parsePtr->tokenPtr[exprIndex];
1167 exprTokenPtr->type = TCL_TOKEN_SUB_EXPR;
1168 exprTokenPtr->start = infoPtr->start;
1169 parsePtr->numTokens++;
1172 * Process the primary then finish setting the fields of the
1173 * TCL_TOKEN_SUB_EXPR token. Note that we can't use the pointer now
1174 * stored in "exprTokenPtr" in the code below since the token array
1175 * might be reallocated.
1178 firstIndex = parsePtr->numTokens;
1182 * Int or double number.
1186 if (parsePtr->numTokens == parsePtr->tokensAvailable) {
1187 TclExpandTokenArray(parsePtr);
1189 tokenPtr = &parsePtr->tokenPtr[parsePtr->numTokens];
1190 tokenPtr->type = TCL_TOKEN_TEXT;
1191 tokenPtr->start = infoPtr->start;
1192 tokenPtr->size = infoPtr->size;
1193 tokenPtr->numComponents = 0;
1194 parsePtr->numTokens++;
1196 exprTokenPtr = &parsePtr->tokenPtr[exprIndex];
1197 exprTokenPtr->size = infoPtr->size;
1198 exprTokenPtr->numComponents = 1;
1203 * $var variable reference.
1206 dollarPtr = (infoPtr->next - 1);
1207 code = Tcl_ParseVarName(interp, dollarPtr,
1208 (infoPtr->lastChar - dollarPtr), parsePtr, 1);
1209 if (code != TCL_OK) {
1212 infoPtr->next = dollarPtr + parsePtr->tokenPtr[firstIndex].size;
1214 exprTokenPtr = &parsePtr->tokenPtr[exprIndex];
1215 exprTokenPtr->size = parsePtr->tokenPtr[firstIndex].size;
1216 exprTokenPtr->numComponents =
1217 (parsePtr->tokenPtr[firstIndex].numComponents + 1);
1225 stringStart = infoPtr->next;
1226 code = Tcl_ParseQuotedString(interp, infoPtr->start,
1227 (infoPtr->lastChar - stringStart), parsePtr, 1, &termPtr);
1228 if (code != TCL_OK) {
1231 infoPtr->next = termPtr;
1233 exprTokenPtr = &parsePtr->tokenPtr[exprIndex];
1234 exprTokenPtr->size = (termPtr - exprTokenPtr->start);
1235 exprTokenPtr->numComponents = parsePtr->numTokens - firstIndex;
1238 * If parsing the quoted string resulted in more than one token,
1239 * insert a TCL_TOKEN_WORD token before them. This indicates that
1240 * the quoted string represents a concatenation of multiple tokens.
1243 if (exprTokenPtr->numComponents > 1) {
1244 if (parsePtr->numTokens >= parsePtr->tokensAvailable) {
1245 TclExpandTokenArray(parsePtr);
1247 tokenPtr = &parsePtr->tokenPtr[firstIndex];
1248 numToMove = (parsePtr->numTokens - firstIndex);
1249 memmove((VOID *) (tokenPtr + 1), (VOID *) tokenPtr,
1250 (size_t) (numToMove * sizeof(Tcl_Token)));
1251 parsePtr->numTokens++;
1253 exprTokenPtr = &parsePtr->tokenPtr[exprIndex];
1254 exprTokenPtr->numComponents++;
1256 tokenPtr->type = TCL_TOKEN_WORD;
1257 tokenPtr->start = exprTokenPtr->start;
1258 tokenPtr->size = exprTokenPtr->size;
1259 tokenPtr->numComponents = (exprTokenPtr->numComponents - 1);
1265 * '[' command {command} ']'
1268 if (parsePtr->numTokens == parsePtr->tokensAvailable) {
1269 TclExpandTokenArray(parsePtr);
1271 tokenPtr = &parsePtr->tokenPtr[parsePtr->numTokens];
1272 tokenPtr->type = TCL_TOKEN_COMMAND;
1273 tokenPtr->start = infoPtr->start;
1274 tokenPtr->numComponents = 0;
1275 parsePtr->numTokens++;
1278 * Call Tcl_ParseCommand repeatedly to parse the nested command(s)
1279 * to find their end, then throw away that parse information.
1282 src = infoPtr->next;
1284 if (Tcl_ParseCommand(interp, src, (parsePtr->end - src), 1,
1285 &nested) != TCL_OK) {
1286 parsePtr->term = nested.term;
1287 parsePtr->errorType = nested.errorType;
1288 parsePtr->incomplete = nested.incomplete;
1291 src = (nested.commandStart + nested.commandSize);
1294 * This is equivalent to Tcl_FreeParse(&nested), but
1295 * presumably inlined here for sake of runtime optimization
1298 if (nested.tokenPtr != nested.staticTokens) {
1299 ckfree((char *) nested.tokenPtr);
1303 * Check for the closing ']' that ends the command substitution.
1304 * It must have been the last character of the parsed command.
1307 if ((nested.term < parsePtr->end) && (*nested.term == ']')
1308 && !nested.incomplete) {
1311 if (src == parsePtr->end) {
1312 if (parsePtr->interp != NULL) {
1313 Tcl_SetResult(interp, "missing close-bracket",
1316 parsePtr->term = tokenPtr->start;
1317 parsePtr->errorType = TCL_PARSE_MISSING_BRACKET;
1318 parsePtr->incomplete = 1;
1322 tokenPtr->size = (src - tokenPtr->start);
1323 infoPtr->next = src;
1325 exprTokenPtr = &parsePtr->tokenPtr[exprIndex];
1326 exprTokenPtr->size = (src - tokenPtr->start);
1327 exprTokenPtr->numComponents = 1;
1335 code = Tcl_ParseBraces(interp, infoPtr->start,
1336 (infoPtr->lastChar - infoPtr->start), parsePtr, 1,
1338 if (code != TCL_OK) {
1341 infoPtr->next = termPtr;
1343 exprTokenPtr = &parsePtr->tokenPtr[exprIndex];
1344 exprTokenPtr->size = (termPtr - infoPtr->start);
1345 exprTokenPtr->numComponents = parsePtr->numTokens - firstIndex;
1348 * If parsing the braced string resulted in more than one token,
1349 * insert a TCL_TOKEN_WORD token before them. This indicates that
1350 * the braced string represents a concatenation of multiple tokens.
1353 if (exprTokenPtr->numComponents > 1) {
1354 if (parsePtr->numTokens >= parsePtr->tokensAvailable) {
1355 TclExpandTokenArray(parsePtr);
1357 tokenPtr = &parsePtr->tokenPtr[firstIndex];
1358 numToMove = (parsePtr->numTokens - firstIndex);
1359 memmove((VOID *) (tokenPtr + 1), (VOID *) tokenPtr,
1360 (size_t) (numToMove * sizeof(Tcl_Token)));
1361 parsePtr->numTokens++;
1363 exprTokenPtr = &parsePtr->tokenPtr[exprIndex];
1364 exprTokenPtr->numComponents++;
1366 tokenPtr->type = TCL_TOKEN_WORD;
1367 tokenPtr->start = exprTokenPtr->start;
1368 tokenPtr->size = exprTokenPtr->size;
1369 tokenPtr->numComponents = exprTokenPtr->numComponents-1;
1377 * math_func '(' expr {',' expr} ')'
1380 ParseInfo savedInfo = *infoPtr;
1382 code = GetLexeme(infoPtr); /* skip over function name */
1383 if (code != TCL_OK) {
1386 if (infoPtr->lexeme != OPEN_PAREN) {
1388 Tcl_DString functionName;
1389 Tcl_HashEntry *hPtr;
1390 Interp *iPtr = (Interp *) infoPtr->parsePtr->interp;
1391 Tcl_Obj *objPtr = Tcl_NewStringObj(savedInfo.start, savedInfo.size);
1393 /* Check for boolean literals (true, false, yes, no, on, off) */
1394 Tcl_IncrRefCount(objPtr);
1395 code = Tcl_ConvertToType(NULL, objPtr, &tclBooleanType);
1396 Tcl_DecrRefCount(objPtr);
1397 if (code == TCL_OK) {
1398 *infoPtr = savedInfo;
1399 goto tokenizeLiteral;
1403 * Guess what kind of error we have by trying to tell
1404 * whether we have a function or variable name here.
1405 * Alas, this makes the parser more tightly bound with the
1406 * rest of the interpreter, but that is the only way to
1407 * give a sensible message here. Still, it is not too
1408 * serious as this is only done when generating an error.
1412 * Look up the name as a function name. We need a writable
1413 * copy (DString) so we can terminate it with a NULL for
1414 * the benefit of Tcl_FindHashEntry which operates on
1415 * NULL-terminated string keys.
1417 Tcl_DStringInit(&functionName);
1418 hPtr = Tcl_FindHashEntry(&iPtr->mathFuncTable,
1419 Tcl_DStringAppend(&functionName,
1420 savedInfo.start, savedInfo.size));
1421 Tcl_DStringFree(&functionName);
1424 * Assume that we have an attempted variable reference
1425 * unless we've got a function name, as the set of
1426 * potential function names is typically much smaller.
1429 LogSyntaxError(infoPtr,
1430 "expected parenthesis enclosing function arguments");
1432 LogSyntaxError(infoPtr,
1433 "variable references require preceding $");
1438 if (parsePtr->numTokens == parsePtr->tokensAvailable) {
1439 TclExpandTokenArray(parsePtr);
1441 tokenPtr = &parsePtr->tokenPtr[parsePtr->numTokens];
1442 tokenPtr->type = TCL_TOKEN_OPERATOR;
1443 tokenPtr->start = savedInfo.start;
1444 tokenPtr->size = savedInfo.size;
1445 tokenPtr->numComponents = 0;
1446 parsePtr->numTokens++;
1448 code = GetLexeme(infoPtr); /* skip over '(' */
1449 if (code != TCL_OK) {
1453 while (infoPtr->lexeme != CLOSE_PAREN) {
1454 code = ParseCondExpr(infoPtr);
1455 if (code != TCL_OK) {
1459 if (infoPtr->lexeme == COMMA) {
1460 code = GetLexeme(infoPtr); /* skip over , */
1461 if (code != TCL_OK) {
1464 } else if (infoPtr->lexeme != CLOSE_PAREN) {
1465 LogSyntaxError(infoPtr,
1466 "missing close parenthesis at end of function call");
1471 exprTokenPtr = &parsePtr->tokenPtr[exprIndex];
1472 exprTokenPtr->size = (infoPtr->next - exprTokenPtr->start);
1473 exprTokenPtr->numComponents = parsePtr->numTokens - firstIndex;
1478 LogSyntaxError(infoPtr,
1479 "commas can only separate function arguments");
1482 LogSyntaxError(infoPtr, "premature end of expression");
1485 LogSyntaxError(infoPtr, "single equality character not legal in expressions");
1488 LogSyntaxError(infoPtr, "character not legal in expressions");
1491 LogSyntaxError(infoPtr, "unexpected ternary 'then' separator");
1494 LogSyntaxError(infoPtr, "unexpected ternary 'else' separator");
1497 LogSyntaxError(infoPtr, "unexpected close parenthesis");
1503 sprintf(buf, "unexpected operator %s", lexemeStrings[lexeme]);
1504 LogSyntaxError(infoPtr, buf);
1510 * Advance to the next lexeme before returning.
1513 code = GetLexeme(infoPtr);
1514 if (code != TCL_OK) {
1517 parsePtr->term = infoPtr->next;
1522 *----------------------------------------------------------------------
1526 * Lexical scanner for Tcl expressions: scans a single operator or
1527 * other syntactic element from an expression string.
1530 * TCL_OK is returned unless an error occurred. In that case a standard
1531 * Tcl error code is returned and, if infoPtr->parsePtr->interp is
1532 * non-NULL, the interpreter's result is set to hold an error
1533 * message. TCL_ERROR is returned if an integer overflow, or a
1534 * floating-point overflow or underflow occurred while reading in a
1535 * number. If the lexical analysis is successful, infoPtr->lexeme
1536 * refers to the next symbol in the expression string, and
1537 * infoPtr->next is advanced past the lexeme. Also, if the lexeme is a
1538 * LITERAL or FUNC_NAME, then infoPtr->start is set to the first
1539 * character of the lexeme; otherwise it is set NULL.
1542 * If there is insufficient space in parsePtr to hold all the
1543 * information about the subexpression, then additional space is
1546 *----------------------------------------------------------------------
1551 ParseInfo *infoPtr; /* Holds state needed to parse the expr,
1552 * including the resulting lexeme. */
1554 register CONST char *src; /* Points to current source char. */
1556 int offset, length, numBytes;
1557 Tcl_Parse *parsePtr = infoPtr->parsePtr;
1558 Tcl_Interp *interp = parsePtr->interp;
1562 * Record where the previous lexeme ended. Since we always read one
1563 * lexeme ahead during parsing, this helps us know the source length of
1564 * subexpression tokens.
1567 infoPtr->prevEnd = infoPtr->next;
1570 * Scan over leading white space at the start of a lexeme.
1573 src = infoPtr->next;
1574 numBytes = parsePtr->end - src;
1577 int scanned = TclParseWhiteSpace(src, numBytes, parsePtr, &type);
1578 src += scanned; numBytes -= scanned;
1579 } while (numBytes && (*src == '\n') && (src++,numBytes--));
1580 parsePtr->term = src;
1581 if (numBytes == 0) {
1582 infoPtr->lexeme = END;
1583 infoPtr->next = src;
1588 * Try to parse the lexeme first as an integer or floating-point
1589 * number. Don't check for a number if the first character c is
1590 * "+" or "-". If we did, we might treat a binary operator as unary
1591 * by mistake, which would eventually cause a syntax error.
1595 if ((c != '+') && (c != '-')) {
1596 CONST char *end = infoPtr->lastChar;
1597 if ((length = TclParseInteger(src, (end - src)))) {
1599 * First length bytes look like an integer. Verify by
1600 * attempting the conversion to the largest integer we have.
1604 Tcl_Obj *value = Tcl_NewStringObj(src, length);
1606 Tcl_IncrRefCount(value);
1607 code = Tcl_GetWideIntFromObj(interp, value, &wide);
1608 Tcl_DecrRefCount(value);
1609 if (code == TCL_ERROR) {
1610 parsePtr->errorType = TCL_PARSE_BAD_NUMBER;
1613 infoPtr->lexeme = LITERAL;
1614 infoPtr->start = src;
1615 infoPtr->size = length;
1616 infoPtr->next = (src + length);
1617 parsePtr->term = infoPtr->next;
1619 } else if ((length = ParseMaxDoubleLength(src, end))) {
1621 * There are length characters that could be a double.
1622 * Let strtod() tells us for sure. Need a writable copy
1623 * so we can set an terminating NULL to keep strtod from
1626 char *startPtr, *termPtr;
1628 Tcl_DString toParse;
1631 Tcl_DStringInit(&toParse);
1632 startPtr = Tcl_DStringAppend(&toParse, src, length);
1633 doubleValue = strtod(startPtr, &termPtr);
1634 Tcl_DStringFree(&toParse);
1635 if (termPtr != startPtr) {
1637 if (interp != NULL) {
1638 TclExprFloatError(interp, doubleValue);
1640 parsePtr->errorType = TCL_PARSE_BAD_NUMBER;
1645 * startPtr was the start of a valid double, copied
1649 infoPtr->lexeme = LITERAL;
1650 infoPtr->start = src;
1651 if ((termPtr - startPtr) > length) {
1652 infoPtr->size = length;
1654 infoPtr->size = (termPtr - startPtr);
1656 infoPtr->next = src + infoPtr->size;
1657 parsePtr->term = infoPtr->next;
1664 * Not an integer or double literal. Initialize the lexeme's fields
1665 * assuming the common case of a single character lexeme.
1668 infoPtr->start = src;
1670 infoPtr->next = src+1;
1671 parsePtr->term = infoPtr->next;
1675 infoPtr->lexeme = OPEN_BRACKET;
1679 infoPtr->lexeme = OPEN_BRACE;
1683 infoPtr->lexeme = OPEN_PAREN;
1687 infoPtr->lexeme = CLOSE_PAREN;
1691 infoPtr->lexeme = DOLLAR;
1695 infoPtr->lexeme = QUOTE;
1699 infoPtr->lexeme = COMMA;
1703 infoPtr->lexeme = MULT;
1707 infoPtr->lexeme = DIVIDE;
1711 infoPtr->lexeme = MOD;
1715 infoPtr->lexeme = PLUS;
1719 infoPtr->lexeme = MINUS;
1723 infoPtr->lexeme = QUESTY;
1727 infoPtr->lexeme = COLON;
1731 infoPtr->lexeme = LESS;
1732 if ((infoPtr->lastChar - src) > 1) {
1735 infoPtr->lexeme = LEFT_SHIFT;
1737 infoPtr->next = src+2;
1740 infoPtr->lexeme = LEQ;
1742 infoPtr->next = src+2;
1746 parsePtr->term = infoPtr->next;
1750 infoPtr->lexeme = GREATER;
1751 if ((infoPtr->lastChar - src) > 1) {
1754 infoPtr->lexeme = RIGHT_SHIFT;
1756 infoPtr->next = src+2;
1759 infoPtr->lexeme = GEQ;
1761 infoPtr->next = src+2;
1765 parsePtr->term = infoPtr->next;
1769 infoPtr->lexeme = UNKNOWN;
1770 if ((src[1] == '=') && ((infoPtr->lastChar - src) > 1)) {
1771 infoPtr->lexeme = EQUAL;
1773 infoPtr->next = src+2;
1775 parsePtr->term = infoPtr->next;
1779 infoPtr->lexeme = NOT;
1780 if ((src[1] == '=') && ((infoPtr->lastChar - src) > 1)) {
1781 infoPtr->lexeme = NEQ;
1783 infoPtr->next = src+2;
1785 parsePtr->term = infoPtr->next;
1789 infoPtr->lexeme = BIT_AND;
1790 if ((src[1] == '&') && ((infoPtr->lastChar - src) > 1)) {
1791 infoPtr->lexeme = AND;
1793 infoPtr->next = src+2;
1795 parsePtr->term = infoPtr->next;
1799 infoPtr->lexeme = BIT_XOR;
1803 infoPtr->lexeme = BIT_OR;
1804 if ((src[1] == '|') && ((infoPtr->lastChar - src) > 1)) {
1805 infoPtr->lexeme = OR;
1807 infoPtr->next = src+2;
1809 parsePtr->term = infoPtr->next;
1813 infoPtr->lexeme = BIT_NOT;
1817 if ((src[1] == 'q') && ((infoPtr->lastChar - src) > 1)) {
1818 infoPtr->lexeme = STREQ;
1820 infoPtr->next = src+2;
1821 parsePtr->term = infoPtr->next;
1828 if ((src[1] == 'e') && ((infoPtr->lastChar - src) > 1)) {
1829 infoPtr->lexeme = STRNEQ;
1831 infoPtr->next = src+2;
1832 parsePtr->term = infoPtr->next;
1840 length = (infoPtr->lastChar - src);
1841 if (Tcl_UtfCharComplete(src, length)) {
1842 offset = Tcl_UtfToUniChar(src, &ch);
1844 char utfBytes[TCL_UTF_MAX];
1845 memcpy(utfBytes, src, (size_t) length);
1846 utfBytes[length] = '\0';
1847 offset = Tcl_UtfToUniChar(utfBytes, &ch);
1850 if (isalpha(UCHAR(c))) { /* INTL: ISO only. */
1851 infoPtr->lexeme = FUNC_NAME;
1852 while (isalnum(UCHAR(c)) || (c == '_')) { /* INTL: ISO only. */
1853 src += offset; length -= offset;
1854 if (Tcl_UtfCharComplete(src, length)) {
1855 offset = Tcl_UtfToUniChar(src, &ch);
1857 char utfBytes[TCL_UTF_MAX];
1858 memcpy(utfBytes, src, (size_t) length);
1859 utfBytes[length] = '\0';
1860 offset = Tcl_UtfToUniChar(utfBytes, &ch);
1864 infoPtr->size = (src - infoPtr->start);
1865 infoPtr->next = src;
1866 parsePtr->term = infoPtr->next;
1869 infoPtr->lexeme = UNKNOWN_CHAR;
1875 *----------------------------------------------------------------------
1877 * TclParseInteger --
1879 * Scans up to numBytes bytes starting at src, and checks whether
1880 * the leading bytes look like an integer's string representation.
1883 * Returns 0 if the leading bytes do not look like an integer.
1884 * Otherwise, returns the number of bytes examined that look
1885 * like an integer. This may be less than numBytes if the integer
1886 * is only the leading part of the string.
1891 *----------------------------------------------------------------------
1895 TclParseInteger(string, numBytes)
1896 register CONST char *string;/* The string to examine. */
1897 register int numBytes; /* Max number of bytes to scan. */
1899 register CONST char *p = string;
1901 /* Take care of introductory "0x" */
1902 if ((numBytes > 1) && (p[0] == '0') && ((p[1] == 'x') || (p[1] == 'X'))) {
1905 p+=2; numBytes -= 2;
1906 scanned = TclParseHex(p, numBytes, &ch);
1911 /* Recognize the 0 as valid integer, but x is left behind */
1914 while (numBytes && isdigit(UCHAR(*p))) { /* INTL: digit */
1917 if (numBytes == 0) {
1918 return (p - string);
1920 if ((*p != '.') && (*p != 'e') && (*p != 'E')) {
1921 return (p - string);
1927 *----------------------------------------------------------------------
1929 * ParseMaxDoubleLength --
1931 * Scans a sequence of bytes checking that the characters could
1932 * be in a string rep of a double.
1935 * Returns the number of bytes starting with string, runing to, but
1936 * not including end, all of which could be part of a string rep.
1937 * of a double. Only character identity is used, no actual
1940 * The legal bytes are '0' - '9', 'A' - 'F', 'a' - 'f',
1941 * '.', '+', '-', 'i', 'I', 'n', 'N', 'p', 'P', 'x', and 'X'.
1942 * This covers the values "Inf" and "Nan" as well as the
1943 * decimal and hexadecimal representations recognized by a
1944 * C99-compliant strtod().
1949 *----------------------------------------------------------------------
1953 ParseMaxDoubleLength(string, end)
1954 register CONST char *string;/* The string to examine. */
1955 CONST char *end; /* Point to the first character past the end
1956 * of the string we are examining. */
1958 CONST char *p = string;
1961 case '0': case '1': case '2': case '3': case '4': case '5':
1962 case '6': case '7': case '8': case '9': case 'A': case 'B':
1963 case 'C': case 'D': case 'E': case 'F': case 'I': case 'N':
1964 case 'P': case 'X': case 'a': case 'b': case 'c': case 'd':
1965 case 'e': case 'f': case 'i': case 'n': case 'p': case 'x':
1966 case '.': case '+': case '-':
1974 return (p - string);
1978 *----------------------------------------------------------------------
1980 * PrependSubExprTokens --
1982 * This procedure is called after the operands of an subexpression have
1983 * been parsed. It generates two tokens: a TCL_TOKEN_SUB_EXPR token for
1984 * the subexpression, and a TCL_TOKEN_OPERATOR token for its operator.
1985 * These two tokens are inserted before the operand tokens.
1991 * If there is insufficient space in parsePtr to hold the new tokens,
1992 * additional space is malloc-ed.
1994 *----------------------------------------------------------------------
1998 PrependSubExprTokens(op, opBytes, src, srcBytes, firstIndex, infoPtr)
1999 CONST char *op; /* Points to first byte of the operator
2000 * in the source script. */
2001 int opBytes; /* Number of bytes in the operator. */
2002 CONST char *src; /* Points to first byte of the subexpression
2003 * in the source script. */
2004 int srcBytes; /* Number of bytes in subexpression's
2006 int firstIndex; /* Index of first token already emitted for
2007 * operator's first (or only) operand. */
2008 ParseInfo *infoPtr; /* Holds the parse state for the
2009 * expression being parsed. */
2011 Tcl_Parse *parsePtr = infoPtr->parsePtr;
2012 Tcl_Token *tokenPtr, *firstTokenPtr;
2015 if ((parsePtr->numTokens + 1) >= parsePtr->tokensAvailable) {
2016 TclExpandTokenArray(parsePtr);
2018 firstTokenPtr = &parsePtr->tokenPtr[firstIndex];
2019 tokenPtr = (firstTokenPtr + 2);
2020 numToMove = (parsePtr->numTokens - firstIndex);
2021 memmove((VOID *) tokenPtr, (VOID *) firstTokenPtr,
2022 (size_t) (numToMove * sizeof(Tcl_Token)));
2023 parsePtr->numTokens += 2;
2025 tokenPtr = firstTokenPtr;
2026 tokenPtr->type = TCL_TOKEN_SUB_EXPR;
2027 tokenPtr->start = src;
2028 tokenPtr->size = srcBytes;
2029 tokenPtr->numComponents = parsePtr->numTokens - (firstIndex + 1);
2032 tokenPtr->type = TCL_TOKEN_OPERATOR;
2033 tokenPtr->start = op;
2034 tokenPtr->size = opBytes;
2035 tokenPtr->numComponents = 0;
2039 *----------------------------------------------------------------------
2043 * This procedure is invoked after an error occurs when parsing an
2044 * expression. It sets the interpreter result to an error message
2045 * describing the error.
2051 * Sets the interpreter result to an error message describing the
2052 * expression that was being parsed when the error occurred, and why
2053 * the parser considers that to be a syntax error at all.
2055 *----------------------------------------------------------------------
2059 LogSyntaxError(infoPtr, extraInfo)
2060 ParseInfo *infoPtr; /* Holds the parse state for the
2061 * expression being parsed. */
2062 CONST char *extraInfo; /* String to provide extra information
2063 * about the syntax error. */
2065 int numBytes = (infoPtr->lastChar - infoPtr->originalExpr);
2068 if (numBytes > 60) {
2069 sprintf(buffer, "syntax error in expression \"%.60s...\"",
2070 infoPtr->originalExpr);
2072 sprintf(buffer, "syntax error in expression \"%.*s\"",
2073 numBytes, infoPtr->originalExpr);
2075 Tcl_ResetResult(infoPtr->parsePtr->interp);
2076 Tcl_AppendStringsToObj(Tcl_GetObjResult(infoPtr->parsePtr->interp),
2077 buffer, ": ", extraInfo, (char *) NULL);
2078 infoPtr->parsePtr->errorType = TCL_PARSE_SYNTAX;
2079 infoPtr->parsePtr->term = infoPtr->start;