os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/generic/tclParse.c
First public contribution.
4 * This file contains procedures that parse Tcl scripts. They
5 * do so in a general-purpose fashion that can be used for many
6 * different purposes, including compilation, direct execution,
9 * Copyright (c) 1997 Sun Microsystems, Inc.
10 * Copyright (c) 1998-2000 Ajuba Solutions.
11 * Portions Copyright (c) 2007-2008 Nokia Corporation and/or its subsidiaries. All rights reserved.
12 * Contributions from Don Porter, NIST, 2002. (not subject to US copyright)
14 * See the file "license.terms" for information on usage and redistribution
15 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
17 * RCS: @(#) $Id: tclParse.c,v 1.25.2.1 2006/09/24 21:15:10 msofer Exp $
24 * The following table provides parsing information about each possible
25 * 8-bit character. The table is designed to be referenced with either
26 * signed or unsigned characters, so it has 384 entries. The first 128
27 * entries correspond to negative character values, the next 256 correspond
28 * to positive character values. The last 128 entries are identical to the
29 * first 128. The table is always indexed with a 128-byte offset (the 128th
30 * entry corresponds to a character value of 0).
32 * The macro CHAR_TYPE is used to index into the table and return
33 * information about its character argument. The following return
36 * TYPE_NORMAL - All characters that don't have special significance
38 * TYPE_SPACE - The character is a whitespace character other
40 * TYPE_COMMAND_END - Character is newline or semicolon.
41 * TYPE_SUBS - Character begins a substitution or has other
42 * special meaning in ParseTokens: backslash, dollar
43 * sign, or open bracket.
44 * TYPE_QUOTE - Character is a double quote.
45 * TYPE_CLOSE_PAREN - Character is a right parenthesis.
46 * TYPE_CLOSE_BRACK - Character is a right square bracket.
47 * TYPE_BRACE - Character is a curly brace (either left or right).
51 #define TYPE_SPACE 0x1
52 #define TYPE_COMMAND_END 0x2
54 #define TYPE_QUOTE 0x8
55 #define TYPE_CLOSE_PAREN 0x10
56 #define TYPE_CLOSE_BRACK 0x20
57 #define TYPE_BRACE 0x40
59 #define CHAR_TYPE(c) (charTypeTable+128)[(int)(c)]
61 static CONST char charTypeTable[] = {
63 * Negative character values, from -128 to -1:
66 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
67 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
68 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
69 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
70 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
71 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
72 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
73 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
74 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
75 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
76 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
77 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
78 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
79 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
80 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
81 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
82 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
83 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
84 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
85 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
86 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
87 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
88 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
89 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
90 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
91 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
92 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
93 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
94 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
95 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
96 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
97 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
100 * Positive character values, from 0-127:
103 TYPE_SUBS, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
104 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
105 TYPE_NORMAL, TYPE_SPACE, TYPE_COMMAND_END, TYPE_SPACE,
106 TYPE_SPACE, TYPE_SPACE, TYPE_NORMAL, TYPE_NORMAL,
107 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
108 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
109 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
110 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
111 TYPE_SPACE, TYPE_NORMAL, TYPE_QUOTE, TYPE_NORMAL,
112 TYPE_SUBS, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
113 TYPE_NORMAL, TYPE_CLOSE_PAREN, TYPE_NORMAL, TYPE_NORMAL,
114 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
115 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
116 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
117 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_COMMAND_END,
118 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
119 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
120 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
121 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
122 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
123 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
124 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
125 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_SUBS,
126 TYPE_SUBS, TYPE_CLOSE_BRACK, TYPE_NORMAL, TYPE_NORMAL,
127 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
128 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
129 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
130 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
131 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
132 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
133 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_BRACE,
134 TYPE_NORMAL, TYPE_BRACE, TYPE_NORMAL, TYPE_NORMAL,
137 * Large unsigned character values, from 128-255:
140 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
141 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
142 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
143 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
144 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
145 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
146 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
147 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
148 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
149 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
150 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
151 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
152 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
153 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
154 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
155 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
156 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
157 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
158 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
159 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
160 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
161 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
162 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
163 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
164 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
165 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
166 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
167 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
168 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
169 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
170 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
171 TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL,
175 * Prototypes for local procedures defined in this file:
178 static int CommandComplete _ANSI_ARGS_((CONST char *script,
180 static int ParseComment _ANSI_ARGS_((CONST char *src, int numBytes,
181 Tcl_Parse *parsePtr));
182 static int ParseTokens _ANSI_ARGS_((CONST char *src, int numBytes,
183 int mask, Tcl_Parse *parsePtr));
186 *----------------------------------------------------------------------
188 * Tcl_ParseCommand --
190 * Given a string, this procedure parses the first Tcl command
191 * in the string and returns information about the structure of
195 * The return value is TCL_OK if the command was parsed
196 * successfully and TCL_ERROR otherwise. If an error occurs
197 * and interp isn't NULL then an error message is left in
198 * its result. On a successful return, parsePtr is filled in
199 * with information about the command that was parsed.
202 * If there is insufficient space in parsePtr to hold all the
203 * information about the command, then additional space is
204 * malloc-ed. If the procedure returns TCL_OK then the caller must
205 * eventually invoke Tcl_FreeParse to release any additional space
206 * that was allocated.
208 *----------------------------------------------------------------------
212 Tcl_ParseCommand(interp, string, numBytes, nested, parsePtr)
213 Tcl_Interp *interp; /* Interpreter to use for error reporting;
214 * if NULL, then no error message is
216 CONST char *string; /* First character of string containing
217 * one or more Tcl commands. */
218 register int numBytes; /* Total number of bytes in string. If < 0,
219 * the script consists of all bytes up to
220 * the first null character. */
221 int nested; /* Non-zero means this is a nested command:
222 * close bracket should be considered
223 * a command terminator. If zero, then close
224 * bracket has no special meaning. */
225 register Tcl_Parse *parsePtr;
226 /* Structure to fill in with information
227 * about the parsed command; any previous
228 * information in the structure is
231 register CONST char *src; /* Points to current character
233 char type; /* Result returned by CHAR_TYPE(*src). */
234 Tcl_Token *tokenPtr; /* Pointer to token being filled in. */
235 int wordIndex; /* Index of word token for current word. */
236 int terminators; /* CHAR_TYPE bits that indicate the end
238 CONST char *termPtr; /* Set by Tcl_ParseBraces/QuotedString to
239 * point to char after terminating one. */
242 if ((string == NULL) && (numBytes!=0)) {
243 if (interp != NULL) {
244 Tcl_SetResult(interp, "can't parse a NULL pointer", TCL_STATIC);
249 numBytes = strlen(string);
251 parsePtr->commentStart = NULL;
252 parsePtr->commentSize = 0;
253 parsePtr->commandStart = NULL;
254 parsePtr->commandSize = 0;
255 parsePtr->numWords = 0;
256 parsePtr->tokenPtr = parsePtr->staticTokens;
257 parsePtr->numTokens = 0;
258 parsePtr->tokensAvailable = NUM_STATIC_TOKENS;
259 parsePtr->string = string;
260 parsePtr->end = string + numBytes;
261 parsePtr->term = parsePtr->end;
262 parsePtr->interp = interp;
263 parsePtr->incomplete = 0;
264 parsePtr->errorType = TCL_PARSE_SUCCESS;
266 terminators = TYPE_COMMAND_END | TYPE_CLOSE_BRACK;
268 terminators = TYPE_COMMAND_END;
272 * Parse any leading space and comments before the first word of the
276 scanned = ParseComment(string, numBytes, parsePtr);
277 src = (string + scanned); numBytes -= scanned;
280 parsePtr->incomplete = nested;
285 * The following loop parses the words of the command, one word
286 * in each iteration through the loop.
289 parsePtr->commandStart = src;
292 * Create the token for the word.
295 if (parsePtr->numTokens == parsePtr->tokensAvailable) {
296 TclExpandTokenArray(parsePtr);
298 wordIndex = parsePtr->numTokens;
299 tokenPtr = &parsePtr->tokenPtr[wordIndex];
300 tokenPtr->type = TCL_TOKEN_WORD;
303 * Skip white space before the word. Also skip a backslash-newline
304 * sequence: it should be treated just like white space.
307 scanned = TclParseWhiteSpace(src, numBytes, parsePtr, &type);
308 src += scanned; numBytes -= scanned;
310 parsePtr->term = src;
313 if ((type & terminators) != 0) {
314 parsePtr->term = src;
318 tokenPtr->start = src;
319 parsePtr->numTokens++;
320 parsePtr->numWords++;
323 * At this point the word can have one of three forms: something
324 * enclosed in quotes, something enclosed in braces, or an
325 * unquoted word (anything else).
329 if (Tcl_ParseQuotedString(interp, src, numBytes,
330 parsePtr, 1, &termPtr) != TCL_OK) {
333 src = termPtr; numBytes = parsePtr->end - src;
334 } else if (*src == '{') {
335 if (Tcl_ParseBraces(interp, src, numBytes,
336 parsePtr, 1, &termPtr) != TCL_OK) {
339 src = termPtr; numBytes = parsePtr->end - src;
342 * This is an unquoted word. Call ParseTokens and let it do
346 if (ParseTokens(src, numBytes, TYPE_SPACE|terminators,
347 parsePtr) != TCL_OK) {
350 src = parsePtr->term; numBytes = parsePtr->end - src;
354 * Finish filling in the token for the word and check for the
355 * special case of a word consisting of a single range of
359 tokenPtr = &parsePtr->tokenPtr[wordIndex];
360 tokenPtr->size = src - tokenPtr->start;
361 tokenPtr->numComponents = parsePtr->numTokens - (wordIndex + 1);
362 if ((tokenPtr->numComponents == 1)
363 && (tokenPtr[1].type == TCL_TOKEN_TEXT)) {
364 tokenPtr->type = TCL_TOKEN_SIMPLE_WORD;
368 * Do two additional checks: (a) make sure we're really at the
369 * end of a word (there might have been garbage left after a
370 * quoted or braced word), and (b) check for the end of the
374 scanned = TclParseWhiteSpace(src, numBytes, parsePtr, &type);
376 src += scanned; numBytes -= scanned;
381 parsePtr->term = src;
384 if ((type & terminators) != 0) {
385 parsePtr->term = src;
389 if (src[-1] == '"') {
390 if (interp != NULL) {
391 Tcl_SetResult(interp, "extra characters after close-quote",
394 parsePtr->errorType = TCL_PARSE_QUOTE_EXTRA;
396 if (interp != NULL) {
397 Tcl_SetResult(interp, "extra characters after close-brace",
400 parsePtr->errorType = TCL_PARSE_BRACE_EXTRA;
402 parsePtr->term = src;
406 parsePtr->commandSize = src - parsePtr->commandStart;
410 Tcl_FreeParse(parsePtr);
411 if (parsePtr->commandStart == NULL) {
412 parsePtr->commandStart = string;
414 parsePtr->commandSize = parsePtr->end - parsePtr->commandStart;
419 *----------------------------------------------------------------------
421 * TclParseWhiteSpace --
423 * Scans up to numBytes bytes starting at src, consuming white
424 * space as defined by Tcl's parsing rules.
427 * Returns the number of bytes recognized as white space. Records
428 * at parsePtr, information about the parse. Records at typePtr
429 * the character type of the non-whitespace character that terminated
435 *----------------------------------------------------------------------
438 TclParseWhiteSpace(src, numBytes, parsePtr, typePtr)
439 CONST char *src; /* First character to parse. */
440 register int numBytes; /* Max number of bytes to scan. */
441 Tcl_Parse *parsePtr; /* Information about parse in progress.
442 * Updated if parsing indicates
443 * an incomplete command. */
444 char *typePtr; /* Points to location to store character
445 * type of character that ends run
448 register char type = TYPE_NORMAL;
449 register CONST char *p = src;
452 while (numBytes && ((type = CHAR_TYPE(*p)) & TYPE_SPACE)) {
455 if (numBytes && (type & TYPE_SUBS)) {
459 if (--numBytes == 0) {
466 if (--numBytes == 0) {
467 parsePtr->incomplete = 1;
479 *----------------------------------------------------------------------
483 * Scans a hexadecimal number as a Tcl_UniChar value.
484 * (e.g., for parsing \x and \u escape sequences).
485 * At most numBytes bytes are scanned.
488 * The numeric value is stored in *resultPtr.
489 * Returns the number of bytes consumed.
492 * Relies on the following properties of the ASCII
493 * character set, with which UTF-8 is compatible:
495 * The digits '0' .. '9' and the letters 'A' .. 'Z' and 'a' .. 'z'
496 * occupy consecutive code points, and '0' < 'A' < 'a'.
498 *----------------------------------------------------------------------
501 TclParseHex(src, numBytes, resultPtr)
502 CONST char *src; /* First character to parse. */
503 int numBytes; /* Max number of byes to scan */
504 Tcl_UniChar *resultPtr; /* Points to storage provided by
505 * caller where the Tcl_UniChar
506 * resulting from the conversion is
509 Tcl_UniChar result = 0;
510 register CONST char *p = src;
513 unsigned char digit = UCHAR(*p);
515 if (!isxdigit(digit))
522 result |= (10 + digit - 'a');
523 } else if (digit >= 'A') {
524 result |= (10 + digit - 'A');
526 result |= (digit - '0');
535 *----------------------------------------------------------------------
537 * TclParseBackslash --
539 * Scans up to numBytes bytes starting at src, consuming a
540 * backslash sequence as defined by Tcl's parsing rules.
543 * Records at readPtr the number of bytes making up the backslash
544 * sequence. Records at dst the UTF-8 encoded equivalent of
545 * that backslash sequence. Returns the number of bytes written
546 * to dst, at most TCL_UTF_MAX. Either readPtr or dst may be
547 * NULL, if the results are not needed, but the return value is
548 * the same either way.
553 *----------------------------------------------------------------------
556 TclParseBackslash(src, numBytes, readPtr, dst)
557 CONST char * src; /* Points to the backslash character of a
558 * a backslash sequence */
559 int numBytes; /* Max number of bytes to scan */
560 int *readPtr; /* NULL, or points to storage where the
561 * number of bytes scanned should be written. */
562 char *dst; /* NULL, or points to buffer where the UTF-8
563 * encoding of the backslash sequence is to be
564 * written. At most TCL_UTF_MAX bytes will be
567 register CONST char *p = src+1;
570 char buf[TCL_UTF_MAX];
573 if (readPtr != NULL) {
584 /* Can only scan the backslash. Return it. */
593 * Note: in the conversions below, use absolute values (e.g.,
594 * 0xa) rather than symbolic values (e.g. \n) that get converted
595 * by the compiler. It's possible that compilers on some
596 * platforms will do the symbolic conversions differently, which
597 * could result in non-portable Tcl scripts.
622 count += TclParseHex(p+1, numBytes-1, &result);
624 /* No hexadigits -> This is just "x". */
627 /* Keep only the last byte (2 hex digits) */
628 result = (unsigned char) result;
632 count += TclParseHex(p+1, (numBytes > 5) ? 4 : numBytes-1, &result);
634 /* No hexadigits -> This is just "u". */
642 } while ((count < numBytes) && ((*p == ' ') || (*p == '\t')));
651 * Check for an octal number \oo?o?
653 if (isdigit(UCHAR(*p)) && (UCHAR(*p) < '8')) { /* INTL: digit */
654 result = (unsigned char)(*p - '0');
656 if ((numBytes == 2) || !isdigit(UCHAR(*p)) /* INTL: digit */
657 || (UCHAR(*p) >= '8')) {
661 result = (unsigned char)((result << 3) + (*p - '0'));
663 if ((numBytes == 3) || !isdigit(UCHAR(*p)) /* INTL: digit */
664 || (UCHAR(*p) >= '8')) {
668 result = (unsigned char)((result << 3) + (*p - '0'));
672 * We have to convert here in case the user has put a
673 * backslash in front of a multi-byte utf-8 character.
674 * While this means nothing special, we shouldn't break up
675 * a correct utf-8 character. [Bug #217987] test subst-3.2
677 if (Tcl_UtfCharComplete(p, numBytes - 1)) {
678 count = Tcl_UtfToUniChar(p, &result) + 1; /* +1 for '\' */
680 char utfBytes[TCL_UTF_MAX];
681 memcpy(utfBytes, p, (size_t) (numBytes - 1));
682 utfBytes[numBytes - 1] = '\0';
683 count = Tcl_UtfToUniChar(utfBytes, &result) + 1;
689 if (readPtr != NULL) {
692 return Tcl_UniCharToUtf((int) result, dst);
696 *----------------------------------------------------------------------
700 * Scans up to numBytes bytes starting at src, consuming a
701 * Tcl comment as defined by Tcl's parsing rules.
704 * Records in parsePtr information about the parse. Returns the
705 * number of bytes consumed.
710 *----------------------------------------------------------------------
713 ParseComment(src, numBytes, parsePtr)
714 CONST char *src; /* First character to parse. */
715 register int numBytes; /* Max number of bytes to scan. */
716 Tcl_Parse *parsePtr; /* Information about parse in progress.
717 * Updated if parsing indicates
718 * an incomplete command. */
720 register CONST char *p = src;
725 scanned = TclParseWhiteSpace(p, numBytes, parsePtr, &type);
726 p += scanned; numBytes -= scanned;
727 } while (numBytes && (*p == '\n') && (p++,numBytes--));
728 if ((numBytes == 0) || (*p != '#')) {
731 if (parsePtr->commentStart == NULL) {
732 parsePtr->commentStart = p;
736 scanned = TclParseWhiteSpace(p, numBytes, parsePtr, &type);
738 p += scanned; numBytes -= scanned;
741 * General backslash substitution in comments isn't
742 * part of the formal spec, but test parse-15.47
743 * and history indicate that it has been the de facto
744 * rule. Don't change it now.
746 TclParseBackslash(p, numBytes, &scanned, NULL);
747 p += scanned; numBytes -= scanned;
756 parsePtr->commentSize = p - parsePtr->commentStart;
762 *----------------------------------------------------------------------
766 * This procedure forms the heart of the Tcl parser. It parses one
767 * or more tokens from a string, up to a termination point
768 * specified by the caller. This procedure is used to parse
769 * unquoted command words (those not in quotes or braces), words in
770 * quotes, and array indices for variables. No more than numBytes
771 * bytes will be scanned.
774 * Tokens are added to parsePtr and parsePtr->term is filled in
775 * with the address of the character that terminated the parse (the
776 * first one whose CHAR_TYPE matched mask or the character at
777 * parsePtr->end). The return value is TCL_OK if the parse
778 * completed successfully and TCL_ERROR otherwise. If a parse
779 * error occurs and parsePtr->interp isn't NULL, then an error
780 * message is left in the interpreter's result.
785 *----------------------------------------------------------------------
789 ParseTokens(src, numBytes, mask, parsePtr)
790 register CONST char *src; /* First character to parse. */
791 register int numBytes; /* Max number of bytes to scan. */
792 int mask; /* Specifies when to stop parsing. The
793 * parse stops at the first unquoted
794 * character whose CHAR_TYPE contains
795 * any of the bits in mask. */
796 Tcl_Parse *parsePtr; /* Information about parse in progress.
797 * Updated with additional tokens and
798 * termination information. */
801 int originalTokens, varToken;
806 * Each iteration through the following loop adds one token of
807 * type TCL_TOKEN_TEXT, TCL_TOKEN_BS, TCL_TOKEN_COMMAND, or
808 * TCL_TOKEN_VARIABLE to parsePtr. For TCL_TOKEN_VARIABLE tokens,
809 * additional tokens are added for the parsed variable name.
812 originalTokens = parsePtr->numTokens;
813 while (numBytes && !((type = CHAR_TYPE(*src)) & mask)) {
814 if (parsePtr->numTokens == parsePtr->tokensAvailable) {
815 TclExpandTokenArray(parsePtr);
817 tokenPtr = &parsePtr->tokenPtr[parsePtr->numTokens];
818 tokenPtr->start = src;
819 tokenPtr->numComponents = 0;
821 if ((type & TYPE_SUBS) == 0) {
823 * This is a simple range of characters. Scan to find the end
827 while ((++src, --numBytes)
828 && !(CHAR_TYPE(*src) & (mask | TYPE_SUBS))) {
831 tokenPtr->type = TCL_TOKEN_TEXT;
832 tokenPtr->size = src - tokenPtr->start;
833 parsePtr->numTokens++;
834 } else if (*src == '$') {
836 * This is a variable reference. Call Tcl_ParseVarName to do
837 * all the dirty work of parsing the name.
840 varToken = parsePtr->numTokens;
841 if (Tcl_ParseVarName(parsePtr->interp, src, numBytes,
842 parsePtr, 1) != TCL_OK) {
845 src += parsePtr->tokenPtr[varToken].size;
846 numBytes -= parsePtr->tokenPtr[varToken].size;
847 } else if (*src == '[') {
849 * Command substitution. Call Tcl_ParseCommand recursively
850 * (and repeatedly) to parse the nested command(s), then
851 * throw away the parse information.
856 if (Tcl_ParseCommand(parsePtr->interp, src,
857 numBytes, 1, &nested) != TCL_OK) {
858 parsePtr->errorType = nested.errorType;
859 parsePtr->term = nested.term;
860 parsePtr->incomplete = nested.incomplete;
863 src = nested.commandStart + nested.commandSize;
864 numBytes = parsePtr->end - src;
867 * This is equivalent to Tcl_FreeParse(&nested), but
868 * presumably inlined here for sake of runtime optimization
871 if (nested.tokenPtr != nested.staticTokens) {
872 ckfree((char *) nested.tokenPtr);
876 * Check for the closing ']' that ends the command
877 * substitution. It must have been the last character of
878 * the parsed command.
881 if ((nested.term < parsePtr->end) && (*nested.term == ']')
882 && !nested.incomplete) {
886 if (parsePtr->interp != NULL) {
887 Tcl_SetResult(parsePtr->interp,
888 "missing close-bracket", TCL_STATIC);
890 parsePtr->errorType = TCL_PARSE_MISSING_BRACKET;
891 parsePtr->term = tokenPtr->start;
892 parsePtr->incomplete = 1;
896 tokenPtr->type = TCL_TOKEN_COMMAND;
897 tokenPtr->size = src - tokenPtr->start;
898 parsePtr->numTokens++;
899 } else if (*src == '\\') {
901 * Backslash substitution.
903 TclParseBackslash(src, numBytes, &tokenPtr->size, NULL);
905 if (tokenPtr->size == 1) {
906 /* Just a backslash, due to end of string */
907 tokenPtr->type = TCL_TOKEN_TEXT;
908 parsePtr->numTokens++;
913 if (src[1] == '\n') {
915 parsePtr->incomplete = 1;
919 * Note: backslash-newline is special in that it is
920 * treated the same as a space character would be. This
921 * means that it could terminate the token.
924 if (mask & TYPE_SPACE) {
925 if (parsePtr->numTokens == originalTokens) {
932 tokenPtr->type = TCL_TOKEN_BS;
933 parsePtr->numTokens++;
934 src += tokenPtr->size;
935 numBytes -= tokenPtr->size;
936 } else if (*src == 0) {
937 tokenPtr->type = TCL_TOKEN_TEXT;
939 parsePtr->numTokens++;
942 panic("ParseTokens encountered unknown character");
945 if (parsePtr->numTokens == originalTokens) {
947 * There was nothing in this range of text. Add an empty token
948 * for the empty range, so that there is always at least one
951 if (parsePtr->numTokens == parsePtr->tokensAvailable) {
952 TclExpandTokenArray(parsePtr);
954 tokenPtr = &parsePtr->tokenPtr[parsePtr->numTokens];
955 tokenPtr->start = src;
956 tokenPtr->numComponents = 0;
959 tokenPtr->type = TCL_TOKEN_TEXT;
961 parsePtr->numTokens++;
963 parsePtr->term = src;
968 *----------------------------------------------------------------------
972 * This procedure is invoked to free any dynamic storage that may
973 * have been allocated by a previous call to Tcl_ParseCommand.
979 * If there is any dynamically allocated memory in *parsePtr,
982 *----------------------------------------------------------------------
986 Tcl_FreeParse(parsePtr)
987 Tcl_Parse *parsePtr; /* Structure that was filled in by a
988 * previous call to Tcl_ParseCommand. */
990 if (parsePtr->tokenPtr != parsePtr->staticTokens) {
991 ckfree((char *) parsePtr->tokenPtr);
992 parsePtr->tokenPtr = parsePtr->staticTokens;
997 *----------------------------------------------------------------------
999 * TclExpandTokenArray --
1001 * This procedure is invoked when the current space for tokens in
1002 * a Tcl_Parse structure fills up; it allocates memory to grow the
1009 * Memory is allocated for a new larger token array; the memory
1010 * for the old array is freed, if it had been dynamically allocated.
1012 *----------------------------------------------------------------------
1016 TclExpandTokenArray(parsePtr)
1017 Tcl_Parse *parsePtr; /* Parse structure whose token space
1018 * has overflowed. */
1023 newCount = parsePtr->tokensAvailable*2;
1024 newPtr = (Tcl_Token *) ckalloc((unsigned) (newCount * sizeof(Tcl_Token)));
1025 memcpy((VOID *) newPtr, (VOID *) parsePtr->tokenPtr,
1026 (size_t) (parsePtr->tokensAvailable * sizeof(Tcl_Token)));
1027 if (parsePtr->tokenPtr != parsePtr->staticTokens) {
1028 ckfree((char *) parsePtr->tokenPtr);
1030 parsePtr->tokenPtr = newPtr;
1031 parsePtr->tokensAvailable = newCount;
1035 *----------------------------------------------------------------------
1037 * Tcl_ParseVarName --
1039 * Given a string starting with a $ sign, parse off a variable
1040 * name and return information about the parse. No more than
1041 * numBytes bytes will be scanned.
1044 * The return value is TCL_OK if the command was parsed
1045 * successfully and TCL_ERROR otherwise. If an error occurs and
1046 * interp isn't NULL then an error message is left in its result.
1047 * On a successful return, tokenPtr and numTokens fields of
1048 * parsePtr are filled in with information about the variable name
1049 * that was parsed. The "size" field of the first new token gives
1050 * the total number of bytes in the variable name. Other fields in
1051 * parsePtr are undefined.
1054 * If there is insufficient space in parsePtr to hold all the
1055 * information about the command, then additional space is
1056 * malloc-ed. If the procedure returns TCL_OK then the caller must
1057 * eventually invoke Tcl_FreeParse to release any additional space
1058 * that was allocated.
1060 *----------------------------------------------------------------------
1064 Tcl_ParseVarName(interp, string, numBytes, parsePtr, append)
1065 Tcl_Interp *interp; /* Interpreter to use for error reporting;
1066 * if NULL, then no error message is
1068 CONST char *string; /* String containing variable name. First
1069 * character must be "$". */
1070 register int numBytes; /* Total number of bytes in string. If < 0,
1071 * the string consists of all bytes up to the
1072 * first null character. */
1073 Tcl_Parse *parsePtr; /* Structure to fill in with information
1074 * about the variable name. */
1075 int append; /* Non-zero means append tokens to existing
1076 * information in parsePtr; zero means ignore
1077 * existing tokens in parsePtr and reinitialize
1080 Tcl_Token *tokenPtr;
1081 register CONST char *src;
1083 int varIndex, offset;
1087 if ((numBytes == 0) || (string == NULL)) {
1091 numBytes = strlen(string);
1095 parsePtr->numWords = 0;
1096 parsePtr->tokenPtr = parsePtr->staticTokens;
1097 parsePtr->numTokens = 0;
1098 parsePtr->tokensAvailable = NUM_STATIC_TOKENS;
1099 parsePtr->string = string;
1100 parsePtr->end = (string + numBytes);
1101 parsePtr->interp = interp;
1102 parsePtr->errorType = TCL_PARSE_SUCCESS;
1103 parsePtr->incomplete = 0;
1107 * Generate one token for the variable, an additional token for the
1108 * name, plus any number of additional tokens for the index, if
1113 if ((parsePtr->numTokens + 2) > parsePtr->tokensAvailable) {
1114 TclExpandTokenArray(parsePtr);
1116 tokenPtr = &parsePtr->tokenPtr[parsePtr->numTokens];
1117 tokenPtr->type = TCL_TOKEN_VARIABLE;
1118 tokenPtr->start = src;
1119 varIndex = parsePtr->numTokens;
1120 parsePtr->numTokens++;
1123 if (numBytes == 0) {
1124 goto justADollarSign;
1126 tokenPtr->type = TCL_TOKEN_TEXT;
1127 tokenPtr->start = src;
1128 tokenPtr->numComponents = 0;
1131 * The name of the variable can have three forms:
1132 * 1. The $ sign is followed by an open curly brace. Then
1133 * the variable name is everything up to the next close
1134 * curly brace, and the variable is a scalar variable.
1135 * 2. The $ sign is not followed by an open curly brace. Then
1136 * the variable name is everything up to the next
1137 * character that isn't a letter, digit, or underscore.
1138 * :: sequences are also considered part of the variable
1139 * name, in order to support namespaces. If the following
1140 * character is an open parenthesis, then the information
1141 * between parentheses is the array element name.
1142 * 3. The $ sign is followed by something that isn't a letter,
1143 * digit, or underscore: in this case, there is no variable
1144 * name and the token is just "$".
1149 tokenPtr->type = TCL_TOKEN_TEXT;
1150 tokenPtr->start = src;
1151 tokenPtr->numComponents = 0;
1153 while (numBytes && (*src != '}')) {
1156 if (numBytes == 0) {
1157 if (interp != NULL) {
1158 Tcl_SetResult(interp, "missing close-brace for variable name",
1161 parsePtr->errorType = TCL_PARSE_MISSING_VAR_BRACE;
1162 parsePtr->term = tokenPtr->start-1;
1163 parsePtr->incomplete = 1;
1166 tokenPtr->size = src - tokenPtr->start;
1167 tokenPtr[-1].size = src - tokenPtr[-1].start;
1168 parsePtr->numTokens++;
1171 tokenPtr->type = TCL_TOKEN_TEXT;
1172 tokenPtr->start = src;
1173 tokenPtr->numComponents = 0;
1175 if (Tcl_UtfCharComplete(src, numBytes)) {
1176 offset = Tcl_UtfToUniChar(src, &ch);
1178 char utfBytes[TCL_UTF_MAX];
1179 memcpy(utfBytes, src, (size_t) numBytes);
1180 utfBytes[numBytes] = '\0';
1181 offset = Tcl_UtfToUniChar(utfBytes, &ch);
1184 if (isalnum(c) || (c == '_')) { /* INTL: ISO only, UCHAR. */
1185 src += offset; numBytes -= offset;
1188 if ((c == ':') && (numBytes != 1) && (src[1] == ':')) {
1189 src += 2; numBytes -= 2;
1190 while (numBytes && (*src == ':')) {
1199 * Support for empty array names here.
1201 array = (numBytes && (*src == '('));
1202 tokenPtr->size = src - tokenPtr->start;
1203 if ((tokenPtr->size == 0) && !array) {
1204 goto justADollarSign;
1206 parsePtr->numTokens++;
1209 * This is a reference to an array element. Call
1210 * ParseTokens recursively to parse the element name,
1211 * since it could contain any number of substitutions.
1214 if (ParseTokens(src+1, numBytes-1, TYPE_CLOSE_PAREN, parsePtr)
1218 if ((parsePtr->term == (src + numBytes))
1219 || (*parsePtr->term != ')')) {
1220 if (parsePtr->interp != NULL) {
1221 Tcl_SetResult(parsePtr->interp, "missing )",
1224 parsePtr->errorType = TCL_PARSE_MISSING_PAREN;
1225 parsePtr->term = src;
1226 parsePtr->incomplete = 1;
1229 src = parsePtr->term + 1;
1232 tokenPtr = &parsePtr->tokenPtr[varIndex];
1233 tokenPtr->size = src - tokenPtr->start;
1234 tokenPtr->numComponents = parsePtr->numTokens - (varIndex + 1);
1238 * The dollar sign isn't followed by a variable name.
1239 * replace the TCL_TOKEN_VARIABLE token with a
1240 * TCL_TOKEN_TEXT token for the dollar sign.
1244 tokenPtr = &parsePtr->tokenPtr[varIndex];
1245 tokenPtr->type = TCL_TOKEN_TEXT;
1247 tokenPtr->numComponents = 0;
1251 Tcl_FreeParse(parsePtr);
1256 *----------------------------------------------------------------------
1260 * Given a string starting with a $ sign, parse off a variable
1261 * name and return its value.
1264 * The return value is the contents of the variable given by
1265 * the leading characters of string. If termPtr isn't NULL,
1266 * *termPtr gets filled in with the address of the character
1267 * just after the last one in the variable specifier. If the
1268 * variable doesn't exist, then the return value is NULL and
1269 * an error message will be left in interp's result.
1274 *----------------------------------------------------------------------
1277 EXPORT_C CONST char *
1278 Tcl_ParseVar(interp, string, termPtr)
1279 Tcl_Interp *interp; /* Context for looking up variable. */
1280 register CONST char *string; /* String containing variable name.
1281 * First character must be "$". */
1282 CONST char **termPtr; /* If non-NULL, points to word to fill
1283 * in with character just after last
1284 * one in the variable specifier. */
1288 register Tcl_Obj *objPtr;
1291 if (Tcl_ParseVarName(interp, string, -1, &parse, 0) != TCL_OK) {
1295 if (termPtr != NULL) {
1296 *termPtr = string + parse.tokenPtr->size;
1298 if (parse.numTokens == 1) {
1300 * There isn't a variable name after all: the $ is just a $.
1306 code = Tcl_EvalTokensStandard(interp, parse.tokenPtr, parse.numTokens);
1307 if (code != TCL_OK) {
1310 objPtr = Tcl_GetObjResult(interp);
1313 * At this point we should have an object containing the value of
1314 * a variable. Just return the string from that object.
1316 * This should have returned the object for the user to manage, but
1317 * instead we have some weak reference to the string value in the
1318 * object, which is why we make sure the object exists after resetting
1319 * the result. This isn't ideal, but it's the best we can do with the
1320 * current documented interface. -- hobbs
1323 if (!Tcl_IsShared(objPtr)) {
1324 Tcl_IncrRefCount(objPtr);
1326 Tcl_ResetResult(interp);
1327 return TclGetString(objPtr);
1331 *----------------------------------------------------------------------
1333 * Tcl_ParseBraces --
1335 * Given a string in braces such as a Tcl command argument or a string
1336 * value in a Tcl expression, this procedure parses the string and
1337 * returns information about the parse. No more than numBytes bytes
1341 * The return value is TCL_OK if the string was parsed successfully and
1342 * TCL_ERROR otherwise. If an error occurs and interp isn't NULL then
1343 * an error message is left in its result. On a successful return,
1344 * tokenPtr and numTokens fields of parsePtr are filled in with
1345 * information about the string that was parsed. Other fields in
1346 * parsePtr are undefined. termPtr is set to point to the character
1347 * just after the last one in the braced string.
1350 * If there is insufficient space in parsePtr to hold all the
1351 * information about the command, then additional space is
1352 * malloc-ed. If the procedure returns TCL_OK then the caller must
1353 * eventually invoke Tcl_FreeParse to release any additional space
1354 * that was allocated.
1356 *----------------------------------------------------------------------
1360 Tcl_ParseBraces(interp, string, numBytes, parsePtr, append, termPtr)
1361 Tcl_Interp *interp; /* Interpreter to use for error reporting;
1362 * if NULL, then no error message is
1364 CONST char *string; /* String containing the string in braces.
1365 * The first character must be '{'. */
1366 register int numBytes; /* Total number of bytes in string. If < 0,
1367 * the string consists of all bytes up to
1368 * the first null character. */
1369 register Tcl_Parse *parsePtr;
1370 /* Structure to fill in with information
1371 * about the string. */
1372 int append; /* Non-zero means append tokens to existing
1373 * information in parsePtr; zero means
1374 * ignore existing tokens in parsePtr and
1375 * reinitialize it. */
1376 CONST char **termPtr; /* If non-NULL, points to word in which to
1377 * store a pointer to the character just
1378 * after the terminating '}' if the parse
1379 * was successful. */
1382 Tcl_Token *tokenPtr;
1383 register CONST char *src;
1384 int startIndex, level, length;
1386 if ((numBytes == 0) || (string == NULL)) {
1390 numBytes = strlen(string);
1394 parsePtr->numWords = 0;
1395 parsePtr->tokenPtr = parsePtr->staticTokens;
1396 parsePtr->numTokens = 0;
1397 parsePtr->tokensAvailable = NUM_STATIC_TOKENS;
1398 parsePtr->string = string;
1399 parsePtr->end = (string + numBytes);
1400 parsePtr->interp = interp;
1401 parsePtr->errorType = TCL_PARSE_SUCCESS;
1405 startIndex = parsePtr->numTokens;
1407 if (parsePtr->numTokens == parsePtr->tokensAvailable) {
1408 TclExpandTokenArray(parsePtr);
1410 tokenPtr = &parsePtr->tokenPtr[startIndex];
1411 tokenPtr->type = TCL_TOKEN_TEXT;
1412 tokenPtr->start = src+1;
1413 tokenPtr->numComponents = 0;
1416 while (++src, --numBytes) {
1417 if (CHAR_TYPE(*src) != TYPE_NORMAL) {
1421 if (numBytes == 0) {
1422 register int openBrace = 0;
1424 parsePtr->errorType = TCL_PARSE_MISSING_BRACE;
1425 parsePtr->term = string;
1426 parsePtr->incomplete = 1;
1427 if (interp == NULL) {
1429 * Skip straight to the exit code since we have no
1430 * interpreter to put error message in.
1435 Tcl_SetResult(interp, "missing close-brace", TCL_STATIC);
1438 * Guess if the problem is due to comments by searching
1439 * the source string for a possible open brace within the
1440 * context of a comment. Since we aren't performing a
1441 * full Tcl parse, just look for an open brace preceded
1442 * by a '<whitespace>#' on the same line.
1445 for (; src > string; src--) {
1454 if (openBrace && (isspace(UCHAR(src[-1])))) {
1455 Tcl_AppendResult(interp,
1456 ": possible unbalanced brace in comment",
1465 Tcl_FreeParse(parsePtr);
1476 * Decide if we need to finish emitting a
1477 * partially-finished token. There are 3 cases:
1478 * {abc \newline xyz} or {xyz}
1479 * - finish emitting "xyz" token
1481 * - don't emit token after \newline
1482 * {} - finish emitting zero-sized token
1484 * The last case ensures that there is a token
1485 * (even if empty) that describes the braced string.
1488 if ((src != tokenPtr->start)
1489 || (parsePtr->numTokens == startIndex)) {
1490 tokenPtr->size = (src - tokenPtr->start);
1491 parsePtr->numTokens++;
1493 if (termPtr != NULL) {
1500 TclParseBackslash(src, numBytes, &length, NULL);
1501 if ((length > 1) && (src[1] == '\n')) {
1503 * A backslash-newline sequence must be collapsed, even
1504 * inside braces, so we have to split the word into
1505 * multiple tokens so that the backslash-newline can be
1506 * represented explicitly.
1509 if (numBytes == 2) {
1510 parsePtr->incomplete = 1;
1512 tokenPtr->size = (src - tokenPtr->start);
1513 if (tokenPtr->size != 0) {
1514 parsePtr->numTokens++;
1516 if ((parsePtr->numTokens+1) >= parsePtr->tokensAvailable) {
1517 TclExpandTokenArray(parsePtr);
1519 tokenPtr = &parsePtr->tokenPtr[parsePtr->numTokens];
1520 tokenPtr->type = TCL_TOKEN_BS;
1521 tokenPtr->start = src;
1522 tokenPtr->size = length;
1523 tokenPtr->numComponents = 0;
1524 parsePtr->numTokens++;
1527 numBytes -= length - 1;
1529 tokenPtr->type = TCL_TOKEN_TEXT;
1530 tokenPtr->start = src + 1;
1531 tokenPtr->numComponents = 0;
1534 numBytes -= length - 1;
1542 *----------------------------------------------------------------------
1544 * Tcl_ParseQuotedString --
1546 * Given a double-quoted string such as a quoted Tcl command argument
1547 * or a quoted value in a Tcl expression, this procedure parses the
1548 * string and returns information about the parse. No more than
1549 * numBytes bytes will be scanned.
1552 * The return value is TCL_OK if the string was parsed successfully and
1553 * TCL_ERROR otherwise. If an error occurs and interp isn't NULL then
1554 * an error message is left in its result. On a successful return,
1555 * tokenPtr and numTokens fields of parsePtr are filled in with
1556 * information about the string that was parsed. Other fields in
1557 * parsePtr are undefined. termPtr is set to point to the character
1558 * just after the quoted string's terminating close-quote.
1561 * If there is insufficient space in parsePtr to hold all the
1562 * information about the command, then additional space is
1563 * malloc-ed. If the procedure returns TCL_OK then the caller must
1564 * eventually invoke Tcl_FreeParse to release any additional space
1565 * that was allocated.
1567 *----------------------------------------------------------------------
1571 Tcl_ParseQuotedString(interp, string, numBytes, parsePtr, append, termPtr)
1572 Tcl_Interp *interp; /* Interpreter to use for error reporting;
1573 * if NULL, then no error message is
1575 CONST char *string; /* String containing the quoted string.
1576 * The first character must be '"'. */
1577 register int numBytes; /* Total number of bytes in string. If < 0,
1578 * the string consists of all bytes up to
1579 * the first null character. */
1580 register Tcl_Parse *parsePtr;
1581 /* Structure to fill in with information
1582 * about the string. */
1583 int append; /* Non-zero means append tokens to existing
1584 * information in parsePtr; zero means
1585 * ignore existing tokens in parsePtr and
1586 * reinitialize it. */
1587 CONST char **termPtr; /* If non-NULL, points to word in which to
1588 * store a pointer to the character just
1589 * after the quoted string's terminating
1590 * close-quote if the parse succeeds. */
1592 if ((numBytes == 0) || (string == NULL)) {
1596 numBytes = strlen(string);
1600 parsePtr->numWords = 0;
1601 parsePtr->tokenPtr = parsePtr->staticTokens;
1602 parsePtr->numTokens = 0;
1603 parsePtr->tokensAvailable = NUM_STATIC_TOKENS;
1604 parsePtr->string = string;
1605 parsePtr->end = (string + numBytes);
1606 parsePtr->interp = interp;
1607 parsePtr->errorType = TCL_PARSE_SUCCESS;
1610 if (ParseTokens(string+1, numBytes-1, TYPE_QUOTE, parsePtr) != TCL_OK) {
1613 if (*parsePtr->term != '"') {
1614 if (interp != NULL) {
1615 Tcl_SetResult(parsePtr->interp, "missing \"", TCL_STATIC);
1617 parsePtr->errorType = TCL_PARSE_MISSING_QUOTE;
1618 parsePtr->term = string;
1619 parsePtr->incomplete = 1;
1622 if (termPtr != NULL) {
1623 *termPtr = (parsePtr->term + 1);
1628 Tcl_FreeParse(parsePtr);
1633 *----------------------------------------------------------------------
1635 * CommandComplete --
1637 * This procedure is shared by TclCommandComplete and
1638 * Tcl_ObjCommandcoComplete; it does all the real work of seeing
1639 * whether a script is complete
1642 * 1 is returned if the script is complete, 0 if there are open
1643 * delimiters such as " or (. 1 is also returned if there is a
1644 * parse error in the script other than unmatched delimiters.
1649 *----------------------------------------------------------------------
1653 CommandComplete(script, numBytes)
1654 CONST char *script; /* Script to check. */
1655 int numBytes; /* Number of bytes in script. */
1658 CONST char *p, *end;
1663 while (Tcl_ParseCommand((Tcl_Interp *) NULL, p, end - p, 0, &parse)
1665 p = parse.commandStart + parse.commandSize;
1669 Tcl_FreeParse(&parse);
1671 if (parse.incomplete) {
1676 Tcl_FreeParse(&parse);
1681 *----------------------------------------------------------------------
1683 * Tcl_CommandComplete --
1685 * Given a partial or complete Tcl script, this procedure
1686 * determines whether the script is complete in the sense
1687 * of having matched braces and quotes and brackets.
1690 * 1 is returned if the script is complete, 0 otherwise.
1691 * 1 is also returned if there is a parse error in the script
1692 * other than unmatched delimiters.
1697 *----------------------------------------------------------------------
1701 Tcl_CommandComplete(script)
1702 CONST char *script; /* Script to check. */
1704 return CommandComplete(script, (int) strlen(script));
1708 *----------------------------------------------------------------------
1710 * TclObjCommandComplete --
1712 * Given a partial or complete Tcl command in a Tcl object, this
1713 * procedure determines whether the command is complete in the sense of
1714 * having matched braces and quotes and brackets.
1717 * 1 is returned if the command is complete, 0 otherwise.
1722 *----------------------------------------------------------------------
1726 TclObjCommandComplete(objPtr)
1727 Tcl_Obj *objPtr; /* Points to object holding script
1733 script = Tcl_GetStringFromObj(objPtr, &length);
1734 return CommandComplete(script, length);
1738 *----------------------------------------------------------------------
1740 * TclIsLocalScalar --
1742 * Check to see if a given string is a legal scalar variable
1743 * name with no namespace qualifiers or substitutions.
1746 * Returns 1 if the variable is a local scalar.
1751 *----------------------------------------------------------------------
1755 TclIsLocalScalar(src, len)
1760 CONST char *lastChar = src + (len - 1);
1762 for (p = src; p <= lastChar; p++) {
1763 if ((CHAR_TYPE(*p) != TYPE_NORMAL) &&
1764 (CHAR_TYPE(*p) != TYPE_COMMAND_END)) {
1766 * TCL_COMMAND_END is returned for the last character
1767 * of the string. By this point we know it isn't
1768 * an array or namespace reference.
1774 if (*lastChar == ')') { /* we have an array element */
1777 } else if (*p == ':') {
1778 if ((p != lastChar) && *(p+1) == ':') { /* qualified name */