/[dtapublic]/projs/trunk/shared_source/c_tcl_base_7_5_w_mods/tclparse.c
ViewVC logotype

Diff of /projs/trunk/shared_source/c_tcl_base_7_5_w_mods/tclparse.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 66 by dashley, Sun Oct 30 21:57:38 2016 UTC revision 71 by dashley, Sat Nov 5 11:07:06 2016 UTC
# Line 1  Line 1 
1  /* $Header$ */  /* $Header$ */
2  /*  /*
3   * tclParse.c --   * tclParse.c --
4   *   *
5   *      This file contains procedures that parse Tcl scripts.  They   *      This file contains procedures that parse Tcl scripts.  They
6   *      do so in a general-purpose fashion that can be used for many   *      do so in a general-purpose fashion that can be used for many
7   *      different purposes, including compilation, direct execution,   *      different purposes, including compilation, direct execution,
8   *      code analysis, etc.  This file also includes a few additional   *      code analysis, etc.  This file also includes a few additional
9   *      procedures such as Tcl_EvalObjv, Tcl_Eval, and Tcl_EvalEx, which   *      procedures such as Tcl_EvalObjv, Tcl_Eval, and Tcl_EvalEx, which
10   *      allow scripts to be evaluated directly, without compiling.   *      allow scripts to be evaluated directly, without compiling.
11   *   *
12   * Copyright (c) 1997 Sun Microsystems, Inc.   * Copyright (c) 1997 Sun Microsystems, Inc.
13   * Copyright (c) 1998 by Scriptics Corporation.   * Copyright (c) 1998 by Scriptics Corporation.
14   *   *
15   * See the file "license.terms" for information on usage and redistribution   * See the file "license.terms" for information on usage and redistribution
16   * of this file, and for a DISCLAIMER OF ALL WARRANTIES.   * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
17   *   *
18   * RCS: @(#) $Id: tclparse.c,v 1.1.1.1 2001/06/13 04:44:26 dtashley Exp $   * RCS: @(#) $Id: tclparse.c,v 1.1.1.1 2001/06/13 04:44:26 dtashley Exp $
19   */   */
20    
21  #include "tclInt.h"  #include "tclInt.h"
22  #include "tclPort.h"  #include "tclPort.h"
23    
24  /*  /*
25   * The following table provides parsing information about each possible   * The following table provides parsing information about each possible
26   * 8-bit character.  The table is designed to be referenced with either   * 8-bit character.  The table is designed to be referenced with either
27   * signed or unsigned characters, so it has 384 entries.  The first 128   * signed or unsigned characters, so it has 384 entries.  The first 128
28   * entries correspond to negative character values, the next 256 correspond   * entries correspond to negative character values, the next 256 correspond
29   * to positive character values.  The last 128 entries are identical to the   * to positive character values.  The last 128 entries are identical to the
30   * first 128.  The table is always indexed with a 128-byte offset (the 128th   * first 128.  The table is always indexed with a 128-byte offset (the 128th
31   * entry corresponds to a character value of 0).   * entry corresponds to a character value of 0).
32   *   *
33   * The macro CHAR_TYPE is used to index into the table and return   * The macro CHAR_TYPE is used to index into the table and return
34   * information about its character argument.  The following return   * information about its character argument.  The following return
35   * values are defined.   * values are defined.
36   *   *
37   * TYPE_NORMAL -        All characters that don't have special significance   * TYPE_NORMAL -        All characters that don't have special significance
38   *                      to the Tcl parser.   *                      to the Tcl parser.
39   * TYPE_SPACE -         The character is a whitespace character other   * TYPE_SPACE -         The character is a whitespace character other
40   *                      than newline.   *                      than newline.
41   * TYPE_COMMAND_END -   Character is newline or semicolon.   * TYPE_COMMAND_END -   Character is newline or semicolon.
42   * TYPE_SUBS -          Character begins a substitution or has other   * TYPE_SUBS -          Character begins a substitution or has other
43   *                      special meaning in ParseTokens: backslash, dollar   *                      special meaning in ParseTokens: backslash, dollar
44   *                      sign, open bracket, or null.   *                      sign, open bracket, or null.
45   * TYPE_QUOTE -         Character is a double quote.   * TYPE_QUOTE -         Character is a double quote.
46   * TYPE_CLOSE_PAREN -   Character is a right parenthesis.   * TYPE_CLOSE_PAREN -   Character is a right parenthesis.
47   * TYPE_CLOSE_BRACK -   Character is a right square bracket.   * TYPE_CLOSE_BRACK -   Character is a right square bracket.
48   * TYPE_BRACE -         Character is a curly brace (either left or right).   * TYPE_BRACE -         Character is a curly brace (either left or right).
49   */   */
50    
51  #define TYPE_NORMAL             0  #define TYPE_NORMAL             0
52  #define TYPE_SPACE              0x1  #define TYPE_SPACE              0x1
53  #define TYPE_COMMAND_END        0x2  #define TYPE_COMMAND_END        0x2
54  #define TYPE_SUBS               0x4  #define TYPE_SUBS               0x4
55  #define TYPE_QUOTE              0x8  #define TYPE_QUOTE              0x8
56  #define TYPE_CLOSE_PAREN        0x10  #define TYPE_CLOSE_PAREN        0x10
57  #define TYPE_CLOSE_BRACK        0x20  #define TYPE_CLOSE_BRACK        0x20
58  #define TYPE_BRACE              0x40  #define TYPE_BRACE              0x40
59    
60  #define CHAR_TYPE(c) (typeTable+128)[(int)(c)]  #define CHAR_TYPE(c) (typeTable+128)[(int)(c)]
61    
62  char typeTable[] = {  char typeTable[] = {
63      /*      /*
64       * Negative character values, from -128 to -1:       * Negative character values, from -128 to -1:
65       */       */
66    
67      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
68      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
69      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
70      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
71      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
72      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
73      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
74      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
75      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
76      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
77      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
78      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
79      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
80      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
81      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
82      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
83      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
84      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
85      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
86      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
87      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
88      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
89      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
90      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
91      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
92      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
93      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
94      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
95      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
96      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
97      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
98      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
99    
100      /*      /*
101       * Positive character values, from 0-127:       * Positive character values, from 0-127:
102       */       */
103    
104      TYPE_SUBS,        TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_SUBS,        TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
105      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
106      TYPE_NORMAL,      TYPE_SPACE,       TYPE_COMMAND_END, TYPE_SPACE,      TYPE_NORMAL,      TYPE_SPACE,       TYPE_COMMAND_END, TYPE_SPACE,
107      TYPE_SPACE,       TYPE_SPACE,       TYPE_NORMAL,      TYPE_NORMAL,      TYPE_SPACE,       TYPE_SPACE,       TYPE_NORMAL,      TYPE_NORMAL,
108      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
109      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
110      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
111      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
112      TYPE_SPACE,       TYPE_NORMAL,      TYPE_QUOTE,       TYPE_NORMAL,      TYPE_SPACE,       TYPE_NORMAL,      TYPE_QUOTE,       TYPE_NORMAL,
113      TYPE_SUBS,        TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_SUBS,        TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
114      TYPE_NORMAL,      TYPE_CLOSE_PAREN, TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_CLOSE_PAREN, TYPE_NORMAL,      TYPE_NORMAL,
115      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
116      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
117      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
118      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_COMMAND_END,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_COMMAND_END,
119      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
120      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
121      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
122      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
123      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
124      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
125      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
126      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_SUBS,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_SUBS,
127      TYPE_SUBS,        TYPE_CLOSE_BRACK, TYPE_NORMAL,      TYPE_NORMAL,      TYPE_SUBS,        TYPE_CLOSE_BRACK, TYPE_NORMAL,      TYPE_NORMAL,
128      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
129      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
130      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
131      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
132      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
133      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
134      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_BRACE,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_BRACE,
135      TYPE_NORMAL,      TYPE_BRACE,       TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_BRACE,       TYPE_NORMAL,      TYPE_NORMAL,
136    
137      /*      /*
138       * Large unsigned character values, from 128-255:       * Large unsigned character values, from 128-255:
139       */       */
140    
141      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
142      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
143      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
144      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
145      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
146      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
147      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
148      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
149      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
150      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
151      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
152      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
153      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
154      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
155      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
156      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
157      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
158      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
159      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
160      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
161      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
162      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
163      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
164      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
165      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
166      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
167      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
168      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
169      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
170      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
171      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
172      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,      TYPE_NORMAL,
173  };  };
174    
175  /*  /*
176   * Prototypes for local procedures defined in this file:   * Prototypes for local procedures defined in this file:
177   */   */
178    
179  static int              CommandComplete _ANSI_ARGS_((char *script,  static int              CommandComplete _ANSI_ARGS_((char *script,
180                              int length));                              int length));
181  static int              ParseTokens _ANSI_ARGS_((char *src, int mask,  static int              ParseTokens _ANSI_ARGS_((char *src, int mask,
182                              Tcl_Parse *parsePtr));                              Tcl_Parse *parsePtr));
183  static int              EvalObjv _ANSI_ARGS_((Tcl_Interp *interp, int objc,  static int              EvalObjv _ANSI_ARGS_((Tcl_Interp *interp, int objc,
184                              Tcl_Obj *CONST objv[], char *command, int length,                              Tcl_Obj *CONST objv[], char *command, int length,
185                              int flags));                              int flags));
186    
187  /*  /*
188   *----------------------------------------------------------------------   *----------------------------------------------------------------------
189   *   *
190   * Tcl_ParseCommand --   * Tcl_ParseCommand --
191   *   *
192   *      Given a string, this procedure parses the first Tcl command   *      Given a string, this procedure parses the first Tcl command
193   *      in the string and returns information about the structure of   *      in the string and returns information about the structure of
194   *      the command.   *      the command.
195   *   *
196   * Results:   * Results:
197   *      The return value is TCL_OK if the command was parsed   *      The return value is TCL_OK if the command was parsed
198   *      successfully and TCL_ERROR otherwise.  If an error occurs   *      successfully and TCL_ERROR otherwise.  If an error occurs
199   *      and interp isn't NULL then an error message is left in   *      and interp isn't NULL then an error message is left in
200   *      its result.  On a successful return, parsePtr is filled in   *      its result.  On a successful return, parsePtr is filled in
201   *      with information about the command that was parsed.   *      with information about the command that was parsed.
202   *   *
203   * Side effects:   * Side effects:
204   *      If there is insufficient space in parsePtr to hold all the   *      If there is insufficient space in parsePtr to hold all the
205   *      information about the command, then additional space is   *      information about the command, then additional space is
206   *      malloc-ed.  If the procedure returns TCL_OK then the caller must   *      malloc-ed.  If the procedure returns TCL_OK then the caller must
207   *      eventually invoke Tcl_FreeParse to release any additional space   *      eventually invoke Tcl_FreeParse to release any additional space
208   *      that was allocated.   *      that was allocated.
209   *   *
210   *----------------------------------------------------------------------   *----------------------------------------------------------------------
211   */   */
212    
213  int  int
214  Tcl_ParseCommand(interp, string, numBytes, nested, parsePtr)  Tcl_ParseCommand(interp, string, numBytes, nested, parsePtr)
215      Tcl_Interp *interp;         /* Interpreter to use for error reporting;      Tcl_Interp *interp;         /* Interpreter to use for error reporting;
216                                   * if NULL, then no error message is                                   * if NULL, then no error message is
217                                   * provided. */                                   * provided. */
218      char *string;               /* First character of string containing      char *string;               /* First character of string containing
219                                   * one or more Tcl commands.  The string                                   * one or more Tcl commands.  The string
220                                   * must be in writable memory and must                                   * must be in writable memory and must
221                                   * have one additional byte of space at                                   * have one additional byte of space at
222                                   * string[length] where we can                                   * string[length] where we can
223                                   * temporarily store a 0 sentinel                                   * temporarily store a 0 sentinel
224                                   * character. */                                   * character. */
225      int numBytes;               /* Total number of bytes in string.  If < 0,      int numBytes;               /* Total number of bytes in string.  If < 0,
226                                   * the script consists of all bytes up to                                   * the script consists of all bytes up to
227                                   * the first null character. */                                   * the first null character. */
228      int nested;                 /* Non-zero means this is a nested command:      int nested;                 /* Non-zero means this is a nested command:
229                                   * close bracket should be considered                                   * close bracket should be considered
230                                   * a command terminator. If zero, then close                                   * a command terminator. If zero, then close
231                                   * bracket has no special meaning. */                                   * bracket has no special meaning. */
232      register Tcl_Parse *parsePtr;      register Tcl_Parse *parsePtr;
233                                  /* Structure to fill in with information                                  /* Structure to fill in with information
234                                   * about the parsed command; any previous                                   * about the parsed command; any previous
235                                   * information in the structure is                                   * information in the structure is
236                                   * ignored. */                                   * ignored. */
237  {  {
238      register char *src;         /* Points to current character      register char *src;         /* Points to current character
239                                   * in the command. */                                   * in the command. */
240      int type;                   /* Result returned by CHAR_TYPE(*src). */      int type;                   /* Result returned by CHAR_TYPE(*src). */
241      Tcl_Token *tokenPtr;        /* Pointer to token being filled in. */      Tcl_Token *tokenPtr;        /* Pointer to token being filled in. */
242      int wordIndex;              /* Index of word token for current word. */      int wordIndex;              /* Index of word token for current word. */
243      char utfBytes[TCL_UTF_MAX]; /* Holds result of backslash substitution. */      char utfBytes[TCL_UTF_MAX]; /* Holds result of backslash substitution. */
244      int terminators;            /* CHAR_TYPE bits that indicate the end      int terminators;            /* CHAR_TYPE bits that indicate the end
245                                   * of a command. */                                   * of a command. */
246      char *termPtr;              /* Set by Tcl_ParseBraces/QuotedString to      char *termPtr;              /* Set by Tcl_ParseBraces/QuotedString to
247                                   * point to char after terminating one. */                                   * point to char after terminating one. */
248      int length, savedChar;      int length, savedChar;
249    
250    
251      if (numBytes < 0) {      if (numBytes < 0) {
252          numBytes = (string? strlen(string) : 0);          numBytes = (string? strlen(string) : 0);
253      }      }
254      parsePtr->commentStart = NULL;      parsePtr->commentStart = NULL;
255      parsePtr->commentSize = 0;      parsePtr->commentSize = 0;
256      parsePtr->commandStart = NULL;      parsePtr->commandStart = NULL;
257      parsePtr->commandSize = 0;      parsePtr->commandSize = 0;
258      parsePtr->numWords = 0;      parsePtr->numWords = 0;
259      parsePtr->tokenPtr = parsePtr->staticTokens;      parsePtr->tokenPtr = parsePtr->staticTokens;
260      parsePtr->numTokens = 0;      parsePtr->numTokens = 0;
261      parsePtr->tokensAvailable = NUM_STATIC_TOKENS;      parsePtr->tokensAvailable = NUM_STATIC_TOKENS;
262      parsePtr->string = string;      parsePtr->string = string;
263      parsePtr->end = string + numBytes;      parsePtr->end = string + numBytes;
264      parsePtr->term = parsePtr->end;      parsePtr->term = parsePtr->end;
265      parsePtr->interp = interp;      parsePtr->interp = interp;
266      parsePtr->incomplete = 0;      parsePtr->incomplete = 0;
267      parsePtr->errorType = TCL_PARSE_SUCCESS;      parsePtr->errorType = TCL_PARSE_SUCCESS;
268      if (nested != 0) {      if (nested != 0) {
269          terminators = TYPE_COMMAND_END | TYPE_CLOSE_BRACK;          terminators = TYPE_COMMAND_END | TYPE_CLOSE_BRACK;
270      } else {      } else {
271          terminators = TYPE_COMMAND_END;          terminators = TYPE_COMMAND_END;
272      }      }
273    
274      /*      /*
275       * Temporarily overwrite the character just after the end of the       * Temporarily overwrite the character just after the end of the
276       * string with a 0 byte.  This acts as a sentinel and reduces the       * string with a 0 byte.  This acts as a sentinel and reduces the
277       * number of places where we have to check for the end of the       * number of places where we have to check for the end of the
278       * input string.  The original value of the byte is restored at       * input string.  The original value of the byte is restored at
279       * the end of the parse.       * the end of the parse.
280       */       */
281    
282      savedChar = string[numBytes];      savedChar = string[numBytes];
283      if (savedChar != 0) {      if (savedChar != 0) {
284          string[numBytes] = 0;          string[numBytes] = 0;
285      }      }
286    
287      /*      /*
288       * Parse any leading space and comments before the first word of the       * Parse any leading space and comments before the first word of the
289       * command.       * command.
290       */       */
291    
292      src = string;      src = string;
293      while (1) {      while (1) {
294          while ((CHAR_TYPE(*src) == TYPE_SPACE) || (*src == '\n')) {          while ((CHAR_TYPE(*src) == TYPE_SPACE) || (*src == '\n')) {
295              src++;              src++;
296          }          }
297          if ((*src == '\\') && (src[1] == '\n')) {          if ((*src == '\\') && (src[1] == '\n')) {
298              /*              /*
299               * Skip backslash-newline sequence: it should be treated               * Skip backslash-newline sequence: it should be treated
300               * just like white space.               * just like white space.
301               */               */
302    
303              if ((src + 2) == parsePtr->end) {              if ((src + 2) == parsePtr->end) {
304                  parsePtr->incomplete = 1;                  parsePtr->incomplete = 1;
305              }              }
306              src += 2;              src += 2;
307              continue;              continue;
308          }          }
309          if (*src != '#') {          if (*src != '#') {
310              break;              break;
311          }          }
312          if (parsePtr->commentStart == NULL) {          if (parsePtr->commentStart == NULL) {
313              parsePtr->commentStart = src;              parsePtr->commentStart = src;
314          }          }
315          while (1) {          while (1) {
316              if (src == parsePtr->end) {              if (src == parsePtr->end) {
317                  if (nested) {                  if (nested) {
318                      parsePtr->incomplete = nested;                      parsePtr->incomplete = nested;
319                  }                  }
320                  parsePtr->commentSize = src - parsePtr->commentStart;                  parsePtr->commentSize = src - parsePtr->commentStart;
321                  break;                  break;
322              } else if (*src == '\\') {              } else if (*src == '\\') {
323                  if ((src[1] == '\n') && ((src + 2) == parsePtr->end)) {                  if ((src[1] == '\n') && ((src + 2) == parsePtr->end)) {
324                      parsePtr->incomplete = 1;                      parsePtr->incomplete = 1;
325                  }                  }
326                  Tcl_UtfBackslash(src, &length, utfBytes);                  Tcl_UtfBackslash(src, &length, utfBytes);
327                  src += length;                  src += length;
328              } else if (*src == '\n') {              } else if (*src == '\n') {
329                  src++;                  src++;
330                  parsePtr->commentSize = src - parsePtr->commentStart;                  parsePtr->commentSize = src - parsePtr->commentStart;
331                  break;                  break;
332              } else {              } else {
333                  src++;                  src++;
334              }              }
335          }          }
336      }      }
337    
338      /*      /*
339       * The following loop parses the words of the command, one word       * The following loop parses the words of the command, one word
340       * in each iteration through the loop.       * in each iteration through the loop.
341       */       */
342    
343      parsePtr->commandStart = src;      parsePtr->commandStart = src;
344      while (1) {      while (1) {
345          /*          /*
346           * Create the token for the word.           * Create the token for the word.
347           */           */
348    
349          if (parsePtr->numTokens == parsePtr->tokensAvailable) {          if (parsePtr->numTokens == parsePtr->tokensAvailable) {
350              TclExpandTokenArray(parsePtr);              TclExpandTokenArray(parsePtr);
351          }          }
352          wordIndex = parsePtr->numTokens;          wordIndex = parsePtr->numTokens;
353          tokenPtr = &parsePtr->tokenPtr[wordIndex];          tokenPtr = &parsePtr->tokenPtr[wordIndex];
354          tokenPtr->type = TCL_TOKEN_WORD;          tokenPtr->type = TCL_TOKEN_WORD;
355    
356          /*          /*
357           * Skip white space before the word. Also skip a backslash-newline           * Skip white space before the word. Also skip a backslash-newline
358           * sequence: it should be treated just like white space.           * sequence: it should be treated just like white space.
359           */           */
360    
361          while (1) {          while (1) {
362              type = CHAR_TYPE(*src);              type = CHAR_TYPE(*src);
363              if (type == TYPE_SPACE) {              if (type == TYPE_SPACE) {
364                  src++;                  src++;
365                  continue;                  continue;
366              } else if ((*src == '\\') && (src[1] == '\n')) {              } else if ((*src == '\\') && (src[1] == '\n')) {
367                  if ((src + 2) == parsePtr->end) {                  if ((src + 2) == parsePtr->end) {
368                      parsePtr->incomplete = 1;                      parsePtr->incomplete = 1;
369                  }                  }
370                  Tcl_UtfBackslash(src, &length, utfBytes);                  Tcl_UtfBackslash(src, &length, utfBytes);
371                  src += length;                  src += length;
372                  continue;                  continue;
373              }              }
374              break;              break;
375          }          }
376          if ((type & terminators) != 0) {          if ((type & terminators) != 0) {
377              parsePtr->term = src;              parsePtr->term = src;
378              src++;              src++;
379              break;              break;
380          }          }
381          if (src == parsePtr->end) {          if (src == parsePtr->end) {
382              break;              break;
383          }          }
384          tokenPtr->start = src;          tokenPtr->start = src;
385          parsePtr->numTokens++;          parsePtr->numTokens++;
386          parsePtr->numWords++;          parsePtr->numWords++;
387    
388          /*          /*
389           * At this point the word can have one of three forms: something           * At this point the word can have one of three forms: something
390           * enclosed in quotes, something enclosed in braces, or an           * enclosed in quotes, something enclosed in braces, or an
391           * unquoted word (anything else).           * unquoted word (anything else).
392           */           */
393    
394          if (*src == '"') {          if (*src == '"') {
395              if (Tcl_ParseQuotedString(interp, src, (parsePtr->end - src),              if (Tcl_ParseQuotedString(interp, src, (parsePtr->end - src),
396                      parsePtr, 1, &termPtr) != TCL_OK) {                      parsePtr, 1, &termPtr) != TCL_OK) {
397                  goto error;                  goto error;
398              }              }
399              src = termPtr;              src = termPtr;
400          } else if (*src == '{') {          } else if (*src == '{') {
401              if (Tcl_ParseBraces(interp, src, (parsePtr->end - src),              if (Tcl_ParseBraces(interp, src, (parsePtr->end - src),
402                      parsePtr, 1, &termPtr) != TCL_OK) {                      parsePtr, 1, &termPtr) != TCL_OK) {
403                  goto error;                  goto error;
404              }              }
405              src = termPtr;              src = termPtr;
406          } else {          } else {
407              /*              /*
408               * This is an unquoted word.  Call ParseTokens and let it do               * This is an unquoted word.  Call ParseTokens and let it do
409               * all of the work.               * all of the work.
410               */               */
411    
412              if (ParseTokens(src, TYPE_SPACE|terminators,              if (ParseTokens(src, TYPE_SPACE|terminators,
413                      parsePtr) != TCL_OK) {                      parsePtr) != TCL_OK) {
414                  goto error;                  goto error;
415              }              }
416              src = parsePtr->term;              src = parsePtr->term;
417          }          }
418    
419          /*          /*
420           * Finish filling in the token for the word and check for the           * Finish filling in the token for the word and check for the
421           * special case of a word consisting of a single range of           * special case of a word consisting of a single range of
422           * literal text.           * literal text.
423           */           */
424    
425          tokenPtr = &parsePtr->tokenPtr[wordIndex];          tokenPtr = &parsePtr->tokenPtr[wordIndex];
426          tokenPtr->size = src - tokenPtr->start;          tokenPtr->size = src - tokenPtr->start;
427          tokenPtr->numComponents = parsePtr->numTokens - (wordIndex + 1);          tokenPtr->numComponents = parsePtr->numTokens - (wordIndex + 1);
428          if ((tokenPtr->numComponents == 1)          if ((tokenPtr->numComponents == 1)
429                  && (tokenPtr[1].type == TCL_TOKEN_TEXT)) {                  && (tokenPtr[1].type == TCL_TOKEN_TEXT)) {
430              tokenPtr->type = TCL_TOKEN_SIMPLE_WORD;              tokenPtr->type = TCL_TOKEN_SIMPLE_WORD;
431          }          }
432    
433          /*          /*
434           * Do two additional checks: (a) make sure we're really at the           * Do two additional checks: (a) make sure we're really at the
435           * end of a word (there might have been garbage left after a           * end of a word (there might have been garbage left after a
436           * quoted or braced word), and (b) check for the end of the           * quoted or braced word), and (b) check for the end of the
437           * command.           * command.
438           */           */
439    
440          type = CHAR_TYPE(*src);          type = CHAR_TYPE(*src);
441          if (type == TYPE_SPACE) {          if (type == TYPE_SPACE) {
442              src++;              src++;
443              continue;              continue;
444          } else {          } else {
445              /*              /*
446               * Backslash-newline (and any following white space) must be               * Backslash-newline (and any following white space) must be
447               * treated as if it were a space character.               * treated as if it were a space character.
448               */               */
449    
450              if ((*src == '\\') && (src[1] == '\n')) {              if ((*src == '\\') && (src[1] == '\n')) {
451                  if ((src + 2) == parsePtr->end) {                  if ((src + 2) == parsePtr->end) {
452                      parsePtr->incomplete = 1;                      parsePtr->incomplete = 1;
453                  }                  }
454                  Tcl_UtfBackslash(src, &length, utfBytes);                  Tcl_UtfBackslash(src, &length, utfBytes);
455                  src += length;                  src += length;
456                  continue;                  continue;
457              }              }
458          }          }
459    
460          if ((type & terminators) != 0) {          if ((type & terminators) != 0) {
461              parsePtr->term = src;              parsePtr->term = src;
462              src++;              src++;
463              break;              break;
464          }          }
465          if (src == parsePtr->end) {          if (src == parsePtr->end) {
466              break;              break;
467          }          }
468          if (src[-1] == '"') {          if (src[-1] == '"') {
469              if (interp != NULL) {              if (interp != NULL) {
470                  Tcl_SetResult(interp, "extra characters after close-quote",                  Tcl_SetResult(interp, "extra characters after close-quote",
471                          TCL_STATIC);                          TCL_STATIC);
472              }              }
473              parsePtr->errorType = TCL_PARSE_QUOTE_EXTRA;              parsePtr->errorType = TCL_PARSE_QUOTE_EXTRA;
474          } else {          } else {
475              if (interp != NULL) {              if (interp != NULL) {
476                  Tcl_SetResult(interp, "extra characters after close-brace",                  Tcl_SetResult(interp, "extra characters after close-brace",
477                          TCL_STATIC);                          TCL_STATIC);
478              }              }
479              parsePtr->errorType = TCL_PARSE_BRACE_EXTRA;              parsePtr->errorType = TCL_PARSE_BRACE_EXTRA;
480          }          }
481          parsePtr->term = src;          parsePtr->term = src;
482          goto error;          goto error;
483      }      }
484    
485    
486      parsePtr->commandSize = src - parsePtr->commandStart;      parsePtr->commandSize = src - parsePtr->commandStart;
487      if (savedChar != 0) {      if (savedChar != 0) {
488          string[numBytes] = (char) savedChar;          string[numBytes] = (char) savedChar;
489      }      }
490      return TCL_OK;      return TCL_OK;
491    
492      error:      error:
493      if (savedChar != 0) {      if (savedChar != 0) {
494          string[numBytes] = (char) savedChar;          string[numBytes] = (char) savedChar;
495      }      }
496      Tcl_FreeParse(parsePtr);      Tcl_FreeParse(parsePtr);
497      if (parsePtr->commandStart == NULL) {      if (parsePtr->commandStart == NULL) {
498          parsePtr->commandStart = string;          parsePtr->commandStart = string;
499      }      }
500      parsePtr->commandSize = parsePtr->term - parsePtr->commandStart;      parsePtr->commandSize = parsePtr->term - parsePtr->commandStart;
501      return TCL_ERROR;      return TCL_ERROR;
502  }  }
503    
504  /*  /*
505   *----------------------------------------------------------------------   *----------------------------------------------------------------------
506   *   *
507   * ParseTokens --   * ParseTokens --
508   *   *
509   *      This procedure forms the heart of the Tcl parser.  It parses one   *      This procedure forms the heart of the Tcl parser.  It parses one
510   *      or more tokens from a string, up to a termination point   *      or more tokens from a string, up to a termination point
511   *      specified by the caller.  This procedure is used to parse   *      specified by the caller.  This procedure is used to parse
512   *      unquoted command words (those not in quotes or braces), words in   *      unquoted command words (those not in quotes or braces), words in
513   *      quotes, and array indices for variables.   *      quotes, and array indices for variables.
514   *   *
515   * Results:   * Results:
516   *      Tokens are added to parsePtr and parsePtr->term is filled in   *      Tokens are added to parsePtr and parsePtr->term is filled in
517   *      with the address of the character that terminated the parse (the   *      with the address of the character that terminated the parse (the
518   *      first one whose CHAR_TYPE matched mask or the character at   *      first one whose CHAR_TYPE matched mask or the character at
519   *      parsePtr->end).  The return value is TCL_OK if the parse   *      parsePtr->end).  The return value is TCL_OK if the parse
520   *      completed successfully and TCL_ERROR otherwise.  If a parse   *      completed successfully and TCL_ERROR otherwise.  If a parse
521   *      error occurs and parsePtr->interp isn't NULL, then an error   *      error occurs and parsePtr->interp isn't NULL, then an error
522   *      message is left in the interpreter's result.   *      message is left in the interpreter's result.
523   *   *
524   * Side effects:   * Side effects:
525   *      None.   *      None.
526   *   *
527   *----------------------------------------------------------------------   *----------------------------------------------------------------------
528   */   */
529    
530  static int  static int
531  ParseTokens(src, mask, parsePtr)  ParseTokens(src, mask, parsePtr)
532      register char *src;         /* First character to parse. */      register char *src;         /* First character to parse. */
533      int mask;                   /* Specifies when to stop parsing.  The      int mask;                   /* Specifies when to stop parsing.  The
534                                   * parse stops at the first unquoted                                   * parse stops at the first unquoted
535                                   * character whose CHAR_TYPE contains                                   * character whose CHAR_TYPE contains
536                                   * any of the bits in mask. */                                   * any of the bits in mask. */
537      Tcl_Parse *parsePtr;        /* Information about parse in progress.      Tcl_Parse *parsePtr;        /* Information about parse in progress.
538                                   * Updated with additional tokens and                                   * Updated with additional tokens and
539                                   * termination information. */                                   * termination information. */
540  {  {
541      int type, originalTokens, varToken;      int type, originalTokens, varToken;
542      char utfBytes[TCL_UTF_MAX];      char utfBytes[TCL_UTF_MAX];
543      Tcl_Token *tokenPtr;      Tcl_Token *tokenPtr;
544      Tcl_Parse nested;      Tcl_Parse nested;
545    
546      /*      /*
547       * Each iteration through the following loop adds one token of       * Each iteration through the following loop adds one token of
548       * type TCL_TOKEN_TEXT, TCL_TOKEN_BS, TCL_TOKEN_COMMAND, or       * type TCL_TOKEN_TEXT, TCL_TOKEN_BS, TCL_TOKEN_COMMAND, or
549       * TCL_TOKEN_VARIABLE to parsePtr.  For TCL_TOKEN_VARIABLE tokens,       * TCL_TOKEN_VARIABLE to parsePtr.  For TCL_TOKEN_VARIABLE tokens,
550       * additional tokens are added for the parsed variable name.       * additional tokens are added for the parsed variable name.
551       */       */
552    
553      originalTokens = parsePtr->numTokens;      originalTokens = parsePtr->numTokens;
554      while (1) {      while (1) {
555          if (parsePtr->numTokens == parsePtr->tokensAvailable) {          if (parsePtr->numTokens == parsePtr->tokensAvailable) {
556              TclExpandTokenArray(parsePtr);              TclExpandTokenArray(parsePtr);
557          }          }
558          tokenPtr = &parsePtr->tokenPtr[parsePtr->numTokens];          tokenPtr = &parsePtr->tokenPtr[parsePtr->numTokens];
559          tokenPtr->start = src;          tokenPtr->start = src;
560          tokenPtr->numComponents = 0;          tokenPtr->numComponents = 0;
561    
562          type = CHAR_TYPE(*src);          type = CHAR_TYPE(*src);
563          if (type & mask) {          if (type & mask) {
564              break;              break;
565          }          }
566    
567          if ((type & TYPE_SUBS) == 0) {          if ((type & TYPE_SUBS) == 0) {
568              /*              /*
569               * This is a simple range of characters.  Scan to find the end               * This is a simple range of characters.  Scan to find the end
570               * of the range.               * of the range.
571               */               */
572    
573              while (1) {              while (1) {
574                  src++;                  src++;
575                  if (CHAR_TYPE(*src) & (mask | TYPE_SUBS)) {                  if (CHAR_TYPE(*src) & (mask | TYPE_SUBS)) {
576                      break;                      break;
577                  }                  }
578              }              }
579              tokenPtr->type = TCL_TOKEN_TEXT;              tokenPtr->type = TCL_TOKEN_TEXT;
580              tokenPtr->size = src - tokenPtr->start;              tokenPtr->size = src - tokenPtr->start;
581              parsePtr->numTokens++;              parsePtr->numTokens++;
582          } else if (*src == '$') {          } else if (*src == '$') {
583              /*              /*
584               * This is a variable reference.  Call Tcl_ParseVarName to do               * This is a variable reference.  Call Tcl_ParseVarName to do
585               * all the dirty work of parsing the name.               * all the dirty work of parsing the name.
586               */               */
587    
588              varToken = parsePtr->numTokens;              varToken = parsePtr->numTokens;
589              if (Tcl_ParseVarName(parsePtr->interp, src, parsePtr->end - src,              if (Tcl_ParseVarName(parsePtr->interp, src, parsePtr->end - src,
590                      parsePtr, 1) != TCL_OK) {                      parsePtr, 1) != TCL_OK) {
591                  return TCL_ERROR;                  return TCL_ERROR;
592              }              }
593              src += parsePtr->tokenPtr[varToken].size;              src += parsePtr->tokenPtr[varToken].size;
594          } else if (*src == '[') {          } else if (*src == '[') {
595              /*              /*
596               * Command substitution.  Call Tcl_ParseCommand recursively               * Command substitution.  Call Tcl_ParseCommand recursively
597               * (and repeatedly) to parse the nested command(s), then               * (and repeatedly) to parse the nested command(s), then
598               * throw away the parse information.               * throw away the parse information.
599               */               */
600    
601              src++;              src++;
602              while (1) {              while (1) {
603                  if (Tcl_ParseCommand(parsePtr->interp, src,                  if (Tcl_ParseCommand(parsePtr->interp, src,
604                          parsePtr->end - src, 1, &nested) != TCL_OK) {                          parsePtr->end - src, 1, &nested) != TCL_OK) {
605                      parsePtr->errorType = nested.errorType;                      parsePtr->errorType = nested.errorType;
606                      parsePtr->term = nested.term;                      parsePtr->term = nested.term;
607                      parsePtr->incomplete = nested.incomplete;                      parsePtr->incomplete = nested.incomplete;
608                      return TCL_ERROR;                      return TCL_ERROR;
609                  }                  }
610                  src = nested.commandStart + nested.commandSize;                  src = nested.commandStart + nested.commandSize;
611                  if (nested.tokenPtr != nested.staticTokens) {                  if (nested.tokenPtr != nested.staticTokens) {
612                      ckfree((char *) nested.tokenPtr);                      ckfree((char *) nested.tokenPtr);
613                  }                  }
614                  if ((*nested.term == ']') && !nested.incomplete) {                  if ((*nested.term == ']') && !nested.incomplete) {
615                      break;                      break;
616                  }                  }
617                  if (src == parsePtr->end) {                  if (src == parsePtr->end) {
618                      if (parsePtr->interp != NULL) {                      if (parsePtr->interp != NULL) {
619                          Tcl_SetResult(parsePtr->interp,                          Tcl_SetResult(parsePtr->interp,
620                              "missing close-bracket", TCL_STATIC);                              "missing close-bracket", TCL_STATIC);
621                      }                      }
622                      parsePtr->errorType = TCL_PARSE_MISSING_BRACKET;                      parsePtr->errorType = TCL_PARSE_MISSING_BRACKET;
623                      parsePtr->term = tokenPtr->start;                      parsePtr->term = tokenPtr->start;
624                      parsePtr->incomplete = 1;                      parsePtr->incomplete = 1;
625                      return TCL_ERROR;                      return TCL_ERROR;
626                  }                  }
627              }              }
628              tokenPtr->type = TCL_TOKEN_COMMAND;              tokenPtr->type = TCL_TOKEN_COMMAND;
629              tokenPtr->size = src - tokenPtr->start;              tokenPtr->size = src - tokenPtr->start;
630              parsePtr->numTokens++;              parsePtr->numTokens++;
631          } else if (*src == '\\') {          } else if (*src == '\\') {
632              /*              /*
633               * Backslash substitution.               * Backslash substitution.
634               */               */
635    
636              if (src[1] == '\n') {              if (src[1] == '\n') {
637                  if ((src + 2) == parsePtr->end) {                  if ((src + 2) == parsePtr->end) {
638                      parsePtr->incomplete = 1;                      parsePtr->incomplete = 1;
639                  }                  }
640    
641                  /*                  /*
642                   * Note: backslash-newline is special in that it is                   * Note: backslash-newline is special in that it is
643                   * treated the same as a space character would be.  This                   * treated the same as a space character would be.  This
644                   * means that it could terminate the token.                   * means that it could terminate the token.
645                   */                   */
646    
647                  if (mask & TYPE_SPACE) {                  if (mask & TYPE_SPACE) {
648                      break;                      break;
649                  }                  }
650              }              }
651              tokenPtr->type = TCL_TOKEN_BS;              tokenPtr->type = TCL_TOKEN_BS;
652              Tcl_UtfBackslash(src, &tokenPtr->size, utfBytes);              Tcl_UtfBackslash(src, &tokenPtr->size, utfBytes);
653              parsePtr->numTokens++;              parsePtr->numTokens++;
654              src += tokenPtr->size;              src += tokenPtr->size;
655          } else if (*src == 0) {          } else if (*src == 0) {
656              /*              /*
657               * We encountered a null character.  If it is the null               * We encountered a null character.  If it is the null
658               * character at the end of the string, then return.               * character at the end of the string, then return.
659               * Otherwise generate a text token for the single               * Otherwise generate a text token for the single
660               * character.               * character.
661               */               */
662    
663              if (src == parsePtr->end) {              if (src == parsePtr->end) {
664                  break;                  break;
665              }              }
666              tokenPtr->type = TCL_TOKEN_TEXT;              tokenPtr->type = TCL_TOKEN_TEXT;
667              tokenPtr->size = 1;              tokenPtr->size = 1;
668              parsePtr->numTokens++;              parsePtr->numTokens++;
669              src++;              src++;
670          } else {          } else {
671              panic("ParseTokens encountered unknown character");              panic("ParseTokens encountered unknown character");
672          }          }
673      }      }
674      if (parsePtr->numTokens == originalTokens) {      if (parsePtr->numTokens == originalTokens) {
675          /*          /*
676           * There was nothing in this range of text.  Add an empty token           * There was nothing in this range of text.  Add an empty token
677           * for the empty range, so that there is always at least one           * for the empty range, so that there is always at least one
678           * token added.           * token added.
679           */           */
680    
681          tokenPtr->type = TCL_TOKEN_TEXT;          tokenPtr->type = TCL_TOKEN_TEXT;
682          tokenPtr->size = 0;          tokenPtr->size = 0;
683          parsePtr->numTokens++;          parsePtr->numTokens++;
684      }      }
685      parsePtr->term = src;      parsePtr->term = src;
686      return TCL_OK;      return TCL_OK;
687  }  }
688    
689  /*  /*
690   *----------------------------------------------------------------------   *----------------------------------------------------------------------
691   *   *
692   * Tcl_FreeParse --   * Tcl_FreeParse --
693   *   *
694   *      This procedure is invoked to free any dynamic storage that may   *      This procedure is invoked to free any dynamic storage that may
695   *      have been allocated by a previous call to Tcl_ParseCommand.   *      have been allocated by a previous call to Tcl_ParseCommand.
696   *   *
697   * Results:   * Results:
698   *      None.   *      None.
699   *   *
700   * Side effects:   * Side effects:
701   *      If there is any dynamically allocated memory in *parsePtr,   *      If there is any dynamically allocated memory in *parsePtr,
702   *      it is freed.   *      it is freed.
703   *   *
704   *----------------------------------------------------------------------   *----------------------------------------------------------------------
705   */   */
706    
707  void  void
708  Tcl_FreeParse(parsePtr)  Tcl_FreeParse(parsePtr)
709      Tcl_Parse *parsePtr;        /* Structure that was filled in by a      Tcl_Parse *parsePtr;        /* Structure that was filled in by a
710                                   * previous call to Tcl_ParseCommand. */                                   * previous call to Tcl_ParseCommand. */
711  {  {
712      if (parsePtr->tokenPtr != parsePtr->staticTokens) {      if (parsePtr->tokenPtr != parsePtr->staticTokens) {
713          ckfree((char *) parsePtr->tokenPtr);          ckfree((char *) parsePtr->tokenPtr);
714          parsePtr->tokenPtr = parsePtr->staticTokens;          parsePtr->tokenPtr = parsePtr->staticTokens;
715      }      }
716  }  }
717    
718  /*  /*
719   *----------------------------------------------------------------------   *----------------------------------------------------------------------
720   *   *
721   * TclExpandTokenArray --   * TclExpandTokenArray --
722   *   *
723   *      This procedure is invoked when the current space for tokens in   *      This procedure is invoked when the current space for tokens in
724   *      a Tcl_Parse structure fills up; it allocates memory to grow the   *      a Tcl_Parse structure fills up; it allocates memory to grow the
725   *      token array   *      token array
726   *   *
727   * Results:   * Results:
728   *      None.   *      None.
729   *   *
730   * Side effects:   * Side effects:
731   *      Memory is allocated for a new larger token array; the memory   *      Memory is allocated for a new larger token array; the memory
732   *      for the old array is freed, if it had been dynamically allocated.   *      for the old array is freed, if it had been dynamically allocated.
733   *   *
734   *----------------------------------------------------------------------   *----------------------------------------------------------------------
735   */   */
736    
737  void  void
738  TclExpandTokenArray(parsePtr)  TclExpandTokenArray(parsePtr)
739      Tcl_Parse *parsePtr;        /* Parse structure whose token space      Tcl_Parse *parsePtr;        /* Parse structure whose token space
740                                   * has overflowed. */                                   * has overflowed. */
741  {  {
742      int newCount;      int newCount;
743      Tcl_Token *newPtr;      Tcl_Token *newPtr;
744    
745      newCount = parsePtr->tokensAvailable*2;      newCount = parsePtr->tokensAvailable*2;
746      newPtr = (Tcl_Token *) ckalloc((unsigned) (newCount * sizeof(Tcl_Token)));      newPtr = (Tcl_Token *) ckalloc((unsigned) (newCount * sizeof(Tcl_Token)));
747      memcpy((VOID *) newPtr, (VOID *) parsePtr->tokenPtr,      memcpy((VOID *) newPtr, (VOID *) parsePtr->tokenPtr,
748              (size_t) (parsePtr->tokensAvailable * sizeof(Tcl_Token)));              (size_t) (parsePtr->tokensAvailable * sizeof(Tcl_Token)));
749      if (parsePtr->tokenPtr != parsePtr->staticTokens) {      if (parsePtr->tokenPtr != parsePtr->staticTokens) {
750          ckfree((char *) parsePtr->tokenPtr);          ckfree((char *) parsePtr->tokenPtr);
751      }      }
752      parsePtr->tokenPtr = newPtr;      parsePtr->tokenPtr = newPtr;
753      parsePtr->tokensAvailable = newCount;      parsePtr->tokensAvailable = newCount;
754  }  }
755    
756  /*  /*
757   *----------------------------------------------------------------------   *----------------------------------------------------------------------
758   *   *
759   * EvalObjv --   * EvalObjv --
760   *   *
761   *      This procedure evaluates a Tcl command that has already been   *      This procedure evaluates a Tcl command that has already been
762   *      parsed into words, with one Tcl_Obj holding each word.   *      parsed into words, with one Tcl_Obj holding each word.
763   *   *
764   * Results:   * Results:
765   *      The return value is a standard Tcl completion code such as   *      The return value is a standard Tcl completion code such as
766   *      TCL_OK or TCL_ERROR.  A result or error message is left in   *      TCL_OK or TCL_ERROR.  A result or error message is left in
767   *      interp's result.  If an error occurs, this procedure does   *      interp's result.  If an error occurs, this procedure does
768   *      NOT add any information to the errorInfo variable.   *      NOT add any information to the errorInfo variable.
769   *   *
770   * Side effects:   * Side effects:
771   *      Depends on the command.   *      Depends on the command.
772   *   *
773   *----------------------------------------------------------------------   *----------------------------------------------------------------------
774   */   */
775    
776  static int  static int
777  EvalObjv(interp, objc, objv, command, length, flags)  EvalObjv(interp, objc, objv, command, length, flags)
778      Tcl_Interp *interp;         /* Interpreter in which to evaluate the      Tcl_Interp *interp;         /* Interpreter in which to evaluate the
779                                   * command.  Also used for error                                   * command.  Also used for error
780                                   * reporting. */                                   * reporting. */
781      int objc;                   /* Number of words in command. */      int objc;                   /* Number of words in command. */
782      Tcl_Obj *CONST objv[];      /* An array of pointers to objects that are      Tcl_Obj *CONST objv[];      /* An array of pointers to objects that are
783                                   * the words that make up the command. */                                   * the words that make up the command. */
784      char *command;              /* Points to the beginning of the string      char *command;              /* Points to the beginning of the string
785                                   * representation of the command; this                                   * representation of the command; this
786                                   * is used for traces.  If the string                                   * is used for traces.  If the string
787                                   * representation of the command is                                   * representation of the command is
788                                   * unknown, an empty string should be                                   * unknown, an empty string should be
789                                   * supplied. */                                   * supplied. */
790      int length;                 /* Number of bytes in command; if -1, all      int length;                 /* Number of bytes in command; if -1, all
791                                   * characters up to the first null byte are                                   * characters up to the first null byte are
792                                   * used. */                                   * used. */
793      int flags;                  /* Collection of OR-ed bits that control      int flags;                  /* Collection of OR-ed bits that control
794                                   * the evaluation of the script.  Only                                   * the evaluation of the script.  Only
795                                   * TCL_EVAL_GLOBAL is currently                                   * TCL_EVAL_GLOBAL is currently
796                                   * supported. */                                   * supported. */
797    
798  {  {
799      Command *cmdPtr;      Command *cmdPtr;
800      Interp *iPtr = (Interp *) interp;      Interp *iPtr = (Interp *) interp;
801      Tcl_Obj **newObjv;      Tcl_Obj **newObjv;
802      int i, code;      int i, code;
803      Trace *tracePtr, *nextPtr;      Trace *tracePtr, *nextPtr;
804      char **argv, *commandCopy;      char **argv, *commandCopy;
805      CallFrame *savedVarFramePtr;        /* Saves old copy of iPtr->varFramePtr      CallFrame *savedVarFramePtr;        /* Saves old copy of iPtr->varFramePtr
806                                           * in case TCL_EVAL_GLOBAL was set. */                                           * in case TCL_EVAL_GLOBAL was set. */
807    
808      Tcl_ResetResult(interp);      Tcl_ResetResult(interp);
809      if (objc == 0) {      if (objc == 0) {
810          return TCL_OK;          return TCL_OK;
811      }      }
812    
813      /*      /*
814       * If the interpreter was deleted, return an error.       * If the interpreter was deleted, return an error.
815       */       */
816            
817      if (iPtr->flags & DELETED) {      if (iPtr->flags & DELETED) {
818          Tcl_AppendToObj(Tcl_GetObjResult(interp),          Tcl_AppendToObj(Tcl_GetObjResult(interp),
819                  "attempt to call eval in deleted interpreter", -1);                  "attempt to call eval in deleted interpreter", -1);
820          Tcl_SetErrorCode(interp, "CORE", "IDELETE",          Tcl_SetErrorCode(interp, "CORE", "IDELETE",
821                  "attempt to call eval in deleted interpreter",                  "attempt to call eval in deleted interpreter",
822                  (char *) NULL);                  (char *) NULL);
823          return TCL_ERROR;          return TCL_ERROR;
824      }      }
825    
826      /*      /*
827       * Check depth of nested calls to Tcl_Eval:  if this gets too large,       * Check depth of nested calls to Tcl_Eval:  if this gets too large,
828       * it's probably because of an infinite loop somewhere.       * it's probably because of an infinite loop somewhere.
829       */       */
830    
831      if (iPtr->numLevels >= iPtr->maxNestingDepth) {      if (iPtr->numLevels >= iPtr->maxNestingDepth) {
832          iPtr->result =  "too many nested calls to Tcl_Eval (infinite loop?)";          iPtr->result =  "too many nested calls to Tcl_Eval (infinite loop?)";
833          return TCL_ERROR;          return TCL_ERROR;
834      }      }
835      iPtr->numLevels++;      iPtr->numLevels++;
836    
837      /*      /*
838       * On the Mac, we will never reach the default recursion limit before       * On the Mac, we will never reach the default recursion limit before
839       * blowing the stack. So we need to do a check here.       * blowing the stack. So we need to do a check here.
840       */       */
841            
842      if (TclpCheckStackSpace() == 0) {      if (TclpCheckStackSpace() == 0) {
843          /*NOTREACHED*/          /*NOTREACHED*/
844          iPtr->numLevels--;          iPtr->numLevels--;
845          iPtr->result =  "too many nested calls to Tcl_Eval (infinite loop?)";          iPtr->result =  "too many nested calls to Tcl_Eval (infinite loop?)";
846          return TCL_ERROR;          return TCL_ERROR;
847      }      }
848            
849      /*      /*
850       * Find the procedure to execute this command. If there isn't one,       * Find the procedure to execute this command. If there isn't one,
851       * then see if there is a command "unknown".  If so, create a new       * then see if there is a command "unknown".  If so, create a new
852       * word array with "unknown" as the first word and the original       * word array with "unknown" as the first word and the original
853       * command words as arguments.  Then call ourselves recursively       * command words as arguments.  Then call ourselves recursively
854       * to execute it.       * to execute it.
855       */       */
856            
857      cmdPtr = (Command *) Tcl_GetCommandFromObj(interp, objv[0]);      cmdPtr = (Command *) Tcl_GetCommandFromObj(interp, objv[0]);
858      if (cmdPtr == NULL) {      if (cmdPtr == NULL) {
859          newObjv = (Tcl_Obj **) ckalloc((unsigned)          newObjv = (Tcl_Obj **) ckalloc((unsigned)
860                  ((objc + 1) * sizeof (Tcl_Obj *)));                  ((objc + 1) * sizeof (Tcl_Obj *)));
861          for (i = objc-1; i >= 0; i--) {          for (i = objc-1; i >= 0; i--) {
862              newObjv[i+1] = objv[i];              newObjv[i+1] = objv[i];
863          }          }
864          newObjv[0] = Tcl_NewStringObj("unknown", -1);          newObjv[0] = Tcl_NewStringObj("unknown", -1);
865          Tcl_IncrRefCount(newObjv[0]);          Tcl_IncrRefCount(newObjv[0]);
866          cmdPtr = (Command *) Tcl_GetCommandFromObj(interp, newObjv[0]);          cmdPtr = (Command *) Tcl_GetCommandFromObj(interp, newObjv[0]);
867          if (cmdPtr == NULL) {          if (cmdPtr == NULL) {
868              Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),              Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
869                      "invalid command name \"", Tcl_GetString(objv[0]), "\"",                      "invalid command name \"", Tcl_GetString(objv[0]), "\"",
870                      (char *) NULL);                      (char *) NULL);
871              code = TCL_ERROR;              code = TCL_ERROR;
872          } else {          } else {
873              code = EvalObjv(interp, objc+1, newObjv, command, length, 0);              code = EvalObjv(interp, objc+1, newObjv, command, length, 0);
874          }          }
875          Tcl_DecrRefCount(newObjv[0]);          Tcl_DecrRefCount(newObjv[0]);
876          ckfree((char *) newObjv);          ckfree((char *) newObjv);
877          goto done;          goto done;
878      }      }
879            
880      /*      /*
881       * Call trace procedures if needed.       * Call trace procedures if needed.
882       */       */
883    
884      argv = NULL;      argv = NULL;
885      commandCopy = command;      commandCopy = command;
886    
887      for (tracePtr = iPtr->tracePtr; tracePtr != NULL; tracePtr = nextPtr) {      for (tracePtr = iPtr->tracePtr; tracePtr != NULL; tracePtr = nextPtr) {
888          nextPtr = tracePtr->nextPtr;          nextPtr = tracePtr->nextPtr;
889          if (iPtr->numLevels > tracePtr->level) {          if (iPtr->numLevels > tracePtr->level) {
890              continue;              continue;
891          }          }
892    
893          /*          /*
894           * This is a bit messy because we have to emulate the old trace           * This is a bit messy because we have to emulate the old trace
895           * interface, which uses strings for everything.           * interface, which uses strings for everything.
896           */           */
897    
898          if (argv == NULL) {          if (argv == NULL) {
899              argv = (char **) ckalloc((unsigned) (objc + 1) * sizeof(char *));              argv = (char **) ckalloc((unsigned) (objc + 1) * sizeof(char *));
900              for (i = 0; i < objc; i++) {              for (i = 0; i < objc; i++) {
901                  argv[i] = Tcl_GetString(objv[i]);                  argv[i] = Tcl_GetString(objv[i]);
902              }              }
903              argv[objc] = 0;              argv[objc] = 0;
904    
905              if (length < 0) {              if (length < 0) {
906                  length = strlen(command);                  length = strlen(command);
907              } else if ((size_t)length < strlen(command)) {              } else if ((size_t)length < strlen(command)) {
908                  commandCopy = (char *) ckalloc((unsigned) (length + 1));                  commandCopy = (char *) ckalloc((unsigned) (length + 1));
909                  strncpy(commandCopy, command, (size_t) length);                  strncpy(commandCopy, command, (size_t) length);
910                  commandCopy[length] = 0;                  commandCopy[length] = 0;
911              }              }
912          }          }
913          (*tracePtr->proc)(tracePtr->clientData, interp, iPtr->numLevels,          (*tracePtr->proc)(tracePtr->clientData, interp, iPtr->numLevels,
914                            commandCopy, cmdPtr->proc, cmdPtr->clientData,                            commandCopy, cmdPtr->proc, cmdPtr->clientData,
915                            objc, argv);                            objc, argv);
916      }      }
917      if (argv != NULL) {      if (argv != NULL) {
918          ckfree((char *) argv);          ckfree((char *) argv);
919      }      }
920      if (commandCopy != command) {      if (commandCopy != command) {
921          ckfree((char *) commandCopy);          ckfree((char *) commandCopy);
922      }      }
923            
924      /*      /*
925       * Finally, invoke the command's Tcl_ObjCmdProc.       * Finally, invoke the command's Tcl_ObjCmdProc.
926       */       */
927            
928      iPtr->cmdCount++;      iPtr->cmdCount++;
929      savedVarFramePtr = iPtr->varFramePtr;      savedVarFramePtr = iPtr->varFramePtr;
930      if (flags & TCL_EVAL_GLOBAL) {      if (flags & TCL_EVAL_GLOBAL) {
931          iPtr->varFramePtr = NULL;          iPtr->varFramePtr = NULL;
932      }      }
933      code = (*cmdPtr->objProc)(cmdPtr->objClientData, interp, objc, objv);      code = (*cmdPtr->objProc)(cmdPtr->objClientData, interp, objc, objv);
934      iPtr->varFramePtr = savedVarFramePtr;      iPtr->varFramePtr = savedVarFramePtr;
935      if (Tcl_AsyncReady()) {      if (Tcl_AsyncReady()) {
936          code = Tcl_AsyncInvoke(interp, code);          code = Tcl_AsyncInvoke(interp, code);
937      }      }
938    
939      /*      /*
940       * If the interpreter has a non-empty string result, the result       * If the interpreter has a non-empty string result, the result
941       * object is either empty or stale because some procedure set       * object is either empty or stale because some procedure set
942       * interp->result directly. If so, move the string result to the       * interp->result directly. If so, move the string result to the
943       * result object, then reset the string result.       * result object, then reset the string result.
944       */       */
945            
946      if (*(iPtr->result) != 0) {      if (*(iPtr->result) != 0) {
947          (void) Tcl_GetObjResult(interp);          (void) Tcl_GetObjResult(interp);
948      }      }
949    
950      done:      done:
951      iPtr->numLevels--;      iPtr->numLevels--;
952      return code;      return code;
953  }  }
954    
955  /*  /*
956   *----------------------------------------------------------------------   *----------------------------------------------------------------------
957   *   *
958   * Tcl_EvalObjv --   * Tcl_EvalObjv --
959   *   *
960   *      This procedure evaluates a Tcl command that has already been   *      This procedure evaluates a Tcl command that has already been
961   *      parsed into words, with one Tcl_Obj holding each word.   *      parsed into words, with one Tcl_Obj holding each word.
962   *   *
963   * Results:   * Results:
964   *      The return value is a standard Tcl completion code such as   *      The return value is a standard Tcl completion code such as
965   *      TCL_OK or TCL_ERROR.  A result or error message is left in   *      TCL_OK or TCL_ERROR.  A result or error message is left in
966   *      interp's result.   *      interp's result.
967   *   *
968   * Side effects:   * Side effects:
969   *      Depends on the command.   *      Depends on the command.
970   *   *
971   *----------------------------------------------------------------------   *----------------------------------------------------------------------
972   */   */
973    
974  int  int
975  Tcl_EvalObjv(interp, objc, objv, flags)  Tcl_EvalObjv(interp, objc, objv, flags)
976      Tcl_Interp *interp;         /* Interpreter in which to evaluate the      Tcl_Interp *interp;         /* Interpreter in which to evaluate the
977                                   * command.  Also used for error                                   * command.  Also used for error
978                                   * reporting. */                                   * reporting. */
979      int objc;                   /* Number of words in command. */      int objc;                   /* Number of words in command. */
980      Tcl_Obj *CONST objv[];      /* An array of pointers to objects that are      Tcl_Obj *CONST objv[];      /* An array of pointers to objects that are
981                                   * the words that make up the command. */                                   * the words that make up the command. */
982      int flags;                  /* Collection of OR-ed bits that control      int flags;                  /* Collection of OR-ed bits that control
983                                   * the evaluation of the script.  Only                                   * the evaluation of the script.  Only
984                                   * TCL_EVAL_GLOBAL is currently                                   * TCL_EVAL_GLOBAL is currently
985                                   * supported. */                                   * supported. */
986  {  {
987      Interp *iPtr = (Interp *)interp;      Interp *iPtr = (Interp *)interp;
988      Trace *tracePtr;      Trace *tracePtr;
989      Tcl_DString cmdBuf;      Tcl_DString cmdBuf;
990      char *cmdString = "";      char *cmdString = "";
991      int cmdLen = 0;      int cmdLen = 0;
992      int code = TCL_OK;      int code = TCL_OK;
993    
994      for (tracePtr = iPtr->tracePtr; tracePtr; tracePtr = tracePtr->nextPtr) {      for (tracePtr = iPtr->tracePtr; tracePtr; tracePtr = tracePtr->nextPtr) {
995          /*          /*
996           * EvalObjv will increment numLevels so use "<" rather than "<="           * EvalObjv will increment numLevels so use "<" rather than "<="
997           */           */
998          if (iPtr->numLevels < tracePtr->level) {          if (iPtr->numLevels < tracePtr->level) {
999              int i;              int i;
1000              /*              /*
1001               * The command will be needed for an execution trace or stack trace               * The command will be needed for an execution trace or stack trace
1002               * generate a command string.               * generate a command string.
1003               */               */
1004          cmdtraced:          cmdtraced:
1005              Tcl_DStringInit(&cmdBuf);              Tcl_DStringInit(&cmdBuf);
1006              for (i = 0; i < objc; i++) {              for (i = 0; i < objc; i++) {
1007                  Tcl_DStringAppendElement(&cmdBuf, Tcl_GetString(objv[i]));                  Tcl_DStringAppendElement(&cmdBuf, Tcl_GetString(objv[i]));
1008              }              }
1009              cmdString = Tcl_DStringValue(&cmdBuf);              cmdString = Tcl_DStringValue(&cmdBuf);
1010              cmdLen = Tcl_DStringLength(&cmdBuf);              cmdLen = Tcl_DStringLength(&cmdBuf);
1011              break;              break;
1012          }          }
1013      }      }
1014    
1015      /*      /*
1016       * Execute the command if we have not done so already       * Execute the command if we have not done so already
1017       */       */
1018      switch (code) {      switch (code) {
1019          case TCL_OK:          case TCL_OK:
1020              code = EvalObjv(interp, objc, objv, cmdString, cmdLen, flags);              code = EvalObjv(interp, objc, objv, cmdString, cmdLen, flags);
1021              if (code == TCL_ERROR && cmdLen == 0)              if (code == TCL_ERROR && cmdLen == 0)
1022                  goto cmdtraced;                  goto cmdtraced;
1023              break;              break;
1024          case TCL_ERROR:          case TCL_ERROR:
1025              Tcl_LogCommandInfo(interp, cmdString, cmdString, cmdLen);              Tcl_LogCommandInfo(interp, cmdString, cmdString, cmdLen);
1026              break;              break;
1027          default:          default:
1028              /*NOTREACHED*/              /*NOTREACHED*/
1029              break;              break;
1030      }      }
1031    
1032      if (cmdLen != 0) {      if (cmdLen != 0) {
1033          Tcl_DStringFree(&cmdBuf);          Tcl_DStringFree(&cmdBuf);
1034      }      }
1035      return code;      return code;
1036  }  }
1037    
1038  /*  /*
1039   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1040   *   *
1041   * Tcl_LogCommandInfo --   * Tcl_LogCommandInfo --
1042   *   *
1043   *      This procedure is invoked after an error occurs in an interpreter.   *      This procedure is invoked after an error occurs in an interpreter.
1044   *      It adds information to the "errorInfo" variable to describe the   *      It adds information to the "errorInfo" variable to describe the
1045   *      command that was being executed when the error occurred.   *      command that was being executed when the error occurred.
1046   *   *
1047   * Results:   * Results:
1048   *      None.   *      None.
1049   *   *
1050   * Side effects:   * Side effects:
1051   *      Information about the command is added to errorInfo and the   *      Information about the command is added to errorInfo and the
1052   *      line number stored internally in the interpreter is set.  If this   *      line number stored internally in the interpreter is set.  If this
1053   *      is the first call to this procedure or Tcl_AddObjErrorInfo since   *      is the first call to this procedure or Tcl_AddObjErrorInfo since
1054   *      an error occurred, then old information in errorInfo is   *      an error occurred, then old information in errorInfo is
1055   *      deleted.   *      deleted.
1056   *   *
1057   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1058   */   */
1059    
1060  void  void
1061  Tcl_LogCommandInfo(interp, script, command, length)  Tcl_LogCommandInfo(interp, script, command, length)
1062      Tcl_Interp *interp;         /* Interpreter in which to log information. */      Tcl_Interp *interp;         /* Interpreter in which to log information. */
1063      char *script;               /* First character in script containing      char *script;               /* First character in script containing
1064                                   * command (must be <= command). */                                   * command (must be <= command). */
1065      char *command;              /* First character in command that      char *command;              /* First character in command that
1066                                   * generated the error. */                                   * generated the error. */
1067      int length;                 /* Number of bytes in command (-1 means      int length;                 /* Number of bytes in command (-1 means
1068                                   * use all bytes up to first null byte). */                                   * use all bytes up to first null byte). */
1069  {  {
1070      char buffer[200];      char buffer[200];
1071      register char *p;      register char *p;
1072      char *ellipsis = "";      char *ellipsis = "";
1073      Interp *iPtr = (Interp *) interp;      Interp *iPtr = (Interp *) interp;
1074    
1075      if (iPtr->flags & ERR_ALREADY_LOGGED) {      if (iPtr->flags & ERR_ALREADY_LOGGED) {
1076          /*          /*
1077           * Someone else has already logged error information for this           * Someone else has already logged error information for this
1078           * command; we shouldn't add anything more.           * command; we shouldn't add anything more.
1079           */           */
1080    
1081          return;          return;
1082      }      }
1083    
1084      /*      /*
1085       * Compute the line number where the error occurred.       * Compute the line number where the error occurred.
1086       */       */
1087    
1088      iPtr->errorLine = 1;      iPtr->errorLine = 1;
1089      for (p = script; p != command; p++) {      for (p = script; p != command; p++) {
1090          if (*p == '\n') {          if (*p == '\n') {
1091              iPtr->errorLine++;              iPtr->errorLine++;
1092          }          }
1093      }      }
1094    
1095      /*      /*
1096       * Create an error message to add to errorInfo, including up to a       * Create an error message to add to errorInfo, including up to a
1097       * maximum number of characters of the command.       * maximum number of characters of the command.
1098       */       */
1099    
1100      if (length < 0) {      if (length < 0) {
1101          length = strlen(command);          length = strlen(command);
1102      }      }
1103      if (length > 150) {      if (length > 150) {
1104          length = 150;          length = 150;
1105          ellipsis = "...";          ellipsis = "...";
1106      }      }
1107      if (!(iPtr->flags & ERR_IN_PROGRESS)) {      if (!(iPtr->flags & ERR_IN_PROGRESS)) {
1108          sprintf(buffer, "\n    while executing\n\"%.*s%s\"",          sprintf(buffer, "\n    while executing\n\"%.*s%s\"",
1109                  length, command, ellipsis);                  length, command, ellipsis);
1110      } else {      } else {
1111          sprintf(buffer, "\n    invoked from within\n\"%.*s%s\"",          sprintf(buffer, "\n    invoked from within\n\"%.*s%s\"",
1112                  length, command, ellipsis);                  length, command, ellipsis);
1113      }      }
1114      Tcl_AddObjErrorInfo(interp, buffer, -1);      Tcl_AddObjErrorInfo(interp, buffer, -1);
1115      iPtr->flags &= ~ERR_ALREADY_LOGGED;      iPtr->flags &= ~ERR_ALREADY_LOGGED;
1116  }  }
1117    
1118  /*  /*
1119   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1120   *   *
1121   * Tcl_EvalTokens --   * Tcl_EvalTokens --
1122   *   *
1123   *      Given an array of tokens parsed from a Tcl command (e.g., the   *      Given an array of tokens parsed from a Tcl command (e.g., the
1124   *      tokens that make up a word or the index for an array variable)   *      tokens that make up a word or the index for an array variable)
1125   *      this procedure evaluates the tokens and concatenates their   *      this procedure evaluates the tokens and concatenates their
1126   *      values to form a single result value.   *      values to form a single result value.
1127   *   *
1128   * Results:   * Results:
1129   *      The return value is a pointer to a newly allocated Tcl_Obj   *      The return value is a pointer to a newly allocated Tcl_Obj
1130   *      containing the value of the array of tokens.  The reference   *      containing the value of the array of tokens.  The reference
1131   *      count of the returned object has been incremented.  If an error   *      count of the returned object has been incremented.  If an error
1132   *      occurs in evaluating the tokens then a NULL value is returned   *      occurs in evaluating the tokens then a NULL value is returned
1133   *      and an error message is left in interp's result.   *      and an error message is left in interp's result.
1134   *   *
1135   * Side effects:   * Side effects:
1136   *      A new object is allocated to hold the result.   *      A new object is allocated to hold the result.
1137   *   *
1138   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1139   */   */
1140    
1141  Tcl_Obj *  Tcl_Obj *
1142  Tcl_EvalTokens(interp, tokenPtr, count)  Tcl_EvalTokens(interp, tokenPtr, count)
1143      Tcl_Interp *interp;         /* Interpreter in which to lookup      Tcl_Interp *interp;         /* Interpreter in which to lookup
1144                                   * variables, execute nested commands,                                   * variables, execute nested commands,
1145                                   * and report errors. */                                   * and report errors. */
1146      Tcl_Token *tokenPtr;        /* Pointer to first in an array of tokens      Tcl_Token *tokenPtr;        /* Pointer to first in an array of tokens
1147                                   * to evaluate and concatenate. */                                   * to evaluate and concatenate. */
1148      int count;                  /* Number of tokens to consider at tokenPtr.      int count;                  /* Number of tokens to consider at tokenPtr.
1149                                   * Must be at least 1. */                                   * Must be at least 1. */
1150  {  {
1151      Tcl_Obj *resultPtr, *indexPtr, *valuePtr, *newPtr;      Tcl_Obj *resultPtr, *indexPtr, *valuePtr, *newPtr;
1152      char buffer[TCL_UTF_MAX];      char buffer[TCL_UTF_MAX];
1153  #ifdef TCL_MEM_DEBUG  #ifdef TCL_MEM_DEBUG
1154  #   define  MAX_VAR_CHARS 5  #   define  MAX_VAR_CHARS 5
1155  #else  #else
1156  #   define  MAX_VAR_CHARS 30  #   define  MAX_VAR_CHARS 30
1157  #endif  #endif
1158      char nameBuffer[MAX_VAR_CHARS+1];      char nameBuffer[MAX_VAR_CHARS+1];
1159      char *varName, *index;      char *varName, *index;
1160      char *p = NULL;             /* Initialized to avoid compiler warning. */      char *p = NULL;             /* Initialized to avoid compiler warning. */
1161      int length, code;      int length, code;
1162    
1163      /*      /*
1164       * The only tricky thing about this procedure is that it attempts to       * The only tricky thing about this procedure is that it attempts to
1165       * avoid object creation and string copying whenever possible.  For       * avoid object creation and string copying whenever possible.  For
1166       * example, if the value is just a nested command, then use the       * example, if the value is just a nested command, then use the
1167       * command's result object directly.       * command's result object directly.
1168       */       */
1169    
1170      resultPtr = NULL;      resultPtr = NULL;
1171      for ( ; count > 0; count--, tokenPtr++) {      for ( ; count > 0; count--, tokenPtr++) {
1172          valuePtr = NULL;          valuePtr = NULL;
1173    
1174          /*          /*
1175           * The switch statement below computes the next value to be           * The switch statement below computes the next value to be
1176           * concat to the result, as either a range of text or an           * concat to the result, as either a range of text or an
1177           * object.           * object.
1178           */           */
1179    
1180          switch (tokenPtr->type) {          switch (tokenPtr->type) {
1181              case TCL_TOKEN_TEXT:              case TCL_TOKEN_TEXT:
1182                  p = tokenPtr->start;                  p = tokenPtr->start;
1183                  length = tokenPtr->size;                  length = tokenPtr->size;
1184                  break;                  break;
1185    
1186              case TCL_TOKEN_BS:              case TCL_TOKEN_BS:
1187                  length = Tcl_UtfBackslash(tokenPtr->start, (int *) NULL,                  length = Tcl_UtfBackslash(tokenPtr->start, (int *) NULL,
1188                          buffer);                          buffer);
1189                  p = buffer;                  p = buffer;
1190                  break;                  break;
1191    
1192              case TCL_TOKEN_COMMAND:              case TCL_TOKEN_COMMAND:
1193                  code = Tcl_EvalEx(interp, tokenPtr->start+1, tokenPtr->size-2,                  code = Tcl_EvalEx(interp, tokenPtr->start+1, tokenPtr->size-2,
1194                          0);                          0);
1195                  if (code != TCL_OK) {                  if (code != TCL_OK) {
1196                      goto error;                      goto error;
1197                  }                  }
1198                  valuePtr = Tcl_GetObjResult(interp);                  valuePtr = Tcl_GetObjResult(interp);
1199                  break;                  break;
1200    
1201              case TCL_TOKEN_VARIABLE:              case TCL_TOKEN_VARIABLE:
1202                  if (tokenPtr->numComponents == 1) {                  if (tokenPtr->numComponents == 1) {
1203                      indexPtr = NULL;                      indexPtr = NULL;
1204                  } else {                  } else {
1205                      indexPtr = Tcl_EvalTokens(interp, tokenPtr+2,                      indexPtr = Tcl_EvalTokens(interp, tokenPtr+2,
1206                              tokenPtr->numComponents - 1);                              tokenPtr->numComponents - 1);
1207                      if (indexPtr == NULL) {                      if (indexPtr == NULL) {
1208                          goto error;                          goto error;
1209                      }                      }
1210                  }                  }
1211    
1212                  /*                  /*
1213                   * We have to make a copy of the variable name in order                   * We have to make a copy of the variable name in order
1214                   * to have a null-terminated string.  We can't make a                   * to have a null-terminated string.  We can't make a
1215                   * temporary modification to the script to null-terminate                   * temporary modification to the script to null-terminate
1216                   * the name, because a trace callback might potentially                   * the name, because a trace callback might potentially
1217                   * reuse the script and be affected by the null character.                   * reuse the script and be affected by the null character.
1218                   */                   */
1219    
1220                  if (tokenPtr[1].size <= MAX_VAR_CHARS) {                  if (tokenPtr[1].size <= MAX_VAR_CHARS) {
1221                      varName = nameBuffer;                      varName = nameBuffer;
1222                  } else {                  } else {
1223                      varName = ckalloc((unsigned) (tokenPtr[1].size + 1));                      varName = ckalloc((unsigned) (tokenPtr[1].size + 1));
1224                  }                  }
1225                  strncpy(varName, tokenPtr[1].start, (size_t) tokenPtr[1].size);                  strncpy(varName, tokenPtr[1].start, (size_t) tokenPtr[1].size);
1226                  varName[tokenPtr[1].size] = 0;                  varName[tokenPtr[1].size] = 0;
1227                  if (indexPtr != NULL) {                  if (indexPtr != NULL) {
1228                      index = TclGetString(indexPtr);                      index = TclGetString(indexPtr);
1229                  } else {                  } else {
1230                      index = NULL;                      index = NULL;
1231                  }                  }
1232                  valuePtr = Tcl_GetVar2Ex(interp, varName, index,                  valuePtr = Tcl_GetVar2Ex(interp, varName, index,
1233                          TCL_LEAVE_ERR_MSG);                          TCL_LEAVE_ERR_MSG);
1234                  if (varName != nameBuffer) {                  if (varName != nameBuffer) {
1235                      ckfree(varName);                      ckfree(varName);
1236                  }                  }
1237                  if (indexPtr != NULL) {                  if (indexPtr != NULL) {
1238                      Tcl_DecrRefCount(indexPtr);                      Tcl_DecrRefCount(indexPtr);
1239                  }                  }
1240                  if (valuePtr == NULL) {                  if (valuePtr == NULL) {
1241                      goto error;                      goto error;
1242                  }                  }
1243                  count -= tokenPtr->numComponents;                  count -= tokenPtr->numComponents;
1244                  tokenPtr += tokenPtr->numComponents;                  tokenPtr += tokenPtr->numComponents;
1245                  break;                  break;
1246    
1247              default:              default:
1248                  panic("unexpected token type in Tcl_EvalTokens");                  panic("unexpected token type in Tcl_EvalTokens");
1249          }          }
1250    
1251          /*          /*
1252           * If valuePtr isn't NULL, the next piece of text comes from that           * If valuePtr isn't NULL, the next piece of text comes from that
1253           * object; otherwise, take length bytes starting at p.           * object; otherwise, take length bytes starting at p.
1254           */           */
1255    
1256          if (resultPtr == NULL) {          if (resultPtr == NULL) {
1257              if (valuePtr != NULL) {              if (valuePtr != NULL) {
1258                  resultPtr = valuePtr;                  resultPtr = valuePtr;
1259              } else {              } else {
1260                  resultPtr = Tcl_NewStringObj(p, length);                  resultPtr = Tcl_NewStringObj(p, length);
1261              }              }
1262              Tcl_IncrRefCount(resultPtr);              Tcl_IncrRefCount(resultPtr);
1263          } else {          } else {
1264              if (Tcl_IsShared(resultPtr)) {              if (Tcl_IsShared(resultPtr)) {
1265                  newPtr = Tcl_DuplicateObj(resultPtr);                  newPtr = Tcl_DuplicateObj(resultPtr);
1266                  Tcl_DecrRefCount(resultPtr);                  Tcl_DecrRefCount(resultPtr);
1267                  resultPtr = newPtr;                  resultPtr = newPtr;
1268                  Tcl_IncrRefCount(resultPtr);                  Tcl_IncrRefCount(resultPtr);
1269              }              }
1270              if (valuePtr != NULL) {              if (valuePtr != NULL) {
1271                  p = Tcl_GetStringFromObj(valuePtr, &length);                  p = Tcl_GetStringFromObj(valuePtr, &length);
1272              }              }
1273              Tcl_AppendToObj(resultPtr, p, length);              Tcl_AppendToObj(resultPtr, p, length);
1274          }          }
1275      }      }
1276      return resultPtr;      return resultPtr;
1277    
1278      error:      error:
1279      if (resultPtr != NULL) {      if (resultPtr != NULL) {
1280          Tcl_DecrRefCount(resultPtr);          Tcl_DecrRefCount(resultPtr);
1281      }      }
1282      return NULL;      return NULL;
1283  }  }
1284    
1285  /*  /*
1286   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1287   *   *
1288   * Tcl_EvalEx --   * Tcl_EvalEx --
1289   *   *
1290   *      This procedure evaluates a Tcl script without using the compiler   *      This procedure evaluates a Tcl script without using the compiler
1291   *      or byte-code interpreter.  It just parses the script, creates   *      or byte-code interpreter.  It just parses the script, creates
1292   *      values for each word of each command, then calls EvalObjv   *      values for each word of each command, then calls EvalObjv
1293   *      to execute each command.   *      to execute each command.
1294   *   *
1295   * Results:   * Results:
1296   *      The return value is a standard Tcl completion code such as   *      The return value is a standard Tcl completion code such as
1297   *      TCL_OK or TCL_ERROR.  A result or error message is left in   *      TCL_OK or TCL_ERROR.  A result or error message is left in
1298   *      interp's result.   *      interp's result.
1299   *   *
1300   * Side effects:   * Side effects:
1301   *      Depends on the script.   *      Depends on the script.
1302   *   *
1303   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1304   */   */
1305    
1306  int  int
1307  Tcl_EvalEx(interp, script, numBytes, flags)  Tcl_EvalEx(interp, script, numBytes, flags)
1308      Tcl_Interp *interp;         /* Interpreter in which to evaluate the      Tcl_Interp *interp;         /* Interpreter in which to evaluate the
1309                                   * script.  Also used for error reporting. */                                   * script.  Also used for error reporting. */
1310      char *script;               /* First character of script to evaluate. */      char *script;               /* First character of script to evaluate. */
1311      int numBytes;               /* Number of bytes in script.  If < 0, the      int numBytes;               /* Number of bytes in script.  If < 0, the
1312                                   * script consists of all bytes up to the                                   * script consists of all bytes up to the
1313                                   * first null character. */                                   * first null character. */
1314      int flags;                  /* Collection of OR-ed bits that control      int flags;                  /* Collection of OR-ed bits that control
1315                                   * the evaluation of the script.  Only                                   * the evaluation of the script.  Only
1316                                   * TCL_EVAL_GLOBAL is currently                                   * TCL_EVAL_GLOBAL is currently
1317                                   * supported. */                                   * supported. */
1318  {  {
1319      Interp *iPtr = (Interp *) interp;      Interp *iPtr = (Interp *) interp;
1320      char *p, *next;      char *p, *next;
1321      Tcl_Parse parse;      Tcl_Parse parse;
1322  #define NUM_STATIC_OBJS 20  #define NUM_STATIC_OBJS 20
1323      Tcl_Obj *staticObjArray[NUM_STATIC_OBJS], **objv;      Tcl_Obj *staticObjArray[NUM_STATIC_OBJS], **objv;
1324      Tcl_Token *tokenPtr;      Tcl_Token *tokenPtr;
1325      int i, code, commandLength, bytesLeft, nested;      int i, code, commandLength, bytesLeft, nested;
1326      CallFrame *savedVarFramePtr;        /* Saves old copy of iPtr->varFramePtr      CallFrame *savedVarFramePtr;        /* Saves old copy of iPtr->varFramePtr
1327                                           * in case TCL_EVAL_GLOBAL was set. */                                           * in case TCL_EVAL_GLOBAL was set. */
1328    
1329      /*      /*
1330       * The variables below keep track of how much state has been       * The variables below keep track of how much state has been
1331       * allocated while evaluating the script, so that it can be freed       * allocated while evaluating the script, so that it can be freed
1332       * properly if an error occurs.       * properly if an error occurs.
1333       */       */
1334    
1335      int gotParse = 0, objectsUsed = 0;      int gotParse = 0, objectsUsed = 0;
1336    
1337      if (numBytes < 0) {      if (numBytes < 0) {
1338          numBytes = strlen(script);          numBytes = strlen(script);
1339      }      }
1340      Tcl_ResetResult(interp);      Tcl_ResetResult(interp);
1341    
1342      savedVarFramePtr = iPtr->varFramePtr;      savedVarFramePtr = iPtr->varFramePtr;
1343      if (flags & TCL_EVAL_GLOBAL) {      if (flags & TCL_EVAL_GLOBAL) {
1344          iPtr->varFramePtr = NULL;          iPtr->varFramePtr = NULL;
1345      }      }
1346    
1347      /*      /*
1348       * Each iteration through the following loop parses the next       * Each iteration through the following loop parses the next
1349       * command from the script and then executes it.       * command from the script and then executes it.
1350       */       */
1351    
1352      objv = staticObjArray;      objv = staticObjArray;
1353      p = script;      p = script;
1354      bytesLeft = numBytes;      bytesLeft = numBytes;
1355      if (iPtr->evalFlags & TCL_BRACKET_TERM) {      if (iPtr->evalFlags & TCL_BRACKET_TERM) {
1356          nested = 1;          nested = 1;
1357      } else {      } else {
1358          nested = 0;          nested = 0;
1359      }      }
1360      iPtr->evalFlags = 0;      iPtr->evalFlags = 0;
1361      do {      do {
1362          if (Tcl_ParseCommand(interp, p, bytesLeft, nested, &parse)          if (Tcl_ParseCommand(interp, p, bytesLeft, nested, &parse)
1363                  != TCL_OK) {                  != TCL_OK) {
1364              code = TCL_ERROR;              code = TCL_ERROR;
1365              goto error;              goto error;
1366          }          }
1367          gotParse = 1;          gotParse = 1;
1368          if (parse.numWords > 0) {          if (parse.numWords > 0) {
1369              /*              /*
1370               * Generate an array of objects for the words of the command.               * Generate an array of objects for the words of the command.
1371               */               */
1372            
1373              if (parse.numWords <= NUM_STATIC_OBJS) {              if (parse.numWords <= NUM_STATIC_OBJS) {
1374                  objv = staticObjArray;                  objv = staticObjArray;
1375              } else {              } else {
1376                  objv = (Tcl_Obj **) ckalloc((unsigned)                  objv = (Tcl_Obj **) ckalloc((unsigned)
1377                      (parse.numWords * sizeof (Tcl_Obj *)));                      (parse.numWords * sizeof (Tcl_Obj *)));
1378              }              }
1379              for (objectsUsed = 0, tokenPtr = parse.tokenPtr;              for (objectsUsed = 0, tokenPtr = parse.tokenPtr;
1380                      objectsUsed < parse.numWords;                      objectsUsed < parse.numWords;
1381                      objectsUsed++, tokenPtr += (tokenPtr->numComponents + 1)) {                      objectsUsed++, tokenPtr += (tokenPtr->numComponents + 1)) {
1382                  objv[objectsUsed] = Tcl_EvalTokens(interp, tokenPtr+1,                  objv[objectsUsed] = Tcl_EvalTokens(interp, tokenPtr+1,
1383                          tokenPtr->numComponents);                          tokenPtr->numComponents);
1384                  if (objv[objectsUsed] == NULL) {                  if (objv[objectsUsed] == NULL) {
1385                      code = TCL_ERROR;                      code = TCL_ERROR;
1386                      goto error;                      goto error;
1387                  }                  }
1388              }              }
1389            
1390              /*              /*
1391               * Execute the command and free the objects for its words.               * Execute the command and free the objects for its words.
1392               */               */
1393            
1394              code = EvalObjv(interp, objectsUsed, objv, p, bytesLeft, 0);              code = EvalObjv(interp, objectsUsed, objv, p, bytesLeft, 0);
1395              if (code != TCL_OK) {              if (code != TCL_OK) {
1396                  goto error;                  goto error;
1397              }              }
1398              for (i = 0; i < objectsUsed; i++) {              for (i = 0; i < objectsUsed; i++) {
1399                  Tcl_DecrRefCount(objv[i]);                  Tcl_DecrRefCount(objv[i]);
1400              }              }
1401              objectsUsed = 0;              objectsUsed = 0;
1402              if (objv != staticObjArray) {              if (objv != staticObjArray) {
1403                  ckfree((char *) objv);                  ckfree((char *) objv);
1404                  objv = staticObjArray;                  objv = staticObjArray;
1405              }              }
1406          }          }
1407    
1408          /*          /*
1409           * Advance to the next command in the script.           * Advance to the next command in the script.
1410           */           */
1411    
1412          next = parse.commandStart + parse.commandSize;          next = parse.commandStart + parse.commandSize;
1413          bytesLeft -= next - p;          bytesLeft -= next - p;
1414          p = next;          p = next;
1415          Tcl_FreeParse(&parse);          Tcl_FreeParse(&parse);
1416          gotParse = 0;          gotParse = 0;
1417          if ((nested != 0) && (p > script) && (p[-1] == ']')) {          if ((nested != 0) && (p > script) && (p[-1] == ']')) {
1418              /*              /*
1419               * We get here in the special case where the TCL_BRACKET_TERM               * We get here in the special case where the TCL_BRACKET_TERM
1420               * flag was set in the interpreter and we reached a close               * flag was set in the interpreter and we reached a close
1421               * bracket in the script.  Return immediately.               * bracket in the script.  Return immediately.
1422               */               */
1423    
1424              iPtr->termOffset = (p - 1) - script;              iPtr->termOffset = (p - 1) - script;
1425              iPtr->varFramePtr = savedVarFramePtr;              iPtr->varFramePtr = savedVarFramePtr;
1426              return TCL_OK;              return TCL_OK;
1427          }          }
1428      } while (bytesLeft > 0);      } while (bytesLeft > 0);
1429      iPtr->termOffset = p - script;      iPtr->termOffset = p - script;
1430      iPtr->varFramePtr = savedVarFramePtr;      iPtr->varFramePtr = savedVarFramePtr;
1431      return TCL_OK;      return TCL_OK;
1432    
1433      error:      error:
1434      /*      /*
1435       * Generate various pieces of error information, such as the line       * Generate various pieces of error information, such as the line
1436       * number where the error occurred and information to add to the       * number where the error occurred and information to add to the
1437       * errorInfo variable.  Then free resources that had been allocated       * errorInfo variable.  Then free resources that had been allocated
1438       * to the command.       * to the command.
1439       */       */
1440    
1441      if ((code == TCL_ERROR) && !(iPtr->flags & ERR_ALREADY_LOGGED)) {      if ((code == TCL_ERROR) && !(iPtr->flags & ERR_ALREADY_LOGGED)) {
1442          commandLength = parse.commandSize;          commandLength = parse.commandSize;
1443          if ((parse.commandStart + commandLength) != (script + numBytes)) {          if ((parse.commandStart + commandLength) != (script + numBytes)) {
1444              /*              /*
1445               * The command where the error occurred didn't end at the end               * The command where the error occurred didn't end at the end
1446               * of the script (i.e. it ended at a terminator character such               * of the script (i.e. it ended at a terminator character such
1447               * as ";".  Reduce the length by one so that the error message               * as ";".  Reduce the length by one so that the error message
1448               * doesn't include the terminator character.               * doesn't include the terminator character.
1449               */               */
1450                            
1451              commandLength -= 1;              commandLength -= 1;
1452          }          }
1453          Tcl_LogCommandInfo(interp, script, parse.commandStart, commandLength);          Tcl_LogCommandInfo(interp, script, parse.commandStart, commandLength);
1454      }      }
1455            
1456      for (i = 0; i < objectsUsed; i++) {      for (i = 0; i < objectsUsed; i++) {
1457          Tcl_DecrRefCount(objv[i]);          Tcl_DecrRefCount(objv[i]);
1458      }      }
1459      if (gotParse) {      if (gotParse) {
1460          p = parse.commandStart + parse.commandSize;          p = parse.commandStart + parse.commandSize;
1461          Tcl_FreeParse(&parse);          Tcl_FreeParse(&parse);
1462          if ((nested != 0) && (p > script) && (p[-1] == ']')) {          if ((nested != 0) && (p > script) && (p[-1] == ']')) {
1463              /*              /*
1464               * We get here in the special case where the TCL_BRACKET_TERM               * We get here in the special case where the TCL_BRACKET_TERM
1465               * flag was set in the interpreter and we reached a close               * flag was set in the interpreter and we reached a close
1466               * bracket in the script.  Return immediately.               * bracket in the script.  Return immediately.
1467               */               */
1468    
1469              iPtr->termOffset = (p - 1) - script;              iPtr->termOffset = (p - 1) - script;
1470          } else {          } else {
1471              iPtr->termOffset = p - script;              iPtr->termOffset = p - script;
1472          }              }    
1473      }      }
1474      if (objv != staticObjArray) {      if (objv != staticObjArray) {
1475          ckfree((char *) objv);          ckfree((char *) objv);
1476      }      }
1477      iPtr->varFramePtr = savedVarFramePtr;      iPtr->varFramePtr = savedVarFramePtr;
1478      return code;      return code;
1479  }  }
1480    
1481  /*  /*
1482   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1483   *   *
1484   * Tcl_Eval --   * Tcl_Eval --
1485   *   *
1486   *      Execute a Tcl command in a string.  This procedure executes the   *      Execute a Tcl command in a string.  This procedure executes the
1487   *      script directly, rather than compiling it to bytecodes.  Before   *      script directly, rather than compiling it to bytecodes.  Before
1488   *      the arrival of the bytecode compiler in Tcl 8.0 Tcl_Eval was   *      the arrival of the bytecode compiler in Tcl 8.0 Tcl_Eval was
1489   *      the main procedure used for executing Tcl commands, but nowadays   *      the main procedure used for executing Tcl commands, but nowadays
1490   *      it isn't used much.   *      it isn't used much.
1491   *   *
1492   * Results:   * Results:
1493   *      The return value is one of the return codes defined in tcl.h   *      The return value is one of the return codes defined in tcl.h
1494   *      (such as TCL_OK), and interp's result contains a value   *      (such as TCL_OK), and interp's result contains a value
1495   *      to supplement the return code. The value of the result   *      to supplement the return code. The value of the result
1496   *      will persist only until the next call to Tcl_Eval or Tcl_EvalObj:   *      will persist only until the next call to Tcl_Eval or Tcl_EvalObj:
1497   *      you must copy it or lose it!   *      you must copy it or lose it!
1498   *   *
1499   * Side effects:   * Side effects:
1500   *      Can be almost arbitrary, depending on the commands in the script.   *      Can be almost arbitrary, depending on the commands in the script.
1501   *   *
1502   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1503   */   */
1504    
1505  int  int
1506  Tcl_Eval(interp, string)  Tcl_Eval(interp, string)
1507      Tcl_Interp *interp;         /* Token for command interpreter (returned      Tcl_Interp *interp;         /* Token for command interpreter (returned
1508                                   * by previous call to Tcl_CreateInterp). */                                   * by previous call to Tcl_CreateInterp). */
1509      char *string;               /* Pointer to TCL command to execute. */      char *string;               /* Pointer to TCL command to execute. */
1510  {  {
1511      int code;      int code;
1512    
1513      code = Tcl_EvalEx(interp, string, -1, 0);      code = Tcl_EvalEx(interp, string, -1, 0);
1514    
1515      /*      /*
1516       * For backwards compatibility with old C code that predates the       * For backwards compatibility with old C code that predates the
1517       * object system in Tcl 8.0, we have to mirror the object result       * object system in Tcl 8.0, we have to mirror the object result
1518       * back into the string result (some callers may expect it there).       * back into the string result (some callers may expect it there).
1519       */       */
1520    
1521      Tcl_SetResult(interp, TclGetString(Tcl_GetObjResult(interp)),      Tcl_SetResult(interp, TclGetString(Tcl_GetObjResult(interp)),
1522              TCL_VOLATILE);              TCL_VOLATILE);
1523      return code;      return code;
1524  }  }
1525    
1526  /*  /*
1527   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1528   *   *
1529   * Tcl_EvalObj, Tcl_GlobalEvalObj --   * Tcl_EvalObj, Tcl_GlobalEvalObj --
1530   *   *
1531   *      These functions are deprecated but we keep them around for backwards   *      These functions are deprecated but we keep them around for backwards
1532   *      compatibility reasons.   *      compatibility reasons.
1533   *   *
1534   * Results:   * Results:
1535   *      See the functions they call.   *      See the functions they call.
1536   *   *
1537   * Side effects:   * Side effects:
1538   *      See the functions they call.   *      See the functions they call.
1539   *   *
1540   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1541   */   */
1542    
1543  #undef Tcl_EvalObj  #undef Tcl_EvalObj
1544  int  int
1545  Tcl_EvalObj(interp, objPtr)  Tcl_EvalObj(interp, objPtr)
1546      Tcl_Interp * interp;      Tcl_Interp * interp;
1547      Tcl_Obj * objPtr;      Tcl_Obj * objPtr;
1548  {  {
1549      return Tcl_EvalObjEx(interp, objPtr, 0);      return Tcl_EvalObjEx(interp, objPtr, 0);
1550  }  }
1551    
1552  #undef Tcl_GlobalEvalObj  #undef Tcl_GlobalEvalObj
1553  int  int
1554  Tcl_GlobalEvalObj(interp, objPtr)  Tcl_GlobalEvalObj(interp, objPtr)
1555      Tcl_Interp * interp;      Tcl_Interp * interp;
1556      Tcl_Obj * objPtr;      Tcl_Obj * objPtr;
1557  {  {
1558      return Tcl_EvalObjEx(interp, objPtr, TCL_EVAL_GLOBAL);      return Tcl_EvalObjEx(interp, objPtr, TCL_EVAL_GLOBAL);
1559  }  }
1560    
1561  /*  /*
1562   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1563   *   *
1564   * Tcl_ParseVarName --   * Tcl_ParseVarName --
1565   *   *
1566   *      Given a string starting with a $ sign, parse off a variable   *      Given a string starting with a $ sign, parse off a variable
1567   *      name and return information about the parse.   *      name and return information about the parse.
1568   *   *
1569   * Results:   * Results:
1570   *      The return value is TCL_OK if the command was parsed   *      The return value is TCL_OK if the command was parsed
1571   *      successfully and TCL_ERROR otherwise.  If an error occurs and   *      successfully and TCL_ERROR otherwise.  If an error occurs and
1572   *      interp isn't NULL then an error message is left in its result.   *      interp isn't NULL then an error message is left in its result.
1573   *      On a successful return, tokenPtr and numTokens fields of   *      On a successful return, tokenPtr and numTokens fields of
1574   *      parsePtr are filled in with information about the variable name   *      parsePtr are filled in with information about the variable name
1575   *      that was parsed.  The "size" field of the first new token gives   *      that was parsed.  The "size" field of the first new token gives
1576   *      the total number of bytes in the variable name.  Other fields in   *      the total number of bytes in the variable name.  Other fields in
1577   *      parsePtr are undefined.   *      parsePtr are undefined.
1578   *   *
1579   * Side effects:   * Side effects:
1580   *      If there is insufficient space in parsePtr to hold all the   *      If there is insufficient space in parsePtr to hold all the
1581   *      information about the command, then additional space is   *      information about the command, then additional space is
1582   *      malloc-ed.  If the procedure returns TCL_OK then the caller must   *      malloc-ed.  If the procedure returns TCL_OK then the caller must
1583   *      eventually invoke Tcl_FreeParse to release any additional space   *      eventually invoke Tcl_FreeParse to release any additional space
1584   *      that was allocated.   *      that was allocated.
1585   *   *
1586   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1587   */   */
1588    
1589  int  int
1590  Tcl_ParseVarName(interp, string, numBytes, parsePtr, append)  Tcl_ParseVarName(interp, string, numBytes, parsePtr, append)
1591      Tcl_Interp *interp;         /* Interpreter to use for error reporting;      Tcl_Interp *interp;         /* Interpreter to use for error reporting;
1592                                   * if NULL, then no error message is                                   * if NULL, then no error message is
1593                                   * provided. */                                   * provided. */
1594      char *string;               /* String containing variable name.  First      char *string;               /* String containing variable name.  First
1595                                   * character must be "$". */                                   * character must be "$". */
1596      int numBytes;               /* Total number of bytes in string.  If < 0,      int numBytes;               /* Total number of bytes in string.  If < 0,
1597                                   * the string consists of all bytes up to the                                   * the string consists of all bytes up to the
1598                                   * first null character. */                                   * first null character. */
1599      Tcl_Parse *parsePtr;        /* Structure to fill in with information      Tcl_Parse *parsePtr;        /* Structure to fill in with information
1600                                   * about the variable name. */                                   * about the variable name. */
1601      int append;                 /* Non-zero means append tokens to existing      int append;                 /* Non-zero means append tokens to existing
1602                                   * information in parsePtr; zero means ignore                                   * information in parsePtr; zero means ignore
1603                                   * existing tokens in parsePtr and reinitialize                                   * existing tokens in parsePtr and reinitialize
1604                                   * it. */                                   * it. */
1605  {  {
1606      Tcl_Token *tokenPtr;      Tcl_Token *tokenPtr;
1607      char *end, *src;      char *end, *src;
1608      unsigned char c;      unsigned char c;
1609      int varIndex, offset;      int varIndex, offset;
1610      Tcl_UniChar ch;      Tcl_UniChar ch;
1611      unsigned array;      unsigned array;
1612    
1613      if (numBytes >= 0) {      if (numBytes >= 0) {
1614          end = string + numBytes;          end = string + numBytes;
1615      } else {      } else {
1616          end = string + strlen(string);          end = string + strlen(string);
1617      }      }
1618    
1619      if (!append) {      if (!append) {
1620          parsePtr->numWords = 0;          parsePtr->numWords = 0;
1621          parsePtr->tokenPtr = parsePtr->staticTokens;          parsePtr->tokenPtr = parsePtr->staticTokens;
1622          parsePtr->numTokens = 0;          parsePtr->numTokens = 0;
1623          parsePtr->tokensAvailable = NUM_STATIC_TOKENS;          parsePtr->tokensAvailable = NUM_STATIC_TOKENS;
1624          parsePtr->string = string;          parsePtr->string = string;
1625          parsePtr->end = end;          parsePtr->end = end;
1626          parsePtr->interp = interp;          parsePtr->interp = interp;
1627          parsePtr->errorType = TCL_PARSE_SUCCESS;          parsePtr->errorType = TCL_PARSE_SUCCESS;
1628          parsePtr->incomplete = 0;          parsePtr->incomplete = 0;
1629      }      }
1630    
1631      /*      /*
1632       * Generate one token for the variable, an additional token for the       * Generate one token for the variable, an additional token for the
1633       * name, plus any number of additional tokens for the index, if       * name, plus any number of additional tokens for the index, if
1634       * there is one.       * there is one.
1635       */       */
1636    
1637      src = string;      src = string;
1638      if ((parsePtr->numTokens + 2) > parsePtr->tokensAvailable) {      if ((parsePtr->numTokens + 2) > parsePtr->tokensAvailable) {
1639          TclExpandTokenArray(parsePtr);          TclExpandTokenArray(parsePtr);
1640      }      }
1641      tokenPtr = &parsePtr->tokenPtr[parsePtr->numTokens];      tokenPtr = &parsePtr->tokenPtr[parsePtr->numTokens];
1642      tokenPtr->type = TCL_TOKEN_VARIABLE;      tokenPtr->type = TCL_TOKEN_VARIABLE;
1643      tokenPtr->start = src;      tokenPtr->start = src;
1644      varIndex = parsePtr->numTokens;      varIndex = parsePtr->numTokens;
1645      parsePtr->numTokens++;      parsePtr->numTokens++;
1646      tokenPtr++;      tokenPtr++;
1647      src++;      src++;
1648      if (src >= end) {      if (src >= end) {
1649          goto justADollarSign;          goto justADollarSign;
1650      }      }
1651      tokenPtr->type = TCL_TOKEN_TEXT;      tokenPtr->type = TCL_TOKEN_TEXT;
1652      tokenPtr->start = src;      tokenPtr->start = src;
1653      tokenPtr->numComponents = 0;      tokenPtr->numComponents = 0;
1654    
1655      /*      /*
1656       * The name of the variable can have three forms:       * The name of the variable can have three forms:
1657       * 1. The $ sign is followed by an open curly brace.  Then       * 1. The $ sign is followed by an open curly brace.  Then
1658       *    the variable name is everything up to the next close       *    the variable name is everything up to the next close
1659       *    curly brace, and the variable is a scalar variable.       *    curly brace, and the variable is a scalar variable.
1660       * 2. The $ sign is not followed by an open curly brace.  Then       * 2. The $ sign is not followed by an open curly brace.  Then
1661       *    the variable name is everything up to the next       *    the variable name is everything up to the next
1662       *    character that isn't a letter, digit, or underscore.       *    character that isn't a letter, digit, or underscore.
1663       *    :: sequences are also considered part of the variable       *    :: sequences are also considered part of the variable
1664       *    name, in order to support namespaces. If the following       *    name, in order to support namespaces. If the following
1665       *    character is an open parenthesis, then the information       *    character is an open parenthesis, then the information
1666       *    between parentheses is the array element name.       *    between parentheses is the array element name.
1667       * 3. The $ sign is followed by something that isn't a letter,       * 3. The $ sign is followed by something that isn't a letter,
1668       *    digit, or underscore:  in this case, there is no variable       *    digit, or underscore:  in this case, there is no variable
1669       *    name and the token is just "$".       *    name and the token is just "$".
1670       */       */
1671    
1672      if (*src == '{') {      if (*src == '{') {
1673          src++;          src++;
1674          tokenPtr->type = TCL_TOKEN_TEXT;          tokenPtr->type = TCL_TOKEN_TEXT;
1675          tokenPtr->start = src;          tokenPtr->start = src;
1676          tokenPtr->numComponents = 0;          tokenPtr->numComponents = 0;
1677          while (1) {          while (1) {
1678              if (src == end) {              if (src == end) {
1679                  if (interp != NULL) {                  if (interp != NULL) {
1680                      Tcl_SetResult(interp,                      Tcl_SetResult(interp,
1681                          "missing close-brace for variable name",                          "missing close-brace for variable name",
1682                          TCL_STATIC);                          TCL_STATIC);
1683                  }                  }
1684                  parsePtr->errorType = TCL_PARSE_MISSING_VAR_BRACE;                  parsePtr->errorType = TCL_PARSE_MISSING_VAR_BRACE;
1685                  parsePtr->term = tokenPtr->start-1;                  parsePtr->term = tokenPtr->start-1;
1686                  parsePtr->incomplete = 1;                  parsePtr->incomplete = 1;
1687                  goto error;                  goto error;
1688              }              }
1689              if (*src == '}') {              if (*src == '}') {
1690                  break;                  break;
1691              }              }
1692              src++;              src++;
1693          }          }
1694          tokenPtr->size = src - tokenPtr->start;          tokenPtr->size = src - tokenPtr->start;
1695          tokenPtr[-1].size = src - tokenPtr[-1].start;          tokenPtr[-1].size = src - tokenPtr[-1].start;
1696          parsePtr->numTokens++;          parsePtr->numTokens++;
1697          src++;          src++;
1698      } else {      } else {
1699          tokenPtr->type = TCL_TOKEN_TEXT;          tokenPtr->type = TCL_TOKEN_TEXT;
1700          tokenPtr->start = src;          tokenPtr->start = src;
1701          tokenPtr->numComponents = 0;          tokenPtr->numComponents = 0;
1702          while (src != end) {          while (src != end) {
1703              offset = Tcl_UtfToUniChar(src, &ch);              offset = Tcl_UtfToUniChar(src, &ch);
1704              c = UCHAR(ch);              c = UCHAR(ch);
1705              if (isalnum(c) || (c == '_')) { /* INTL: ISO only, UCHAR. */              if (isalnum(c) || (c == '_')) { /* INTL: ISO only, UCHAR. */
1706                  src += offset;                  src += offset;
1707                  continue;                  continue;
1708              }              }
1709              if ((c == ':') && (((src+1) != end) && (src[1] == ':'))) {              if ((c == ':') && (((src+1) != end) && (src[1] == ':'))) {
1710                  src += 2;                  src += 2;
1711                  while ((src != end) && (*src == ':')) {                  while ((src != end) && (*src == ':')) {
1712                      src += 1;                      src += 1;
1713                  }                  }
1714                  continue;                  continue;
1715              }              }
1716              break;              break;
1717          }          }
1718    
1719          /*          /*
1720           * Support for empty array names here.           * Support for empty array names here.
1721           */           */
1722          array = ((src != end) && (*src == '('));          array = ((src != end) && (*src == '('));
1723          tokenPtr->size = src - tokenPtr->start;          tokenPtr->size = src - tokenPtr->start;
1724          if (tokenPtr->size == 0 && !array) {          if (tokenPtr->size == 0 && !array) {
1725              goto justADollarSign;              goto justADollarSign;
1726          }          }
1727          parsePtr->numTokens++;          parsePtr->numTokens++;
1728          if (array) {          if (array) {
1729              /*              /*
1730               * This is a reference to an array element.  Call               * This is a reference to an array element.  Call
1731               * ParseTokens recursively to parse the element name,               * ParseTokens recursively to parse the element name,
1732               * since it could contain any number of substitutions.               * since it could contain any number of substitutions.
1733               */               */
1734    
1735              if (ParseTokens(src+1, TYPE_CLOSE_PAREN, parsePtr)              if (ParseTokens(src+1, TYPE_CLOSE_PAREN, parsePtr)
1736                      != TCL_OK) {                      != TCL_OK) {
1737                  goto error;                  goto error;
1738              }              }
1739              if ((parsePtr->term == end) || (*parsePtr->term != ')')) {              if ((parsePtr->term == end) || (*parsePtr->term != ')')) {
1740                  if (parsePtr->interp != NULL) {                  if (parsePtr->interp != NULL) {
1741                      Tcl_SetResult(parsePtr->interp, "missing )",                      Tcl_SetResult(parsePtr->interp, "missing )",
1742                              TCL_STATIC);                              TCL_STATIC);
1743                  }                  }
1744                  parsePtr->errorType = TCL_PARSE_MISSING_PAREN;                  parsePtr->errorType = TCL_PARSE_MISSING_PAREN;
1745                  parsePtr->term = src;                  parsePtr->term = src;
1746                  parsePtr->incomplete = 1;                  parsePtr->incomplete = 1;
1747                  goto error;                  goto error;
1748              }              }
1749              src = parsePtr->term + 1;              src = parsePtr->term + 1;
1750          }          }
1751      }      }
1752      tokenPtr = &parsePtr->tokenPtr[varIndex];      tokenPtr = &parsePtr->tokenPtr[varIndex];
1753      tokenPtr->size = src - tokenPtr->start;      tokenPtr->size = src - tokenPtr->start;
1754      tokenPtr->numComponents = parsePtr->numTokens - (varIndex + 1);      tokenPtr->numComponents = parsePtr->numTokens - (varIndex + 1);
1755      return TCL_OK;      return TCL_OK;
1756    
1757      /*      /*
1758       * The dollar sign isn't followed by a variable name.       * The dollar sign isn't followed by a variable name.
1759       * replace the TCL_TOKEN_VARIABLE token with a       * replace the TCL_TOKEN_VARIABLE token with a
1760       * TCL_TOKEN_TEXT token for the dollar sign.       * TCL_TOKEN_TEXT token for the dollar sign.
1761       */       */
1762    
1763      justADollarSign:      justADollarSign:
1764      tokenPtr = &parsePtr->tokenPtr[varIndex];      tokenPtr = &parsePtr->tokenPtr[varIndex];
1765      tokenPtr->type = TCL_TOKEN_TEXT;      tokenPtr->type = TCL_TOKEN_TEXT;
1766      tokenPtr->size = 1;      tokenPtr->size = 1;
1767      tokenPtr->numComponents = 0;      tokenPtr->numComponents = 0;
1768      return TCL_OK;      return TCL_OK;
1769    
1770      error:      error:
1771      Tcl_FreeParse(parsePtr);      Tcl_FreeParse(parsePtr);
1772      return TCL_ERROR;      return TCL_ERROR;
1773  }  }
1774    
1775  /*  /*
1776   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1777   *   *
1778   * Tcl_ParseVar --   * Tcl_ParseVar --
1779   *   *
1780   *      Given a string starting with a $ sign, parse off a variable   *      Given a string starting with a $ sign, parse off a variable
1781   *      name and return its value.   *      name and return its value.
1782   *   *
1783   * Results:   * Results:
1784   *      The return value is the contents of the variable given by   *      The return value is the contents of the variable given by
1785   *      the leading characters of string.  If termPtr isn't NULL,   *      the leading characters of string.  If termPtr isn't NULL,
1786   *      *termPtr gets filled in with the address of the character   *      *termPtr gets filled in with the address of the character
1787   *      just after the last one in the variable specifier.  If the   *      just after the last one in the variable specifier.  If the
1788   *      variable doesn't exist, then the return value is NULL and   *      variable doesn't exist, then the return value is NULL and
1789   *      an error message will be left in interp's result.   *      an error message will be left in interp's result.
1790   *   *
1791   * Side effects:   * Side effects:
1792   *      None.   *      None.
1793   *   *
1794   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1795   */   */
1796    
1797  char *  char *
1798  Tcl_ParseVar(interp, string, termPtr)  Tcl_ParseVar(interp, string, termPtr)
1799      Tcl_Interp *interp;                 /* Context for looking up variable. */      Tcl_Interp *interp;                 /* Context for looking up variable. */
1800      register char *string;              /* String containing variable name.      register char *string;              /* String containing variable name.
1801                                           * First character must be "$". */                                           * First character must be "$". */
1802      char **termPtr;                     /* If non-NULL, points to word to fill      char **termPtr;                     /* If non-NULL, points to word to fill
1803                                           * in with character just after last                                           * in with character just after last
1804                                           * one in the variable specifier. */                                           * one in the variable specifier. */
1805    
1806  {  {
1807      Tcl_Parse parse;      Tcl_Parse parse;
1808      register Tcl_Obj *objPtr;      register Tcl_Obj *objPtr;
1809    
1810      if (Tcl_ParseVarName(interp, string, -1, &parse, 0) != TCL_OK) {      if (Tcl_ParseVarName(interp, string, -1, &parse, 0) != TCL_OK) {
1811          return NULL;          return NULL;
1812      }      }
1813    
1814      if (termPtr != NULL) {      if (termPtr != NULL) {
1815          *termPtr = string + parse.tokenPtr->size;          *termPtr = string + parse.tokenPtr->size;
1816      }      }
1817      if (parse.numTokens == 1) {      if (parse.numTokens == 1) {
1818          /*          /*
1819           * There isn't a variable name after all: the $ is just a $.           * There isn't a variable name after all: the $ is just a $.
1820           */           */
1821    
1822          return "$";          return "$";
1823      }      }
1824    
1825      objPtr = Tcl_EvalTokens(interp, parse.tokenPtr, parse.numTokens);      objPtr = Tcl_EvalTokens(interp, parse.tokenPtr, parse.numTokens);
1826      if (objPtr == NULL) {      if (objPtr == NULL) {
1827          return NULL;          return NULL;
1828      }      }
1829    
1830      /*      /*
1831       * At this point we should have an object containing the value of       * At this point we should have an object containing the value of
1832       * a variable.  Just return the string from that object.       * a variable.  Just return the string from that object.
1833       */       */
1834    
1835  #ifdef TCL_COMPILE_DEBUG  #ifdef TCL_COMPILE_DEBUG
1836      if (objPtr->refCount < 2) {      if (objPtr->refCount < 2) {
1837          panic("Tcl_ParseVar got temporary object from Tcl_EvalTokens");          panic("Tcl_ParseVar got temporary object from Tcl_EvalTokens");
1838      }      }
1839  #endif /*TCL_COMPILE_DEBUG*/      #endif /*TCL_COMPILE_DEBUG*/    
1840      TclDecrRefCount(objPtr);      TclDecrRefCount(objPtr);
1841      return TclGetString(objPtr);      return TclGetString(objPtr);
1842  }  }
1843    
1844  /*  /*
1845   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1846   *   *
1847   * Tcl_ParseBraces --   * Tcl_ParseBraces --
1848   *   *
1849   *      Given a string in braces such as a Tcl command argument or a string   *      Given a string in braces such as a Tcl command argument or a string
1850   *      value in a Tcl expression, this procedure parses the string and   *      value in a Tcl expression, this procedure parses the string and
1851   *      returns information about the parse.   *      returns information about the parse.
1852   *   *
1853   * Results:   * Results:
1854   *      The return value is TCL_OK if the string was parsed successfully and   *      The return value is TCL_OK if the string was parsed successfully and
1855   *      TCL_ERROR otherwise. If an error occurs and interp isn't NULL then   *      TCL_ERROR otherwise. If an error occurs and interp isn't NULL then
1856   *      an error message is left in its result. On a successful return,   *      an error message is left in its result. On a successful return,
1857   *      tokenPtr and numTokens fields of parsePtr are filled in with   *      tokenPtr and numTokens fields of parsePtr are filled in with
1858   *      information about the string that was parsed. Other fields in   *      information about the string that was parsed. Other fields in
1859   *      parsePtr are undefined. termPtr is set to point to the character   *      parsePtr are undefined. termPtr is set to point to the character
1860   *      just after the last one in the braced string.   *      just after the last one in the braced string.
1861   *   *
1862   * Side effects:   * Side effects:
1863   *      If there is insufficient space in parsePtr to hold all the   *      If there is insufficient space in parsePtr to hold all the
1864   *      information about the command, then additional space is   *      information about the command, then additional space is
1865   *      malloc-ed. If the procedure returns TCL_OK then the caller must   *      malloc-ed. If the procedure returns TCL_OK then the caller must
1866   *      eventually invoke Tcl_FreeParse to release any additional space   *      eventually invoke Tcl_FreeParse to release any additional space
1867   *      that was allocated.   *      that was allocated.
1868   *   *
1869   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1870   */   */
1871    
1872  int  int
1873  Tcl_ParseBraces(interp, string, numBytes, parsePtr, append, termPtr)  Tcl_ParseBraces(interp, string, numBytes, parsePtr, append, termPtr)
1874      Tcl_Interp *interp;         /* Interpreter to use for error reporting;      Tcl_Interp *interp;         /* Interpreter to use for error reporting;
1875                                   * if NULL, then no error message is                                   * if NULL, then no error message is
1876                                   * provided. */                                   * provided. */
1877      char *string;               /* String containing the string in braces.      char *string;               /* String containing the string in braces.
1878                                   * The first character must be '{'. */                                   * The first character must be '{'. */
1879      int numBytes;               /* Total number of bytes in string. If < 0,      int numBytes;               /* Total number of bytes in string. If < 0,
1880                                   * the string consists of all bytes up to                                   * the string consists of all bytes up to
1881                                   * the first null character. */                                   * the first null character. */
1882      register Tcl_Parse *parsePtr;      register Tcl_Parse *parsePtr;
1883                                  /* Structure to fill in with information                                  /* Structure to fill in with information
1884                                   * about the string. */                                   * about the string. */
1885      int append;                 /* Non-zero means append tokens to existing      int append;                 /* Non-zero means append tokens to existing
1886                                   * information in parsePtr; zero means                                   * information in parsePtr; zero means
1887                                   * ignore existing tokens in parsePtr and                                   * ignore existing tokens in parsePtr and
1888                                   * reinitialize it. */                                   * reinitialize it. */
1889      char **termPtr;             /* If non-NULL, points to word in which to      char **termPtr;             /* If non-NULL, points to word in which to
1890                                   * store a pointer to the character just                                   * store a pointer to the character just
1891                                   * after the terminating '}' if the parse                                   * after the terminating '}' if the parse
1892                                   * was successful. */                                   * was successful. */
1893    
1894  {  {
1895      char utfBytes[TCL_UTF_MAX]; /* For result of backslash substitution. */      char utfBytes[TCL_UTF_MAX]; /* For result of backslash substitution. */
1896      Tcl_Token *tokenPtr;      Tcl_Token *tokenPtr;
1897      register char *src, *end;      register char *src, *end;
1898      int startIndex, level, length;      int startIndex, level, length;
1899    
1900      if ((numBytes >= 0) || (string == NULL)) {      if ((numBytes >= 0) || (string == NULL)) {
1901          end = string + numBytes;          end = string + numBytes;
1902      } else {      } else {
1903          end = string + strlen(string);          end = string + strlen(string);
1904      }      }
1905            
1906      if (!append) {      if (!append) {
1907          parsePtr->numWords = 0;          parsePtr->numWords = 0;
1908          parsePtr->tokenPtr = parsePtr->staticTokens;          parsePtr->tokenPtr = parsePtr->staticTokens;
1909          parsePtr->numTokens = 0;          parsePtr->numTokens = 0;
1910          parsePtr->tokensAvailable = NUM_STATIC_TOKENS;          parsePtr->tokensAvailable = NUM_STATIC_TOKENS;
1911          parsePtr->string = string;          parsePtr->string = string;
1912          parsePtr->end = end;          parsePtr->end = end;
1913          parsePtr->interp = interp;          parsePtr->interp = interp;
1914          parsePtr->errorType = TCL_PARSE_SUCCESS;          parsePtr->errorType = TCL_PARSE_SUCCESS;
1915      }      }
1916    
1917      src = string+1;      src = string+1;
1918      startIndex = parsePtr->numTokens;      startIndex = parsePtr->numTokens;
1919    
1920      if (parsePtr->numTokens == parsePtr->tokensAvailable) {      if (parsePtr->numTokens == parsePtr->tokensAvailable) {
1921          TclExpandTokenArray(parsePtr);          TclExpandTokenArray(parsePtr);
1922      }      }
1923      tokenPtr = &parsePtr->tokenPtr[startIndex];      tokenPtr = &parsePtr->tokenPtr[startIndex];
1924      tokenPtr->type = TCL_TOKEN_TEXT;      tokenPtr->type = TCL_TOKEN_TEXT;
1925      tokenPtr->start = src;      tokenPtr->start = src;
1926      tokenPtr->numComponents = 0;      tokenPtr->numComponents = 0;
1927      level = 1;      level = 1;
1928      while (1) {      while (1) {
1929          while (CHAR_TYPE(*src) == TYPE_NORMAL) {          while (CHAR_TYPE(*src) == TYPE_NORMAL) {
1930              src++;              src++;
1931          }          }
1932          if (*src == '}') {          if (*src == '}') {
1933              level--;              level--;
1934              if (level == 0) {              if (level == 0) {
1935                  break;                  break;
1936              }              }
1937              src++;              src++;
1938          } else if (*src == '{') {          } else if (*src == '{') {
1939              level++;              level++;
1940              src++;              src++;
1941          } else if (*src == '\\') {          } else if (*src == '\\') {
1942              Tcl_UtfBackslash(src, &length, utfBytes);              Tcl_UtfBackslash(src, &length, utfBytes);
1943              if (src[1] == '\n') {              if (src[1] == '\n') {
1944                  /*                  /*
1945                   * A backslash-newline sequence must be collapsed, even                   * A backslash-newline sequence must be collapsed, even
1946                   * inside braces, so we have to split the word into                   * inside braces, so we have to split the word into
1947                   * multiple tokens so that the backslash-newline can be                   * multiple tokens so that the backslash-newline can be
1948                   * represented explicitly.                   * represented explicitly.
1949                   */                   */
1950                                    
1951                  if ((src + 2) == end) {                  if ((src + 2) == end) {
1952                      parsePtr->incomplete = 1;                      parsePtr->incomplete = 1;
1953                  }                  }
1954                  tokenPtr->size = (src - tokenPtr->start);                  tokenPtr->size = (src - tokenPtr->start);
1955                  if (tokenPtr->size != 0) {                  if (tokenPtr->size != 0) {
1956                      parsePtr->numTokens++;                      parsePtr->numTokens++;
1957                  }                  }
1958                  if ((parsePtr->numTokens+1) >= parsePtr->tokensAvailable) {                  if ((parsePtr->numTokens+1) >= parsePtr->tokensAvailable) {
1959                      TclExpandTokenArray(parsePtr);                      TclExpandTokenArray(parsePtr);
1960                  }                  }
1961                  tokenPtr = &parsePtr->tokenPtr[parsePtr->numTokens];                  tokenPtr = &parsePtr->tokenPtr[parsePtr->numTokens];
1962                  tokenPtr->type = TCL_TOKEN_BS;                  tokenPtr->type = TCL_TOKEN_BS;
1963                  tokenPtr->start = src;                  tokenPtr->start = src;
1964                  tokenPtr->size = length;                  tokenPtr->size = length;
1965                  tokenPtr->numComponents = 0;                  tokenPtr->numComponents = 0;
1966                  parsePtr->numTokens++;                  parsePtr->numTokens++;
1967                                    
1968                  src += length;                  src += length;
1969                  tokenPtr++;                  tokenPtr++;
1970                  tokenPtr->type = TCL_TOKEN_TEXT;                  tokenPtr->type = TCL_TOKEN_TEXT;
1971                  tokenPtr->start = src;                  tokenPtr->start = src;
1972                  tokenPtr->numComponents = 0;                  tokenPtr->numComponents = 0;
1973              } else {              } else {
1974                  src += length;                  src += length;
1975              }              }
1976          } else if (src == end) {          } else if (src == end) {
1977              int openBrace;              int openBrace;
1978    
1979              if (interp != NULL) {              if (interp != NULL) {
1980                  Tcl_SetResult(interp, "missing close-brace", TCL_STATIC);                  Tcl_SetResult(interp, "missing close-brace", TCL_STATIC);
1981              }              }
1982              /*              /*
1983               *  Search the source string for a possible open               *  Search the source string for a possible open
1984               *  brace within the context of a comment.  Since we               *  brace within the context of a comment.  Since we
1985               *  aren't performing a full Tcl parse, just look for               *  aren't performing a full Tcl parse, just look for
1986               *  an open brace preceeded by a '<whitspace>#' on               *  an open brace preceeded by a '<whitspace>#' on
1987               *  the same line.               *  the same line.
1988               */               */
1989              openBrace = 0;              openBrace = 0;
1990              while (src > string ) {              while (src > string ) {
1991                  switch (*src) {                  switch (*src) {
1992                      case '{':                      case '{':
1993                          openBrace = 1;                          openBrace = 1;
1994                          break;                          break;
1995                      case '\n':                      case '\n':
1996                          openBrace = 0;                          openBrace = 0;
1997                          break;                          break;
1998                      case '#':                      case '#':
1999                          if ((openBrace == 1) && (isspace(UCHAR(src[-1])))) {                          if ((openBrace == 1) && (isspace(UCHAR(src[-1])))) {
2000                              if (interp != NULL) {                              if (interp != NULL) {
2001                                  Tcl_AppendResult(interp,                                  Tcl_AppendResult(interp,
2002                                          ": possible unbalanced brace in comment",                                          ": possible unbalanced brace in comment",
2003                                          (char *) NULL);                                          (char *) NULL);
2004                              }                              }
2005                              openBrace = -1;                              openBrace = -1;
2006                              break;                              break;
2007                          }                          }
2008                          break;                          break;
2009                  }                  }
2010                  if (openBrace == -1) {                  if (openBrace == -1) {
2011                      break;                      break;
2012                  }                  }
2013                  src--;                  src--;
2014              }              }
2015              parsePtr->errorType = TCL_PARSE_MISSING_BRACE;              parsePtr->errorType = TCL_PARSE_MISSING_BRACE;
2016              parsePtr->term = string;              parsePtr->term = string;
2017              parsePtr->incomplete = 1;              parsePtr->incomplete = 1;
2018              goto error;              goto error;
2019          } else {          } else {
2020              src++;              src++;
2021          }          }
2022      }      }
2023    
2024      /*      /*
2025       * Decide if we need to finish emitting a partially-finished token.       * Decide if we need to finish emitting a partially-finished token.
2026       * There are 3 cases:       * There are 3 cases:
2027       *     {abc \newline xyz} or {xyz}  - finish emitting "xyz" token       *     {abc \newline xyz} or {xyz}  - finish emitting "xyz" token
2028       *     {abc \newline}               - don't emit token after \newline       *     {abc \newline}               - don't emit token after \newline
2029       *     {}                           - finish emitting zero-sized token       *     {}                           - finish emitting zero-sized token
2030       * The last case ensures that there is a token (even if empty) that       * The last case ensures that there is a token (even if empty) that
2031       * describes the braced string.       * describes the braced string.
2032       */       */
2033            
2034      if ((src != tokenPtr->start)      if ((src != tokenPtr->start)
2035              || (parsePtr->numTokens == startIndex)) {              || (parsePtr->numTokens == startIndex)) {
2036          tokenPtr->size = (src - tokenPtr->start);          tokenPtr->size = (src - tokenPtr->start);
2037          parsePtr->numTokens++;          parsePtr->numTokens++;
2038      }      }
2039      if (termPtr != NULL) {      if (termPtr != NULL) {
2040          *termPtr = src+1;          *termPtr = src+1;
2041      }      }
2042      return TCL_OK;      return TCL_OK;
2043    
2044      error:      error:
2045      Tcl_FreeParse(parsePtr);      Tcl_FreeParse(parsePtr);
2046      return TCL_ERROR;      return TCL_ERROR;
2047  }  }
2048    
2049  /*  /*
2050   *----------------------------------------------------------------------   *----------------------------------------------------------------------
2051   *   *
2052   * Tcl_ParseQuotedString --   * Tcl_ParseQuotedString --
2053   *   *
2054   *      Given a double-quoted string such as a quoted Tcl command argument   *      Given a double-quoted string such as a quoted Tcl command argument
2055   *      or a quoted value in a Tcl expression, this procedure parses the   *      or a quoted value in a Tcl expression, this procedure parses the
2056   *      string and returns information about the parse.   *      string and returns information about the parse.
2057   *   *
2058   * Results:   * Results:
2059   *      The return value is TCL_OK if the string was parsed successfully and   *      The return value is TCL_OK if the string was parsed successfully and
2060   *      TCL_ERROR otherwise. If an error occurs and interp isn't NULL then   *      TCL_ERROR otherwise. If an error occurs and interp isn't NULL then
2061   *      an error message is left in its result. On a successful return,   *      an error message is left in its result. On a successful return,
2062   *      tokenPtr and numTokens fields of parsePtr are filled in with   *      tokenPtr and numTokens fields of parsePtr are filled in with
2063   *      information about the string that was parsed. Other fields in   *      information about the string that was parsed. Other fields in
2064   *      parsePtr are undefined. termPtr is set to point to the character   *      parsePtr are undefined. termPtr is set to point to the character
2065   *      just after the quoted string's terminating close-quote.   *      just after the quoted string's terminating close-quote.
2066   *   *
2067   * Side effects:   * Side effects:
2068   *      If there is insufficient space in parsePtr to hold all the   *      If there is insufficient space in parsePtr to hold all the
2069   *      information about the command, then additional space is   *      information about the command, then additional space is
2070   *      malloc-ed. If the procedure returns TCL_OK then the caller must   *      malloc-ed. If the procedure returns TCL_OK then the caller must
2071   *      eventually invoke Tcl_FreeParse to release any additional space   *      eventually invoke Tcl_FreeParse to release any additional space
2072   *      that was allocated.   *      that was allocated.
2073   *   *
2074   *----------------------------------------------------------------------   *----------------------------------------------------------------------
2075   */   */
2076    
2077  int  int
2078  Tcl_ParseQuotedString(interp, string, numBytes, parsePtr, append, termPtr)  Tcl_ParseQuotedString(interp, string, numBytes, parsePtr, append, termPtr)
2079      Tcl_Interp *interp;         /* Interpreter to use for error reporting;      Tcl_Interp *interp;         /* Interpreter to use for error reporting;
2080                                   * if NULL, then no error message is                                   * if NULL, then no error message is
2081                                   * provided. */                                   * provided. */
2082      char *string;               /* String containing the quoted string.      char *string;               /* String containing the quoted string.
2083                                   * The first character must be '"'. */                                   * The first character must be '"'. */
2084      int numBytes;               /* Total number of bytes in string. If < 0,      int numBytes;               /* Total number of bytes in string. If < 0,
2085                                   * the string consists of all bytes up to                                   * the string consists of all bytes up to
2086                                   * the first null character. */                                   * the first null character. */
2087      register Tcl_Parse *parsePtr;      register Tcl_Parse *parsePtr;
2088                                  /* Structure to fill in with information                                  /* Structure to fill in with information
2089                                   * about the string. */                                   * about the string. */
2090      int append;                 /* Non-zero means append tokens to existing      int append;                 /* Non-zero means append tokens to existing
2091                                   * information in parsePtr; zero means                                   * information in parsePtr; zero means
2092                                   * ignore existing tokens in parsePtr and                                   * ignore existing tokens in parsePtr and
2093                                   * reinitialize it. */                                   * reinitialize it. */
2094      char **termPtr;             /* If non-NULL, points to word in which to      char **termPtr;             /* If non-NULL, points to word in which to
2095                                   * store a pointer to the character just                                   * store a pointer to the character just
2096                                   * after the quoted string's terminating                                   * after the quoted string's terminating
2097                                   * close-quote if the parse succeeds. */                                   * close-quote if the parse succeeds. */
2098  {  {
2099      char *end;      char *end;
2100            
2101      if ((numBytes >= 0) || (string == NULL)) {      if ((numBytes >= 0) || (string == NULL)) {
2102          end = string + numBytes;          end = string + numBytes;
2103      } else {      } else {
2104          end = string + strlen(string);          end = string + strlen(string);
2105      }      }
2106            
2107      if (!append) {      if (!append) {
2108          parsePtr->numWords = 0;          parsePtr->numWords = 0;
2109          parsePtr->tokenPtr = parsePtr->staticTokens;          parsePtr->tokenPtr = parsePtr->staticTokens;
2110          parsePtr->numTokens = 0;          parsePtr->numTokens = 0;
2111          parsePtr->tokensAvailable = NUM_STATIC_TOKENS;          parsePtr->tokensAvailable = NUM_STATIC_TOKENS;
2112          parsePtr->string = string;          parsePtr->string = string;
2113          parsePtr->end = end;          parsePtr->end = end;
2114          parsePtr->interp = interp;          parsePtr->interp = interp;
2115          parsePtr->errorType = TCL_PARSE_SUCCESS;          parsePtr->errorType = TCL_PARSE_SUCCESS;
2116      }      }
2117            
2118      if (ParseTokens(string+1, TYPE_QUOTE, parsePtr) != TCL_OK) {      if (ParseTokens(string+1, TYPE_QUOTE, parsePtr) != TCL_OK) {
2119          goto error;          goto error;
2120      }      }
2121      if (*parsePtr->term != '"') {      if (*parsePtr->term != '"') {
2122          if (interp != NULL) {          if (interp != NULL) {
2123              Tcl_SetResult(parsePtr->interp, "missing \"", TCL_STATIC);              Tcl_SetResult(parsePtr->interp, "missing \"", TCL_STATIC);
2124          }          }
2125          parsePtr->errorType = TCL_PARSE_MISSING_QUOTE;          parsePtr->errorType = TCL_PARSE_MISSING_QUOTE;
2126          parsePtr->term = string;          parsePtr->term = string;
2127          parsePtr->incomplete = 1;          parsePtr->incomplete = 1;
2128          goto error;          goto error;
2129      }      }
2130      if (termPtr != NULL) {      if (termPtr != NULL) {
2131          *termPtr = (parsePtr->term + 1);          *termPtr = (parsePtr->term + 1);
2132      }      }
2133      return TCL_OK;      return TCL_OK;
2134    
2135      error:      error:
2136      Tcl_FreeParse(parsePtr);      Tcl_FreeParse(parsePtr);
2137      return TCL_ERROR;      return TCL_ERROR;
2138  }  }
2139    
2140  /*  /*
2141   *----------------------------------------------------------------------   *----------------------------------------------------------------------
2142   *   *
2143   * CommandComplete --   * CommandComplete --
2144   *   *
2145   *      This procedure is shared by TclCommandComplete and   *      This procedure is shared by TclCommandComplete and
2146   *      Tcl_ObjCommandcoComplete; it does all the real work of seeing   *      Tcl_ObjCommandcoComplete; it does all the real work of seeing
2147   *      whether a script is complete   *      whether a script is complete
2148   *   *
2149   * Results:   * Results:
2150   *      1 is returned if the script is complete, 0 if there are open   *      1 is returned if the script is complete, 0 if there are open
2151   *      delimiters such as " or (. 1 is also returned if there is a   *      delimiters such as " or (. 1 is also returned if there is a
2152   *      parse error in the script other than unmatched delimiters.   *      parse error in the script other than unmatched delimiters.
2153   *   *
2154   * Side effects:   * Side effects:
2155   *      None.   *      None.
2156   *   *
2157   *----------------------------------------------------------------------   *----------------------------------------------------------------------
2158   */   */
2159    
2160  static int  static int
2161  CommandComplete(script, length)  CommandComplete(script, length)
2162      char *script;                       /* Script to check. */      char *script;                       /* Script to check. */
2163      int length;                         /* Number of bytes in script. */      int length;                         /* Number of bytes in script. */
2164  {  {
2165      Tcl_Parse parse;      Tcl_Parse parse;
2166      char *p, *end;      char *p, *end;
2167      int result;      int result;
2168    
2169      p = script;      p = script;
2170      end = p + length;      end = p + length;
2171      while (Tcl_ParseCommand((Tcl_Interp *) NULL, p, end - p, 0, &parse)      while (Tcl_ParseCommand((Tcl_Interp *) NULL, p, end - p, 0, &parse)
2172              == TCL_OK) {              == TCL_OK) {
2173          p = parse.commandStart + parse.commandSize;          p = parse.commandStart + parse.commandSize;
2174          if (*p == 0) {          if (*p == 0) {
2175              break;              break;
2176          }          }
2177          Tcl_FreeParse(&parse);          Tcl_FreeParse(&parse);
2178      }      }
2179      if (parse.incomplete) {      if (parse.incomplete) {
2180          result = 0;          result = 0;
2181      } else {      } else {
2182          result = 1;          result = 1;
2183      }      }
2184      Tcl_FreeParse(&parse);      Tcl_FreeParse(&parse);
2185      return result;      return result;
2186  }  }
2187    
2188  /*  /*
2189   *----------------------------------------------------------------------   *----------------------------------------------------------------------
2190   *   *
2191   * Tcl_CommandComplete --   * Tcl_CommandComplete --
2192   *   *
2193   *      Given a partial or complete Tcl script, this procedure   *      Given a partial or complete Tcl script, this procedure
2194   *      determines whether the script is complete in the sense   *      determines whether the script is complete in the sense
2195   *      of having matched braces and quotes and brackets.   *      of having matched braces and quotes and brackets.
2196   *   *
2197   * Results:   * Results:
2198   *      1 is returned if the script is complete, 0 otherwise.   *      1 is returned if the script is complete, 0 otherwise.
2199   *      1 is also returned if there is a parse error in the script   *      1 is also returned if there is a parse error in the script
2200   *      other than unmatched delimiters.   *      other than unmatched delimiters.
2201   *   *
2202   * Side effects:   * Side effects:
2203   *      None.   *      None.
2204   *   *
2205   *----------------------------------------------------------------------   *----------------------------------------------------------------------
2206   */   */
2207    
2208  int  int
2209  Tcl_CommandComplete(script)  Tcl_CommandComplete(script)
2210      char *script;                       /* Script to check. */      char *script;                       /* Script to check. */
2211  {  {
2212      return CommandComplete(script, (int) strlen(script));      return CommandComplete(script, (int) strlen(script));
2213  }  }
2214    
2215  /*  /*
2216   *----------------------------------------------------------------------   *----------------------------------------------------------------------
2217   *   *
2218   * TclObjCommandComplete --   * TclObjCommandComplete --
2219   *   *
2220   *      Given a partial or complete Tcl command in a Tcl object, this   *      Given a partial or complete Tcl command in a Tcl object, this
2221   *      procedure determines whether the command is complete in the sense of   *      procedure determines whether the command is complete in the sense of
2222   *      having matched braces and quotes and brackets.   *      having matched braces and quotes and brackets.
2223   *   *
2224   * Results:   * Results:
2225   *      1 is returned if the command is complete, 0 otherwise.   *      1 is returned if the command is complete, 0 otherwise.
2226   *   *
2227   * Side effects:   * Side effects:
2228   *      None.   *      None.
2229   *   *
2230   *----------------------------------------------------------------------   *----------------------------------------------------------------------
2231   */   */
2232    
2233  int  int
2234  TclObjCommandComplete(objPtr)  TclObjCommandComplete(objPtr)
2235      Tcl_Obj *objPtr;                    /* Points to object holding script      Tcl_Obj *objPtr;                    /* Points to object holding script
2236                                           * to check. */                                           * to check. */
2237  {  {
2238      char *script;      char *script;
2239      int length;      int length;
2240    
2241      script = Tcl_GetStringFromObj(objPtr, &length);      script = Tcl_GetStringFromObj(objPtr, &length);
2242      return CommandComplete(script, length);      return CommandComplete(script, length);
2243  }  }
2244    
2245  /*  /*
2246   *----------------------------------------------------------------------   *----------------------------------------------------------------------
2247   *   *
2248   * TclIsLocalScalar --   * TclIsLocalScalar --
2249   *   *
2250   *      Check to see if a given string is a legal scalar variable   *      Check to see if a given string is a legal scalar variable
2251   *      name with no namespace qualifiers or substitutions.   *      name with no namespace qualifiers or substitutions.
2252   *   *
2253   * Results:   * Results:
2254   *      Returns 1 if the variable is a local scalar.   *      Returns 1 if the variable is a local scalar.
2255   *   *
2256   * Side effects:   * Side effects:
2257   *      None.   *      None.
2258   *   *
2259   *----------------------------------------------------------------------   *----------------------------------------------------------------------
2260   */   */
2261    
2262  int  int
2263  TclIsLocalScalar(src, len)  TclIsLocalScalar(src, len)
2264      CONST char *src;      CONST char *src;
2265      int len;      int len;
2266  {  {
2267      CONST char *p;      CONST char *p;
2268      CONST char *lastChar = src + (len - 1);      CONST char *lastChar = src + (len - 1);
2269    
2270      for (p = src; p <= lastChar; p++) {      for (p = src; p <= lastChar; p++) {
2271          if ((CHAR_TYPE(*p) != TYPE_NORMAL) &&          if ((CHAR_TYPE(*p) != TYPE_NORMAL) &&
2272                  (CHAR_TYPE(*p) != TYPE_COMMAND_END)) {                  (CHAR_TYPE(*p) != TYPE_COMMAND_END)) {
2273              /*              /*
2274               * TCL_COMMAND_END is returned for the last character               * TCL_COMMAND_END is returned for the last character
2275               * of the string.  By this point we know it isn't               * of the string.  By this point we know it isn't
2276               * an array or namespace reference.               * an array or namespace reference.
2277               */               */
2278    
2279              return 0;              return 0;
2280          }          }
2281          if  (*p == '(') {          if  (*p == '(') {
2282              if (*lastChar == ')') { /* we have an array element */              if (*lastChar == ')') { /* we have an array element */
2283                  return 0;                  return 0;
2284              }              }
2285          } else if (*p == ':') {          } else if (*p == ':') {
2286              if ((p != lastChar) && *(p+1) == ':') { /* qualified name */              if ((p != lastChar) && *(p+1) == ':') { /* qualified name */
2287                  return 0;                  return 0;
2288              }              }
2289          }          }
2290      }      }
2291                    
2292      return 1;      return 1;
2293  }  }
2294    
2295  /* End of tclparse.c */  /* End of tclparse.c */

Legend:
Removed from v.66  
changed lines
  Added in v.71

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25