]>
git.zerfleddert.de Git - micropolis/blob - src/tcl/tclutil.c
13071c2338dc25e1edf036a4f0797547823691cb
4 * This file contains utility procedures that are used by many Tcl
7 * Copyright 1987-1991 Regents of the University of California
8 * Permission to use, copy, modify, and distribute this
9 * software and its documentation for any purpose and without
10 * fee is hereby granted, provided that the above copyright
11 * notice appear in all copies. The University of California
12 * makes no representations about the suitability of this
13 * software for any purpose. It is provided "as is" without
14 * express or implied warranty.
18 static char rcsid
[] = "$Header: /user6/ouster/tcl/RCS/tclUtil.c,v 1.63 92/07/02 08:50:54 ouster Exp $ SPRITE (Berkeley)";
24 * The following values are used in the flags returned by Tcl_ScanElement
25 * and used by Tcl_ConvertElement. The value TCL_DONT_USE_BRACES is also
26 * defined in tcl.h; make sure its value doesn't overlap with any of the
29 * TCL_DONT_USE_BRACES - 1 means the string mustn't be enclosed in
30 * braces (e.g. it contains unmatched braces,
31 * or ends in a backslash character, or user
32 * just doesn't want braces); handle all
33 * special characters by adding backslashes.
34 * USE_BRACES - 1 means the string contains a special
35 * character that can be handled simply by
36 * enclosing the entire argument in braces.
37 * BRACES_UNMATCHED - 1 means that braces aren't properly matched
42 #define BRACES_UNMATCHED 4
45 * The variable below is set to NULL before invoking regexp functions
46 * and checked after those functions. If an error occurred then regerror
47 * will set the variable to point to a (static) error message. This
48 * mechanism unfortunately does not support multi-threading, but then
49 * neither does the rest of the regexp facilities.
52 char *tclRegexpError
= NULL
;
55 * Function prototypes for local procedures in this file:
58 static void SetupAppendBuffer
_ANSI_ARGS_((Interp
*iPtr
,
62 *----------------------------------------------------------------------
66 * Given a pointer into a Tcl list, locate the first (or next)
67 * element in the list.
70 * The return value is normally TCL_OK, which means that the
71 * element was successfully located. If TCL_ERROR is returned
72 * it means that list didn't have proper list structure;
73 * interp->result contains a more detailed error message.
75 * If TCL_OK is returned, then *elementPtr will be set to point
76 * to the first element of list, and *nextPtr will be set to point
77 * to the character just after any white space following the last
78 * character that's part of the element. If this is the last argument
79 * in the list, then *nextPtr will point to the NULL character at the
80 * end of list. If sizePtr is non-NULL, *sizePtr is filled in with
81 * the number of characters in the element. If the element is in
82 * braces, then *elementPtr will point to the character after the
83 * opening brace and *sizePtr will not include either of the braces.
84 * If there isn't an element in the list, *sizePtr will be zero, and
85 * both *elementPtr and *termPtr will refer to the null character at
86 * the end of list. Note: this procedure does NOT collapse backslash
92 *----------------------------------------------------------------------
96 TclFindElement(interp
, list
, elementPtr
, nextPtr
, sizePtr
, bracePtr
)
97 Tcl_Interp
*interp
; /* Interpreter to use for error reporting. */
98 register char *list
; /* String containing Tcl list with zero
99 * or more elements (possibly in braces). */
100 char **elementPtr
; /* Fill in with location of first significant
101 * character in first element of list. */
102 char **nextPtr
; /* Fill in with location of character just
103 * after all white space following end of
104 * argument (i.e. next argument or end of
106 int *sizePtr
; /* If non-zero, fill in with size of
108 int *bracePtr
; /* If non-zero fill in with non-zero/zero
109 * to indicate that arg was/wasn't
118 * Skim off leading white space and check for an opening brace or
119 * quote. Note: use of "isascii" below and elsewhere in this
120 * procedure is a temporary workaround (7/27/90) because Mx uses characters
121 * with the high-order bit set for some things. This should probably
122 * be changed back eventually, or all of Tcl should call isascii.
125 while (isascii(*list
) && isspace(*list
)) {
131 } else if (*list
== '"') {
136 *bracePtr
= openBraces
;
141 * Find the end of the element (either a space or a close brace or
142 * the end of the string).
149 * Open brace: don't treat specially unless the element is
150 * in braces. In this case, keep a nesting count.
154 if (openBraces
!= 0) {
160 * Close brace: if element is in braces, keep nesting
161 * count and quit when the last close brace is seen.
165 if (openBraces
== 1) {
170 if ((isascii(*p
) && isspace(*p
)) || (*p
== 0)) {
173 for (p2
= p
; (*p2
!= 0) && (!isspace(*p2
)) && (p2
< p
+20);
177 Tcl_ResetResult(interp
);
178 sprintf(interp
->result
,
179 "list element in braces followed by \"%.*s\" instead of space",
182 } else if (openBraces
!= 0) {
188 * Backslash: skip over everything up to the end of the
189 * backslash sequence.
195 (void) Tcl_Backslash(p
, &size
);
201 * Space: ignore if element is in braces or quotes; otherwise
211 if ((openBraces
== 0) && !inQuotes
) {
218 * Double-quote: if element is in quotes then terminate it.
227 if ((isascii(*p
) && isspace(*p
)) || (*p
== 0)) {
230 for (p2
= p
; (*p2
!= 0) && (!isspace(*p2
)) && (p2
< p
+20);
234 Tcl_ResetResult(interp
);
235 sprintf(interp
->result
,
236 "list element in quotes followed by \"%.*s\" %s",
237 p2
-p
, p
, "instead of space");
243 * End of list: terminate element.
247 if (openBraces
!= 0) {
248 Tcl_SetResult(interp
, "unmatched open brace in list",
251 } else if (inQuotes
) {
252 Tcl_SetResult(interp
, "unmatched open quote in list",
264 while (isascii(*p
) && isspace(*p
)) {
276 *----------------------------------------------------------------------
278 * TclCopyAndCollapse --
280 * Copy a string and eliminate any backslashes that aren't in braces.
283 * There is no return value. Count chars. get copied from src
284 * to dst. Along the way, if backslash sequences are found outside
285 * braces, the backslashes are eliminated in the copy.
286 * After scanning count chars. from source, a null character is
287 * placed at the end of dst.
292 *----------------------------------------------------------------------
296 TclCopyAndCollapse(count
, src
, dst
)
297 int count
; /* Total number of characters to copy
299 register char *src
; /* Copy from here... */
300 register char *dst
; /* ... to here. */
305 for (c
= *src
; count
> 0; src
++, c
= *src
, count
--) {
307 *dst
= Tcl_Backslash(src
, &numRead
);
322 *----------------------------------------------------------------------
326 * Splits a list up into its constituent fields.
329 * The return value is normally TCL_OK, which means that
330 * the list was successfully split up. If TCL_ERROR is
331 * returned, it means that "list" didn't have proper list
332 * structure; interp->result will contain a more detailed
335 * *argvPtr will be filled in with the address of an array
336 * whose elements point to the elements of list, in order.
337 * *argcPtr will get filled in with the number of valid elements
338 * in the array. A single block of memory is dynamically allocated
339 * to hold both the argv array and a copy of the list (with
340 * backslashes and braces removed in the standard way).
341 * The caller must eventually free this memory by calling free()
342 * on *argvPtr. Note: *argvPtr and *argcPtr are only modified
343 * if the procedure returns normally.
346 * Memory is allocated.
348 *----------------------------------------------------------------------
352 Tcl_SplitList(interp
, list
, argcPtr
, argvPtr
)
353 Tcl_Interp
*interp
; /* Interpreter to use for error reporting. */
354 char *list
; /* Pointer to string with list structure. */
355 int *argcPtr
; /* Pointer to location to fill in with
356 * the number of elements in the list. */
357 char ***argvPtr
; /* Pointer to place to store pointer to array
358 * of pointers to list elements. */
362 int size
, i
, result
, elSize
, brace
;
366 * Figure out how much space to allocate. There must be enough
367 * space for both the array of pointers and also for a copy of
368 * the list. To estimate the number of pointers needed, count
369 * the number of space characters in the list.
372 for (size
= 1, p
= list
; *p
!= 0; p
++) {
377 size
++; /* Leave space for final NULL pointer. */
378 argv
= (char **) ckalloc((unsigned)
379 ((size
* sizeof(char *)) + (p
- list
) + 1));
380 for (i
= 0, p
= ((char *) argv
) + size
*sizeof(char *);
382 result
= TclFindElement(interp
, list
, &element
, &list
, &elSize
, &brace
);
383 if (result
!= TCL_OK
) {
384 ckfree((char *) argv
);
391 ckfree((char *) argv
);
392 Tcl_SetResult(interp
, "internal error in Tcl_SplitList",
398 strncpy(p
, element
, elSize
);
403 TclCopyAndCollapse(elSize
, element
, p
);
415 *----------------------------------------------------------------------
419 * This procedure is a companion procedure to Tcl_ConvertElement.
420 * It scans a string to see what needs to be done to it (e.g.
421 * add backslashes or enclosing braces) to make the string into
422 * a valid Tcl list element.
425 * The return value is an overestimate of the number of characters
426 * that will be needed by Tcl_ConvertElement to produce a valid
427 * list element from string. The word at *flagPtr is filled in
428 * with a value needed by Tcl_ConvertElement when doing the actual
434 *----------------------------------------------------------------------
438 Tcl_ScanElement(string
, flagPtr
)
439 char *string
; /* String to convert to Tcl list element. */
440 int *flagPtr
; /* Where to store information to guide
441 * Tcl_ConvertElement. */
443 int flags
, nestingLevel
;
447 * This procedure and Tcl_ConvertElement together do two things:
449 * 1. They produce a proper list, one that will yield back the
450 * argument strings when evaluated or when disassembled with
451 * Tcl_SplitList. This is the most important thing.
453 * 2. They try to produce legible output, which means minimizing the
454 * use of backslashes (using braces instead). However, there are
455 * some situations where backslashes must be used (e.g. an element
456 * like "{abc": the leading brace will have to be backslashed. For
457 * each element, one of three things must be done:
459 * (a) Use the element as-is (it doesn't contain anything special
460 * characters). This is the most desirable option.
462 * (b) Enclose the element in braces, but leave the contents alone.
463 * This happens if the element contains embedded space, or if it
464 * contains characters with special interpretation ($, [, ;, or \),
465 * or if it starts with a brace or double-quote, or if there are
466 * no characters in the element.
468 * (c) Don't enclose the element in braces, but add backslashes to
469 * prevent special interpretation of special characters. This is a
470 * last resort used when the argument would normally fall under case
471 * (b) but contains unmatched braces. It also occurs if the last
472 * character of the argument is a backslash.
474 * The procedure figures out how many bytes will be needed to store
475 * the result (actually, it overestimates). It also collects information
476 * about the element in the form of a flags word.
482 if ((*p
== '{') || (*p
== '"') || (*p
== 0)) {
485 for ( ; *p
!= 0; p
++) {
492 if (nestingLevel
< 0) {
493 flags
|= TCL_DONT_USE_BRACES
|BRACES_UNMATCHED
;
509 flags
= TCL_DONT_USE_BRACES
;
513 (void) Tcl_Backslash(p
, &size
);
520 if (nestingLevel
!= 0) {
521 flags
= TCL_DONT_USE_BRACES
| BRACES_UNMATCHED
;
526 * Allow enough space to backslash every character plus leave
527 * two spaces for braces.
530 return 2*(p
-string
) + 2;
534 *----------------------------------------------------------------------
536 * Tcl_ConvertElement --
538 * This is a companion procedure to Tcl_ScanElement. Given the
539 * information produced by Tcl_ScanElement, this procedure converts
540 * a string to a list element equal to that string.
543 * Information is copied to *dst in the form of a list element
544 * identical to src (i.e. if Tcl_SplitList is applied to dst it
545 * will produce a string identical to src). The return value is
546 * a count of the number of characters copied (not including the
547 * terminating NULL character).
552 *----------------------------------------------------------------------
556 Tcl_ConvertElement(src
, dst
, flags
)
557 register char *src
; /* Source information for list element. */
558 char *dst
; /* Place to put list-ified element. */
559 int flags
; /* Flags produced by Tcl_ScanElement. */
561 register char *p
= dst
;
564 * See the comment block at the beginning of the Tcl_ScanElement
565 * code for details of how this works.
568 if ((flags
& USE_BRACES
) && !(flags
& TCL_DONT_USE_BRACES
)) {
571 for ( ; *src
!= 0; src
++, p
++) {
576 } else if (*src
== 0) {
578 * If string is empty but can't use braces, then use special
579 * backslash sequence that maps to empty string.
586 for (; *src
!= 0 ; src
++) {
600 if (flags
& BRACES_UNMATCHED
) {
645 *----------------------------------------------------------------------
649 * Given a collection of strings, merge them together into a
650 * single string that has proper Tcl list structured (i.e.
651 * Tcl_SplitList may be used to retrieve strings equal to the
652 * original elements, and Tcl_Eval will parse the string back
653 * into its original elements).
656 * The return value is the address of a dynamically-allocated
657 * string containing the merged list.
662 *----------------------------------------------------------------------
666 Tcl_Merge(argc
, argv
)
667 int argc
; /* How many strings to merge. */
668 char **argv
; /* Array of string values. */
670 # define LOCAL_SIZE 20
671 int localFlags
[LOCAL_SIZE
], *flagPtr
;
678 * Pass 1: estimate space, gather flags.
681 if (argc
<= LOCAL_SIZE
) {
682 flagPtr
= localFlags
;
684 flagPtr
= (int *) ckalloc((unsigned) argc
*sizeof(int));
687 for (i
= 0; i
< argc
; i
++) {
688 numChars
+= Tcl_ScanElement(argv
[i
], &flagPtr
[i
]) + 1;
692 * Pass two: copy into the result area.
695 result
= (char *) ckalloc((unsigned) numChars
);
697 for (i
= 0; i
< argc
; i
++) {
698 numChars
= Tcl_ConvertElement(argv
[i
], dst
, flagPtr
[i
]);
709 if (flagPtr
!= localFlags
) {
710 ckfree((char *) flagPtr
);
716 *----------------------------------------------------------------------
720 * Concatenate a set of strings into a single large string.
723 * The return value is dynamically-allocated string containing
724 * a concatenation of all the strings in argv, with spaces between
725 * the original argv elements.
728 * Memory is allocated for the result; the caller is responsible
729 * for freeing the memory.
731 *----------------------------------------------------------------------
735 Tcl_Concat(argc
, argv
)
736 int argc
; /* Number of strings to concatenate. */
737 char **argv
; /* Array of strings to concatenate. */
743 for (totalSize
= 1, i
= 0; i
< argc
; i
++) {
744 totalSize
+= strlen(argv
[i
]) + 1;
746 result
= (char *) ckalloc((unsigned) totalSize
);
751 for (p
= result
, i
= 0; i
< argc
; i
++) {
756 * Clip white space off the front and back of the string
757 * to generate a neater result, and ignore any empty
762 while (isspace(*element
)) {
765 for (length
= strlen(element
);
766 (length
> 0) && (isspace(element
[length
-1]));
768 /* Null loop body. */
773 (void) strncpy(p
, element
, length
);
787 *----------------------------------------------------------------------
791 * See if a particular string matches a particular pattern.
794 * The return value is 1 if string matches pattern, and
795 * 0 otherwise. The matching operation permits the following
796 * special characters in the pattern: *?\[] (see the manual
797 * entry for details on what these mean).
802 *----------------------------------------------------------------------
806 Tcl_StringMatch(string
, pattern
)
807 register char *string
; /* String. */
808 register char *pattern
; /* Pattern, which may contain
809 * special characters. */
814 /* See if we're at the end of both the pattern and the string.
815 * If so, we succeeded. If we're at the end of the pattern
816 * but not at the end of the string, we failed.
826 if ((*string
== 0) && (*pattern
!= '*')) {
830 /* Check for a "*" as the next pattern character. It matches
831 * any substring. We handle this by calling ourselves
832 * recursively for each postfix of string, until either we
833 * match or we reach the end of the string.
836 if (*pattern
== '*') {
842 if (Tcl_StringMatch(string
, pattern
)) {
852 /* Check for a "?" as the next pattern character. It matches
853 * any single character.
856 if (*pattern
== '?') {
860 /* Check for a "[" as the next pattern character. It is followed
861 * by a list of characters that are acceptable, or by a range
862 * (two characters separated by "-").
865 if (*pattern
== '[') {
868 if ((*pattern
== ']') || (*pattern
== 0)) {
871 if (*pattern
== *string
) {
874 if (pattern
[1] == '-') {
879 if ((*pattern
<= *string
) && (c2
>= *string
)) {
882 if ((*pattern
>= *string
) && (c2
<= *string
)) {
889 while ((*pattern
!= ']') && (*pattern
!= 0)) {
895 /* If the next pattern character is '/', just strip off the '/'
896 * so we do exact matching on the character that follows.
899 if (*pattern
== '\\') {
906 /* There's no special character. Just make sure that the next
907 * characters of each string match.
910 if (*pattern
!= *string
) {
914 thisCharOK
: pattern
+= 1;
920 *----------------------------------------------------------------------
924 * Arrange for "string" to be the Tcl return value.
930 * interp->result is left pointing either to "string" (if "copy" is 0)
931 * or to a copy of string.
933 *----------------------------------------------------------------------
937 Tcl_SetResult(interp
, string
, freeProc
)
938 Tcl_Interp
*interp
; /* Interpreter with which to associate the
940 char *string
; /* Value to be returned. If NULL,
941 * the result is set to an empty string. */
942 Tcl_FreeProc
*freeProc
; /* Gives information about the string:
943 * TCL_STATIC, TCL_VOLATILE, or the address
944 * of a Tcl_FreeProc such as free. */
946 register Interp
*iPtr
= (Interp
*) interp
;
948 Tcl_FreeProc
*oldFreeProc
= iPtr
->freeProc
;
949 char *oldResult
= iPtr
->result
;
951 iPtr
->freeProc
= freeProc
;
952 if (string
== NULL
) {
953 iPtr
->resultSpace
[0] = 0;
954 iPtr
->result
= iPtr
->resultSpace
;
956 } else if (freeProc
== TCL_VOLATILE
) {
957 length
= strlen(string
);
958 if (length
> TCL_RESULT_SIZE
) {
959 iPtr
->result
= (char *) ckalloc((unsigned) length
+1);
960 iPtr
->freeProc
= (Tcl_FreeProc
*) free
;
962 iPtr
->result
= iPtr
->resultSpace
;
965 strcpy(iPtr
->result
, string
);
967 iPtr
->result
= string
;
971 * If the old result was dynamically-allocated, free it up. Do it
972 * here, rather than at the beginning, in case the new result value
973 * was part of the old result value.
976 if (oldFreeProc
!= 0) {
977 (*oldFreeProc
)(oldResult
);
982 *----------------------------------------------------------------------
984 * Tcl_AppendResult --
986 * Append a variable number of strings onto the result already
987 * present for an interpreter.
993 * The result in the interpreter given by the first argument
994 * is extended by the strings given by the second and following
995 * arguments (up to a terminating NULL argument).
997 *----------------------------------------------------------------------
1001 Tcl_AppendResult(Tcl_Interp
*interp
, ...)
1004 register Interp
*iPtr
;
1009 * First, scan through all the arguments to see how much space is
1013 va_start(argList
, interp
);
1014 iPtr
= (Interp
*)interp
;
1017 string
= va_arg(argList
, char *);
1018 if (string
== NULL
) {
1021 newSpace
+= strlen(string
);
1026 * If the append buffer isn't already setup and large enough
1027 * to hold the new data, set it up.
1030 if ((iPtr
->result
!= iPtr
->appendResult
)
1031 || ((newSpace
+ iPtr
->appendUsed
) >= iPtr
->appendAvl
)) {
1032 SetupAppendBuffer(iPtr
, newSpace
);
1036 * Final step: go through all the argument strings again, copying
1037 * them into the buffer.
1040 va_start(argList
, interp
);
1042 string
= va_arg(argList
, char *);
1043 if (string
== NULL
) {
1046 strcpy(iPtr
->appendResult
+ iPtr
->appendUsed
, string
);
1047 iPtr
->appendUsed
+= strlen(string
);
1053 *----------------------------------------------------------------------
1055 * Tcl_AppendElement --
1057 * Convert a string to a valid Tcl list element and append it
1058 * to the current result (which is ostensibly a list).
1064 * The result in the interpreter given by the first argument
1065 * is extended with a list element converted from string. If
1066 * the original result wasn't empty, then a blank is added before
1067 * the converted list element.
1069 *----------------------------------------------------------------------
1073 Tcl_AppendElement(interp
, string
, noSep
)
1074 Tcl_Interp
*interp
; /* Interpreter whose result is to be
1076 char *string
; /* String to convert to list element and
1078 int noSep
; /* If non-zero, then don't output a
1079 * space character before this element,
1080 * even if the element isn't the first
1081 * thing in the output buffer. */
1083 register Interp
*iPtr
= (Interp
*) interp
;
1088 * See how much space is needed, and grow the append buffer if
1089 * needed to accommodate the list element.
1092 size
= Tcl_ScanElement(string
, &flags
) + 1;
1093 if ((iPtr
->result
!= iPtr
->appendResult
)
1094 || ((size
+ iPtr
->appendUsed
) >= iPtr
->appendAvl
)) {
1095 SetupAppendBuffer(iPtr
, size
+iPtr
->appendUsed
);
1099 * Convert the string into a list element and copy it to the
1100 * buffer that's forming.
1103 dst
= iPtr
->appendResult
+ iPtr
->appendUsed
;
1104 if (!noSep
&& (iPtr
->appendUsed
!= 0)) {
1109 iPtr
->appendUsed
+= Tcl_ConvertElement(string
, dst
, flags
);
1113 *----------------------------------------------------------------------
1115 * SetupAppendBuffer --
1117 * This procedure makes sure that there is an append buffer
1118 * properly initialized for interp, and that it has at least
1119 * enough room to accommodate newSpace new bytes of information.
1127 *----------------------------------------------------------------------
1131 SetupAppendBuffer(iPtr
, newSpace
)
1132 register Interp
*iPtr
; /* Interpreter whose result is being set up. */
1133 int newSpace
; /* Make sure that at least this many bytes
1134 * of new information may be added. */
1139 * Make the append buffer larger, if that's necessary, then
1140 * copy the current result into the append buffer and make the
1141 * append buffer the official Tcl result.
1144 if (iPtr
->result
!= iPtr
->appendResult
) {
1146 * If an oversized buffer was used recently, then free it up
1147 * so we go back to a smaller buffer. This avoids tying up
1148 * memory forever after a large operation.
1151 if (iPtr
->appendAvl
> 500) {
1152 ckfree(iPtr
->appendResult
);
1153 iPtr
->appendResult
= NULL
;
1154 iPtr
->appendAvl
= 0;
1156 iPtr
->appendUsed
= strlen(iPtr
->result
);
1158 totalSpace
= newSpace
+ iPtr
->appendUsed
;
1159 if (totalSpace
>= iPtr
->appendAvl
) {
1162 if (totalSpace
< 100) {
1167 new = (char *) ckalloc((unsigned) totalSpace
);
1168 strcpy(new, iPtr
->result
);
1169 if (iPtr
->appendResult
!= NULL
) {
1170 ckfree(iPtr
->appendResult
);
1172 iPtr
->appendResult
= new;
1173 iPtr
->appendAvl
= totalSpace
;
1174 } else if (iPtr
->result
!= iPtr
->appendResult
) {
1175 strcpy(iPtr
->appendResult
, iPtr
->result
);
1177 Tcl_FreeResult(iPtr
);
1178 iPtr
->result
= iPtr
->appendResult
;
1182 *----------------------------------------------------------------------
1184 * Tcl_ResetResult --
1186 * This procedure restores the result area for an interpreter
1187 * to its default initialized state, freeing up any memory that
1188 * may have been allocated for the result and clearing any
1189 * error information for the interpreter.
1197 *----------------------------------------------------------------------
1201 Tcl_ResetResult(interp
)
1202 Tcl_Interp
*interp
; /* Interpreter for which to clear result. */
1204 register Interp
*iPtr
= (Interp
*) interp
;
1206 Tcl_FreeResult(iPtr
);
1207 iPtr
->result
= iPtr
->resultSpace
;
1208 iPtr
->resultSpace
[0] = 0;
1210 ~(ERR_ALREADY_LOGGED
| ERR_IN_PROGRESS
| ERROR_CODE_SET
);
1214 *----------------------------------------------------------------------
1216 * Tcl_SetErrorCode --
1218 * This procedure is called to record machine-readable information
1219 * about an error that is about to be returned.
1225 * The errorCode global variable is modified to hold all of the
1226 * arguments to this procedure, in a list form with each argument
1227 * becoming one element of the list. A flag is set internally
1228 * to remember that errorCode has been set, so the variable doesn't
1229 * get set automatically when the error is returned.
1231 *----------------------------------------------------------------------
1234 Tcl_SetErrorCode(Tcl_Interp
*interp
, ...)
1242 * Scan through the arguments one at a time, appending them to
1243 * $errorCode as list elements.
1246 va_start(argList
, interp
);
1247 iPtr
= (Interp
*)interp
;
1248 flags
= TCL_GLOBAL_ONLY
| TCL_LIST_ELEMENT
;
1250 string
= va_arg(argList
, char *);
1251 if (string
== NULL
) {
1254 (void) Tcl_SetVar2((Tcl_Interp
*) iPtr
, "errorCode",
1255 (char *) NULL
, string
, flags
);
1256 flags
|= TCL_APPEND_VALUE
;
1259 iPtr
->flags
|= ERROR_CODE_SET
;
1263 *----------------------------------------------------------------------
1265 * TclGetListIndex --
1267 * Parse a list index, which may be either an integer or the
1271 * The return value is either TCL_OK or TCL_ERROR. If it is
1272 * TCL_OK, then the index corresponding to string is left in
1273 * *indexPtr. If the return value is TCL_ERROR, then string
1274 * was bogus; an error message is returned in interp->result.
1275 * If a negative index is specified, it is rounded up to 0.
1276 * The index value may be larger than the size of the list
1277 * (this happens when "end" is specified).
1282 *----------------------------------------------------------------------
1286 TclGetListIndex(interp
, string
, indexPtr
)
1287 Tcl_Interp
*interp
; /* Interpreter for error reporting. */
1288 char *string
; /* String containing list index. */
1289 int *indexPtr
; /* Where to store index. */
1291 if (isdigit(*string
) || (*string
== '-')) {
1292 if (Tcl_GetInt(interp
, string
, indexPtr
) != TCL_OK
) {
1295 if (*indexPtr
< 0) {
1298 } else if (strncmp(string
, "end", strlen(string
)) == 0) {
1301 Tcl_AppendResult(interp
, "bad index \"", string
,
1302 "\": must be integer or \"end\"", (char *) NULL
);
1309 *----------------------------------------------------------------------
1311 * TclCompileRegexp --
1313 * Compile a regular expression into a form suitable for fast
1314 * matching. This procedure retains a small cache of pre-compiled
1315 * regular expressions in the interpreter, in order to avoid
1316 * compilation costs as much as possible.
1319 * The return value is a pointer to the compiled form of string,
1320 * suitable for passing to regexec. If an error occurred while
1321 * compiling the pattern, then NULL is returned and an error
1322 * message is left in interp->result.
1325 * The cache of compiled regexp's in interp will be modified to
1326 * hold information for string, if such information isn't already
1327 * present in the cache.
1329 *----------------------------------------------------------------------
1333 TclCompileRegexp(interp
, string
)
1334 Tcl_Interp
*interp
; /* For use in error reporting. */
1335 char *string
; /* String for which to produce
1336 * compiled regular expression. */
1338 register Interp
*iPtr
= (Interp
*) interp
;
1342 length
= strlen(string
);
1343 for (i
= 0; i
< NUM_REGEXPS
; i
++) {
1344 if ((length
== iPtr
->patLengths
[i
])
1345 && (strcmp(string
, iPtr
->patterns
[i
]) == 0)) {
1347 * Move the matched pattern to the first slot in the
1348 * cache and shift the other patterns down one position.
1355 cachedString
= iPtr
->patterns
[i
];
1356 result
= iPtr
->regexps
[i
];
1357 for (j
= i
-1; j
>= 0; j
--) {
1358 iPtr
->patterns
[j
+1] = iPtr
->patterns
[j
];
1359 iPtr
->patLengths
[j
+1] = iPtr
->patLengths
[j
];
1360 iPtr
->regexps
[j
+1] = iPtr
->regexps
[j
];
1362 iPtr
->patterns
[0] = cachedString
;
1363 iPtr
->patLengths
[0] = length
;
1364 iPtr
->regexps
[0] = result
;
1366 return iPtr
->regexps
[0];
1371 * No match in the cache. Compile the string and add it to the
1375 tclRegexpError
= NULL
;
1376 result
= regcomp(string
);
1377 if (tclRegexpError
!= NULL
) {
1378 Tcl_AppendResult(interp
,
1379 "couldn't compile regular expression pattern: ",
1380 tclRegexpError
, (char *) NULL
);
1383 if (iPtr
->patterns
[NUM_REGEXPS
-1] != NULL
) {
1384 ckfree(iPtr
->patterns
[NUM_REGEXPS
-1]);
1385 ckfree((char *) iPtr
->regexps
[NUM_REGEXPS
-1]);
1387 for (i
= NUM_REGEXPS
- 2; i
>= 0; i
--) {
1388 iPtr
->patterns
[i
+1] = iPtr
->patterns
[i
];
1389 iPtr
->patLengths
[i
+1] = iPtr
->patLengths
[i
];
1390 iPtr
->regexps
[i
+1] = iPtr
->regexps
[i
];
1392 iPtr
->patterns
[0] = (char *) ckalloc((unsigned) (length
+1));
1393 strcpy(iPtr
->patterns
[0], string
);
1394 iPtr
->patLengths
[0] = length
;
1395 iPtr
->regexps
[0] = result
;
1400 *----------------------------------------------------------------------
1404 * This procedure is invoked by the Henry Spencer's regexp code
1405 * when an error occurs. It saves the error message so it can
1406 * be seen by the code that called Spencer's code.
1412 * The value of "string" is saved in "tclRegexpError".
1414 *----------------------------------------------------------------------
1419 char *string
; /* Error message. */
1421 tclRegexpError
= string
;