]>
git.zerfleddert.de Git - micropolis/blob - src/tcl/tclparse.c
0200cd2f75170c221219bbb1ae34b062540b355e
4 * This file contains a collection of procedures that are used
5 * to parse Tcl commands or parts of commands (like quoted
6 * strings or nested sub-commands).
8 * Copyright 1991 Regents of the University of California.
9 * Permission to use, copy, modify, and distribute this
10 * software and its documentation for any purpose and without
11 * fee is hereby granted, provided that the above copyright
12 * notice appear in all copies. The University of California
13 * makes no representations about the suitability of this
14 * software for any purpose. It is provided "as is" without
15 * express or implied warranty.
19 static char rcsid
[] = "$Header: /user6/ouster/tcl/RCS/tclParse.c,v 1.21 92/06/08 09:32:37 ouster Exp $ SPRITE (Berkeley)";
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 *----------------------------------------------------------------------
131 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. */
137 register char *p
= src
+1;
167 if (isspace(*p
) || (*p
== 0)) {
175 if (isspace(*p
) || (*p
== 0)) {
180 result
= (*p
& 037) | 0200;
188 if (isspace(*p
) || (*p
== 0)) {
218 result
= (result
<< 3) + (*p
- '0');
224 result
= (result
<< 3) + (*p
- '0');
232 if (readPtr
!= NULL
) {
239 *--------------------------------------------------------------
243 * This procedure parses a double-quoted string such as a
244 * quoted Tcl command argument or a quoted value in a Tcl
245 * expression. This procedure is also used to parse array
246 * element names within parentheses, or anything else that
247 * needs all the substitutions that happen in quotes.
250 * The return value is a standard Tcl result, which is
251 * TCL_OK unless there was an error while parsing the
252 * quoted string. If an error occurs then interp->result
253 * contains a standard error message. *TermPtr is filled
254 * in with the address of the character just after the
255 * last one successfully processed; this is usually the
256 * character just after the matching close-quote. The
257 * fully-substituted contents of the quotes are stored in
258 * standard fashion in *pvPtr, null-terminated with
259 * pvPtr->next pointing to the terminating null character.
262 * The buffer space in pvPtr may be enlarged by calling its
265 *--------------------------------------------------------------
270 Tcl_Interp
*interp
, /* Interpreter to use for nested command
271 * evaluations and error messages. */
272 char *string
, /* Character just after opening double-
274 int termChar
, /* Character that terminates "quoted" string
275 * (usually double-quote, but sometimes
276 * right-paren or something else). */
277 int flags
, /* Flags to pass to nested Tcl_Eval calls. */
278 char **termPtr
, /* Store address of terminating character
280 ParseValue
*pvPtr
/* Information about where to place
281 * fully-substituted result of parse. */
284 register char *src
, *dst
, c
;
290 if (dst
== pvPtr
->end
) {
292 * Target buffer space is about to run out. Make more space.
296 (*pvPtr
->expandProc
)(pvPtr
, 1);
307 } else if (CHAR_TYPE(c
) == TCL_NORMAL
) {
312 } else if (c
== '$') {
316 value
= Tcl_ParseVar(interp
, src
-1, termPtr
);
321 length
= strlen(value
);
322 if ((pvPtr
->end
- dst
) <= length
) {
324 (*pvPtr
->expandProc
)(pvPtr
, length
);
330 } else if (c
== '[') {
334 result
= TclParseNestedCmd(interp
, src
, flags
, termPtr
, pvPtr
);
335 if (result
!= TCL_OK
) {
341 } else if (c
== '\\') {
345 *dst
= Tcl_Backslash(src
, &numRead
);
351 } else if (c
== '\0') {
352 Tcl_ResetResult(interp
);
353 sprintf(interp
->result
, "missing %c", termChar
);
363 *--------------------------------------------------------------
365 * TclParseNestedCmd --
367 * This procedure parses a nested Tcl command between
368 * brackets, returning the result of the command.
371 * The return value is a standard Tcl result, which is
372 * TCL_OK unless there was an error while executing the
373 * nested command. If an error occurs then interp->result
374 * contains a standard error message. *TermPtr is filled
375 * in with the address of the character just after the
376 * last one processed; this is usually the character just
377 * after the matching close-bracket, or the null character
378 * at the end of the string if the close-bracket was missing
379 * (a missing close bracket is an error). The result returned
380 * by the command is stored in standard fashion in *pvPtr,
381 * null-terminated, with pvPtr->next pointing to the null
385 * The storage space at *pvPtr may be expanded.
387 *--------------------------------------------------------------
392 Tcl_Interp
*interp
, /* Interpreter to use for nested command
393 * evaluations and error messages. */
394 char *string
, /* Character just after opening bracket. */
395 int flags
, /* Flags to pass to nested Tcl_Eval. */
396 char **termPtr
, /* Store address of terminating character
398 register ParseValue
*pvPtr
/* Information about where to place
399 * result of command. */
402 int result
, length
, shortfall
;
403 Interp
*iPtr
= (Interp
*) interp
;
405 result
= Tcl_Eval(interp
, string
, flags
| TCL_BRACKET_TERM
, termPtr
);
406 if (result
!= TCL_OK
) {
408 * The increment below results in slightly cleaner message in
409 * the errorInfo variable (the close-bracket will appear).
412 if (**termPtr
== ']') {
418 length
= strlen(iPtr
->result
);
419 shortfall
= length
+ 1 - (pvPtr
->end
- pvPtr
->next
);
421 (*pvPtr
->expandProc
)(pvPtr
, shortfall
);
423 strcpy(pvPtr
->next
, iPtr
->result
);
424 pvPtr
->next
+= length
;
425 Tcl_FreeResult(iPtr
);
426 iPtr
->result
= iPtr
->resultSpace
;
427 iPtr
->resultSpace
[0] = '\0';
432 *--------------------------------------------------------------
436 * This procedure scans the information between matching
440 * The return value is a standard Tcl result, which is
441 * TCL_OK unless there was an error while parsing string.
442 * If an error occurs then interp->result contains a
443 * standard error message. *TermPtr is filled
444 * in with the address of the character just after the
445 * last one successfully processed; this is usually the
446 * character just after the matching close-brace. The
447 * information between curly braces is stored in standard
448 * fashion in *pvPtr, null-terminated with pvPtr->next
449 * pointing to the terminating null character.
452 * The storage space at *pvPtr may be expanded.
454 *--------------------------------------------------------------
459 Tcl_Interp
*interp
, /* Interpreter to use for nested command
460 * evaluations and error messages. */
461 char *string
, /* Character just after opening bracket. */
462 char **termPtr
, /* Store address of terminating character
464 register ParseValue
*pvPtr
/* Information about where to place
465 * result of command. */
469 register char *src
, *dst
, *end
;
478 * Copy the characters one at a time to the result area, stopping
479 * when the matching close-brace is found.
487 (*pvPtr
->expandProc
)(pvPtr
, 20);
493 if (CHAR_TYPE(c
) == TCL_NORMAL
) {
495 } else if (c
== '{') {
497 } else if (c
== '}') {
500 dst
--; /* Don't copy the last close brace. */
503 } else if (c
== '\\') {
507 * Must always squish out backslash-newlines, even when in
508 * braces. This is needed so that this sequence can appear
509 * anywhere in a command, such as the middle of an expression.
516 (void) Tcl_Backslash(src
-1, &count
);
520 (*pvPtr
->expandProc
)(pvPtr
, 20);
530 } else if (c
== '\0') {
531 Tcl_SetResult(interp
, "missing close-brace", TCL_STATIC
);
544 *--------------------------------------------------------------
548 * This procedure parses one or more words from a command
549 * string and creates argv-style pointers to fully-substituted
550 * copies of those words.
553 * The return value is a standard Tcl result.
555 * *argcPtr is modified to hold a count of the number of words
556 * successfully parsed, which may be 0. At most maxWords words
557 * will be parsed. If 0 <= *argcPtr < maxWords then it
558 * means that a command separator was seen. If *argcPtr
559 * is maxWords then it means that a command separator was
562 * *TermPtr is filled in with the address of the character
563 * just after the last one successfully processed in the
564 * last word. This is either the command terminator (if
565 * *argcPtr < maxWords), the character just after the last
566 * one in a word (if *argcPtr is maxWords), or the vicinity
567 * of an error (if the result is not TCL_OK).
569 * The pointers at *argv are filled in with pointers to the
570 * fully-substituted words, and the actual contents of the
571 * words are copied to the buffer at pvPtr.
573 * If an error occurrs then an error message is left in
574 * interp->result and the information at *argv, *argcPtr,
575 * and *pvPtr may be incomplete.
578 * The buffer space in pvPtr may be enlarged by calling its
581 *--------------------------------------------------------------
586 Tcl_Interp
*interp
, /* Interpreter to use for nested command
587 * evaluations and error messages. */
588 char *string
, /* First character of word. */
589 int flags
, /* Flags to control parsing (same values as
590 * passed to Tcl_Eval). */
591 int maxWords
, /* Maximum number of words to parse. */
592 char **termPtr
, /* Store address of terminating character
594 int *argcPtr
, /* Filled in with actual number of words
596 char **argv
, /* Store addresses of individual words here. */
597 register ParseValue
*pvPtr
/* Information about where to place
598 * fully-substituted word. */
601 register char *src
, *dst
;
603 int type
, result
, argc
;
604 char *oldBuffer
; /* Used to detect when pvPtr's buffer gets
605 * reallocated, so we can adjust all of the
609 oldBuffer
= pvPtr
->buffer
;
611 for (argc
= 0; argc
< maxWords
; argc
++) {
615 * Skip leading space.
621 while (type
== TCL_SPACE
) {
628 * Handle the normal case (i.e. no leading double-quote or brace).
631 if (type
== TCL_NORMAL
) {
634 if (dst
== pvPtr
->end
) {
636 * Target buffer space is about to run out. Make
641 (*pvPtr
->expandProc
)(pvPtr
, 1);
645 if (type
== TCL_NORMAL
) {
650 } else if (type
== TCL_SPACE
) {
652 } else if (type
== TCL_DOLLAR
) {
656 value
= Tcl_ParseVar(interp
, src
, termPtr
);
661 length
= strlen(value
);
662 if ((pvPtr
->end
- dst
) <= length
) {
664 (*pvPtr
->expandProc
)(pvPtr
, length
);
669 } else if (type
== TCL_COMMAND_END
) {
670 if ((c
== ']') && !(flags
& TCL_BRACKET_TERM
)) {
675 * End of command; simulate a word-end first, so
676 * that the end-of-command can be processed as the
677 * first thing in a new word.
681 } else if (type
== TCL_OPEN_BRACKET
) {
683 result
= TclParseNestedCmd(interp
, src
+1, flags
, termPtr
,
685 if (result
!= TCL_OK
) {
690 } else if (type
== TCL_BACKSLASH
) {
693 *dst
= Tcl_Backslash(src
, &numRead
);
707 * Check for the end of the command.
710 if (type
== TCL_COMMAND_END
) {
711 if (flags
& TCL_BRACKET_TERM
) {
713 Tcl_SetResult(interp
, "missing close-bracket",
726 * Now handle the special cases: open braces, double-quotes,
727 * and backslash-newline.
731 if (type
== TCL_QUOTE
) {
732 result
= TclParseQuotes(interp
, src
+1, '"', flags
,
734 } else if (type
== TCL_OPEN_BRACE
) {
735 result
= TclParseBraces(interp
, src
+1, termPtr
, pvPtr
);
736 } else if ((type
== TCL_BACKSLASH
) && (src
[1] == '\n')) {
742 if (result
!= TCL_OK
) {
747 * Back from quotes or braces; make sure that the terminating
748 * character was the end of the word. Have to be careful here
749 * to handle continuation lines (i.e. lines ending in backslash).
753 if ((c
== '\\') && ((*termPtr
)[1] == '\n')) {
757 if ((type
!= TCL_SPACE
) && (type
!= TCL_COMMAND_END
)) {
759 Tcl_SetResult(interp
, "extra characters after close-quote",
762 Tcl_SetResult(interp
, "extra characters after close-brace",
773 * We're at the end of a word, so add a null terminator. Then
774 * see if the buffer was re-allocated during this word. If so,
775 * update all of the argv pointers.
781 if (oldBuffer
!= pvPtr
->buffer
) {
784 for (i
= 0; i
<= argc
; i
++) {
785 argv
[i
] = pvPtr
->buffer
+ (argv
[i
] - oldBuffer
);
787 oldBuffer
= pvPtr
->buffer
;
799 *--------------------------------------------------------------
801 * TclExpandParseValue --
803 * This procedure is commonly used as the value of the
804 * expandProc in a ParseValue. It uses malloc to allocate
805 * more space for the result of a parse.
808 * The buffer space in *pvPtr is reallocated to something
809 * larger, and if pvPtr->clientData is non-zero the old
810 * buffer is freed. Information is copied from the old
811 * buffer to the new one.
816 *--------------------------------------------------------------
820 TclExpandParseValue (
821 register ParseValue
*pvPtr
, /* Information about buffer that
822 * must be expanded. If the clientData
823 * in the structure is non-zero, it
824 * means that the current buffer is
825 * dynamically allocated. */
826 int needed
/* Minimum amount of additional space
834 * Either double the size of the buffer or add enough new space
835 * to meet the demand, whichever produces a larger new buffer.
838 newSpace
= (pvPtr
->end
- pvPtr
->buffer
) + 1;
839 if (newSpace
< needed
) {
842 newSpace
+= newSpace
;
844 new = (char *) ckalloc((unsigned) newSpace
);
847 * Copy from old buffer to new, free old buffer if needed, and
848 * mark new buffer as malloc-ed.
851 memcpy((VOID
*) new, (VOID
*) pvPtr
->buffer
, pvPtr
->next
- pvPtr
->buffer
);
852 pvPtr
->next
= new + (pvPtr
->next
- pvPtr
->buffer
);
853 if (pvPtr
->clientData
!= 0) {
854 ckfree(pvPtr
->buffer
);
857 pvPtr
->end
= new + newSpace
- 1;
858 pvPtr
->clientData
= (ClientData
) 1;
862 *----------------------------------------------------------------------
866 * Given a pointer into a Tcl command, find the end of the next
867 * word of the command.
870 * The return value is a pointer to the character just after the
871 * last one that's part of the word pointed to by "start". This
872 * may be the address of the NULL character at the end of the
878 *----------------------------------------------------------------------
883 char *start
, /* Beginning of a word of a Tcl command. */
884 int nested
/* Zero means this is a top-level command.
885 * One means this is a nested command (close
886 * brace is a word terminator). */
893 while (isspace(*p
)) {
898 * Handle words beginning with a double-quote or a brace.
902 p
= QuoteEnd(p
+1, '"');
903 } else if (*p
== '{') {
905 while (braces
!= 0) {
908 (void) Tcl_Backslash(p
, &count
);
913 } else if (*p
== '{') {
915 } else if (*p
== 0) {
922 * Handle words that don't start with a brace or double-quote.
923 * This code is also invoked if the word starts with a brace or
924 * double-quote and there is garbage after the closing brace or
925 * quote. This is an error as far as Tcl_Eval is concerned, but
926 * for here the garbage is treated as part of the word.
932 while ((*p
!= ']') && (*p
!= 0)) {
933 p
= TclWordEnd(p
, 1);
938 } else if (*p
== '\\') {
939 (void) Tcl_Backslash(p
, &count
);
941 } else if (*p
== '$') {
943 } else if (*p
== ';') {
945 * Note: semi-colon terminates a word
946 * and also counts as a word by itself.
953 } else if (isspace(*p
)) {
955 } else if ((*p
== ']') && nested
) {
965 *----------------------------------------------------------------------
969 * Given a pointer to a string that obeys the parsing conventions
970 * for quoted things in Tcl, find the end of that quoted thing.
971 * The actual thing may be a quoted argument or a parenthesized
975 * The return value is a pointer to the character just after the
976 * last one that is part of the quoted string.
981 *----------------------------------------------------------------------
986 char *string
, /* Pointer to character just after opening
988 int term
/* This character will terminate the
989 * quoted string (e.g. '"' or ')'). */
992 register char *p
= string
;
995 while ((*p
!= 0) && (*p
!= term
)) {
997 (void) Tcl_Backslash(p
, &count
);
999 } else if (*p
== '[') {
1001 while ((*p
!= ']') && (*p
!= 0)) {
1002 p
= TclWordEnd(p
, 1);
1007 } else if (*p
== '$') {
1017 *----------------------------------------------------------------------
1021 * Given a pointer to a variable reference using $-notation, find
1022 * the end of the variable name spec.
1025 * The return value is a pointer to the character just after the
1026 * last one that is part of the variable name.
1031 *----------------------------------------------------------------------
1036 char *string
/* Pointer to dollar-sign character. */
1039 register char *p
= string
+1;
1044 } while ((*p
!= '}') && (*p
!= 0));
1046 while (isalnum(*p
) || (*p
== '_')) {
1049 if ((*p
== '(') && (p
!= string
+1)) {
1050 p
= QuoteEnd(p
+1, ')');
1057 *----------------------------------------------------------------------
1061 * Given a string starting with a $ sign, parse off a variable
1062 * name and return its value.
1065 * The return value is the contents of the variable given by
1066 * the leading characters of string. If termPtr isn't NULL,
1067 * *termPtr gets filled in with the address of the character
1068 * just after the last one in the variable specifier. If the
1069 * variable doesn't exist, then the return value is NULL and
1070 * an error message will be left in interp->result.
1075 *----------------------------------------------------------------------
1080 Tcl_Interp
*interp
, /* Context for looking up variable. */
1081 register char *string
, /* String containing variable name.
1082 * First character must be "$". */
1083 char **termPtr
/* If non-NULL, points to word to fill
1084 * in with character just after last
1085 * one in the variable specifier. */
1089 char *name1
, *name1End
, c
, *result
;
1090 register char *name2
;
1091 #define NUM_CHARS 200
1092 char copyStorage
[NUM_CHARS
];
1096 * There are three cases:
1097 * 1. The $ sign is followed by an open curly brace. Then the variable
1098 * name is everything up to the next close curly brace, and the
1099 * variable is a scalar variable.
1100 * 2. The $ sign is not followed by an open curly brace. Then the
1101 * variable name is everything up to the next character that isn't
1102 * a letter, digit, or underscore. If the following character is an
1103 * open parenthesis, then the information between parentheses is
1104 * the array element name, which can include any of the substitutions
1105 * permissible between quotes.
1106 * 3. The $ sign is followed by something that isn't a letter, digit,
1107 * or underscore: in this case, there is no variable name, and "$"
1113 if (*string
== '{') {
1116 while (*string
!= '}') {
1118 Tcl_SetResult(interp
, "missing close-brace for variable name",
1131 while (isalnum(*string
) || (*string
== '_')) {
1134 if (string
== name1
) {
1141 if (*string
== '(') {
1145 * Perform substitutions on the array element name, just as
1146 * is done for quotes.
1149 pv
.buffer
= pv
.next
= copyStorage
;
1150 pv
.end
= copyStorage
+ NUM_CHARS
- 1;
1151 pv
.expandProc
= TclExpandParseValue
;
1152 pv
.clientData
= (ClientData
) NULL
;
1153 if (TclParseQuotes(interp
, string
+1, ')', 0, &end
, &pv
)
1156 sprintf(msg
, "\n (parsing index for array \"%.*s\")",
1157 string
-name1
, name1
);
1158 Tcl_AddErrorInfo(interp
, msg
);
1176 result
= Tcl_GetVar2(interp
, name1
, name2
, TCL_LEAVE_ERR_MSG
);
1180 if ((name2
!= NULL
) && (pv
.buffer
!= copyStorage
)) {