tclParseExpr.c
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:55k
源码类别:

通讯编程

开发平台:

Visual C++

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