]>
cvs.zerfleddert.de Git - micropolis/blob - src/tcl/tclutil.c
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 *----------------------------------------------------------------------
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
119 * Skim off leading white space and check for an opening brace or
120 * quote. Note: use of "isascii" below and elsewhere in this
121 * procedure is a temporary workaround (7/27/90) because Mx uses characters
122 * with the high-order bit set for some things. This should probably
123 * be changed back eventually, or all of Tcl should call isascii.
126 while (isascii(*list
) && isspace(*list
)) {
132 } else if (*list
== '"') {
137 *bracePtr
= openBraces
;
142 * Find the end of the element (either a space or a close brace or
143 * the end of the string).
150 * Open brace: don't treat specially unless the element is
151 * in braces. In this case, keep a nesting count.
155 if (openBraces
!= 0) {
161 * Close brace: if element is in braces, keep nesting
162 * count and quit when the last close brace is seen.
166 if (openBraces
== 1) {
171 if ((isascii(*p
) && isspace(*p
)) || (*p
== 0)) {
174 for (p2
= p
; (*p2
!= 0) && (!isspace(*p2
)) && (p2
< p
+20);
178 Tcl_ResetResult(interp
);
179 sprintf(interp
->result
,
180 "list element in braces followed by \"%.*s\" instead of space",
183 } else if (openBraces
!= 0) {
189 * Backslash: skip over everything up to the end of the
190 * backslash sequence.
196 (void) Tcl_Backslash(p
, &size
);
202 * Space: ignore if element is in braces or quotes; otherwise
212 if ((openBraces
== 0) && !inQuotes
) {
219 * Double-quote: if element is in quotes then terminate it.
228 if ((isascii(*p
) && isspace(*p
)) || (*p
== 0)) {
231 for (p2
= p
; (*p2
!= 0) && (!isspace(*p2
)) && (p2
< p
+20);
235 Tcl_ResetResult(interp
);
236 sprintf(interp
->result
,
237 "list element in quotes followed by \"%.*s\" %s",
238 p2
-p
, p
, "instead of space");
244 * End of list: terminate element.
248 if (openBraces
!= 0) {
249 Tcl_SetResult(interp
, "unmatched open brace in list",
252 } else if (inQuotes
) {
253 Tcl_SetResult(interp
, "unmatched open quote in list",
265 while (isascii(*p
) && isspace(*p
)) {
277 *----------------------------------------------------------------------
279 * TclCopyAndCollapse --
281 * Copy a string and eliminate any backslashes that aren't in braces.
284 * There is no return value. Count chars. get copied from src
285 * to dst. Along the way, if backslash sequences are found outside
286 * braces, the backslashes are eliminated in the copy.
287 * After scanning count chars. from source, a null character is
288 * placed at the end of dst.
293 *----------------------------------------------------------------------
298 int count
, /* Total number of characters to copy
300 register char *src
, /* Copy from here... */
301 register char *dst
/* ... to here. */
307 for (c
= *src
; count
> 0; src
++, c
= *src
, count
--) {
309 *dst
= Tcl_Backslash(src
, &numRead
);
324 *----------------------------------------------------------------------
328 * Splits a list up into its constituent fields.
331 * The return value is normally TCL_OK, which means that
332 * the list was successfully split up. If TCL_ERROR is
333 * returned, it means that "list" didn't have proper list
334 * structure; interp->result will contain a more detailed
337 * *argvPtr will be filled in with the address of an array
338 * whose elements point to the elements of list, in order.
339 * *argcPtr will get filled in with the number of valid elements
340 * in the array. A single block of memory is dynamically allocated
341 * to hold both the argv array and a copy of the list (with
342 * backslashes and braces removed in the standard way).
343 * The caller must eventually free this memory by calling free()
344 * on *argvPtr. Note: *argvPtr and *argcPtr are only modified
345 * if the procedure returns normally.
348 * Memory is allocated.
350 *----------------------------------------------------------------------
355 Tcl_Interp
*interp
, /* Interpreter to use for error reporting. */
356 char *list
, /* Pointer to string with list structure. */
357 int *argcPtr
, /* Pointer to location to fill in with
358 * the number of elements in the list. */
359 char ***argvPtr
/* Pointer to place to store pointer to array
360 * of pointers to list elements. */
365 int size
, i
, result
, elSize
, brace
;
369 * Figure out how much space to allocate. There must be enough
370 * space for both the array of pointers and also for a copy of
371 * the list. To estimate the number of pointers needed, count
372 * the number of space characters in the list.
375 for (size
= 1, p
= list
; *p
!= 0; p
++) {
380 size
++; /* Leave space for final NULL pointer. */
381 argv
= (char **) ckalloc((unsigned)
382 ((size
* sizeof(char *)) + (p
- list
) + 1));
383 for (i
= 0, p
= ((char *) argv
) + size
*sizeof(char *);
385 result
= TclFindElement(interp
, list
, &element
, &list
, &elSize
, &brace
);
386 if (result
!= TCL_OK
) {
387 ckfree((char *) argv
);
394 ckfree((char *) argv
);
395 Tcl_SetResult(interp
, "internal error in Tcl_SplitList",
401 strncpy(p
, element
, elSize
);
406 TclCopyAndCollapse(elSize
, element
, p
);
418 *----------------------------------------------------------------------
422 * This procedure is a companion procedure to Tcl_ConvertElement.
423 * It scans a string to see what needs to be done to it (e.g.
424 * add backslashes or enclosing braces) to make the string into
425 * a valid Tcl list element.
428 * The return value is an overestimate of the number of characters
429 * that will be needed by Tcl_ConvertElement to produce a valid
430 * list element from string. The word at *flagPtr is filled in
431 * with a value needed by Tcl_ConvertElement when doing the actual
437 *----------------------------------------------------------------------
442 char *string
, /* String to convert to Tcl list element. */
443 int *flagPtr
/* Where to store information to guide
444 * Tcl_ConvertElement. */
447 int flags
, nestingLevel
;
451 * This procedure and Tcl_ConvertElement together do two things:
453 * 1. They produce a proper list, one that will yield back the
454 * argument strings when evaluated or when disassembled with
455 * Tcl_SplitList. This is the most important thing.
457 * 2. They try to produce legible output, which means minimizing the
458 * use of backslashes (using braces instead). However, there are
459 * some situations where backslashes must be used (e.g. an element
460 * like "{abc": the leading brace will have to be backslashed. For
461 * each element, one of three things must be done:
463 * (a) Use the element as-is (it doesn't contain anything special
464 * characters). This is the most desirable option.
466 * (b) Enclose the element in braces, but leave the contents alone.
467 * This happens if the element contains embedded space, or if it
468 * contains characters with special interpretation ($, [, ;, or \),
469 * or if it starts with a brace or double-quote, or if there are
470 * no characters in the element.
472 * (c) Don't enclose the element in braces, but add backslashes to
473 * prevent special interpretation of special characters. This is a
474 * last resort used when the argument would normally fall under case
475 * (b) but contains unmatched braces. It also occurs if the last
476 * character of the argument is a backslash.
478 * The procedure figures out how many bytes will be needed to store
479 * the result (actually, it overestimates). It also collects information
480 * about the element in the form of a flags word.
486 if ((*p
== '{') || (*p
== '"') || (*p
== 0)) {
489 for ( ; *p
!= 0; p
++) {
496 if (nestingLevel
< 0) {
497 flags
|= TCL_DONT_USE_BRACES
|BRACES_UNMATCHED
;
513 flags
= TCL_DONT_USE_BRACES
;
517 (void) Tcl_Backslash(p
, &size
);
524 if (nestingLevel
!= 0) {
525 flags
= TCL_DONT_USE_BRACES
| BRACES_UNMATCHED
;
530 * Allow enough space to backslash every character plus leave
531 * two spaces for braces.
534 return 2*(p
-string
) + 2;
538 *----------------------------------------------------------------------
540 * Tcl_ConvertElement --
542 * This is a companion procedure to Tcl_ScanElement. Given the
543 * information produced by Tcl_ScanElement, this procedure converts
544 * a string to a list element equal to that string.
547 * Information is copied to *dst in the form of a list element
548 * identical to src (i.e. if Tcl_SplitList is applied to dst it
549 * will produce a string identical to src). The return value is
550 * a count of the number of characters copied (not including the
551 * terminating NULL character).
556 *----------------------------------------------------------------------
561 register char *src
, /* Source information for list element. */
562 char *dst
, /* Place to put list-ified element. */
563 int flags
/* Flags produced by Tcl_ScanElement. */
566 register char *p
= dst
;
569 * See the comment block at the beginning of the Tcl_ScanElement
570 * code for details of how this works.
573 if ((flags
& USE_BRACES
) && !(flags
& TCL_DONT_USE_BRACES
)) {
576 for ( ; *src
!= 0; src
++, p
++) {
581 } else if (*src
== 0) {
583 * If string is empty but can't use braces, then use special
584 * backslash sequence that maps to empty string.
591 for (; *src
!= 0 ; src
++) {
605 if (flags
& BRACES_UNMATCHED
) {
650 *----------------------------------------------------------------------
654 * Given a collection of strings, merge them together into a
655 * single string that has proper Tcl list structured (i.e.
656 * Tcl_SplitList may be used to retrieve strings equal to the
657 * original elements, and Tcl_Eval will parse the string back
658 * into its original elements).
661 * The return value is the address of a dynamically-allocated
662 * string containing the merged list.
667 *----------------------------------------------------------------------
672 int argc
, /* How many strings to merge. */
673 char **argv
/* Array of string values. */
676 # define LOCAL_SIZE 20
677 int localFlags
[LOCAL_SIZE
], *flagPtr
;
684 * Pass 1: estimate space, gather flags.
687 if (argc
<= LOCAL_SIZE
) {
688 flagPtr
= localFlags
;
690 flagPtr
= (int *) ckalloc((unsigned) argc
*sizeof(int));
693 for (i
= 0; i
< argc
; i
++) {
694 numChars
+= Tcl_ScanElement(argv
[i
], &flagPtr
[i
]) + 1;
698 * Pass two: copy into the result area.
701 result
= (char *) ckalloc((unsigned) numChars
);
703 for (i
= 0; i
< argc
; i
++) {
704 numChars
= Tcl_ConvertElement(argv
[i
], dst
, flagPtr
[i
]);
715 if (flagPtr
!= localFlags
) {
716 ckfree((char *) flagPtr
);
722 *----------------------------------------------------------------------
726 * Concatenate a set of strings into a single large string.
729 * The return value is dynamically-allocated string containing
730 * a concatenation of all the strings in argv, with spaces between
731 * the original argv elements.
734 * Memory is allocated for the result; the caller is responsible
735 * for freeing the memory.
737 *----------------------------------------------------------------------
742 int argc
, /* Number of strings to concatenate. */
743 char **argv
/* Array of strings to concatenate. */
750 for (totalSize
= 1, i
= 0; i
< argc
; i
++) {
751 totalSize
+= strlen(argv
[i
]) + 1;
753 result
= (char *) ckalloc((unsigned) totalSize
);
758 for (p
= result
, i
= 0; i
< argc
; i
++) {
763 * Clip white space off the front and back of the string
764 * to generate a neater result, and ignore any empty
769 while (isspace(*element
)) {
772 for (length
= strlen(element
);
773 (length
> 0) && (isspace(element
[length
-1]));
775 /* Null loop body. */
780 (void) strncpy(p
, element
, length
);
794 *----------------------------------------------------------------------
798 * See if a particular string matches a particular pattern.
801 * The return value is 1 if string matches pattern, and
802 * 0 otherwise. The matching operation permits the following
803 * special characters in the pattern: *?\[] (see the manual
804 * entry for details on what these mean).
809 *----------------------------------------------------------------------
814 register char *string
, /* String. */
815 register char *pattern
/* Pattern, which may contain
816 * special characters. */
822 /* See if we're at the end of both the pattern and the string.
823 * If so, we succeeded. If we're at the end of the pattern
824 * but not at the end of the string, we failed.
834 if ((*string
== 0) && (*pattern
!= '*')) {
838 /* Check for a "*" as the next pattern character. It matches
839 * any substring. We handle this by calling ourselves
840 * recursively for each postfix of string, until either we
841 * match or we reach the end of the string.
844 if (*pattern
== '*') {
850 if (Tcl_StringMatch(string
, pattern
)) {
860 /* Check for a "?" as the next pattern character. It matches
861 * any single character.
864 if (*pattern
== '?') {
868 /* Check for a "[" as the next pattern character. It is followed
869 * by a list of characters that are acceptable, or by a range
870 * (two characters separated by "-").
873 if (*pattern
== '[') {
876 if ((*pattern
== ']') || (*pattern
== 0)) {
879 if (*pattern
== *string
) {
882 if (pattern
[1] == '-') {
887 if ((*pattern
<= *string
) && (c2
>= *string
)) {
890 if ((*pattern
>= *string
) && (c2
<= *string
)) {
897 while ((*pattern
!= ']') && (*pattern
!= 0)) {
903 /* If the next pattern character is '/', just strip off the '/'
904 * so we do exact matching on the character that follows.
907 if (*pattern
== '\\') {
914 /* There's no special character. Just make sure that the next
915 * characters of each string match.
918 if (*pattern
!= *string
) {
922 thisCharOK
: pattern
+= 1;
928 *----------------------------------------------------------------------
932 * Arrange for "string" to be the Tcl return value.
938 * interp->result is left pointing either to "string" (if "copy" is 0)
939 * or to a copy of string.
941 *----------------------------------------------------------------------
946 Tcl_Interp
*interp
, /* Interpreter with which to associate the
948 char *string
, /* Value to be returned. If NULL,
949 * the result is set to an empty string. */
950 Tcl_FreeProc
*freeProc
/* Gives information about the string:
951 * TCL_STATIC, TCL_VOLATILE, or the address
952 * of a Tcl_FreeProc such as free. */
955 register Interp
*iPtr
= (Interp
*) interp
;
957 Tcl_FreeProc
*oldFreeProc
= iPtr
->freeProc
;
958 char *oldResult
= iPtr
->result
;
960 iPtr
->freeProc
= freeProc
;
961 if (string
== NULL
) {
962 iPtr
->resultSpace
[0] = 0;
963 iPtr
->result
= iPtr
->resultSpace
;
965 } else if (freeProc
== TCL_VOLATILE
) {
966 length
= strlen(string
);
967 if (length
> TCL_RESULT_SIZE
) {
968 iPtr
->result
= (char *) ckalloc((unsigned) length
+1);
969 iPtr
->freeProc
= (Tcl_FreeProc
*) free
;
971 iPtr
->result
= iPtr
->resultSpace
;
974 strcpy(iPtr
->result
, string
);
976 iPtr
->result
= string
;
980 * If the old result was dynamically-allocated, free it up. Do it
981 * here, rather than at the beginning, in case the new result value
982 * was part of the old result value.
985 if (oldFreeProc
!= 0) {
986 (*oldFreeProc
)(oldResult
);
991 *----------------------------------------------------------------------
993 * Tcl_AppendResult --
995 * Append a variable number of strings onto the result already
996 * present for an interpreter.
1002 * The result in the interpreter given by the first argument
1003 * is extended by the strings given by the second and following
1004 * arguments (up to a terminating NULL argument).
1006 *----------------------------------------------------------------------
1010 Tcl_AppendResult(Tcl_Interp
*interp
, ...)
1013 register Interp
*iPtr
;
1018 * First, scan through all the arguments to see how much space is
1022 va_start(argList
, interp
);
1023 iPtr
= (Interp
*)interp
;
1026 string
= va_arg(argList
, char *);
1027 if (string
== NULL
) {
1030 newSpace
+= strlen(string
);
1035 * If the append buffer isn't already setup and large enough
1036 * to hold the new data, set it up.
1039 if ((iPtr
->result
!= iPtr
->appendResult
)
1040 || ((newSpace
+ iPtr
->appendUsed
) >= iPtr
->appendAvl
)) {
1041 SetupAppendBuffer(iPtr
, newSpace
);
1045 * Final step: go through all the argument strings again, copying
1046 * them into the buffer.
1049 va_start(argList
, interp
);
1051 string
= va_arg(argList
, char *);
1052 if (string
== NULL
) {
1055 strcpy(iPtr
->appendResult
+ iPtr
->appendUsed
, string
);
1056 iPtr
->appendUsed
+= strlen(string
);
1062 *----------------------------------------------------------------------
1064 * Tcl_AppendElement --
1066 * Convert a string to a valid Tcl list element and append it
1067 * to the current result (which is ostensibly a list).
1073 * The result in the interpreter given by the first argument
1074 * is extended with a list element converted from string. If
1075 * the original result wasn't empty, then a blank is added before
1076 * the converted list element.
1078 *----------------------------------------------------------------------
1083 Tcl_Interp
*interp
, /* Interpreter whose result is to be
1085 char *string
, /* String to convert to list element and
1087 int noSep
/* If non-zero, then don't output a
1088 * space character before this element,
1089 * even if the element isn't the first
1090 * thing in the output buffer. */
1093 register Interp
*iPtr
= (Interp
*) interp
;
1098 * See how much space is needed, and grow the append buffer if
1099 * needed to accommodate the list element.
1102 size
= Tcl_ScanElement(string
, &flags
) + 1;
1103 if ((iPtr
->result
!= iPtr
->appendResult
)
1104 || ((size
+ iPtr
->appendUsed
) >= iPtr
->appendAvl
)) {
1105 SetupAppendBuffer(iPtr
, size
+iPtr
->appendUsed
);
1109 * Convert the string into a list element and copy it to the
1110 * buffer that's forming.
1113 dst
= iPtr
->appendResult
+ iPtr
->appendUsed
;
1114 if (!noSep
&& (iPtr
->appendUsed
!= 0)) {
1119 iPtr
->appendUsed
+= Tcl_ConvertElement(string
, dst
, flags
);
1123 *----------------------------------------------------------------------
1125 * SetupAppendBuffer --
1127 * This procedure makes sure that there is an append buffer
1128 * properly initialized for interp, and that it has at least
1129 * enough room to accommodate newSpace new bytes of information.
1137 *----------------------------------------------------------------------
1142 register Interp
*iPtr
, /* Interpreter whose result is being set up. */
1143 int newSpace
/* Make sure that at least this many bytes
1144 * of new information may be added. */
1150 * Make the append buffer larger, if that's necessary, then
1151 * copy the current result into the append buffer and make the
1152 * append buffer the official Tcl result.
1155 if (iPtr
->result
!= iPtr
->appendResult
) {
1157 * If an oversized buffer was used recently, then free it up
1158 * so we go back to a smaller buffer. This avoids tying up
1159 * memory forever after a large operation.
1162 if (iPtr
->appendAvl
> 500) {
1163 ckfree(iPtr
->appendResult
);
1164 iPtr
->appendResult
= NULL
;
1165 iPtr
->appendAvl
= 0;
1167 iPtr
->appendUsed
= strlen(iPtr
->result
);
1169 totalSpace
= newSpace
+ iPtr
->appendUsed
;
1170 if (totalSpace
>= iPtr
->appendAvl
) {
1173 if (totalSpace
< 100) {
1178 new = (char *) ckalloc((unsigned) totalSpace
);
1179 strcpy(new, iPtr
->result
);
1180 if (iPtr
->appendResult
!= NULL
) {
1181 ckfree(iPtr
->appendResult
);
1183 iPtr
->appendResult
= new;
1184 iPtr
->appendAvl
= totalSpace
;
1185 } else if (iPtr
->result
!= iPtr
->appendResult
) {
1186 strcpy(iPtr
->appendResult
, iPtr
->result
);
1188 Tcl_FreeResult(iPtr
);
1189 iPtr
->result
= iPtr
->appendResult
;
1193 *----------------------------------------------------------------------
1195 * Tcl_ResetResult --
1197 * This procedure restores the result area for an interpreter
1198 * to its default initialized state, freeing up any memory that
1199 * may have been allocated for the result and clearing any
1200 * error information for the interpreter.
1208 *----------------------------------------------------------------------
1213 Tcl_Interp
*interp
/* Interpreter for which to clear result. */
1216 register Interp
*iPtr
= (Interp
*) interp
;
1218 Tcl_FreeResult(iPtr
);
1219 iPtr
->result
= iPtr
->resultSpace
;
1220 iPtr
->resultSpace
[0] = 0;
1222 ~(ERR_ALREADY_LOGGED
| ERR_IN_PROGRESS
| ERROR_CODE_SET
);
1226 *----------------------------------------------------------------------
1228 * Tcl_SetErrorCode --
1230 * This procedure is called to record machine-readable information
1231 * about an error that is about to be returned.
1237 * The errorCode global variable is modified to hold all of the
1238 * arguments to this procedure, in a list form with each argument
1239 * becoming one element of the list. A flag is set internally
1240 * to remember that errorCode has been set, so the variable doesn't
1241 * get set automatically when the error is returned.
1243 *----------------------------------------------------------------------
1246 Tcl_SetErrorCode(Tcl_Interp
*interp
, ...)
1254 * Scan through the arguments one at a time, appending them to
1255 * $errorCode as list elements.
1258 va_start(argList
, interp
);
1259 iPtr
= (Interp
*)interp
;
1260 flags
= TCL_GLOBAL_ONLY
| TCL_LIST_ELEMENT
;
1262 string
= va_arg(argList
, char *);
1263 if (string
== NULL
) {
1266 (void) Tcl_SetVar2((Tcl_Interp
*) iPtr
, "errorCode",
1267 (char *) NULL
, string
, flags
);
1268 flags
|= TCL_APPEND_VALUE
;
1271 iPtr
->flags
|= ERROR_CODE_SET
;
1275 *----------------------------------------------------------------------
1277 * TclGetListIndex --
1279 * Parse a list index, which may be either an integer or the
1283 * The return value is either TCL_OK or TCL_ERROR. If it is
1284 * TCL_OK, then the index corresponding to string is left in
1285 * *indexPtr. If the return value is TCL_ERROR, then string
1286 * was bogus; an error message is returned in interp->result.
1287 * If a negative index is specified, it is rounded up to 0.
1288 * The index value may be larger than the size of the list
1289 * (this happens when "end" is specified).
1294 *----------------------------------------------------------------------
1299 Tcl_Interp
*interp
, /* Interpreter for error reporting. */
1300 char *string
, /* String containing list index. */
1301 int *indexPtr
/* Where to store index. */
1304 if (isdigit(*string
) || (*string
== '-')) {
1305 if (Tcl_GetInt(interp
, string
, indexPtr
) != TCL_OK
) {
1308 if (*indexPtr
< 0) {
1311 } else if (strncmp(string
, "end", strlen(string
)) == 0) {
1314 Tcl_AppendResult(interp
, "bad index \"", string
,
1315 "\": must be integer or \"end\"", (char *) NULL
);
1322 *----------------------------------------------------------------------
1324 * TclCompileRegexp --
1326 * Compile a regular expression into a form suitable for fast
1327 * matching. This procedure retains a small cache of pre-compiled
1328 * regular expressions in the interpreter, in order to avoid
1329 * compilation costs as much as possible.
1332 * The return value is a pointer to the compiled form of string,
1333 * suitable for passing to regexec. If an error occurred while
1334 * compiling the pattern, then NULL is returned and an error
1335 * message is left in interp->result.
1338 * The cache of compiled regexp's in interp will be modified to
1339 * hold information for string, if such information isn't already
1340 * present in the cache.
1342 *----------------------------------------------------------------------
1347 Tcl_Interp
*interp
, /* For use in error reporting. */
1348 char *string
/* String for which to produce
1349 * compiled regular expression. */
1352 register Interp
*iPtr
= (Interp
*) interp
;
1356 length
= strlen(string
);
1357 for (i
= 0; i
< NUM_REGEXPS
; i
++) {
1358 if ((length
== iPtr
->patLengths
[i
])
1359 && (strcmp(string
, iPtr
->patterns
[i
]) == 0)) {
1361 * Move the matched pattern to the first slot in the
1362 * cache and shift the other patterns down one position.
1369 cachedString
= iPtr
->patterns
[i
];
1370 result
= iPtr
->regexps
[i
];
1371 for (j
= i
-1; j
>= 0; j
--) {
1372 iPtr
->patterns
[j
+1] = iPtr
->patterns
[j
];
1373 iPtr
->patLengths
[j
+1] = iPtr
->patLengths
[j
];
1374 iPtr
->regexps
[j
+1] = iPtr
->regexps
[j
];
1376 iPtr
->patterns
[0] = cachedString
;
1377 iPtr
->patLengths
[0] = length
;
1378 iPtr
->regexps
[0] = result
;
1380 return iPtr
->regexps
[0];
1385 * No match in the cache. Compile the string and add it to the
1389 tclRegexpError
= NULL
;
1390 result
= regcomp(string
);
1391 if (tclRegexpError
!= NULL
) {
1392 Tcl_AppendResult(interp
,
1393 "couldn't compile regular expression pattern: ",
1394 tclRegexpError
, (char *) NULL
);
1397 if (iPtr
->patterns
[NUM_REGEXPS
-1] != NULL
) {
1398 ckfree(iPtr
->patterns
[NUM_REGEXPS
-1]);
1399 ckfree((char *) iPtr
->regexps
[NUM_REGEXPS
-1]);
1401 for (i
= NUM_REGEXPS
- 2; i
>= 0; i
--) {
1402 iPtr
->patterns
[i
+1] = iPtr
->patterns
[i
];
1403 iPtr
->patLengths
[i
+1] = iPtr
->patLengths
[i
];
1404 iPtr
->regexps
[i
+1] = iPtr
->regexps
[i
];
1406 iPtr
->patterns
[0] = (char *) ckalloc((unsigned) (length
+1));
1407 strcpy(iPtr
->patterns
[0], string
);
1408 iPtr
->patLengths
[0] = length
;
1409 iPtr
->regexps
[0] = result
;
1414 *----------------------------------------------------------------------
1418 * This procedure is invoked by the Henry Spencer's regexp code
1419 * when an error occurs. It saves the error message so it can
1420 * be seen by the code that called Spencer's code.
1426 * The value of "string" is saved in "tclRegexpError".
1428 *----------------------------------------------------------------------
1433 char *string
/* Error message. */
1436 tclRegexpError
= string
;