]> cvs.zerfleddert.de Git - micropolis/blob - src/tcl/tclutil.c
Fixes for compilation with gcc 15
[micropolis] / src / tcl / tclutil.c
1 /*
2 * tclUtil.c --
3 *
4 * This file contains utility procedures that are used by many Tcl
5 * commands.
6 *
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.
15 */
16
17 #ifndef lint
18 static char rcsid[] = "$Header: /user6/ouster/tcl/RCS/tclUtil.c,v 1.63 92/07/02 08:50:54 ouster Exp $ SPRITE (Berkeley)";
19 #endif
20
21 #include "tclint.h"
22
23 /*
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
27 * values below.
28 *
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
38 * in the argument.
39 */
40
41 #define USE_BRACES 2
42 #define BRACES_UNMATCHED 4
43
44 /*
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.
50 */
51
52 char *tclRegexpError = NULL;
53
54 /*
55 * Function prototypes for local procedures in this file:
56 */
57
58 static void SetupAppendBuffer _ANSI_ARGS_((Interp *iPtr,
59 int newSpace));
60 \f
61 /*
62 *----------------------------------------------------------------------
63 *
64 * TclFindElement --
65 *
66 * Given a pointer into a Tcl list, locate the first (or next)
67 * element in the list.
68 *
69 * Results:
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.
74 *
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
87 * sequences.
88 *
89 * Side effects:
90 * None.
91 *
92 *----------------------------------------------------------------------
93 */
94
95 int
96 TclFindElement (
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
105 * list). */
106 int *sizePtr, /* If non-zero, fill in with size of
107 * element. */
108 int *bracePtr /* If non-zero fill in with non-zero/zero
109 * to indicate that arg was/wasn't
110 * in braces. */
111 )
112 {
113 register char *p;
114 int openBraces = 0;
115 int inQuotes = 0;
116 int size;
117
118 /*
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.
124 */
125
126 while (isascii(*list) && isspace(*list)) {
127 list++;
128 }
129 if (*list == '{') {
130 openBraces = 1;
131 list++;
132 } else if (*list == '"') {
133 inQuotes = 1;
134 list++;
135 }
136 if (bracePtr != 0) {
137 *bracePtr = openBraces;
138 }
139 p = list;
140
141 /*
142 * Find the end of the element (either a space or a close brace or
143 * the end of the string).
144 */
145
146 while (1) {
147 switch (*p) {
148
149 /*
150 * Open brace: don't treat specially unless the element is
151 * in braces. In this case, keep a nesting count.
152 */
153
154 case '{':
155 if (openBraces != 0) {
156 openBraces++;
157 }
158 break;
159
160 /*
161 * Close brace: if element is in braces, keep nesting
162 * count and quit when the last close brace is seen.
163 */
164
165 case '}':
166 if (openBraces == 1) {
167 char *p2;
168
169 size = p - list;
170 p++;
171 if ((isascii(*p) && isspace(*p)) || (*p == 0)) {
172 goto done;
173 }
174 for (p2 = p; (*p2 != 0) && (!isspace(*p2)) && (p2 < p+20);
175 p2++) {
176 /* null body */
177 }
178 Tcl_ResetResult(interp);
179 sprintf(interp->result,
180 "list element in braces followed by \"%.*s\" instead of space",
181 p2-p, p);
182 return TCL_ERROR;
183 } else if (openBraces != 0) {
184 openBraces--;
185 }
186 break;
187
188 /*
189 * Backslash: skip over everything up to the end of the
190 * backslash sequence.
191 */
192
193 case '\\': {
194 int size;
195
196 (void) Tcl_Backslash(p, &size);
197 p += size - 1;
198 break;
199 }
200
201 /*
202 * Space: ignore if element is in braces or quotes; otherwise
203 * terminate element.
204 */
205
206 case ' ':
207 case '\f':
208 case '\n':
209 case '\r':
210 case '\t':
211 case '\v':
212 if ((openBraces == 0) && !inQuotes) {
213 size = p - list;
214 goto done;
215 }
216 break;
217
218 /*
219 * Double-quote: if element is in quotes then terminate it.
220 */
221
222 case '"':
223 if (inQuotes) {
224 char *p2;
225
226 size = p-list;
227 p++;
228 if ((isascii(*p) && isspace(*p)) || (*p == 0)) {
229 goto done;
230 }
231 for (p2 = p; (*p2 != 0) && (!isspace(*p2)) && (p2 < p+20);
232 p2++) {
233 /* null body */
234 }
235 Tcl_ResetResult(interp);
236 sprintf(interp->result,
237 "list element in quotes followed by \"%.*s\" %s",
238 p2-p, p, "instead of space");
239 return TCL_ERROR;
240 }
241 break;
242
243 /*
244 * End of list: terminate element.
245 */
246
247 case 0:
248 if (openBraces != 0) {
249 Tcl_SetResult(interp, "unmatched open brace in list",
250 TCL_STATIC);
251 return TCL_ERROR;
252 } else if (inQuotes) {
253 Tcl_SetResult(interp, "unmatched open quote in list",
254 TCL_STATIC);
255 return TCL_ERROR;
256 }
257 size = p - list;
258 goto done;
259
260 }
261 p++;
262 }
263
264 done:
265 while (isascii(*p) && isspace(*p)) {
266 p++;
267 }
268 *elementPtr = list;
269 *nextPtr = p;
270 if (sizePtr != 0) {
271 *sizePtr = size;
272 }
273 return TCL_OK;
274 }
275 \f
276 /*
277 *----------------------------------------------------------------------
278 *
279 * TclCopyAndCollapse --
280 *
281 * Copy a string and eliminate any backslashes that aren't in braces.
282 *
283 * Results:
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.
289 *
290 * Side effects:
291 * None.
292 *
293 *----------------------------------------------------------------------
294 */
295
296 void
297 TclCopyAndCollapse (
298 int count, /* Total number of characters to copy
299 * from src. */
300 register char *src, /* Copy from here... */
301 register char *dst /* ... to here. */
302 )
303 {
304 register char c;
305 int numRead;
306
307 for (c = *src; count > 0; src++, c = *src, count--) {
308 if (c == '\\') {
309 *dst = Tcl_Backslash(src, &numRead);
310 if (*dst != 0) {
311 dst++;
312 }
313 src += numRead-1;
314 count -= numRead-1;
315 } else {
316 *dst = c;
317 dst++;
318 }
319 }
320 *dst = 0;
321 }
322 \f
323 /*
324 *----------------------------------------------------------------------
325 *
326 * Tcl_SplitList --
327 *
328 * Splits a list up into its constituent fields.
329 *
330 * Results
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
335 * error message.
336 *
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.
346 *
347 * Side effects:
348 * Memory is allocated.
349 *
350 *----------------------------------------------------------------------
351 */
352
353 int
354 Tcl_SplitList (
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. */
361 )
362 {
363 char **argv;
364 register char *p;
365 int size, i, result, elSize, brace;
366 char *element;
367
368 /*
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.
373 */
374
375 for (size = 1, p = list; *p != 0; p++) {
376 if (isspace(*p)) {
377 size++;
378 }
379 }
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 *);
384 *list != 0; i++) {
385 result = TclFindElement(interp, list, &element, &list, &elSize, &brace);
386 if (result != TCL_OK) {
387 ckfree((char *) argv);
388 return result;
389 }
390 if (*element == 0) {
391 break;
392 }
393 if (i >= size) {
394 ckfree((char *) argv);
395 Tcl_SetResult(interp, "internal error in Tcl_SplitList",
396 TCL_STATIC);
397 return TCL_ERROR;
398 }
399 argv[i] = p;
400 if (brace) {
401 strncpy(p, element, elSize);
402 p += elSize;
403 *p = 0;
404 p++;
405 } else {
406 TclCopyAndCollapse(elSize, element, p);
407 p += elSize+1;
408 }
409 }
410
411 argv[i] = NULL;
412 *argvPtr = argv;
413 *argcPtr = i;
414 return TCL_OK;
415 }
416 \f
417 /*
418 *----------------------------------------------------------------------
419 *
420 * Tcl_ScanElement --
421 *
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.
426 *
427 * Results:
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
432 * conversion.
433 *
434 * Side effects:
435 * None.
436 *
437 *----------------------------------------------------------------------
438 */
439
440 int
441 Tcl_ScanElement (
442 char *string, /* String to convert to Tcl list element. */
443 int *flagPtr /* Where to store information to guide
444 * Tcl_ConvertElement. */
445 )
446 {
447 int flags, nestingLevel;
448 register char *p;
449
450 /*
451 * This procedure and Tcl_ConvertElement together do two things:
452 *
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.
456 *
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:
462 *
463 * (a) Use the element as-is (it doesn't contain anything special
464 * characters). This is the most desirable option.
465 *
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.
471 *
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.
477 *
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.
481 */
482
483 nestingLevel = 0;
484 flags = 0;
485 p = string;
486 if ((*p == '{') || (*p == '"') || (*p == 0)) {
487 flags |= USE_BRACES;
488 }
489 for ( ; *p != 0; p++) {
490 switch (*p) {
491 case '{':
492 nestingLevel++;
493 break;
494 case '}':
495 nestingLevel--;
496 if (nestingLevel < 0) {
497 flags |= TCL_DONT_USE_BRACES|BRACES_UNMATCHED;
498 }
499 break;
500 case '[':
501 case '$':
502 case ';':
503 case ' ':
504 case '\f':
505 case '\n':
506 case '\r':
507 case '\t':
508 case '\v':
509 flags |= USE_BRACES;
510 break;
511 case '\\':
512 if (p[1] == 0) {
513 flags = TCL_DONT_USE_BRACES;
514 } else {
515 int size;
516
517 (void) Tcl_Backslash(p, &size);
518 p += size-1;
519 flags |= USE_BRACES;
520 }
521 break;
522 }
523 }
524 if (nestingLevel != 0) {
525 flags = TCL_DONT_USE_BRACES | BRACES_UNMATCHED;
526 }
527 *flagPtr = flags;
528
529 /*
530 * Allow enough space to backslash every character plus leave
531 * two spaces for braces.
532 */
533
534 return 2*(p-string) + 2;
535 }
536 \f
537 /*
538 *----------------------------------------------------------------------
539 *
540 * Tcl_ConvertElement --
541 *
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.
545 *
546 * Results:
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).
552 *
553 * Side effects:
554 * None.
555 *
556 *----------------------------------------------------------------------
557 */
558
559 int
560 Tcl_ConvertElement (
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. */
564 )
565 {
566 register char *p = dst;
567
568 /*
569 * See the comment block at the beginning of the Tcl_ScanElement
570 * code for details of how this works.
571 */
572
573 if ((flags & USE_BRACES) && !(flags & TCL_DONT_USE_BRACES)) {
574 *p = '{';
575 p++;
576 for ( ; *src != 0; src++, p++) {
577 *p = *src;
578 }
579 *p = '}';
580 p++;
581 } else if (*src == 0) {
582 /*
583 * If string is empty but can't use braces, then use special
584 * backslash sequence that maps to empty string.
585 */
586
587 p[0] = '\\';
588 p[1] = '0';
589 p += 2;
590 } else {
591 for (; *src != 0 ; src++) {
592 switch (*src) {
593 case ']':
594 case '[':
595 case '$':
596 case ';':
597 case ' ':
598 case '\\':
599 case '"':
600 *p = '\\';
601 p++;
602 break;
603 case '{':
604 case '}':
605 if (flags & BRACES_UNMATCHED) {
606 *p = '\\';
607 p++;
608 }
609 break;
610 case '\f':
611 *p = '\\';
612 p++;
613 *p = 'f';
614 p++;
615 continue;
616 case '\n':
617 *p = '\\';
618 p++;
619 *p = 'n';
620 p++;
621 continue;
622 case '\r':
623 *p = '\\';
624 p++;
625 *p = 'r';
626 p++;
627 continue;
628 case '\t':
629 *p = '\\';
630 p++;
631 *p = 't';
632 p++;
633 continue;
634 case '\v':
635 *p = '\\';
636 p++;
637 *p = 'v';
638 p++;
639 continue;
640 }
641 *p = *src;
642 p++;
643 }
644 }
645 *p = '\0';
646 return p-dst;
647 }
648 \f
649 /*
650 *----------------------------------------------------------------------
651 *
652 * Tcl_Merge --
653 *
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).
659 *
660 * Results:
661 * The return value is the address of a dynamically-allocated
662 * string containing the merged list.
663 *
664 * Side effects:
665 * None.
666 *
667 *----------------------------------------------------------------------
668 */
669
670 char *
671 Tcl_Merge (
672 int argc, /* How many strings to merge. */
673 char **argv /* Array of string values. */
674 )
675 {
676 # define LOCAL_SIZE 20
677 int localFlags[LOCAL_SIZE], *flagPtr;
678 int numChars;
679 char *result;
680 register char *dst;
681 int i;
682
683 /*
684 * Pass 1: estimate space, gather flags.
685 */
686
687 if (argc <= LOCAL_SIZE) {
688 flagPtr = localFlags;
689 } else {
690 flagPtr = (int *) ckalloc((unsigned) argc*sizeof(int));
691 }
692 numChars = 1;
693 for (i = 0; i < argc; i++) {
694 numChars += Tcl_ScanElement(argv[i], &flagPtr[i]) + 1;
695 }
696
697 /*
698 * Pass two: copy into the result area.
699 */
700
701 result = (char *) ckalloc((unsigned) numChars);
702 dst = result;
703 for (i = 0; i < argc; i++) {
704 numChars = Tcl_ConvertElement(argv[i], dst, flagPtr[i]);
705 dst += numChars;
706 *dst = ' ';
707 dst++;
708 }
709 if (dst == result) {
710 *dst = 0;
711 } else {
712 dst[-1] = 0;
713 }
714
715 if (flagPtr != localFlags) {
716 ckfree((char *) flagPtr);
717 }
718 return result;
719 }
720 \f
721 /*
722 *----------------------------------------------------------------------
723 *
724 * Tcl_Concat --
725 *
726 * Concatenate a set of strings into a single large string.
727 *
728 * Results:
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.
732 *
733 * Side effects:
734 * Memory is allocated for the result; the caller is responsible
735 * for freeing the memory.
736 *
737 *----------------------------------------------------------------------
738 */
739
740 char *
741 Tcl_Concat (
742 int argc, /* Number of strings to concatenate. */
743 char **argv /* Array of strings to concatenate. */
744 )
745 {
746 int totalSize, i;
747 register char *p;
748 char *result;
749
750 for (totalSize = 1, i = 0; i < argc; i++) {
751 totalSize += strlen(argv[i]) + 1;
752 }
753 result = (char *) ckalloc((unsigned) totalSize);
754 if (argc == 0) {
755 *result = '\0';
756 return result;
757 }
758 for (p = result, i = 0; i < argc; i++) {
759 char *element;
760 int length;
761
762 /*
763 * Clip white space off the front and back of the string
764 * to generate a neater result, and ignore any empty
765 * elements.
766 */
767
768 element = argv[i];
769 while (isspace(*element)) {
770 element++;
771 }
772 for (length = strlen(element);
773 (length > 0) && (isspace(element[length-1]));
774 length--) {
775 /* Null loop body. */
776 }
777 if (length == 0) {
778 continue;
779 }
780 (void) strncpy(p, element, length);
781 p += length;
782 *p = ' ';
783 p++;
784 }
785 if (p != result) {
786 p[-1] = 0;
787 } else {
788 *p = 0;
789 }
790 return result;
791 }
792 \f
793 /*
794 *----------------------------------------------------------------------
795 *
796 * Tcl_StringMatch --
797 *
798 * See if a particular string matches a particular pattern.
799 *
800 * Results:
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).
805 *
806 * Side effects:
807 * None.
808 *
809 *----------------------------------------------------------------------
810 */
811
812 int
813 Tcl_StringMatch (
814 register char *string, /* String. */
815 register char *pattern /* Pattern, which may contain
816 * special characters. */
817 )
818 {
819 char c2;
820
821 while (1) {
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.
825 */
826
827 if (*pattern == 0) {
828 if (*string == 0) {
829 return 1;
830 } else {
831 return 0;
832 }
833 }
834 if ((*string == 0) && (*pattern != '*')) {
835 return 0;
836 }
837
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.
842 */
843
844 if (*pattern == '*') {
845 pattern += 1;
846 if (*pattern == 0) {
847 return 1;
848 }
849 while (1) {
850 if (Tcl_StringMatch(string, pattern)) {
851 return 1;
852 }
853 if (*string == 0) {
854 return 0;
855 }
856 string += 1;
857 }
858 }
859
860 /* Check for a "?" as the next pattern character. It matches
861 * any single character.
862 */
863
864 if (*pattern == '?') {
865 goto thisCharOK;
866 }
867
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 "-").
871 */
872
873 if (*pattern == '[') {
874 pattern += 1;
875 while (1) {
876 if ((*pattern == ']') || (*pattern == 0)) {
877 return 0;
878 }
879 if (*pattern == *string) {
880 break;
881 }
882 if (pattern[1] == '-') {
883 c2 = pattern[2];
884 if (c2 == 0) {
885 return 0;
886 }
887 if ((*pattern <= *string) && (c2 >= *string)) {
888 break;
889 }
890 if ((*pattern >= *string) && (c2 <= *string)) {
891 break;
892 }
893 pattern += 2;
894 }
895 pattern += 1;
896 }
897 while ((*pattern != ']') && (*pattern != 0)) {
898 pattern += 1;
899 }
900 goto thisCharOK;
901 }
902
903 /* If the next pattern character is '/', just strip off the '/'
904 * so we do exact matching on the character that follows.
905 */
906
907 if (*pattern == '\\') {
908 pattern += 1;
909 if (*pattern == 0) {
910 return 0;
911 }
912 }
913
914 /* There's no special character. Just make sure that the next
915 * characters of each string match.
916 */
917
918 if (*pattern != *string) {
919 return 0;
920 }
921
922 thisCharOK: pattern += 1;
923 string += 1;
924 }
925 }
926 \f
927 /*
928 *----------------------------------------------------------------------
929 *
930 * Tcl_SetResult --
931 *
932 * Arrange for "string" to be the Tcl return value.
933 *
934 * Results:
935 * None.
936 *
937 * Side effects:
938 * interp->result is left pointing either to "string" (if "copy" is 0)
939 * or to a copy of string.
940 *
941 *----------------------------------------------------------------------
942 */
943
944 void
945 Tcl_SetResult (
946 Tcl_Interp *interp, /* Interpreter with which to associate the
947 * return value. */
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. */
953 )
954 {
955 register Interp *iPtr = (Interp *) interp;
956 int length;
957 Tcl_FreeProc *oldFreeProc = iPtr->freeProc;
958 char *oldResult = iPtr->result;
959
960 iPtr->freeProc = freeProc;
961 if (string == NULL) {
962 iPtr->resultSpace[0] = 0;
963 iPtr->result = iPtr->resultSpace;
964 iPtr->freeProc = 0;
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;
970 } else {
971 iPtr->result = iPtr->resultSpace;
972 iPtr->freeProc = 0;
973 }
974 strcpy(iPtr->result, string);
975 } else {
976 iPtr->result = string;
977 }
978
979 /*
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.
983 */
984
985 if (oldFreeProc != 0) {
986 (*oldFreeProc)(oldResult);
987 }
988 }
989 \f
990 /*
991 *----------------------------------------------------------------------
992 *
993 * Tcl_AppendResult --
994 *
995 * Append a variable number of strings onto the result already
996 * present for an interpreter.
997 *
998 * Results:
999 * None.
1000 *
1001 * Side effects:
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).
1005 *
1006 *----------------------------------------------------------------------
1007 */
1008
1009 void
1010 Tcl_AppendResult(Tcl_Interp *interp, ...)
1011 {
1012 va_list argList;
1013 register Interp *iPtr;
1014 char *string;
1015 int newSpace;
1016
1017 /*
1018 * First, scan through all the arguments to see how much space is
1019 * needed.
1020 */
1021
1022 va_start(argList, interp);
1023 iPtr = (Interp *)interp;
1024 newSpace = 0;
1025 while (1) {
1026 string = va_arg(argList, char *);
1027 if (string == NULL) {
1028 break;
1029 }
1030 newSpace += strlen(string);
1031 }
1032 va_end(argList);
1033
1034 /*
1035 * If the append buffer isn't already setup and large enough
1036 * to hold the new data, set it up.
1037 */
1038
1039 if ((iPtr->result != iPtr->appendResult)
1040 || ((newSpace + iPtr->appendUsed) >= iPtr->appendAvl)) {
1041 SetupAppendBuffer(iPtr, newSpace);
1042 }
1043
1044 /*
1045 * Final step: go through all the argument strings again, copying
1046 * them into the buffer.
1047 */
1048
1049 va_start(argList, interp);
1050 while (1) {
1051 string = va_arg(argList, char *);
1052 if (string == NULL) {
1053 break;
1054 }
1055 strcpy(iPtr->appendResult + iPtr->appendUsed, string);
1056 iPtr->appendUsed += strlen(string);
1057 }
1058 va_end(argList);
1059 }
1060 \f
1061 /*
1062 *----------------------------------------------------------------------
1063 *
1064 * Tcl_AppendElement --
1065 *
1066 * Convert a string to a valid Tcl list element and append it
1067 * to the current result (which is ostensibly a list).
1068 *
1069 * Results:
1070 * None.
1071 *
1072 * Side effects:
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.
1077 *
1078 *----------------------------------------------------------------------
1079 */
1080
1081 void
1082 Tcl_AppendElement (
1083 Tcl_Interp *interp, /* Interpreter whose result is to be
1084 * extended. */
1085 char *string, /* String to convert to list element and
1086 * add to result. */
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. */
1091 )
1092 {
1093 register Interp *iPtr = (Interp *) interp;
1094 int size, flags;
1095 char *dst;
1096
1097 /*
1098 * See how much space is needed, and grow the append buffer if
1099 * needed to accommodate the list element.
1100 */
1101
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);
1106 }
1107
1108 /*
1109 * Convert the string into a list element and copy it to the
1110 * buffer that's forming.
1111 */
1112
1113 dst = iPtr->appendResult + iPtr->appendUsed;
1114 if (!noSep && (iPtr->appendUsed != 0)) {
1115 iPtr->appendUsed++;
1116 *dst = ' ';
1117 dst++;
1118 }
1119 iPtr->appendUsed += Tcl_ConvertElement(string, dst, flags);
1120 }
1121 \f
1122 /*
1123 *----------------------------------------------------------------------
1124 *
1125 * SetupAppendBuffer --
1126 *
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.
1130 *
1131 * Results:
1132 * None.
1133 *
1134 * Side effects:
1135 * None.
1136 *
1137 *----------------------------------------------------------------------
1138 */
1139
1140 static void
1141 SetupAppendBuffer (
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. */
1145 )
1146 {
1147 int totalSpace;
1148
1149 /*
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.
1153 */
1154
1155 if (iPtr->result != iPtr->appendResult) {
1156 /*
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.
1160 */
1161
1162 if (iPtr->appendAvl > 500) {
1163 ckfree(iPtr->appendResult);
1164 iPtr->appendResult = NULL;
1165 iPtr->appendAvl = 0;
1166 }
1167 iPtr->appendUsed = strlen(iPtr->result);
1168 }
1169 totalSpace = newSpace + iPtr->appendUsed;
1170 if (totalSpace >= iPtr->appendAvl) {
1171 char *new;
1172
1173 if (totalSpace < 100) {
1174 totalSpace = 200;
1175 } else {
1176 totalSpace *= 2;
1177 }
1178 new = (char *) ckalloc((unsigned) totalSpace);
1179 strcpy(new, iPtr->result);
1180 if (iPtr->appendResult != NULL) {
1181 ckfree(iPtr->appendResult);
1182 }
1183 iPtr->appendResult = new;
1184 iPtr->appendAvl = totalSpace;
1185 } else if (iPtr->result != iPtr->appendResult) {
1186 strcpy(iPtr->appendResult, iPtr->result);
1187 }
1188 Tcl_FreeResult(iPtr);
1189 iPtr->result = iPtr->appendResult;
1190 }
1191 \f
1192 /*
1193 *----------------------------------------------------------------------
1194 *
1195 * Tcl_ResetResult --
1196 *
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.
1201 *
1202 * Results:
1203 * None.
1204 *
1205 * Side effects:
1206 * None.
1207 *
1208 *----------------------------------------------------------------------
1209 */
1210
1211 void
1212 Tcl_ResetResult (
1213 Tcl_Interp *interp /* Interpreter for which to clear result. */
1214 )
1215 {
1216 register Interp *iPtr = (Interp *) interp;
1217
1218 Tcl_FreeResult(iPtr);
1219 iPtr->result = iPtr->resultSpace;
1220 iPtr->resultSpace[0] = 0;
1221 iPtr->flags &=
1222 ~(ERR_ALREADY_LOGGED | ERR_IN_PROGRESS | ERROR_CODE_SET);
1223 }
1224 \f
1225 /*
1226 *----------------------------------------------------------------------
1227 *
1228 * Tcl_SetErrorCode --
1229 *
1230 * This procedure is called to record machine-readable information
1231 * about an error that is about to be returned.
1232 *
1233 * Results:
1234 * None.
1235 *
1236 * Side effects:
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.
1242 *
1243 *----------------------------------------------------------------------
1244 */
1245 void
1246 Tcl_SetErrorCode(Tcl_Interp *interp, ...)
1247 {
1248 va_list argList;
1249 char *string;
1250 int flags;
1251 Interp *iPtr;
1252
1253 /*
1254 * Scan through the arguments one at a time, appending them to
1255 * $errorCode as list elements.
1256 */
1257
1258 va_start(argList, interp);
1259 iPtr = (Interp *)interp;
1260 flags = TCL_GLOBAL_ONLY | TCL_LIST_ELEMENT;
1261 while (1) {
1262 string = va_arg(argList, char *);
1263 if (string == NULL) {
1264 break;
1265 }
1266 (void) Tcl_SetVar2((Tcl_Interp *) iPtr, "errorCode",
1267 (char *) NULL, string, flags);
1268 flags |= TCL_APPEND_VALUE;
1269 }
1270 va_end(argList);
1271 iPtr->flags |= ERROR_CODE_SET;
1272 }
1273 \f
1274 /*
1275 *----------------------------------------------------------------------
1276 *
1277 * TclGetListIndex --
1278 *
1279 * Parse a list index, which may be either an integer or the
1280 * value "end".
1281 *
1282 * Results:
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).
1290 *
1291 * Side effects:
1292 * None.
1293 *
1294 *----------------------------------------------------------------------
1295 */
1296
1297 int
1298 TclGetListIndex (
1299 Tcl_Interp *interp, /* Interpreter for error reporting. */
1300 char *string, /* String containing list index. */
1301 int *indexPtr /* Where to store index. */
1302 )
1303 {
1304 if (isdigit(*string) || (*string == '-')) {
1305 if (Tcl_GetInt(interp, string, indexPtr) != TCL_OK) {
1306 return TCL_ERROR;
1307 }
1308 if (*indexPtr < 0) {
1309 *indexPtr = 0;
1310 }
1311 } else if (strncmp(string, "end", strlen(string)) == 0) {
1312 *indexPtr = 1<<30;
1313 } else {
1314 Tcl_AppendResult(interp, "bad index \"", string,
1315 "\": must be integer or \"end\"", (char *) NULL);
1316 return TCL_ERROR;
1317 }
1318 return TCL_OK;
1319 }
1320 \f
1321 /*
1322 *----------------------------------------------------------------------
1323 *
1324 * TclCompileRegexp --
1325 *
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.
1330 *
1331 * Results:
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.
1336 *
1337 * Side effects:
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.
1341 *
1342 *----------------------------------------------------------------------
1343 */
1344
1345 regexp *
1346 TclCompileRegexp (
1347 Tcl_Interp *interp, /* For use in error reporting. */
1348 char *string /* String for which to produce
1349 * compiled regular expression. */
1350 )
1351 {
1352 register Interp *iPtr = (Interp *) interp;
1353 int i, length;
1354 regexp *result;
1355
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)) {
1360 /*
1361 * Move the matched pattern to the first slot in the
1362 * cache and shift the other patterns down one position.
1363 */
1364
1365 if (i != 0) {
1366 int j;
1367 char *cachedString;
1368
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];
1375 }
1376 iPtr->patterns[0] = cachedString;
1377 iPtr->patLengths[0] = length;
1378 iPtr->regexps[0] = result;
1379 }
1380 return iPtr->regexps[0];
1381 }
1382 }
1383
1384 /*
1385 * No match in the cache. Compile the string and add it to the
1386 * cache.
1387 */
1388
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);
1395 return NULL;
1396 }
1397 if (iPtr->patterns[NUM_REGEXPS-1] != NULL) {
1398 ckfree(iPtr->patterns[NUM_REGEXPS-1]);
1399 ckfree((char *) iPtr->regexps[NUM_REGEXPS-1]);
1400 }
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];
1405 }
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;
1410 return result;
1411 }
1412 \f
1413 /*
1414 *----------------------------------------------------------------------
1415 *
1416 * regerror --
1417 *
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.
1421 *
1422 * Results:
1423 * None.
1424 *
1425 * Side effects:
1426 * The value of "string" is saved in "tclRegexpError".
1427 *
1428 *----------------------------------------------------------------------
1429 */
1430
1431 void
1432 regerror (
1433 char *string /* Error message. */
1434 )
1435 {
1436 tclRegexpError = string;
1437 }
Impressum, Datenschutz