6 * This file contains a collection of procedures that are used
7 * to parse Tcl commands or parts of commands (like quoted
8 * strings or nested sub-commands).
10 * Copyright 1991 Regents of the University of California.
11 * Permission to use, copy, modify, and distribute this
12 * software and its documentation for any purpose and without
13 * fee is hereby granted, provided that the above copyright
14 * notice appear in all copies. The University of California
15 * makes no representations about the suitability of this
16 * software for any purpose. It is provided "as is" without
17 * express or implied warranty.
19 * $Id: tclParse.c,v 1.1.1.1 2001/04/29 20:35:00 karll Exp $
25 * The following table assigns a type to each character. Only types
26 * meaningful to Tcl parsing are represented here. The table indexes
27 * all 256 characters, with the negative ones first, then the positive
31 char tclTypeTable[] = {
32 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
33 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
34 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
35 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
36 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
37 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
38 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
39 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
40 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
41 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
42 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
43 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
44 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
45 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
46 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
47 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
48 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
49 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
50 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
51 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
52 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
53 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
54 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
55 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
56 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
57 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
58 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
59 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
60 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
61 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
62 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
63 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
64 TCL_COMMAND_END, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
65 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
66 TCL_NORMAL, TCL_SPACE, TCL_COMMAND_END, TCL_SPACE,
67 TCL_SPACE, TCL_SPACE, TCL_NORMAL, TCL_NORMAL,
68 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
69 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
70 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
71 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
72 TCL_SPACE, TCL_NORMAL, TCL_QUOTE, TCL_NORMAL,
73 TCL_DOLLAR, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
74 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
75 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
76 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
77 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
78 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_COMMAND_END,
79 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
80 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
81 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
82 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
83 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
84 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
85 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
86 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_OPEN_BRACKET,
87 TCL_BACKSLASH, TCL_COMMAND_END, TCL_NORMAL, TCL_NORMAL,
88 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
89 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
90 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
91 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
92 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
93 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
94 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_OPEN_BRACE,
95 TCL_NORMAL, TCL_CLOSE_BRACE, TCL_NORMAL, TCL_NORMAL,
99 * Function prototypes for procedures local to this file:
102 static char * QuoteEnd _ANSI_ARGS_((char *string, int term));
103 static char * VarNameEnd _ANSI_ARGS_((char *string));
106 *----------------------------------------------------------------------
110 * Figure out how to handle a backslash sequence.
113 * The return value is the character that should be substituted
114 * in place of the backslash sequence that starts at src, or 0
115 * if the backslash sequence should be replace by nothing (e.g.
116 * backslash followed by newline). If readPtr isn't NULL then
117 * it is filled in with a count of the number of characters in
118 * the backslash sequence. Note: if the backslash isn't followed
119 * by characters that are understood here, then the backslash
120 * sequence is only considered to be one character long, and it
121 * is replaced by a backslash char.
126 *----------------------------------------------------------------------
130 Tcl_Backslash(src, readPtr)
131 CONST char *src; /* Points to the backslash character of
132 * a backslash sequence. */
133 int *readPtr; /* Fill in with number of characters read
134 * from src, unless NULL. */
136 register CONST char *p = src+1;
166 if (isspace(*p) || (*p == 0)) {
174 if (isspace(*p) || (*p == 0)) {
179 result = (*p & 037) | '\200';
187 if (isspace(*p) || (*p == 0)) {
193 result = *p + '\200';
217 result = (result << 3) + (*p - '0');
223 result = (result << 3) + (*p - '0');
231 if (readPtr != NULL) {
238 *--------------------------------------------------------------
242 * This procedure parses a double-quoted string such as a
243 * quoted Tcl command argument or a quoted value in a Tcl
244 * expression. This procedure is also used to parse array
245 * element names within parentheses, or anything else that
246 * needs all the substitutions that happen in quotes.
249 * The return value is a standard Tcl result, which is
250 * TCL_OK unless there was an error while parsing the
251 * quoted string. If an error occurs then interp->result
252 * contains a standard error message. *TermPtr is filled
253 * in with the address of the character just after the
254 * last one successfully processed; this is usually the
255 * character just after the matching close-quote. The
256 * fully-substituted contents of the quotes are stored in
257 * standard fashion in *pvPtr, null-terminated with
258 * pvPtr->next pointing to the terminating null character.
261 * The buffer space in pvPtr may be enlarged by calling its
264 *--------------------------------------------------------------
268 TclParseQuotes(interp, string, termChar, flags, termPtr, pvPtr)
269 Tcl_Interp *interp; /* Interpreter to use for nested command
270 * evaluations and error messages. */
271 char *string; /* Character just after opening double-
273 int termChar; /* Character that terminates "quoted" string
274 * (usually double-quote, but sometimes
275 * right-paren or something else). */
276 int flags; /* Flags to pass to nested Tcl_Eval calls. */
277 char **termPtr; /* Store address of terminating character
279 ParseValue *pvPtr; /* Information about where to place
280 * fully-substituted result of parse. */
282 register char *src, *dst;
289 if (dst == pvPtr->end) {
291 * Target buffer space is about to run out. Make more space.
295 (*pvPtr->expandProc)(pvPtr, 1);
306 } else if (CHAR_TYPE(c) == TCL_NORMAL) {
311 } else if (c == '$') {
315 value = Tcl_ParseVar(interp, src-1, termPtr);
320 length = strlen(value);
321 if ((pvPtr->end - dst) <= length) {
323 (*pvPtr->expandProc)(pvPtr, length);
329 } else if (c == '[') {
333 result = TclParseNestedCmd(interp, src, flags, termPtr, pvPtr);
334 if (result != TCL_OK) {
340 } else if (c == '\\') {
344 *dst = Tcl_Backslash(src, &numRead);
350 } else if (c == '\0') {
351 Tcl_ResetResult(interp);
352 sprintf(interp->result, "missing %c", termChar);
362 *--------------------------------------------------------------
364 * TclParseNestedCmd --
366 * This procedure parses a nested Tcl command between
367 * brackets, returning the result of the command.
370 * The return value is a standard Tcl result, which is
371 * TCL_OK unless there was an error while executing the
372 * nested command. If an error occurs then interp->result
373 * contains a standard error message. *TermPtr is filled
374 * in with the address of the character just after the
375 * last one processed; this is usually the character just
376 * after the matching close-bracket, or the null character
377 * at the end of the string if the close-bracket was missing
378 * (a missing close bracket is an error). The result returned
379 * by the command is stored in standard fashion in *pvPtr,
380 * null-terminated, with pvPtr->next pointing to the null
384 * The storage space at *pvPtr may be expanded.
386 *--------------------------------------------------------------
390 TclParseNestedCmd(interp, string, flags, termPtr, pvPtr)
391 Tcl_Interp *interp; /* Interpreter to use for nested command
392 * evaluations and error messages. */
393 char *string; /* Character just after opening bracket. */
394 int flags; /* Flags to pass to nested Tcl_Eval. */
395 char **termPtr; /* Store address of terminating character
397 register ParseValue *pvPtr; /* Information about where to place
398 * result of command. */
400 int result, length, shortfall;
401 Interp *iPtr = (Interp *) interp;
403 result = Tcl_Eval(interp, string, flags | TCL_BRACKET_TERM, termPtr);
404 if (result != TCL_OK) {
406 * The increment below results in slightly cleaner message in
407 * the errorInfo variable (the close-bracket will appear).
410 if (**termPtr == ']') {
416 length = strlen(iPtr->result);
417 shortfall = length + 1 - (pvPtr->end - pvPtr->next);
419 (*pvPtr->expandProc)(pvPtr, shortfall);
421 strcpy(pvPtr->next, iPtr->result);
422 pvPtr->next += length;
423 Tcl_FreeResult(iPtr);
424 iPtr->result = iPtr->resultSpace;
425 iPtr->resultSpace[0] = '\0';
430 *--------------------------------------------------------------
434 * This procedure scans the information between matching
438 * The return value is a standard Tcl result, which is
439 * TCL_OK unless there was an error while parsing string.
440 * If an error occurs then interp->result contains a
441 * standard error message. *TermPtr is filled
442 * in with the address of the character just after the
443 * last one successfully processed; this is usually the
444 * character just after the matching close-brace. The
445 * information between curly braces is stored in standard
446 * fashion in *pvPtr, null-terminated with pvPtr->next
447 * pointing to the terminating null character.
450 * The storage space at *pvPtr may be expanded.
452 *--------------------------------------------------------------
456 TclParseBraces(interp, string, termPtr, pvPtr)
457 Tcl_Interp *interp; /* Interpreter to use for nested command
458 * evaluations and error messages. */
459 char *string; /* Character just after opening bracket. */
460 char **termPtr; /* Store address of terminating character
462 register ParseValue *pvPtr; /* Information about where to place
463 * result of command. */
466 register char *src, *dst, *end;
475 * Copy the characters one at a time to the result area, stopping
476 * when the matching close-brace is found.
484 (*pvPtr->expandProc)(pvPtr, 20);
490 if (CHAR_TYPE(c) == TCL_NORMAL) {
492 } else if (c == '{') {
494 } else if (c == '}') {
497 dst--; /* Don't copy the last close brace. */
500 } else if (c == '\\') {
504 * Must always squish out backslash-newlines, even when in
505 * braces. This is needed so that this sequence can appear
506 * anywhere in a command, such as the middle of an expression.
513 (void) Tcl_Backslash(src-1, &count);
517 (*pvPtr->expandProc)(pvPtr, 20);
527 } else if (c == '\0') {
528 Tcl_SetResult(interp, "missing close-brace", TCL_STATIC);
541 *--------------------------------------------------------------
545 * This procedure parses one or more words from a command
546 * string and creates argv-style pointers to fully-substituted
547 * copies of those words.
550 * The return value is a standard Tcl result.
552 * *argcPtr is modified to hold a count of the number of words
553 * successfully parsed, which may be 0. At most maxWords words
554 * will be parsed. If 0 <= *argcPtr < maxWords then it
555 * means that a command separator was seen. If *argcPtr
556 * is maxWords then it means that a command separator was
559 * *TermPtr is filled in with the address of the character
560 * just after the last one successfully processed in the
561 * last word. This is either the command terminator (if
562 * *argcPtr < maxWords), the character just after the last
563 * one in a word (if *argcPtr is maxWords), or the vicinity
564 * of an error (if the result is not TCL_OK).
566 * The pointers at *argv are filled in with pointers to the
567 * fully-substituted words, and the actual contents of the
568 * words are copied to the buffer at pvPtr.
570 * If an error occurrs then an error message is left in
571 * interp->result and the information at *argv, *argcPtr,
572 * and *pvPtr may be incomplete.
575 * The buffer space in pvPtr may be enlarged by calling its
578 *--------------------------------------------------------------
582 TclParseWords(interp, string, flags, maxWords, termPtr, argcPtr, argv, pvPtr)
583 Tcl_Interp *interp; /* Interpreter to use for nested command
584 * evaluations and error messages. */
585 char *string; /* First character of word. */
586 int flags; /* Flags to control parsing (same values as
587 * passed to Tcl_Eval). */
588 int maxWords; /* Maximum number of words to parse. */
589 char **termPtr; /* Store address of terminating character
591 int *argcPtr; /* Filled in with actual number of words
593 char **argv; /* Store addresses of individual words here. */
594 register ParseValue *pvPtr; /* Information about where to place
595 * fully-substituted word. */
597 register char *src, *dst;
599 int type, result, argc;
600 char *oldBuffer; /* Used to detect when pvPtr's buffer gets
601 * reallocated, so we can adjust all of the
605 oldBuffer = pvPtr->buffer;
607 for (argc = 0; argc < maxWords; argc++) {
611 * Skip leading space.
617 while (type == TCL_SPACE) {
624 * Handle the normal case (i.e. no leading double-quote or brace).
627 if (type == TCL_NORMAL) {
630 if (dst == pvPtr->end) {
632 * Target buffer space is about to run out. Make
637 (*pvPtr->expandProc)(pvPtr, 1);
641 if (type == TCL_NORMAL) {
646 } else if (type == TCL_SPACE) {
648 } else if (type == TCL_DOLLAR) {
652 value = Tcl_ParseVar(interp, src, termPtr);
657 length = strlen(value);
658 if ((pvPtr->end - dst) <= length) {
660 (*pvPtr->expandProc)(pvPtr, length);
665 } else if (type == TCL_COMMAND_END) {
666 if ((c == ']') && !(flags & TCL_BRACKET_TERM)) {
671 * End of command; simulate a word-end first, so
672 * that the end-of-command can be processed as the
673 * first thing in a new word.
677 } else if (type == TCL_OPEN_BRACKET) {
679 result = TclParseNestedCmd(interp, src+1, flags, termPtr,
681 if (result != TCL_OK) {
686 } else if (type == TCL_BACKSLASH) {
689 *dst = Tcl_Backslash(src, &numRead);
703 * Check for the end of the command.
706 if (type == TCL_COMMAND_END) {
707 if (flags & TCL_BRACKET_TERM) {
709 Tcl_SetResult(interp, "missing close-bracket",
722 * Now handle the special cases: open braces, double-quotes,
723 * and backslash-newline.
727 if (type == TCL_QUOTE) {
728 result = TclParseQuotes(interp, src+1, '"', flags,
730 } else if (type == TCL_OPEN_BRACE) {
731 result = TclParseBraces(interp, src+1, termPtr, pvPtr);
732 } else if ((type == TCL_BACKSLASH) && (src[1] == '\n')) {
738 if (result != TCL_OK) {
743 * Back from quotes or braces; make sure that the terminating
744 * character was the end of the word. Have to be careful here
745 * to handle continuation lines (i.e. lines ending in backslash).
749 if ((c == '\\') && ((*termPtr)[1] == '\n')) {
753 if ((type != TCL_SPACE) && (type != TCL_COMMAND_END)) {
755 Tcl_SetResult(interp, "extra characters after close-quote",
758 Tcl_SetResult(interp, "extra characters after close-brace",
769 * We're at the end of a word, so add a null terminator. Then
770 * see if the buffer was re-allocated during this word. If so,
771 * update all of the argv pointers.
777 if (oldBuffer != pvPtr->buffer) {
780 for (i = 0; i <= argc; i++) {
781 argv[i] = pvPtr->buffer + (argv[i] - oldBuffer);
783 oldBuffer = pvPtr->buffer;
795 *--------------------------------------------------------------
797 * TclExpandParseValue --
799 * This procedure is commonly used as the value of the
800 * expandProc in a ParseValue. It uses malloc to allocate
801 * more space for the result of a parse.
804 * The buffer space in *pvPtr is reallocated to something
805 * larger, and if pvPtr->clientData is non-zero the old
806 * buffer is freed. Information is copied from the old
807 * buffer to the new one.
812 *--------------------------------------------------------------
816 TclExpandParseValue(pvPtr, needed)
817 register ParseValue *pvPtr; /* Information about buffer that
818 * must be expanded. If the clientData
819 * in the structure is non-zero, it
820 * means that the current buffer is
821 * dynamically allocated. */
822 int needed; /* Minimum amount of additional space
829 * Either double the size of the buffer or add enough new space
830 * to meet the demand, whichever produces a larger new buffer.
833 newSpace = (pvPtr->end - pvPtr->buffer) + 1;
834 if (newSpace < needed) {
837 newSpace += newSpace;
839 new = (char *) ckalloc((unsigned) newSpace);
842 * Copy from old buffer to new, free old buffer if needed, and
843 * mark new buffer as malloc-ed.
846 memcpy((VOID *) new, (VOID *) pvPtr->buffer, pvPtr->next - pvPtr->buffer);
847 pvPtr->next = new + (pvPtr->next - pvPtr->buffer);
848 if (pvPtr->clientData != 0) {
849 ckfree(pvPtr->buffer);
852 pvPtr->end = new + newSpace - 1;
853 pvPtr->clientData = (ClientData) 1;
857 *----------------------------------------------------------------------
861 * Given a pointer into a Tcl command, find the end of the next
862 * word of the command.
865 * The return value is a pointer to the last character that's part
866 * of the word pointed to by "start". If the word doesn't end
867 * properly within the string then the return value is the address
868 * of the null character at the end of the string.
873 *----------------------------------------------------------------------
877 TclWordEnd(start, nested)
878 char *start; /* Beginning of a word of a Tcl command. */
879 int nested; /* Zero means this is a top-level command.
880 * One means this is a nested command (close
881 * brace is a word terminator). */
887 while (isspace(*p)) {
892 * Handle words beginning with a double-quote or a brace.
896 p = QuoteEnd(p+1, '"');
901 } else if (*p == '{') {
903 while (braces != 0) {
906 (void) Tcl_Backslash(p, &count);
911 } else if (*p == '{') {
913 } else if (*p == 0) {
921 * Handle words that don't start with a brace or double-quote.
922 * This code is also invoked if the word starts with a brace or
923 * double-quote and there is garbage after the closing brace or
924 * quote. This is an error as far as Tcl_Eval is concerned, but
925 * for here the garbage is treated as part of the word.
930 for (p++; *p != ']'; p++) {
931 p = TclWordEnd(p, 1);
937 } else if (*p == '\\') {
938 (void) Tcl_Backslash(p, &count);
940 if ((*p == 0) && (count == 2) && (p[-1] == '\n')) {
943 } else if (*p == '$') {
949 } else if (*p == ';') {
951 * Include the semi-colon in the word that is returned.
955 } else if (isspace(*p)) {
957 } else if ((*p == ']') && nested) {
959 } else if (*p == 0) {
962 * Nested commands can't end because of the end of the
975 *----------------------------------------------------------------------
979 * Given a pointer to a string that obeys the parsing conventions
980 * for quoted things in Tcl, find the end of that quoted thing.
981 * The actual thing may be a quoted argument or a parenthesized
985 * The return value is a pointer to the last character that is
986 * part of the quoted string (i.e the character that's equal to
987 * term). If the quoted string doesn't terminate properly then
988 * the return value is a pointer to the null character at the
994 *----------------------------------------------------------------------
998 QuoteEnd(string, term)
999 char *string; /* Pointer to character just after opening
1001 int term; /* This character will terminate the
1002 * quoted string (e.g. '"' or ')'). */
1004 register char *p = string;
1007 while (*p != term) {
1009 (void) Tcl_Backslash(p, &count);
1011 } else if (*p == '[') {
1012 for (p++; *p != ']'; p++) {
1013 p = TclWordEnd(p, 1);
1019 } else if (*p == '$') {
1025 } else if (*p == 0) {
1035 *----------------------------------------------------------------------
1039 * Given a pointer to a variable reference using $-notation, find
1040 * the end of the variable name spec.
1043 * The return value is a pointer to the last character that
1044 * is part of the variable name. If the variable name doesn't
1045 * terminate properly then the return value is a pointer to the
1046 * null character at the end of the string.
1051 *----------------------------------------------------------------------
1056 char *string; /* Pointer to dollar-sign character. */
1058 register char *p = string+1;
1061 for (p++; (*p != '}') && (*p != 0); p++) {
1062 /* Empty loop body. */
1066 /* Two leading colons are OK */
1067 if (p[0] == ':' && p[1] == ':') {
1070 while (isalnum(*p) || (*p == '_')) {
1073 if ((*p == '(') && (p != string+1)) {
1074 return QuoteEnd(p+1, ')');
1080 *----------------------------------------------------------------------
1084 * Given a string starting with a $ sign, parse off a variable
1085 * name and return its value.
1088 * The return value is the contents of the variable given by
1089 * the leading characters of string. If termPtr isn't NULL,
1090 * *termPtr gets filled in with the address of the character
1091 * just after the last one in the variable specifier. If the
1092 * variable doesn't exist, then the return value is NULL and
1093 * an error message will be left in interp->result.
1098 *----------------------------------------------------------------------
1102 Tcl_ParseVar(interp, string, termPtr)
1103 Tcl_Interp *interp; /* Context for looking up variable. */
1104 register char *string; /* String containing variable name.
1105 * First character must be "$". */
1106 char **termPtr; /* If non-NULL, points to word to fill
1107 * in with character just after last
1108 * one in the variable specifier. */
1111 char *name1, *name1End, c, *result;
1112 register char *name2;
1113 #define NUM_CHARS 200
1114 char copyStorage[NUM_CHARS];
1118 * There are three cases:
1119 * 1. The $ sign is followed by an open curly brace. Then the variable
1120 * name is everything up to the next close curly brace, and the
1121 * variable is a scalar variable.
1122 * 2. The $ sign is not followed by an open curly brace. Then the
1123 * variable name is everything up to the next character that isn't
1124 * a letter, digit, or underscore. If the following character is an
1125 * open parenthesis, then the information between parentheses is
1126 * the array element name, which can include any of the substitutions
1127 * permissible between quotes.
1128 * 3. The $ sign is followed by something that isn't a letter, digit, colon
1129 * or underscore: in this case, there is no variable name, and "$"
1135 if (*string == '{') {
1138 while (*string != '}') {
1140 Tcl_SetResult(interp, "missing close-brace for variable name",
1153 /* Two leading colons are OK */
1154 if (string[0] == ':' && string[1] == ':') {
1157 while (isalnum(*string) || (*string == '_')) {
1160 if (string == name1) {
1167 if (*string == '(') {
1171 * Perform substitutions on the array element name, just as
1172 * is done for quotes.
1175 pv.buffer = pv.next = copyStorage;
1176 pv.end = copyStorage + NUM_CHARS - 1;
1177 pv.expandProc = TclExpandParseValue;
1178 pv.clientData = (ClientData) NULL;
1179 if (TclParseQuotes(interp, string+1, ')', 0, &end, &pv)
1182 sprintf(msg, "\n (parsing index for array \"%.*s\")",
1183 (int)(string-name1), name1);
1184 Tcl_AddErrorInfo(interp, msg);
1200 if (((Interp *) interp)->noEval) {
1205 result = Tcl_GetVar2(interp, name1, name2, TCL_LEAVE_ERR_MSG);
1209 if ((name2 != NULL) && (pv.buffer != copyStorage)) {