2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* $XConsortium: tclParse.c /main/2 1996/08/08 14:45:49 cde-hp $ */
27 * This file contains a collection of procedures that are used
28 * to parse Tcl commands or parts of commands (like quoted
29 * strings or nested sub-commands).
31 * Copyright (c) 1987-1993 The Regents of the University of California.
32 * Copyright (c) 1994-1996 Sun Microsystems, Inc.
34 * See the file "license.terms" for information on usage and redistribution
35 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
37 * SCCS: @(#) tclParse.c 1.50 96/03/02 14:46:55
44 * The following table assigns a type to each character. Only types
45 * meaningful to Tcl parsing are represented here. The table is
46 * designed to be referenced with either signed or unsigned characters,
47 * so it has 384 entries. The first 128 entries correspond to negative
48 * character values, the next 256 correspond to positive character
49 * values. The last 128 entries are identical to the first 128. The
50 * table is always indexed with a 128-byte offset (the 128th entry
51 * corresponds to a 0 character value).
54 char tclTypeTable[] = {
56 * Negative character values, from -128 to -1:
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_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
65 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
66 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
67 TCL_NORMAL, TCL_NORMAL, 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_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
73 TCL_NORMAL, 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_NORMAL,
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_NORMAL,
87 TCL_NORMAL, TCL_NORMAL, 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,
93 * Positive character values, from 0-127:
96 TCL_COMMAND_END, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
97 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
98 TCL_NORMAL, TCL_SPACE, TCL_COMMAND_END, TCL_SPACE,
99 TCL_SPACE, TCL_SPACE, TCL_NORMAL, TCL_NORMAL,
100 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
101 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
102 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
103 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
104 TCL_SPACE, TCL_NORMAL, TCL_QUOTE, TCL_NORMAL,
105 TCL_DOLLAR, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
106 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
107 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
108 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
109 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
110 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_COMMAND_END,
111 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
112 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
113 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
114 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
115 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
116 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
117 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
118 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_OPEN_BRACKET,
119 TCL_BACKSLASH, TCL_COMMAND_END, TCL_NORMAL, TCL_NORMAL,
120 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
121 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
122 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
123 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
124 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
125 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
126 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_OPEN_BRACE,
127 TCL_NORMAL, TCL_CLOSE_BRACE, TCL_NORMAL, TCL_NORMAL,
130 * Large unsigned character values, from 128-255:
133 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
134 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
135 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
136 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
137 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
138 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
139 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
140 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
141 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
142 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
143 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
144 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
145 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
146 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
147 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
148 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
149 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
150 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
151 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
152 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
153 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
154 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
155 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
156 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
157 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
158 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
159 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
160 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
161 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
162 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
163 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
164 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
168 * Function prototypes for procedures local to this file:
171 static char * QuoteEnd _ANSI_ARGS_((char *string, int term));
172 static char * ScriptEnd _ANSI_ARGS_((char *p, int nested));
173 static char * VarNameEnd _ANSI_ARGS_((char *string));
176 *----------------------------------------------------------------------
180 * Figure out how to handle a backslash sequence.
183 * The return value is the character that should be substituted
184 * in place of the backslash sequence that starts at src. If
185 * readPtr isn't NULL then it is filled in with a count of the
186 * number of characters in the backslash sequence.
191 *----------------------------------------------------------------------
195 Tcl_Backslash(src, readPtr)
196 char *src; /* Points to the backslash character of
197 * a backslash sequence. */
198 int *readPtr; /* Fill in with number of characters read
199 * from src, unless NULL. */
201 register char *p = src+1;
209 result = 0x7; /* Don't say '\a' here, since some compilers */
210 break; /* don't support it. */
230 if (isxdigit(UCHAR(p[1]))) {
233 result = (char) strtoul(p+1, &end, 16);
243 } while ((*p == ' ') || (*p == '\t'));
252 if (isdigit(UCHAR(*p))) {
253 result = (char)(*p - '0');
255 if (!isdigit(UCHAR(*p))) {
259 result = (char)((result << 3) + (*p - '0'));
261 if (!isdigit(UCHAR(*p))) {
265 result = (char)((result << 3) + (*p - '0'));
273 if (readPtr != NULL) {
280 *--------------------------------------------------------------
284 * This procedure parses a double-quoted string such as a
285 * quoted Tcl command argument or a quoted value in a Tcl
286 * expression. This procedure is also used to parse array
287 * element names within parentheses, or anything else that
288 * needs all the substitutions that happen in quotes.
291 * The return value is a standard Tcl result, which is
292 * TCL_OK unless there was an error while parsing the
293 * quoted string. If an error occurs then interp->result
294 * contains a standard error message. *TermPtr is filled
295 * in with the address of the character just after the
296 * last one successfully processed; this is usually the
297 * character just after the matching close-quote. The
298 * fully-substituted contents of the quotes are stored in
299 * standard fashion in *pvPtr, null-terminated with
300 * pvPtr->next pointing to the terminating null character.
303 * The buffer space in pvPtr may be enlarged by calling its
306 *--------------------------------------------------------------
310 TclParseQuotes(interp, string, termChar, flags, termPtr, pvPtr)
311 Tcl_Interp *interp; /* Interpreter to use for nested command
312 * evaluations and error messages. */
313 char *string; /* Character just after opening double-
315 int termChar; /* Character that terminates "quoted" string
316 * (usually double-quote, but sometimes
317 * right-paren or something else). */
318 int flags; /* Flags to pass to nested Tcl_Eval calls. */
319 char **termPtr; /* Store address of terminating character
321 ParseValue *pvPtr; /* Information about where to place
322 * fully-substituted result of parse. */
324 register char *src, *dst, c;
330 if (dst == pvPtr->end) {
332 * Target buffer space is about to run out. Make more space.
336 (*pvPtr->expandProc)(pvPtr, 1);
347 } else if (CHAR_TYPE(c) == TCL_NORMAL) {
352 } else if (c == '$') {
356 value = Tcl_ParseVar(interp, src-1, termPtr);
361 length = strlen(value);
362 if ((pvPtr->end - dst) <= length) {
364 (*pvPtr->expandProc)(pvPtr, length);
370 } else if (c == '[') {
374 result = TclParseNestedCmd(interp, src, flags, termPtr, pvPtr);
375 if (result != TCL_OK) {
381 } else if (c == '\\') {
385 *dst = Tcl_Backslash(src, &numRead);
389 } else if (c == '\0') {
390 Tcl_ResetResult(interp);
391 sprintf(interp->result, "missing %c", termChar);
401 *--------------------------------------------------------------
403 * TclParseNestedCmd --
405 * This procedure parses a nested Tcl command between
406 * brackets, returning the result of the command.
409 * The return value is a standard Tcl result, which is
410 * TCL_OK unless there was an error while executing the
411 * nested command. If an error occurs then interp->result
412 * contains a standard error message. *TermPtr is filled
413 * in with the address of the character just after the
414 * last one processed; this is usually the character just
415 * after the matching close-bracket, or the null character
416 * at the end of the string if the close-bracket was missing
417 * (a missing close bracket is an error). The result returned
418 * by the command is stored in standard fashion in *pvPtr,
419 * null-terminated, with pvPtr->next pointing to the null
423 * The storage space at *pvPtr may be expanded.
425 *--------------------------------------------------------------
429 TclParseNestedCmd(interp, string, flags, termPtr, pvPtr)
430 Tcl_Interp *interp; /* Interpreter to use for nested command
431 * evaluations and error messages. */
432 char *string; /* Character just after opening bracket. */
433 int flags; /* Flags to pass to nested Tcl_Eval. */
434 char **termPtr; /* Store address of terminating character
436 register ParseValue *pvPtr; /* Information about where to place
437 * result of command. */
439 int result, length, shortfall;
440 Interp *iPtr = (Interp *) interp;
442 iPtr->evalFlags = flags | TCL_BRACKET_TERM;
443 result = Tcl_Eval(interp, string);
444 *termPtr = iPtr->termPtr;
445 if (result != TCL_OK) {
447 * The increment below results in slightly cleaner message in
448 * the errorInfo variable (the close-bracket will appear).
451 if (**termPtr == ']') {
457 length = strlen(iPtr->result);
458 shortfall = length + 1 - (pvPtr->end - pvPtr->next);
460 (*pvPtr->expandProc)(pvPtr, shortfall);
462 strcpy(pvPtr->next, iPtr->result);
463 pvPtr->next += length;
464 Tcl_FreeResult(iPtr);
465 iPtr->result = iPtr->resultSpace;
466 iPtr->resultSpace[0] = '\0';
471 *--------------------------------------------------------------
475 * This procedure scans the information between matching
479 * The return value is a standard Tcl result, which is
480 * TCL_OK unless there was an error while parsing string.
481 * If an error occurs then interp->result contains a
482 * standard error message. *TermPtr is filled
483 * in with the address of the character just after the
484 * last one successfully processed; this is usually the
485 * character just after the matching close-brace. The
486 * information between curly braces is stored in standard
487 * fashion in *pvPtr, null-terminated with pvPtr->next
488 * pointing to the terminating null character.
491 * The storage space at *pvPtr may be expanded.
493 *--------------------------------------------------------------
497 TclParseBraces(interp, string, termPtr, pvPtr)
498 Tcl_Interp *interp; /* Interpreter to use for nested command
499 * evaluations and error messages. */
500 char *string; /* Character just after opening bracket. */
501 char **termPtr; /* Store address of terminating character
503 register ParseValue *pvPtr; /* Information about where to place
504 * result of command. */
507 register char *src, *dst, *end;
516 * Copy the characters one at a time to the result area, stopping
517 * when the matching close-brace is found.
525 (*pvPtr->expandProc)(pvPtr, 20);
531 if (CHAR_TYPE(c) == TCL_NORMAL) {
533 } else if (c == '{') {
535 } else if (c == '}') {
538 dst--; /* Don't copy the last close brace. */
541 } else if (c == '\\') {
545 * Must always squish out backslash-newlines, even when in
546 * braces. This is needed so that this sequence can appear
547 * anywhere in a command, such as the middle of an expression.
551 dst[-1] = Tcl_Backslash(src-1, &count);
554 (void) Tcl_Backslash(src-1, &count);
558 (*pvPtr->expandProc)(pvPtr, 20);
568 } else if (c == '\0') {
569 Tcl_SetResult(interp, "missing close-brace", TCL_STATIC);
582 *--------------------------------------------------------------
586 * This procedure parses one or more words from a command
587 * string and creates argv-style pointers to fully-substituted
588 * copies of those words.
591 * The return value is a standard Tcl result.
593 * *argcPtr is modified to hold a count of the number of words
594 * successfully parsed, which may be 0. At most maxWords words
595 * will be parsed. If 0 <= *argcPtr < maxWords then it
596 * means that a command separator was seen. If *argcPtr
597 * is maxWords then it means that a command separator was
600 * *TermPtr is filled in with the address of the character
601 * just after the last one successfully processed in the
602 * last word. This is either the command terminator (if
603 * *argcPtr < maxWords), the character just after the last
604 * one in a word (if *argcPtr is maxWords), or the vicinity
605 * of an error (if the result is not TCL_OK).
607 * The pointers at *argv are filled in with pointers to the
608 * fully-substituted words, and the actual contents of the
609 * words are copied to the buffer at pvPtr.
611 * If an error occurrs then an error message is left in
612 * interp->result and the information at *argv, *argcPtr,
613 * and *pvPtr may be incomplete.
616 * The buffer space in pvPtr may be enlarged by calling its
619 *--------------------------------------------------------------
623 TclParseWords(interp, string, flags, maxWords, termPtr, argcPtr, argv, pvPtr)
624 Tcl_Interp *interp; /* Interpreter to use for nested command
625 * evaluations and error messages. */
626 char *string; /* First character of word. */
627 int flags; /* Flags to control parsing (same values as
628 * passed to Tcl_Eval). */
629 int maxWords; /* Maximum number of words to parse. */
630 char **termPtr; /* Store address of terminating character
632 int *argcPtr; /* Filled in with actual number of words
634 char **argv; /* Store addresses of individual words here. */
635 register ParseValue *pvPtr; /* Information about where to place
636 * fully-substituted word. */
638 register char *src, *dst;
640 int type, result, argc;
641 char *oldBuffer; /* Used to detect when pvPtr's buffer gets
642 * reallocated, so we can adjust all of the
646 oldBuffer = pvPtr->buffer;
648 for (argc = 0; argc < maxWords; argc++) {
652 * Skip leading space.
658 while (type == TCL_SPACE) {
665 * Handle the normal case (i.e. no leading double-quote or brace).
668 if (type == TCL_NORMAL) {
671 if (dst == pvPtr->end) {
673 * Target buffer space is about to run out. Make
678 (*pvPtr->expandProc)(pvPtr, 1);
682 if (type == TCL_NORMAL) {
687 } else if (type == TCL_SPACE) {
689 } else if (type == TCL_DOLLAR) {
693 value = Tcl_ParseVar(interp, src, termPtr);
698 length = strlen(value);
699 if ((pvPtr->end - dst) <= length) {
701 (*pvPtr->expandProc)(pvPtr, length);
706 } else if (type == TCL_COMMAND_END) {
707 if ((c == ']') && !(flags & TCL_BRACKET_TERM)) {
712 * End of command; simulate a word-end first, so
713 * that the end-of-command can be processed as the
714 * first thing in a new word.
718 } else if (type == TCL_OPEN_BRACKET) {
720 result = TclParseNestedCmd(interp, src+1, flags, termPtr,
722 if (result != TCL_OK) {
727 } else if (type == TCL_BACKSLASH) {
730 *dst = Tcl_Backslash(src, &numRead);
733 * The following special check allows a backslash-newline
734 * to be treated as a word-separator, as if the backslash
735 * and newline had been collapsed before command parsing
739 if (src[1] == '\n') {
754 * Check for the end of the command.
757 if (type == TCL_COMMAND_END) {
758 if (flags & TCL_BRACKET_TERM) {
760 Tcl_SetResult(interp, "missing close-bracket",
773 * Now handle the special cases: open braces, double-quotes,
774 * and backslash-newline.
778 if (type == TCL_QUOTE) {
779 result = TclParseQuotes(interp, src+1, '"', flags,
781 } else if (type == TCL_OPEN_BRACE) {
782 result = TclParseBraces(interp, src+1, termPtr, pvPtr);
783 } else if ((type == TCL_BACKSLASH) && (src[1] == '\n')) {
785 * This code is needed so that a backslash-newline at the
786 * very beginning of a word is treated as part of the white
787 * space between words and not as a space within the word.
795 if (result != TCL_OK) {
800 * Back from quotes or braces; make sure that the terminating
801 * character was the end of the word.
805 if ((c == '\\') && ((*termPtr)[1] == '\n')) {
807 * Line is continued on next line; the backslash-newline
808 * sequence turns into space, which is OK. No need to do
813 if ((type != TCL_SPACE) && (type != TCL_COMMAND_END)) {
815 Tcl_SetResult(interp,
816 "extra characters after close-quote",
819 Tcl_SetResult(interp,
820 "extra characters after close-brace",
831 * We're at the end of a word, so add a null terminator. Then
832 * see if the buffer was re-allocated during this word. If so,
833 * update all of the argv pointers.
839 if (oldBuffer != pvPtr->buffer) {
842 for (i = 0; i <= argc; i++) {
843 argv[i] = pvPtr->buffer + (argv[i] - oldBuffer);
845 oldBuffer = pvPtr->buffer;
857 *--------------------------------------------------------------
859 * TclExpandParseValue --
861 * This procedure is commonly used as the value of the
862 * expandProc in a ParseValue. It uses malloc to allocate
863 * more space for the result of a parse.
866 * The buffer space in *pvPtr is reallocated to something
867 * larger, and if pvPtr->clientData is non-zero the old
868 * buffer is freed. Information is copied from the old
869 * buffer to the new one.
874 *--------------------------------------------------------------
878 TclExpandParseValue(pvPtr, needed)
879 register ParseValue *pvPtr; /* Information about buffer that
880 * must be expanded. If the clientData
881 * in the structure is non-zero, it
882 * means that the current buffer is
883 * dynamically allocated. */
884 int needed; /* Minimum amount of additional space
891 * Either double the size of the buffer or add enough new space
892 * to meet the demand, whichever produces a larger new buffer.
895 newSpace = (pvPtr->end - pvPtr->buffer) + 1;
896 if (newSpace < needed) {
899 newSpace += newSpace;
901 new = (char *) ckalloc((unsigned) newSpace);
904 * Copy from old buffer to new, free old buffer if needed, and
905 * mark new buffer as malloc-ed.
908 memcpy((VOID *) new, (VOID *) pvPtr->buffer,
909 (size_t) (pvPtr->next - pvPtr->buffer));
910 pvPtr->next = new + (pvPtr->next - pvPtr->buffer);
911 if (pvPtr->clientData != 0) {
912 ckfree(pvPtr->buffer);
915 pvPtr->end = new + newSpace - 1;
916 pvPtr->clientData = (ClientData) 1;
920 *----------------------------------------------------------------------
924 * Given a pointer into a Tcl command, find the end of the next
925 * word of the command.
928 * The return value is a pointer to the last character that's part
929 * of the word pointed to by "start". If the word doesn't end
930 * properly within the string then the return value is the address
931 * of the null character at the end of the string.
936 *----------------------------------------------------------------------
940 TclWordEnd(start, nested, semiPtr)
941 char *start; /* Beginning of a word of a Tcl command. */
942 int nested; /* Zero means this is a top-level command.
943 * One means this is a nested command (close
944 * bracket is a word terminator). */
945 int *semiPtr; /* Set to 1 if word ends with a command-
946 * terminating semi-colon, zero otherwise.
947 * If NULL then ignored. */
952 if (semiPtr != NULL) {
957 * Skip leading white space (backslash-newline must be treated like
958 * white-space, except that it better not be the last thing in the
962 for (p = start; ; p++) {
963 if (isspace(UCHAR(*p))) {
966 if ((p[0] == '\\') && (p[1] == '\n')) {
976 * Handle words beginning with a double-quote or a brace.
980 p = QuoteEnd(p+1, '"');
985 } else if (*p == '{') {
987 while (braces != 0) {
990 (void) Tcl_Backslash(p, &count);
995 } else if (*p == '{') {
997 } else if (*p == 0) {
1005 * Handle words that don't start with a brace or double-quote.
1006 * This code is also invoked if the word starts with a brace or
1007 * double-quote and there is garbage after the closing brace or
1008 * quote. This is an error as far as Tcl_Eval is concerned, but
1009 * for here the garbage is treated as part of the word.
1014 p = ScriptEnd(p+1, 1);
1019 } else if (*p == '\\') {
1022 * Backslash-newline: it maps to a space character
1023 * that is a word separator, so the word ends just before
1029 (void) Tcl_Backslash(p, &count);
1031 } else if (*p == '$') {
1037 } else if (*p == ';') {
1039 * Include the semi-colon in the word that is returned.
1042 if (semiPtr != NULL) {
1046 } else if (isspace(UCHAR(*p))) {
1048 } else if ((*p == ']') && nested) {
1050 } else if (*p == 0) {
1053 * Nested commands can't end because of the end of the
1066 *----------------------------------------------------------------------
1070 * Given a pointer to a string that obeys the parsing conventions
1071 * for quoted things in Tcl, find the end of that quoted thing.
1072 * The actual thing may be a quoted argument or a parenthesized
1076 * The return value is a pointer to the last character that is
1077 * part of the quoted string (i.e the character that's equal to
1078 * term). If the quoted string doesn't terminate properly then
1079 * the return value is a pointer to the null character at the
1080 * end of the string.
1085 *----------------------------------------------------------------------
1089 QuoteEnd(string, term)
1090 char *string; /* Pointer to character just after opening
1092 int term; /* This character will terminate the
1093 * quoted string (e.g. '"' or ')'). */
1095 register char *p = string;
1098 while (*p != term) {
1100 (void) Tcl_Backslash(p, &count);
1102 } else if (*p == '[') {
1103 for (p++; *p != ']'; p++) {
1104 p = TclWordEnd(p, 1, (int *) NULL);
1110 } else if (*p == '$') {
1116 } else if (*p == 0) {
1126 *----------------------------------------------------------------------
1130 * Given a pointer to a variable reference using $-notation, find
1131 * the end of the variable name spec.
1134 * The return value is a pointer to the last character that
1135 * is part of the variable name. If the variable name doesn't
1136 * terminate properly then the return value is a pointer to the
1137 * null character at the end of the string.
1142 *----------------------------------------------------------------------
1147 char *string; /* Pointer to dollar-sign character. */
1149 register char *p = string+1;
1152 for (p++; (*p != '}') && (*p != 0); p++) {
1153 /* Empty loop body. */
1157 while (isalnum(UCHAR(*p)) || (*p == '_')) {
1160 if ((*p == '(') && (p != string+1)) {
1161 return QuoteEnd(p+1, ')');
1168 *----------------------------------------------------------------------
1172 * Given a pointer to the beginning of a Tcl script, find the end of
1176 * The return value is a pointer to the last character that's part
1177 * of the script pointed to by "p". If the command doesn't end
1178 * properly within the string then the return value is the address
1179 * of the null character at the end of the string.
1184 *----------------------------------------------------------------------
1188 ScriptEnd(p, nested)
1189 char *p; /* Script to check. */
1190 int nested; /* Zero means this is a top-level command.
1191 * One means this is a nested command (the
1192 * last character of the script must be
1193 * an unquoted ]). */
1199 while (isspace(UCHAR(*p))) {
1205 if ((*p == '#') && commentOK) {
1209 * If the script ends with backslash-newline, then
1210 * this command isn't complete.
1213 if ((p[1] == '\n') && (p[2] == 0)) {
1216 Tcl_Backslash(p, &length);
1221 } while ((*p != 0) && (*p != '\n'));
1224 p = TclWordEnd(p, nested, &commentOK);
1242 *----------------------------------------------------------------------
1246 * Given a string starting with a $ sign, parse off a variable
1247 * name and return its value.
1250 * The return value is the contents of the variable given by
1251 * the leading characters of string. If termPtr isn't NULL,
1252 * *termPtr gets filled in with the address of the character
1253 * just after the last one in the variable specifier. If the
1254 * variable doesn't exist, then the return value is NULL and
1255 * an error message will be left in interp->result.
1260 *----------------------------------------------------------------------
1264 Tcl_ParseVar(interp, string, termPtr)
1265 Tcl_Interp *interp; /* Context for looking up variable. */
1266 register char *string; /* String containing variable name.
1267 * First character must be "$". */
1268 char **termPtr; /* If non-NULL, points to word to fill
1269 * in with character just after last
1270 * one in the variable specifier. */
1273 char *name1, *name1End, c, *result;
1274 register char *name2;
1275 #define NUM_CHARS 200
1276 char copyStorage[NUM_CHARS];
1280 * There are three cases:
1281 * 1. The $ sign is followed by an open curly brace. Then the variable
1282 * name is everything up to the next close curly brace, and the
1283 * variable is a scalar variable.
1284 * 2. The $ sign is not followed by an open curly brace. Then the
1285 * variable name is everything up to the next character that isn't
1286 * a letter, digit, or underscore. If the following character is an
1287 * open parenthesis, then the information between parentheses is
1288 * the array element name, which can include any of the substitutions
1289 * permissible between quotes.
1290 * 3. The $ sign is followed by something that isn't a letter, digit,
1291 * or underscore: in this case, there is no variable name, and "$"
1297 if (*string == '{') {
1300 while (*string != '}') {
1302 Tcl_SetResult(interp, "missing close-brace for variable name",
1315 while (isalnum(UCHAR(*string)) || (*string == '_')) {
1318 if (string == name1) {
1325 if (*string == '(') {
1329 * Perform substitutions on the array element name, just as
1330 * is done for quotes.
1333 pv.buffer = pv.next = copyStorage;
1334 pv.end = copyStorage + NUM_CHARS - 1;
1335 pv.expandProc = TclExpandParseValue;
1336 pv.clientData = (ClientData) NULL;
1337 if (TclParseQuotes(interp, string+1, ')', 0, &end, &pv)
1342 length = string-name1;
1346 sprintf(msg, "\n (parsing index for array \"%.*s\")",
1348 Tcl_AddErrorInfo(interp, msg);
1356 Tcl_ResetResult(interp);
1365 if (((Interp *) interp)->noEval) {
1370 result = Tcl_GetVar2(interp, name1, name2, TCL_LEAVE_ERR_MSG);
1374 if ((name2 != NULL) && (pv.buffer != copyStorage)) {
1381 *----------------------------------------------------------------------
1383 * Tcl_CommandComplete --
1385 * Given a partial or complete Tcl command, this procedure
1386 * determines whether the command is complete in the sense
1387 * of having matched braces and quotes and brackets.
1390 * 1 is returned if the command is complete, 0 otherwise.
1395 *----------------------------------------------------------------------
1399 Tcl_CommandComplete(cmd)
1400 char *cmd; /* Command to check. */
1407 p = ScriptEnd(cmd, 0);