4 * Contains a collection of procedures that are used to parse Tcl
5 * commands or parts of commands (like quoted strings or nested
8 * Since Tcl 8.1.0 these routines have been replaced by ones that
9 * generate byte-codes. But since these routines are used in
10 * vector expressions, where no such byte-compilation is
11 * necessary, I now include them. In fact, the byte-compiled
12 * versions would be slower since the compiled code typically
15 * Copyright (c) 1987-1993 The Regents of the University of California.
16 * Copyright (c) 19941998 Sun Microsystems, Inc.
22 #if (TCL_VERSION_NUMBER >= _VERSION(8,1,0))
23 #include "bltInterp.h"
26 * A table used to classify input characters to assist in parsing
27 * Tcl commands. The table should be indexed with a signed character
28 * using the CHAR_TYPE macro. The character may have a negative
29 * value. The CHAR_TYPE macro takes a pointer to a signed character
30 * and a pointer to the last character in the source string. If the
31 * src pointer is pointing at the terminating null of the string,
32 * CHAR_TYPE returns TCL_COMMAND_END.
35 #define STATIC_STRING_SPACE 150
36 #define UCHAR(c) ((unsigned char) (c))
37 #define TCL_NORMAL 0x01
38 #define TCL_SPACE 0x02
39 #define TCL_COMMAND_END 0x04
40 #define TCL_QUOTE 0x08
41 #define TCL_OPEN_BRACKET 0x10
42 #define TCL_OPEN_BRACE 0x20
43 #define TCL_CLOSE_BRACE 0x40
44 #define TCL_BACKSLASH 0x80
45 #define TCL_DOLLAR 0x00
48 * The following table assigns a type to each character. Only types
49 * meaningful to Tcl parsing are represented here. The table is
50 * designed to be referenced with either signed or unsigned characters,
51 * so it has 384 entries. The first 128 entries correspond to negative
52 * character values, the next 256 correspond to positive character
53 * values. The last 128 entries are identical to the first 128. The
54 * table is always indexed with a 128-byte offset (the 128th entry
55 * corresponds to a 0 character value).
58 static unsigned char tclTypeTable[] =
61 * Negative character values, from -128 to -1:
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,
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_NORMAL,
95 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
98 * Positive character values, from 0-127:
101 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
102 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
103 TCL_NORMAL, TCL_SPACE, TCL_COMMAND_END, TCL_SPACE,
104 TCL_SPACE, TCL_SPACE, TCL_NORMAL, TCL_NORMAL,
105 TCL_NORMAL, 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_SPACE, TCL_NORMAL, TCL_QUOTE, TCL_NORMAL,
110 TCL_DOLLAR, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
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_COMMAND_END,
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_NORMAL,
119 TCL_NORMAL, TCL_NORMAL, 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_OPEN_BRACKET,
124 TCL_BACKSLASH, TCL_COMMAND_END, TCL_NORMAL, TCL_NORMAL,
125 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
126 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
127 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
128 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
129 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
130 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
131 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_OPEN_BRACE,
132 TCL_NORMAL, TCL_CLOSE_BRACE, TCL_NORMAL, TCL_NORMAL,
135 * Large unsigned character values, from 128-255:
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,
165 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
166 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
167 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
168 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
169 TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
172 #define CHAR_TYPE(src,last) \
173 (((src)==(last))?TCL_COMMAND_END:(tclTypeTable+128)[(int)*(src)])
176 *--------------------------------------------------------------
178 * Blt_ParseNestedCmd --
180 * This procedure parses a nested Tcl command between
181 * brackets, returning the result of the command.
184 * The return value is a standard Tcl result, which is
185 * TCL_OK unless there was an error while executing the
186 * nested command. If an error occurs then interp->result
187 * contains a standard error message. *TermPtr is filled
188 * in with the address of the character just after the
189 * last one processed; this is usually the character just
190 * after the matching close-bracket, or the null character
191 * at the end of the string if the close-bracket was missing
192 * (a missing close bracket is an error). The result returned
193 * by the command is stored in standard fashion in *parsePtr,
194 * null-terminated, with parsePtr->next pointing to the null
198 * The storage space at *parsePtr may be expanded.
200 *--------------------------------------------------------------
203 Blt_ParseNestedCmd(interp, string, flags, termPtr, parsePtr)
204 Tcl_Interp *interp; /* Interpreter to use for nested command
205 * evaluations and error messages. */
206 char *string; /* Character just after opening bracket. */
207 int flags; /* Flags to pass to nested Tcl_Eval. */
208 char **termPtr; /* Store address of terminating character
210 ParseValue *parsePtr; /* Information about where to place
211 * result of command. */
213 int result, length, shortfall;
214 Interp *iPtr = (Interp *) interp;
216 iPtr->evalFlags = flags | TCL_BRACKET_TERM;
217 result = Tcl_Eval(interp, string);
218 *termPtr = (string + iPtr->termOffset);
219 if (result != TCL_OK) {
221 * The increment below results in slightly cleaner message in
222 * the errorInfo variable (the close-bracket will appear).
225 if (**termPtr == ']') {
231 length = strlen(iPtr->result);
232 shortfall = length + 1 - (parsePtr->end - parsePtr->next);
234 (*parsePtr->expandProc) (parsePtr, shortfall);
236 strcpy(parsePtr->next, iPtr->result);
237 parsePtr->next += length;
239 Tcl_FreeResult(interp);
240 iPtr->result = iPtr->resultSpace;
241 iPtr->resultSpace[0] = '\0';
246 *--------------------------------------------------------------
250 * This procedure scans the information between matching
254 * The return value is a standard Tcl result, which is
255 * TCL_OK unless there was an error while parsing string.
256 * If an error occurs then interp->result contains a
257 * standard error message. *TermPtr is filled
258 * in with the address of the character just after the
259 * last one successfully processed; this is usually the
260 * character just after the matching close-brace. The
261 * information between curly braces is stored in standard
262 * fashion in *parsePtr, null-terminated with parsePtr->next
263 * pointing to the terminating null character.
266 * The storage space at *parsePtr may be expanded.
268 *--------------------------------------------------------------
272 Blt_ParseBraces(interp, string, termPtr, parsePtr)
273 Tcl_Interp *interp; /* Interpreter to use for nested command
274 * evaluations and error messages. */
275 char *string; /* Character just after opening bracket. */
276 char **termPtr; /* Store address of terminating character
278 ParseValue *parsePtr; /* Information about where to place
279 * result of command. */
282 register char *src, *dest, *end;
284 char *lastChar = string + strlen(string);
287 dest = parsePtr->next;
292 * Copy the characters one at a time to the result area, stopping
293 * when the matching close-brace is found.
301 parsePtr->next = dest;
302 (*parsePtr->expandProc) (parsePtr, 20);
303 dest = parsePtr->next;
309 if (CHAR_TYPE(src - 1, lastChar) == TCL_NORMAL) {
311 } else if (c == '{') {
313 } else if (c == '}') {
316 dest--; /* Don't copy the last close brace. */
319 } else if (c == '\\') {
323 * Must always squish out backslash-newlines, even when in
324 * braces. This is needed so that this sequence can appear
325 * anywhere in a command, such as the middle of an expression.
329 dest[-1] = Tcl_Backslash(src - 1, &count);
332 Tcl_Backslash(src - 1, &count);
335 parsePtr->next = dest;
336 (*parsePtr->expandProc) (parsePtr, 20);
337 dest = parsePtr->next;
346 } else if (c == '\0') {
347 Tcl_AppendResult(interp, "missing close-brace", (char *)NULL);
348 *termPtr = string - 1;
354 parsePtr->next = dest;
360 *--------------------------------------------------------------
362 * Blt_ExpandParseValue --
364 * This procedure is commonly used as the value of the
365 * expandProc in a ParseValue. It uses malloc to allocate
366 * more space for the result of a parse.
369 * The buffer space in *parsePtr is reallocated to something
370 * larger, and if parsePtr->clientData is non-zero the old
371 * buffer is freed. Information is copied from the old
372 * buffer to the new one.
377 *--------------------------------------------------------------
380 Blt_ExpandParseValue(parsePtr, needed)
381 ParseValue *parsePtr; /* Information about buffer that
382 * must be expanded. If the clientData
383 * in the structure is non-zero, it
384 * means that the current buffer is
385 * dynamically allocated. */
386 int needed; /* Minimum amount of additional space
393 * Either double the size of the buffer or add enough new space
394 * to meet the demand, whichever produces a larger new buffer.
396 size = (parsePtr->end - parsePtr->buffer) + 1;
402 buffer = Blt_Malloc((unsigned int)size);
405 * Copy from old buffer to new, free old buffer if needed, and
406 * mark new buffer as malloc-ed.
408 memcpy((VOID *) buffer, (VOID *) parsePtr->buffer,
409 (size_t) (parsePtr->next - parsePtr->buffer));
410 parsePtr->next = buffer + (parsePtr->next - parsePtr->buffer);
411 if (parsePtr->clientData != 0) {
412 Blt_Free(parsePtr->buffer);
414 parsePtr->buffer = buffer;
415 parsePtr->end = buffer + size - 1;
416 parsePtr->clientData = (ClientData)1;
420 *--------------------------------------------------------------
424 * This procedure parses a double-quoted string such as a
425 * quoted Tcl command argument or a quoted value in a Tcl
426 * expression. This procedure is also used to parse array
427 * element names within parentheses, or anything else that
428 * needs all the substitutions that happen in quotes.
431 * The return value is a standard Tcl result, which is
432 * TCL_OK unless there was an error while parsing the
433 * quoted string. If an error occurs then interp->result
434 * contains a standard error message. *TermPtr is filled
435 * in with the address of the character just after the
436 * last one successfully processed; this is usually the
437 * character just after the matching close-quote. The
438 * fully-substituted contents of the quotes are stored in
439 * standard fashion in *parsePtr, null-terminated with
440 * parsePtr->next pointing to the terminating null character.
443 * The buffer space in parsePtr may be enlarged by calling its
446 *--------------------------------------------------------------
449 Blt_ParseQuotes(interp, string, termChar, flags, termPtr, parsePtr)
450 Tcl_Interp *interp; /* Interpreter to use for nested command
451 * evaluations and error messages. */
452 char *string; /* Character just after opening double-
454 int termChar; /* Character that terminates "quoted" string
455 * (usually double-quote, but sometimes
456 * right-paren or something else). */
457 int flags; /* Flags to pass to nested Tcl_Eval calls. */
458 char **termPtr; /* Store address of terminating character
460 ParseValue *parsePtr; /* Information about where to place
461 * fully-substituted result of parse. */
463 register char *src, *dest, c;
464 char *lastChar = string + strlen(string);
467 dest = parsePtr->next;
470 if (dest == parsePtr->end) {
472 * Target buffer space is about to run out. Make more space.
474 parsePtr->next = dest;
475 (*parsePtr->expandProc) (parsePtr, 1);
476 dest = parsePtr->next;
482 parsePtr->next = dest;
485 } else if (CHAR_TYPE(src - 1, lastChar) == TCL_NORMAL) {
490 } else if (c == '$') {
494 value = Tcl_ParseVar(interp, src - 1, termPtr);
499 length = strlen(value);
500 if ((parsePtr->end - dest) <= length) {
501 parsePtr->next = dest;
502 (*parsePtr->expandProc) (parsePtr, length);
503 dest = parsePtr->next;
508 } else if (c == '[') {
511 parsePtr->next = dest;
512 result = Blt_ParseNestedCmd(interp, src, flags, termPtr, parsePtr);
513 if (result != TCL_OK) {
517 dest = parsePtr->next;
519 } else if (c == '\\') {
523 *dest = Tcl_Backslash(src, &nRead);
527 } else if (c == '\0') {
530 Tcl_ResetResult(interp);
531 sprintf(buf, "missing %c", termChar);
532 Tcl_SetResult(interp, buf, TCL_VOLATILE);
533 *termPtr = string - 1;
541 #endif /* TCL_VERSION_NUMBER >= _VERSION(8,1,0) */