Fork me on GitHub

source: git/external/tcl/tclUtil.c@ 4a67ae4

ImprovedOutputFile Timing dual_readout llp
Last change on this file since 4a67ae4 was d7d2da3, checked in by pavel <pavel@…>, 12 years ago

move branches/ModularDelphes to trunk

  • Property mode set to 100644
File size: 68.3 KB
Line 
1/*
2 * tclUtil.c --
3 *
4 * This file contains utility procedures that are used by many Tcl
5 * commands.
6 *
7 * Copyright (c) 1987-1993 The Regents of the University of California.
8 * Copyright (c) 1994-1997 Sun Microsystems, Inc.
9 *
10 * See the file "license.terms" for information on usage and redistribution
11 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
12 *
13 * RCS: @(#) $Id: tclUtil.c,v 1.1 2008-06-04 13:58:11 demin Exp $
14 */
15
16#include "tclInt.h"
17#include "tclPort.h"
18
19/*
20 * The following variable holds the full path name of the binary
21 * from which this application was executed, or NULL if it isn't
22 * know. The value of the variable is set by the procedure
23 * Tcl_FindExecutable. The storage space is dynamically allocated.
24 */
25
26char *tclExecutableName = NULL;
27
28/*
29 * The following values are used in the flags returned by Tcl_ScanElement
30 * and used by Tcl_ConvertElement. The value TCL_DONT_USE_BRACES is also
31 * defined in tcl.h; make sure its value doesn't overlap with any of the
32 * values below.
33 *
34 * TCL_DONT_USE_BRACES - 1 means the string mustn't be enclosed in
35 * braces (e.g. it contains unmatched braces,
36 * or ends in a backslash character, or user
37 * just doesn't want braces); handle all
38 * special characters by adding backslashes.
39 * USE_BRACES - 1 means the string contains a special
40 * character that can be handled simply by
41 * enclosing the entire argument in braces.
42 * BRACES_UNMATCHED - 1 means that braces aren't properly matched
43 * in the argument.
44 */
45
46#define USE_BRACES 2
47#define BRACES_UNMATCHED 4
48
49/*
50 * The following values determine the precision used when converting
51 * floating-point values to strings. This information is linked to all
52 * of the tcl_precision variables in all interpreters via the procedure
53 * TclPrecTraceProc.
54 *
55 * NOTE: these variables are not thread-safe.
56 */
57
58static char precisionString[10] = "12";
59 /* The string value of all the tcl_precision
60 * variables. */
61static char precisionFormat[10] = "%.12g";
62 /* The format string actually used in calls
63 * to sprintf. */
64
65
66/*
67 * Function prototypes for local procedures in this file:
68 */
69
70static void SetupAppendBuffer _ANSI_ARGS_((Interp *iPtr,
71 int newSpace));
72
73
74/*
75 *----------------------------------------------------------------------
76 *
77 * TclFindElement --
78 *
79 * Given a pointer into a Tcl list, locate the first (or next)
80 * element in the list.
81 *
82 * Results:
83 * The return value is normally TCL_OK, which means that the
84 * element was successfully located. If TCL_ERROR is returned
85 * it means that list didn't have proper list structure;
86 * interp->result contains a more detailed error message.
87 *
88 * If TCL_OK is returned, then *elementPtr will be set to point to the
89 * first element of list, and *nextPtr will be set to point to the
90 * character just after any white space following the last character
91 * that's part of the element. If this is the last argument in the
92 * list, then *nextPtr will point just after the last character in the
93 * list (i.e., at the character at list+listLength). If sizePtr is
94 * non-NULL, *sizePtr is filled in with the number of characters in the
95 * element. If the element is in braces, then *elementPtr will point
96 * to the character after the opening brace and *sizePtr will not
97 * include either of the braces. If there isn't an element in the list,
98 * *sizePtr will be zero, and both *elementPtr and *termPtr will point
99 * just after the last character in the list. Note: this procedure does
100 * NOT collapse backslash sequences.
101 *
102 * Side effects:
103 * None.
104 *
105 *----------------------------------------------------------------------
106 */
107
108int
109TclFindElement(interp, list, listLength, elementPtr, nextPtr, sizePtr,
110 bracePtr)
111 Tcl_Interp *interp; /* Interpreter to use for error reporting.
112 * If NULL, then no error message is left
113 * after errors. */
114 char *list; /* Points to the first byte of a string
115 * containing a Tcl list with zero or more
116 * elements (possibly in braces). */
117 int listLength; /* Number of bytes in the list's string. */
118 char **elementPtr; /* Where to put address of first significant
119 * character in first element of list. */
120 char **nextPtr; /* Fill in with location of character just
121 * after all white space following end of
122 * argument (next arg or end of list). */
123 int *sizePtr; /* If non-zero, fill in with size of
124 * element. */
125 int *bracePtr; /* If non-zero, fill in with non-zero/zero
126 * to indicate that arg was/wasn't
127 * in braces. */
128{
129 char *p = list;
130 char *elemStart; /* Points to first byte of first element. */
131 char *limit; /* Points just after list's last byte. */
132 int openBraces = 0; /* Brace nesting level during parse. */
133 int inQuotes = 0;
134 int size = 0; /* Init. avoids compiler warning. */
135 int numChars;
136 char *p2;
137
138 /*
139 * Skim off leading white space and check for an opening brace or
140 * quote. We treat embedded NULLs in the list as bytes belonging to
141 * a list element. Note: use of "isascii" below and elsewhere in this
142 * procedure is a temporary hack (7/27/90) because Mx uses characters
143 * with the high-order bit set for some things. This should probably
144 * be changed back eventually, or all of Tcl should call isascii.
145 */
146
147 limit = (list + listLength);
148 while ((p < limit) && (isspace(UCHAR(*p)))) {
149 p++;
150 }
151 if (p == limit) { /* no element found */
152 elemStart = limit;
153 goto done;
154 }
155
156 if (*p == '{') {
157 openBraces = 1;
158 p++;
159 } else if (*p == '"') {
160 inQuotes = 1;
161 p++;
162 }
163 elemStart = p;
164 if (bracePtr != 0) {
165 *bracePtr = openBraces;
166 }
167
168 /*
169 * Find element's end (a space, close brace, or the end of the string).
170 */
171
172 while (p < limit) {
173 switch (*p) {
174
175 /*
176 * Open brace: don't treat specially unless the element is in
177 * braces. In this case, keep a nesting count.
178 */
179
180 case '{':
181 if (openBraces != 0) {
182 openBraces++;
183 }
184 break;
185
186 /*
187 * Close brace: if element is in braces, keep nesting count and
188 * quit when the last close brace is seen.
189 */
190
191 case '}':
192 if (openBraces > 1) {
193 openBraces--;
194 } else if (openBraces == 1) {
195 size = (p - elemStart);
196 p++;
197 if ((p >= limit) || isspace(UCHAR(*p))) {
198 goto done;
199 }
200
201 /*
202 * Garbage after the closing brace; return an error.
203 */
204
205 if (interp != NULL) {
206 char buf[100];
207
208 p2 = p;
209 while ((p2 < limit) && (!isspace(UCHAR(*p2)))
210 && (p2 < p+20)) {
211 p2++;
212 }
213 sprintf(buf,
214 "list element in braces followed by \"%.*s\" instead of space",
215 (int) (p2-p), p);
216 Tcl_SetResult(interp, buf, TCL_VOLATILE);
217 }
218 return TCL_ERROR;
219 }
220 break;
221
222 /*
223 * Backslash: skip over everything up to the end of the
224 * backslash sequence.
225 */
226
227 case '\\': {
228 (void) Tcl_Backslash(p, &numChars);
229 p += (numChars - 1);
230 break;
231 }
232
233 /*
234 * Space: ignore if element is in braces or quotes; otherwise
235 * terminate element.
236 */
237
238 case ' ':
239 case '\f':
240 case '\n':
241 case '\r':
242 case '\t':
243 case '\v':
244 if ((openBraces == 0) && !inQuotes) {
245 size = (p - elemStart);
246 goto done;
247 }
248 break;
249
250 /*
251 * Double-quote: if element is in quotes then terminate it.
252 */
253
254 case '"':
255 if (inQuotes) {
256 size = (p - elemStart);
257 p++;
258 if ((p >= limit) || isspace(UCHAR(*p))) {
259 goto done;
260 }
261
262 /*
263 * Garbage after the closing quote; return an error.
264 */
265
266 if (interp != NULL) {
267 char buf[100];
268
269 p2 = p;
270 while ((p2 < limit) && (!isspace(UCHAR(*p2)))
271 && (p2 < p+20)) {
272 p2++;
273 }
274 sprintf(buf,
275 "list element in quotes followed by \"%.*s\" %s",
276 (int) (p2-p), p, "instead of space");
277 Tcl_SetResult(interp, buf, TCL_VOLATILE);
278 }
279 return TCL_ERROR;
280 }
281 break;
282 }
283 p++;
284 }
285
286
287 /*
288 * End of list: terminate element.
289 */
290
291 if (p == limit) {
292 if (openBraces != 0) {
293 if (interp != NULL) {
294 Tcl_SetResult(interp, "unmatched open brace in list",
295 TCL_STATIC);
296 }
297 return TCL_ERROR;
298 } else if (inQuotes) {
299 if (interp != NULL) {
300 Tcl_SetResult(interp, "unmatched open quote in list",
301 TCL_STATIC);
302 }
303 return TCL_ERROR;
304 }
305 size = (p - elemStart);
306 }
307
308 done:
309 while ((p < limit) && (isspace(UCHAR(*p)))) {
310 p++;
311 }
312 *elementPtr = elemStart;
313 *nextPtr = p;
314 if (sizePtr != 0) {
315 *sizePtr = size;
316 }
317 return TCL_OK;
318}
319
320
321/*
322 *----------------------------------------------------------------------
323 *
324 * TclCopyAndCollapse --
325 *
326 * Copy a string and eliminate any backslashes that aren't in braces.
327 *
328 * Results:
329 * There is no return value. Count characters get copied from src to
330 * dst. Along the way, if backslash sequences are found outside braces,
331 * the backslashes are eliminated in the copy. After scanning count
332 * chars from source, a null character is placed at the end of dst.
333 * Returns the number of characters that got copied.
334 *
335 * Side effects:
336 * None.
337 *
338 *----------------------------------------------------------------------
339 */
340
341int
342TclCopyAndCollapse(count, src, dst)
343 int count; /* Number of characters to copy from src. */
344 char *src; /* Copy from here... */
345 char *dst; /* ... to here. */
346{
347 char c;
348 int numRead;
349 int newCount = 0;
350
351 for (c = *src; count > 0; src++, c = *src, count--) {
352 if (c == '\\') {
353 *dst = Tcl_Backslash(src, &numRead);
354 dst++;
355 src += numRead-1;
356 count -= numRead-1;
357 newCount++;
358 } else {
359 *dst = c;
360 dst++;
361 newCount++;
362 }
363 }
364 *dst = 0;
365 return newCount;
366}
367
368
369/*
370 *----------------------------------------------------------------------
371 *
372 * Tcl_SplitList --
373 *
374 * Splits a list up into its constituent fields.
375 *
376 * Results
377 * The return value is normally TCL_OK, which means that
378 * the list was successfully split up. If TCL_ERROR is
379 * returned, it means that "list" didn't have proper list
380 * structure; interp->result will contain a more detailed
381 * error message.
382 *
383 * *argvPtr will be filled in with the address of an array
384 * whose elements point to the elements of list, in order.
385 * *argcPtr will get filled in with the number of valid elements
386 * in the array. A single block of memory is dynamically allocated
387 * to hold both the argv array and a copy of the list (with
388 * backslashes and braces removed in the standard way).
389 * The caller must eventually free this memory by calling free()
390 * on *argvPtr. Note: *argvPtr and *argcPtr are only modified
391 * if the procedure returns normally.
392 *
393 * Side effects:
394 * Memory is allocated.
395 *
396 *----------------------------------------------------------------------
397 */
398
399int
400Tcl_SplitList(interp, list, argcPtr, argvPtr)
401 Tcl_Interp *interp; /* Interpreter to use for error reporting.
402 * If NULL, no error message is left. */
403 char *list; /* Pointer to string with list structure. */
404 int *argcPtr; /* Pointer to location to fill in with
405 * the number of elements in the list. */
406 char ***argvPtr; /* Pointer to place to store pointer to
407 * array of pointers to list elements. */
408{
409 char **argv;
410 char *p;
411 int length, size, i, result, elSize, brace;
412 char *element;
413
414 /*
415 * Figure out how much space to allocate. There must be enough
416 * space for both the array of pointers and also for a copy of
417 * the list. To estimate the number of pointers needed, count
418 * the number of space characters in the list.
419 */
420
421 for (size = 1, p = list; *p != 0; p++) {
422 if (isspace(UCHAR(*p))) {
423 size++;
424 }
425 }
426 size++; /* Leave space for final NULL pointer. */
427 argv = (char **) ckalloc((unsigned)
428 ((size * sizeof(char *)) + (p - list) + 1));
429 length = strlen(list);
430 for (i = 0, p = ((char *) argv) + size*sizeof(char *);
431 *list != 0; i++) {
432 char *prevList = list;
433
434 result = TclFindElement(interp, list, length, &element,
435 &list, &elSize, &brace);
436 length -= (list - prevList);
437 if (result != TCL_OK) {
438 ckfree((char *) argv);
439 return result;
440 }
441 if (*element == 0) {
442 break;
443 }
444 if (i >= size) {
445 ckfree((char *) argv);
446 if (interp != NULL) {
447 Tcl_SetResult(interp, "internal error in Tcl_SplitList",
448 TCL_STATIC);
449 }
450 return TCL_ERROR;
451 }
452 argv[i] = p;
453 if (brace) {
454 memcpy((VOID *) p, (VOID *) element, (size_t) elSize);
455 p += elSize;
456 *p = 0;
457 p++;
458 } else {
459 TclCopyAndCollapse(elSize, element, p);
460 p += elSize+1;
461 }
462 }
463
464 argv[i] = NULL;
465 *argvPtr = argv;
466 *argcPtr = i;
467 return TCL_OK;
468}
469
470
471/*
472 *----------------------------------------------------------------------
473 *
474 * Tcl_ScanElement --
475 *
476 * This procedure is a companion procedure to Tcl_ConvertElement.
477 * It scans a string to see what needs to be done to it (e.g. add
478 * backslashes or enclosing braces) to make the string into a
479 * valid Tcl list element.
480 *
481 * Results:
482 * The return value is an overestimate of the number of characters
483 * that will be needed by Tcl_ConvertElement to produce a valid
484 * list element from string. The word at *flagPtr is filled in
485 * with a value needed by Tcl_ConvertElement when doing the actual
486 * conversion.
487 *
488 * Side effects:
489 * None.
490 *
491 *----------------------------------------------------------------------
492 */
493
494int
495Tcl_ScanElement(string, flagPtr)
496 CONST char *string; /* String to convert to Tcl list element. */
497 int *flagPtr; /* Where to store information to guide
498 * Tcl_ConvertCountedElement. */
499{
500 return Tcl_ScanCountedElement(string, -1, flagPtr);
501}
502
503
504/*
505 *----------------------------------------------------------------------
506 *
507 * Tcl_ScanCountedElement --
508 *
509 * This procedure is a companion procedure to
510 * Tcl_ConvertCountedElement. It scans a string to see what
511 * needs to be done to it (e.g. add backslashes or enclosing
512 * braces) to make the string into a valid Tcl list element.
513 * If length is -1, then the string is scanned up to the first
514 * null byte.
515 *
516 * Results:
517 * The return value is an overestimate of the number of characters
518 * that will be needed by Tcl_ConvertCountedElement to produce a
519 * valid list element from string. The word at *flagPtr is
520 * filled in with a value needed by Tcl_ConvertCountedElement
521 * when doing the actual conversion.
522 *
523 * Side effects:
524 * None.
525 *
526 *----------------------------------------------------------------------
527 */
528
529int
530Tcl_ScanCountedElement(string, length, flagPtr)
531 CONST char *string; /* String to convert to Tcl list element. */
532 int length; /* Number of bytes in string, or -1. */
533 int *flagPtr; /* Where to store information to guide
534 * Tcl_ConvertElement. */
535{
536 int flags, nestingLevel;
537 CONST char *p, *lastChar;
538
539 /*
540 * This procedure and Tcl_ConvertElement together do two things:
541 *
542 * 1. They produce a proper list, one that will yield back the
543 * argument strings when evaluated or when disassembled with
544 * Tcl_SplitList. This is the most important thing.
545 *
546 * 2. They try to produce legible output, which means minimizing the
547 * use of backslashes (using braces instead). However, there are
548 * some situations where backslashes must be used (e.g. an element
549 * like "{abc": the leading brace will have to be backslashed.
550 * For each element, one of three things must be done:
551 *
552 * (a) Use the element as-is (it doesn't contain any special
553 * characters). This is the most desirable option.
554 *
555 * (b) Enclose the element in braces, but leave the contents alone.
556 * This happens if the element contains embedded space, or if it
557 * contains characters with special interpretation ($, [, ;, or \),
558 * or if it starts with a brace or double-quote, or if there are
559 * no characters in the element.
560 *
561 * (c) Don't enclose the element in braces, but add backslashes to
562 * prevent special interpretation of special characters. This is a
563 * last resort used when the argument would normally fall under case
564 * (b) but contains unmatched braces. It also occurs if the last
565 * character of the argument is a backslash or if the element contains
566 * a backslash followed by newline.
567 *
568 * The procedure figures out how many bytes will be needed to store
569 * the result (actually, it overestimates). It also collects information
570 * about the element in the form of a flags word.
571 *
572 * Note: list elements produced by this procedure and
573 * Tcl_ConvertCountedElement must have the property that they can be
574 * enclosing in curly braces to make sub-lists. This means, for
575 * example, that we must not leave unmatched curly braces in the
576 * resulting list element. This property is necessary in order for
577 * procedures like Tcl_DStringStartSublist to work.
578 */
579
580 nestingLevel = 0;
581 flags = 0;
582 if (string == NULL) {
583 string = "";
584 }
585 if (length == -1) {
586 length = strlen(string);
587 }
588 lastChar = string + length;
589 p = string;
590 if ((p == lastChar) || (*p == '{') || (*p == '"')) {
591 flags |= USE_BRACES;
592 }
593 for ( ; p != lastChar; p++) {
594 switch (*p) {
595 case '{':
596 nestingLevel++;
597 break;
598 case '}':
599 nestingLevel--;
600 if (nestingLevel < 0) {
601 flags |= TCL_DONT_USE_BRACES|BRACES_UNMATCHED;
602 }
603 break;
604 case '[':
605 case '$':
606 case ';':
607 case ' ':
608 case '\f':
609 case '\n':
610 case '\r':
611 case '\t':
612 case '\v':
613 flags |= USE_BRACES;
614 break;
615 case '\\':
616 if ((p+1 == lastChar) || (p[1] == '\n')) {
617 flags = TCL_DONT_USE_BRACES | BRACES_UNMATCHED;
618 } else {
619 int size;
620
621 (void) Tcl_Backslash(p, &size);
622 p += size-1;
623 flags |= USE_BRACES;
624 }
625 break;
626 }
627 }
628 if (nestingLevel != 0) {
629 flags = TCL_DONT_USE_BRACES | BRACES_UNMATCHED;
630 }
631 *flagPtr = flags;
632
633 /*
634 * Allow enough space to backslash every character plus leave
635 * two spaces for braces.
636 */
637
638 return 2*(p-string) + 2;
639}
640
641
642/*
643 *----------------------------------------------------------------------
644 *
645 * Tcl_ConvertElement --
646 *
647 * This is a companion procedure to Tcl_ScanElement. Given
648 * the information produced by Tcl_ScanElement, this procedure
649 * converts a string to a list element equal to that string.
650 *
651 * Results:
652 * Information is copied to *dst in the form of a list element
653 * identical to src (i.e. if Tcl_SplitList is applied to dst it
654 * will produce a string identical to src). The return value is
655 * a count of the number of characters copied (not including the
656 * terminating NULL character).
657 *
658 * Side effects:
659 * None.
660 *
661 *----------------------------------------------------------------------
662 */
663
664int
665Tcl_ConvertElement(src, dst, flags)
666 CONST char *src; /* Source information for list element. */
667 char *dst; /* Place to put list-ified element. */
668 int flags; /* Flags produced by Tcl_ScanElement. */
669{
670 return Tcl_ConvertCountedElement(src, -1, dst, flags);
671}
672
673
674/*
675 *----------------------------------------------------------------------
676 *
677 * Tcl_ConvertCountedElement --
678 *
679 * This is a companion procedure to Tcl_ScanCountedElement. Given
680 * the information produced by Tcl_ScanCountedElement, this
681 * procedure converts a string to a list element equal to that
682 * string.
683 *
684 * Results:
685 * Information is copied to *dst in the form of a list element
686 * identical to src (i.e. if Tcl_SplitList is applied to dst it
687 * will produce a string identical to src). The return value is
688 * a count of the number of characters copied (not including the
689 * terminating NULL character).
690 *
691 * Side effects:
692 * None.
693 *
694 *----------------------------------------------------------------------
695 */
696
697int
698Tcl_ConvertCountedElement(src, length, dst, flags)
699 CONST char *src; /* Source information for list element. */
700 int length; /* Number of bytes in src, or -1. */
701 char *dst; /* Place to put list-ified element. */
702 int flags; /* Flags produced by Tcl_ScanElement. */
703{
704 char *p = dst;
705 CONST char *lastChar;
706
707 /*
708 * See the comment block at the beginning of the Tcl_ScanElement
709 * code for details of how this works.
710 */
711
712 if (src && length == -1) {
713 length = strlen(src);
714 }
715 if ((src == NULL) || (length == 0)) {
716 p[0] = '{';
717 p[1] = '}';
718 p[2] = 0;
719 return 2;
720 }
721 lastChar = src + length;
722 if ((flags & USE_BRACES) && !(flags & TCL_DONT_USE_BRACES)) {
723 *p = '{';
724 p++;
725 for ( ; src != lastChar; src++, p++) {
726 *p = *src;
727 }
728 *p = '}';
729 p++;
730 } else {
731 if (*src == '{') {
732 /*
733 * Can't have a leading brace unless the whole element is
734 * enclosed in braces. Add a backslash before the brace.
735 * Furthermore, this may destroy the balance between open
736 * and close braces, so set BRACES_UNMATCHED.
737 */
738
739 p[0] = '\\';
740 p[1] = '{';
741 p += 2;
742 src++;
743 flags |= BRACES_UNMATCHED;
744 }
745 for (; src != lastChar; src++) {
746 switch (*src) {
747 case ']':
748 case '[':
749 case '$':
750 case ';':
751 case ' ':
752 case '\\':
753 case '"':
754 *p = '\\';
755 p++;
756 break;
757 case '{':
758 case '}':
759 /*
760 * It may not seem necessary to backslash braces, but
761 * it is. The reason for this is that the resulting
762 * list element may actually be an element of a sub-list
763 * enclosed in braces (e.g. if Tcl_DStringStartSublist
764 * has been invoked), so there may be a brace mismatch
765 * if the braces aren't backslashed.
766 */
767
768 if (flags & BRACES_UNMATCHED) {
769 *p = '\\';
770 p++;
771 }
772 break;
773 case '\f':
774 *p = '\\';
775 p++;
776 *p = 'f';
777 p++;
778 continue;
779 case '\n':
780 *p = '\\';
781 p++;
782 *p = 'n';
783 p++;
784 continue;
785 case '\r':
786 *p = '\\';
787 p++;
788 *p = 'r';
789 p++;
790 continue;
791 case '\t':
792 *p = '\\';
793 p++;
794 *p = 't';
795 p++;
796 continue;
797 case '\v':
798 *p = '\\';
799 p++;
800 *p = 'v';
801 p++;
802 continue;
803 }
804 *p = *src;
805 p++;
806 }
807 }
808 *p = '\0';
809 return p-dst;
810}
811
812
813/*
814 *----------------------------------------------------------------------
815 *
816 * Tcl_Merge --
817 *
818 * Given a collection of strings, merge them together into a
819 * single string that has proper Tcl list structured (i.e.
820 * Tcl_SplitList may be used to retrieve strings equal to the
821 * original elements, and Tcl_Eval will parse the string back
822 * into its original elements).
823 *
824 * Results:
825 * The return value is the address of a dynamically-allocated
826 * string containing the merged list.
827 *
828 * Side effects:
829 * None.
830 *
831 *----------------------------------------------------------------------
832 */
833
834char *
835Tcl_Merge(argc, argv)
836 int argc; /* How many strings to merge. */
837 char **argv; /* Array of string values. */
838{
839# define LOCAL_SIZE 20
840 int localFlags[LOCAL_SIZE], *flagPtr;
841 int numChars;
842 char *result;
843 char *dst;
844 int i;
845
846 /*
847 * Pass 1: estimate space, gather flags.
848 */
849
850 if (argc <= LOCAL_SIZE) {
851 flagPtr = localFlags;
852 } else {
853 flagPtr = (int *) ckalloc((unsigned) argc*sizeof(int));
854 }
855 numChars = 1;
856 for (i = 0; i < argc; i++) {
857 numChars += Tcl_ScanElement(argv[i], &flagPtr[i]) + 1;
858 }
859
860 /*
861 * Pass two: copy into the result area.
862 */
863
864 result = (char *) ckalloc((unsigned) numChars);
865 dst = result;
866 for (i = 0; i < argc; i++) {
867 numChars = Tcl_ConvertElement(argv[i], dst, flagPtr[i]);
868 dst += numChars;
869 *dst = ' ';
870 dst++;
871 }
872 if (dst == result) {
873 *dst = 0;
874 } else {
875 dst[-1] = 0;
876 }
877
878 if (flagPtr != localFlags) {
879 ckfree((char *) flagPtr);
880 }
881 return result;
882}
883
884
885/*
886 *----------------------------------------------------------------------
887 *
888 * Tcl_Concat --
889 *
890 * Concatenate a set of strings into a single large string.
891 *
892 * Results:
893 * The return value is dynamically-allocated string containing
894 * a concatenation of all the strings in argv, with spaces between
895 * the original argv elements.
896 *
897 * Side effects:
898 * Memory is allocated for the result; the caller is responsible
899 * for freeing the memory.
900 *
901 *----------------------------------------------------------------------
902 */
903
904char *
905Tcl_Concat(argc, argv)
906 int argc; /* Number of strings to concatenate. */
907 char **argv; /* Array of strings to concatenate. */
908{
909 int totalSize, i;
910 char *p;
911 char *result;
912
913 for (totalSize = 1, i = 0; i < argc; i++) {
914 totalSize += strlen(argv[i]) + 1;
915 }
916 result = (char *) ckalloc((unsigned) totalSize);
917 if (argc == 0) {
918 *result = '\0';
919 return result;
920 }
921 for (p = result, i = 0; i < argc; i++) {
922 char *element;
923 int length;
924
925 /*
926 * Clip white space off the front and back of the string
927 * to generate a neater result, and ignore any empty
928 * elements.
929 */
930
931 element = argv[i];
932 while (isspace(UCHAR(*element))) {
933 element++;
934 }
935 for (length = strlen(element);
936 (length > 0) && (isspace(UCHAR(element[length-1])))
937 && ((length < 2) || (element[length-2] != '\\'));
938 length--) {
939 /* Null loop body. */
940 }
941 if (length == 0) {
942 continue;
943 }
944 memcpy((VOID *) p, (VOID *) element, (size_t) length);
945 p += length;
946 *p = ' ';
947 p++;
948 }
949 if (p != result) {
950 p[-1] = 0;
951 } else {
952 *p = 0;
953 }
954 return result;
955}
956
957
958/*
959 *----------------------------------------------------------------------
960 *
961 * Tcl_ConcatObj --
962 *
963 * Concatenate the strings from a set of objects into a single string
964 * object with spaces between the original strings.
965 *
966 * Results:
967 * The return value is a new string object containing a concatenation
968 * of the strings in objv. Its ref count is zero.
969 *
970 * Side effects:
971 * A new object is created.
972 *
973 *----------------------------------------------------------------------
974 */
975
976Tcl_Obj *
977Tcl_ConcatObj(objc, objv)
978 int objc; /* Number of objects to concatenate. */
979 Tcl_Obj *CONST objv[]; /* Array of objects to concatenate. */
980{
981 int allocSize, finalSize, length, elemLength, i;
982 char *p;
983 char *element;
984 char *concatStr;
985 Tcl_Obj *objPtr;
986
987 allocSize = 0;
988 for (i = 0; i < objc; i++) {
989 objPtr = objv[i];
990 element = TclGetStringFromObj(objPtr, &length);
991 if ((element != NULL) && (length > 0)) {
992 allocSize += (length + 1);
993 }
994 }
995 if (allocSize == 0) {
996 allocSize = 1; /* enough for the NULL byte at end */
997 }
998
999 /*
1000 * Allocate storage for the concatenated result. Note that allocSize
1001 * is one more than the total number of characters, and so includes
1002 * room for the terminating NULL byte.
1003 */
1004
1005 concatStr = (char *) ckalloc((unsigned) allocSize);
1006
1007 /*
1008 * Now concatenate the elements. Clip white space off the front and back
1009 * to generate a neater result, and ignore any empty elements. Also put
1010 * a null byte at the end.
1011 */
1012
1013 finalSize = 0;
1014 if (objc == 0) {
1015 *concatStr = '\0';
1016 } else {
1017 p = concatStr;
1018 for (i = 0; i < objc; i++) {
1019 objPtr = objv[i];
1020 element = TclGetStringFromObj(objPtr, &elemLength);
1021 while ((elemLength > 0) && (isspace(UCHAR(*element)))) {
1022 element++;
1023 elemLength--;
1024 }
1025
1026 /*
1027 * Trim trailing white space. But, be careful not to trim
1028 * a space character if it is preceded by a backslash: in
1029 * this case it could be significant.
1030 */
1031
1032 while ((elemLength > 0)
1033 && isspace(UCHAR(element[elemLength-1]))
1034 && ((elemLength < 2) || (element[elemLength-2] != '\\'))) {
1035 elemLength--;
1036 }
1037 if (elemLength == 0) {
1038 continue; /* nothing left of this element */
1039 }
1040 memcpy((VOID *) p, (VOID *) element, (size_t) elemLength);
1041 p += elemLength;
1042 *p = ' ';
1043 p++;
1044 finalSize += (elemLength + 1);
1045 }
1046 if (p != concatStr) {
1047 p[-1] = 0;
1048 finalSize -= 1; /* we overwrote the final ' ' */
1049 } else {
1050 *p = 0;
1051 }
1052 }
1053
1054 TclNewObj(objPtr);
1055 objPtr->bytes = concatStr;
1056 objPtr->length = finalSize;
1057 return objPtr;
1058}
1059
1060
1061/*
1062 *----------------------------------------------------------------------
1063 *
1064 * Tcl_StringMatch --
1065 *
1066 * See if a particular string matches a particular pattern.
1067 *
1068 * Results:
1069 * The return value is 1 if string matches pattern, and
1070 * 0 otherwise. The matching operation permits the following
1071 * special characters in the pattern: *?\[] (see the manual
1072 * entry for details on what these mean).
1073 *
1074 * Side effects:
1075 * None.
1076 *
1077 *----------------------------------------------------------------------
1078 */
1079
1080int
1081Tcl_StringMatch(string, pattern)
1082 char *string; /* String. */
1083 char *pattern; /* Pattern, which may contain special
1084 * characters. */
1085{
1086 char c2;
1087
1088 while (1) {
1089 /* See if we're at the end of both the pattern and the string.
1090 * If so, we succeeded. If we're at the end of the pattern
1091 * but not at the end of the string, we failed.
1092 */
1093
1094 if (*pattern == 0) {
1095 if (*string == 0) {
1096 return 1;
1097 } else {
1098 return 0;
1099 }
1100 }
1101 if ((*string == 0) && (*pattern != '*')) {
1102 return 0;
1103 }
1104
1105 /* Check for a "*" as the next pattern character. It matches
1106 * any substring. We handle this by calling ourselves
1107 * recursively for each postfix of string, until either we
1108 * match or we reach the end of the string.
1109 */
1110
1111 if (*pattern == '*') {
1112 pattern += 1;
1113 if (*pattern == 0) {
1114 return 1;
1115 }
1116 while (1) {
1117 if (Tcl_StringMatch(string, pattern)) {
1118 return 1;
1119 }
1120 if (*string == 0) {
1121 return 0;
1122 }
1123 string += 1;
1124 }
1125 }
1126
1127 /* Check for a "?" as the next pattern character. It matches
1128 * any single character.
1129 */
1130
1131 if (*pattern == '?') {
1132 goto thisCharOK;
1133 }
1134
1135 /* Check for a "[" as the next pattern character. It is followed
1136 * by a list of characters that are acceptable, or by a range
1137 * (two characters separated by "-").
1138 */
1139
1140 if (*pattern == '[') {
1141 pattern += 1;
1142 while (1) {
1143 if ((*pattern == ']') || (*pattern == 0)) {
1144 return 0;
1145 }
1146 if (*pattern == *string) {
1147 break;
1148 }
1149 if (pattern[1] == '-') {
1150 c2 = pattern[2];
1151 if (c2 == 0) {
1152 return 0;
1153 }
1154 if ((*pattern <= *string) && (c2 >= *string)) {
1155 break;
1156 }
1157 if ((*pattern >= *string) && (c2 <= *string)) {
1158 break;
1159 }
1160 pattern += 2;
1161 }
1162 pattern += 1;
1163 }
1164 while (*pattern != ']') {
1165 if (*pattern == 0) {
1166 pattern--;
1167 break;
1168 }
1169 pattern += 1;
1170 }
1171 goto thisCharOK;
1172 }
1173
1174 /* If the next pattern character is '/', just strip off the '/'
1175 * so we do exact matching on the character that follows.
1176 */
1177
1178 if (*pattern == '\\') {
1179 pattern += 1;
1180 if (*pattern == 0) {
1181 return 0;
1182 }
1183 }
1184
1185 /* There's no special character. Just make sure that the next
1186 * characters of each string match.
1187 */
1188
1189 if (*pattern != *string) {
1190 return 0;
1191 }
1192
1193 thisCharOK: pattern += 1;
1194 string += 1;
1195 }
1196}
1197
1198
1199/*
1200 *----------------------------------------------------------------------
1201 *
1202 * Tcl_SetResult --
1203 *
1204 * Arrange for "string" to be the Tcl return value.
1205 *
1206 * Results:
1207 * None.
1208 *
1209 * Side effects:
1210 * interp->result is left pointing either to "string" (if "copy" is 0)
1211 * or to a copy of string. Also, the object result is reset.
1212 *
1213 *----------------------------------------------------------------------
1214 */
1215
1216void
1217Tcl_SetResult(interp, string, freeProc)
1218 Tcl_Interp *interp; /* Interpreter with which to associate the
1219 * return value. */
1220 char *string; /* Value to be returned. If NULL, the
1221 * result is set to an empty string. */
1222 Tcl_FreeProc *freeProc; /* Gives information about the string:
1223 * TCL_STATIC, TCL_VOLATILE, or the address
1224 * of a Tcl_FreeProc such as free. */
1225{
1226 Interp *iPtr = (Interp *) interp;
1227 int length;
1228 Tcl_FreeProc *oldFreeProc = iPtr->freeProc;
1229 char *oldResult = iPtr->result;
1230
1231 if (string == NULL) {
1232 iPtr->resultSpace[0] = 0;
1233 iPtr->result = iPtr->resultSpace;
1234 iPtr->freeProc = 0;
1235 } else if (freeProc == TCL_VOLATILE) {
1236 length = strlen(string);
1237 if (length > TCL_RESULT_SIZE) {
1238 iPtr->result = (char *) ckalloc((unsigned) length+1);
1239 iPtr->freeProc = TCL_DYNAMIC;
1240 } else {
1241 iPtr->result = iPtr->resultSpace;
1242 iPtr->freeProc = 0;
1243 }
1244 strcpy(iPtr->result, string);
1245 } else {
1246 iPtr->result = string;
1247 iPtr->freeProc = freeProc;
1248 }
1249
1250 /*
1251 * If the old result was dynamically-allocated, free it up. Do it
1252 * here, rather than at the beginning, in case the new result value
1253 * was part of the old result value.
1254 */
1255
1256 if (oldFreeProc != 0) {
1257 if ((oldFreeProc == TCL_DYNAMIC)
1258 || (oldFreeProc == (Tcl_FreeProc *) free)) {
1259 ckfree(oldResult);
1260 } else {
1261 (*oldFreeProc)(oldResult);
1262 }
1263 }
1264
1265 /*
1266 * Reset the object result since we just set the string result.
1267 */
1268
1269 TclResetObjResult(iPtr);
1270}
1271
1272
1273/*
1274 *----------------------------------------------------------------------
1275 *
1276 * Tcl_GetStringResult --
1277 *
1278 * Returns an interpreter's result value as a string.
1279 *
1280 * Results:
1281 * The interpreter's result as a string.
1282 *
1283 * Side effects:
1284 * If the string result is empty, the object result is moved to the
1285 * string result, then the object result is reset.
1286 *
1287 *----------------------------------------------------------------------
1288 */
1289
1290char *
1291Tcl_GetStringResult(interp)
1292 Tcl_Interp *interp; /* Interpreter whose result to return. */
1293{
1294 /*
1295 * If the string result is empty, move the object result to the
1296 * string result, then reset the object result.
1297 * FAILS IF OBJECT RESULT'S STRING REPRESENTATION CONTAINS NULLS.
1298 */
1299
1300 if (*(interp->result) == 0) {
1301 Tcl_SetResult(interp,
1302 TclGetStringFromObj(Tcl_GetObjResult(interp), (int *) NULL),
1303 TCL_VOLATILE);
1304 }
1305 return interp->result;
1306}
1307
1308
1309/*
1310 *----------------------------------------------------------------------
1311 *
1312 * Tcl_SetObjResult --
1313 *
1314 * Arrange for objPtr to be an interpreter's result value.
1315 *
1316 * Results:
1317 * None.
1318 *
1319 * Side effects:
1320 * interp->objResultPtr is left pointing to the object referenced
1321 * by objPtr. The object's reference count is incremented since
1322 * there is now a new reference to it. The reference count for any
1323 * old objResultPtr value is decremented. Also, the string result
1324 * is reset.
1325 *
1326 *----------------------------------------------------------------------
1327 */
1328
1329void
1330Tcl_SetObjResult(interp, objPtr)
1331 Tcl_Interp *interp; /* Interpreter with which to associate the
1332 * return object value. */
1333 Tcl_Obj *objPtr; /* Tcl object to be returned. If NULL, the
1334 * obj result is made an empty string
1335 * object. */
1336{
1337 Interp *iPtr = (Interp *) interp;
1338 Tcl_Obj *oldObjResult = iPtr->objResultPtr;
1339
1340 iPtr->objResultPtr = objPtr;
1341 Tcl_IncrRefCount(objPtr); /* since interp result is a reference */
1342
1343 /*
1344 * We wait until the end to release the old object result, in case
1345 * we are setting the result to itself.
1346 */
1347
1348 TclDecrRefCount(oldObjResult);
1349
1350 /*
1351 * Reset the string result since we just set the result object.
1352 */
1353
1354 if (iPtr->freeProc != NULL) {
1355 if ((iPtr->freeProc == TCL_DYNAMIC)
1356 || (iPtr->freeProc == (Tcl_FreeProc *) free)) {
1357 ckfree(iPtr->result);
1358 } else {
1359 (*iPtr->freeProc)(iPtr->result);
1360 }
1361 iPtr->freeProc = 0;
1362 }
1363 iPtr->result = iPtr->resultSpace;
1364 iPtr->resultSpace[0] = 0;
1365}
1366
1367
1368/*
1369 *----------------------------------------------------------------------
1370 *
1371 * Tcl_GetObjResult --
1372 *
1373 * Returns an interpreter's result value as a Tcl object. The object's
1374 * reference count is not modified; the caller must do that if it
1375 * needs to hold on to a long-term reference to it.
1376 *
1377 * Results:
1378 * The interpreter's result as an object.
1379 *
1380 * Side effects:
1381 * If the interpreter has a non-empty string result, the result object
1382 * is either empty or stale because some procedure set interp->result
1383 * directly. If so, the string result is moved to the result object
1384 * then the string result is reset.
1385 *
1386 *----------------------------------------------------------------------
1387 */
1388
1389Tcl_Obj *
1390Tcl_GetObjResult(interp)
1391 Tcl_Interp *interp; /* Interpreter whose result to return. */
1392{
1393 Interp *iPtr = (Interp *) interp;
1394 Tcl_Obj *objResultPtr;
1395 int length;
1396
1397 /*
1398 * If the string result is non-empty, move the string result to the
1399 * object result, then reset the string result.
1400 */
1401
1402 if (*(iPtr->result) != 0) {
1403 TclResetObjResult(iPtr);
1404
1405 objResultPtr = iPtr->objResultPtr;
1406 length = strlen(iPtr->result);
1407 TclInitStringRep(objResultPtr, iPtr->result, length);
1408
1409 if (iPtr->freeProc != NULL) {
1410 if ((iPtr->freeProc == TCL_DYNAMIC)
1411 || (iPtr->freeProc == (Tcl_FreeProc *) free)) {
1412 ckfree(iPtr->result);
1413 } else {
1414 (*iPtr->freeProc)(iPtr->result);
1415 }
1416 iPtr->freeProc = 0;
1417 }
1418 iPtr->result = iPtr->resultSpace;
1419 iPtr->resultSpace[0] = 0;
1420 }
1421 return iPtr->objResultPtr;
1422}
1423
1424
1425/*
1426 *----------------------------------------------------------------------
1427 *
1428 * Tcl_AppendResult --
1429 *
1430 * Append a variable number of strings onto the interpreter's string
1431 * result.
1432 *
1433 * Results:
1434 * None.
1435 *
1436 * Side effects:
1437 * The result of the interpreter given by the first argument is
1438 * extended by the strings given by the second and following arguments
1439 * (up to a terminating NULL argument).
1440 *
1441 * If the string result is empty, the object result is moved to the
1442 * string result, then the object result is reset.
1443 *
1444 *----------------------------------------------------------------------
1445 */
1446
1447void
1448Tcl_AppendResult TCL_VARARGS_DEF(Tcl_Interp *,arg1)
1449{
1450 va_list argList;
1451 Interp *iPtr;
1452 char *string;
1453 int newSpace;
1454
1455 /*
1456 * If the string result is empty, move the object result to the
1457 * string result, then reset the object result.
1458 * FAILS IF OBJECT RESULT'S STRING REPRESENTATION CONTAINS NULLS.
1459 */
1460
1461 iPtr = (Interp *) TCL_VARARGS_START(Tcl_Interp *,arg1,argList);
1462 if (*(iPtr->result) == 0) {
1463 Tcl_SetResult((Tcl_Interp *) iPtr,
1464 TclGetStringFromObj(Tcl_GetObjResult((Tcl_Interp *) iPtr),
1465 (int *) NULL),
1466 TCL_VOLATILE);
1467 }
1468
1469 /*
1470 * Scan through all the arguments to see how much space is needed.
1471 */
1472
1473 newSpace = 0;
1474 while (1) {
1475 string = va_arg(argList, char *);
1476 if (string == NULL) {
1477 break;
1478 }
1479 newSpace += strlen(string);
1480 }
1481 va_end(argList);
1482
1483 /*
1484 * If the append buffer isn't already setup and large enough to hold
1485 * the new data, set it up.
1486 */
1487
1488 if ((iPtr->result != iPtr->appendResult)
1489 || (iPtr->appendResult[iPtr->appendUsed] != 0)
1490 || ((newSpace + iPtr->appendUsed) >= iPtr->appendAvl)) {
1491 SetupAppendBuffer(iPtr, newSpace);
1492 }
1493
1494 /*
1495 * Now go through all the argument strings again, copying them into the
1496 * buffer.
1497 */
1498
1499 TCL_VARARGS_START(Tcl_Interp *,arg1,argList);
1500 while (1) {
1501 string = va_arg(argList, char *);
1502 if (string == NULL) {
1503 break;
1504 }
1505 strcpy(iPtr->appendResult + iPtr->appendUsed, string);
1506 iPtr->appendUsed += strlen(string);
1507 }
1508 va_end(argList);
1509}
1510
1511
1512/*
1513 *----------------------------------------------------------------------
1514 *
1515 * Tcl_AppendElement --
1516 *
1517 * Convert a string to a valid Tcl list element and append it to the
1518 * result (which is ostensibly a list).
1519 *
1520 * Results:
1521 * None.
1522 *
1523 * Side effects:
1524 * The result in the interpreter given by the first argument is
1525 * extended with a list element converted from string. A separator
1526 * space is added before the converted list element unless the current
1527 * result is empty, contains the single character "{", or ends in " {".
1528 *
1529 * If the string result is empty, the object result is moved to the
1530 * string result, then the object result is reset.
1531 *
1532 *----------------------------------------------------------------------
1533 */
1534
1535void
1536Tcl_AppendElement(interp, string)
1537 Tcl_Interp *interp; /* Interpreter whose result is to be
1538 * extended. */
1539 char *string; /* String to convert to list element and
1540 * add to result. */
1541{
1542 Interp *iPtr = (Interp *) interp;
1543 char *dst;
1544 int size;
1545 int flags;
1546
1547 /*
1548 * If the string result is empty, move the object result to the
1549 * string result, then reset the object result.
1550 * FAILS IF OBJECT RESULT'S STRING REPRESENTATION CONTAINS NULLS.
1551 */
1552
1553 if (*(iPtr->result) == 0) {
1554 Tcl_SetResult(interp,
1555 TclGetStringFromObj(Tcl_GetObjResult(interp), (int *) NULL),
1556 TCL_VOLATILE);
1557 }
1558
1559 /*
1560 * See how much space is needed, and grow the append buffer if
1561 * needed to accommodate the list element.
1562 */
1563
1564 size = Tcl_ScanElement(string, &flags) + 1;
1565 if ((iPtr->result != iPtr->appendResult)
1566 || (iPtr->appendResult[iPtr->appendUsed] != 0)
1567 || ((size + iPtr->appendUsed) >= iPtr->appendAvl)) {
1568 SetupAppendBuffer(iPtr, size+iPtr->appendUsed);
1569 }
1570
1571 /*
1572 * Convert the string into a list element and copy it to the
1573 * buffer that's forming, with a space separator if needed.
1574 */
1575
1576 dst = iPtr->appendResult + iPtr->appendUsed;
1577 if (TclNeedSpace(iPtr->appendResult, dst)) {
1578 iPtr->appendUsed++;
1579 *dst = ' ';
1580 dst++;
1581 }
1582 iPtr->appendUsed += Tcl_ConvertElement(string, dst, flags);
1583}
1584
1585
1586/*
1587 *----------------------------------------------------------------------
1588 *
1589 * SetupAppendBuffer --
1590 *
1591 * This procedure makes sure that there is an append buffer properly
1592 * initialized, if necessary, from the interpreter's result, and
1593 * that it has at least enough room to accommodate newSpace new
1594 * bytes of information.
1595 *
1596 * Results:
1597 * None.
1598 *
1599 * Side effects:
1600 * None.
1601 *
1602 *----------------------------------------------------------------------
1603 */
1604
1605static void
1606SetupAppendBuffer(iPtr, newSpace)
1607 Interp *iPtr; /* Interpreter whose result is being set up. */
1608 int newSpace; /* Make sure that at least this many bytes
1609 * of new information may be added. */
1610{
1611 int totalSpace;
1612
1613 /*
1614 * Make the append buffer larger, if that's necessary, then copy the
1615 * result into the append buffer and make the append buffer the official
1616 * Tcl result.
1617 */
1618
1619 if (iPtr->result != iPtr->appendResult) {
1620 /*
1621 * If an oversized buffer was used recently, then free it up
1622 * so we go back to a smaller buffer. This avoids tying up
1623 * memory forever after a large operation.
1624 */
1625
1626 if (iPtr->appendAvl > 500) {
1627 ckfree(iPtr->appendResult);
1628 iPtr->appendResult = NULL;
1629 iPtr->appendAvl = 0;
1630 }
1631 iPtr->appendUsed = strlen(iPtr->result);
1632 } else if (iPtr->result[iPtr->appendUsed] != 0) {
1633 /*
1634 * Most likely someone has modified a result created by
1635 * Tcl_AppendResult et al. so that it has a different size.
1636 * Just recompute the size.
1637 */
1638
1639 iPtr->appendUsed = strlen(iPtr->result);
1640 }
1641
1642 totalSpace = newSpace + iPtr->appendUsed;
1643 if (totalSpace >= iPtr->appendAvl) {
1644 char *new;
1645
1646 if (totalSpace < 100) {
1647 totalSpace = 200;
1648 } else {
1649 totalSpace *= 2;
1650 }
1651 new = (char *) ckalloc((unsigned) totalSpace);
1652 strcpy(new, iPtr->result);
1653 if (iPtr->appendResult != NULL) {
1654 ckfree(iPtr->appendResult);
1655 }
1656 iPtr->appendResult = new;
1657 iPtr->appendAvl = totalSpace;
1658 } else if (iPtr->result != iPtr->appendResult) {
1659 strcpy(iPtr->appendResult, iPtr->result);
1660 }
1661
1662 Tcl_FreeResult((Tcl_Interp *) iPtr);
1663 iPtr->result = iPtr->appendResult;
1664}
1665
1666
1667/*
1668 *----------------------------------------------------------------------
1669 *
1670 * Tcl_FreeResult --
1671 *
1672 * This procedure frees up the memory associated with an interpreter's
1673 * string result. It also resets the interpreter's result object.
1674 * Tcl_FreeResult is most commonly used when a procedure is about to
1675 * replace one result value with another.
1676 *
1677 * Results:
1678 * None.
1679 *
1680 * Side effects:
1681 * Frees the memory associated with interp's string result and sets
1682 * interp->freeProc to zero, but does not change interp->result or
1683 * clear error state. Resets interp's result object to an unshared
1684 * empty object.
1685 *
1686 *----------------------------------------------------------------------
1687 */
1688
1689void
1690Tcl_FreeResult(interp)
1691 Tcl_Interp *interp; /* Interpreter for which to free result. */
1692{
1693 Interp *iPtr = (Interp *) interp;
1694
1695 if (iPtr->freeProc != NULL) {
1696 if ((iPtr->freeProc == TCL_DYNAMIC)
1697 || (iPtr->freeProc == (Tcl_FreeProc *) free)) {
1698 ckfree(iPtr->result);
1699 } else {
1700 (*iPtr->freeProc)(iPtr->result);
1701 }
1702 iPtr->freeProc = 0;
1703 }
1704
1705 TclResetObjResult(iPtr);
1706}
1707
1708
1709/*
1710 *----------------------------------------------------------------------
1711 *
1712 * Tcl_ResetResult --
1713 *
1714 * This procedure resets both the interpreter's string and object
1715 * results.
1716 *
1717 * Results:
1718 * None.
1719 *
1720 * Side effects:
1721 * It resets the result object to an unshared empty object. It
1722 * then restores the interpreter's string result area to its default
1723 * initialized state, freeing up any memory that may have been
1724 * allocated. It also clears any error information for the interpreter.
1725 *
1726 *----------------------------------------------------------------------
1727 */
1728
1729void
1730Tcl_ResetResult(interp)
1731 Tcl_Interp *interp; /* Interpreter for which to clear result. */
1732{
1733 Interp *iPtr = (Interp *) interp;
1734
1735 TclResetObjResult(iPtr);
1736
1737 Tcl_FreeResult(interp);
1738 iPtr->result = iPtr->resultSpace;
1739 iPtr->resultSpace[0] = 0;
1740
1741 iPtr->flags &= ~(ERR_ALREADY_LOGGED | ERR_IN_PROGRESS | ERROR_CODE_SET);
1742}
1743
1744
1745/*
1746 *----------------------------------------------------------------------
1747 *
1748 * Tcl_SetErrorCode --
1749 *
1750 * This procedure is called to record machine-readable information
1751 * about an error that is about to be returned.
1752 *
1753 * Results:
1754 * None.
1755 *
1756 * Side effects:
1757 * The errorCode global variable is modified to hold all of the
1758 * arguments to this procedure, in a list form with each argument
1759 * becoming one element of the list. A flag is set internally
1760 * to remember that errorCode has been set, so the variable doesn't
1761 * get set automatically when the error is returned.
1762 *
1763 *----------------------------------------------------------------------
1764 */
1765 /* VARARGS2 */
1766void
1767Tcl_SetErrorCode TCL_VARARGS_DEF(Tcl_Interp *,arg1)
1768{
1769 va_list argList;
1770 char *string;
1771 int flags;
1772 Interp *iPtr;
1773
1774 /*
1775 * Scan through the arguments one at a time, appending them to
1776 * $errorCode as list elements.
1777 */
1778
1779 iPtr = (Interp *) TCL_VARARGS_START(Tcl_Interp *,arg1,argList);
1780 flags = TCL_GLOBAL_ONLY | TCL_LIST_ELEMENT;
1781 while (1) {
1782 string = va_arg(argList, char *);
1783 if (string == NULL) {
1784 break;
1785 }
1786 (void) Tcl_SetVar2((Tcl_Interp *) iPtr, "errorCode",
1787 (char *) NULL, string, flags);
1788 flags |= TCL_APPEND_VALUE;
1789 }
1790 va_end(argList);
1791 iPtr->flags |= ERROR_CODE_SET;
1792}
1793
1794
1795/*
1796 *----------------------------------------------------------------------
1797 *
1798 * Tcl_SetObjErrorCode --
1799 *
1800 * This procedure is called to record machine-readable information
1801 * about an error that is about to be returned. The caller should
1802 * build a list object up and pass it to this routine.
1803 *
1804 * Results:
1805 * None.
1806 *
1807 * Side effects:
1808 * The errorCode global variable is modified to be the new value.
1809 * A flag is set internally to remember that errorCode has been
1810 * set, so the variable doesn't get set automatically when the
1811 * error is returned.
1812 *
1813 *----------------------------------------------------------------------
1814 */
1815
1816void
1817Tcl_SetObjErrorCode(interp, errorObjPtr)
1818 Tcl_Interp *interp;
1819 Tcl_Obj *errorObjPtr;
1820{
1821 Tcl_Obj *namePtr;
1822 Interp *iPtr;
1823
1824 namePtr = Tcl_NewStringObj("errorCode", -1);
1825 iPtr = (Interp *) interp;
1826 Tcl_ObjSetVar2(interp, namePtr, (Tcl_Obj *) NULL, errorObjPtr,
1827 TCL_GLOBAL_ONLY);
1828 iPtr->flags |= ERROR_CODE_SET;
1829 Tcl_DecrRefCount(namePtr);
1830}
1831
1832/*
1833 *----------------------------------------------------------------------
1834 *
1835 * Tcl_DStringInit --
1836 *
1837 * Initializes a dynamic string, discarding any previous contents
1838 * of the string (Tcl_DStringFree should have been called already
1839 * if the dynamic string was previously in use).
1840 *
1841 * Results:
1842 * None.
1843 *
1844 * Side effects:
1845 * The dynamic string is initialized to be empty.
1846 *
1847 *----------------------------------------------------------------------
1848 */
1849
1850void
1851Tcl_DStringInit(dsPtr)
1852 Tcl_DString *dsPtr; /* Pointer to structure for dynamic string. */
1853{
1854 dsPtr->string = dsPtr->staticSpace;
1855 dsPtr->length = 0;
1856 dsPtr->spaceAvl = TCL_DSTRING_STATIC_SIZE;
1857 dsPtr->staticSpace[0] = 0;
1858}
1859
1860
1861/*
1862 *----------------------------------------------------------------------
1863 *
1864 * Tcl_DStringAppend --
1865 *
1866 * Append more characters to the current value of a dynamic string.
1867 *
1868 * Results:
1869 * The return value is a pointer to the dynamic string's new value.
1870 *
1871 * Side effects:
1872 * Length bytes from string (or all of string if length is less
1873 * than zero) are added to the current value of the string. Memory
1874 * gets reallocated if needed to accomodate the string's new size.
1875 *
1876 *----------------------------------------------------------------------
1877 */
1878
1879char *
1880Tcl_DStringAppend(dsPtr, string, length)
1881 Tcl_DString *dsPtr; /* Structure describing dynamic string. */
1882 CONST char *string; /* String to append. If length is -1 then
1883 * this must be null-terminated. */
1884 int length; /* Number of characters from string to
1885 * append. If < 0, then append all of string,
1886 * up to null at end. */
1887{
1888 int newSize;
1889 char *newString, *dst;
1890 CONST char *end;
1891
1892 if (length < 0) {
1893 length = strlen(string);
1894 }
1895 newSize = length + dsPtr->length;
1896
1897 /*
1898 * Allocate a larger buffer for the string if the current one isn't
1899 * large enough. Allocate extra space in the new buffer so that there
1900 * will be room to grow before we have to allocate again.
1901 */
1902
1903 if (newSize >= dsPtr->spaceAvl) {
1904 dsPtr->spaceAvl = newSize*2;
1905 newString = (char *) ckalloc((unsigned) dsPtr->spaceAvl);
1906 memcpy((VOID *) newString, (VOID *) dsPtr->string,
1907 (size_t) dsPtr->length);
1908 if (dsPtr->string != dsPtr->staticSpace) {
1909 ckfree(dsPtr->string);
1910 }
1911 dsPtr->string = newString;
1912 }
1913
1914 /*
1915 * Copy the new string into the buffer at the end of the old
1916 * one.
1917 */
1918
1919 for (dst = dsPtr->string + dsPtr->length, end = string+length;
1920 string < end; string++, dst++) {
1921 *dst = *string;
1922 }
1923 *dst = '\0';
1924 dsPtr->length += length;
1925 return dsPtr->string;
1926}
1927
1928
1929/*
1930 *----------------------------------------------------------------------
1931 *
1932 * Tcl_DStringAppendElement --
1933 *
1934 * Append a list element to the current value of a dynamic string.
1935 *
1936 * Results:
1937 * The return value is a pointer to the dynamic string's new value.
1938 *
1939 * Side effects:
1940 * String is reformatted as a list element and added to the current
1941 * value of the string. Memory gets reallocated if needed to
1942 * accomodate the string's new size.
1943 *
1944 *----------------------------------------------------------------------
1945 */
1946
1947char *
1948Tcl_DStringAppendElement(dsPtr, string)
1949 Tcl_DString *dsPtr; /* Structure describing dynamic string. */
1950 CONST char *string; /* String to append. Must be
1951 * null-terminated. */
1952{
1953 int newSize, flags;
1954 char *dst, *newString;
1955
1956 newSize = Tcl_ScanElement(string, &flags) + dsPtr->length + 1;
1957
1958 /*
1959 * Allocate a larger buffer for the string if the current one isn't
1960 * large enough. Allocate extra space in the new buffer so that there
1961 * will be room to grow before we have to allocate again.
1962 * SPECIAL NOTE: must use memcpy, not strcpy, to copy the string
1963 * to a larger buffer, since there may be embedded NULLs in the
1964 * string in some cases.
1965 */
1966
1967 if (newSize >= dsPtr->spaceAvl) {
1968 dsPtr->spaceAvl = newSize*2;
1969 newString = (char *) ckalloc((unsigned) dsPtr->spaceAvl);
1970 memcpy((VOID *) newString, (VOID *) dsPtr->string,
1971 (size_t) dsPtr->length);
1972 if (dsPtr->string != dsPtr->staticSpace) {
1973 ckfree(dsPtr->string);
1974 }
1975 dsPtr->string = newString;
1976 }
1977
1978 /*
1979 * Convert the new string to a list element and copy it into the
1980 * buffer at the end, with a space, if needed.
1981 */
1982
1983 dst = dsPtr->string + dsPtr->length;
1984 if (TclNeedSpace(dsPtr->string, dst)) {
1985 *dst = ' ';
1986 dst++;
1987 dsPtr->length++;
1988 }
1989 dsPtr->length += Tcl_ConvertElement(string, dst, flags);
1990 return dsPtr->string;
1991}
1992
1993
1994/*
1995 *----------------------------------------------------------------------
1996 *
1997 * Tcl_DStringSetLength --
1998 *
1999 * Change the length of a dynamic string. This can cause the
2000 * string to either grow or shrink, depending on the value of
2001 * length.
2002 *
2003 * Results:
2004 * None.
2005 *
2006 * Side effects:
2007 * The length of dsPtr is changed to length and a null byte is
2008 * stored at that position in the string. If length is larger
2009 * than the space allocated for dsPtr, then a panic occurs.
2010 *
2011 *----------------------------------------------------------------------
2012 */
2013
2014void
2015Tcl_DStringSetLength(dsPtr, length)
2016 Tcl_DString *dsPtr; /* Structure describing dynamic string. */
2017 int length; /* New length for dynamic string. */
2018{
2019 if (length < 0) {
2020 length = 0;
2021 }
2022 if (length >= dsPtr->spaceAvl) {
2023 char *newString;
2024
2025 dsPtr->spaceAvl = length+1;
2026 newString = (char *) ckalloc((unsigned) dsPtr->spaceAvl);
2027
2028 /*
2029 * SPECIAL NOTE: must use memcpy, not strcpy, to copy the string
2030 * to a larger buffer, since there may be embedded NULLs in the
2031 * string in some cases.
2032 */
2033
2034 memcpy((VOID *) newString, (VOID *) dsPtr->string,
2035 (size_t) dsPtr->length);
2036 if (dsPtr->string != dsPtr->staticSpace) {
2037 ckfree(dsPtr->string);
2038 }
2039 dsPtr->string = newString;
2040 }
2041 dsPtr->length = length;
2042 dsPtr->string[length] = 0;
2043}
2044
2045
2046/*
2047 *----------------------------------------------------------------------
2048 *
2049 * Tcl_DStringFree --
2050 *
2051 * Frees up any memory allocated for the dynamic string and
2052 * reinitializes the string to an empty state.
2053 *
2054 * Results:
2055 * None.
2056 *
2057 * Side effects:
2058 * The previous contents of the dynamic string are lost, and
2059 * the new value is an empty string.
2060 *
2061 *----------------------------------------------------------------------
2062 */
2063
2064void
2065Tcl_DStringFree(dsPtr)
2066 Tcl_DString *dsPtr; /* Structure describing dynamic string. */
2067{
2068 if (dsPtr->string != dsPtr->staticSpace) {
2069 ckfree(dsPtr->string);
2070 }
2071 dsPtr->string = dsPtr->staticSpace;
2072 dsPtr->length = 0;
2073 dsPtr->spaceAvl = TCL_DSTRING_STATIC_SIZE;
2074 dsPtr->staticSpace[0] = 0;
2075}
2076
2077
2078/*
2079 *----------------------------------------------------------------------
2080 *
2081 * Tcl_DStringResult --
2082 *
2083 * This procedure moves the value of a dynamic string into an
2084 * interpreter as its string result. Afterwards, the dynamic string
2085 * is reset to an empty string.
2086 *
2087 * Results:
2088 * None.
2089 *
2090 * Side effects:
2091 * The string is "moved" to interp's result, and any existing
2092 * string result for interp is freed. dsPtr is reinitialized to
2093 * an empty string.
2094 *
2095 *----------------------------------------------------------------------
2096 */
2097
2098void
2099Tcl_DStringResult(interp, dsPtr)
2100 Tcl_Interp *interp; /* Interpreter whose result is to be reset. */
2101 Tcl_DString *dsPtr; /* Dynamic string that is to become the
2102 * result of interp. */
2103{
2104 Tcl_ResetResult(interp);
2105
2106 if (dsPtr->string != dsPtr->staticSpace) {
2107 interp->result = dsPtr->string;
2108 interp->freeProc = TCL_DYNAMIC;
2109 } else if (dsPtr->length < TCL_RESULT_SIZE) {
2110 interp->result = ((Interp *) interp)->resultSpace;
2111 strcpy(interp->result, dsPtr->string);
2112 } else {
2113 Tcl_SetResult(interp, dsPtr->string, TCL_VOLATILE);
2114 }
2115
2116 dsPtr->string = dsPtr->staticSpace;
2117 dsPtr->length = 0;
2118 dsPtr->spaceAvl = TCL_DSTRING_STATIC_SIZE;
2119 dsPtr->staticSpace[0] = 0;
2120}
2121
2122
2123/*
2124 *----------------------------------------------------------------------
2125 *
2126 * Tcl_DStringGetResult --
2127 *
2128 * This procedure moves an interpreter's result into a dynamic string.
2129 *
2130 * Results:
2131 * None.
2132 *
2133 * Side effects:
2134 * The interpreter's string result is cleared, and the previous
2135 * contents of dsPtr are freed.
2136 *
2137 * If the string result is empty, the object result is moved to the
2138 * string result, then the object result is reset.
2139 *
2140 *----------------------------------------------------------------------
2141 */
2142
2143void
2144Tcl_DStringGetResult(interp, dsPtr)
2145 Tcl_Interp *interp; /* Interpreter whose result is to be reset. */
2146 Tcl_DString *dsPtr; /* Dynamic string that is to become the
2147 * result of interp. */
2148{
2149 Interp *iPtr = (Interp *) interp;
2150
2151 if (dsPtr->string != dsPtr->staticSpace) {
2152 ckfree(dsPtr->string);
2153 }
2154
2155 /*
2156 * If the string result is empty, move the object result to the
2157 * string result, then reset the object result.
2158 * FAILS IF OBJECT RESULT'S STRING REPRESENTATION CONTAINS NULLS.
2159 */
2160
2161 if (*(iPtr->result) == 0) {
2162 Tcl_SetResult(interp,
2163 TclGetStringFromObj(Tcl_GetObjResult(interp), (int *) NULL),
2164 TCL_VOLATILE);
2165 }
2166
2167 dsPtr->length = strlen(iPtr->result);
2168 if (iPtr->freeProc != NULL) {
2169 if ((iPtr->freeProc == TCL_DYNAMIC)
2170 || (iPtr->freeProc == (Tcl_FreeProc *) free)) {
2171 dsPtr->string = iPtr->result;
2172 dsPtr->spaceAvl = dsPtr->length+1;
2173 } else {
2174 dsPtr->string = (char *) ckalloc((unsigned) (dsPtr->length+1));
2175 strcpy(dsPtr->string, iPtr->result);
2176 (*iPtr->freeProc)(iPtr->result);
2177 }
2178 dsPtr->spaceAvl = dsPtr->length+1;
2179 iPtr->freeProc = NULL;
2180 } else {
2181 if (dsPtr->length < TCL_DSTRING_STATIC_SIZE) {
2182 dsPtr->string = dsPtr->staticSpace;
2183 dsPtr->spaceAvl = TCL_DSTRING_STATIC_SIZE;
2184 } else {
2185 dsPtr->string = (char *) ckalloc((unsigned) (dsPtr->length + 1));
2186 dsPtr->spaceAvl = dsPtr->length + 1;
2187 }
2188 strcpy(dsPtr->string, iPtr->result);
2189 }
2190
2191 iPtr->result = iPtr->resultSpace;
2192 iPtr->resultSpace[0] = 0;
2193}
2194
2195
2196/*
2197 *----------------------------------------------------------------------
2198 *
2199 * Tcl_DStringStartSublist --
2200 *
2201 * This procedure adds the necessary information to a dynamic
2202 * string (e.g. " {" to start a sublist. Future element
2203 * appends will be in the sublist rather than the main list.
2204 *
2205 * Results:
2206 * None.
2207 *
2208 * Side effects:
2209 * Characters get added to the dynamic string.
2210 *
2211 *----------------------------------------------------------------------
2212 */
2213
2214void
2215Tcl_DStringStartSublist(dsPtr)
2216 Tcl_DString *dsPtr; /* Dynamic string. */
2217{
2218 if (TclNeedSpace(dsPtr->string, dsPtr->string + dsPtr->length)) {
2219 Tcl_DStringAppend(dsPtr, " {", -1);
2220 } else {
2221 Tcl_DStringAppend(dsPtr, "{", -1);
2222 }
2223}
2224
2225
2226/*
2227 *----------------------------------------------------------------------
2228 *
2229 * Tcl_DStringEndSublist --
2230 *
2231 * This procedure adds the necessary characters to a dynamic
2232 * string to end a sublist (e.g. "}"). Future element appends
2233 * will be in the enclosing (sub)list rather than the current
2234 * sublist.
2235 *
2236 * Results:
2237 * None.
2238 *
2239 * Side effects:
2240 * None.
2241 *
2242 *----------------------------------------------------------------------
2243 */
2244
2245void
2246Tcl_DStringEndSublist(dsPtr)
2247 Tcl_DString *dsPtr; /* Dynamic string. */
2248{
2249 Tcl_DStringAppend(dsPtr, "}", -1);
2250}
2251
2252
2253/*
2254 *----------------------------------------------------------------------
2255 *
2256 * Tcl_PrintDouble --
2257 *
2258 * Given a floating-point value, this procedure converts it to
2259 * an ASCII string using.
2260 *
2261 * Results:
2262 * The ASCII equivalent of "value" is written at "dst". It is
2263 * written using the current precision, and it is guaranteed to
2264 * contain a decimal point or exponent, so that it looks like
2265 * a floating-point value and not an integer.
2266 *
2267 * Side effects:
2268 * None.
2269 *
2270 *----------------------------------------------------------------------
2271 */
2272
2273void
2274Tcl_PrintDouble(interp, value, dst)
2275 Tcl_Interp *interp; /* Interpreter whose tcl_precision
2276 * variable used to be used to control
2277 * printing. It's ignored now. */
2278 double value; /* Value to print as string. */
2279 char *dst; /* Where to store converted value;
2280 * must have at least TCL_DOUBLE_SPACE
2281 * characters. */
2282{
2283 char *p;
2284
2285 sprintf(dst, precisionFormat, value);
2286
2287 /*
2288 * If the ASCII result looks like an integer, add ".0" so that it
2289 * doesn't look like an integer anymore. This prevents floating-point
2290 * values from being converted to integers unintentionally.
2291 */
2292
2293 for (p = dst; *p != 0; p++) {
2294 if ((*p == '.') || (isalpha(UCHAR(*p)))) {
2295 return;
2296 }
2297 }
2298 p[0] = '.';
2299 p[1] = '0';
2300 p[2] = 0;
2301}
2302
2303
2304/*
2305 *----------------------------------------------------------------------
2306 *
2307 * TclPrecTraceProc --
2308 *
2309 * This procedure is invoked whenever the variable "tcl_precision"
2310 * is written.
2311 *
2312 * Results:
2313 * Returns NULL if all went well, or an error message if the
2314 * new value for the variable doesn't make sense.
2315 *
2316 * Side effects:
2317 * If the new value doesn't make sense then this procedure
2318 * undoes the effect of the variable modification. Otherwise
2319 * it modifies the format string that's used by Tcl_PrintDouble.
2320 *
2321 *----------------------------------------------------------------------
2322 */
2323
2324 /* ARGSUSED */
2325char *
2326TclPrecTraceProc(clientData, interp, name1, name2, flags)
2327 ClientData clientData; /* Not used. */
2328 Tcl_Interp *interp; /* Interpreter containing variable. */
2329 char *name1; /* Name of variable. */
2330 char *name2; /* Second part of variable name. */
2331 int flags; /* Information about what happened. */
2332{
2333 char *value, *end;
2334 int prec;
2335
2336 /*
2337 * If the variable is unset, then recreate the trace.
2338 */
2339
2340 if (flags & TCL_TRACE_UNSETS) {
2341 if ((flags & TCL_TRACE_DESTROYED) && !(flags & TCL_INTERP_DESTROYED)) {
2342 Tcl_TraceVar2(interp, name1, name2,
2343 TCL_GLOBAL_ONLY|TCL_TRACE_READS|TCL_TRACE_WRITES
2344 |TCL_TRACE_UNSETS, TclPrecTraceProc, clientData);
2345 }
2346 return (char *) NULL;
2347 }
2348
2349 /*
2350 * When the variable is read, reset its value from our shared
2351 * value. This is needed in case the variable was modified in
2352 * some other interpreter so that this interpreter's value is
2353 * out of date.
2354 */
2355
2356 if (flags & TCL_TRACE_READS) {
2357 Tcl_SetVar2(interp, name1, name2, precisionString,
2358 flags & TCL_GLOBAL_ONLY);
2359 return (char *) NULL;
2360 }
2361
2362 /*
2363 * The variable is being written. Check the new value and disallow
2364 * it if it isn't reasonable or if this is a safe interpreter (we
2365 * don't want safe interpreters messing up the precision of other
2366 * interpreters).
2367 */
2368
2369 value = Tcl_GetVar2(interp, name1, name2, flags & TCL_GLOBAL_ONLY);
2370 if (value == NULL) {
2371 value = "";
2372 }
2373 prec = strtoul(value, &end, 10);
2374 if ((prec <= 0) || (prec > TCL_MAX_PREC) || (prec > 100) ||
2375 (end == value) || (*end != 0)) {
2376 Tcl_SetVar2(interp, name1, name2, precisionString,
2377 flags & TCL_GLOBAL_ONLY);
2378 return "improper value for precision";
2379 }
2380 TclFormatInt(precisionString, prec);
2381 sprintf(precisionFormat, "%%.%dg", prec);
2382 return (char *) NULL;
2383}
2384
2385
2386/*
2387 *----------------------------------------------------------------------
2388 *
2389 * TclNeedSpace --
2390 *
2391 * This procedure checks to see whether it is appropriate to
2392 * add a space before appending a new list element to an
2393 * existing string.
2394 *
2395 * Results:
2396 * The return value is 1 if a space is appropriate, 0 otherwise.
2397 *
2398 * Side effects:
2399 * None.
2400 *
2401 *----------------------------------------------------------------------
2402 */
2403
2404int
2405TclNeedSpace(start, end)
2406 char *start; /* First character in string. */
2407 char *end; /* End of string (place where space will
2408 * be added, if appropriate). */
2409{
2410 /*
2411 * A space is needed unless either
2412 * (a) we're at the start of the string, or
2413 * (b) the trailing characters of the string consist of one or more
2414 * open curly braces preceded by a space or extending back to
2415 * the beginning of the string.
2416 * (c) the trailing characters of the string consist of a space
2417 * preceded by a character other than backslash.
2418 */
2419
2420 if (end == start) {
2421 return 0;
2422 }
2423 end--;
2424 if (*end != '{') {
2425 if (isspace(UCHAR(*end)) && ((end == start) || (end[-1] != '\\'))) {
2426 return 0;
2427 }
2428 return 1;
2429 }
2430 do {
2431 if (end == start) {
2432 return 0;
2433 }
2434 end--;
2435 } while (*end == '{');
2436 if (isspace(UCHAR(*end))) {
2437 return 0;
2438 }
2439 return 1;
2440}
2441
2442
2443/*
2444 *----------------------------------------------------------------------
2445 *
2446 * TclFormatInt --
2447 *
2448 * This procedure formats an integer into a sequence of decimal digit
2449 * characters in a buffer. If the integer is negative, a minus sign is
2450 * inserted at the start of the buffer. A null character is inserted at
2451 * the end of the formatted characters. It is the caller's
2452 * responsibility to ensure that enough storage is available. This
2453 * procedure has the effect of sprintf(buffer, "%d", n) but is faster.
2454 *
2455 * Results:
2456 * An integer representing the number of characters formatted, not
2457 * including the terminating \0.
2458 *
2459 * Side effects:
2460 * The formatted characters are written into the storage pointer to
2461 * by the "buffer" argument.
2462 *
2463 *----------------------------------------------------------------------
2464 */
2465
2466int
2467TclFormatInt(buffer, n)
2468 char *buffer; /* Points to the storage into which the
2469 * formatted characters are written. */
2470 long n; /* The integer to format. */
2471{
2472 long intVal;
2473 int i;
2474 int numFormatted, j;
2475 char *digits = "0123456789";
2476
2477 /*
2478 * Check first whether "n" is the maximum negative value. This is
2479 * -2^(m-1) for an m-bit word, and has no positive equivalent;
2480 * negating it produces the same value.
2481 */
2482
2483 if (n == -n) {
2484 sprintf(buffer, "%ld", n);
2485 return strlen(buffer);
2486 }
2487
2488 /*
2489 * Generate the characters of the result backwards in the buffer.
2490 */
2491
2492 intVal = (n < 0? -n : n);
2493 i = 0;
2494 buffer[0] = '\0';
2495 do {
2496 i++;
2497 buffer[i] = digits[intVal % 10];
2498 intVal = intVal/10;
2499 } while (intVal > 0);
2500 if (n < 0) {
2501 i++;
2502 buffer[i] = '-';
2503 }
2504 numFormatted = i;
2505
2506 /*
2507 * Now reverse the characters.
2508 */
2509
2510 for (j = 0; j < i; j++, i--) {
2511 char tmp = buffer[i];
2512 buffer[i] = buffer[j];
2513 buffer[j] = tmp;
2514 }
2515 return numFormatted;
2516}
2517
2518
2519/*
2520 *----------------------------------------------------------------------
2521 *
2522 * TclLooksLikeInt --
2523 *
2524 * This procedure decides whether the leading characters of a
2525 * string look like an integer or something else (such as a
2526 * floating-point number or string).
2527 *
2528 * Results:
2529 * The return value is 1 if the leading characters of p look
2530 * like a valid Tcl integer. If they look like a floating-point
2531 * number (e.g. "e01" or "2.4"), or if they don't look like a
2532 * number at all, then 0 is returned.
2533 *
2534 * Side effects:
2535 * None.
2536 *
2537 *----------------------------------------------------------------------
2538 */
2539
2540int
2541TclLooksLikeInt(p)
2542 char *p; /* Pointer to string. */
2543{
2544 while (isspace(UCHAR(*p))) {
2545 p++;
2546 }
2547 if ((*p == '+') || (*p == '-')) {
2548 p++;
2549 }
2550 if (!isdigit(UCHAR(*p))) {
2551 return 0;
2552 }
2553 p++;
2554 while (isdigit(UCHAR(*p))) {
2555 p++;
2556 }
2557 if ((*p != '.') && (*p != 'e') && (*p != 'E')) {
2558 return 1;
2559 }
2560 return 0;
2561}
2562
2563
2564/*
2565 *----------------------------------------------------------------------
2566 *
2567 * TclGetIntForIndex --
2568 *
2569 * This procedure returns an integer corresponding to the list index
2570 * held in a Tcl object. The Tcl object's value is expected to be
2571 * either an integer or the string "end".
2572 *
2573 * Results:
2574 * The return value is normally TCL_OK, which means that the index was
2575 * successfully stored into the location referenced by "indexPtr". If
2576 * the Tcl object referenced by "objPtr" has the value "end", the
2577 * value stored is "endValue". If "objPtr"s values is not "end" and
2578 * can not be converted to an integer, TCL_ERROR is returned and, if
2579 * "interp" is non-NULL, an error message is left in the interpreter's
2580 * result object.
2581 *
2582 * Side effects:
2583 * The object referenced by "objPtr" might be converted to an
2584 * integer object.
2585 *
2586 *----------------------------------------------------------------------
2587 */
2588
2589int
2590TclGetIntForIndex(interp, objPtr, endValue, indexPtr)
2591 Tcl_Interp *interp; /* Interpreter to use for error reporting.
2592 * If NULL, then no error message is left
2593 * after errors. */
2594 Tcl_Obj *objPtr; /* Points to an object containing either
2595 * "end" or an integer. */
2596 int endValue; /* The value to be stored at "indexPtr" if
2597 * "objPtr" holds "end". */
2598 int *indexPtr; /* Location filled in with an integer
2599 * representing an index. */
2600{
2601 Interp *iPtr = (Interp *) interp;
2602 char *bytes;
2603 int index, length, result;
2604
2605 /*
2606 * THIS FAILS IF THE INDEX OBJECT'S STRING REP CONTAINS NULLS.
2607 */
2608
2609 if (objPtr->typePtr == &tclIntType) {
2610 *indexPtr = (int)objPtr->internalRep.longValue;
2611 return TCL_OK;
2612 }
2613
2614 bytes = TclGetStringFromObj(objPtr, &length);
2615 if ((*bytes == 'e')
2616 && (strncmp(bytes, "end", (unsigned) length) == 0)) {
2617 index = endValue;
2618 } else {
2619 result = Tcl_GetIntFromObj((Tcl_Interp *) NULL, objPtr, &index);
2620 if (result != TCL_OK) {
2621 if (iPtr != NULL) {
2622 Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
2623 "bad index \"", bytes,
2624 "\": must be integer or \"end\"", (char *) NULL);
2625 }
2626 return result;
2627 }
2628 }
2629 *indexPtr = index;
2630 return TCL_OK;
2631}
2632
2633
2634/*
2635 *----------------------------------------------------------------------
2636 *
2637 * Tcl_GetNameOfExecutable --
2638 *
2639 * This procedure simply returns a pointer to the internal full
2640 * path name of the executable file as computed by
2641 * Tcl_FindExecutable. This procedure call is the C API
2642 * equivalent to the "info nameofexecutable" command.
2643 *
2644 * Results:
2645 * A pointer to the internal string or NULL if the internal full
2646 * path name has not been computed or unknown.
2647 *
2648 * Side effects:
2649 * The object referenced by "objPtr" might be converted to an
2650 * integer object.
2651 *
2652 *----------------------------------------------------------------------
2653 */
2654
2655CONST char *
2656Tcl_GetNameOfExecutable()
2657{
2658 return (tclExecutableName);
2659}
Note: See TracBrowser for help on using the repository browser.