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