Tcl Source Code

Check-in [c74bd61cc0]
Login
Bounty program for improvements to Tcl and certain Tcl packages.
Tcl 2019 Conference, Houston/TX, US, Nov 4-8
Send your abstracts to [email protected]
or submit via the online form by Sep 9.

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:
[kennykb-numerics-branch] Merge updates from HEAD.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | kennykb-numerics-branch
Files: files | file ages | folders
SHA1: c74bd61cc03c7e456ad34c1453b9895690f6a53a
User & Date: dgp 2005-08-29 18:38:45
Context
2005-08-30
15:54
[kennykb-numerics-branch]
* generic/tclTomMath.h: Added mp_sqrt to routines from ...
check-in: 7e5e925b15 user: dgp tags: kennykb-numerics-branch
2005-08-29
18:38
[kennykb-numerics-branch] Merge updates from HEAD.
check-in: c74bd61cc0 user: dgp tags: kennykb-numerics-branch
17:11
[kennykb-numerics-branch]
* generic/tclBasic.c: Restored round(.) to the Tcl 8.4 ...
check-in: 2088e4d384 user: dgp tags: kennykb-numerics-branch
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to ChangeLog.

1
2
3
4
5
6

























7




8
9
10
11
12
13
14
2005-08-29  Don Porter  <[email protected]>

	[kennykb-numerics-branch]

	* generic/tclBasic.c:	Restored round(.) to the Tcl 8.4 rules.


























2005-08-25  Donal K. Fellows  <[email protected]>





	* generic/tclExecute.c (TEBC:INST_DICT_LAPPEND): Stop dropping a
	duplicated object on the floor, which was a memory leak (and a wrong
	result too). Thanks to Andreas Kupries for reporting this.

2005-08-25  Don Porter  <[email protected]>


|



>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
2005-08-29  Don Porter  <[email protected]>

	[kennykb-numerics-branch]	Merge updates from HEAD.

	* generic/tclBasic.c:	Restored round(.) to the Tcl 8.4 rules.

2005-08-29  Kevin Kenny  <[email protected]>

	* generic/tclBasic.c (ExprMathFunc): Restored "round away from
	* tests/expr.test (expr-46.*):       zero" behaviour to the
	                                     "round" function.  Added 
	test cases for the behavior, including the awkward case of a
	number whose fractional part is 1/2-1/2ulp. [Bug 1275043]
	
2005-08-26  Andreas Kupries <[email protected]>

	* generic/tclIO.c: Moved Tcl_{Cut,Splice}Channel to
	  {Cut,Splice}Channel for internal use, and created new public
	  functions for Tcl_{Cut,Splice}Channel which walk the whole stack
	  of transformations and invoke the necessary thread actions.
	  Added code to Tcl_(Un)StackChannel to properly invoke the thread
	  actions when pushing and popping transformations on/from a
	  channel.

2005-08-26  Donal K. Fellows  <[email protected]>

	* generic/tclNamesp.c (NamespaceEnsembleCmd): Reset the result after
	creating an ensemble to clear any result object sharing (potentially
	caused by delete traces) so that we can safely return the name of the
	ensemble. Previously, this caused crashes in Snit's test suite.

2005-08-25  Donal K. Fellows  <[email protected]>

	* generic/tclListObj.c (UpdateStringOfList): Stop uncontrolled and
	unsafe crashes from happening when working with very large string
	representations. [Bug 1267380]

	* generic/tclExecute.c (TEBC:INST_DICT_LAPPEND): Stop dropping a
	duplicated object on the floor, which was a memory leak (and a wrong
	result too). Thanks to Andreas Kupries for reporting this.

2005-08-25  Don Porter  <[email protected]>

Changes to generic/tclBasic.c.

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
....
5550
5551
5552
5553
5554
5555
5556
5557
5558
5559
5560
5561
5562
5563
5564
....
5576
5577
5578
5579
5580
5581
5582
5583
5584
5585
5586
5587
5588
5589


5590
5591
5592
5593
5594


5595
5596
5597









5598


5599

5600
5601
5602
5603
5604
5605
5606
5607

5608
5609
5610
5611
5612
5613
5614
 * Copyright (c) 1994-1997 Sun Microsystems, Inc.
 * Copyright (c) 1998-1999 by Scriptics Corporation.
 * Copyright (c) 2001, 2002 by Kevin B. Kenny.  All rights reserved.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclBasic.c,v 1.136.2.30 2005/08/29 17:11:58 dgp Exp $
 */

#include "tclInt.h"
#include "tclCompile.h"
#include <float.h>
#include <math.h>
#include "tommath.h"
................................................................................
    int objc;			/* Actual parameter count */
    Tcl_Obj *CONST *objv;	/* Parameter vector */
{
    Tcl_Obj *valuePtr;
    double d, fractPart, intPart;
    mp_int big;
#if 0
    double a, f;
    Tcl_Obj *resPtr;
#endif

    /* Check the argument count. */

    if (objc != 2) {
	MathFuncWrongNumArgs(interp, 1, objc, objv);
................................................................................
	    (valuePtr->typePtr == &tclWideIntType)) {
	Tcl_SetObjResult(interp, valuePtr);
	return TCL_OK;
    }
    GET_DOUBLE_VALUE(d, valuePtr, valuePtr->typePtr);

    /* 
     * Round the number to the nearest integer.  I'd like to use rint()
     * or nearbyint(), but they are far from universal.
     */

    a = fabs(d);
    if (a < Tcl_WideAsDouble(LLONG_MAX) + 0.5) {
	d = valuePtr->internalRep.doubleValue;


	f = floor(d);
	d -= f;
	if (d > 0.5 || (d == 0.5 && fmod(f, 2.0) != 0.0)) {
	    f = f + 1.0;
	}


	if (f >= (double) LONG_MIN && f <= (double) LONG_MAX) {
	    TclNewLongObj(resPtr, (long) f);
	} else {









	    resPtr = Tcl_NewWideIntObj(Tcl_DoubleAsWide(f));


	}

	Tcl_SetObjResult(interp, resPtr);
	return TCL_OK;
    }

    /*
     * Error return: result cannot be represented as an integer.
     */


    Tcl_SetObjResult(interp, Tcl_NewStringObj(
	    "integer value too large to represent", -1));
    Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW",
	    "integer value too large to represent", (char *) NULL);

    return TCL_ERROR;
#else






|







 







|







 







|
|


<
<
|
>
>
|
<
<
|

>
>
|
|

>
>
>
>
>
>
>
>
>
|
>
>

>
|
|
<





>







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
....
5550
5551
5552
5553
5554
5555
5556
5557
5558
5559
5560
5561
5562
5563
5564
....
5576
5577
5578
5579
5580
5581
5582
5583
5584
5585
5586


5587
5588
5589
5590


5591
5592
5593
5594
5595
5596
5597
5598
5599
5600
5601
5602
5603
5604
5605
5606
5607
5608
5609
5610
5611
5612
5613

5614
5615
5616
5617
5618
5619
5620
5621
5622
5623
5624
5625
5626
 * Copyright (c) 1994-1997 Sun Microsystems, Inc.
 * Copyright (c) 1998-1999 by Scriptics Corporation.
 * Copyright (c) 2001, 2002 by Kevin B. Kenny.  All rights reserved.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclBasic.c,v 1.136.2.31 2005/08/29 18:38:45 dgp Exp $
 */

#include "tclInt.h"
#include "tclCompile.h"
#include <float.h>
#include <math.h>
#include "tommath.h"
................................................................................
    int objc;			/* Actual parameter count */
    Tcl_Obj *CONST *objv;	/* Parameter vector */
{
    Tcl_Obj *valuePtr;
    double d, fractPart, intPart;
    mp_int big;
#if 0
    double i, f;
    Tcl_Obj *resPtr;
#endif

    /* Check the argument count. */

    if (objc != 2) {
	MathFuncWrongNumArgs(interp, 1, objc, objv);
................................................................................
	    (valuePtr->typePtr == &tclWideIntType)) {
	Tcl_SetObjResult(interp, valuePtr);
	return TCL_OK;
    }
    GET_DOUBLE_VALUE(d, valuePtr, valuePtr->typePtr);

    /* 
     * Round the number to the nearest integer.  I'd like to use round(),
     * but it's C99 (or BSD), and not yet universal.
     */



    d = valuePtr->internalRep.doubleValue;
    f = modf(d, &i);
    if (d < 0.0) {
	if (f <= -0.5) {


	    i += -1.0;
	}
	if (i <= Tcl_WideAsDouble(LLONG_MIN)) {
	    goto tooLarge;
	} else if (d <= (double) LONG_MIN) {
	    resPtr = Tcl_NewWideIntObj(Tcl_DoubleAsWide(i));
	} else {
	    resPtr = Tcl_NewLongObj((long) i);
	}			    
    } else {
	if (f >= 0.5) {
	    i += 1.0;
	}
	if (i >= Tcl_WideAsDouble(LLONG_MAX)) {
	    goto tooLarge;
	} else if (i >= (double) LONG_MAX) {
	    resPtr = Tcl_NewWideIntObj(Tcl_DoubleAsWide(i));
	} else {
	    resPtr = Tcl_NewLongObj((long) i);
	}
    }
    Tcl_SetObjResult(interp, resPtr);
    return TCL_OK;


    /*
     * Error return: result cannot be represented as an integer.
     */

  tooLarge:
    Tcl_SetObjResult(interp, Tcl_NewStringObj(
	    "integer value too large to represent", -1));
    Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW",
	    "integer value too large to represent", (char *) NULL);

    return TCL_ERROR;
#else

Changes to generic/tclCmdAH.c.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
..
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
...
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
...
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
...
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
...
651
652
653
654
655
656
657
658
659
660

661
662
663
664
665
666
667
...
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
...
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
...
832
833
834
835
836
837
838
839
840
841
842


843
844
845
846
847
848
849
...
855
856
857
858
859
860
861

862
863





864
865
866

867
868
869
870
871
872
873
874
875
876
877
878
879
880
881

882

883
884
885
886
887
888
889
...
931
932
933
934
935
936
937
938
939
940
941

942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961



















962
963
964
965
966
967
968
....
1096
1097
1098
1099
1100
1101
1102
1103

1104
1105

1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119

1120
1121
1122
1123
1124
1125


1126
1127
1128
1129
1130

1131
1132
1133
1134

1135
1136
1137
1138
1139
1140
1141
1142
1143
1144

1145



1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158

1159
1160
1161
1162
1163
1164
1165
....
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
....
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
....
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
....
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
....
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
....
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
....
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
....
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
....
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
....
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
....
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
....
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
....
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
....
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
....
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
....
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
....
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
....
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
....
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
/*
 * tclCmdAH.c --
 *
 *	This file contains the top-level command routines for most of
 *	the Tcl built-in commands whose names begin with the letters
 *	A to H.
 *
 * Copyright (c) 1987-1993 The Regents of the University of California.
 * Copyright (c) 1994-1997 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclCmdAH.c,v 1.57.2.6 2005/08/22 20:50:25 dgp Exp $
 */

#include "tclInt.h"
#include <locale.h>

/*
 * Prototypes for local procedures defined in this file:
 */

static int		CheckAccess _ANSI_ARGS_((Tcl_Interp *interp,
			    Tcl_Obj *pathPtr, int mode));
static int		GetStatBuf _ANSI_ARGS_((Tcl_Interp *interp,
			    Tcl_Obj *pathPtr, Tcl_FSStatProc *statProc,
			    Tcl_StatBuf *statPtr));
static char *		GetTypeFromMode _ANSI_ARGS_((int mode));
static int		StoreStatData _ANSI_ARGS_((Tcl_Interp *interp,
			    Tcl_Obj *varName, Tcl_StatBuf *statPtr));
 
/*
 *----------------------------------------------------------------------
 *
 * Tcl_BreakObjCmd --
 *
 *	This procedure is invoked to process the "break" Tcl command.  See the
 *	user documentation for details on what it does.
 *
 *	With the bytecode compiler, this procedure is only called when a
 *	command name is computed at runtime, and is "break" or the name to
 *	which "break" was renamed: e.g., "set z break; $z"
 *
 * Results:
................................................................................
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
int
Tcl_BreakObjCmd(dummy, interp, objc, objv)
    ClientData dummy;			/* Not used. */
    Tcl_Interp *interp;			/* Current interpreter. */
    int objc;				/* Number of arguments. */
    Tcl_Obj *CONST objv[];		/* Argument objects. */
{
    if (objc != 1) {
	Tcl_WrongNumArgs(interp, 1, objv, NULL);
	return TCL_ERROR;
    }
    return TCL_BREAK;
}
 
/*
 *----------------------------------------------------------------------
 *
 * Tcl_CaseObjCmd --
 *
 *	This procedure is invoked to process the "case" Tcl command.  See the
 *	user documentation for details on what it does.
 *
 * Results:
 *	A standard Tcl object result.
 *
 * Side effects:
 *	See the user documentation.
................................................................................
}
 
/*
 *----------------------------------------------------------------------
 *
 * Tcl_CdObjCmd --
 *
 *	This procedure is invoked to process the "cd" Tcl command.  See the
 *	user documentation for details on what it does.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	See the user documentation.
................................................................................
}
 
/*
 *----------------------------------------------------------------------
 *
 * Tcl_ContinueObjCmd --
 *
 *	This procedure is invoked to process the "continue" Tcl command.  See
 *	the user documentation for details on what it does.
 *
 *	With the bytecode compiler, this procedure is only called when a
 *	command name is computed at runtime, and is "continue" or the name to
 *	which "continue" was renamed: e.g., "set z continue; $z"
 *
 * Results:
................................................................................
}
 
/*
 *----------------------------------------------------------------------
 *
 * Tcl_ErrorObjCmd --
 *
 *	This procedure is invoked to process the "error" Tcl command.  See the
 *	user documentation for details on what it does.
 *
 * Results:
 *	A standard Tcl object result.
 *
 * Side effects:
 *	See the user documentation.
................................................................................
    }

    if (objc == 2) {
	result = Tcl_EvalObjEx(interp, objv[1], TCL_EVAL_DIRECT);
    } else {
	/*
	 * More than one argument: concatenate them together with spaces
	 * between, then evaluate the result.  Tcl_EvalObjEx will delete the
	 * object when it decrements its refcount after eval'ing it.
	 */

	objPtr = Tcl_ConcatObj(objc-1, objv+1);
	result = Tcl_EvalObjEx(interp, objPtr, TCL_EVAL_DIRECT);
    }
    if (result == TCL_ERROR) {
	char msg[32 + TCL_INTEGER_SPACE];

	sprintf(msg, "\n    (\"eval\" body line %d)", interp->errorLine);
................................................................................
}
 
/*
 *----------------------------------------------------------------------
 *
 * Tcl_ExitObjCmd --
 *
 *	This procedure is invoked to process the "exit" Tcl command.  See the
 *	user documentation for details on what it does.
 *
 * Results:
 *	A standard Tcl object result.
 *
 * Side effects:
 *	See the user documentation.
................................................................................
    objPtr = Tcl_ConcatObj(objc-1, objv+1);
    Tcl_IncrRefCount(objPtr);
    result = Tcl_ExprObj(interp, objPtr, &resultPtr);
    Tcl_DecrRefCount(objPtr);

    if (result == TCL_OK) {
	Tcl_SetObjResult(interp, resultPtr);
	Tcl_DecrRefCount(resultPtr);  /* done with the result object */
    }

    return result;
}
 
/*
 *----------------------------------------------------------------------
................................................................................
    }
    if (Tcl_GetIndexFromObj(interp, objv[1], fileOptions, "option", 0,
	    &index) != TCL_OK) {
	return TCL_ERROR;
    }

    switch ((enum options) index) {
    case FCMD_ATIME: {
	Tcl_StatBuf buf;
	struct utimbuf tval;



	if ((objc < 3) || (objc > 4)) {
	    Tcl_WrongNumArgs(interp, 2, objv, "name ?time?");
	    return TCL_ERROR;
	}
	if (GetStatBuf(interp, objv[2], Tcl_FSStat, &buf) != TCL_OK) {
	    return TCL_ERROR;
	}
................................................................................

	    long newTime;

	    if (Tcl_GetLongFromObj(interp, objv[3], &newTime) != TCL_OK) {
		return TCL_ERROR;
	    }


	    tval.actime = newTime;
	    tval.modtime = buf.st_mtime;





	    if (Tcl_FSUtime(objv[2], &tval) != 0) {
		Tcl_AppendResult(interp,
			"could not set access time for file \"",

			TclGetString(objv[2]), "\": ", Tcl_PosixError(interp),
			(char *) NULL);
		return TCL_ERROR;
	    }

	    /*
	     * Do another stat to ensure that the we return the new recognized
	     * atime - hopefully the same as the one we sent in.  However,
	     * fs's like FAT don't even know what atime is.
	     */

	    if (GetStatBuf(interp, objv[2], Tcl_FSStat, &buf) != TCL_OK) {
		return TCL_ERROR;
	    }
	}

	Tcl_SetObjResult(interp, Tcl_NewLongObj((long) buf.st_atime));

	return TCL_OK;
    }
    case FCMD_ATTRIBUTES:
	return TclFileAttrsCmd(interp, objc, objv);
    case FCMD_CHANNELS:
	if ((objc < 2) || (objc > 3)) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?pattern?");
................................................................................
	    Tcl_SetObjResult(interp, ext);
	    Tcl_DecrRefCount(ext);
	    return TCL_OK;
	} else {
	    return TCL_ERROR;
	}
    }
    case FCMD_ISDIRECTORY: {
	int value;
	Tcl_StatBuf buf;


	if (objc != 3) {
	    goto only3Args;
	}
	value = 0;
	if (GetStatBuf(NULL, objv[2], Tcl_FSStat, &buf) == TCL_OK) {
	    value = S_ISDIR(buf.st_mode);
	}
	Tcl_SetObjResult(interp, Tcl_NewBooleanObj(value));
	return TCL_OK;
    }
    case FCMD_ISFILE: {
	int value;
	Tcl_StatBuf buf;

	if (objc != 3) {
	    goto only3Args;
	}
	value = 0;
	if (GetStatBuf(NULL, objv[2], Tcl_FSStat, &buf) == TCL_OK) {
	    value = S_ISREG(buf.st_mode);



















	}
	Tcl_SetObjResult(interp, Tcl_NewBooleanObj(value));
	return TCL_OK;
    }
    case FCMD_JOIN: {
	Tcl_Obj *resObj;

................................................................................
	     * so we don't own it.
	     */

	    Tcl_DecrRefCount(contents);
	}
	return TCL_OK;
    }
    case FCMD_LSTAT: {

	Tcl_StatBuf buf;


	if (objc != 4) {
	    Tcl_WrongNumArgs(interp, 2, objv, "name varName");
	    return TCL_ERROR;
	}
	if (GetStatBuf(interp, objv[2], Tcl_FSLstat, &buf) != TCL_OK) {
	    return TCL_ERROR;
	}
	return StoreStatData(interp, objv[3], &buf);
    }
    case FCMD_MTIME: {
	Tcl_StatBuf buf;
	struct utimbuf tval;

	if ((objc < 3) || (objc > 4)) {

	    Tcl_WrongNumArgs(interp, 2, objv, "name ?time?");
	    return TCL_ERROR;
	}
	if (GetStatBuf(interp, objv[2], Tcl_FSStat, &buf) != TCL_OK) {
	    return TCL_ERROR;
	}


	if (objc == 4) {
	    /*
	     * Need separate variable for reading longs from an object on
	     * 64-bit platforms. [Bug #698146]
	     */


	    long newTime;

	    if (Tcl_GetLongFromObj(interp, objv[3], &newTime) != TCL_OK) {

		return TCL_ERROR;
	    }

	    tval.actime = buf.st_atime;
	    tval.modtime = newTime;
	    if (Tcl_FSUtime(objv[2], &tval) != 0) {
		Tcl_AppendResult(interp,
			"could not set modification time for file \"",
			TclGetString(objv[2]), "\": ", Tcl_PosixError(interp),
			(char *) NULL);

		return TCL_ERROR;



	    }

	    /*
	     * Do another stat to ensure that the we return the new recognized
	     * atime - hopefully the same as the one we sent in. However, fs's
	     * like FAT don't even know what atime is.
	     */

	    if (GetStatBuf(interp, objv[2], Tcl_FSStat, &buf) != TCL_OK) {
		return TCL_ERROR;
	    }
	}
	Tcl_SetObjResult(interp, Tcl_NewLongObj((long) buf.st_mtime));

	return TCL_OK;
    }
    case FCMD_MKDIR:
	if (objc < 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "name ?name ...?");
	    return TCL_ERROR;
	}
................................................................................
	fileName = Tcl_FSGetNormalizedPath(interp, objv[2]);
	if (fileName == NULL) {
	    return TCL_ERROR;
	}
	Tcl_SetObjResult(interp, fileName);
	return TCL_OK;
    }
    case FCMD_OWNED: {
	int value;
	Tcl_StatBuf buf;

	if (objc != 3) {
	    goto only3Args;
	}
	value = 0;
	if (GetStatBuf(NULL, objv[2], Tcl_FSStat, &buf) == TCL_OK) {
	    /*
	     * For Windows, there are no user ids associated with a file, so
	     * we always return 1.
	     */

#if defined(__WIN32__)
	    value = 1;
#else
	    value = (geteuid() == buf.st_uid);
#endif
	}
	Tcl_SetObjResult(interp, Tcl_NewBooleanObj(value));
	return TCL_OK;
    }
    case FCMD_PATHTYPE:
	if (objc != 3) {
	    goto only3Args;
	}
	switch (Tcl_FSGetPathType(objv[2])) {
	case TCL_PATH_ABSOLUTE:
	    Tcl_SetObjResult(interp, Tcl_NewStringObj("absolute", -1));
................................................................................
	    } else {
		Tcl_SetObjResult(interp,
			Tcl_NewStringObj("Unrecognised path",-1));
		return TCL_ERROR;
	    }
	}
	return TCL_OK;
    case FCMD_SIZE: {
	Tcl_StatBuf buf;

	if (objc != 3) {
	    goto only3Args;
	}
	if (GetStatBuf(interp, objv[2], Tcl_FSStat, &buf) != TCL_OK) {
	    return TCL_ERROR;
	}
	Tcl_SetObjResult(interp,
		Tcl_NewWideIntObj((Tcl_WideInt) buf.st_size));
	return TCL_OK;
    }
    case FCMD_SPLIT: {
	Tcl_Obj *res;

	if (objc != 3) {
	    goto only3Args;
	}
	res = Tcl_FSSplitPath(objv[2], NULL);
................................................................................
	    }
	    return TCL_ERROR;
	} else {
	    Tcl_SetObjResult(interp, res);
	    return TCL_OK;
	}
    }
    case FCMD_STAT: {
	Tcl_StatBuf buf;

	if (objc != 4) {
	    Tcl_WrongNumArgs(interp, 1, objv, "stat name varName");
	    return TCL_ERROR;
	}
	if (GetStatBuf(interp, objv[2], Tcl_FSStat, &buf) != TCL_OK) {
	    return TCL_ERROR;
	}
	return StoreStatData(interp, objv[3], &buf);
    }
    case FCMD_SYSTEM: {
	Tcl_Obj* fsInfo;

	if (objc != 3) {
	    goto only3Args;
	}
	fsInfo = Tcl_FSFileSystemInfo(objv[2]);
................................................................................
	    return TCL_ERROR;
	} else {
	    Tcl_SetObjResult(interp, dirPtr);
	    Tcl_DecrRefCount(dirPtr);
	    return TCL_OK;
	}
    }
    case FCMD_TYPE: {
	Tcl_StatBuf buf;

	if (objc != 3) {
	    goto only3Args;
	}
	if (GetStatBuf(interp, objv[2], Tcl_FSLstat, &buf) != TCL_OK) {
	    return TCL_ERROR;
	}
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		GetTypeFromMode((unsigned short) buf.st_mode), -1));
	return TCL_OK;
    }
    case FCMD_VOLUMES:
	if (objc != 2) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	Tcl_SetObjResult(interp, Tcl_FSListVolumes());
	return TCL_OK;
................................................................................
 *
 * CheckAccess --
 *
 *	Utility procedure used by Tcl_FileObjCmd() to query file attributes
 *	available through the access() system call.
 *
 * Results:
 *	Always returns TCL_OK.  Sets interp's result to boolean true or false
 *	depending on whether the file has the specified attribute.
 *
 * Side effects:
 *	None.
 *
 *---------------------------------------------------------------------------
 */
................................................................................
 * GetStatBuf --
 *
 *	Utility procedure used by Tcl_FileObjCmd() to query file attributes
 *	available through the stat() or lstat() system call.
 *
 * Results:
 *	The return value is TCL_OK if the specified file exists and can be
 *	stat'ed, TCL_ERROR otherwise.  If TCL_ERROR is returned, an error
 *	message is left in interp's result.  If TCL_OK is returned, *statPtr
 *	is filled with information about the specified file.
 *
 * Side effects:
 *	None.
 *
 *---------------------------------------------------------------------------
 */

static int
GetStatBuf(interp, pathPtr, statProc, statPtr)
    Tcl_Interp *interp;		/* Interp for error return.  May be NULL. */
    Tcl_Obj *pathPtr;		/* Path name to examine. */
    Tcl_FSStatProc *statProc;	/* Either stat() or lstat() depending on
				 * desired behavior. */
    Tcl_StatBuf *statPtr;	/* Filled with info about file obtained by
				 * calling (*statProc)(). */
{
    int status;
................................................................................
 * StoreStatData --
 *
 *	This is a utility procedure that breaks out the fields of a "stat"
 *	structure and stores them in textual form into the elements of an
 *	associative array.
 *
 * Results:
 *	Returns a standard Tcl return value.  If an error occurs then a
 *	message is left in interp's result.
 *
 * Side effects:
 *	Elements of the associative array given by "varName" are modified.
 *
 *----------------------------------------------------------------------
 */

static int
StoreStatData(interp, varName, statPtr)
    Tcl_Interp *interp;			/* Interpreter for error reports. */
    Tcl_Obj *varName;			/* Name of associative array variable
					 * in which to store stat results. */
    Tcl_StatBuf *statPtr;		/* Pointer to buffer containing stat
					 * data to store in varName. */
{
    Tcl_Obj *field = Tcl_NewObj();
    Tcl_Obj *value;
    register unsigned short mode;

    /*
     * Assume Tcl_ObjSetVar2() does not keep a copy of the field name!
................................................................................
}
 
/*
 *----------------------------------------------------------------------
 *
 * Tcl_ForObjCmd --
 *
 *	This procedure is invoked to process the "for" Tcl command.  See the
 *	user documentation for details on what it does.
 *
 *	With the bytecode compiler, this procedure is only called when a
 *	command name is computed at runtime, and is "for" or the name to which
 *	"for" was renamed: e.g.,
 *	"set z for; $z {set i 0} {$i<100} {incr i} {puts $i}"
 *
................................................................................
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
int
Tcl_ForObjCmd(dummy, interp, objc, objv)
    ClientData dummy;			/* Not used. */
    Tcl_Interp *interp;			/* Current interpreter. */
    int objc;				/* Number of arguments. */
    Tcl_Obj *CONST objv[];		/* Argument objects. */
{
    int result, value;

    if (objc != 5) {
	Tcl_WrongNumArgs(interp, 1, objv, "start test next command");
	return TCL_ERROR;
    }
................................................................................
	    Tcl_AddErrorInfo(interp, "\n    (\"for\" initial command)");
	}
	return result;
    }
    while (1) {
	/*
	 * We need to reset the result before passing it off to
	 * Tcl_ExprBooleanObj.  Otherwise, any error message will be appended
	 * to the result of the last evaluation.
	 */

	Tcl_ResetResult(interp);
	result = Tcl_ExprBooleanObj(interp, objv[2], &value);
	if (result != TCL_OK) {
	    return result;
................................................................................
 
/*
 *----------------------------------------------------------------------
 *
 * Tcl_ForeachObjCmd --
 *
 *	This object-based procedure is invoked to process the "foreach" Tcl
 *	command.  See the user documentation for details on what it does.
 *
 * Results:
 *	A standard Tcl object result.
 *
 * Side effects:
 *	See the user documentation.
 *
................................................................................
#define STATIC_LIST_SIZE 4
    int indexArray[STATIC_LIST_SIZE];
    int varcListArray[STATIC_LIST_SIZE];
    Tcl_Obj **varvListArray[STATIC_LIST_SIZE];
    int argcListArray[STATIC_LIST_SIZE];
    Tcl_Obj **argvListArray[STATIC_LIST_SIZE];

    int *index = indexArray;		   /* Array of value list indices */
    int *varcList = varcListArray;	   /* # loop variables per list */
    Tcl_Obj ***varvList = varvListArray;   /* Array of var name lists */
    int *argcList = argcListArray;	   /* Array of value list sizes */
    Tcl_Obj ***argvList = argvListArray;   /* Array of value lists */

    if (objc < 4 || (objc%2 != 0)) {
	Tcl_WrongNumArgs(interp, 1, objv,
		"varList list ?varList list ...? command");
	return TCL_ERROR;
    }

................................................................................
}
 
/*
 *----------------------------------------------------------------------
 *
 * Tcl_FormatObjCmd --
 *
 *	This procedure is invoked to process the "format" Tcl command.  See
 *	the user documentation for details on what it does.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	See the user documentation.
................................................................................
				 * it's a double value. */
    Tcl_WideInt wideValue;	/* Used to hold value to pass to sprintf if
				 * it's a 'long long' value. */
    int whichValue;		/* Indicates which of intValue, ptrValue, or
				 * doubleValue has the value to pass to
				 * sprintf, according to the following
				 * definitions: */
#   define INT_VALUE 0
#   define CHAR_VALUE 1
#   define PTR_VALUE 2
#   define DOUBLE_VALUE 3
#   define STRING_VALUE 4
#   define WIDE_VALUE 5
#   define MAX_FLOAT_SIZE 320

    Tcl_Obj *resultPtr;		/* Where result is stored finally. */
    char staticBuf[MAX_FLOAT_SIZE + 1];
				/* A static buffer to copy the format results
				 * into */
    char *dst = staticBuf;	/* The buffer that sprintf writes into each
				 * time the format processes a specifier */
................................................................................
    int gotXpg = 0;		/* Non-zero means that an XPG3 %n$-style
				 * specifier has been seen. */
    int gotSequential = 0;	/* Non-zero means that a regular sequential
				 * (non-XPG3) conversion specifier has been
				 * seen. */
    int useShort;		/* Value to be printed is short (half word). */
    char *end;			/* Used to locate end of numerical fields. */
    int stringLen = 0;		/* Length of string in characters rather
				 * than bytes.  Used for %s substitution. */
    int gotMinus;		/* Non-zero indicates that a minus flag has
				 * been seen in the current field. */
    int gotPrecision;		/* Non-zero indicates that a precision has
				 * been set for the current field. */
    int gotZero;		/* Non-zero indicates that a zero flag has
				 * been seen in the current field. */
    int useWide;		/* Value to be printed is Tcl_WideInt. */

    /*
     * This procedure is a bit nasty.  The goal is to use sprintf to do most
     * of the dirty work.  There are several problems:
     * 1. this procedure can't trust its arguments.
     * 2. we must be able to provide a large enough result area to hold
     *	  whatever's generated.  This is hard to estimate.
     * 3. there's no way to move the arguments from objv to the call to
     *	  sprintf in a reasonable way.  This is particularly nasty because
     *	  some of the arguments may be two-word values (doubles and
     *	  wide-ints).
     * So, what happens here is to scan the format string one % group at a
     * time, making many individual calls to sprintf.
     */

    if (objc < 2) {
................................................................................
	if (*format == '.') {
	    *newPtr = '.';
	    newPtr++;
	    format++;
	    gotPrecision = 1;
	}
	if (isdigit(UCHAR(*format))) {		/* INTL: Tcl source. */
	    precision = strtoul(format, &end, 10);  /* INTL: "C" locale. */
	    format = end;
	} else if (*format == '*') {
	    if (objIndex >= objc) {
		goto badIndex;
	    }
	    if (Tcl_GetIntFromObj(interp,	/* INTL: Tcl source. */
		    objv[objIndex], &precision) != TCL_OK) {
................................................................................
	    }
	}
	if (*format == 'l') {
	    useWide = 1;

	    /*
	     * Only add a 'll' modifier for integer values as it makes some
	     * libc's go into spasm otherwise.  [Bug #702622]
	     */

	    switch (format[1]) {
	    case 'i':
	    case 'd':
	    case 'o':
	    case 'u':
................................................................................
		/*
		 * Add the 'l' for long format type because we are on an LP64
		 * archtecture and we are really going to pass a long argument
		 * to sprintf.
		 *
		 * Do not add this if we're going to pass in a short (i.e. if
		 * we've got an 'h' modifier already in the string); some libc
		 * implementations of sprintf() do not like it at all.  [Bug
		 * 1154163]
		 */

		newPtr++;
		*newPtr = 0;
		newPtr[-1] = newPtr[-2];
		newPtr[-2] = 'l';
................................................................................
#endif /* LONG_MAX > INT_MAX */
	    whichValue = INT_VALUE;
	    size = 40 + precision;
	    break;
	case 's':
	    /*
	     * Compute the length of the string in characters and add any
	     * additional space required by the field width.  All of the extra
	     * characters will be spaces, so one byte per character is
	     * adequate.
	     */

	    whichValue = STRING_VALUE;
	    ptrValue = Tcl_GetStringFromObj(objv[objIndex], &size);
	    stringLen = Tcl_NumUtfChars(ptrValue, size);


|
|
<




|
|

|









|
|
|
<
|
|
|
|






|







 







|
|
|
|













|







 







|







 







|







 







|







 







|


>







 







|







 







|







 







|



>
>







 







>
|
|
>
>
>
>
>

|
<
>
|
|





|
|






>
|
>







 







|



>









<
|
<
<
<






>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







<
>


>








<
|
<
<
<
<
>
|





>
>
|
<
<
<
<
>
|
<
<
<
>
|
|
<
<
<
<
|
<
<
<
>
|
>
>
>
|
<
<
<
<
<
<
<
|
|
|
<
|
>







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







 







<
<
<
<
<
<
<
<
<
<
<
<
<







 







<
<
<
<
<
<
<
<
<
<
<
<







 







<
<
<
<
<
<
<
<
<
<
<
<
<







 







|







 







|
|
|









|







 







|
|









|
|
|
|
|







 







|







 







|
|
|
|







 







|







 







|







 







|
|
|
|
|







 







|







 







|
|
|
|
|
|
|







 







|
|









|
|


|

|







 







|







 







|







 







|







 







|







1
2
3
4
5

6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
..
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
...
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
...
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
...
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
...
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
...
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
...
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
...
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
...
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872

873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
...
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960

961



962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
....
1121
1122
1123
1124
1125
1126
1127

1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139

1140




1141
1142
1143
1144
1145
1146
1147
1148
1149
1150




1151
1152



1153
1154
1155




1156



1157
1158
1159
1160
1161
1162







1163
1164
1165

1166
1167
1168
1169
1170
1171
1172
1173
1174
....
1201
1202
1203
1204
1205
1206
1207























1208
1209
1210
1211
1212
1213
1214
....
1290
1291
1292
1293
1294
1295
1296













1297
1298
1299
1300
1301
1302
1303
....
1309
1310
1311
1312
1313
1314
1315












1316
1317
1318
1319
1320
1321
1322
....
1339
1340
1341
1342
1343
1344
1345













1346
1347
1348
1349
1350
1351
1352
....
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
....
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
....
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
....
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
....
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
....
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
....
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
....
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
....
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
....
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
....
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
....
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
....
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
....
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
....
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
/*
 * tclCmdAH.c --
 *
 *	This file contains the top-level command routines for most of the Tcl
 *	built-in commands whose names begin with the letters A to H.

 *
 * Copyright (c) 1987-1993 The Regents of the University of California.
 * Copyright (c) 1994-1997 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclCmdAH.c,v 1.57.2.7 2005/08/29 18:38:45 dgp Exp $
 */

#include "tclInt.h"
#include <locale.h>

/*
 * Prototypes for local procedures defined in this file:
 */

static int		CheckAccess(Tcl_Interp *interp, Tcl_Obj *pathPtr,
			    int mode);
static int		GetStatBuf(Tcl_Interp *interp, Tcl_Obj *pathPtr,

			    Tcl_FSStatProc *statProc, Tcl_StatBuf *statPtr);
static char *		GetTypeFromMode(int mode);
static int		StoreStatData(Tcl_Interp *interp, Tcl_Obj *varName,
			    Tcl_StatBuf *statPtr);
 
/*
 *----------------------------------------------------------------------
 *
 * Tcl_BreakObjCmd --
 *
 *	This procedure is invoked to process the "break" Tcl command. See the
 *	user documentation for details on what it does.
 *
 *	With the bytecode compiler, this procedure is only called when a
 *	command name is computed at runtime, and is "break" or the name to
 *	which "break" was renamed: e.g., "set z break; $z"
 *
 * Results:
................................................................................
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
int
Tcl_BreakObjCmd(dummy, interp, objc, objv)
    ClientData dummy;		/* Not used. */
    Tcl_Interp *interp;		/* Current interpreter. */
    int objc;			/* Number of arguments. */
    Tcl_Obj *CONST objv[];	/* Argument objects. */
{
    if (objc != 1) {
	Tcl_WrongNumArgs(interp, 1, objv, NULL);
	return TCL_ERROR;
    }
    return TCL_BREAK;
}
 
/*
 *----------------------------------------------------------------------
 *
 * Tcl_CaseObjCmd --
 *
 *	This procedure is invoked to process the "case" Tcl command. See the
 *	user documentation for details on what it does.
 *
 * Results:
 *	A standard Tcl object result.
 *
 * Side effects:
 *	See the user documentation.
................................................................................
}
 
/*
 *----------------------------------------------------------------------
 *
 * Tcl_CdObjCmd --
 *
 *	This procedure is invoked to process the "cd" Tcl command. See the
 *	user documentation for details on what it does.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	See the user documentation.
................................................................................
}
 
/*
 *----------------------------------------------------------------------
 *
 * Tcl_ContinueObjCmd --
 *
 *	This procedure is invoked to process the "continue" Tcl command. See
 *	the user documentation for details on what it does.
 *
 *	With the bytecode compiler, this procedure is only called when a
 *	command name is computed at runtime, and is "continue" or the name to
 *	which "continue" was renamed: e.g., "set z continue; $z"
 *
 * Results:
................................................................................
}
 
/*
 *----------------------------------------------------------------------
 *
 * Tcl_ErrorObjCmd --
 *
 *	This procedure is invoked to process the "error" Tcl command. See the
 *	user documentation for details on what it does.
 *
 * Results:
 *	A standard Tcl object result.
 *
 * Side effects:
 *	See the user documentation.
................................................................................
    }

    if (objc == 2) {
	result = Tcl_EvalObjEx(interp, objv[1], TCL_EVAL_DIRECT);
    } else {
	/*
	 * More than one argument: concatenate them together with spaces
	 * between, then evaluate the result. Tcl_EvalObjEx will delete the
	 * object when it decrements its refcount after eval'ing it.
	 */

	objPtr = Tcl_ConcatObj(objc-1, objv+1);
	result = Tcl_EvalObjEx(interp, objPtr, TCL_EVAL_DIRECT);
    }
    if (result == TCL_ERROR) {
	char msg[32 + TCL_INTEGER_SPACE];

	sprintf(msg, "\n    (\"eval\" body line %d)", interp->errorLine);
................................................................................
}
 
/*
 *----------------------------------------------------------------------
 *
 * Tcl_ExitObjCmd --
 *
 *	This procedure is invoked to process the "exit" Tcl command. See the
 *	user documentation for details on what it does.
 *
 * Results:
 *	A standard Tcl object result.
 *
 * Side effects:
 *	See the user documentation.
................................................................................
    objPtr = Tcl_ConcatObj(objc-1, objv+1);
    Tcl_IncrRefCount(objPtr);
    result = Tcl_ExprObj(interp, objPtr, &resultPtr);
    Tcl_DecrRefCount(objPtr);

    if (result == TCL_OK) {
	Tcl_SetObjResult(interp, resultPtr);
	Tcl_DecrRefCount(resultPtr);	/* done with the result object */
    }

    return result;
}
 
/*
 *----------------------------------------------------------------------
................................................................................
    }
    if (Tcl_GetIndexFromObj(interp, objv[1], fileOptions, "option", 0,
	    &index) != TCL_OK) {
	return TCL_ERROR;
    }

    switch ((enum options) index) {
    {
	Tcl_StatBuf buf;
	struct utimbuf tval;

    case FCMD_ATIME:
    case FCMD_MTIME:
	if ((objc < 3) || (objc > 4)) {
	    Tcl_WrongNumArgs(interp, 2, objv, "name ?time?");
	    return TCL_ERROR;
	}
	if (GetStatBuf(interp, objv[2], Tcl_FSStat, &buf) != TCL_OK) {
	    return TCL_ERROR;
	}
................................................................................

	    long newTime;

	    if (Tcl_GetLongFromObj(interp, objv[3], &newTime) != TCL_OK) {
		return TCL_ERROR;
	    }

	    if (index == FCMD_ATIME) {
		tval.actime = newTime;
		tval.modtime = buf.st_mtime;
	    } else {	/* index == FCMD_MTIME */
		tval.actime = buf.st_atime;
		tval.modtime = newTime;
	    }

	    if (Tcl_FSUtime(objv[2], &tval) != 0) {
		Tcl_AppendResult(interp, "could not set ",

			(index == FCMD_ATIME ? "access" : "modification"),
			" time for file \"", TclGetString(objv[2]), "\": ",
			Tcl_PosixError(interp), (char *) NULL);
		return TCL_ERROR;
	    }

	    /*
	     * Do another stat to ensure that the we return the new recognized
	     * atime - hopefully the same as the one we sent in. However, fs's
	     * like FAT don't even know what atime is.
	     */

	    if (GetStatBuf(interp, objv[2], Tcl_FSStat, &buf) != TCL_OK) {
		return TCL_ERROR;
	    }
	}

	Tcl_SetObjResult(interp, Tcl_NewLongObj((long)
		(index == FCMD_ATIME ? buf.st_atime : buf.st_mtime)));
	return TCL_OK;
    }
    case FCMD_ATTRIBUTES:
	return TclFileAttrsCmd(interp, objc, objv);
    case FCMD_CHANNELS:
	if ((objc < 2) || (objc > 3)) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?pattern?");
................................................................................
	    Tcl_SetObjResult(interp, ext);
	    Tcl_DecrRefCount(ext);
	    return TCL_OK;
	} else {
	    return TCL_ERROR;
	}
    }
    {
	int value;
	Tcl_StatBuf buf;

    case FCMD_ISDIRECTORY:
	if (objc != 3) {
	    goto only3Args;
	}
	value = 0;
	if (GetStatBuf(NULL, objv[2], Tcl_FSStat, &buf) == TCL_OK) {
	    value = S_ISDIR(buf.st_mode);
	}
	Tcl_SetObjResult(interp, Tcl_NewBooleanObj(value));
	return TCL_OK;

    case FCMD_ISFILE:



	if (objc != 3) {
	    goto only3Args;
	}
	value = 0;
	if (GetStatBuf(NULL, objv[2], Tcl_FSStat, &buf) == TCL_OK) {
	    value = S_ISREG(buf.st_mode);
	}
	Tcl_SetObjResult(interp, Tcl_NewBooleanObj(value));
	return TCL_OK;
    case FCMD_OWNED:
	if (objc != 3) {
	    goto only3Args;
	}
	value = 0;
	if (GetStatBuf(NULL, objv[2], Tcl_FSStat, &buf) == TCL_OK) {
	    /*
	     * For Windows, there are no user ids associated with a file, so
	     * we always return 1.
	     */

#if defined(__WIN32__)
	    value = 1;
#else
	    value = (geteuid() == buf.st_uid);
#endif
	}
	Tcl_SetObjResult(interp, Tcl_NewBooleanObj(value));
	return TCL_OK;
    }
    case FCMD_JOIN: {
	Tcl_Obj *resObj;

................................................................................
	     * so we don't own it.
	     */

	    Tcl_DecrRefCount(contents);
	}
	return TCL_OK;
    }

    {
	Tcl_StatBuf buf;

    case FCMD_LSTAT:
	if (objc != 4) {
	    Tcl_WrongNumArgs(interp, 2, objv, "name varName");
	    return TCL_ERROR;
	}
	if (GetStatBuf(interp, objv[2], Tcl_FSLstat, &buf) != TCL_OK) {
	    return TCL_ERROR;
	}
	return StoreStatData(interp, objv[3], &buf);

    case FCMD_STAT:




	if (objc != 4) {
	    Tcl_WrongNumArgs(interp, 2, objv, "name varName");
	    return TCL_ERROR;
	}
	if (GetStatBuf(interp, objv[2], Tcl_FSStat, &buf) != TCL_OK) {
	    return TCL_ERROR;
	}
	return StoreStatData(interp, objv[3], &buf);
    case FCMD_SIZE:
	if (objc != 3) {




	    goto only3Args;
	}



	if (GetStatBuf(interp, objv[2], Tcl_FSStat, &buf) != TCL_OK) {
	    return TCL_ERROR;
	}




	Tcl_SetObjResult(interp,



		Tcl_NewWideIntObj((Tcl_WideInt) buf.st_size));
	return TCL_OK;
    case FCMD_TYPE:
	if (objc != 3) {
	    goto only3Args;
	}







	if (GetStatBuf(interp, objv[2], Tcl_FSLstat, &buf) != TCL_OK) {
	    return TCL_ERROR;
	}

	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		GetTypeFromMode((unsigned short) buf.st_mode), -1));
	return TCL_OK;
    }
    case FCMD_MKDIR:
	if (objc < 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "name ?name ...?");
	    return TCL_ERROR;
	}
................................................................................
	fileName = Tcl_FSGetNormalizedPath(interp, objv[2]);
	if (fileName == NULL) {
	    return TCL_ERROR;
	}
	Tcl_SetObjResult(interp, fileName);
	return TCL_OK;
    }























    case FCMD_PATHTYPE:
	if (objc != 3) {
	    goto only3Args;
	}
	switch (Tcl_FSGetPathType(objv[2])) {
	case TCL_PATH_ABSOLUTE:
	    Tcl_SetObjResult(interp, Tcl_NewStringObj("absolute", -1));
................................................................................
	    } else {
		Tcl_SetObjResult(interp,
			Tcl_NewStringObj("Unrecognised path",-1));
		return TCL_ERROR;
	    }
	}
	return TCL_OK;













    case FCMD_SPLIT: {
	Tcl_Obj *res;

	if (objc != 3) {
	    goto only3Args;
	}
	res = Tcl_FSSplitPath(objv[2], NULL);
................................................................................
	    }
	    return TCL_ERROR;
	} else {
	    Tcl_SetObjResult(interp, res);
	    return TCL_OK;
	}
    }












    case FCMD_SYSTEM: {
	Tcl_Obj* fsInfo;

	if (objc != 3) {
	    goto only3Args;
	}
	fsInfo = Tcl_FSFileSystemInfo(objv[2]);
................................................................................
	    return TCL_ERROR;
	} else {
	    Tcl_SetObjResult(interp, dirPtr);
	    Tcl_DecrRefCount(dirPtr);
	    return TCL_OK;
	}
    }













    case FCMD_VOLUMES:
	if (objc != 2) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	Tcl_SetObjResult(interp, Tcl_FSListVolumes());
	return TCL_OK;
................................................................................
 *
 * CheckAccess --
 *
 *	Utility procedure used by Tcl_FileObjCmd() to query file attributes
 *	available through the access() system call.
 *
 * Results:
 *	Always returns TCL_OK. Sets interp's result to boolean true or false
 *	depending on whether the file has the specified attribute.
 *
 * Side effects:
 *	None.
 *
 *---------------------------------------------------------------------------
 */
................................................................................
 * GetStatBuf --
 *
 *	Utility procedure used by Tcl_FileObjCmd() to query file attributes
 *	available through the stat() or lstat() system call.
 *
 * Results:
 *	The return value is TCL_OK if the specified file exists and can be
 *	stat'ed, TCL_ERROR otherwise. If TCL_ERROR is returned, an error
 *	message is left in interp's result. If TCL_OK is returned, *statPtr is
 *	filled with information about the specified file.
 *
 * Side effects:
 *	None.
 *
 *---------------------------------------------------------------------------
 */

static int
GetStatBuf(interp, pathPtr, statProc, statPtr)
    Tcl_Interp *interp;		/* Interp for error return. May be NULL. */
    Tcl_Obj *pathPtr;		/* Path name to examine. */
    Tcl_FSStatProc *statProc;	/* Either stat() or lstat() depending on
				 * desired behavior. */
    Tcl_StatBuf *statPtr;	/* Filled with info about file obtained by
				 * calling (*statProc)(). */
{
    int status;
................................................................................
 * StoreStatData --
 *
 *	This is a utility procedure that breaks out the fields of a "stat"
 *	structure and stores them in textual form into the elements of an
 *	associative array.
 *
 * Results:
 *	Returns a standard Tcl return value. If an error occurs then a message
 *	is left in interp's result.
 *
 * Side effects:
 *	Elements of the associative array given by "varName" are modified.
 *
 *----------------------------------------------------------------------
 */

static int
StoreStatData(interp, varName, statPtr)
    Tcl_Interp *interp;		/* Interpreter for error reports. */
    Tcl_Obj *varName;		/* Name of associative array variable in which
				 * to store stat results. */
    Tcl_StatBuf *statPtr;	/* Pointer to buffer containing stat data to
				 * store in varName. */
{
    Tcl_Obj *field = Tcl_NewObj();
    Tcl_Obj *value;
    register unsigned short mode;

    /*
     * Assume Tcl_ObjSetVar2() does not keep a copy of the field name!
................................................................................
}
 
/*
 *----------------------------------------------------------------------
 *
 * Tcl_ForObjCmd --
 *
 *	This procedure is invoked to process the "for" Tcl command. See the
 *	user documentation for details on what it does.
 *
 *	With the bytecode compiler, this procedure is only called when a
 *	command name is computed at runtime, and is "for" or the name to which
 *	"for" was renamed: e.g.,
 *	"set z for; $z {set i 0} {$i<100} {incr i} {puts $i}"
 *
................................................................................
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
int
Tcl_ForObjCmd(dummy, interp, objc, objv)
    ClientData dummy;		/* Not used. */
    Tcl_Interp *interp;		/* Current interpreter. */
    int objc;			/* Number of arguments. */
    Tcl_Obj *CONST objv[];	/* Argument objects. */
{
    int result, value;

    if (objc != 5) {
	Tcl_WrongNumArgs(interp, 1, objv, "start test next command");
	return TCL_ERROR;
    }
................................................................................
	    Tcl_AddErrorInfo(interp, "\n    (\"for\" initial command)");
	}
	return result;
    }
    while (1) {
	/*
	 * We need to reset the result before passing it off to
	 * Tcl_ExprBooleanObj. Otherwise, any error message will be appended
	 * to the result of the last evaluation.
	 */

	Tcl_ResetResult(interp);
	result = Tcl_ExprBooleanObj(interp, objv[2], &value);
	if (result != TCL_OK) {
	    return result;
................................................................................
 
/*
 *----------------------------------------------------------------------
 *
 * Tcl_ForeachObjCmd --
 *
 *	This object-based procedure is invoked to process the "foreach" Tcl
 *	command. See the user documentation for details on what it does.
 *
 * Results:
 *	A standard Tcl object result.
 *
 * Side effects:
 *	See the user documentation.
 *
................................................................................
#define STATIC_LIST_SIZE 4
    int indexArray[STATIC_LIST_SIZE];
    int varcListArray[STATIC_LIST_SIZE];
    Tcl_Obj **varvListArray[STATIC_LIST_SIZE];
    int argcListArray[STATIC_LIST_SIZE];
    Tcl_Obj **argvListArray[STATIC_LIST_SIZE];

    int *index = indexArray;		/* Array of value list indices */
    int *varcList = varcListArray;	/* # loop variables per list */
    Tcl_Obj ***varvList = varvListArray;/* Array of var name lists */
    int *argcList = argcListArray;	/* Array of value list sizes */
    Tcl_Obj ***argvList = argvListArray;/* Array of value lists */

    if (objc < 4 || (objc%2 != 0)) {
	Tcl_WrongNumArgs(interp, 1, objv,
		"varList list ?varList list ...? command");
	return TCL_ERROR;
    }

................................................................................
}
 
/*
 *----------------------------------------------------------------------
 *
 * Tcl_FormatObjCmd --
 *
 *	This procedure is invoked to process the "format" Tcl command. See
 *	the user documentation for details on what it does.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	See the user documentation.
................................................................................
				 * it's a double value. */
    Tcl_WideInt wideValue;	/* Used to hold value to pass to sprintf if
				 * it's a 'long long' value. */
    int whichValue;		/* Indicates which of intValue, ptrValue, or
				 * doubleValue has the value to pass to
				 * sprintf, according to the following
				 * definitions: */
#define INT_VALUE	0
#define CHAR_VALUE	1
#define PTR_VALUE	2
#define DOUBLE_VALUE	3
#define STRING_VALUE	4
#define WIDE_VALUE	5
#define MAX_FLOAT_SIZE	320

    Tcl_Obj *resultPtr;		/* Where result is stored finally. */
    char staticBuf[MAX_FLOAT_SIZE + 1];
				/* A static buffer to copy the format results
				 * into */
    char *dst = staticBuf;	/* The buffer that sprintf writes into each
				 * time the format processes a specifier */
................................................................................
    int gotXpg = 0;		/* Non-zero means that an XPG3 %n$-style
				 * specifier has been seen. */
    int gotSequential = 0;	/* Non-zero means that a regular sequential
				 * (non-XPG3) conversion specifier has been
				 * seen. */
    int useShort;		/* Value to be printed is short (half word). */
    char *end;			/* Used to locate end of numerical fields. */
    int stringLen = 0;		/* Length of string in characters rather than
				 * bytes. Used for %s substitution. */
    int gotMinus;		/* Non-zero indicates that a minus flag has
				 * been seen in the current field. */
    int gotPrecision;		/* Non-zero indicates that a precision has
				 * been set for the current field. */
    int gotZero;		/* Non-zero indicates that a zero flag has
				 * been seen in the current field. */
    int useWide;		/* Value to be printed is Tcl_WideInt. */

    /*
     * This procedure is a bit nasty. The goal is to use sprintf to do most of
     * the dirty work. There are several problems:
     * 1. this procedure can't trust its arguments.
     * 2. we must be able to provide a large enough result area to hold
     *	  whatever's generated. This is hard to estimate.
     * 3. there's no way to move the arguments from objv to the call to
     *	  sprintf in a reasonable way. This is particularly nasty because
     *	  some of the arguments may be two-word values (doubles and
     *	  wide-ints).
     * So, what happens here is to scan the format string one % group at a
     * time, making many individual calls to sprintf.
     */

    if (objc < 2) {
................................................................................
	if (*format == '.') {
	    *newPtr = '.';
	    newPtr++;
	    format++;
	    gotPrecision = 1;
	}
	if (isdigit(UCHAR(*format))) {		/* INTL: Tcl source. */
	    precision = strtoul(format, &end, 10);	/* INTL: "C" locale. */
	    format = end;
	} else if (*format == '*') {
	    if (objIndex >= objc) {
		goto badIndex;
	    }
	    if (Tcl_GetIntFromObj(interp,	/* INTL: Tcl source. */
		    objv[objIndex], &precision) != TCL_OK) {
................................................................................
	    }
	}
	if (*format == 'l') {
	    useWide = 1;

	    /*
	     * Only add a 'll' modifier for integer values as it makes some
	     * libc's go into spasm otherwise. [Bug #702622]
	     */

	    switch (format[1]) {
	    case 'i':
	    case 'd':
	    case 'o':
	    case 'u':
................................................................................
		/*
		 * Add the 'l' for long format type because we are on an LP64
		 * archtecture and we are really going to pass a long argument
		 * to sprintf.
		 *
		 * Do not add this if we're going to pass in a short (i.e. if
		 * we've got an 'h' modifier already in the string); some libc
		 * implementations of sprintf() do not like it at all. [Bug
		 * 1154163]
		 */

		newPtr++;
		*newPtr = 0;
		newPtr[-1] = newPtr[-2];
		newPtr[-2] = 'l';
................................................................................
#endif /* LONG_MAX > INT_MAX */
	    whichValue = INT_VALUE;
	    size = 40 + precision;
	    break;
	case 's':
	    /*
	     * Compute the length of the string in characters and add any
	     * additional space required by the field width. All of the extra
	     * characters will be spaces, so one byte per character is
	     * adequate.
	     */

	    whichValue = STRING_VALUE;
	    ptrValue = Tcl_GetStringFromObj(objv[objIndex], &size);
	    stringLen = Tcl_NumUtfChars(ptrValue, size);

Changes to generic/tclCmdIL.c.

12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
..
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
...
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
...
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
...
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
...
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
...
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
...
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
...
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
...
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
....
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
....
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
....
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
....
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
....
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
....
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
....
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
....
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
....
2186
2187
2188
2189
2190
2191
2192
2193

2194
2195
2196
2197
2198
2199
2200
....
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
....
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
....
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
....
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
....
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
....
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
....
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
....
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
....
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
....
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
....
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
....
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
....
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
....
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
....
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
....
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
....
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041

3042
3043
3044
3045
3046
3047
3048
....
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
....
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
....
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
....
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
....
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
....
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
....
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
....
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
....
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
....
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
....
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
....
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
....
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
....
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
....
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
....
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
....
4308
4309
4310
4311
4312
4313
4314
4315
4316
4317
4318
4319
4320
4321
4322
4323
4324
4325
4326
4327
4328
4329
4330
4331
4332
4333
4334
4335
....
4383
4384
4385
4386
4387
4388
4389
4390
4391
4392
4393
4394
4395
4396
4397
4398
4399
4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410
....
4427
4428
4429
4430
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
....
4478
4479
4480
4481
4482
4483
4484
4485
4486
4487
4488
4489
4490
4491
4492
....
4512
4513
4514
4515
4516
4517
4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533
4534
4535
4536
4537
....
4558
4559
4560
4561
4562
4563
4564
4565
4566
4567
4568
4569
4570
4571
4572
....
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
 * Copyright (c) 1998-1999 by Scriptics Corporation.
 * Copyright (c) 2001 by Kevin B. Kenny.  All rights reserved.
 * Copyright (c) 2005 Donal K. Fellows.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclCmdIL.c,v 1.70.2.7 2005/08/19 05:17:47 dgp Exp $
 */

#include "tclInt.h"
#include "tclRegexp.h"

/*
 * During execution of the "lsort" command, structures of the following type
 * are used to arrange the objects being sorted into a collection of linked
 * lists.
 */

typedef struct SortElement {
    Tcl_Obj *objPtr;			/* Object being sorted. */
    int count;				/* number of same elements in list */
    struct SortElement *nextPtr;	/* Next element in the list, or NULL
					 * for end of list. */
} SortElement;

/*
 * These function pointer types are used with the "lsearch" and "lsort"
 * commands to facilitate the "-nocase" option.
 */

typedef int (*SortStrCmpFn_t) _ANSI_ARGS_((const char *, const char *));
typedef int (*SortMemCmpFn_t) _ANSI_ARGS_((const void *, const void *,
			    size_t));

/*
 * The "lsort" command needs to pass certain information down to the function
 * that compares two list elements, and the comparison function needs to pass
 * success or failure information back up to the top-level "lsort" command.
 * The following structure is used to pass this information.
 */

typedef struct SortInfo {
    int isIncreasing;		/* Nonzero means sort in increasing order. */
    int sortMode;		/* The sort mode.  One of SORTMODE_* values
				 * defined below */
    SortStrCmpFn_t strCmpFn;	/* Basic string compare command (used with
				 * ASCII mode). */
    Tcl_Obj *compareCmdPtr;	/* The Tcl comparison command when sortMode is
				 * SORTMODE_COMMAND.  Pre-initialized to hold
				 * base of command.*/
    int *indexv;		/* If the -index option was specified, this
				 * holds the indexes contained in the list
				 * supplied as an argument to that option.
				 * NULL if no indexes supplied, and points to
				 * singleIndex field when only one
				 * supplied. */
    int indexc;			/* Number of indexes in indexv array. */
    int singleIndex;		/* Static space for common index case. */
    Tcl_Interp *interp;		/* The interpreter in which the sort is being
				 * done. */
    int resultCode;		/* Completion code for the lsort command.  If
				 * an error occurs during the sort this is
				 * changed from TCL_OK to TCL_ERROR. */
} SortInfo;

/*
 * The "sortMode" field of the SortInfo structure can take on any of the
 * following values.
................................................................................
#define SORTMODE_ASCII		0
#define SORTMODE_INTEGER	1
#define SORTMODE_REAL		2
#define SORTMODE_COMMAND	3
#define SORTMODE_DICTIONARY	4

/*
 * Magic values for the index field of the SortInfo structure.  Note that the
 * index "end-1" will be translated to SORTIDX_END-1, etc.
 */

#define SORTIDX_NONE	-1		/* Not indexed; use whole value. */
#define SORTIDX_END	-2		/* Indexed from end. */

/*
 * Forward declarations for procedures defined in this file:
 */

static void		AppendLocals _ANSI_ARGS_((Tcl_Interp *interp,
			    Tcl_Obj *listPtr, CONST char *pattern,
			    int includeLinks));
static int		DictionaryCompare _ANSI_ARGS_((char *left,
			    char *right));
static int		InfoArgsCmd _ANSI_ARGS_((ClientData dummy,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
static int		InfoBodyCmd _ANSI_ARGS_((ClientData dummy,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
static int		InfoCmdCountCmd _ANSI_ARGS_((ClientData dummy,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
static int		InfoCommandsCmd _ANSI_ARGS_((ClientData dummy,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
static int		InfoCompleteCmd _ANSI_ARGS_((ClientData dummy,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
static int		InfoDefaultCmd _ANSI_ARGS_((ClientData dummy,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
static int		InfoExistsCmd _ANSI_ARGS_((ClientData dummy,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
static int		InfoFunctionsCmd _ANSI_ARGS_((ClientData dummy,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
static int		InfoGlobalsCmd _ANSI_ARGS_((ClientData dummy,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
static int		InfoHostnameCmd _ANSI_ARGS_((ClientData dummy,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
static int		InfoLevelCmd _ANSI_ARGS_((ClientData dummy,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
static int		InfoLibraryCmd _ANSI_ARGS_((ClientData dummy,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
static int		InfoLoadedCmd _ANSI_ARGS_((ClientData dummy,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
static int		InfoLocalsCmd _ANSI_ARGS_((ClientData dummy,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
static int		InfoNameOfExecutableCmd _ANSI_ARGS_((
			    ClientData dummy, Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
static int		InfoPatchLevelCmd _ANSI_ARGS_((ClientData dummy,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
static int		InfoProcsCmd _ANSI_ARGS_((ClientData dummy,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
static int		InfoScriptCmd _ANSI_ARGS_((ClientData dummy,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
static int		InfoSharedlibCmd _ANSI_ARGS_((ClientData dummy,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
static int		InfoTclVersionCmd _ANSI_ARGS_((ClientData dummy,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
static int		InfoVarsCmd _ANSI_ARGS_((ClientData dummy,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
static SortElement *    MergeSort _ANSI_ARGS_((SortElement *headPt,
			    SortInfo *infoPtr));
static SortElement *    MergeLists _ANSI_ARGS_((SortElement *leftPtr,
			    SortElement *rightPtr, SortInfo *infoPtr));
static int		SortCompare _ANSI_ARGS_((Tcl_Obj *firstPtr,
			    Tcl_Obj *second, SortInfo *infoPtr));
static Tcl_Obj *	SelectObjFromSublist _ANSI_ARGS_((Tcl_Obj *firstPtr,
			    SortInfo *infoPtr));

 
/*
 *----------------------------------------------------------------------
 *
 * Tcl_IfObjCmd --
 *
 *	This procedure is invoked to process the "if" Tcl command.  See the
 *	user documentation for details on what it does.
 *
 *	With the bytecode compiler, this procedure is only called when a
 *	command name is computed at runtime, and is "if" or the name to which
 *	"if" was renamed: e.g., "set z if; $z 1 {puts foo}"
 *
 * Results:
................................................................................
    int i, result, value;
    char *clause;
    i = 1;
    while (1) {
	/*
	 * At this point in the loop, objv and objc refer to an expression to
	 * test, either for the main expression or an expression following an
	 * "elseif".  The arguments after the expression must be "then"
	 * (optional) and a script to execute if the expression is true.
	 */

	if (i >= objc) {
	    clause = TclGetString(objv[i-1]);
	    Tcl_AppendResult(interp, "wrong # args: no expression after \"",
		    clause, "\" argument", (char *) NULL);
................................................................................
	}
	if (value) {
	    thenScriptIndex = i;
	    value = 0;
	}

	/*
	 * The expression evaluated to false.  Skip the command, then see if
	 * there is an "else" or "elseif" clause.
	 */

	i++;
	if (i >= objc) {
	    if (thenScriptIndex) {
		return Tcl_EvalObjEx(interp, objv[thenScriptIndex], 0);
................................................................................
	    i++;
	    continue;
	}
	break;
    }

    /*
     * Couldn't find a "then" or "elseif" clause to execute.  Check now for an
     * "else" clause.  We know that there's at least one more argument when we
     * get here.
     */

    if (strcmp(clause, "else") == 0) {
	i++;
	if (i >= objc) {
	    Tcl_AppendResult(interp,
................................................................................
}
 
/*
 *----------------------------------------------------------------------
 *
 * Tcl_IncrObjCmd --
 *
 *	This procedure is invoked to process the "incr" Tcl command.  See the
 *	user documentation for details on what it does.
 *
 *	With the bytecode compiler, this procedure is only called when a
 *	command name is computed at runtime, and is "incr" or the name to
 *	which "incr" was renamed: e.g., "set z incr; $z i -1"
 *
 * Results:
................................................................................
}
 
/*
 *----------------------------------------------------------------------
 *
 * Tcl_InfoObjCmd --
 *
 *	This procedure is invoked to process the "info" Tcl command.  See the
 *	user documentation for details on what it does.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	See the user documentation.
................................................................................
     * the object do not invalidate the internal rep.
     */

    bodyPtr = procPtr->bodyPtr;
    if (bodyPtr->bytes == NULL) {
	/*
	 * The string rep might not be valid if the procedure has never been
	 * run before.  [Bug #545644]
	 */

	(void) Tcl_GetString(bodyPtr);
    }
    resultPtr = Tcl_NewStringObj(bodyPtr->bytes, bodyPtr->length);

    Tcl_SetObjResult(interp, resultPtr);
................................................................................
 
/*
 *----------------------------------------------------------------------
 *
 * InfoCommandsCmd --
 *
 *	Called to implement the "info commands" command that returns the list
 *	of commands in the interpreter that match an optional pattern.  The
 *	pattern, if any, consists of an optional sequence of namespace names
 *	separated by "::" qualifiers, which is followed by a glob-style
 *	pattern that restricts which commands are returned.  Handles the
 *	following syntax:
 *
 *	    info commands ?pattern?
 *
 * Results:
 *	Returns TCL_OK if successful and TCL_ERROR if there is an error.
 *
................................................................................
{
    char *cmdName, *pattern;
    CONST char *simplePattern;
    register Tcl_HashEntry *entryPtr;
    Tcl_HashSearch search;
    Namespace *nsPtr;
    Namespace *globalNsPtr = (Namespace *) Tcl_GetGlobalNamespace(interp);
    Namespace *currNsPtr   = (Namespace *) Tcl_GetCurrentNamespace(interp);
    Tcl_Obj *listPtr, *elemObjPtr;
    int specificNsInPattern = 0;  /* Init. to avoid compiler warning. */
    Tcl_Command cmd;
    int i;

    /*
     * Get the pattern and find the "effective namespace" in which to list
     * commands.
     */
................................................................................
 
/*
 *----------------------------------------------------------------------
 *
 * InfoProcsCmd --
 *
 *	Called to implement the "info procs" command that returns the list of
 *	procedures in the interpreter that match an optional pattern.  The
 *	pattern, if any, consists of an optional sequence of namespace names
 *	separated by "::" qualifiers, which is followed by a glob-style
 *	pattern that restricts which commands are returned.  Handles the
 *	following syntax:
 *
 *	    info procs ?pattern?
 *
 * Results:
 *	Returns TCL_OK if successful and TCL_ERROR if there is an error.
 *
................................................................................
{
    char *cmdName, *pattern;
    CONST char *simplePattern;
    Namespace *nsPtr;
#ifdef INFO_PROCS_SEARCH_GLOBAL_NS
    Namespace *globalNsPtr = (Namespace *) Tcl_GetGlobalNamespace(interp);
#endif
    Namespace *currNsPtr   = (Namespace *) Tcl_GetCurrentNamespace(interp);
    Tcl_Obj *listPtr, *elemObjPtr;
    int specificNsInPattern = 0;  /* Init. to avoid compiler warning. */
    register Tcl_HashEntry *entryPtr;
    Tcl_HashSearch search;
    Command *cmdPtr, *realCmdPtr;

    /*
     * Get the pattern and find the "effective namespace" in which to list
     * procs.
................................................................................
		if (!TclIsProc(cmdPtr)) {
		    realCmdPtr = (Command *)
			    TclGetOriginalCommand((Tcl_Command) cmdPtr);
		    if (realCmdPtr != NULL && TclIsProc(realCmdPtr)) {
			goto procOK;
		    }
		} else {
		  procOK:
		    if (specificNsInPattern) {
			elemObjPtr = Tcl_NewObj();
			Tcl_GetCommandFullName(interp, (Tcl_Command) cmdPtr,
				elemObjPtr);
		    } else {
			elemObjPtr = Tcl_NewStringObj(cmdName, -1);
		    }
................................................................................
	 * namespace.
	 */

#ifdef INFO_PROCS_SEARCH_GLOBAL_NS
	/*
	 * If "info procs" worked like "info commands", returning the commands
	 * also seen in the global namespace, then you would include this
	 * code.  As this could break backwards compatibilty with 8.0-8.2, we
	 * decided not to "fix" it in 8.3, leaving the behavior slightly
	 * different.
	 */

	if ((nsPtr != globalNsPtr) && !specificNsInPattern) {
	    entryPtr = Tcl_FirstHashEntry(&globalNsPtr->cmdTable, &search);
	    while (entryPtr != NULL) {
................................................................................
 *	If newName is specified, it will set that as the internal name.
 *
 * Results:
 *	Returns TCL_OK if successful and TCL_ERROR if there is an error.
 *
 * Side effects:
 *	Returns a result in the interpreter's result object. If there is an
 *	error, the result is an error message.  It may change the internal
 *	script filename.
 *
 *----------------------------------------------------------------------
 */

static int
InfoScriptCmd(dummy, interp, objc, objv)
................................................................................

    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 2, objv, NULL);
	return TCL_ERROR;
    }

    version = Tcl_GetVar2Ex(interp, "tcl_version", NULL,
	(TCL_GLOBAL_ONLY | TCL_LEAVE_ERR_MSG));
    if (version != NULL) {
	Tcl_SetObjResult(interp, version);
	return TCL_OK;
    }
    return TCL_ERROR;
}
 
/*
 *----------------------------------------------------------------------
 *
 * InfoVarsCmd --
 *
 *	Called to implement the "info vars" command that returns the list of
 *	variables in the interpreter that match an optional pattern.  The
 *	pattern, if any, consists of an optional sequence of namespace names
 *	separated by "::" qualifiers, which is followed by a glob-style
 *	pattern that restricts which variables are returned.  Handles the
 *	following syntax:
 *
 *	    info vars ?pattern?
 *
 * Results:
 *	Returns TCL_OK if successful and TCL_ERROR if there is an error.
 *
................................................................................
    char *varName, *pattern;
    CONST char *simplePattern;
    register Tcl_HashEntry *entryPtr;
    Tcl_HashSearch search;
    Var *varPtr;
    Namespace *nsPtr;
    Namespace *globalNsPtr = (Namespace *) Tcl_GetGlobalNamespace(interp);
    Namespace *currNsPtr   = (Namespace *) Tcl_GetCurrentNamespace(interp);
    Tcl_Obj *listPtr, *elemObjPtr;
    int specificNsInPattern = 0;  /* Init. to avoid compiler warning. */

    /*
     * Get the pattern and find the "effective namespace" in which to list
     * variables. We only use this effective namespace if there's no active
     * Tcl procedure frame.
     */

................................................................................
	Namespace *dummy1NsPtr, *dummy2NsPtr;

	pattern = TclGetString(objv[2]);
	TclGetNamespaceForQualName(interp, pattern, (Namespace *) NULL,
		/*flags*/ 0, &nsPtr, &dummy1NsPtr, &dummy2NsPtr,
		&simplePattern);

	if (nsPtr != NULL) {	/* we successfully found the pattern's ns */
	    specificNsInPattern = (strcmp(simplePattern, pattern) != 0);
	}
    } else {
	Tcl_WrongNumArgs(interp, 2, objv, "?pattern?");
	return TCL_ERROR;
    }

................................................................................
		if (!TclIsVarUndefined(varPtr)
			|| TclIsVarNamespaceVar(varPtr)) {
		    varName = Tcl_GetHashKey(&nsPtr->varTable, entryPtr);
		    if ((simplePattern == NULL)
			    || Tcl_StringMatch(varName, simplePattern)) {
			if (specificNsInPattern) {
			    elemObjPtr = Tcl_NewObj();
			    Tcl_GetVariableFullName(interp, (Tcl_Var) varPtr,				    elemObjPtr);

			} else {
			    elemObjPtr = Tcl_NewStringObj(varName, -1);
			}
			Tcl_ListObjAppendElement(interp, listPtr, elemObjPtr);
		    }
		}
		entryPtr = Tcl_NextHashEntry(&search);
................................................................................
}
 
/*
 *----------------------------------------------------------------------
 *
 * Tcl_JoinObjCmd --
 *
 *	This procedure is invoked to process the "join" Tcl command.  See the
 *	user documentation for details on what it does.
 *
 * Results:
 *	A standard Tcl object result.
 *
 * Side effects:
 *	See the user documentation.
................................................................................
	Tcl_DecrRefCount(emptyObj);
    }

    /*
     * Now place a list of any values left over into the interpreter result.
     *
     * First, figure out how many values were not assigned by getting the
     * length of the list.  Note that I do not expect this operation to fail.
     */

    if (Tcl_ListObjGetElements(interp, objv[1],
	    &listObjc, &listObjv) != TCL_OK) {
	return TCL_ERROR;
    }

    if (listObjc > objc-2) {
	/*
	 * OK, there were left-overs.  Make a list of them and slap that back
	 * in the interpreter result.
	 */

	Tcl_SetObjResult(interp,
		Tcl_NewListObj(listObjc - objc + 2, listObjv + objc - 2));
    }

................................................................................
    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "list ?index...?");
	return TCL_ERROR;
    }

    /*
     * If objc==3, then objv[2] may be either a single index or a list of
     * indices: go to TclLindexList to determine which.  If objc>=4, or
     * objc==2, then objv[2 .. objc-2] are all single indices and processed as
     * such in TclLindexFlat.
     */

    if (objc == 3) {
	elemPtr = TclLindexList(interp, objv[1], objv[2]);
    } else {
................................................................................
 *	occurred.
 *
 * Side effects:
 *	None.
 *
 * Notes:
 *	If objv[1] can be parsed as a list, TclLindexList handles extraction
 *	of the desired element locally.  Otherwise, it invokes TclLindexFlat
 *	to treat objv[1] as a scalar.
 *
 *	The reference count of the returned object includes one reference
 *	corresponding to the pointer returned.  Thus, the calling code will
 *	usually do something like:
 *		Tcl_SetObjResult(interp, result);
 *		Tcl_DecrRefCount(result);
 *
 *----------------------------------------------------------------------
 */

................................................................................

	return TclLindexFlat(interp, listPtr, 1, &argPtr);
    }

    if (Tcl_ListObjGetElements(NULL, argPtr, &indexCount, &indices) != TCL_OK){
	/*
	 * argPtr designates something that is neither an index nor a
	 * well-formed list.  Report the error via TclLindexFlat.
	 */

	return TclLindexFlat(interp, listPtr, 1, &argPtr);
    }

    /*
     * Record the reference to the list that we are maintaining in the
................................................................................
	    Tcl_DecrRefCount(listPtr);
	    listPtr = Tcl_NewObj();
	    Tcl_IncrRefCount(listPtr);
	    return listPtr;
	}

	/*
	 * Make sure listPtr still refers to a list object.  If it shared a
	 * Tcl_Obj structure with the arguments, then it might have just been
	 * converted to something else.
	 */

	if (listPtr->typePtr != &tclListType) {
	    result = Tcl_ListObjGetElements(interp, listPtr, &listLen,
		    &elemPtrs);
................................................................................
	oldListPtr = listPtr;
	listPtr = elemPtrs[index];
	Tcl_IncrRefCount(listPtr);
	Tcl_DecrRefCount(oldListPtr);

	/*
	 * The work we did above may have caused the internal rep of *argPtr
	 * to change to something else.  Get it back.
	 */

	result = Tcl_ListObjGetElements(interp, argPtr, &indexCount, &indices);
	if (result != TCL_OK) {
	    /*
	     * This can't happen unless some extension corrupted a Tcl_Obj.
	     */
................................................................................

	    Tcl_DecrRefCount(listPtr);
	    return NULL;
	}
    }

    /*
     * Return the last object extracted.  Its reference count will include the
     * reference being returned.
     */

    return listPtr;
}
 
/*
................................................................................
 *	Returns a standard Tcl result.
 *
 * Side effects:
 *	None.
 *
 * Notes:
 *	This procedure is called from either tclExecute.c or Tcl_LindexObjCmd
 *	whenever either is presented with objc==2 or objc>=4.  It is also
 *	called from TclLindexList for the objc==3 case once it is determined
 *	that objv[2] cannot be parsed as a list.
 *
 *----------------------------------------------------------------------
 */

Tcl_Obj *
................................................................................
    int i;			/* Current list index. */
    int result;			/* Result of Tcl library calls. */
    int listLen;		/* Length of the current list being
				 * processed. */
    Tcl_Obj** elemPtrs;		/* Array of pointers to the elements of the
				 * current list. */
    int index;			/* Parsed version of the current element of
				 * indexArray.  */
    Tcl_Obj* oldListPtr;	/* Temporary to hold listPtr so that its ref
				 * count can be decremented. */

    /*
     * Record the reference to the 'listPtr' object that we are maintaining in
     * the C activation record.
     */
................................................................................
	    Tcl_DecrRefCount(listPtr);
	    listPtr = Tcl_NewObj();
	    Tcl_IncrRefCount(listPtr);
	    return listPtr;
	}

	/*
	 * Make sure listPtr still refers to a list object.  It might have
	 * been converted to something else above if objv[1] overlaps with one
	 * of the other parameters.
	 */

	if (listPtr->typePtr != &tclListType) {
	    result = Tcl_ListObjGetElements(interp, listPtr, &listLen,
		    &elemPtrs);
	    if (result != TCL_OK) {
		Tcl_DecrRefCount(listPtr);
................................................................................

    result = Tcl_ListObjLength(interp, objv[1], &len);
    if (result != TCL_OK) {
	return result;
    }

    /*
     * Get the index.  "end" is interpreted to be the index after the last
     * element, such that using it will cause any inserted elements to be
     * appended to the list.
     */

    result = TclGetIntForIndex(interp, objv[2], /*end*/ len, &index);
    if (result != TCL_OK) {
	return result;
................................................................................
}
 
/*
 *----------------------------------------------------------------------
 *
 * Tcl_ListObjCmd --
 *
 *	This procedure is invoked to process the "list" Tcl command.  See the
 *	user documentation for details on what it does.
 *
 * Results:
 *	A standard Tcl object result.
 *
 * Side effects:
 *	See the user documentation.
................................................................................
 
/*
 *----------------------------------------------------------------------
 *
 * Tcl_LlengthObjCmd --
 *
 *	This object-based procedure is invoked to process the "llength" Tcl
 *	command.  See the user documentation for details on what it does.
 *
 * Results:
 *	A standard Tcl object result.
 *
 * Side effects:
 *	See the user documentation.
 *
................................................................................
}
 
/*
 *----------------------------------------------------------------------
 *
 * Tcl_LrangeObjCmd --
 *
 *	This procedure is invoked to process the "lrange" Tcl command.  See
 *	the user documentation for details on what it does.
 *
 * Results:
 *	A standard Tcl object result.
 *
 * Side effects:
 *	See the user documentation.
 *
................................................................................
}
 
/*
 *----------------------------------------------------------------------
 *
 * Tcl_LrepeatObjCmd --
 *
 *	This procedure is invoked to process the "lrepeat" Tcl command.  See
 *	the user documentation for details on what it does.
 *
 * Results:
 *	A standard Tcl object result.
 *
 * Side effects:
 *	See the user documentation.
................................................................................
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
int
Tcl_LrepeatObjCmd(dummy, interp, objc, objv)
    ClientData dummy;			/* Not used. */
    Tcl_Interp *interp;			/* Current interpreter. */
    register int objc;			/* Number of arguments. */
    register Tcl_Obj *CONST objv[];	/* The argument objects. */

{
    int elementCount, i, result;
    Tcl_Obj *listPtr, **dataArray;
    List *listRepPtr;

    /*
     * Check arguments for legality:
................................................................................

    listPtr = Tcl_NewListObj(elementCount*objc, NULL);
    listRepPtr = (List *) listPtr->internalRep.twoPtrValue.ptr1;
    listRepPtr->elemCount = elementCount*objc;
    dataArray = &listRepPtr->elements;

    /*
     * Set the elements.  Note that we handle the common degenerate case of a
     * single value being repeated separately to permit the compiler as much
     * room as possible to optimize a loop that might be run a very large
     * number of times.
     */

    if (objc == 1) {
	register Tcl_Obj *tmpPtr = objv[0];
................................................................................

    result = Tcl_ListObjLength(interp, objv[1], &listLen);
    if (result != TCL_OK) {
	return result;
    }

    /*
     * Get the first and last indexes.  "end" is interpreted to be the index
     * for the last element, such that using it will cause that element to be
     * included for deletion.
     */

    result = TclGetIntForIndex(interp, objv[2], /*end*/ (listLen - 1), &first);
    if (result != TCL_OK) {
	return result;
................................................................................
    }

    result = TclGetIntForIndex(interp, objv[3], /*end*/ (listLen - 1), &last);
    if (result != TCL_OK) {
	return result;
    }

    if (first < 0)  {
    	first = 0;
    }

    /*
     * Complain if the user asked for a start element that is greater than the
     * list length.  This won't ever trigger for the "end*" case as that will
     * be properly constrained by TclGetIntForIndex because we use listLen-1
     * (to allow for replacing the last elem).
     */

    if ((first >= listLen) && (listLen > 0)) {
	Tcl_AppendResult(interp, "list doesn't contain element ",
		TclGetString(objv[2]), (int *) NULL);
................................................................................
}
 
/*
 *----------------------------------------------------------------------
 *
 * Tcl_LsearchObjCmd --
 *
 *	This procedure is invoked to process the "lsearch" Tcl command.  See
 *	the user documentation for details on what it does.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	See the user documentation.
................................................................................
		}
		Tcl_AppendResult(interp, "missing starting index", NULL);
		return TCL_ERROR;
	    }
	    i++;
	    if (objv[i] == objv[objc - 2]) {
		/*
		 * Take copy to prevent shimmering problems.  Note that it
		 * does not matter if the index obj is also a component of the
		 * list being searched.  We only need to copy where the list
		 * and the index are one-and-the-same.
		 */

		startPtr = Tcl_DuplicateObj(objv[i]);
	    } else {
		startPtr = objv[i];
		Tcl_IncrRefCount(startPtr);
................................................................................
			"\"-index\" option must be followed by list index",
			NULL);
		return TCL_ERROR;
	    }

	    /*
	     * Store the extracted indices for processing by sublist
	     * extraction.  Note that we don't do this using objects because
	     * that has shimmering problems.
	     */

	    i++;
	    if (Tcl_ListObjGetElements(interp, objv[i],
		    &sortInfo.indexc, &indices) != TCL_OK) {
		if (startPtr != NULL) {
................................................................................
		break;
	    default:
		sortInfo.indexv = (int *)
			ckalloc(sizeof(int) * sortInfo.indexc);
	    }

	    /*
	     * Fill the array by parsing each index.  We don't know whether
	     * their scale is sensible yet, but we at least perform the
	     * syntactic check here.
	     */

	    for (j=0 ; j<sortInfo.indexc ; j++) {
		if (TclGetIntForIndex(interp, indices[j], SORTIDX_END,
			&sortInfo.indexv[j]) != TCL_OK) {
................................................................................
     */

    index = -1;
    match = 0;

    if ((enum modes) mode == SORTED && !allMatches && !negatedMatch) {
	/*
	 * If the data is sorted, we can do a more intelligent search.  Note
	 * that there is no point in being smart when -all was specified; in
	 * that case, we have to look at all items anyway, and there is no
	 * sense in doing this when the match sense is inverted.
	 */

	lower = offset - 1;
	upper = listc;
................................................................................
		    match = 1;
		}
		break;
	    }
	    if (match == 0) {
		/*
		 * Normally, binary search is written to stop when it finds a
		 * match.  If there are duplicates of an element in the list,
		 * our first match might not be the first occurance.
		 * Consider:  0 0 0 1 1 1 2 2 2
		 *
		 * To maintain consistancy with standard lsearch semantics, we
		 * must find the leftmost occurance of the pattern in the
		 * list. Thus we don't just stop searching here.  This
		 * variation means that a search always makes log n
		 * comparisons (normal binary search might "get lucky" with an
		 * early comparison).
		 */

		index = i;
		upper = i;
................................................................................
	    }
	    Tcl_SetObjResult(interp, itemPtr);
	} else {
	    Tcl_SetObjResult(interp, Tcl_NewIntObj(index));
	}
    } else if (index < 0) {
	/*
	 * Is this superfluous?  The result should be a blank object by
	 * default...
	 */

	Tcl_SetObjResult(interp, Tcl_NewObj());
    } else {
	Tcl_SetObjResult(interp, listv[index]);
    }
................................................................................
}
 
/*
 *----------------------------------------------------------------------
 *
 * Tcl_LsetObjCmd --
 *
 *	This procedure is invoked to process the "lset" Tcl command.  See the
 *	user documentation for details on what it does.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	See the user documentation.
................................................................................
    listPtr = Tcl_ObjGetVar2(interp, objv[1], (Tcl_Obj *) NULL,
	    TCL_LEAVE_ERR_MSG);
    if (listPtr == NULL) {
	return TCL_ERROR;
    }

    /*
     * Substitute the value in the value.  Return either the value or else an
     * unshared copy of it.
     */

    if (objc == 4) {
	finalValuePtr = TclLsetList(interp, listPtr, objv[2], objv[3]);
    } else {
	finalValuePtr = TclLsetFlat(interp, listPtr, objc-3, objv+2,
................................................................................
}
 
/*
 *----------------------------------------------------------------------
 *
 * Tcl_LsortObjCmd --
 *
 *	This procedure is invoked to process the "lsort" Tcl command.  See the
 *	user documentation for details on what it does.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	See the user documentation.
................................................................................
		break;
	    default:
		sortInfo.indexv = (int *)
			ckalloc(sizeof(int) * sortInfo.indexc);
	    }

	    /*
	     * Fill the array by parsing each index.  We don't know whether
	     * their scale is sensible yet, but we at least perform the
	     * syntactic check here.
	     */

	    for (j=0 ; j<sortInfo.indexc ; j++) {
		if (TclGetIntForIndex(interp, indices[j], SORTIDX_END,
			&sortInfo.indexv[j]) != TCL_OK) {
................................................................................
 *	None, unless a user-defined comparison command does something weird.
 *
 *----------------------------------------------------------------------
 */

static SortElement *
MergeSort(headPtr, infoPtr)
    SortElement *headPtr;		/* First element on the list. */
    SortInfo *infoPtr;			/* Information needed by the
					 * comparison operator. */
{
    /*
     * The subList array below holds pointers to temporary lists built during
     * the merge sort.  Element i of the array holds a list of length 2**i.
     */

#   define NUM_LISTS 30
    SortElement *subList[NUM_LISTS];
    SortElement *elementPtr;
    int i;

................................................................................
 *	None, unless a user-defined comparison command does something weird.
 *
 *----------------------------------------------------------------------
 */

static SortElement *
MergeLists(leftPtr, rightPtr, infoPtr)
    SortElement *leftPtr;		/* First list to be merged; may be
					 * NULL. */
    SortElement *rightPtr;		/* Second list to be merged; may be
					 * NULL. */
    SortInfo *infoPtr;			/* Information needed by the
					 * comparison operator. */
{
    SortElement *headPtr;
    SortElement *tailPtr;
    int cmp;

    if (leftPtr == NULL) {
	return rightPtr;
................................................................................
 *
 *	This procedure is invoked by MergeLists to determine the proper
 *	ordering between two elements.
 *
 * Results:
 *	A negative results means the the first element comes before the
 *	second, and a positive results means that the second element should
 *	come first.  A result of zero means the two elements are equal and it
 *	doesn't matter which comes first.
 *
 * Side effects:
 *	None, unless a user-defined comparison command does something weird.
 *
 *----------------------------------------------------------------------
 */

static int
SortCompare(objPtr1, objPtr2, infoPtr)
    Tcl_Obj *objPtr1, *objPtr2;		/* Values to be compared. */
    SortInfo *infoPtr;			/* Information passed from the
					 * top-level "lsort" command. */
{
    int order;

    order = 0;
    if (infoPtr->resultCode != TCL_OK) {
	/*
	 * Once an error has occurred, skip any future comparisons so as to
................................................................................
    } else {
	Tcl_Obj **objv, *paramObjv[2];
	int objc;

	paramObjv[0] = objPtr1;
	paramObjv[1] = objPtr2;

  	/*
	 * We made space in the command list for the two things to compare.
	 * Replace them and evaluate the result.
	 */

	Tcl_ListObjLength(infoPtr->interp, infoPtr->compareCmdPtr, &objc);
	Tcl_ListObjReplace(infoPtr->interp, infoPtr->compareCmdPtr, objc - 2,
		2, 2, paramObjv);
   	Tcl_ListObjGetElements(infoPtr->interp, infoPtr->compareCmdPtr,
		&objc, &objv);

	infoPtr->resultCode = Tcl_EvalObjv(infoPtr->interp, objc, objv, 0);

  	if (infoPtr->resultCode != TCL_OK) {
	    Tcl_AddErrorInfo(infoPtr->interp,
		    "\n    (-compare command)");
	    return order;
	}

	/*
	 * Parse the result of the command.
................................................................................
 
/*
 *----------------------------------------------------------------------
 *
 * DictionaryCompare
 *
 *	This function compares two strings as if they were being used in an
 *	index or card catalog.  The case of alphabetic characters is ignored,
 *	except to break ties.  Thus "B" comes before "b" but after "a".  Also,
 *	integers embedded in the strings compare in numerical order.  In other
 *	words, "x10y" comes after "x9y", not * before it as it would when
 *	using strcmp().
 *
 * Results:
 *	A negative result means that the first element comes before the
 *	second, and a positive result means that the second element should
 *	come first.  A result of zero means the two elements are equal and it
 *	doesn't matter which comes first.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
DictionaryCompare(left, right)
    char *left, *right;			/* The strings to compare. */
{
    Tcl_UniChar uniLeft, uniRight, uniLeftLower, uniRightLower;
    int diff, zeros;
    int secondaryDiff = 0;

    while (1) {
	if (isdigit(UCHAR(*right))		/* INTL: digit */
		&& isdigit(UCHAR(*left))) {	/* INTL: digit */
	    /*
	     * There are decimal numbers embedded in the two strings.  Compare
	     * them as numbers, rather than strings.  If one number has more
	     * leading zeros than the other, the number with more leading
	     * zeros sorts later, but only as a secondary choice.
	     */

	    zeros = 0;
	    while ((*right == '0') && (isdigit(UCHAR(right[1])))) {
		right++;
................................................................................
	    }
	    if (secondaryDiff == 0) {
		secondaryDiff = zeros;
	    }

	    /*
	     * The code below compares the numbers in the two strings without
	     * ever converting them to integers.  It does this by first
	     * comparing the lengths of the numbers and then comparing the
	     * digit values.
	     */

	    diff = 0;
	    while (1) {
		if (diff == 0) {
................................................................................
		    return -1;
		}
	    }
	    continue;
	}

	/*
	 * Convert character to Unicode for comparison purposes.  If either
	 * string is at the terminating null, do a byte-wise comparison and
	 * bail out immediately.
	 */

	if ((*left != '\0') && (*right != '\0')) {
	    left += Tcl_UtfToUniChar(left, &uniLeft);
	    right += Tcl_UtfToUniChar(right, &uniRight);

	    /*
	     * Convert both chars to lower for the comparison, because
	     * dictionary sorts are case insensitve.  Covert to lower, not
	     * upper, so chars between Z and a will sort before A (where most
	     * other interesting punctuations occur)
	     */

	    uniLeftLower = Tcl_UniCharToLower(uniLeft);
	    uniRightLower = Tcl_UniCharToLower(uniRight);
	} else {
................................................................................
}
 
/*
 *----------------------------------------------------------------------
 *
 * SelectObjFromSublist --
 *
 *	This procedure is invoked from lsearch and SortCompare.  It is used
 *	for implementing the -index option, for the lsort and lsearch
 *	commands.
 *
 * Results:
 *	Returns NULL if a failure occurs, and sets the result in the infoPtr.
 *	Otherwise returns the Tcl_Obj* to the item.
 *
................................................................................
 *	and never passed directly to user code.
 *
 *----------------------------------------------------------------------
 */

static Tcl_Obj*
SelectObjFromSublist(objPtr, infoPtr)
    Tcl_Obj *objPtr;			/* Obj to select sublist from. */
    SortInfo *infoPtr;			/* Information passed from the
					 * top-level "lsearch" or "lsort"
					 * command. */
{
    int i;

    /*
     * Quick check for case when no "-index" option is there.
     */







|












|
|
|
|







|
|
<










|




|











|







 







|



|
|





|
<
|
|
<
<
|
|
<
|
|
|
<
|
|
<
|
|
<
|
|
<
|
|
<
|
|
<
|
|
<
|
|
<
|
<
|
|
|
<
|
|
<
|
|
<
|
|
|
|
|
<
|
<
|
|
|
<
|
|
<
|
|
<
|
<
|
|
|
<
|
|
|
|
|
|
|
<





|







 







|







 







|







 







|
|







 







|







 







|







 







|







 







|


|







 







|

|







 







|


|







 







|

|







 







|







 







|







 







|







 







|













|


|







 







|

|







 







|







 







|
>







 







|







 







|









|







 







|







 







|
|


|







 







|







 







|







 







|







 







|







 







|







 







|







 







|
|
|







 







|







 







|







 







|







 







|
|







 







|







 







|
|
|
|
>







 







|







 







|







 







|





|







 







|







 







|

|







 







|







 







|







 







|







 







|

|



|







 







|







 







|







 







|







 







|







 







|







 







|
|
|



|







 







|
<
|
<
|
|







 







|










|
|
|







 







|







|




|







 







|
|
|






|










|









|
|







 







|







 







|










|







 







|







 







|
|
|
<







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44

45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
..
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100

101
102


103
104

105
106
107

108
109

110
111

112
113

114
115

116
117

118
119

120
121

122

123
124
125

126
127

128
129

130
131
132
133
134

135

136
137
138

139
140

141
142

143

144
145
146

147
148
149
150
151
152
153

154
155
156
157
158
159
160
161
162
163
164
165
166
...
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
...
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
...
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
...
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
...
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
...
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
...
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
...
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
....
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
....
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
....
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
....
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
....
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
....
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
....
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
....
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
....
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
....
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
....
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
....
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
....
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
....
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
....
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
....
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
....
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
....
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
....
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
....
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
....
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
....
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
....
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
....
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
....
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
....
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
....
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
....
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
....
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
....
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
....
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
....
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
....
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
....
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
....
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
....
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
....
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
....
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
....
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
....
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
....
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
....
4222
4223
4224
4225
4226
4227
4228
4229

4230

4231
4232
4233
4234
4235
4236
4237
4238
4239
....
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
....
4358
4359
4360
4361
4362
4363
4364
4365
4366
4367
4368
4369
4370
4371
4372
4373
4374
4375
4376
4377
4378
4379
4380
4381
4382
4383
4384
4385
....
4402
4403
4404
4405
4406
4407
4408
4409
4410
4411
4412
4413
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
....
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
4466
4467
....
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
4506
4507
4508
4509
4510
4511
4512
....
4533
4534
4535
4536
4537
4538
4539
4540
4541
4542
4543
4544
4545
4546
4547
....
4553
4554
4555
4556
4557
4558
4559
4560
4561
4562

4563
4564
4565
4566
4567
4568
4569
 * Copyright (c) 1998-1999 by Scriptics Corporation.
 * Copyright (c) 2001 by Kevin B. Kenny.  All rights reserved.
 * Copyright (c) 2005 Donal K. Fellows.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclCmdIL.c,v 1.70.2.8 2005/08/29 18:38:45 dgp Exp $
 */

#include "tclInt.h"
#include "tclRegexp.h"

/*
 * During execution of the "lsort" command, structures of the following type
 * are used to arrange the objects being sorted into a collection of linked
 * lists.
 */

typedef struct SortElement {
    Tcl_Obj *objPtr;		/* Object being sorted. */
    int count;			/* number of same elements in list */
    struct SortElement *nextPtr;/* Next element in the list, or NULL for end
				 * of list. */
} SortElement;

/*
 * These function pointer types are used with the "lsearch" and "lsort"
 * commands to facilitate the "-nocase" option.
 */

typedef int (*SortStrCmpFn_t) (const char *, const char *);
typedef int (*SortMemCmpFn_t) (const void *, const void *, size_t);


/*
 * The "lsort" command needs to pass certain information down to the function
 * that compares two list elements, and the comparison function needs to pass
 * success or failure information back up to the top-level "lsort" command.
 * The following structure is used to pass this information.
 */

typedef struct SortInfo {
    int isIncreasing;		/* Nonzero means sort in increasing order. */
    int sortMode;		/* The sort mode. One of SORTMODE_* values
				 * defined below */
    SortStrCmpFn_t strCmpFn;	/* Basic string compare command (used with
				 * ASCII mode). */
    Tcl_Obj *compareCmdPtr;	/* The Tcl comparison command when sortMode is
				 * SORTMODE_COMMAND. Pre-initialized to hold
				 * base of command.*/
    int *indexv;		/* If the -index option was specified, this
				 * holds the indexes contained in the list
				 * supplied as an argument to that option.
				 * NULL if no indexes supplied, and points to
				 * singleIndex field when only one
				 * supplied. */
    int indexc;			/* Number of indexes in indexv array. */
    int singleIndex;		/* Static space for common index case. */
    Tcl_Interp *interp;		/* The interpreter in which the sort is being
				 * done. */
    int resultCode;		/* Completion code for the lsort command. If
				 * an error occurs during the sort this is
				 * changed from TCL_OK to TCL_ERROR. */
} SortInfo;

/*
 * The "sortMode" field of the SortInfo structure can take on any of the
 * following values.
................................................................................
#define SORTMODE_ASCII		0
#define SORTMODE_INTEGER	1
#define SORTMODE_REAL		2
#define SORTMODE_COMMAND	3
#define SORTMODE_DICTIONARY	4

/*
 * Magic values for the index field of the SortInfo structure. Note that the
 * index "end-1" will be translated to SORTIDX_END-1, etc.
 */

#define SORTIDX_NONE	-1	/* Not indexed; use whole value. */
#define SORTIDX_END	-2	/* Indexed from end. */

/*
 * Forward declarations for procedures defined in this file:
 */

static void		AppendLocals(Tcl_Interp *interp, Tcl_Obj *listPtr,

			    CONST char *pattern, int includeLinks);
static int		DictionaryCompare(char *left, char *right);


static int		InfoArgsCmd(ClientData dummy, Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]);

static int		InfoBodyCmd(ClientData dummy, Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]);
static int		InfoCmdCountCmd(ClientData dummy, Tcl_Interp *interp,

			    int objc, Tcl_Obj *CONST objv[]);
static int		InfoCommandsCmd(ClientData dummy, Tcl_Interp *interp,

			    int objc, Tcl_Obj *CONST objv[]);
static int		InfoCompleteCmd(ClientData dummy, Tcl_Interp *interp,

			    int objc, Tcl_Obj *CONST objv[]);
static int		InfoDefaultCmd(ClientData dummy, Tcl_Interp *interp,

			    int objc, Tcl_Obj *CONST objv[]);
static int		InfoExistsCmd(ClientData dummy, Tcl_Interp *interp,

			    int objc, Tcl_Obj *CONST objv[]);
static int		InfoFunctionsCmd(ClientData dummy, Tcl_Interp *interp,

			    int objc, Tcl_Obj *CONST objv[]);
static int		InfoGlobalsCmd(ClientData dummy, Tcl_Interp *interp,

			    int objc, Tcl_Obj *CONST objv[]);
static int		InfoHostnameCmd(ClientData dummy, Tcl_Interp *interp,

			    int objc, Tcl_Obj *CONST objv[]);

static int		InfoLevelCmd(ClientData dummy, Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]);
static int		InfoLibraryCmd(ClientData dummy, Tcl_Interp *interp,

			    int objc, Tcl_Obj *CONST objv[]);
static int		InfoLoadedCmd(ClientData dummy, Tcl_Interp *interp,

			    int objc, Tcl_Obj *CONST objv[]);
static int		InfoLocalsCmd(ClientData dummy, Tcl_Interp *interp,

			    int objc, Tcl_Obj *CONST objv[]);
static int		InfoNameOfExecutableCmd(ClientData dummy,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
static int		InfoPatchLevelCmd(ClientData dummy, Tcl_Interp *interp,

			    int objc, Tcl_Obj *CONST objv[]);

static int		InfoProcsCmd(ClientData dummy, Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]);
static int		InfoScriptCmd(ClientData dummy, Tcl_Interp *interp,

			    int objc, Tcl_Obj *CONST objv[]);
static int		InfoSharedlibCmd(ClientData dummy, Tcl_Interp *interp,

			    int objc, Tcl_Obj *CONST objv[]);
static int		InfoTclVersionCmd(ClientData dummy, Tcl_Interp *interp,

			    int objc, Tcl_Obj *CONST objv[]);

static int		InfoVarsCmd(ClientData dummy, Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]);
static SortElement *    MergeSort(SortElement *headPt, SortInfo *infoPtr);

static SortElement *    MergeLists(SortElement *leftPtr, SortElement *rightPtr,
			    SortInfo *infoPtr);
static int		SortCompare(Tcl_Obj *firstPtr, Tcl_Obj *second,
			    SortInfo *infoPtr);
static Tcl_Obj *	SelectObjFromSublist(Tcl_Obj *firstPtr,
			    SortInfo *infoPtr);
 

/*
 *----------------------------------------------------------------------
 *
 * Tcl_IfObjCmd --
 *
 *	This procedure is invoked to process the "if" Tcl command. See the
 *	user documentation for details on what it does.
 *
 *	With the bytecode compiler, this procedure is only called when a
 *	command name is computed at runtime, and is "if" or the name to which
 *	"if" was renamed: e.g., "set z if; $z 1 {puts foo}"
 *
 * Results:
................................................................................
    int i, result, value;
    char *clause;
    i = 1;
    while (1) {
	/*
	 * At this point in the loop, objv and objc refer to an expression to
	 * test, either for the main expression or an expression following an
	 * "elseif". The arguments after the expression must be "then"
	 * (optional) and a script to execute if the expression is true.
	 */

	if (i >= objc) {
	    clause = TclGetString(objv[i-1]);
	    Tcl_AppendResult(interp, "wrong # args: no expression after \"",
		    clause, "\" argument", (char *) NULL);
................................................................................
	}
	if (value) {
	    thenScriptIndex = i;
	    value = 0;
	}

	/*
	 * The expression evaluated to false. Skip the command, then see if
	 * there is an "else" or "elseif" clause.
	 */

	i++;
	if (i >= objc) {
	    if (thenScriptIndex) {
		return Tcl_EvalObjEx(interp, objv[thenScriptIndex], 0);
................................................................................
	    i++;
	    continue;
	}
	break;
    }

    /*
     * Couldn't find a "then" or "elseif" clause to execute. Check now for an
     * "else" clause. We know that there's at least one more argument when we
     * get here.
     */

    if (strcmp(clause, "else") == 0) {
	i++;
	if (i >= objc) {
	    Tcl_AppendResult(interp,
................................................................................
}
 
/*
 *----------------------------------------------------------------------
 *
 * Tcl_IncrObjCmd --
 *
 *	This procedure is invoked to process the "incr" Tcl command. See the
 *	user documentation for details on what it does.
 *
 *	With the bytecode compiler, this procedure is only called when a
 *	command name is computed at runtime, and is "incr" or the name to
 *	which "incr" was renamed: e.g., "set z incr; $z i -1"
 *
 * Results:
................................................................................
}
 
/*
 *----------------------------------------------------------------------
 *
 * Tcl_InfoObjCmd --
 *
 *	This procedure is invoked to process the "info" Tcl command. See the
 *	user documentation for details on what it does.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	See the user documentation.
................................................................................
     * the object do not invalidate the internal rep.
     */

    bodyPtr = procPtr->bodyPtr;
    if (bodyPtr->bytes == NULL) {
	/*
	 * The string rep might not be valid if the procedure has never been
	 * run before. [Bug #545644]
	 */

	(void) Tcl_GetString(bodyPtr);
    }
    resultPtr = Tcl_NewStringObj(bodyPtr->bytes, bodyPtr->length);

    Tcl_SetObjResult(interp, resultPtr);
................................................................................
 
/*
 *----------------------------------------------------------------------
 *
 * InfoCommandsCmd --
 *
 *	Called to implement the "info commands" command that returns the list
 *	of commands in the interpreter that match an optional pattern. The
 *	pattern, if any, consists of an optional sequence of namespace names
 *	separated by "::" qualifiers, which is followed by a glob-style
 *	pattern that restricts which commands are returned. Handles the
 *	following syntax:
 *
 *	    info commands ?pattern?
 *
 * Results:
 *	Returns TCL_OK if successful and TCL_ERROR if there is an error.
 *
................................................................................
{
    char *cmdName, *pattern;
    CONST char *simplePattern;
    register Tcl_HashEntry *entryPtr;
    Tcl_HashSearch search;
    Namespace *nsPtr;
    Namespace *globalNsPtr = (Namespace *) Tcl_GetGlobalNamespace(interp);
    Namespace *currNsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp);
    Tcl_Obj *listPtr, *elemObjPtr;
    int specificNsInPattern = 0;/* Init. to avoid compiler warning. */
    Tcl_Command cmd;
    int i;

    /*
     * Get the pattern and find the "effective namespace" in which to list
     * commands.
     */
................................................................................
 
/*
 *----------------------------------------------------------------------
 *
 * InfoProcsCmd --
 *
 *	Called to implement the "info procs" command that returns the list of
 *	procedures in the interpreter that match an optional pattern. The
 *	pattern, if any, consists of an optional sequence of namespace names
 *	separated by "::" qualifiers, which is followed by a glob-style
 *	pattern that restricts which commands are returned. Handles the
 *	following syntax:
 *
 *	    info procs ?pattern?
 *
 * Results:
 *	Returns TCL_OK if successful and TCL_ERROR if there is an error.
 *
................................................................................
{
    char *cmdName, *pattern;
    CONST char *simplePattern;
    Namespace *nsPtr;
#ifdef INFO_PROCS_SEARCH_GLOBAL_NS
    Namespace *globalNsPtr = (Namespace *) Tcl_GetGlobalNamespace(interp);
#endif
    Namespace *currNsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp);
    Tcl_Obj *listPtr, *elemObjPtr;
    int specificNsInPattern = 0;/* Init. to avoid compiler warning. */
    register Tcl_HashEntry *entryPtr;
    Tcl_HashSearch search;
    Command *cmdPtr, *realCmdPtr;

    /*
     * Get the pattern and find the "effective namespace" in which to list
     * procs.
................................................................................
		if (!TclIsProc(cmdPtr)) {
		    realCmdPtr = (Command *)
			    TclGetOriginalCommand((Tcl_Command) cmdPtr);
		    if (realCmdPtr != NULL && TclIsProc(realCmdPtr)) {
			goto procOK;
		    }
		} else {
		procOK:
		    if (specificNsInPattern) {
			elemObjPtr = Tcl_NewObj();
			Tcl_GetCommandFullName(interp, (Tcl_Command) cmdPtr,
				elemObjPtr);
		    } else {
			elemObjPtr = Tcl_NewStringObj(cmdName, -1);
		    }
................................................................................
	 * namespace.
	 */

#ifdef INFO_PROCS_SEARCH_GLOBAL_NS
	/*
	 * If "info procs" worked like "info commands", returning the commands
	 * also seen in the global namespace, then you would include this
	 * code. As this could break backwards compatibilty with 8.0-8.2, we
	 * decided not to "fix" it in 8.3, leaving the behavior slightly
	 * different.
	 */

	if ((nsPtr != globalNsPtr) && !specificNsInPattern) {
	    entryPtr = Tcl_FirstHashEntry(&globalNsPtr->cmdTable, &search);
	    while (entryPtr != NULL) {
................................................................................
 *	If newName is specified, it will set that as the internal name.
 *
 * Results:
 *	Returns TCL_OK if successful and TCL_ERROR if there is an error.
 *
 * Side effects:
 *	Returns a result in the interpreter's result object. If there is an
 *	error, the result is an error message. It may change the internal
 *	script filename.
 *
 *----------------------------------------------------------------------
 */

static int
InfoScriptCmd(dummy, interp, objc, objv)
................................................................................

    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 2, objv, NULL);
	return TCL_ERROR;
    }

    version = Tcl_GetVar2Ex(interp, "tcl_version", NULL,
	    (TCL_GLOBAL_ONLY | TCL_LEAVE_ERR_MSG));
    if (version != NULL) {
	Tcl_SetObjResult(interp, version);
	return TCL_OK;
    }
    return TCL_ERROR;
}
 
/*
 *----------------------------------------------------------------------
 *
 * InfoVarsCmd --
 *
 *	Called to implement the "info vars" command that returns the list of
 *	variables in the interpreter that match an optional pattern. The
 *	pattern, if any, consists of an optional sequence of namespace names
 *	separated by "::" qualifiers, which is followed by a glob-style
 *	pattern that restricts which variables are returned. Handles the
 *	following syntax:
 *
 *	    info vars ?pattern?
 *
 * Results:
 *	Returns TCL_OK if successful and TCL_ERROR if there is an error.
 *
................................................................................
    char *varName, *pattern;
    CONST char *simplePattern;
    register Tcl_HashEntry *entryPtr;
    Tcl_HashSearch search;
    Var *varPtr;
    Namespace *nsPtr;
    Namespace *globalNsPtr = (Namespace *) Tcl_GetGlobalNamespace(interp);
    Namespace *currNsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp);
    Tcl_Obj *listPtr, *elemObjPtr;
    int specificNsInPattern = 0;/* Init. to avoid compiler warning. */

    /*
     * Get the pattern and find the "effective namespace" in which to list
     * variables. We only use this effective namespace if there's no active
     * Tcl procedure frame.
     */

................................................................................
	Namespace *dummy1NsPtr, *dummy2NsPtr;

	pattern = TclGetString(objv[2]);
	TclGetNamespaceForQualName(interp, pattern, (Namespace *) NULL,
		/*flags*/ 0, &nsPtr, &dummy1NsPtr, &dummy2NsPtr,
		&simplePattern);

	if (nsPtr != NULL) {	/* We successfully found the pattern's ns */
	    specificNsInPattern = (strcmp(simplePattern, pattern) != 0);
	}
    } else {
	Tcl_WrongNumArgs(interp, 2, objv, "?pattern?");
	return TCL_ERROR;
    }

................................................................................
		if (!TclIsVarUndefined(varPtr)
			|| TclIsVarNamespaceVar(varPtr)) {
		    varName = Tcl_GetHashKey(&nsPtr->varTable, entryPtr);
		    if ((simplePattern == NULL)
			    || Tcl_StringMatch(varName, simplePattern)) {
			if (specificNsInPattern) {
			    elemObjPtr = Tcl_NewObj();
			    Tcl_GetVariableFullName(interp, (Tcl_Var) varPtr,
				    elemObjPtr);
			} else {
			    elemObjPtr = Tcl_NewStringObj(varName, -1);
			}
			Tcl_ListObjAppendElement(interp, listPtr, elemObjPtr);
		    }
		}
		entryPtr = Tcl_NextHashEntry(&search);
................................................................................
}
 
/*
 *----------------------------------------------------------------------
 *
 * Tcl_JoinObjCmd --
 *
 *	This procedure is invoked to process the "join" Tcl command. See the
 *	user documentation for details on what it does.
 *
 * Results:
 *	A standard Tcl object result.
 *
 * Side effects:
 *	See the user documentation.
................................................................................
	Tcl_DecrRefCount(emptyObj);
    }

    /*
     * Now place a list of any values left over into the interpreter result.
     *
     * First, figure out how many values were not assigned by getting the
     * length of the list. Note that I do not expect this operation to fail.
     */

    if (Tcl_ListObjGetElements(interp, objv[1],
	    &listObjc, &listObjv) != TCL_OK) {
	return TCL_ERROR;
    }

    if (listObjc > objc-2) {
	/*
	 * OK, there were left-overs. Make a list of them and slap that back
	 * in the interpreter result.
	 */

	Tcl_SetObjResult(interp,
		Tcl_NewListObj(listObjc - objc + 2, listObjv + objc - 2));
    }

................................................................................
    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "list ?index...?");
	return TCL_ERROR;
    }

    /*
     * If objc==3, then objv[2] may be either a single index or a list of
     * indices: go to TclLindexList to determine which. If objc>=4, or
     * objc==2, then objv[2 .. objc-2] are all single indices and processed as
     * such in TclLindexFlat.
     */

    if (objc == 3) {
	elemPtr = TclLindexList(interp, objv[1], objv[2]);
    } else {
................................................................................
 *	occurred.
 *
 * Side effects:
 *	None.
 *
 * Notes:
 *	If objv[1] can be parsed as a list, TclLindexList handles extraction
 *	of the desired element locally. Otherwise, it invokes TclLindexFlat to
 *	treat objv[1] as a scalar.
 *
 *	The reference count of the returned object includes one reference
 *	corresponding to the pointer returned. Thus, the calling code will
 *	usually do something like:
 *		Tcl_SetObjResult(interp, result);
 *		Tcl_DecrRefCount(result);
 *
 *----------------------------------------------------------------------
 */

................................................................................

	return TclLindexFlat(interp, listPtr, 1, &argPtr);
    }

    if (Tcl_ListObjGetElements(NULL, argPtr, &indexCount, &indices) != TCL_OK){
	/*
	 * argPtr designates something that is neither an index nor a
	 * well-formed list. Report the error via TclLindexFlat.
	 */

	return TclLindexFlat(interp, listPtr, 1, &argPtr);
    }

    /*
     * Record the reference to the list that we are maintaining in the
................................................................................
	    Tcl_DecrRefCount(listPtr);
	    listPtr = Tcl_NewObj();
	    Tcl_IncrRefCount(listPtr);
	    return listPtr;
	}

	/*
	 * Make sure listPtr still refers to a list object. If it shared a
	 * Tcl_Obj structure with the arguments, then it might have just been
	 * converted to something else.
	 */

	if (listPtr->typePtr != &tclListType) {
	    result = Tcl_ListObjGetElements(interp, listPtr, &listLen,
		    &elemPtrs);
................................................................................
	oldListPtr = listPtr;
	listPtr = elemPtrs[index];
	Tcl_IncrRefCount(listPtr);
	Tcl_DecrRefCount(oldListPtr);

	/*
	 * The work we did above may have caused the internal rep of *argPtr
	 * to change to something else. Get it back.
	 */

	result = Tcl_ListObjGetElements(interp, argPtr, &indexCount, &indices);
	if (result != TCL_OK) {
	    /*
	     * This can't happen unless some extension corrupted a Tcl_Obj.
	     */
................................................................................

	    Tcl_DecrRefCount(listPtr);
	    return NULL;
	}
    }

    /*
     * Return the last object extracted. Its reference count will include the
     * reference being returned.
     */

    return listPtr;
}
 
/*
................................................................................
 *	Returns a standard Tcl result.
 *
 * Side effects:
 *	None.
 *
 * Notes:
 *	This procedure is called from either tclExecute.c or Tcl_LindexObjCmd
 *	whenever either is presented with objc==2 or objc>=4. It is also
 *	called from TclLindexList for the objc==3 case once it is determined
 *	that objv[2] cannot be parsed as a list.
 *
 *----------------------------------------------------------------------
 */

Tcl_Obj *
................................................................................
    int i;			/* Current list index. */
    int result;			/* Result of Tcl library calls. */
    int listLen;		/* Length of the current list being
				 * processed. */
    Tcl_Obj** elemPtrs;		/* Array of pointers to the elements of the
				 * current list. */
    int index;			/* Parsed version of the current element of
				 * indexArray. */
    Tcl_Obj* oldListPtr;	/* Temporary to hold listPtr so that its ref
				 * count can be decremented. */

    /*
     * Record the reference to the 'listPtr' object that we are maintaining in
     * the C activation record.
     */
................................................................................
	    Tcl_DecrRefCount(listPtr);
	    listPtr = Tcl_NewObj();
	    Tcl_IncrRefCount(listPtr);
	    return listPtr;
	}

	/*
	 * Make sure listPtr still refers to a list object. It might have been
	 * converted to something else above if objv[1] overlaps with one of
	 * the other parameters.
	 */

	if (listPtr->typePtr != &tclListType) {
	    result = Tcl_ListObjGetElements(interp, listPtr, &listLen,
		    &elemPtrs);
	    if (result != TCL_OK) {
		Tcl_DecrRefCount(listPtr);
................................................................................

    result = Tcl_ListObjLength(interp, objv[1], &len);
    if (result != TCL_OK) {
	return result;
    }

    /*
     * Get the index. "end" is interpreted to be the index after the last
     * element, such that using it will cause any inserted elements to be
     * appended to the list.
     */

    result = TclGetIntForIndex(interp, objv[2], /*end*/ len, &index);
    if (result != TCL_OK) {
	return result;
................................................................................
}
 
/*
 *----------------------------------------------------------------------
 *
 * Tcl_ListObjCmd --
 *
 *	This procedure is invoked to process the "list" Tcl command. See the
 *	user documentation for details on what it does.
 *
 * Results:
 *	A standard Tcl object result.
 *
 * Side effects:
 *	See the user documentation.
................................................................................
 
/*
 *----------------------------------------------------------------------
 *
 * Tcl_LlengthObjCmd --
 *
 *	This object-based procedure is invoked to process the "llength" Tcl
 *	command. See the user documentation for details on what it does.
 *
 * Results:
 *	A standard Tcl object result.
 *
 * Side effects:
 *	See the user documentation.
 *
................................................................................
}
 
/*
 *----------------------------------------------------------------------
 *
 * Tcl_LrangeObjCmd --
 *
 *	This procedure is invoked to process the "lrange" Tcl command. See the
 *	user documentation for details on what it does.
 *
 * Results:
 *	A standard Tcl object result.
 *
 * Side effects:
 *	See the user documentation.
 *
................................................................................
}
 
/*
 *----------------------------------------------------------------------
 *
 * Tcl_LrepeatObjCmd --
 *
 *	This procedure is invoked to process the "lrepeat" Tcl command. See
 *	the user documentation for details on what it does.
 *
 * Results:
 *	A standard Tcl object result.
 *
 * Side effects:
 *	See the user documentation.
................................................................................
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
int
Tcl_LrepeatObjCmd(dummy, interp, objc, objv)
    ClientData dummy;		/* Not used. */
    Tcl_Interp *interp;		/* Current interpreter. */
    register int objc;		/* Number of arguments. */
    register Tcl_Obj *CONST objv[];
				/* The argument objects. */
{
    int elementCount, i, result;
    Tcl_Obj *listPtr, **dataArray;
    List *listRepPtr;

    /*
     * Check arguments for legality:
................................................................................

    listPtr = Tcl_NewListObj(elementCount*objc, NULL);
    listRepPtr = (List *) listPtr->internalRep.twoPtrValue.ptr1;
    listRepPtr->elemCount = elementCount*objc;
    dataArray = &listRepPtr->elements;

    /*
     * Set the elements. Note that we handle the common degenerate case of a
     * single value being repeated separately to permit the compiler as much
     * room as possible to optimize a loop that might be run a very large
     * number of times.
     */

    if (objc == 1) {
	register Tcl_Obj *tmpPtr = objv[0];
................................................................................

    result = Tcl_ListObjLength(interp, objv[1], &listLen);
    if (result != TCL_OK) {
	return result;
    }

    /*
     * Get the first and last indexes. "end" is interpreted to be the index
     * for the last element, such that using it will cause that element to be
     * included for deletion.
     */

    result = TclGetIntForIndex(interp, objv[2], /*end*/ (listLen - 1), &first);
    if (result != TCL_OK) {
	return result;
................................................................................
    }

    result = TclGetIntForIndex(interp, objv[3], /*end*/ (listLen - 1), &last);
    if (result != TCL_OK) {
	return result;
    }

    if (first < 0) {
    	first = 0;
    }

    /*
     * Complain if the user asked for a start element that is greater than the
     * list length. This won't ever trigger for the "end*" case as that will
     * be properly constrained by TclGetIntForIndex because we use listLen-1
     * (to allow for replacing the last elem).
     */

    if ((first >= listLen) && (listLen > 0)) {
	Tcl_AppendResult(interp, "list doesn't contain element ",
		TclGetString(objv[2]), (int *) NULL);
................................................................................
}
 
/*
 *----------------------------------------------------------------------
 *
 * Tcl_LsearchObjCmd --
 *
 *	This procedure is invoked to process the "lsearch" Tcl command. See
 *	the user documentation for details on what it does.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	See the user documentation.
................................................................................
		}
		Tcl_AppendResult(interp, "missing starting index", NULL);
		return TCL_ERROR;
	    }
	    i++;
	    if (objv[i] == objv[objc - 2]) {
		/*
		 * Take copy to prevent shimmering problems. Note that it
		 * does not matter if the index obj is also a component of the
		 * list being searched. We only need to copy where the list
		 * and the index are one-and-the-same.
		 */

		startPtr = Tcl_DuplicateObj(objv[i]);
	    } else {
		startPtr = objv[i];
		Tcl_IncrRefCount(startPtr);
................................................................................
			"\"-index\" option must be followed by list index",
			NULL);
		return TCL_ERROR;
	    }

	    /*
	     * Store the extracted indices for processing by sublist
	     * extraction. Note that we don't do this using objects because
	     * that has shimmering problems.
	     */

	    i++;
	    if (Tcl_ListObjGetElements(interp, objv[i],
		    &sortInfo.indexc, &indices) != TCL_OK) {
		if (startPtr != NULL) {
................................................................................
		break;
	    default:
		sortInfo.indexv = (int *)
			ckalloc(sizeof(int) * sortInfo.indexc);
	    }

	    /*
	     * Fill the array by parsing each index. We don't know whether
	     * their scale is sensible yet, but we at least perform the
	     * syntactic check here.
	     */

	    for (j=0 ; j<sortInfo.indexc ; j++) {
		if (TclGetIntForIndex(interp, indices[j], SORTIDX_END,
			&sortInfo.indexv[j]) != TCL_OK) {
................................................................................
     */

    index = -1;
    match = 0;

    if ((enum modes) mode == SORTED && !allMatches && !negatedMatch) {
	/*
	 * If the data is sorted, we can do a more intelligent search. Note
	 * that there is no point in being smart when -all was specified; in
	 * that case, we have to look at all items anyway, and there is no
	 * sense in doing this when the match sense is inverted.
	 */

	lower = offset - 1;
	upper = listc;
................................................................................
		    match = 1;
		}
		break;
	    }
	    if (match == 0) {
		/*
		 * Normally, binary search is written to stop when it finds a
		 * match. If there are duplicates of an element in the list,
		 * our first match might not be the first occurance.
		 * Consider: 0 0 0 1 1 1 2 2 2
		 *
		 * To maintain consistancy with standard lsearch semantics, we
		 * must find the leftmost occurance of the pattern in the
		 * list. Thus we don't just stop searching here. This
		 * variation means that a search always makes log n
		 * comparisons (normal binary search might "get lucky" with an
		 * early comparison).
		 */

		index = i;
		upper = i;
................................................................................
	    }
	    Tcl_SetObjResult(interp, itemPtr);
	} else {
	    Tcl_SetObjResult(interp, Tcl_NewIntObj(index));
	}
    } else if (index < 0) {
	/*
	 * Is this superfluous? The result should be a blank object by
	 * default...
	 */

	Tcl_SetObjResult(interp, Tcl_NewObj());
    } else {
	Tcl_SetObjResult(interp, listv[index]);
    }
................................................................................
}
 
/*
 *----------------------------------------------------------------------
 *
 * Tcl_LsetObjCmd --
 *
 *	This procedure is invoked to process the "lset" Tcl command. See the
 *	user documentation for details on what it does.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	See the user documentation.
................................................................................
    listPtr = Tcl_ObjGetVar2(interp, objv[1], (Tcl_Obj *) NULL,
	    TCL_LEAVE_ERR_MSG);
    if (listPtr == NULL) {
	return TCL_ERROR;
    }

    /*
     * Substitute the value in the value. Return either the value or else an
     * unshared copy of it.
     */

    if (objc == 4) {
	finalValuePtr = TclLsetList(interp, listPtr, objv[2], objv[3]);
    } else {
	finalValuePtr = TclLsetFlat(interp, listPtr, objc-3, objv+2,
................................................................................
}
 
/*
 *----------------------------------------------------------------------
 *
 * Tcl_LsortObjCmd --
 *
 *	This procedure is invoked to process the "lsort" Tcl command. See the
 *	user documentation for details on what it does.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	See the user documentation.
................................................................................
		break;
	    default:
		sortInfo.indexv = (int *)
			ckalloc(sizeof(int) * sortInfo.indexc);
	    }

	    /*
	     * Fill the array by parsing each index. We don't know whether
	     * their scale is sensible yet, but we at least perform the
	     * syntactic check here.
	     */

	    for (j=0 ; j<sortInfo.indexc ; j++) {
		if (TclGetIntForIndex(interp, indices[j], SORTIDX_END,
			&sortInfo.indexv[j]) != TCL_OK) {
................................................................................
 *	None, unless a user-defined comparison command does something weird.
 *
 *----------------------------------------------------------------------
 */

static SortElement *
MergeSort(headPtr, infoPtr)
    SortElement *headPtr;	/* First element on the list. */
    SortInfo *infoPtr;		/* Information needed by the comparison
				 * operator. */
{
    /*
     * The subList array below holds pointers to temporary lists built during
     * the merge sort. Element i of the array holds a list of length 2**i.
     */

#   define NUM_LISTS 30
    SortElement *subList[NUM_LISTS];
    SortElement *elementPtr;
    int i;

................................................................................
 *	None, unless a user-defined comparison command does something weird.
 *
 *----------------------------------------------------------------------
 */

static SortElement *
MergeLists(leftPtr, rightPtr, infoPtr)
    SortElement *leftPtr;	/* First list to be merged; may be NULL. */

    SortElement *rightPtr;	/* Second list to be merged; may be NULL. */

    SortInfo *infoPtr;		/* Information needed by the comparison
				 * operator. */
{
    SortElement *headPtr;
    SortElement *tailPtr;
    int cmp;

    if (leftPtr == NULL) {
	return rightPtr;
................................................................................
 *
 *	This procedure is invoked by MergeLists to determine the proper
 *	ordering between two elements.
 *
 * Results:
 *	A negative results means the the first element comes before the
 *	second, and a positive results means that the second element should
 *	come first. A result of zero means the two elements are equal and it
 *	doesn't matter which comes first.
 *
 * Side effects:
 *	None, unless a user-defined comparison command does something weird.
 *
 *----------------------------------------------------------------------
 */

static int
SortCompare(objPtr1, objPtr2, infoPtr)
    Tcl_Obj *objPtr1, *objPtr2;	/* Values to be compared. */
    SortInfo *infoPtr;		/* Information passed from the top-level
				 * "lsort" command. */
{
    int order;

    order = 0;
    if (infoPtr->resultCode != TCL_OK) {
	/*
	 * Once an error has occurred, skip any future comparisons so as to
................................................................................
    } else {
	Tcl_Obj **objv, *paramObjv[2];
	int objc;

	paramObjv[0] = objPtr1;
	paramObjv[1] = objPtr2;

	/*
	 * We made space in the command list for the two things to compare.
	 * Replace them and evaluate the result.
	 */

	Tcl_ListObjLength(infoPtr->interp, infoPtr->compareCmdPtr, &objc);
	Tcl_ListObjReplace(infoPtr->interp, infoPtr->compareCmdPtr, objc - 2,
		2, 2, paramObjv);
	Tcl_ListObjGetElements(infoPtr->interp, infoPtr->compareCmdPtr,
		&objc, &objv);

	infoPtr->resultCode = Tcl_EvalObjv(infoPtr->interp, objc, objv, 0);

	if (infoPtr->resultCode != TCL_OK) {
	    Tcl_AddErrorInfo(infoPtr->interp,
		    "\n    (-compare command)");
	    return order;
	}

	/*
	 * Parse the result of the command.
................................................................................
 
/*
 *----------------------------------------------------------------------
 *
 * DictionaryCompare
 *
 *	This function compares two strings as if they were being used in an
 *	index or card catalog. The case of alphabetic characters is ignored,
 *	except to break ties. Thus "B" comes before "b" but after "a". Also,
 *	integers embedded in the strings compare in numerical order. In other
 *	words, "x10y" comes after "x9y", not * before it as it would when
 *	using strcmp().
 *
 * Results:
 *	A negative result means that the first element comes before the
 *	second, and a positive result means that the second element should
 *	come first. A result of zero means the two elements are equal and it
 *	doesn't matter which comes first.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
DictionaryCompare(left, right)
    char *left, *right;		/* The strings to compare. */
{
    Tcl_UniChar uniLeft, uniRight, uniLeftLower, uniRightLower;
    int diff, zeros;
    int secondaryDiff = 0;

    while (1) {
	if (isdigit(UCHAR(*right))		/* INTL: digit */
		&& isdigit(UCHAR(*left))) {	/* INTL: digit */
	    /*
	     * There are decimal numbers embedded in the two strings. Compare
	     * them as numbers, rather than strings. If one number has more
	     * leading zeros than the other, the number with more leading
	     * zeros sorts later, but only as a secondary choice.
	     */

	    zeros = 0;
	    while ((*right == '0') && (isdigit(UCHAR(right[1])))) {
		right++;
................................................................................
	    }
	    if (secondaryDiff == 0) {
		secondaryDiff = zeros;
	    }

	    /*
	     * The code below compares the numbers in the two strings without
	     * ever converting them to integers. It does this by first
	     * comparing the lengths of the numbers and then comparing the
	     * digit values.
	     */

	    diff = 0;
	    while (1) {
		if (diff == 0) {
................................................................................
		    return -1;
		}
	    }
	    continue;
	}

	/*
	 * Convert character to Unicode for comparison purposes. If either
	 * string is at the terminating null, do a byte-wise comparison and
	 * bail out immediately.
	 */

	if ((*left != '\0') && (*right != '\0')) {
	    left += Tcl_UtfToUniChar(left, &uniLeft);
	    right += Tcl_UtfToUniChar(right, &uniRight);

	    /*
	     * Convert both chars to lower for the comparison, because
	     * dictionary sorts are case insensitve. Covert to lower, not
	     * upper, so chars between Z and a will sort before A (where most
	     * other interesting punctuations occur)
	     */

	    uniLeftLower = Tcl_UniCharToLower(uniLeft);
	    uniRightLower = Tcl_UniCharToLower(uniRight);
	} else {
................................................................................
}
 
/*
 *----------------------------------------------------------------------
 *
 * SelectObjFromSublist --
 *
 *	This procedure is invoked from lsearch and SortCompare. It is used
 *	for implementing the -index option, for the lsort and lsearch
 *	commands.
 *
 * Results:
 *	Returns NULL if a failure occurs, and sets the result in the infoPtr.
 *	Otherwise returns the Tcl_Obj* to the item.
 *
................................................................................
 *	and never passed directly to user code.
 *
 *----------------------------------------------------------------------
 */

static Tcl_Obj*
SelectObjFromSublist(objPtr, infoPtr)
    Tcl_Obj *objPtr;		/* Obj to select sublist from. */
    SortInfo *infoPtr;		/* Information passed from the top-level
				 * "lsearch" or "lsort" command. */

{
    int i;

    /*
     * Quick check for case when no "-index" option is there.
     */

Changes to generic/tclCmdMZ.c.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
..
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
..
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
..
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
..
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
...
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
...
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
...
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
...
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
...
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
...
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
...
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
...
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
...
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
...
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
...
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
...
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
...
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
...
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
...
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
...
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
....
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
....
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
....
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
....
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
....
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
....
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
....
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
....
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
....
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
....
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
....
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
....
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
....
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
....
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
....
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
....
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
....
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
....
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128

2129
2130
2131

2132
2133
2134
2135
2136
2137
2138
....
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
....
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
....
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
....
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
....
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
....
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
....
2870
2871
2872
2873
2874
2875
2876

2877
2878
2879
2880
2881
2882
2883
....
2886
2887
2888
2889
2890
2891
2892

2893
2894
2895
2896
2897
2898
2899
....
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
....
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
/*
 * tclCmdMZ.c --
 *
 *	This file contains the top-level command routines for most of the Tcl
 *	built-in commands whose names begin with the letters M to Z.  It
 *	contains only commands in the generic core (i.e.  those that don't
 *	depend much upon UNIX facilities).
 *
 * Copyright (c) 1987-1993 The Regents of the University of California.
 * Copyright (c) 1994-1997 Sun Microsystems, Inc.
 * Copyright (c) 1998-2000 Scriptics Corporation.
 * Copyright (c) 2002 ActiveState Corporation.
 * Copyright (c) 2003 Donal K. Fellows.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclCmdMZ.c,v 1.115.2.11 2005/08/23 18:28:51 kennykb Exp $
 */

#include "tclInt.h"
#include "tclRegexp.h"

/*
 *----------------------------------------------------------------------
 *
 * Tcl_PwdObjCmd --
 *
 *	This procedure is invoked to process the "pwd" Tcl command.  See the
 *	user documentation for details on what it does.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	See the user documentation.
................................................................................
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
int
Tcl_PwdObjCmd(dummy, interp, objc, objv)
    ClientData dummy;			/* Not used. */
    Tcl_Interp *interp;			/* Current interpreter. */
    int objc;				/* Number of arguments. */
    Tcl_Obj *CONST objv[];		/* Argument objects. */
{
    Tcl_Obj *retVal;

    if (objc != 1) {
	Tcl_WrongNumArgs(interp, 1, objv, NULL);
	return TCL_ERROR;
    }
................................................................................
}
 
/*
 *----------------------------------------------------------------------
 *
 * Tcl_RegexpObjCmd --
 *
 *	This procedure is invoked to process the "regexp" Tcl command.  See
 *	the user documentation for details on what it does.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	See the user documentation.
................................................................................
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
int
Tcl_RegexpObjCmd(dummy, interp, objc, objv)
    ClientData dummy;			/* Not used. */
    Tcl_Interp *interp;			/* Current interpreter. */
    int objc;				/* Number of arguments. */
    Tcl_Obj *CONST objv[];		/* Argument objects. */
{
    int i, indices, match, about, offset, all, doinline, numMatchesSaved;
    int cflags, eflags, stringLength;
    Tcl_RegExp regExpr;
    Tcl_Obj *objPtr, *startIndex = NULL, *resultPtr = NULL;
    Tcl_RegExpInfo info;
    static CONST char *options[] = {
................................................................................
    };
    enum options {
	REGEXP_ALL,	REGEXP_ABOUT,	REGEXP_INDICES,	REGEXP_INLINE,
	REGEXP_EXPANDED,REGEXP_LINE,	REGEXP_LINESTOP,REGEXP_LINEANCHOR,
	REGEXP_NOCASE,	REGEXP_START,	REGEXP_LAST
    };

    indices	= 0;
    about	= 0;
    cflags	= TCL_REG_ADVANCED;
    eflags	= 0;
    offset	= 0;
    all		= 0;
    doinline	= 0;

    for (i = 1; i < objc; i++) {
	char *name;
	int index;

	name = TclGetString(objv[i]);
	if (name[0] != '-') {
................................................................................
	}
	case REGEXP_LAST:
	    i++;
	    goto endOfForLoop;
	}
    }

    endOfForLoop:
    if ((objc - i) < (2 - about)) {
	Tcl_WrongNumArgs(interp, 1, objv,
	    "?switches? exp string ?matchVar? ?subMatchVar subMatchVar ...?");
	goto optionError;
    }
    objc -= i;
    objv += i;
................................................................................
    /*
     * Handle the odd about case separately.
     */

    if (about) {
	regExpr = Tcl_GetRegExpFromObj(interp, objv[0], cflags);
	if ((regExpr == NULL) || (TclRegAbout(interp, regExpr) < 0)) {
	  optionError:
	    if (startIndex) {
		Tcl_DecrRefCount(startIndex);
	    }
	    return TCL_ERROR;
	}
	return TCL_OK;
    }

    /*
     * Get the length of the string that we are matching against so we can do
     * the termination test for -all matches.  Do this before getting the
     * regexp to avoid shimmering problems.
     */

    objPtr = objv[1];
    stringLength = Tcl_GetCharLength(objPtr);

    if (startIndex) {
................................................................................
	 */

	numMatchesSaved = (objc == 0) ? all : objc;
    }

    /*
     * The following loop is to handle multiple matches within the same source
     * string; each iteration handles one match.  If "-all" hasn't been
     * specified then the loop body only gets executed once.  We terminate the
     * loop when the starting offset is past the end of the string.
     */

    while (1) {
	match = Tcl_RegExpExecObj(interp, regExpr, objPtr,
		offset /* offset */, numMatchesSaved, eflags
		| ((offset > 0 &&
		   (Tcl_GetUniChar(objPtr,offset-1) != (Tcl_UniChar)'\n'))
		   ? TCL_REG_NOTBOL : 0));

	if (match < 0) {
	    return TCL_ERROR;
	}

	if (match == 0) {
	    /*
................................................................................

	    if (indices) {
		int start, end;
		Tcl_Obj *objs[2];

		/*
		 * Only adjust the match area if there was a match for that
		 * area.  (Scriptics Bug 4391/SF Bug #219232)
		 */

		if (i <= info.nsubs && info.matches[i].start >= 0) {
		    start = offset + info.matches[i].start;
		    end   = offset + info.matches[i].end;

		    /*
		     * Adjust index so it refers to the last character in the
		     * match instead of the first character after the match.
		     */

		    if (end >= offset) {
			end--;
		    }
		} else {
		    start = -1;
		    end   = -1;
		}

		objs[0] = Tcl_NewLongObj(start);
		objs[1] = Tcl_NewLongObj(end);

		newPtr = Tcl_NewListObj(2, objs);
	    } else {
................................................................................
	if (all == 0) {
	    break;
	}

	/*
	 * Adjust the offset to the character just after the last one in the
	 * matchVar and increment all to count how many times we are making a
	 * match.  We always increment the offset by at least one to prevent
	 * endless looping (as in the case: regexp -all {a*} a).  Otherwise,
	 * when we match the NULL string at the end of the input string, we
	 * will loop indefinately (because the length of the match is 0, so
	 * offset never changes).
	 */

	if (info.matches[0].end == 0) {
	    offset++;
................................................................................
}
 
/*
 *----------------------------------------------------------------------
 *
 * Tcl_RegsubObjCmd --
 *
 *	This procedure is invoked to process the "regsub" Tcl command.  See
 *	the user documentation for details on what it does.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
int
Tcl_RegsubObjCmd(dummy, interp, objc, objv)
    ClientData dummy;			/* Not used. */
    Tcl_Interp *interp;			/* Current interpreter. */
    int objc;				/* Number of arguments. */
    Tcl_Obj *CONST objv[];		/* Argument objects. */
{
    int idx, result, cflags, all, wlen, wsublen, numMatches, offset;
    int start, end, subStart, subEnd, match;
    Tcl_RegExp regExpr;
    Tcl_RegExpInfo info;
    Tcl_Obj *resultPtr, *subPtr, *objPtr, *startIndex = NULL;
    Tcl_UniChar ch, *wsrc, *wfirstChar, *wstring, *wsubspec, *wend;
................................................................................
	}
    }

    if (all && (offset == 0)
	    && (strpbrk(TclGetString(objv[2]), "&\\") == NULL)
	    && (strpbrk(TclGetString(objv[0]), "*+?{}()[].\\|^$") == NULL)) {
	/*
	 * This is a simple one pair string map situation.  We make use of a
	 * slightly modified version of the one pair STR_MAP code.
	 */

	int slen, nocase;
	int (*strCmpFn)_ANSI_ARGS_((CONST Tcl_UniChar *, CONST Tcl_UniChar *,
		unsigned long));
	Tcl_UniChar *p, wsrclc;

	numMatches = 0;
	nocase     = (cflags & TCL_REG_NOCASE);
	strCmpFn   = nocase ? Tcl_UniCharNcasecmp : Tcl_UniCharNcmp;

	wsrc     = Tcl_GetUnicodeFromObj(objv[0], &slen);
	wstring  = Tcl_GetUnicodeFromObj(objv[1], &wlen);
	wsubspec = Tcl_GetUnicodeFromObj(objv[2], &wsublen);
	wend     = wstring + wlen - (slen ? slen - 1 : 0);
	result   = TCL_OK;

	if (slen == 0) {
	    /*
	     * regsub behavior for "" matches between each character.  'string
	     * map' skips the "" case.
	     */

	    if (wstring < wend) {
		resultPtr = Tcl_NewUnicodeObj(wstring, 0);
		Tcl_IncrRefCount(resultPtr);
		for (; wstring < wend; wstring++) {
................................................................................

    regExpr = Tcl_GetRegExpFromObj(interp, objv[0], cflags);
    if (regExpr == NULL) {
	return TCL_ERROR;
    }

    /*
     * Make sure to avoid problems where the objects are shared.  This can
     * cause RegExpObj <> UnicodeObj shimmering that causes data corruption.
     * [Bug #461322]
     */

    if (objv[1] == objv[0]) {
	objPtr = Tcl_DuplicateObj(objv[1]);
    } else {
................................................................................
    wsubspec = Tcl_GetUnicodeFromObj(subPtr, &wsublen);

    result = TCL_OK;

    /*
     * The following loop is to handle multiple matches within the same source
     * string; each iteration handles one match and its corresponding
     * substitution.  If "-all" hasn't been specified then the loop body only
     * gets executed once.  We must use 'offset <= wlen' in particular for the
     * case where the regexp pattern can match the empty string - this is
     * useful when doing, say, 'regsub -- ^ $str ...' when $str might be
     * empty.
     */

    numMatches = 0;
    for ( ; offset <= wlen; ) {
................................................................................
	/*
	 * The flags argument is set if string is part of a larger string, so
	 * that "^" won't match.
	 */

	match = Tcl_RegExpExecObj(interp, regExpr, objPtr, offset,
		10 /* matches */, ((offset > 0 &&
		   (wstring[offset-1] != (Tcl_UniChar)'\n'))
		   ? TCL_REG_NOTBOL : 0));

	if (match < 0) {
	    result = TCL_ERROR;
	    goto done;
	}
	if (match == 0) {
	    break;
................................................................................
	Tcl_RegExpGetInfo(regExpr, &info);
	start = info.matches[0].start;
	end = info.matches[0].end;
	Tcl_AppendUnicodeToObj(resultPtr, wstring + offset, start);

	/*
	 * Append the subSpec argument to the variable, making appropriate
	 * substitutions.  This code is a bit hairy because of the backslash
	 * conventions and because the code saves up ranges of characters in
	 * subSpec to reduce the number of calls to Tcl_SetVar.
	 */

	wsrc = wfirstChar = wsubspec;
	wend = wsubspec + wsublen;
	for (ch = *wsrc; wsrc != wend; wsrc++, ch = *wsrc) {
................................................................................
    }

    /*
     * Copy the portion of the source string after the last match to the
     * result variable.
     */

    regsubDone:
    if (numMatches == 0) {
	/*
	 * On zero matches, just ignore the offset, since it shouldn't matter
	 * to us in this case, and the user may have skewed it.
	 */

	resultPtr = objv[1];
................................................................................
	/*
	 * No varname supplied, so just return the modified string.
	 */

	Tcl_SetObjResult(interp, resultPtr);
    }

    done:
    if (objPtr && (objv[1] == objv[0])) {
	Tcl_DecrRefCount(objPtr);
    }
    if (subPtr && (objv[2] == objv[0])) {
	Tcl_DecrRefCount(subPtr);
    }
    if (resultPtr) {
................................................................................
}
 
/*
 *----------------------------------------------------------------------
 *
 * Tcl_RenameObjCmd --
 *
 *	This procedure is invoked to process the "rename" Tcl command.  See
 *	the user documentation for details on what it does.
 *
 * Results:
 *	A standard Tcl object result.
 *
 * Side effects:
 *	See the user documentation.
 *
................................................................................
}
 
/*
 *----------------------------------------------------------------------
 *
 * Tcl_SourceObjCmd --
 *
 *	This procedure is invoked to process the "source" Tcl command.  See
 *	the user documentation for details on what it does.
 *
 * Results:
 *	A standard Tcl object result.
 *
 * Side effects:
 *	See the user documentation.
 *
................................................................................
}
 
/*
 *----------------------------------------------------------------------
 *
 * Tcl_SplitObjCmd --
 *
 *	This procedure is invoked to process the "split" Tcl command.  See the
 *	user documentation for details on what it does.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	See the user documentation.
................................................................................
	Tcl_HashEntry *hPtr;
	int isNew;

	/*
	 * Handle the special case of splitting on every character.
	 *
	 * Uses a hash table to ensure that each kind of character has only
	 * one Tcl_Obj instance (multiply-referenced) in the final list.  This
	 * is a *major* win when splitting on a long string (especially in the
	 * megabyte range!) - DKF
	 */

	Tcl_InitHashTable(&charReuseTable, TCL_ONE_WORD_KEYS);

	for ( ; stringPtr < end; stringPtr += len) {
................................................................................
	}
	Tcl_DeleteHashTable(&charReuseTable);

    } else if (splitCharLen == 1) {
	char *p;

	/*
	 * Handle the special case of splitting on a single character.  This
	 * is only true for the one-char ASCII case, as one unicode char is >
	 * 1 byte in length.
	 */

	while (*stringPtr && (p=strchr(stringPtr,(int)*splitChars)) != NULL) {
	    objPtr = Tcl_NewStringObj(stringPtr, p - stringPtr);
	    Tcl_ListObjAppendElement(NULL, listPtr, objPtr);
	    stringPtr = p + 1;
	}
................................................................................
	Tcl_ListObjAppendElement(NULL, listPtr, objPtr);
    } else {
	char *element, *p, *splitEnd;
	int splitLen;
	Tcl_UniChar splitChar;

	/*
	 * Normal case: split on any of a given set of characters.  Discard
	 * instances of the split characters.
	 */

	splitEnd = splitChars + splitCharLen;

	for (element = stringPtr; stringPtr < end; stringPtr += len) {
	    len = TclUtfToUniChar(stringPtr, &ch);
................................................................................
}
 
/*
 *----------------------------------------------------------------------
 *
 * Tcl_StringObjCmd --
 *
 *	This procedure is invoked to process the "string" Tcl command.  See
 *	the user documentation for details on what it does.  Note that this
 *	command only functions correctly on properly formed Tcl UTF strings.
 *
 *	Note that the primary methods here (equal, compare, match, ...)  have
 *	bytecode equivalents.  You will find the code for those in
 *	tclExecute.c.  The code here will only be used in the non-bc case
 *	(like in an 'eval').
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	See the user documentation.
 *
................................................................................
	STR_MAP,	STR_MATCH,	STR_RANGE,	STR_REPEAT,
	STR_REPLACE,	STR_TOLOWER,	STR_TOUPPER,	STR_TOTITLE,
	STR_TRIM,	STR_TRIMLEFT,	STR_TRIMRIGHT,
	STR_WORDEND,	STR_WORDSTART
    };

    if (objc < 2) {
        Tcl_WrongNumArgs(interp, 1, objv, "option arg ?arg ...?");
	return TCL_ERROR;
    }

    if (Tcl_GetIndexFromObj(interp, objv[1], options, "option", 0,
	    &index) != TCL_OK) {
	return TCL_ERROR;
    }
................................................................................
	 * Remember to keep code here in some sync with the byte-compiled
	 * versions in tclExecute.c (INST_STR_EQ, INST_STR_NEQ and
	 * INST_STR_CMP as well as the expr string comparison in
	 * INST_EQ/INST_NEQ/INST_LT/...).
	 */

	int i, match, length, nocase = 0, reqlength = -1;
	typedef int (*strCmpFn_t) _ANSI_ARGS_((const char *, const char *,
		unsigned int));
	strCmpFn_t strCmpFn;

	if (objc < 4 || objc > 7) {
	str_cmp_args:
	    Tcl_WrongNumArgs(interp, 2, objv,
		    "?-nocase? ?-length int? string1 string2");
	    return TCL_ERROR;
................................................................................
	    Tcl_SetObjResult(interp,
		    Tcl_NewBooleanObj((enum options) index == STR_EQUAL));
	    break;
	} else if (!nocase && objv[0]->typePtr == &tclByteArrayType &&
		objv[1]->typePtr == &tclByteArrayType) {
	    /*
	     * Use binary versions of comparisons since that won't cause undue
	     * type conversions and it is much faster.  Only do this if we're
	     * case-sensitive (which is all that really makes sense with byte
	     * arrays anyway, and we have no memcasecmp() for some
	     * reason... :^)
	     */

	    string1 = (char*) Tcl_GetByteArrayFromObj(objv[0], &length1);
	    string2 = (char*) Tcl_GetByteArrayFromObj(objv[1], &length2);
	    strCmpFn = (strCmpFn_t) memcmp;
	} else if ((objv[0]->typePtr == &tclStringType)
		&& (objv[1]->typePtr == &tclStringType)) {
	    /*
	     * Do a unicode-specific comparison if both of the args are of
	     * String type.  In benchmark testing this proved the most
	     * efficient check between the unicode and string comparison
	     * operations.
	     */

	    string1 = (char*) Tcl_GetUnicodeFromObj(objv[0], &length1);
	    string2 = (char*) Tcl_GetUnicodeFromObj(objv[1], &length2);
	    strCmpFn = (strCmpFn_t)
		    (nocase ? Tcl_UniCharNcasecmp : Tcl_UniCharNcmp);
	} else {
	    /*
	     * As a catch-all we will work with UTF-8.  We cannot use memcmp()
	     * as that is unsafe with any string containing NULL (\xC0\x80 in
	     * Tcl's utf rep).  We can use the more efficient TclpUtfNcmp2 if
	     * we are case-sensitive and no specific length was requested.
	     */

	    string1 = (char*) Tcl_GetStringFromObj(objv[0], &length1);
	    string2 = (char*) Tcl_GetStringFromObj(objv[1], &length2);
	    if ((reqlength < 0) && !nocase) {
		strCmpFn = (strCmpFn_t) TclpUtfNcmp2;
................................................................................

	ustring1 = Tcl_GetUnicodeFromObj(objv[2], &length1);
	ustring2 = Tcl_GetUnicodeFromObj(objv[3], &length2);

	if (objc == 5) {
	    /*
	     * If a startIndex is specified, we will need to fast forward to
	     * that point in the string before we think about a match
	     */

	    if (TclGetIntForIndex(interp, objv[4], length2 - 1,
		    &start) != TCL_OK) {
		return TCL_ERROR;
	    }
	    if (start >= length2) {
		goto str_first_done;
	    } else if (start > 0) {
		ustring2 += start;
		length2  -= start;
	    } else if (start < 0) {
		/*
		 * Invalid start index mapped to string start; Bug #423581
		 */

		start = 0;
	    }
................................................................................
	if (objc != 4) {
	    Tcl_WrongNumArgs(interp, 2, objv, "string charIndex");
	    return TCL_ERROR;
	}

	/*
	 * If we have a ByteArray object, avoid indexing in the Utf string
	 * since the byte array contains one byte per character.  Otherwise,
	 * use the Unicode string rep to get the index'th char.
	 */

	if (objv[2]->typePtr == &tclByteArrayType) {
	    string1 = (char *) Tcl_GetByteArrayFromObj(objv[2], &length1);

	    if (TclGetIntForIndex(interp, objv[3], length1 - 1,
................................................................................
	char *end;
	Tcl_UniChar ch;

	/*
	 * The UniChar comparison function
	 */

	int (*chcomp)_ANSI_ARGS_((int)) = NULL;
	int i, failat = 0, result = 1, strict = 0;
	Tcl_Obj *objPtr, *failVarObj = NULL;
	Tcl_WideInt w;

	static CONST char *isOptions[] = {
	    "alnum",	   "alpha",	"ascii",	"control",
	    "boolean",	   "digit",	"double",	"false",
................................................................................
	    char *stop;

	    if (TCL_OK == Tcl_GetWideIntFromObj(NULL, objPtr, &w)) {
		break;
	    }

	    /*
	     * Like STR_IS_DOUBLE, but we use strtoll.  Since
	     * Tcl_GetWideIntFromObj already failed, we set result to 0.
	     */

	    result = 0;
	    errno = 0;
	    w = strtoll(string1, &stop, 0);	/* INTL: Tcl source. */
	    if (errno == ERANGE) {
................................................................................
		p = ustring2 + length2 - length1;
	    }
	} else {
	    p = ustring2 + length2 - length1;
	}

	if (length1 > 0) {
	    for (; p >= ustring2;  p--) {
		/*
		 * Scan backwards to find the first character.
		 */

		if ((*p == *ustring1) &&
			(memcmp((char *) ustring1, (char *) p, (size_t)
			    (length1 * sizeof(Tcl_UniChar))) == 0)) {
................................................................................
	}
	Tcl_SetObjResult(interp, Tcl_NewIntObj(length1));
	break;
    case STR_MAP: {
	int mapElemc, nocase = 0, mapWithDict = 0, copySource = 0;
	Tcl_Obj **mapElemv, *sourceObj, *resultPtr;
	Tcl_UniChar *ustring1, *ustring2, *p, *end;
	int (*strCmpFn)_ANSI_ARGS_((CONST Tcl_UniChar *, CONST Tcl_UniChar *,
		unsigned long));

	if (objc < 4 || objc > 5) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?-nocase? charMap string");
	    return TCL_ERROR;
	}

	if (objc == 5) {
................................................................................
	if (objv[objc-2]->typePtr == &tclDictType &&
		objv[objc-2]->bytes == NULL) {
	    int i, done;
	    Tcl_DictSearch search;

	    /*
	     * We know the type exactly, so all dict operations will succeed
	     * for sure.  This shortens this code quite a bit.
	     */

	    Tcl_DictObjSize(interp, objv[objc-2], &mapElemc);
	    if (mapElemc == 0) {
		/*
		 * empty charMap, just return whatever string was given
		 */
................................................................................
		}
	    }
	} else {
	    Tcl_UniChar **mapStrings, *u2lc = NULL;
	    int *mapLens;

	    /*
	     * Precompute pointers to the unicode string and length.  This
	     * saves us repeated function calls later, significantly speeding
	     * up the algorithm.  We only need the lowercase first char in the
	     * nocase case.
	     */

	    mapStrings = (Tcl_UniChar **) ckalloc((mapElemc * 2)
		    * sizeof(Tcl_UniChar *));
	    mapLens = (int *) ckalloc((mapElemc * 2) * sizeof(int));
	    if (nocase) {
................................................................................
	    for (p = ustring1; ustring1 < end; ustring1++) {
		for (index = 0; index < mapElemc; index += 2) {
		    /*
		     * Get the key string to match on.
		     */

		    ustring2 = mapStrings[index];
		    length2  = mapLens[index];
		    if ((length2 > 0) && ((*ustring1 == *ustring2) ||
			    (nocase && (Tcl_UniCharToLower(*ustring1) ==
				    u2lc[index/2]))) &&
			    /* restrict max compare length */
			    ((end - ustring1) >= length2) &&
			    ((length2 == 1) || strCmpFn(ustring2, ustring1,
				    (unsigned long) length2) == 0)) {
................................................................................
	if (objc != 5) {
	    Tcl_WrongNumArgs(interp, 2, objv, "string first last");
	    return TCL_ERROR;
	}

	/*
	 * If we have a ByteArray object, avoid indexing in the Utf string
	 * since the byte array contains one byte per character.  Otherwise,
	 * use the Unicode string rep to get the range.
	 */

	if (objv[2]->typePtr == &tclByteArrayType) {
	    string1 = (char *)Tcl_GetByteArrayFromObj(objv[2], &length1);
	    length1--;
	} else {
................................................................................

	if (count == 1) {
	    Tcl_SetObjResult(interp, objv[2]);
	} else if (count > 1) {
	    string1 = Tcl_GetStringFromObj(objv[2], &length1);
	    if (length1 > 0) {
		/*
		 * Only build up a string that has data.  Instead of building
		 * it up with repeated appends, we just allocate the necessary
		 * space once and copy the string value in.  Check for
		 * overflow with back-division. [Bug #714106]
		 */

		Tcl_Obj *resultPtr;

		length2 = length1 * count;
		if ((length2 / count) != length1) {
		    char buf[TCL_INTEGER_SPACE+1];

		    sprintf(buf, "%d", INT_MAX);
		    Tcl_AppendResult(interp,
			    "string size overflow, must be less than ",
			    buf, (char *) NULL);
		    return TCL_ERROR;
		}

................................................................................
		}
	    }
	}
	if (right) {
	    end = string1;

	    /*
	     * The outer loop iterates over the string.  The inner loop
	     * iterates over the trim characters.  The loops terminate as soon
	     * as a non-trim character is discovered and length1 marks the
	     * last non-trim character.
	     */

	    for (p = string1 + length1; p > end; ) {
		p = Tcl_UtfPrev(p, string1);
		offset = TclUtfToUniChar(p, &ch);
................................................................................
}
 
/*
 *----------------------------------------------------------------------
 *
 * Tcl_SubstObjCmd --
 *
 *	This procedure is invoked to process the "subst" Tcl command.  See the
 *	user documentation for details on what it does.  This command relies
 *	on Tcl_SubstObj() for its implementation.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
int
Tcl_SubstObjCmd(dummy, interp, objc, objv)
    ClientData dummy;			/* Not used. */
    Tcl_Interp *interp;			/* Current interpreter. */
    int objc;				/* Number of arguments. */
    Tcl_Obj *CONST objv[];       	/* Argument objects. */
{
    static CONST char *substOptions[] = {
	"-nobackslashes", "-nocommands", "-novariables", (char *) NULL
    };
    enum substOptions {
	SUBST_NOBACKSLASHES,      SUBST_NOCOMMANDS,       SUBST_NOVARS
    };
    Tcl_Obj *resultPtr;
    int optionIndex, flags, i;

    /*
     * Parse command-line options.
     */
................................................................................
	"-exact", "-glob", "-indexvar", "-matchvar", "-nocase", "-regexp",
	"--", NULL
    };
    enum options {
	OPT_EXACT, OPT_GLOB, OPT_INDEXV, OPT_MATCHV, OPT_NOCASE, OPT_REGEXP,
	OPT_LAST
    };
    typedef int (*strCmpFn_t) _ANSI_ARGS_((const char *, const char *));
    strCmpFn_t strCmpFn = strcmp;

    mode = OPT_EXACT;
    foundmode = 0;
    indexVarObj = NULL;
    matchVarObj = NULL;
    numMatchesSaved = 0;
................................................................................
	    }
	}

	return TCL_ERROR;
    }

    /*
     * Complain if the last body is a continuation.  Note that this check
     * assumes that the list is non-empty!
     */

    if (strcmp(TclGetString(objv[objc-1]), "-") == 0) {
	Tcl_ResetResult(interp);
	Tcl_AppendResult(interp, "no body specified for pattern \"",
		TclGetString(objv[objc-2]), "\"", NULL);
................................................................................

	if ((i == objc - 2) && (*pattern == 'd')
		&& (strcmp(pattern, "default") == 0)) {
	    Tcl_Obj *emptyObj = NULL;

	    /*
	     * If either indexVarObj or matchVarObj are non-NULL, we're in
	     * REGEXP mode but have reached the default clause anyway.  TIP#75
	     * specifies that we set the variables to empty lists (== empty
	     * objects) in that case.
	     */

	    if (indexVarObj != NULL) {
		TclNewObj(emptyObj);
		if (Tcl_ObjSetVar2(interp, indexVarObj, NULL, emptyObj,
................................................................................

	if (indexVarObj != NULL) {
	    if (Tcl_ObjSetVar2(interp, indexVarObj, NULL, indicesObj,
		    TCL_LEAVE_ERR_MSG) == NULL) {
		Tcl_DecrRefCount(indicesObj);

		/*
		 * Careful!  Check to see if we have allocated the list of
		 * matched strings; if so (but there was an error assigning
		 * the indices list) we have a potential memory leak because
		 * the match list has not been written to a variable.  Except
		 * that we'll clean that up right now.
		 */

		if (matchesObj != NULL) {
		    Tcl_DecrRefCount(matchesObj);
		}
		return TCL_ERROR;
................................................................................
  matchFound:
    for (j = i + 1; ; j += 2) {
	if (j >= objc) {
	    /*
	     * This shouldn't happen since we've checked that the last body is
	     * not a continuation...
	     */

	    Tcl_Panic("fall-out when searching for body to match pattern");
	}
	if (strcmp(TclGetString(objv[j]), "-") != 0) {
	    break;
	}
    }

................................................................................
    /*
     * Generate an error message if necessary.
     */

    if (result == TCL_ERROR) {
	Tcl_Obj *msg = Tcl_NewStringObj("\n    (\"", -1);
	Tcl_Obj *errorLine = Tcl_NewIntObj(interp->errorLine);

	Tcl_IncrRefCount(msg);
	Tcl_IncrRefCount(errorLine);
	TclAppendLimitedToObj(msg, pattern, -1, 50, "");
	Tcl_AppendToObj(msg,"\" arm line ", -1);
	Tcl_AppendObjToObj(msg, errorLine);
	Tcl_DecrRefCount(errorLine);
	Tcl_AppendToObj(msg,")", -1);
................................................................................
 
/*
 *----------------------------------------------------------------------
 *
 * Tcl_TimeObjCmd --
 *
 *	This object-based procedure is invoked to process the "time" Tcl
 *	command.  See the user documentation for details on what it does.
 *
 * Results:
 *	A standard Tcl object result.
 *
 * Side effects:
 *	See the user documentation.
 *
................................................................................
}
 
/*
 *----------------------------------------------------------------------
 *
 * Tcl_WhileObjCmd --
 *
 *      This procedure is invoked to process the "while" Tcl command.  See the
 *      user documentation for details on what it does.
 *
 *	With the bytecode compiler, this procedure is only called when a
 *	command name is computed at runtime, and is "while" or the name to
 *	which "while" was renamed: e.g., "set z while; $z {$i<100} {}"
 *
 * Results:
 *      A standard Tcl result.
 *
 * Side effects:
 *      See the user documentation.
 *
 *----------------------------------------------------------------------
 */

        /* ARGSUSED */
int
Tcl_WhileObjCmd(dummy, interp, objc, objv)
    ClientData dummy;                   /* Not used. */
    Tcl_Interp *interp;                 /* Current interpreter. */
    int objc;                           /* Number of arguments. */
    Tcl_Obj *CONST objv[];       	/* Argument objects. */
{
    int result, value;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "test command");
        return TCL_ERROR;
    }

    while (1) {
        result = Tcl_ExprBooleanObj(interp, objv[1], &value);
        if (result != TCL_OK) {
            return result;
        }
        if (!value) {
            break;
        }
        result = Tcl_EvalObjEx(interp, objv[2], 0);
        if ((result != TCL_OK) && (result != TCL_CONTINUE)) {
            if (result == TCL_ERROR) {
                char msg[32 + TCL_INTEGER_SPACE];

                sprintf(msg, "\n    (\"while\" body line %d)",
                        interp->errorLine);
                Tcl_AddErrorInfo(interp, msg);
            }
            break;
        }
    }
    if (result == TCL_BREAK) {
        result = TCL_OK;
    }
    if (result == TCL_OK) {
        Tcl_ResetResult(interp);
    }
    return result;
}
 
/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */



|
|











|




|





|







 







|
|
|
|







 







|







 







|
|
|
|







 







|
|
|
|
|
|
|







 







|







 







|










|







 







|
|







|
|







 







|




|











|







 







|
|







 







|
|













|
|
|
|







 







|




|
<



|
|

|
|

|
|



|







 







|







 







|
|







 







|
|







 







|







 







|







 







|







 







|
|







 







|
|







 







|







 







|







 







|
|
|







 







|







 







|
|
|

|
|
|
|







 







|







 







|
<







 







|












|










|

|







 







|










|







 







|







 







|







 







|







 







|







 







|
<







 







|







 







|

|







 







|







 







|







 







|

|
|



>



>







 







|
|







 







|
|
|













|
|
|
|





|







 







|







 







|







 







|







 







|


|







 







>







 







>







 







|







 







|
|






|


|




|


|
|
|
|





|



|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|


|


|











1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
..
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
..
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
..
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
..
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
...
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
...
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
...
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
...
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
...
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
...
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
...
538
539
540
541
542
543
544
545
546
547
548
549
550

551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
...
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
...
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
...
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
...
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
...
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
...
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
...
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
...
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
...
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
....
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
....
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
....
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
....
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
....
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
....
1164
1165
1166
1167
1168
1169
1170
1171

1172
1173
1174
1175
1176
1177
1178
....
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
....
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
....
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
....
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
....
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
....
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
....
1775
1776
1777
1778
1779
1780
1781
1782

1783
1784
1785
1786
1787
1788
1789
....
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
....
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
....
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
....
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
....
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
....
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
....
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
....
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
....
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
....
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
....
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
....
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
....
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
....
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
....
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
/*
 * tclCmdMZ.c --
 *
 *	This file contains the top-level command routines for most of the Tcl
 *	built-in commands whose names begin with the letters M to Z. It
 *	contains only commands in the generic core (i.e. those that don't
 *	depend much upon UNIX facilities).
 *
 * Copyright (c) 1987-1993 The Regents of the University of California.
 * Copyright (c) 1994-1997 Sun Microsystems, Inc.
 * Copyright (c) 1998-2000 Scriptics Corporation.
 * Copyright (c) 2002 ActiveState Corporation.
 * Copyright (c) 2003 Donal K. Fellows.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclCmdMZ.c,v 1.115.2.12 2005/08/29 18:38:45 dgp Exp $
 */

#include "tclInt.h"
#include "tclRegexp.h"
 
/*
 *----------------------------------------------------------------------
 *
 * Tcl_PwdObjCmd --
 *
 *	This procedure is invoked to process the "pwd" Tcl command. See the
 *	user documentation for details on what it does.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	See the user documentation.
................................................................................
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
int
Tcl_PwdObjCmd(dummy, interp, objc, objv)
    ClientData dummy;		/* Not used. */
    Tcl_Interp *interp;		/* Current interpreter. */
    int objc;			/* Number of arguments. */
    Tcl_Obj *CONST objv[];	/* Argument objects. */
{
    Tcl_Obj *retVal;

    if (objc != 1) {
	Tcl_WrongNumArgs(interp, 1, objv, NULL);
	return TCL_ERROR;
    }
................................................................................
}
 
/*
 *----------------------------------------------------------------------
 *
 * Tcl_RegexpObjCmd --
 *
 *	This procedure is invoked to process the "regexp" Tcl command. See
 *	the user documentation for details on what it does.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	See the user documentation.
................................................................................
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
int
Tcl_RegexpObjCmd(dummy, interp, objc, objv)
    ClientData dummy;		/* Not used. */
    Tcl_Interp *interp;		/* Current interpreter. */
    int objc;			/* Number of arguments. */
    Tcl_Obj *CONST objv[];	/* Argument objects. */
{
    int i, indices, match, about, offset, all, doinline, numMatchesSaved;
    int cflags, eflags, stringLength;
    Tcl_RegExp regExpr;
    Tcl_Obj *objPtr, *startIndex = NULL, *resultPtr = NULL;
    Tcl_RegExpInfo info;
    static CONST char *options[] = {
................................................................................
    };
    enum options {
	REGEXP_ALL,	REGEXP_ABOUT,	REGEXP_INDICES,	REGEXP_INLINE,
	REGEXP_EXPANDED,REGEXP_LINE,	REGEXP_LINESTOP,REGEXP_LINEANCHOR,
	REGEXP_NOCASE,	REGEXP_START,	REGEXP_LAST
    };

    indices = 0;
    about = 0;
    cflags = TCL_REG_ADVANCED;
    eflags = 0;
    offset = 0;
    all = 0;
    doinline = 0;

    for (i = 1; i < objc; i++) {
	char *name;
	int index;

	name = TclGetString(objv[i]);
	if (name[0] != '-') {
................................................................................
	}
	case REGEXP_LAST:
	    i++;
	    goto endOfForLoop;
	}
    }

  endOfForLoop:
    if ((objc - i) < (2 - about)) {
	Tcl_WrongNumArgs(interp, 1, objv,
	    "?switches? exp string ?matchVar? ?subMatchVar subMatchVar ...?");
	goto optionError;
    }
    objc -= i;
    objv += i;
................................................................................
    /*
     * Handle the odd about case separately.
     */

    if (about) {
	regExpr = Tcl_GetRegExpFromObj(interp, objv[0], cflags);
	if ((regExpr == NULL) || (TclRegAbout(interp, regExpr) < 0)) {
	optionError:
	    if (startIndex) {
		Tcl_DecrRefCount(startIndex);
	    }
	    return TCL_ERROR;
	}
	return TCL_OK;
    }

    /*
     * Get the length of the string that we are matching against so we can do
     * the termination test for -all matches. Do this before getting the
     * regexp to avoid shimmering problems.
     */

    objPtr = objv[1];
    stringLength = Tcl_GetCharLength(objPtr);

    if (startIndex) {
................................................................................
	 */

	numMatchesSaved = (objc == 0) ? all : objc;
    }

    /*
     * The following loop is to handle multiple matches within the same source
     * string; each iteration handles one match. If "-all" hasn't been
     * specified then the loop body only gets executed once. We terminate the
     * loop when the starting offset is past the end of the string.
     */

    while (1) {
	match = Tcl_RegExpExecObj(interp, regExpr, objPtr,
		offset /* offset */, numMatchesSaved, eflags
		| ((offset > 0 &&
		(Tcl_GetUniChar(objPtr,offset-1) != (Tcl_UniChar)'\n'))
		? TCL_REG_NOTBOL : 0));

	if (match < 0) {
	    return TCL_ERROR;
	}

	if (match == 0) {
	    /*
................................................................................

	    if (indices) {
		int start, end;
		Tcl_Obj *objs[2];

		/*
		 * Only adjust the match area if there was a match for that
		 * area. (Scriptics Bug 4391/SF Bug #219232)
		 */

		if (i <= info.nsubs && info.matches[i].start >= 0) {
		    start = offset + info.matches[i].start;
		    end = offset + info.matches[i].end;

		    /*
		     * Adjust index so it refers to the last character in the
		     * match instead of the first character after the match.
		     */

		    if (end >= offset) {
			end--;
		    }
		} else {
		    start = -1;
		    end = -1;
		}

		objs[0] = Tcl_NewLongObj(start);
		objs[1] = Tcl_NewLongObj(end);

		newPtr = Tcl_NewListObj(2, objs);
	    } else {
................................................................................
	if (all == 0) {
	    break;
	}

	/*
	 * Adjust the offset to the character just after the last one in the
	 * matchVar and increment all to count how many times we are making a
	 * match. We always increment the offset by at least one to prevent
	 * endless looping (as in the case: regexp -all {a*} a). Otherwise,
	 * when we match the NULL string at the end of the input string, we
	 * will loop indefinately (because the length of the match is 0, so
	 * offset never changes).
	 */

	if (info.matches[0].end == 0) {
	    offset++;
................................................................................
}
 
/*
 *----------------------------------------------------------------------
 *
 * Tcl_RegsubObjCmd --
 *
 *	This procedure is invoked to process the "regsub" Tcl command. See the
 *	user documentation for details on what it does.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
int
Tcl_RegsubObjCmd(dummy, interp, objc, objv)
    ClientData dummy;		/* Not used. */
    Tcl_Interp *interp;		/* Current interpreter. */
    int objc;			/* Number of arguments. */
    Tcl_Obj *CONST objv[];	/* Argument objects. */
{
    int idx, result, cflags, all, wlen, wsublen, numMatches, offset;
    int start, end, subStart, subEnd, match;
    Tcl_RegExp regExpr;
    Tcl_RegExpInfo info;
    Tcl_Obj *resultPtr, *subPtr, *objPtr, *startIndex = NULL;
    Tcl_UniChar ch, *wsrc, *wfirstChar, *wstring, *wsubspec, *wend;
................................................................................
	}
    }

    if (all && (offset == 0)
	    && (strpbrk(TclGetString(objv[2]), "&\\") == NULL)
	    && (strpbrk(TclGetString(objv[0]), "*+?{}()[].\\|^$") == NULL)) {
	/*
	 * This is a simple one pair string map situation. We make use of a
	 * slightly modified version of the one pair STR_MAP code.
	 */

	int slen, nocase;
	int (*strCmpFn)(CONST Tcl_UniChar*, CONST Tcl_UniChar*, unsigned long);

	Tcl_UniChar *p, wsrclc;

	numMatches = 0;
	nocase = (cflags & TCL_REG_NOCASE);
	strCmpFn = nocase ? Tcl_UniCharNcasecmp : Tcl_UniCharNcmp;

	wsrc = Tcl_GetUnicodeFromObj(objv[0], &slen);
	wstring = Tcl_GetUnicodeFromObj(objv[1], &wlen);
	wsubspec = Tcl_GetUnicodeFromObj(objv[2], &wsublen);
	wend = wstring + wlen - (slen ? slen - 1 : 0);
	result = TCL_OK;

	if (slen == 0) {
	    /*
	     * regsub behavior for "" matches between each character. 'string
	     * map' skips the "" case.
	     */

	    if (wstring < wend) {
		resultPtr = Tcl_NewUnicodeObj(wstring, 0);
		Tcl_IncrRefCount(resultPtr);
		for (; wstring < wend; wstring++) {
................................................................................

    regExpr = Tcl_GetRegExpFromObj(interp, objv[0], cflags);
    if (regExpr == NULL) {
	return TCL_ERROR;
    }

    /*
     * Make sure to avoid problems where the objects are shared. This can
     * cause RegExpObj <> UnicodeObj shimmering that causes data corruption.
     * [Bug #461322]
     */

    if (objv[1] == objv[0]) {
	objPtr = Tcl_DuplicateObj(objv[1]);
    } else {
................................................................................
    wsubspec = Tcl_GetUnicodeFromObj(subPtr, &wsublen);

    result = TCL_OK;

    /*
     * The following loop is to handle multiple matches within the same source
     * string; each iteration handles one match and its corresponding
     * substitution. If "-all" hasn't been specified then the loop body only
     * gets executed once. We must use 'offset <= wlen' in particular for the
     * case where the regexp pattern can match the empty string - this is
     * useful when doing, say, 'regsub -- ^ $str ...' when $str might be
     * empty.
     */

    numMatches = 0;
    for ( ; offset <= wlen; ) {
................................................................................
	/*
	 * The flags argument is set if string is part of a larger string, so
	 * that "^" won't match.
	 */

	match = Tcl_RegExpExecObj(interp, regExpr, objPtr, offset,
		10 /* matches */, ((offset > 0 &&
		(wstring[offset-1] != (Tcl_UniChar)'\n'))
		? TCL_REG_NOTBOL : 0));

	if (match < 0) {
	    result = TCL_ERROR;
	    goto done;
	}
	if (match == 0) {
	    break;
................................................................................
	Tcl_RegExpGetInfo(regExpr, &info);
	start = info.matches[0].start;
	end = info.matches[0].end;
	Tcl_AppendUnicodeToObj(resultPtr, wstring + offset, start);

	/*
	 * Append the subSpec argument to the variable, making appropriate
	 * substitutions. This code is a bit hairy because of the backslash
	 * conventions and because the code saves up ranges of characters in
	 * subSpec to reduce the number of calls to Tcl_SetVar.
	 */

	wsrc = wfirstChar = wsubspec;
	wend = wsubspec + wsublen;
	for (ch = *wsrc; wsrc != wend; wsrc++, ch = *wsrc) {
................................................................................
    }

    /*
     * Copy the portion of the source string after the last match to the
     * result variable.
     */

  regsubDone:
    if (numMatches == 0) {
	/*
	 * On zero matches, just ignore the offset, since it shouldn't matter
	 * to us in this case, and the user may have skewed it.
	 */

	resultPtr = objv[1];
................................................................................
	/*
	 * No varname supplied, so just return the modified string.
	 */

	Tcl_SetObjResult(interp, resultPtr);
    }

  done:
    if (objPtr && (objv[1] == objv[0])) {
	Tcl_DecrRefCount(objPtr);
    }
    if (subPtr && (objv[2] == objv[0])) {
	Tcl_DecrRefCount(subPtr);
    }
    if (resultPtr) {
................................................................................
}
 
/*
 *----------------------------------------------------------------------
 *
 * Tcl_RenameObjCmd --
 *
 *	This procedure is invoked to process the "rename" Tcl command. See the
 *	user documentation for details on what it does.
 *
 * Results:
 *	A standard Tcl object result.
 *
 * Side effects:
 *	See the user documentation.
 *
................................................................................
}
 
/*
 *----------------------------------------------------------------------
 *
 * Tcl_SourceObjCmd --
 *
 *	This procedure is invoked to process the "source" Tcl command. See the
 *	user documentation for details on what it does.
 *
 * Results:
 *	A standard Tcl object result.
 *
 * Side effects:
 *	See the user documentation.
 *
................................................................................
}
 
/*
 *----------------------------------------------------------------------
 *
 * Tcl_SplitObjCmd --
 *
 *	This procedure is invoked to process the "split" Tcl command. See the
 *	user documentation for details on what it does.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	See the user documentation.
................................................................................
	Tcl_HashEntry *hPtr;
	int isNew;

	/*
	 * Handle the special case of splitting on every character.
	 *
	 * Uses a hash table to ensure that each kind of character has only
	 * one Tcl_Obj instance (multiply-referenced) in the final list. This
	 * is a *major* win when splitting on a long string (especially in the
	 * megabyte range!) - DKF
	 */

	Tcl_InitHashTable(&charReuseTable, TCL_ONE_WORD_KEYS);

	for ( ; stringPtr < end; stringPtr += len) {
................................................................................
	}
	Tcl_DeleteHashTable(&charReuseTable);

    } else if (splitCharLen == 1) {
	char *p;

	/*
	 * Handle the special case of splitting on a single character. This is
	 * only true for the one-char ASCII case, as one unicode char is > 1
	 * byte in length.
	 */

	while (*stringPtr && (p=strchr(stringPtr,(int)*splitChars)) != NULL) {
	    objPtr = Tcl_NewStringObj(stringPtr, p - stringPtr);
	    Tcl_ListObjAppendElement(NULL, listPtr, objPtr);
	    stringPtr = p + 1;
	}
................................................................................
	Tcl_ListObjAppendElement(NULL, listPtr, objPtr);
    } else {
	char *element, *p, *splitEnd;
	int splitLen;
	Tcl_UniChar splitChar;

	/*
	 * Normal case: split on any of a given set of characters. Discard
	 * instances of the split characters.
	 */

	splitEnd = splitChars + splitCharLen;

	for (element = stringPtr; stringPtr < end; stringPtr += len) {
	    len = TclUtfToUniChar(stringPtr, &ch);
................................................................................
}
 
/*
 *----------------------------------------------------------------------
 *
 * Tcl_StringObjCmd --
 *
 *	This procedure is invoked to process the "string" Tcl command. See the
 *	user documentation for details on what it does. Note that this command
 *	only functions correctly on properly formed Tcl UTF strings.
 *
 *	Note that the primary methods here (equal, compare, match, ...) have
 *	bytecode equivalents. You will find the code for those in
 *	tclExecute.c. The code here will only be used in the non-bc case (like
 *	in an 'eval').
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	See the user documentation.
 *
................................................................................
	STR_MAP,	STR_MATCH,	STR_RANGE,	STR_REPEAT,
	STR_REPLACE,	STR_TOLOWER,	STR_TOUPPER,	STR_TOTITLE,
	STR_TRIM,	STR_TRIMLEFT,	STR_TRIMRIGHT,
	STR_WORDEND,	STR_WORDSTART
    };

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "option arg ?arg ...?");
	return TCL_ERROR;
    }

    if (Tcl_GetIndexFromObj(interp, objv[1], options, "option", 0,
	    &index) != TCL_OK) {
	return TCL_ERROR;
    }
................................................................................
	 * Remember to keep code here in some sync with the byte-compiled
	 * versions in tclExecute.c (INST_STR_EQ, INST_STR_NEQ and
	 * INST_STR_CMP as well as the expr string comparison in
	 * INST_EQ/INST_NEQ/INST_LT/...).
	 */

	int i, match, length, nocase = 0, reqlength = -1;
	typedef int (*strCmpFn_t)(const char *, const char *, unsigned int);

	strCmpFn_t strCmpFn;

	if (objc < 4 || objc > 7) {
	str_cmp_args:
	    Tcl_WrongNumArgs(interp, 2, objv,
		    "?-nocase? ?-length int? string1 string2");
	    return TCL_ERROR;
................................................................................
	    Tcl_SetObjResult(interp,
		    Tcl_NewBooleanObj((enum options) index == STR_EQUAL));
	    break;
	} else if (!nocase && objv[0]->typePtr == &tclByteArrayType &&
		objv[1]->typePtr == &tclByteArrayType) {
	    /*
	     * Use binary versions of comparisons since that won't cause undue
	     * type conversions and it is much faster. Only do this if we're
	     * case-sensitive (which is all that really makes sense with byte
	     * arrays anyway, and we have no memcasecmp() for some
	     * reason... :^)
	     */

	    string1 = (char*) Tcl_GetByteArrayFromObj(objv[0], &length1);
	    string2 = (char*) Tcl_GetByteArrayFromObj(objv[1], &length2);
	    strCmpFn = (strCmpFn_t) memcmp;
	} else if ((objv[0]->typePtr == &tclStringType)
		&& (objv[1]->typePtr == &tclStringType)) {
	    /*
	     * Do a unicode-specific comparison if both of the args are of
	     * String type. In benchmark testing this proved the most
	     * efficient check between the unicode and string comparison
	     * operations.
	     */

	    string1 = (char*) Tcl_GetUnicodeFromObj(objv[0], &length1);
	    string2 = (char*) Tcl_GetUnicodeFromObj(objv[1], &length2);
	    strCmpFn = (strCmpFn_t)
		    (nocase ? Tcl_UniCharNcasecmp : Tcl_UniCharNcmp);
	} else {
	    /*
	     * As a catch-all we will work with UTF-8. We cannot use memcmp()
	     * as that is unsafe with any string containing NULL (\xC0\x80 in
	     * Tcl's utf rep). We can use the more efficient TclpUtfNcmp2 if
	     * we are case-sensitive and no specific length was requested.
	     */

	    string1 = (char*) Tcl_GetStringFromObj(objv[0], &length1);
	    string2 = (char*) Tcl_GetStringFromObj(objv[1], &length2);
	    if ((reqlength < 0) && !nocase) {
		strCmpFn = (strCmpFn_t) TclpUtfNcmp2;
................................................................................

	ustring1 = Tcl_GetUnicodeFromObj(objv[2], &length1);
	ustring2 = Tcl_GetUnicodeFromObj(objv[3], &length2);

	if (objc == 5) {
	    /*
	     * If a startIndex is specified, we will need to fast forward to
	     * that point in the string before we think about a match.
	     */

	    if (TclGetIntForIndex(interp, objv[4], length2 - 1,
		    &start) != TCL_OK) {
		return TCL_ERROR;
	    }
	    if (start >= length2) {
		goto str_first_done;
	    } else if (start > 0) {
		ustring2 += start;
		length2 -= start;
	    } else if (start < 0) {
		/*
		 * Invalid start index mapped to string start; Bug #423581
		 */

		start = 0;
	    }
................................................................................
	if (objc != 4) {
	    Tcl_WrongNumArgs(interp, 2, objv, "string charIndex");
	    return TCL_ERROR;
	}

	/*
	 * If we have a ByteArray object, avoid indexing in the Utf string
	 * since the byte array contains one byte per character. Otherwise,
	 * use the Unicode string rep to get the index'th char.
	 */

	if (objv[2]->typePtr == &tclByteArrayType) {
	    string1 = (char *) Tcl_GetByteArrayFromObj(objv[2], &length1);

	    if (TclGetIntForIndex(interp, objv[3], length1 - 1,
................................................................................
	char *end;
	Tcl_UniChar ch;

	/*
	 * The UniChar comparison function
	 */

	int (*chcomp)(int) = NULL;
	int i, failat = 0, result = 1, strict = 0;
	Tcl_Obj *objPtr, *failVarObj = NULL;
	Tcl_WideInt w;

	static CONST char *isOptions[] = {
	    "alnum",	   "alpha",	"ascii",	"control",
	    "boolean",	   "digit",	"double",	"false",
................................................................................
	    char *stop;

	    if (TCL_OK == Tcl_GetWideIntFromObj(NULL, objPtr, &w)) {
		break;
	    }

	    /*
	     * Like STR_IS_DOUBLE, but we use strtoll. Since
	     * Tcl_GetWideIntFromObj already failed, we set result to 0.
	     */

	    result = 0;
	    errno = 0;
	    w = strtoll(string1, &stop, 0);	/* INTL: Tcl source. */
	    if (errno == ERANGE) {
................................................................................
		p = ustring2 + length2 - length1;
	    }
	} else {
	    p = ustring2 + length2 - length1;
	}

	if (length1 > 0) {
	    for (; p >= ustring2; p--) {
		/*
		 * Scan backwards to find the first character.
		 */

		if ((*p == *ustring1) &&
			(memcmp((char *) ustring1, (char *) p, (size_t)
			    (length1 * sizeof(Tcl_UniChar))) == 0)) {
................................................................................
	}
	Tcl_SetObjResult(interp, Tcl_NewIntObj(length1));
	break;
    case STR_MAP: {
	int mapElemc, nocase = 0, mapWithDict = 0, copySource = 0;
	Tcl_Obj **mapElemv, *sourceObj, *resultPtr;
	Tcl_UniChar *ustring1, *ustring2, *p, *end;
	int (*strCmpFn)(CONST Tcl_UniChar*, CONST Tcl_UniChar*, unsigned long);


	if (objc < 4 || objc > 5) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?-nocase? charMap string");
	    return TCL_ERROR;
	}

	if (objc == 5) {
................................................................................
	if (objv[objc-2]->typePtr == &tclDictType &&
		objv[objc-2]->bytes == NULL) {
	    int i, done;
	    Tcl_DictSearch search;

	    /*
	     * We know the type exactly, so all dict operations will succeed
	     * for sure. This shortens this code quite a bit.
	     */

	    Tcl_DictObjSize(interp, objv[objc-2], &mapElemc);
	    if (mapElemc == 0) {
		/*
		 * empty charMap, just return whatever string was given
		 */
................................................................................
		}
	    }
	} else {
	    Tcl_UniChar **mapStrings, *u2lc = NULL;
	    int *mapLens;

	    /*
	     * Precompute pointers to the unicode string and length. This
	     * saves us repeated function calls later, significantly speeding
	     * up the algorithm. We only need the lowercase first char in the
	     * nocase case.
	     */

	    mapStrings = (Tcl_UniChar **) ckalloc((mapElemc * 2)
		    * sizeof(Tcl_UniChar *));
	    mapLens = (int *) ckalloc((mapElemc * 2) * sizeof(int));
	    if (nocase) {
................................................................................
	    for (p = ustring1; ustring1 < end; ustring1++) {
		for (index = 0; index < mapElemc; index += 2) {
		    /*
		     * Get the key string to match on.
		     */

		    ustring2 = mapStrings[index];
		    length2 = mapLens[index];
		    if ((length2 > 0) && ((*ustring1 == *ustring2) ||
			    (nocase && (Tcl_UniCharToLower(*ustring1) ==
				    u2lc[index/2]))) &&
			    /* restrict max compare length */
			    ((end - ustring1) >= length2) &&
			    ((length2 == 1) || strCmpFn(ustring2, ustring1,
				    (unsigned long) length2) == 0)) {
................................................................................
	if (objc != 5) {
	    Tcl_WrongNumArgs(interp, 2, objv, "string first last");
	    return TCL_ERROR;
	}

	/*
	 * If we have a ByteArray object, avoid indexing in the Utf string
	 * since the byte array contains one byte per character. Otherwise,
	 * use the Unicode string rep to get the range.
	 */

	if (objv[2]->typePtr == &tclByteArrayType) {
	    string1 = (char *)Tcl_GetByteArrayFromObj(objv[2], &length1);
	    length1--;
	} else {
................................................................................

	if (count == 1) {
	    Tcl_SetObjResult(interp, objv[2]);
	} else if (count > 1) {
	    string1 = Tcl_GetStringFromObj(objv[2], &length1);
	    if (length1 > 0) {
		/*
		 * Only build up a string that has data. Instead of building
		 * it up with repeated appends, we just allocate the necessary
		 * space once and copy the string value in. Check for overflow
		 * with back-division. [Bug #714106]
		 */

		Tcl_Obj *resultPtr;

		length2 = length1 * count;
		if ((length2 / count) != length1) {
		    char buf[TCL_INTEGER_SPACE+1];

		    sprintf(buf, "%d", INT_MAX);
		    Tcl_AppendResult(interp,
			    "string size overflow, must be less than ",
			    buf, (char *) NULL);
		    return TCL_ERROR;
		}

................................................................................
		}
	    }
	}
	if (right) {
	    end = string1;

	    /*
	     * The outer loop iterates over the string. The inner loop
	     * iterates over the trim characters. The loops terminate as soon
	     * as a non-trim character is discovered and length1 marks the
	     * last non-trim character.
	     */

	    for (p = string1 + length1; p > end; ) {
		p = Tcl_UtfPrev(p, string1);
		offset = TclUtfToUniChar(p, &ch);
................................................................................
}
 
/*
 *----------------------------------------------------------------------
 *
 * Tcl_SubstObjCmd --
 *
 *	This procedure is invoked to process the "subst" Tcl command. See the
 *	user documentation for details on what it does. This command relies on
 *	Tcl_SubstObj() for its implementation.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
int
Tcl_SubstObjCmd(dummy, interp, objc, objv)
    ClientData dummy;		/* Not used. */
    Tcl_Interp *interp;		/* Current interpreter. */
    int objc;			/* Number of arguments. */
    Tcl_Obj *CONST objv[];	/* Argument objects. */
{
    static CONST char *substOptions[] = {
	"-nobackslashes", "-nocommands", "-novariables", (char *) NULL
    };
    enum substOptions {
	SUBST_NOBACKSLASHES, SUBST_NOCOMMANDS, SUBST_NOVARS
    };
    Tcl_Obj *resultPtr;
    int optionIndex, flags, i;

    /*
     * Parse command-line options.
     */
................................................................................
	"-exact", "-glob", "-indexvar", "-matchvar", "-nocase", "-regexp",
	"--", NULL
    };
    enum options {
	OPT_EXACT, OPT_GLOB, OPT_INDEXV, OPT_MATCHV, OPT_NOCASE, OPT_REGEXP,
	OPT_LAST
    };
    typedef int (*strCmpFn_t)(const char *, const char *);
    strCmpFn_t strCmpFn = strcmp;

    mode = OPT_EXACT;
    foundmode = 0;
    indexVarObj = NULL;
    matchVarObj = NULL;
    numMatchesSaved = 0;
................................................................................
	    }
	}

	return TCL_ERROR;
    }

    /*
     * Complain if the last body is a continuation. Note that this check
     * assumes that the list is non-empty!
     */

    if (strcmp(TclGetString(objv[objc-1]), "-") == 0) {
	Tcl_ResetResult(interp);
	Tcl_AppendResult(interp, "no body specified for pattern \"",
		TclGetString(objv[objc-2]), "\"", NULL);
................................................................................

	if ((i == objc - 2) && (*pattern == 'd')
		&& (strcmp(pattern, "default") == 0)) {
	    Tcl_Obj *emptyObj = NULL;

	    /*
	     * If either indexVarObj or matchVarObj are non-NULL, we're in
	     * REGEXP mode but have reached the default clause anyway. TIP#75
	     * specifies that we set the variables to empty lists (== empty
	     * objects) in that case.
	     */

	    if (indexVarObj != NULL) {
		TclNewObj(emptyObj);
		if (Tcl_ObjSetVar2(interp, indexVarObj, NULL, emptyObj,
................................................................................

	if (indexVarObj != NULL) {
	    if (Tcl_ObjSetVar2(interp, indexVarObj, NULL, indicesObj,
		    TCL_LEAVE_ERR_MSG) == NULL) {
		Tcl_DecrRefCount(indicesObj);

		/*
		 * Careful! Check to see if we have allocated the list of
		 * matched strings; if so (but there was an error assigning
		 * the indices list) we have a potential memory leak because
		 * the match list has not been written to a variable. Except
		 * that we'll clean that up right now.
		 */

		if (matchesObj != NULL) {
		    Tcl_DecrRefCount(matchesObj);
		}
		return TCL_ERROR;
................................................................................
  matchFound:
    for (j = i + 1; ; j += 2) {
	if (j >= objc) {
	    /*
	     * This shouldn't happen since we've checked that the last body is
	     * not a continuation...
	     */

	    Tcl_Panic("fall-out when searching for body to match pattern");
	}
	if (strcmp(TclGetString(objv[j]), "-") != 0) {
	    break;
	}
    }

................................................................................
    /*
     * Generate an error message if necessary.
     */

    if (result == TCL_ERROR) {
	Tcl_Obj *msg = Tcl_NewStringObj("\n    (\"", -1);
	Tcl_Obj *errorLine = Tcl_NewIntObj(interp->errorLine);

	Tcl_IncrRefCount(msg);
	Tcl_IncrRefCount(errorLine);
	TclAppendLimitedToObj(msg, pattern, -1, 50, "");
	Tcl_AppendToObj(msg,"\" arm line ", -1);
	Tcl_AppendObjToObj(msg, errorLine);
	Tcl_DecrRefCount(errorLine);
	Tcl_AppendToObj(msg,")", -1);
................................................................................
 
/*
 *----------------------------------------------------------------------
 *
 * Tcl_TimeObjCmd --
 *
 *	This object-based procedure is invoked to process the "time" Tcl
 *	command. See the user documentation for details on what it does.
 *
 * Results:
 *	A standard Tcl object result.
 *
 * Side effects:
 *	See the user documentation.
 *
................................................................................
}
 
/*
 *----------------------------------------------------------------------
 *
 * Tcl_WhileObjCmd --
 *
 *	This procedure is invoked to process the "while" Tcl command. See the
 *	user documentation for details on what it does.
 *
 *	With the bytecode compiler, this procedure is only called when a
 *	command name is computed at runtime, and is "while" or the name to
 *	which "while" was renamed: e.g., "set z while; $z {$i<100} {}"
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
int
Tcl_WhileObjCmd(dummy, interp, objc, objv)
    ClientData dummy;		/* Not used. */
    Tcl_Interp *interp;		/* Current interpreter. */
    int objc;			/* Number of arguments. */
    Tcl_Obj *CONST objv[];	/* Argument objects. */
{
    int result, value;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "test command");
	return TCL_ERROR;
    }

    while (1) {
	result = Tcl_ExprBooleanObj(interp, objv[1], &value);
	if (result != TCL_OK) {
	    return result;
	}
	if (!value) {
	    break;
	}
	result = Tcl_EvalObjEx(interp, objv[2], 0);
	if ((result != TCL_OK) && (result != TCL_CONTINUE)) {
	    if (result == TCL_ERROR) {
		char msg[32 + TCL_INTEGER_SPACE];

		sprintf(msg, "\n    (\"while\" body line %d)",
			interp->errorLine);
		Tcl_AddErrorInfo(interp, msg);
	    }
	    break;
	}
    }
    if (result == TCL_BREAK) {
	result = TCL_OK;
    }
    if (result == TCL_OK) {
	Tcl_ResetResult(interp);
    }
    return result;
}
 
/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */

Changes to generic/tclIO.c.

6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
...
133
134
135
136
137
138
139





140
141
142
143
144
145
146
....
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
....
1264
1265
1266
1267
1268
1269
1270

1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
....
1384
1385
1386
1387
1388
1389
1390
















1391
1392
1393
1394
1395
1396
1397
....
1414
1415
1416
1417
1418
1419
1420

1421
1422
1423
1424
1425
1426
1427
....
1494
1495
1496
1497
1498
1499
1500

















1501
1502
1503
1504
1505
1506
1507
....
1548
1549
1550
1551
1552
1553
1554






1555
1556
1557
1558
1559
1560
1561
....
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
....
2418
2419
2420
2421
2422
2423
2424

2425
2426
2427
2428
2429
2430
2431
....
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
....
2480
2481
2482
2483
2484
2485
2486
2487















2488



































2489
2490
2491

2492
2493
2494
2495
2496
2497
2498
....
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
....
2538
2539
2540
2541
2542
2543
2544








































2545
2546
2547
2548
2549
2550
2551
 *
 * Copyright (c) 1998-2000 Ajuba Solutions
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclIO.c,v 1.81.2.8 2005/08/25 15:46:31 dgp Exp $
 */

#include "tclInt.h"
#include "tclIO.h"
#include <assert.h>

/*
................................................................................
			    int *dstLenPtr, int *srcLenPtr));
static void		UpdateInterest _ANSI_ARGS_((Channel *chanPtr));
static int		WriteBytes _ANSI_ARGS_((Channel *chanPtr,
			    CONST char *src, int srcLen));
static int		WriteChars _ANSI_ARGS_((Channel *chanPtr,
			    CONST char *src, int srcLen));
static Tcl_Obj*         FixLevelCode _ANSI_ARGS_ ((Tcl_Obj* msg));





 
/*
 *---------------------------------------------------------------------------
 *
 * TclInitIOSubsystem --
 *
 *	Initialize all resources used by this subsystem on a per-process
................................................................................
     * NOTE: All drivers using thread actions now have to perform their TSD
     *	     manipulation only in their thread action proc. Doing it when
     *	     creating their instance structures will collide with the thread
     *	     action activity and lead to damaged lists.
     */

    statePtr->nextCSPtr = (ChannelState *) NULL;
    Tcl_SpliceChannel ((Tcl_Channel) chanPtr);

    /*
     * Install this channel in the first empty standard channel slot, if the
     * channel was previously closed explicitly.
     */

    if ((tsdPtr->stdinChannel == NULL) && (tsdPtr->stdinInitialized == 1)) {
................................................................................
    int mask;			/* TCL_READABLE & TCL_WRITABLE to indicate if
				 * the channel is readable, writable. */
    Tcl_Channel prevChan;	/* The channel structure to replace */
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    Channel *chanPtr, *prevChanPtr;
    ChannelState *statePtr;


    /*
     * Find the given channel in the list of all channels.  If we don't find
     * it, then it was never registered correctly.
     *
     * This operation should occur at the top of a channel stack.
     */

    statePtr = (ChannelState *) tsdPtr->firstCSPtr;
    prevChanPtr = ((Channel *) prevChan)->state->topChanPtr;
................................................................................
    /*
     * Place new block at the head of a possibly existing list of previously
     * stacked channels.
     */

    prevChanPtr->upChanPtr	= chanPtr;
    statePtr->topChanPtr	= chanPtr;

















    return (Tcl_Channel) chanPtr;
}
 
/*
 *----------------------------------------------------------------------
 *
................................................................................
Tcl_UnstackChannel(interp, chan)
    Tcl_Interp *interp; /* The interpreter we are working in */
    Tcl_Channel chan;   /* The channel to unstack */
{
    Channel *chanPtr = (Channel *) chan;
    ChannelState *statePtr = chanPtr->state;
    int result = 0;


    /*
     * This operation should occur at the top of a channel stack.
     */

    chanPtr = statePtr->topChanPtr;

................................................................................
	    }

	    chanPtr->inQueueHead = (ChannelBuffer *) NULL;
	    chanPtr->inQueueTail = (ChannelBuffer *) NULL;

	    DiscardInputQueued(statePtr, 0);
	}


















	statePtr->topChanPtr = downChanPtr;
	downChanPtr->upChanPtr = (Channel *) NULL;

	/*
	 * Leave this link intact for closeproc
	 *  chanPtr->downChanPtr = (Channel *) NULL;
................................................................................
		/* TIP #219, Tcl Channel Reflection API.
		 * "TclChanCaughtErrorBypass" is not required here, it was
		 * done already by "Tcl_Close".
		 */
		return TCL_ERROR;
	    }
	}






    }

    return TCL_OK;
}
 
/*
 *----------------------------------------------------------------------
................................................................................
	statePtr->chanMsg = NULL;
    }

    /*
     * Remove this channel from of the list of all channels.
     */

    Tcl_CutChannel((Tcl_Channel) chanPtr);

    /*
     * Close and free the channel driver state.
     * This may leave a TIP #219 error message in the interp.
     */

    if (chanPtr->typePtr->closeProc != TCL_CLOSE2PROC) {
................................................................................
    return errorCode;
}
 
/*
 *----------------------------------------------------------------------
 *
 * Tcl_CutChannel --

 *
 *	Removes a channel from the (thread-)global list of all channels (in
 *	that thread).  This is actually the statePtr for the stack of channel.
 *
 * Results:
 *	Nothing.
 *
................................................................................
 *	the refcount) because the caller usually wants fiddle with the channel
 *	(like transfering it to a different thread) and thus keeps the
 *	refcount artifically high to prevent its destruction.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_CutChannel(chan)
    Tcl_Channel chan;			/* The channel being removed. Must
					 * not be referenced in any
					 * interpreter. */
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    ChannelState *prevCSPtr;		/* Preceding channel state in list of
					 * all states - used to splice a
................................................................................
    /* TIP #218, Channel Thread Actions */
    threadActionProc = Tcl_ChannelThreadActionProc(Tcl_GetChannelType(chan));
    if (threadActionProc != NULL) {
	(*threadActionProc) (Tcl_GetChannelInstanceData(chan),
		TCL_CHANNEL_THREAD_REMOVE);
    }
}
 















/*



































 *----------------------------------------------------------------------
 *
 * Tcl_SpliceChannel --

 *
 *	Adds a channel to the (thread-)global list of all channels (in that
 *	thread). Expects that the field 'nextChanPtr' in the channel is set to
 *	NULL.
 *
 * Results:
 *	Nothing.
................................................................................
 *	the refcount) because the caller usually wants figgle with the channel
 *	(like transfering it to a different thread) and thus keeps the
 *	refcount artifically high to prevent its destruction.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_SpliceChannel(chan)
    Tcl_Channel chan;			/* The channel being added. Must not
					 * be referenced in any
					 * interpreter. */
{
    ThreadSpecificData	*tsdPtr = TCL_TSD_INIT(&dataKey);
    ChannelState	*statePtr = ((Channel *) chan)->state;
    Tcl_DriverThreadActionProc *threadActionProc;

    if (statePtr->nextCSPtr != (ChannelState *) NULL) {
	Tcl_Panic("Tcl_SpliceChannel: trying to add channel used in different list");
    }

    statePtr->nextCSPtr = tsdPtr->firstCSPtr;
    tsdPtr->firstCSPtr = statePtr;

    /*
     * TIP #10. Mark the current thread as the new one managing this channel.
................................................................................
    /* TIP #218, Channel Thread Actions */
    threadActionProc = Tcl_ChannelThreadActionProc(Tcl_GetChannelType(chan));
    if (threadActionProc != NULL) {
	(*threadActionProc) (Tcl_GetChannelInstanceData(chan),
		TCL_CHANNEL_THREAD_INSERT);
    }
}








































 
/*
 *----------------------------------------------------------------------
 *
 * Tcl_Close --
 *
 *	Closes a channel.






|







 







>
>
>
>
>







 







|







 







>


|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>
>
>
>
>
>







 







|







 







>







 







|
|







 







|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



>







 







|
|









|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
...
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
....
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
....
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
....
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
....
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
....
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
....
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
....
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
....
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
....
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
....
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
....
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
....
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
 *
 * Copyright (c) 1998-2000 Ajuba Solutions
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclIO.c,v 1.81.2.9 2005/08/29 18:38:45 dgp Exp $
 */

#include "tclInt.h"
#include "tclIO.h"
#include <assert.h>

/*
................................................................................
			    int *dstLenPtr, int *srcLenPtr));
static void		UpdateInterest _ANSI_ARGS_((Channel *chanPtr));
static int		WriteBytes _ANSI_ARGS_((Channel *chanPtr,
			    CONST char *src, int srcLen));
static int		WriteChars _ANSI_ARGS_((Channel *chanPtr,
			    CONST char *src, int srcLen));
static Tcl_Obj*         FixLevelCode _ANSI_ARGS_ ((Tcl_Obj* msg));


static void SpliceChannel _ANSI_ARGS_ ((Tcl_Channel chan));
static void CutChannel    _ANSI_ARGS_ ((Tcl_Channel chan));

 
/*
 *---------------------------------------------------------------------------
 *
 * TclInitIOSubsystem --
 *
 *	Initialize all resources used by this subsystem on a per-process
................................................................................
     * NOTE: All drivers using thread actions now have to perform their TSD
     *	     manipulation only in their thread action proc. Doing it when
     *	     creating their instance structures will collide with the thread
     *	     action activity and lead to damaged lists.
     */

    statePtr->nextCSPtr = (ChannelState *) NULL;
    SpliceChannel ((Tcl_Channel) chanPtr);

    /*
     * Install this channel in the first empty standard channel slot, if the
     * channel was previously closed explicitly.
     */

    if ((tsdPtr->stdinChannel == NULL) && (tsdPtr->stdinInitialized == 1)) {
................................................................................
    int mask;			/* TCL_READABLE & TCL_WRITABLE to indicate if
				 * the channel is readable, writable. */
    Tcl_Channel prevChan;	/* The channel structure to replace */
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    Channel *chanPtr, *prevChanPtr;
    ChannelState *statePtr;
    Tcl_DriverThreadActionProc *threadActionProc;

    /*
     * Find the given channel (prevChan) in the list of all channels.  If we don't find
     * it, then it was never registered correctly.
     *
     * This operation should occur at the top of a channel stack.
     */

    statePtr = (ChannelState *) tsdPtr->firstCSPtr;
    prevChanPtr = ((Channel *) prevChan)->state->topChanPtr;
................................................................................
    /*
     * Place new block at the head of a possibly existing list of previously
     * stacked channels.
     */

    prevChanPtr->upChanPtr	= chanPtr;
    statePtr->topChanPtr	= chanPtr;

    /* TIP #218, Channel Thread Actions.
     *
     * We call the thread actions for the new channel directly. We _cannot_
     * use SpliceChannel, because the (thread-)global list of all channels
     * always contains the _ChannelState_ for a stack of channels, not the
     * individual channels. And SpliceChannel would not only call the thread
     * actions, but also add the shared ChannelState to this list a second
     * time, mangling it.
     */

    threadActionProc = Tcl_ChannelThreadActionProc (chanPtr->typePtr);
    if (threadActionProc != NULL) {
	(*threadActionProc) (chanPtr->instanceData,
			     TCL_CHANNEL_THREAD_INSERT);
    }

    return (Tcl_Channel) chanPtr;
}
 
/*
 *----------------------------------------------------------------------
 *
................................................................................
Tcl_UnstackChannel(interp, chan)
    Tcl_Interp *interp; /* The interpreter we are working in */
    Tcl_Channel chan;   /* The channel to unstack */
{
    Channel *chanPtr = (Channel *) chan;
    ChannelState *statePtr = chanPtr->state;
    int result = 0;
    Tcl_DriverThreadActionProc *threadActionProc;

    /*
     * This operation should occur at the top of a channel stack.
     */

    chanPtr = statePtr->topChanPtr;

................................................................................
	    }

	    chanPtr->inQueueHead = (ChannelBuffer *) NULL;
	    chanPtr->inQueueTail = (ChannelBuffer *) NULL;

	    DiscardInputQueued(statePtr, 0);
	}

	/* TIP #218, Channel Thread Actions.
	 *
	 * We call the thread actions for the new channel directly. We
	 * _cannot_ use CutChannel, because the (thread-)global list of all
	 * channels always contains the _ChannelState_ for a stack of
	 * channels, not the individual channels. And SpliceChannel would not
	 * only call the thread actions, but also remove the shared
	 * ChannelState from this list despite there being more channels for
	 * the state which are still active.
	 */

	threadActionProc = Tcl_ChannelThreadActionProc (chanPtr->typePtr);
	if (threadActionProc != NULL) {
	    (*threadActionProc) (chanPtr->instanceData,
				 TCL_CHANNEL_THREAD_REMOVE);
	}

	statePtr->topChanPtr = downChanPtr;
	downChanPtr->upChanPtr = (Channel *) NULL;

	/*
	 * Leave this link intact for closeproc
	 *  chanPtr->downChanPtr = (Channel *) NULL;
................................................................................
		/* TIP #219, Tcl Channel Reflection API.
		 * "TclChanCaughtErrorBypass" is not required here, it was
		 * done already by "Tcl_Close".
		 */
		return TCL_ERROR;
	    }
	}

	/* TIP #218, Channel Thread Actions.
	 * Not required in this branch, this is done by Tcl_Close. If
	 * Tcl_Close is not called then the ChannelState is still active in
	 * the thread and no action has to be taken either.
	 */
    }

    return TCL_OK;
}
 
/*
 *----------------------------------------------------------------------
................................................................................
	statePtr->chanMsg = NULL;
    }

    /*
     * Remove this channel from of the list of all channels.
     */

    CutChannel((Tcl_Channel) chanPtr);

    /*
     * Close and free the channel driver state.
     * This may leave a TIP #219 error message in the interp.
     */

    if (chanPtr->typePtr->closeProc != TCL_CLOSE2PROC) {
................................................................................
    return errorCode;
}
 
/*
 *----------------------------------------------------------------------
 *
 * Tcl_CutChannel --
 * CutChannel --
 *
 *	Removes a channel from the (thread-)global list of all channels (in
 *	that thread).  This is actually the statePtr for the stack of channel.
 *
 * Results:
 *	Nothing.
 *
................................................................................
 *	the refcount) because the caller usually wants fiddle with the channel
 *	(like transfering it to a different thread) and thus keeps the
 *	refcount artifically high to prevent its destruction.
 *
 *----------------------------------------------------------------------
 */

static void
CutChannel(chan)
    Tcl_Channel chan;			/* The channel being removed. Must
					 * not be referenced in any
					 * interpreter. */
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    ChannelState *prevCSPtr;		/* Preceding channel state in list of
					 * all states - used to splice a
................................................................................
    /* TIP #218, Channel Thread Actions */
    threadActionProc = Tcl_ChannelThreadActionProc(Tcl_GetChannelType(chan));
    if (threadActionProc != NULL) {
	(*threadActionProc) (Tcl_GetChannelInstanceData(chan),
		TCL_CHANNEL_THREAD_REMOVE);
    }
}

void
Tcl_CutChannel(chan)
    Tcl_Channel chan;			/* The channel being added. Must not
					 * be referenced in any
					 * interpreter. */
{
    Channel* chanPtr = ((Channel*) chan)->state->bottomChanPtr;
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    ChannelState *prevCSPtr;		/* Preceding channel state in list of
					 * all states - used to splice a
					 * channel out of the list on close. */
    ChannelState *statePtr = chanPtr->state;
					/* state of the channel stack. */
    Tcl_DriverThreadActionProc *threadActionProc;

    /*
     * Remove this channel from of the list of all channels (in the current
     * thread).
     */

    if (tsdPtr->firstCSPtr && (statePtr == tsdPtr->firstCSPtr)) {
	tsdPtr->firstCSPtr = statePtr->nextCSPtr;
    } else {
	for (prevCSPtr = tsdPtr->firstCSPtr;
		prevCSPtr && (prevCSPtr->nextCSPtr != statePtr);
		prevCSPtr = prevCSPtr->nextCSPtr) {
	    /* Empty loop body. */
	}
	if (prevCSPtr == (ChannelState *) NULL) {
	    Tcl_Panic("FlushChannel: damaged channel list");
	}
	prevCSPtr->nextCSPtr = statePtr->nextCSPtr;
    }

    statePtr->nextCSPtr = (ChannelState *) NULL;

    /* TIP #218, Channel Thread Actions
     * For all transformations and the base channel.
     */

    while (chanPtr) {
	threadActionProc = Tcl_ChannelThreadActionProc(chanPtr->typePtr);
	if (threadActionProc != NULL) {
	    (*threadActionProc) (chanPtr->instanceData,
				 TCL_CHANNEL_THREAD_REMOVE);
	}
	chanPtr= chanPtr->upChanPtr;
    }
}
 
/*
 *----------------------------------------------------------------------
 *
 * Tcl_SpliceChannel --
 * SpliceChannel --
 *
 *	Adds a channel to the (thread-)global list of all channels (in that
 *	thread). Expects that the field 'nextChanPtr' in the channel is set to
 *	NULL.
 *
 * Results:
 *	Nothing.
................................................................................
 *	the refcount) because the caller usually wants figgle with the channel
 *	(like transfering it to a different thread) and thus keeps the
 *	refcount artifically high to prevent its destruction.
 *
 *----------------------------------------------------------------------
 */

static void
SpliceChannel(chan)
    Tcl_Channel chan;			/* The channel being added. Must not
					 * be referenced in any
					 * interpreter. */
{
    ThreadSpecificData	*tsdPtr = TCL_TSD_INIT(&dataKey);
    ChannelState	*statePtr = ((Channel *) chan)->state;
    Tcl_DriverThreadActionProc *threadActionProc;

    if (statePtr->nextCSPtr != (ChannelState *) NULL) {
	Tcl_Panic("SpliceChannel: trying to add channel used in different list");
    }

    statePtr->nextCSPtr = tsdPtr->firstCSPtr;
    tsdPtr->firstCSPtr = statePtr;

    /*
     * TIP #10. Mark the current thread as the new one managing this channel.
................................................................................
    /* TIP #218, Channel Thread Actions */
    threadActionProc = Tcl_ChannelThreadActionProc(Tcl_GetChannelType(chan));
    if (threadActionProc != NULL) {
	(*threadActionProc) (Tcl_GetChannelInstanceData(chan),
		TCL_CHANNEL_THREAD_INSERT);
    }
}

void
Tcl_SpliceChannel(chan)
    Tcl_Channel chan;			/* The channel being added. Must not
					 * be referenced in any
					 * interpreter. */
{
    Channel             *chanPtr  = ((Channel*) chan)->state->bottomChanPtr;
    ThreadSpecificData	*tsdPtr   = TCL_TSD_INIT(&dataKey);
    ChannelState	*statePtr = chanPtr->state;
    Tcl_DriverThreadActionProc *threadActionProc;

    if (statePtr->nextCSPtr != (ChannelState *) NULL) {
	Tcl_Panic("SpliceChannel: trying to add channel used in different list");
    }

    statePtr->nextCSPtr = tsdPtr->firstCSPtr;
    tsdPtr->firstCSPtr = statePtr;

    /*
     * TIP #10. Mark the current thread as the new one managing this channel.
     *		Note: 'Tcl_GetCurrentThread' returns sensible values even for
     *		a non-threaded core.
     */

    statePtr->managingThread = Tcl_GetCurrentThread();

    /* TIP #218, Channel Thread Actions
     * For all transformations and the base channel.
     */

    while (chanPtr) {
	threadActionProc = Tcl_ChannelThreadActionProc(chanPtr->typePtr);
	if (threadActionProc != NULL) {
	    (*threadActionProc) (chanPtr->instanceData,
				 TCL_CHANNEL_THREAD_INSERT);
	}
	chanPtr= chanPtr->upChanPtr;
    }
}
 
/*
 *----------------------------------------------------------------------
 *
 * Tcl_Close --
 *
 *	Closes a channel.

Changes to generic/tclInt.h.

5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
..
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
...
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
...
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
...
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
...
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
...
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371

372
373
374
375
376
377

378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557

558
559
560
561
562
563
564
565
566
567
568
569
570
...
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
...
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
...
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
...
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772

773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
...
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964


965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123

1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141

1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240

1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
....
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
....
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495

1496
1497
1498
1499
1500
1501
1502

1503
1504
1505
1506

1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540

1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577

1578
1579
1580
1581
1582
1583

1584

1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
....
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654

1655
1656

1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
....
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810

1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
....
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896

1897

1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
....
1930
1931
1932
1933
1934
1935
1936

1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
....
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
....
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
....
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
....
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
....
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
....
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
....
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000

3001
3002
3003
3004
3005
3006
3007
....
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039

3040
3041
3042
3043
3044
3045
3046
....
3116
3117
3118
3119
3120
3121
3122
3123







 *
 * Copyright (c) 1987-1993 The Regents of the University of California.
 * Copyright (c) 1993-1997 Lucent Technologies.
 * Copyright (c) 1994-1998 Sun Microsystems, Inc.
 * Copyright (c) 1998-19/99 by Scriptics Corporation.
 * Copyright (c) 2001, 2002 by Kevin B. Kenny.  All rights reserved.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclInt.h,v 1.202.2.34 2005/08/25 15:46:31 dgp Exp $
 */

#ifndef _TCLINT
#define _TCLINT

/*
 * Some numerics configuration options
 */

#define NO_WIDE_TYPE
#undef	ACCEPT_NAN

/*
 * Common include files needed by most of the Tcl source files are
 * included here, so that system-dependent personalizations for the
 * include files only have to be made in once place.  This results
 * in a few extra includes, but greater modularity.  The order of
 * the three groups of #includes is important.	For example, stdio.h
 * is needed by tcl.h, and the _ANSI_ARGS_ declaration in tcl.h is
 * needed by stdlib.h in some configurations.
 */

#ifdef HAVE_TCL_CONFIG_H
#include "tclConfig.h"
#endif
#ifndef _TCL
#include "tcl.h"
................................................................................
#include <stddef.h>
#else
typedef int ptrdiff_t;
#endif

/*
 * Ensure WORDS_BIGENDIAN is defined correcly:
 * Needs to happen here in addition to configure to work with
 * fat compiles on Darwin (i.e. ppc and i386 at the same time).
 */

#ifdef HAVE_SYS_TYPES_H
#    include <sys/types.h>
#endif
#ifdef HAVE_SYS_PARAM_H
#    include <sys/param.h>
#endif
#ifdef BYTE_ORDER
#    ifdef BIG_ENDIAN
#        if BYTE_ORDER == BIG_ENDIAN
#            undef WORDS_BIGENDIAN
#            define WORDS_BIGENDIAN
#        endif
#    endif
#    ifdef LITTLE_ENDIAN
#        if BYTE_ORDER == LITTLE_ENDIAN
#            undef WORDS_BIGENDIAN
#        endif
#    endif
#endif

/*
 * Used to tag functions that are only to be visible within the module
 * being built and not outside it (where this is supported by the
 * linker).
 */

#ifndef MODULE_SCOPE
#   ifdef __cplusplus
#	define MODULE_SCOPE extern "C"
#   else
#	define MODULE_SCOPE extern
................................................................................
 * having a tclWideIntType separate from the tclIntType.
 */
#ifdef TCL_WIDE_INT_IS_LONG
#define NO_WIDE_TYPE
#endif

/*
 * The following procedures allow namespaces to be customized to
 * support special name resolution rules for commands/variables.
 * 
 */

struct Tcl_ResolvedVarInfo;

typedef Tcl_Var (Tcl_ResolveRuntimeVarProc) _ANSI_ARGS_((
    Tcl_Interp* interp, struct Tcl_ResolvedVarInfo *vinfoPtr));

typedef void (Tcl_ResolveVarDeleteProc) _ANSI_ARGS_((
    struct Tcl_ResolvedVarInfo *vinfoPtr));

/*
 * The following structure encapsulates the routines needed to resolve a
 * variable reference at runtime.  Any variable specific state will typically
 * be appended to this structure.
 */


typedef struct Tcl_ResolvedVarInfo {
    Tcl_ResolveRuntimeVarProc *fetchProc;
    Tcl_ResolveVarDeleteProc *deleteProc;
} Tcl_ResolvedVarInfo;



typedef int (Tcl_ResolveCompiledVarProc) _ANSI_ARGS_((
    Tcl_Interp* interp, CONST84 char* name, int length,
    Tcl_Namespace *context, Tcl_ResolvedVarInfo **rPtr));

typedef int (Tcl_ResolveVarProc) _ANSI_ARGS_((
    Tcl_Interp* interp, CONST84 char* name, Tcl_Namespace *context,
    int flags, Tcl_Var *rPtr));

typedef int (Tcl_ResolveCmdProc) _ANSI_ARGS_((Tcl_Interp* interp,
    CONST84 char* name, Tcl_Namespace *context, int flags,
    Tcl_Command *rPtr));
 
typedef struct Tcl_ResolverInfo {
    Tcl_ResolveCmdProc *cmdResProc;	/* Procedure handling command name
					 * resolution. */
    Tcl_ResolveVarProc *varResProc;	/* Procedure handling variable name
					 * resolution for variables that
					 * can only be handled at runtime. */
    Tcl_ResolveCompiledVarProc *compiledVarResProc;
................................................................................

typedef struct Tcl_Ensemble Tcl_Ensemble;
typedef struct NamespacePathEntry NamespacePathEntry;

/*
 * The structure below defines a namespace.
 * Note: the first five fields must match exactly the fields in a
 * Tcl_Namespace structure (see tcl.h). If you change one, be sure to
 * change the other.
 */

typedef struct Namespace {
    char *name;			/* The namespace's simple (unqualified)
				 * name. This contains no ::'s. The name of
				 * the global namespace is "" although "::"
				 * is an synonym. */
    char *fullName;		/* The namespace's fully qualified name.
				 * This starts with ::. */
    ClientData clientData;	/* An arbitrary value associated with this
				 * namespace. */
    Tcl_NamespaceDeleteProc *deleteProc;
				/* Procedure invoked when deleting the
				 * namespace to, e.g., free clientData. */
    struct Namespace *parentPtr;/* Points to the namespace that contains
				 * this one. NULL if this is the global
				 * namespace. */
    Tcl_HashTable childTable;	/* Contains any child namespaces. Indexed
				 * by strings; values have type
				 * (Namespace *). */
    long nsId;			/* Unique id for the namespace. */
    Tcl_Interp *interp;		/* The interpreter containing this
				 * namespace. */
    int flags;			/* OR-ed combination of the namespace
				 * status flags NS_DYING and NS_DEAD
				 * listed below. */
    int activationCount;	/* Number of "activations" or active call
				 * frames for this namespace that are on
				 * the Tcl call stack. The namespace won't
				 * be freed until activationCount becomes
				 * zero. */
    int refCount;		/* Count of references by namespaceName *
				 * objects. The namespace can't be freed
				 * until refCount becomes zero. */
    Tcl_HashTable cmdTable;	/* Contains all the commands currently
				 * registered in the namespace. Indexed by
				 * strings; values have type (Command *).
				 * Commands imported by Tcl_Import have
				 * Command structures that point (via an
				 * ImportedCmdRef structure) to the
				 * Command structure in the source
				 * namespace's command table. */
    Tcl_HashTable varTable;	/* Contains all the (global) variables
				 * currently in this namespace. Indexed
				 * by strings; values have type (Var *). */
    char **exportArrayPtr;	/* Points to an array of string patterns
				 * specifying which commands are exported.
				 * A pattern may include "string match"
				 * style wildcard characters to specify
				 * multiple commands; however, no namespace
				 * qualifiers are allowed. NULL if no
				 * export patterns are registered. */
    int numExportPatterns;	/* Number of export patterns currently
				 * registered using "namespace export". */
    int maxExportPatterns;	/* Mumber of export patterns for which
				 * space is currently allocated. */
    int cmdRefEpoch;		/* Incremented if a newly added command
				 * shadows a command for which this
				 * namespace has already cached a Command *
				 * pointer; this causes all its cached
				 * Command* pointers to be invalidated. */
    int resolverEpoch;		/* Incremented whenever (a) the name resolution
				 * rules change for this namespace or (b) a 
				 * newly added command shadows a command that
				 * is compiled to bytecodes.
				 * This invalidates all byte codes compiled
				 * in the namespace, causing the code to be
				 * recompiled under the new rules.*/
    Tcl_ResolveCmdProc *cmdResProc;
				/* If non-null, this procedure overrides
				 * the usual command resolution mechanism
				 * in Tcl.  This procedure is invoked
				 * within Tcl_FindCommand to resolve all
				 * command references within the namespace. */
    Tcl_ResolveVarProc *varResProc;
				/* If non-null, this procedure overrides
				 * the usual variable resolution mechanism
				 * in Tcl.  This procedure is invoked
				 * within Tcl_FindNamespaceVar to resolve all
				 * variable references within the namespace
				 * at runtime. */
    Tcl_ResolveCompiledVarProc *compiledVarResProc;
				/* If non-null, this procedure overrides
				 * the usual variable resolution mechanism
				 * in Tcl.  This procedure is invoked
				 * within LookupCompiledLocal to resolve
				 * variable references within the namespace
				 * at compile time. */
    int exportLookupEpoch;	/* Incremented whenever a command is added to
				 * a namespace, removed from a namespace or
				 * the exports of a namespace are changed.
				 * Allows TIP#112-driven command lists to be
				 * validated efficiently. */
    Tcl_Ensemble *ensembles;	/* List of structures that contain the details
				 * of the ensembles that are implemented on
................................................................................

/*
 * An entry on a namespace's command resolution path.
 */

struct NamespacePathEntry {
    Namespace *nsPtr;		/* What does this path entry point to? If it
				 *is NULL, this path entry points is redundant
				 * and should be skipped. */
    Namespace *creatorNsPtr;	/* Where does this path entry point from? This
				 * allows for efficient invalidation of
				 * references when the path entry's target
				 * updates its current list of defined
				 * commands. */
    NamespacePathEntry *prevPtr, *nextPtr;
				/* Linked list pointers or NULL at either end
................................................................................
/*
 * Flags used to represent the status of a namespace:
 *
 * NS_DYING -	1 means Tcl_DeleteNamespace has been called to delete the
 *		namespace but there are still active call frames on the Tcl
 *		stack that refer to the namespace. When the last call frame
 *		referring to it has been popped, it's variables and command
 *		will be destroyed and it will be marked "dead" (NS_DEAD).
 *		The namespace can no longer be looked up by name.
 * NS_DEAD -	1 means Tcl_DeleteNamespace has been called to delete the
 *		namespace and no call frames still refer to it. Its
 *		variables and command have already been destroyed. This bit
 *		allows the namespace resolution code to recognize that the
 *		namespace is "deleted". When the last namespaceName object
 *		in any byte code unit that refers to the namespace has
 *		been freed (i.e., when the namespace's refCount is 0), the
 *		namespace's storage will be freed.
 */

#define NS_DYING	0x01
#define NS_DEAD		0x02

/*
 * Flags passed to TclGetNamespaceForQualName:
................................................................................
 */

#define TCL_CREATE_NS_IF_UNKNOWN	0x800
#define TCL_FIND_ONLY_NS		0x1000

/*
 *----------------------------------------------------------------
 * Data structures related to variables.   These are used primarily
 * in tclVar.c
 *----------------------------------------------------------------
 */

/*
 * The following structure defines a variable trace, which is used to
 * invoke a specific C procedure whenever certain operations are performed
 * on a variable.
 */

typedef struct VarTrace {
    Tcl_VarTraceProc *traceProc;/* Procedure to call when operations given
				 * by flags are performed on variable. */
    ClientData clientData;	/* Argument to pass to proc. */
    int flags;			/* What events the trace procedure is
				 * interested in:  OR-ed combination of
				 * TCL_TRACE_READS, TCL_TRACE_WRITES,
				 * TCL_TRACE_UNSETS and TCL_TRACE_ARRAY. */
    struct VarTrace *nextPtr;	/* Next in list of traces associated with
				 * a particular variable. */
} VarTrace;

/*
 * The following structure defines a command trace, which is used to
 * invoke a specific C procedure whenever certain operations are performed
 * on a command.
 */

typedef struct CommandTrace {

    Tcl_CommandTraceProc *traceProc;/* Procedure to call when operations given
				     * by flags are performed on command. */
    ClientData clientData;	    /* Argument to pass to proc. */
    int flags;			    /* What events the trace procedure is
				     * interested in:  OR-ed combination of
				     * TCL_TRACE_RENAME, TCL_TRACE_DELETE. */

    struct CommandTrace *nextPtr;   /* Next in list of traces associated with
				     * a particular command. */
    int refCount;		    /* Used to ensure this structure is
				     * not deleted too early.  Keeps track
				     * of how many pieces of code have
				     * a pointer to this structure. */
} CommandTrace;

/*
 * When a command trace is active (i.e. its associated procedure is
 * executing), one of the following structures is linked into a list
 * associated with the command's interpreter.  The information in
 * the structure is needed in order for Tcl to behave reasonably
 * if traces are deleted while traces are active.
 */

typedef struct ActiveCommandTrace {
    struct Command *cmdPtr;	/* Command that's being traced. */
    struct ActiveCommandTrace *nextPtr;
				/* Next in list of all active command
				 * traces for the interpreter, or NULL
				 * if no more. */
    CommandTrace *nextTracePtr;	/* Next trace to check after current
				 * trace procedure returns;  if this
				 * trace gets deleted, must update pointer
				 * to avoid using free'd memory. */
    int reverseScan;		/* Boolean set true when traces
				 * are scanning in reverse order. */
} ActiveCommandTrace;

/*
 * When a variable trace is active (i.e. its associated procedure is
 * executing), one of the following structures is linked into a list
 * associated with the variable's interpreter.	The information in
 * the structure is needed in order for Tcl to behave reasonably
 * if traces are deleted while traces are active.
 */

typedef struct ActiveVarTrace {
    struct Var *varPtr;		/* Variable that's being traced. */
    struct ActiveVarTrace *nextPtr;
				/* Next in list of all active variable
				 * traces for the interpreter, or NULL
				 * if no more. */
    VarTrace *nextTracePtr;	/* Next trace to check after current
				 * trace procedure returns;  if this
				 * trace gets deleted, must update pointer
				 * to avoid using free'd memory. */
} ActiveVarTrace;

/*
 * The following structure describes an enumerative search in progress on
 * an array variable;  this are invoked with options to the "array"
 * command.
 */

typedef struct ArraySearch {
    int id;			/* Integer id used to distinguish among
				 * multiple concurrent searches for the
				 * same array. */
    struct Var *varPtr;		/* Pointer to array variable that's being
				 * searched. */
    Tcl_HashSearch search;	/* Info kept by the hash module about
				 * progress through the array. */
    Tcl_HashEntry *nextEntry;	/* Non-null means this is the next element
				 * to be enumerated (it's leftover from
				 * the Tcl_FirstHashEntry call or from
				 * an "array anymore" command).	 NULL
				 * means must call Tcl_NextHashEntry
				 * to get value to return. */
    struct ArraySearch *nextPtr;/* Next in list of all active searches
				 * for this variable, or NULL if this is
				 * the last one. */
} ArraySearch;

/*
 * The structure below defines a variable, which associates a string name
 * with a Tcl_Obj value. These structures are kept in procedure call frames
 * (for local variables recognized by the compiler) or in the heap (for
 * global variables and any variable not known to the compiler). For each
 * Var structure in the heap, a hash table entry holds the variable name and
 * a pointer to the Var structure.
 */

typedef struct Var {
    union {
	Tcl_Obj *objPtr;	/* The variable's object value. Used for 
				 * scalar variables and array elements. */
	Tcl_HashTable *tablePtr;/* For array variables, this points to
				 * information about the hash table used
				 * to implement the associative array. 
				 * Points to malloc-ed data. */
	struct Var *linkPtr;	/* If this is a global variable being
				 * referred to in a procedure, or a variable
				 * created by "upvar", this field points to
				 * the referenced variable's Var struct. */
    } value;
    char *name;			/* NULL if the variable is in a hashtable,
				 * otherwise points to the variable's
				 * name. It is used, e.g., by TclLookupVar
				 * and "info locals". The storage for the
				 * characters of the name is not owned by
				 * the Var and must not be freed when
				 * freeing the Var. */
    Namespace *nsPtr;		/* Points to the namespace that contains
				 * this variable or NULL if the variable is
				 * a local variable in a Tcl procedure. */
    Tcl_HashEntry *hPtr;	/* If variable is in a hashtable, either the
				 * hash table entry that refers to this
				 * variable or NULL if the variable has been
				 * detached from its hash table (e.g. an
				 * array is deleted, but some of its
				 * elements are still referred to in
				 * upvars). NULL if the variable is not in a
				 * hashtable. This is used to delete an
				 * variable from its hashtable if it is no
				 * longer needed. */
    int refCount;		/* Counts number of active uses of this
				 * variable, not including its entry in the
				 * call frame or the hash table: 1 for each
				 * additional variable whose linkPtr points
				 * here, 1 for each nested trace active on
				 * variable, and 1 if the variable is a 
				 * namespace variable. This record can't be
				 * deleted until refCount becomes 0. */
    VarTrace *tracePtr;		/* First in list of all traces set for this
				 * variable. */
    ArraySearch *searchPtr;	/* First in list of all searches active
				 * for this variable, or NULL if none. */
    int flags;			/* Miscellaneous bits of information about
				 * variable. See below for definitions. */
} Var;

/*
 * Flag bits for variables. The first three (VAR_SCALAR, VAR_ARRAY, and
 * VAR_LINK) are mutually exclusive and give the "type" of the variable.
 * VAR_UNDEFINED is independent of the variable's type. 
 *
 * VAR_SCALAR -			1 means this is a scalar variable and not
 *				an array or link. The "objPtr" field points
 *				to the variable's value, a Tcl object.
 * VAR_ARRAY -			1 means this is an array variable rather
 *				than a scalar variable or link. The
 *				"tablePtr" field points to the array's
 *				hashtable for its elements.
 * VAR_LINK -			1 means this Var structure contains a
 *				pointer to another Var structure that
 *				either has the real value or is itself
 *				another VAR_LINK pointer. Variables like
 *				this come about through "upvar" and "global"
 *				commands, or through references to variables
 *				in enclosing namespaces.
 * VAR_UNDEFINED -		1 means that the variable is in the process
 *				of being deleted. An undefined variable
 *				logically does not exist and survives only
 *				while it has a trace, or if it is a global
 *				variable currently being used by some
 *				procedure.
 * VAR_IN_HASHTABLE -		1 means this variable is in a hashtable and
 *				the Var structure is malloced. 0 if it is
 *				a local variable that was assigned a slot
 *				in a procedure frame by	the compiler so the
 *				Var storage is part of the call frame.
 * VAR_TRACE_ACTIVE -		1 means that trace processing is currently
 *				underway for a read or write access, so
 *				new read or write accesses should not cause
 *				trace procedures to be called and the
 *				variable can't be deleted.
 * VAR_ARRAY_ELEMENT -		1 means that this variable is an array
 *				element, so it is not legal for it to be
 *				an array itself (the VAR_ARRAY flag had
 *				better not be set).
 * VAR_NAMESPACE_VAR -		1 means that this variable was declared
 *				as a namespace variable. This flag ensures
 *				it persists until its namespace is
 *				destroyed or until the variable is unset;
 *				it will persist even if it has not been
 *				initialized and is marked undefined.
 *				The variable's refCount is incremented to
 *				reflect the "reference" from its namespace.

 *
 * The following additional flags are used with the CompiledLocal type
 * defined below:
 *
 * VAR_ARGUMENT -		1 means that this variable holds a procedure
 *				argument. 
 * VAR_TEMPORARY -		1 if the local variable is an anonymous
 *				temporary variable. Temporaries have a NULL
 *				name.
 * VAR_RESOLVED -		1 if name resolution has been done for this
 *				variable.
 */

................................................................................
#define VAR_IN_HASHTABLE	0x10
#define VAR_TRACE_ACTIVE	0x20
#define VAR_ARRAY_ELEMENT	0x40
#define VAR_NAMESPACE_VAR	0x80

#define VAR_ARGUMENT		0x100
#define VAR_TEMPORARY		0x200
#define VAR_RESOLVED		0x400	
#define VAR_IS_ARGS             0x800

/*
 * Macros to ensure that various flag bits are set properly for variables.
 * The ANSI C "prototypes" for these macros are:
 *
 * MODULE_SCOPE void	TclSetVarScalar _ANSI_ARGS_((Var *varPtr));
 * MODULE_SCOPE void	TclSetVarArray _ANSI_ARGS_((Var *varPtr));
 * MODULE_SCOPE void	TclSetVarLink _ANSI_ARGS_((Var *varPtr));
 * MODULE_SCOPE void	TclSetVarArrayElement _ANSI_ARGS_((Var *varPtr));
 * MODULE_SCOPE void	TclSetVarUndefined _ANSI_ARGS_((Var *varPtr));
 * MODULE_SCOPE void	TclClearVarUndefined _ANSI_ARGS_((Var *varPtr));
 */

#define TclSetVarScalar(varPtr) \
    (varPtr)->flags = ((varPtr)->flags & ~(VAR_ARRAY|VAR_LINK)) | VAR_SCALAR

#define TclSetVarArray(varPtr) \
    (varPtr)->flags = ((varPtr)->flags & ~(VAR_SCALAR|VAR_LINK)) | VAR_ARRAY
................................................................................
#define TclClearVarNamespaceVar(varPtr) \
    (varPtr)->flags &= ~VAR_NAMESPACE_VAR

/*
 * Macros to read various flag bits of variables.
 * The ANSI C "prototypes" for these macros are:
 *
 * MODULE_SCOPE int	TclIsVarScalar _ANSI_ARGS_((Var *varPtr));
 * MODULE_SCOPE int	TclIsVarLink _ANSI_ARGS_((Var *varPtr));
 * MODULE_SCOPE int	TclIsVarArray _ANSI_ARGS_((Var *varPtr));
 * MODULE_SCOPE int	TclIsVarUndefined _ANSI_ARGS_((Var *varPtr));
 * MODULE_SCOPE int	TclIsVarArrayElement _ANSI_ARGS_((Var *varPtr));
 * MODULE_SCOPE int	TclIsVarTemporary _ANSI_ARGS_((Var *varPtr));
 * MODULE_SCOPE int	TclIsVarArgument _ANSI_ARGS_((Var *varPtr));
 * MODULE_SCOPE int	TclIsVarResolved _ANSI_ARGS_((Var *varPtr));
 */
    
#define TclIsVarScalar(varPtr) \
    ((varPtr)->flags & VAR_SCALAR)

#define TclIsVarLink(varPtr) \
    ((varPtr)->flags & VAR_LINK)

#define TclIsVarArray(varPtr) \
................................................................................
    ((varPtr)->flags & VAR_ARRAY_ELEMENT)

#define TclIsVarNamespaceVar(varPtr) \
    ((varPtr)->flags & VAR_NAMESPACE_VAR)

#define TclIsVarTemporary(varPtr) \
    ((varPtr)->flags & VAR_TEMPORARY)
    
#define TclIsVarArgument(varPtr) \
    ((varPtr)->flags & VAR_ARGUMENT)
    
#define TclIsVarResolved(varPtr) \
    ((varPtr)->flags & VAR_RESOLVED)

#define TclIsVarTraceActive(varPtr) \
    ((varPtr)->flags & VAR_TRACE_ACTIVE)

#define TclIsVarUntraced(varPtr) \
................................................................................
    ((varPtr)->tracePtr == NULL)

/*
 * Macros for direct variable access by TEBC
 */

#define TclIsVarDirectReadable(varPtr) \
       (TclIsVarScalar(varPtr) \
    && !TclIsVarUndefined(varPtr) \
    && TclIsVarUntraced(varPtr))

#define TclIsVarDirectWritable(varPtr) \
    (   !(((varPtr)->flags & VAR_IN_HASHTABLE) \
		&& ((varPtr)->hPtr == NULL)) \
     && TclIsVarUntraced(varPtr) \
     && (TclIsVarScalar(varPtr) \
	     || TclIsVarUndefined(varPtr)))

/*
 *----------------------------------------------------------------
 * Data structures related to procedures.  These are used primarily
 * in tclProc.c, tclCompile.c, and tclExecute.c.
 *----------------------------------------------------------------
 */

/*
 * Forward declaration to prevent an error when the forward reference to
 * Command is encountered in the Proc and ImportRef types declared below.
 */

struct Command;

/*
 * The variable-length structure below describes a local variable of a
 * procedure that was recognized by the compiler. These variables have a
 * name, an element in the array of compiler-assigned local variables in the
 * procedure's call frame, and various other items of information. If the
 * local variable is a formal argument, it may also have a default value.
 * The compiler can't recognize local variables whose names are
 * expressions (these names are only known at runtime when the expressions
 * are evaluated) or local variables that are created as a result of an
 * "upvar" or "uplevel" command. These other local variables are kept
 * separately in a hash table in the call frame.
 */

typedef struct CompiledLocal {
    struct CompiledLocal *nextPtr;
				/* Next compiler-recognized local variable
				 * for this procedure, or NULL if this is
				 * the last local. */
    int nameLength;		/* The number of characters in local
				 * variable's name. Used to speed up
				 * variable lookups. */
    int frameIndex;		/* Index in the array of compiler-assigned
				 * variables in the procedure call frame. */
    int flags;			/* Flag bits for the local variable. Same as
				 * the flags for the Var structure above,
				 * although only VAR_SCALAR, VAR_ARRAY, 
				 * VAR_LINK, VAR_ARGUMENT, VAR_TEMPORARY, and
				 * VAR_RESOLVED make sense. */
    Tcl_Obj *defValuePtr;	/* Pointer to the default value of an
				 * argument, if any. NULL if not an argument
				 * or, if an argument, no default value. */
    Tcl_ResolvedVarInfo *resolveInfo;
				/* Customized variable resolution info
				 * supplied by the Tcl_ResolveCompiledVarProc
				 * associated with a namespace. Each variable
				 * is marked by a unique ClientData tag
				 * during compilation, and that same tag
				 * is used to find the variable at runtime. */
    char name[4];		/* Name of the local variable starts here.
				 * If the name is NULL, this will just be
				 * '\0'. The actual size of this field will
				 * be large enough to hold the name. MUST
				 * BE THE LAST FIELD IN THE STRUCTURE! */
} CompiledLocal;

/*
 * The structure below defines a command procedure, which consists of a
 * collection of Tcl commands plus information about arguments and other
 * local variables recognized at compile time.
 */

typedef struct Proc {
    struct Interp *iPtr;	  /* Interpreter for which this command
				   * is defined. */
    int refCount;		  /* Reference count: 1 if still present
				   * in command table plus 1 for each call
				   * to the procedure that is currently
				   * active. This structure can be freed
				   * when refCount becomes zero. */
    struct Command *cmdPtr;	  /* Points to the Command structure for
				   * this procedure. This is used to get
				   * the namespace in which to execute
				   * the procedure. */
    Tcl_Obj *bodyPtr;		  /* Points to the ByteCode object for
				   * procedure's body command. */
    int numArgs;		  /* Number of formal parameters. */
    int numCompiledLocals;	  /* Count of local variables recognized by
				   * the compiler including arguments and
				   * temporaries. */

    CompiledLocal *firstLocalPtr; /* Pointer to first of the procedure's
				   * compiler-allocated local variables, or
				   * NULL if none. The first numArgs entries
				   * in this list describe the procedure's
				   * formal arguments. */
    CompiledLocal *lastLocalPtr;  /* Pointer to the last allocated local
				   * variable or NULL if none. This has
				   * frame index (numCompiledLocals-1). */
} Proc;

/*
 * The structure below defines a command trace.	 This is used to allow Tcl
 * clients to find out whenever a command is about to be executed.
 */

typedef struct Trace {
    int level;			/* Only trace commands at nesting level
				 * less than or equal to this. */
    Tcl_CmdObjTraceProc *proc;	/* Procedure to call to trace command. */
    ClientData clientData;	/* Arbitrary value to pass to proc. */
    struct Trace *nextPtr;	/* Next in list of traces for this interp. */
    int flags;			/* Flags governing the trace - see
				 * Tcl_CreateObjTrace for details */
    Tcl_CmdObjTraceDeleteProc* delProc;
				/* Procedure to call when trace is deleted */
} Trace;

/*
 * When an interpreter trace is active (i.e. its associated procedure
 * is executing), one of the following structures is linked into a list
 * associated with the interpreter.  The information in the structure
 * is needed in order for Tcl to behave reasonably if traces are
 * deleted while traces are active.
 */

typedef struct ActiveInterpTrace {
    struct ActiveInterpTrace *nextPtr;
				/* Next in list of all active command
				 * traces for the interpreter, or NULL
				 * if no more. */
    Trace *nextTracePtr;	/* Next trace to check after current
				 * trace procedure returns;  if this
				 * trace gets deleted, must update pointer
				 * to avoid using free'd memory. */
    int reverseScan;		/* Boolean set true when traces
				 * are scanning in reverse order. */
} ActiveInterpTrace;

/*
 * Flag values designating types of execution traces.
 * See tclTrace.c for related flag values.
 *
 * TCL_TRACE_ENTER_EXEC         - triggers enter/enterstep traces.
 * 				- passed to Tcl_CreateObjTrace to set up
 *                                "enterstep" traces.
 * TCL_TRACE_LEAVE_EXEC         - triggets leave/leavestep traces.
 * 				- passed to Tcl_CreateObjTrace to set up
 *                                "leavestep" traces.
 *
 */
#define TCL_TRACE_ENTER_EXEC            1
#define TCL_TRACE_LEAVE_EXEC            2

/*
 * The structure below defines an entry in the assocData hash table which
 * is associated with an interpreter. The entry contains a pointer to a
 * function to call when the interpreter is deleted, and a pointer to
 * a user-defined piece of data.
 */

typedef struct AssocData {
    Tcl_InterpDeleteProc *proc;	/* Proc to call when deleting. */
    ClientData clientData;	/* Value to pass to proc. */
} AssocData;	

/*
 * The structure below defines a call frame. A call frame defines a naming
 * context for a procedure call: its local naming scope (for local
 * variables) and its global naming scope (a namespace, perhaps the global
 * :: namespace). A call frame can also define the naming context for a
 * namespace eval or namespace inscope command: the namespace in which the
 * command's code should execute. The Tcl_CallFrame structures exist only
 * while procedures or namespace eval/inscope's are being executed, and
 * provide a kind of Tcl call stack.
 * 
 * WARNING!! The structure definition must be kept consistent with the
 * Tcl_CallFrame structure in tcl.h. If you change one, change the other.
 */

typedef struct CallFrame {
    Namespace *nsPtr;		/* Points to the namespace used to resolve
				 * commands and global variables. */
................................................................................
    int isProcCallFrame;	/* If 0, the frame was pushed to execute a
				 * namespace command and var references are
				 * treated as references to namespace vars;
				 * varTablePtr and compiledLocals are ignored.
				 * If FRAME_IS_PROC is set, the frame was
				 * pushed to execute a Tcl procedure and may
				 * have local vars. */
    int objc;			/* This and objv below describe the
				 * arguments for this procedure call. */
    Tcl_Obj *CONST *objv;	/* Array of argument objects. */
    struct CallFrame *callerPtr;
				/* Value of interp->framePtr when this
				 * procedure was invoked (i.e. next higher
				 * in stack of all active procedures). */
    struct CallFrame *callerVarPtr;
				/* Value of interp->varFramePtr when this
				 * procedure was invoked (i.e. determines
				 * variable scoping within caller). Same
				 * as callerPtr unless an "uplevel" command
				 * or something equivalent was active in
				 * the caller). */
    int level;			/* Level of this procedure, for "uplevel"
				 * purposes (i.e. corresponds to nesting of
				 * callerVarPtr's, not callerPtr's). 1 for
				 * outermost procedure, 0 for top-level. */
    Proc *procPtr;		/* Points to the structure defining the
				 * called procedure. Used to get information
				 * such as the number of compiled local
				 * variables (local variables assigned
				 * entries ["slots"] in the compiledLocals
				 * array below). */
    Tcl_HashTable *varTablePtr;	/* Hash table containing local variables not
				 * recognized by the compiler, or created at
				 * execution time through, e.g., upvar.
				 * Initially NULL and created if needed. */
    int numCompiledLocals;	/* Count of local variables recognized by
				 * the compiler including arguments. */
    Var* compiledLocals;	/* Points to the array of local variables
				 * recognized by the compiler. The compiler
				 * emits code that refers to these variables
				 * using an index into this array. */
} CallFrame;

#define FRAME_IS_PROC 0x1

/*
 *----------------------------------------------------------------
 * Data structures and procedures related to TclHandles, which
 * are a very lightweight method of preserving enough information
 * to determine if an arbitrary malloc'd block has been deleted.
 *----------------------------------------------------------------
 */

typedef VOID **TclHandle;

/*
 *----------------------------------------------------------------
 * Data structures related to expressions.  These are used only in
 * tclExpr.c.
 *----------------------------------------------------------------
 */

/*
 * The data structure below defines a math function (e.g. sin or hypot)
 * for use in Tcl expressions.
 */

#define MAX_MATH_ARGS 5
typedef struct MathFunc {
    int builtinFuncIndex;	/* If this is a builtin math function, its
				 * index in the array of builtin functions.
				 * (tclCompilation.h lists these indices.)
				 * The value is -1 if this is a new function
				 * defined by Tcl_CreateMathFunc. The value
				 * is also -1 if a builtin function is
				 * replaced by a Tcl_CreateMathFunc call. */
    int numArgs;		/* Number of arguments for function. */
    Tcl_ValueType argTypes[MAX_MATH_ARGS];
				/* Acceptable types for each argument. */
    Tcl_MathProc *proc;		/* Procedure that implements this function.
				 * NULL if isBuiltinFunc is 1. */
    ClientData clientData;	/* Additional argument to pass to the
				 * function when invoking it. NULL if
				 * isBuiltinFunc is 1. */
} MathFunc;

/*
 * These are a thin layer over TclpThreadKeyDataGet and TclpThreadKeyDataSet
 * when threads are used, or an emulation if there are no threads.  These
 * are really internal and Tcl clients should use Tcl_GetThreadData.
 */

MODULE_SCOPE VOID *	TclThreadDataKeyGet _ANSI_ARGS_((
			    Tcl_ThreadDataKey *keyPtr));
MODULE_SCOPE void	TclThreadDataKeySet _ANSI_ARGS_((
			    Tcl_ThreadDataKey *keyPtr, VOID *data));

/*
 * This is a convenience macro used to initialize a thread local storage ptr.
 */


#define TCL_TSD_INIT(keyPtr)	(ThreadSpecificData *)Tcl_GetThreadData((keyPtr), sizeof(ThreadSpecificData))


/*
 *----------------------------------------------------------------
 * Data structures related to bytecode compilation and execution.
 * These are used primarily in tclCompile.c, tclExecute.c, and
 * tclBasic.c.
 *----------------------------------------------------------------
 */

/*
 * Forward declaration to prevent errors when the forward references to
 * Tcl_Parse and CompileEnv are encountered in the procedure type
 * CompileProc declared below.
 */

struct CompileEnv;

/*
 * The type of procedures called by the Tcl bytecode compiler to compile
 * commands. Pointers to these procedures are kept in the Command structure
 * describing each command.  The integer value returned by a CompileProc
 * must be one of the following:
 *
 * TCL_OK		Compilation completed normally.
 * TCL_ERROR 		Compilation could not be completed.  This can
 * 			be just a judgment by the CompileProc that the
 * 			command is too complex to compile effectively,
 * 			or it can indicate that in the current state of
 * 			the interp, the command would raise an error.
 * 			The bytecode compiler will not do any error reporting
 * 			at compiler time.  Error reporting is deferred
 * 			until the actual runtime, because by then changes
 * 			in the interp state may allow the command to be
 * 			successfully evaluated.  
 * TCL_OUT_LINE_COMPILE	A source-compatible alias for TCL_ERROR, kept
 * 			for the sake of old code only.
 */

#define TCL_OUT_LINE_COMPILE	TCL_ERROR

typedef int (CompileProc) _ANSI_ARGS_((Tcl_Interp *interp,
	Tcl_Parse *parsePtr, struct CompileEnv *compEnvPtr));

/*
 * The type of procedure called from the compilation hook point in
 * SetByteCodeFromAny.
 */

typedef int (CompileHookProc) _ANSI_ARGS_((Tcl_Interp *interp,
	struct CompileEnv *compEnvPtr, ClientData clientData));

/*
 * The data structure defining the execution environment for ByteCode's.
 * There is one ExecEnv structure per Tcl interpreter. It holds the
 * evaluation stack that holds command operands and results. The stack grows
 * towards increasing addresses. The "stackTop" member is cached by
 * TclExecuteByteCode in a local variable: it must be set before calling
 * TclExecuteByteCode and will be restored by TclExecuteByteCode before it
 * returns.
 */

typedef struct ExecEnv {
    Tcl_Obj **stackPtr;		/* Points to the first item in the
				 * evaluation stack on the heap. */
    Tcl_Obj **tosPtr;		/* Points to current top of stack; 
				 * (stackPtr-1) when the stack is empty. */
    Tcl_Obj **endPtr;		/* Points to last usable item in stack. */
    Tcl_Obj *constants[2];      /* Pointers to constant "0" and "1" objs. */    
} ExecEnv;

/*
 * The definitions for the LiteralTable and LiteralEntry structures. Each
 * interpreter contains a LiteralTable. It is used to reduce the storage
 * needed for all the Tcl objects that hold the literals of scripts compiled
 * by the interpreter. A literal's object is shared by all the ByteCodes
 * that refer to the literal. Each distinct literal has one LiteralEntry
 * entry in the LiteralTable. A literal table is a specialized hash table
 * that is indexed by the literal's string representation, which may contain
 * null characters.
 *
 * Note that we reduce the space needed for literals by sharing literal
 * objects both within a ByteCode (each ByteCode contains a local
 * LiteralTable) and across all an interpreter's ByteCodes (with the
 * interpreter's global LiteralTable).
 */

typedef struct LiteralEntry {
    struct LiteralEntry *nextPtr;	/* Points to next entry in this
					 * hash bucket or NULL if end of
					 * chain. */
    Tcl_Obj *objPtr;			/* Points to Tcl object that
					 * holds the literal's bytes and
					 * length. */
    int refCount;			/* If in an interpreter's global
					 * literal table, the number of
					 * ByteCode structures that share
					 * the literal object; the literal
					 * entry can be freed when refCount
					 * drops to 0. If in a local literal
					 * table, -1. */
    Namespace *nsPtr;                    /* Namespace in which this literal is
					 * used. We try to avoid sharing
					 * literal non-FQ command names among
					 * different namespaces to reduce
					 * shimmering.*/ 
} LiteralEntry;

typedef struct LiteralTable {
    LiteralEntry **buckets;		/* Pointer to bucket array. Each
					 * element points to first entry in
					 * bucket's hash chain, or NULL. */
    LiteralEntry *staticBuckets[TCL_SMALL_HASH_TABLE];
					/* Bucket array used for small
					 * tables to avoid mallocs and
					 * frees. */
    int numBuckets;			/* Total number of buckets allocated
					 * at **buckets. */
    int numEntries;			/* Total number of entries present
					 * in table. */
    int rebuildSize;			/* Enlarge table when numEntries
					 * gets to be this large. */
    int mask;				/* Mask value used in hashing
					 * function. */
} LiteralTable;

/*
 * The following structure defines for each Tcl interpreter various
 * statistics-related information about the bytecode compiler and
 * interpreter's operation in that interpreter.
 */

#ifdef TCL_COMPILE_STATS
typedef struct ByteCodeStats {
    long numExecutions;		  /* Number of ByteCodes executed. */
    long numCompilations;	  /* Number of ByteCodes created. */
    long numByteCodesFreed;	  /* Number of ByteCodes destroyed. */
    long instructionCount[256];	  /* Number of times each instruction was
				   * executed. */

    double totalSrcBytes;	  /* Total source bytes ever compiled. */
    double totalByteCodeBytes;	  /* Total bytes for all ByteCodes. */
    double currentSrcBytes;	  /* Src bytes for all current ByteCodes. */
    double currentByteCodeBytes;  /* Code bytes in all current ByteCodes. */

    long srcCount[32];		  /* Source size distribution: # of srcs of
				   * size [2**(n-1)..2**n), n in [0..32). */
    long byteCodeCount[32];	  /* ByteCode size distribution. */
    long lifetimeCount[32];	  /* ByteCode lifetime distribution (ms). */
    
    double currentInstBytes;	  /* Instruction bytes-current ByteCodes. */
    double currentLitBytes;	  /* Current literal bytes. */
    double currentExceptBytes;	  /* Current exception table bytes. */
    double currentAuxBytes;	  /* Current auxiliary information bytes. */
    double currentCmdMapBytes;	  /* Current src<->code map bytes. */
    
    long numLiteralsCreated;	  /* Total literal objects ever compiled. */
    double totalLitStringBytes;	  /* Total string bytes in all literals. */

    double currentLitStringBytes; /* String bytes in current literals. */
    long literalCount[32];	  /* Distribution of literal string sizes. */
} ByteCodeStats;
#endif /* TCL_COMPILE_STATS */

/*
 *----------------------------------------------------------------
 * Data structures related to commands.
 *----------------------------------------------------------------
 */

/*
 * An imported command is created in an namespace when it imports a "real"
 * command from another namespace. An imported command has a Command
 * structure that points (via its ClientData value) to the "real" Command
 * structure in the source namespace's command table. The real command
 * records all the imported commands that refer to it in a list of ImportRef
 * structures so that they can be deleted when the real command is deleted.  */


typedef struct ImportRef {
    struct Command *importedCmdPtr;
				/* Points to the imported command created in
				 * an importing namespace; this command
				 * redirects its invocations to the "real"
				 * command. */
    struct ImportRef *nextPtr;	/* Next element on the linked list of
				 * imported commands that refer to the
				 * "real" command. The real command deletes
				 * these imported commands on this list when
				 * it is deleted. */
} ImportRef;

/*
 * Data structure used as the ClientData of imported commands: commands
 * created in an namespace when it imports a "real" command from another
 * namespace.
 */

typedef struct ImportedCmdData {
    struct Command *realCmdPtr;	/* "Real" command that this imported command
				 * refers to. */
    struct Command *selfPtr;	/* Pointer to this imported command. Needed
				 * only when deleting it in order to remove
				 * it from the real command's linked list of
				 * imported commands that refer to it. */
} ImportedCmdData;

/*
 * A Command structure exists for each command in a namespace. The
 * Tcl_Command opaque type actually refers to these structures.
 */

typedef struct Command {
    Tcl_HashEntry *hPtr;	/* Pointer to the hash table entry that
				 * refers to this command. The hash table is
				 * either a namespace's command table or an
				 * interpreter's hidden command table. This
				 * pointer is used to get a command's name
				 * from its Tcl_Command handle. NULL means
				 * that the hash table entry has been
				 * removed already (this can happen if
				 * deleteProc causes the command to be
				 * deleted or recreated). */
    Namespace *nsPtr;		/* Points to the namespace containing this
				 * command. */
    int refCount;		/* 1 if in command hashtable plus 1 for each
				 * reference from a CmdName Tcl object
				 * representing a command's name in a
				 * ByteCode instruction sequence. This
				 * structure can be freed when refCount
				 * becomes zero. */
    int cmdEpoch;		/* Incremented to invalidate any references
				 * that point to this command when it is
				 * renamed, deleted, hidden, or exposed. */
    CompileProc *compileProc;	/* Procedure called to compile command. NULL
				 * if no compile proc exists for command. */
    Tcl_ObjCmdProc *objProc;	/* Object-based command procedure. */
    ClientData objClientData;	/* Arbitrary value passed to object proc. */
    Tcl_CmdProc *proc;		/* String-based command procedure. */
    ClientData clientData;	/* Arbitrary value passed to string proc. */
    Tcl_CmdDeleteProc *deleteProc;
				/* Procedure invoked when deleting command
				 * to, e.g., free all client data. */
    ClientData deleteData;	/* Arbitrary value passed to deleteProc. */
    int flags;			/* Miscellaneous bits of information about
				 * command. See below for definitions. */
    ImportRef *importRefPtr;	/* List of each imported Command created in
				 * another namespace when this command is
				 * imported. These imported commands
				 * redirect invocations back to this
				 * command. The list is used to remove all
				 * those imported commands when deleting
				 * this "real" command. */
    CommandTrace *tracePtr;	/* First in list of all traces set for this
				 * command. */
} Command;

/*
 * Flag bits for commands. 
 *
 * CMD_IS_DELETED -		Means that the command is in the process
 *				of being deleted (its deleteProc is
 *				currently executing). Other attempts to
 *				delete the command should be ignored.
 * CMD_TRACE_ACTIVE -		1 means that trace processing is currently
 *				underway for a rename/delete change.
 *				See the two flags below for which is
 *				currently being processed.
 * CMD_HAS_EXEC_TRACES -	1 means that this command has at least
 *				one execution trace (as opposed to simple
 *				delete/rename traces) in its tracePtr list.
 * TCL_TRACE_RENAME -		A rename trace is in progress. Further
 *				recursive renames will not be traced.
 * TCL_TRACE_DELETE -		A delete trace is in progress. Further 
 *				recursive deletes will not be traced.
 * (these last two flags are defined in tcl.h)
 */

#define CMD_IS_DELETED		0x1
#define CMD_TRACE_ACTIVE	0x2
#define CMD_HAS_EXEC_TRACES	0x4

/*
 *----------------------------------------------------------------
 * Data structures related to name resolution procedures.
 *----------------------------------------------------------------
 */

/*
 * The interpreter keeps a linked list of name resolution schemes.
 * The scheme for a namespace is consulted first, followed by the
 * list of schemes in an interpreter, followed by the default
 * name resolution in Tcl.  Schemes are added/removed from the
 * interpreter's list by calling Tcl_AddInterpResolver and
 * Tcl_RemoveInterpResolver.
 */

typedef struct ResolverScheme {
    char *name;			/* Name identifying this scheme. */
    Tcl_ResolveCmdProc *cmdResProc;
				/* Procedure handling command name
				 * resolution. */
    Tcl_ResolveVarProc *varResProc;
				/* Procedure handling variable name
				 * resolution for variables that
				 * can only be handled at runtime. */
    Tcl_ResolveCompiledVarProc *compiledVarResProc;
				/* Procedure handling variable name
				 * resolution at compile time. */

    struct ResolverScheme *nextPtr;
				/* Pointer to next record in linked list. */
} ResolverScheme;

/*
 * Forward declaration of the TIP#143 limit handler structure.
 */

typedef struct LimitHandler LimitHandler;

/*
 *----------------------------------------------------------------
 * This structure defines an interpreter, which is a collection of
 * commands plus other state information related to interpreting
 * commands, such as variable storage. Primary responsibility for
 * this data structure is in tclBasic.c, but almost every Tcl
 * source file uses something in here.
 *----------------------------------------------------------------
 */

typedef struct Interp {

    /*
     * Note:  the first three fields must match exactly the fields in
     * a Tcl_Interp struct (see tcl.h).	 If you change one, be sure to
     * change the other.
     *
     * The interpreter's result is held in both the string and the
     * objResultPtr fields. These fields hold, respectively, the result's
     * string or object value. The interpreter's result is always in the
     * result field if that is non-empty, otherwise it is in objResultPtr.
     * The two fields are kept consistent unless some C code sets
     * interp->result directly. Programs should not access result and
     * objResultPtr directly; instead, they should always get and set the
     * result using procedures such as Tcl_SetObjResult, Tcl_GetObjResult,
     * and Tcl_GetStringResult. See the SetResult man page for details.
     */

    char *result;		/* If the last command returned a string
				 * result, this points to it. Should not be
				 * accessed directly; see comment above. */
    Tcl_FreeProc *freeProc;	/* Zero means a string result is statically
				 * allocated. TCL_DYNAMIC means string
				 * result was allocated with ckalloc and
				 * should be freed with ckfree. Other values
				 * give address of procedure to invoke to
				 * free the string result. Tcl_Eval must
				 * free it before executing next command. */
    int errorLine;		/* When TCL_ERROR is returned, this gives
				 * the line number in the command where the
				 * error occurred (1 means first line). */
    struct TclStubs *stubTable;
				/* Pointer to the exported Tcl stub table.
				 * On previous versions of Tcl this is a
				 * pointer to the objResultPtr or a pointer
				 * to a buckets array in a hash table. We
				 * therefore have to do some careful checking
				 * before we can use this. */

    TclHandle handle;		/* Handle used to keep track of when this
				 * interp is deleted. */

    Namespace *globalNsPtr;	/* The interpreter's global namespace. */
    Tcl_HashTable *hiddenCmdTablePtr;
				/* Hash table used by tclBasic.c to keep
				 * track of hidden commands on a per-interp
				 * basis. */
    ClientData interpInfo;	/* Information used by tclInterp.c to keep
				 * track of master/slave interps on
				 * a per-interp basis. */
    Tcl_HashTable mathFuncTable;/* Contains all the math functions currently
				 * defined for the interpreter.	 Indexed by
				 * strings (function names); values have
				 * type (MathFunc *). */



    /*
     * Information related to procedures and variables. See tclProc.c
     * and tclVar.c for usage.
     */

    int numLevels;		/* Keeps track of how many nested calls to
				 * Tcl_Eval are in progress for this
				 * interpreter.	 It's used to delay deletion
				 * of the table until all Tcl_Eval
				 * invocations are completed. */
    int maxNestingDepth;	/* If numLevels exceeds this value then Tcl
				 * assumes that infinite recursion has
				 * occurred and it generates an error. */
    CallFrame *framePtr;	/* Points to top-most in stack of all nested
				 * procedure invocations.  NULL means there
				 * are no active procedures. */
    CallFrame *varFramePtr;	/* Points to the call frame whose variables
				 * are currently in use (same as framePtr
				 * unless an "uplevel" command is
				 * executing). NULL means no procedure is
				 * active or "uplevel 0" is executing. */
    ActiveVarTrace *activeVarTracePtr;
				/* First in list of active traces for
				 * interp, or NULL if no active traces. */
    int returnCode;		/* [return -code] parameter */
    char *unused3;		/* No longer used (was errorInfo) */
    char *unused4;		/* No longer used (was errorCode) */

    /*
     * Information used by Tcl_AppendResult to keep track of partial
     * results.	 See Tcl_AppendResult code for details.
     */

    char *appendResult;		/* Storage space for results generated
				 * by Tcl_AppendResult.	 Malloc-ed.  NULL
				 * means not yet allocated. */
    int appendAvl;		/* Total amount of space available at
				 * partialResult. */
    int appendUsed;		/* Number of non-null bytes currently
				 * stored at partialResult. */

    /*
     * Information about packages.  Used only in tclPkg.c.
     */

    Tcl_HashTable packageTable;	/* Describes all of the packages loaded
				 * in or available to this interpreter.
				 * Keys are package names, values are
				 * (Package *) pointers. */
    char *packageUnknown;	/* Command to invoke during "package
				 * require" commands for packages that
				 * aren't described in packageTable. 
				 * Malloc'ed, may be NULL. */

    /*
     * Miscellaneous information:
     */

    int cmdCount;		/* Total number of times a command procedure
				 * has been called for this interpreter. */
    int evalFlags;		/* Flags to control next call to Tcl_Eval.
				 * Normally zero, but may be set before
				 * calling Tcl_Eval.  See below for valid
				 * values. */
    int unused1;		/* No longer used (was termOffset) */
    LiteralTable literalTable;	/* Contains LiteralEntry's describing all
				 * Tcl objects holding literals of scripts
				 * compiled by the interpreter. Indexed by
				 * the string representations of literals.
				 * Used to avoid creating duplicate
				 * objects. */
    int compileEpoch;		/* Holds the current "compilation epoch"
				 * for this interpreter. This is
				 * incremented to invalidate existing
				 * ByteCodes when, e.g., a command with a
				 * compile procedure is redefined. */
    Proc *compiledProcPtr;	/* If a procedure is being compiled, a
				 * pointer to its Proc structure; otherwise,
				 * this is NULL. Set by ObjInterpProc in
				 * tclProc.c and used by tclCompile.c to
				 * process local variables appropriately. */
    ResolverScheme *resolverPtr;
				/* Linked list of name resolution schemes
				 * added to this interpreter.  Schemes
				 * are added/removed by calling
				 * Tcl_AddInterpResolvers and
				 * Tcl_RemoveInterpResolver. */
    Tcl_Obj *scriptFile;	/* NULL means there is no nested source
				 * command active;  otherwise this points to
				 * pathPtr of the file being sourced. */
    int flags;			/* Various flag bits.  See below. */
    long randSeed;		/* Seed used for rand() function. */
    Trace *tracePtr;		/* List of traces for this interpreter. */
    Tcl_HashTable *assocData;	/* Hash table for associating data with
				 * this interpreter. Cleaned up when
				 * this interpreter is deleted. */
    struct ExecEnv *execEnvPtr;	/* Execution environment for Tcl bytecode
				 * execution. Contains a pointer to the
				 * Tcl evaluation stack. */
    Tcl_Obj *emptyObjPtr;	/* Points to an object holding an empty
				 * string. Returned by Tcl_ObjSetVar2 when
				 * variable traces change a variable in a
				 * gross way. */
    char resultSpace[TCL_RESULT_SIZE+1];
				/* Static space holding small results. */
    Tcl_Obj *objResultPtr;	/* If the last command returned an object
................................................................................
				 * accessed directly; see comment above. */
    Tcl_ThreadId threadId;	/* ID of thread that owns the interpreter */

    ActiveCommandTrace *activeCmdTracePtr;
				/* First in list of active command traces for
				 * interp, or NULL if no active traces. */
    ActiveInterpTrace *activeInterpTracePtr;
				/* First in list of active traces for
				 * interp, or NULL if no active traces. */

    int tracesForbiddingInline; /* Count of traces (in the list headed by
				 * tracePtr) that forbid inline bytecode
				 * compilation */

    /* Fields used to manage extensible return options (TIP 90) */
    Tcl_Obj *returnOpts;	/* A dictionary holding the options to the
................................................................................
    int returnLevel;		/* [return -level] parameter */

    /*
     * Resource limiting framework support (TIP#143).
     */

    struct {
	int active;		/* Flag values defining which limits have
				 * been set. */
	int granularityTicker;	/* Counter used to determine how often to
				 * check the limits. */
	int exceeded;		/* Which limits have been exceeded, described
				 * as flag values the same as the 'active'
				 * field. */

	int cmdCount;		/* Limit for how many commands to execute
				 * in the interpreter. */

	LimitHandler *cmdHandlers; /* Handlers to execute when the limit
				    * is reached. */
	int cmdGranularity;	/* Mod factor used to determine how often
				 * to evaluate the limit check. */

	Tcl_Time time;		/* Time limit for execution within the
				 * interpreter. */

	LimitHandler *timeHandlers; /* Handlers to execute when the limit
				     * is reached. */
	int timeGranularity;	/* Mod factor used to determine how often
				 * to evaluate the limit check. */

	Tcl_TimerToken timeEvent; /* Handle for a timer callback that will
				   * occur when the time-limit is exceeded. */

	Tcl_HashTable callbacks; /* Mapping from (interp,type) pair to data
				  * used to install a limit handler callback
				  * to run in _this_ interp when the limit
				  * is exceeded. */
    } limit;

    /*
     * Information for improved default error generation from
     * ensembles (TIP#112).
     */

    struct {
	Tcl_Obj * CONST *sourceObjs;
				/* What arguments were actually input into
				 * the *root* ensemble command?  (Nested
				 * ensembles don't rewrite this.)  NULL if
				 * we're not processing an ensemble. */
	int numRemovedObjs;	/* How many arguments have been stripped off
				 * because of ensemble processing. */
	int numInsertedObjs;	/* How many of the current arguments were
				 * inserted by an ensemble. */
    } ensembleRewrite;

    /* TIP #219 ... Global info for the I/O system ...
     * Error message set by channel drivers, for the propagation of
     * arbitrary Tcl errors. This information, if present (chanMsg not
     * NULL), takes precedence over a posix error code returned by a
     * channel operation.
     */

    Tcl_Obj* chanMsg;


    /*
     * Statistical information about the bytecode compiler and interpreter's
     * operation.
     */

#ifdef TCL_COMPILE_STATS
    ByteCodeStats stats;	/* Holds compilation and execution
				 * statistics for this interpreter. */
#endif /* TCL_COMPILE_STATS */	  
} Interp;

/*
 * General list of interpreters. Doubly linked for easier
 * removal of items deep in the list.
 */

typedef struct InterpList {
   Interp* interpPtr;
   struct InterpList* prevPtr;
   struct InterpList* nextPtr;
} InterpList;

/*
 * Macros for splicing into and out of doubly linked lists.
 * They assume existence of struct items 'prevPtr' and 'nextPtr'.
 *
 * a = element to add or remove.
 * b = list head.
 *
 * TclSpliceIn adds to the head of the list.
 */

#define TclSpliceIn(a,b)                       \
    (a)->nextPtr = (b);                        \
    if ((b) != NULL)                           \
        (b)->prevPtr = (a);                    \

    (a)->prevPtr = NULL, (b) = (a);

#define TclSpliceOut(a,b)                      \
    if ((a)->prevPtr != NULL)                  \
        (a)->prevPtr->nextPtr = (a)->nextPtr;  \
    else                                       \

        (b) = (a)->nextPtr;                    \

    if ((a)->nextPtr != NULL)                  \
        (a)->nextPtr->prevPtr = (a)->prevPtr;


/*
 * EvalFlag bits for Interp structures:
 *
 * TCL_ALLOW_EXCEPTIONS	1 means it's OK for the script to terminate with
 *			a code other than TCL_OK or TCL_ERROR;	0 means
 *			codes other than these should be turned into errors.
 */

#define TCL_ALLOW_EXCEPTIONS	  4

/*
 * Flag bits for Interp structures:
 *
 * DELETED:		Non-zero means the interpreter has been deleted:
 *			don't process any more commands for it, and destroy
 *			the structure as soon as all nested invocations of
 *			Tcl_Eval are done.
 * ERR_ALREADY_LOGGED:	Non-zero means information has already been logged
 *			in iPtr->errorInfo for the current Tcl_Eval instance,
 *			so Tcl_Eval needn't log it (used to implement the
 *			"error message log" command).
 * DONT_COMPILE_CMDS_INLINE: Non-zero means that the bytecode compiler
 *			should not compile any commands into an inline
 *			sequence of instructions. This is set 1, for
 *			example, when command traces are requested.
 * RAND_SEED_INITIALIZED: Non-zero means that the randSeed value of the
 *			interp has not be initialized.	This is set 1
 *			when we first use the rand() or srand() functions.
 * SAFE_INTERP:		Non zero means that the current interp is a
 *			safe interp (ie it has only the safe commands
 *			installed, less priviledge than a regular interp).
 * INTERP_TRACE_IN_PROGRESS: Non-zero means that an interp trace is currently
 *			active; so no further trace callbacks should be
 *			invoked.
 * INTERP_ALTERNATE_WRONG_ARGS: Used for listing second and subsequent forms
 *			of the wrong-num-args string in Tcl_WrongNumArgs.
 *			Makes it append instead of replacing and uses
 *			different intermediate text.
................................................................................
#define DONT_COMPILE_CMDS_INLINE	 0x20
#define RAND_SEED_INITIALIZED		 0x40
#define SAFE_INTERP			 0x80
#define INTERP_TRACE_IN_PROGRESS	0x200
#define INTERP_ALTERNATE_WRONG_ARGS	0x400

/*
 * Maximum number of levels of nesting permitted in Tcl commands (used
 * to catch infinite recursion).
 */

#define MAX_NESTING_DEPTH	1000

/*
 * TIP#143 limit handler internal representation.
 */

struct LimitHandler {
    int flags;			/* The state of this particular handler. */
    Tcl_LimitHandlerProc *handlerProc; /* The handler callback. */

    ClientData clientData;	/* Opaque argument to the handler callback. */
    Tcl_LimitHandlerDeleteProc *deleteProc; /* How to delete the clientData */

    LimitHandler *prevPtr;	/* Previous item in linked list of handlers */
    LimitHandler *nextPtr;	/* Next item in linked list of handlers */
};

/*
 * Values for the LimitHandler flags field.
 *	LIMIT_HANDLER_ACTIVE - Whether the handler is currently being
 *		processed; handlers are never to be entered reentrantly.
 *	LIMIT_HANDLER_DELETED - Whether the handler has been deleted.  This
 *		should not normally be observed because when a handler is
 *		deleted it is also spliced out of the list of handlers, but
 *		even so we will be careful.
 */

#define LIMIT_HANDLER_ACTIVE	0x01
#define LIMIT_HANDLER_DELETED	0x02

/*
 * The macro below is used to modify a "char" value (e.g. by casting
 * it to an unsigned character) so that it can be used safely with
 * macros such as isspace.
 */

#define UCHAR(c) ((unsigned char) (c))

/*
 * This macro is used to determine the offset needed to safely allocate any
 * data structure in memory. Given a starting offset or size, it "rounds up"
 * or "aligns" the offset to the next 8-byte boundary so that any data
 * structure can be placed at the resulting offset without fear of an
 * alignment error.
 *
 * WARNING!! DO NOT USE THIS MACRO TO ALIGN POINTERS: it will produce
 * the wrong result on platforms that allocate addresses that are divisible
 * by 4 or 2. Only use it for offsets or sizes.
 *
 * This macro is only used by tclCompile.c in the core (Bug 926445). It
 * however not be made file static, as extensions that touch bytecodes
 * (notably tbcload) require it.
 */

#define TCL_ALIGN(x) (((int)(x) + 7) & ~7)


/*
 * The following enum values are used to specify the runtime platform
 * setting of the tclPlatform variable.
 */

typedef enum {
    TCL_PLATFORM_UNIX = 0,	/* Any Unix-like OS. */
    TCL_PLATFORM_WINDOWS = 2	/* Any Microsoft Windows OS. */
} TclPlatformType;

/*
 *  The following enum values are used to indicate the translation
 *  of a Tcl channel.  Declared here so that each platform can define
 *  TCL_PLATFORM_TRANSLATION to the native translation on that platform
 */

typedef enum TclEolTranslation {
    TCL_TRANSLATE_AUTO,		/* Eol == \r, \n and \r\n. */
    TCL_TRANSLATE_CR,		/* Eol == \r. */
    TCL_TRANSLATE_LF,		/* Eol == \n. */
    TCL_TRANSLATE_CRLF		/* Eol == \r\n. */
} TclEolTranslation;

/*
 * Flags for TclInvoke:
 *
 * TCL_INVOKE_HIDDEN		Invoke a hidden command; if not set,
 *				invokes an exposed command.
 * TCL_INVOKE_NO_UNKNOWN	If set, "unknown" is not invoked if
 *				the command to be invoked is not found.
 *				Only has an effect if invoking an exposed
 *				command, i.e. if TCL_INVOKE_HIDDEN is not
 *				also set.
 * TCL_INVOKE_NO_TRACEBACK	Does not record traceback information if
 *				the invoked command returns an error.  Used
 *				if the caller plans on recording its own
 *				traceback information.
 */

#define	TCL_INVOKE_HIDDEN	(1<<0)
#define TCL_INVOKE_NO_UNKNOWN	(1<<1)
#define TCL_INVOKE_NO_TRACEBACK	(1<<2)

/*
 * The structure used as the internal representation of Tcl list
 * objects. This struct is grown (reallocated and copied) as necessary to hold
 * all the list's element pointers. The struct might contain more slots than
 * currently used to hold all element pointers. This is done to make append
 * operations faster.
 */

typedef struct List {
    int refCount;
    int maxElemCount;		/* Total number of element array slots. */
    int elemCount;		/* Current number of list elements. */
    Tcl_Obj *elements;		/* First list element; the struct is grown to
................................................................................
 * Macro used to get the elements of a list object - do NOT forget to verify
 * that it is of list type before using!
 */

#define TclListObjGetElements(listPtr, objc, objv) \
    { \
	List *listRepPtr = \
	    (List *) (listPtr)->internalRep.twoPtrValue.ptr1;\
	(objc) = listRepPtr->elemCount;\
	(objv) = &listRepPtr->elements;\
    }

/*
 * Flag values for TclTraceDictPath().
 *
 * DICT_PATH_READ indicates that all entries on the path must exist
 * but no updates will be needed.
 *
 * DICT_PATH_UPDATE indicates that we are going to be doing an update
 * at the tip of the path, so duplication of shared objects should be
 * done along the way.
 *
 * DICT_PATH_EXISTS indicates that we are performing an existance test
 * and a lookup failure should therefore not be an error.  If (and
 * only if) this flag is set, TclTraceDictPath() will return the special
 * value DICT_PATH_NON_EXISTENT if the path is not traceable.
 *
 * DICT_PATH_CREATE (which also requires the DICT_PATH_UPDATE bit to
 * be set) indicates that we are to create non-existant dictionaries
 * on the path.
 */

#define DICT_PATH_READ   0
#define DICT_PATH_UPDATE 1
#define DICT_PATH_EXISTS 2
#define DICT_PATH_CREATE 5

#define DICT_PATH_NON_EXISTENT ((Tcl_Obj *) (void *) 1)

/*
 *----------------------------------------------------------------
 * Data structures related to the filesystem internals
 *----------------------------------------------------------------
 */


/* 
 * The version_2 filesystem is private to Tcl.  As and when these
 * changes have been thoroughly tested and investigated a new public
 * filesystem interface will be released.  The aim is more versatile

 * virtual filesystem interfaces, more efficiency in 'path' manipulation
 * and usage, and cleaner filesystem code internally.
 */

#define TCL_FILESYSTEM_VERSION_2	((Tcl_FSVersion) 0x2)
typedef ClientData (TclFSGetCwdProc2) _ANSI_ARGS_((ClientData clientData));

/*
 * The following types are used for getting and storing platform-specific
 * file attributes in tclFCmd.c and the various platform-versions of
 * that file. This is done to have as much common code as possible
 * in the file attributes code. For more information about the callbacks,
 * see TclFileAttrsCmd in tclFCmd.c.
 */

typedef int (TclGetFileAttrProc) _ANSI_ARGS_((Tcl_Interp *interp,
	int objIndex, Tcl_Obj *fileName, Tcl_Obj **attrObjPtrPtr));
typedef int (TclSetFileAttrProc) _ANSI_ARGS_((Tcl_Interp *interp,
	int objIndex, Tcl_Obj *fileName, Tcl_Obj *attrObjPtr));

typedef struct TclFileAttrProcs {
    TclGetFileAttrProc *getProc;	/* The procedure for getting attrs. */
    TclSetFileAttrProc *setProc;	/* The procedure for setting attrs. */
} TclFileAttrProcs;

/*
 * Opaque handle used in pipeline routines to encapsulate platform-dependent
 * state. 
 */

typedef struct TclFile_ *TclFile;
    
/*
 * The "globParameters" argument of the function TclGlob is an
 * or'ed combination of the following values:
 */

#define TCL_GLOBMODE_NO_COMPLAIN	1
#define TCL_GLOBMODE_JOIN		2
#define TCL_GLOBMODE_DIR		4
#define TCL_GLOBMODE_TAILS		8

typedef enum Tcl_PathPart {
    TCL_PATH_DIRNAME,
    TCL_PATH_TAIL,	
    TCL_PATH_EXTENSION,
    TCL_PATH_ROOT
} Tcl_PathPart;

/*
 *----------------------------------------------------------------
 * Data structures related to obsolete filesystem hooks
 *----------------------------------------------------------------
 */

typedef int (TclStatProc_) _ANSI_ARGS_((CONST char *path, struct stat *buf));
typedef int (TclAccessProc_) _ANSI_ARGS_((CONST char *path, int mode));
typedef Tcl_Channel (TclOpenFileChannelProc_) _ANSI_ARGS_((Tcl_Interp *interp,
	CONST char *fileName, CONST char *modeString,
	int permissions));


/*
 *----------------------------------------------------------------
 * Data structures related to procedures
 *----------------------------------------------------------------
 */

................................................................................

/*
 *----------------------------------------------------------------
 * Data structures for process-global values.
 *----------------------------------------------------------------
 */

typedef void (TclInitProcessGlobalValueProc) _ANSI_ARGS_((char **valuePtr,
	int *lengthPtr, Tcl_Encoding *encodingPtr));

/*
 * A ProcessGlobalValue struct exists for each internal value in
 * Tcl that is to be shared among several threads.  Each thread
 * sees a (Tcl_Obj) copy of the value, and the master is kept as
 * a counted string, with epoch and mutex control.  Each ProcessGlobalValue
 * struct should be a static variable in some file.

 */

typedef struct ProcessGlobalValue {
    int epoch;			/* Epoch counter to detect changes
				 * in the master value */
    int numBytes;		/* Length of the master string */
    char *value;		/* The master string value */
    Tcl_Encoding encoding;	/* system encoding when master string
				 * was initialized */
    TclInitProcessGlobalValueProc *proc;
    				/* A procedure to initialize the
				 * master string copy when a "get"
				 * request comes in before any
				 * "set" request has been received. */
    Tcl_Mutex mutex;		/* Enforce orderly access from
				 * multiple threads */
    Tcl_ThreadDataKey key;	/* Key for per-thread data holding
				 * the (Tcl_Obj) copy for each thread */
} ProcessGlobalValue;

/*
 *----------------------------------------------------------------------
 * Flags for TclParseNumber
 *----------------------------------------------------------------------
 */
................................................................................

MODULE_SCOPE char *	tclNativeExecutableName;
MODULE_SCOPE int	tclFindExecutableSearchDone;
MODULE_SCOPE char *	tclMemDumpFileName;
MODULE_SCOPE TclPlatformType tclPlatform;
MODULE_SCOPE Tcl_NotifierProcs tclOriginalNotifier;


/* TIP #233 (Virtualized Time)
 * Data for the time hooks, if any.
 */

MODULE_SCOPE Tcl_GetTimeProc*   tclGetTimeProcPtr;
MODULE_SCOPE Tcl_ScaleTimeProc* tclScaleTimeProcPtr;
MODULE_SCOPE ClientData         tclTimeClientData;

/*
 * Variables denoting the Tcl object types defined in the core.
 */

MODULE_SCOPE Tcl_ObjType tclBignumType;
MODULE_SCOPE Tcl_ObjType tclBooleanType;
................................................................................
MODULE_SCOPE long	tclObjsAlloced;
MODULE_SCOPE long	tclObjsFreed;
#define TCL_MAX_SHARED_OBJ_STATS 5
MODULE_SCOPE long	tclObjsShared[TCL_MAX_SHARED_OBJ_STATS];
#endif /* TCL_COMPILE_STATS */

/*
 * Pointer to a heap-allocated string of length zero that the Tcl core uses
 * as the value of an empty string representation for an object. This value
 * is shared by all new objects allocated by Tcl_NewObj.
 */

MODULE_SCOPE char *	tclEmptyStringRep;
MODULE_SCOPE char	tclEmptyString;

/*
 *----------------------------------------------------------------
 * Procedures shared among Tcl modules but not used by the outside
 * world:
 *----------------------------------------------------------------
 */

MODULE_SCOPE void	TclAppendLimitedToObj _ANSI_ARGS_((Tcl_Obj *objPtr, 
			    CONST char *bytes, int length, int limit,
			    CONST char *ellipsis));
MODULE_SCOPE void	TclAppendObjToErrorInfo _ANSI_ARGS_((
			    Tcl_Interp *interp, Tcl_Obj *objPtr));
MODULE_SCOPE int	TclArraySet _ANSI_ARGS_((Tcl_Interp *interp,
			    Tcl_Obj *arrayNameObj, Tcl_Obj *arrayElemObj));
MODULE_SCOPE double     TclBignumToDouble _ANSI_ARGS_((mp_int* bignum));
MODULE_SCOPE double	TclCeil _ANSI_ARGS_((mp_int* a));
MODULE_SCOPE int	TclCheckBadOctal _ANSI_ARGS_((Tcl_Interp *interp,
			    CONST char *value));
MODULE_SCOPE int        TclChanCreateObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
MODULE_SCOPE int        TclChanPostEventObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
MODULE_SCOPE int        TclChanCaughtErrorBypass _ANSI_ARGS_((Tcl_Interp *interp,
			    Tcl_Channel chan));
MODULE_SCOPE void	TclCleanupLiteralTable _ANSI_ARGS_((
			    Tcl_Interp* interp, LiteralTable* tablePtr));
MODULE_SCOPE int	TclDoubleDigits _ANSI_ARGS_((char* buf,
						     double value,
						     int* signum));
MODULE_SCOPE void	TclExpandTokenArray _ANSI_ARGS_((
			    Tcl_Parse *parsePtr));
MODULE_SCOPE int	TclFileAttrsCmd _ANSI_ARGS_((Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	TclFileCopyCmd _ANSI_ARGS_((Tcl_Interp *interp, 
			    int objc, Tcl_Obj *CONST objv[])) ;
MODULE_SCOPE int	TclFileDeleteCmd _ANSI_ARGS_((Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	TclFileMakeDirsCmd _ANSI_ARGS_((Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[])) ;
MODULE_SCOPE int	TclFileRenameCmd _ANSI_ARGS_((Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[])) ;
MODULE_SCOPE void	TclFinalizeAllocSubsystem _ANSI_ARGS_((void));
MODULE_SCOPE void	TclFinalizeAsync _ANSI_ARGS_((void));
MODULE_SCOPE void	TclFinalizeCompilation _ANSI_ARGS_((void));
MODULE_SCOPE void	TclFinalizeDoubleConversion _ANSI_ARGS_((void));
MODULE_SCOPE void	TclFinalizeEncodingSubsystem _ANSI_ARGS_((void));
MODULE_SCOPE void	TclFinalizeEnvironment _ANSI_ARGS_((void));
MODULE_SCOPE void	TclFinalizeExecution _ANSI_ARGS_((void));
MODULE_SCOPE void	TclFinalizeIOSubsystem _ANSI_ARGS_((void));
MODULE_SCOPE void	TclFinalizeFilesystem _ANSI_ARGS_((void));
MODULE_SCOPE void	TclResetFilesystem _ANSI_ARGS_((void));
MODULE_SCOPE void	TclFinalizeLoad _ANSI_ARGS_((void));
MODULE_SCOPE void	TclFinalizeLock _ANSI_ARGS_((void));
MODULE_SCOPE void	TclFinalizeMemorySubsystem _ANSI_ARGS_((void));
MODULE_SCOPE void	TclFinalizeNotifier _ANSI_ARGS_((void));
MODULE_SCOPE void	TclFinalizeObjects _ANSI_ARGS_((void));
MODULE_SCOPE void	TclFinalizePreserve _ANSI_ARGS_((void));
MODULE_SCOPE void	TclFinalizeSynchronization _ANSI_ARGS_((void));
MODULE_SCOPE void	TclFinalizeThreadData _ANSI_ARGS_((void));
MODULE_SCOPE double	TclFloor _ANSI_ARGS_((mp_int* a));
MODULE_SCOPE void	TclFormatNaN _ANSI_ARGS_((double value, char* buffer));
MODULE_SCOPE int	TclFSFileAttrIndex _ANSI_ARGS_((Tcl_Obj *pathPtr,
			    CONST char *attributeName, int *indexPtr));
MODULE_SCOPE Tcl_Obj *	TclGetBgErrorHandler _ANSI_ARGS_((Tcl_Interp *interp));
MODULE_SCOPE int	TclGetEncodingFromObj _ANSI_ARGS_((Tcl_Interp *interp,
			    Tcl_Obj *objPtr, Tcl_Encoding *encodingPtr));
MODULE_SCOPE int        TclGetNamespaceFromObj _ANSI_ARGS_((
			    Tcl_Interp *interp, Tcl_Obj *objPtr,
			    Tcl_Namespace **nsPtrPtr));
MODULE_SCOPE int	TclGetOpenModeEx _ANSI_ARGS_((Tcl_Interp *interp,
			    CONST char *modeString, int *seekFlagPtr,
			    int *binaryPtr));
MODULE_SCOPE Tcl_Obj *	TclGetProcessGlobalValue _ANSI_ARGS_ ((
			    ProcessGlobalValue *pgvPtr));
MODULE_SCOPE int	TclGlob _ANSI_ARGS_((Tcl_Interp *interp,
			    char *pattern, Tcl_Obj *unquotedPrefix, 
			    int globFlags, Tcl_GlobTypeData* types));
MODULE_SCOPE int	TclIncrObj _ANSI_ARGS_((Tcl_Interp *interp,
			    Tcl_Obj *valuePtr, Tcl_Obj *incrPtr));
MODULE_SCOPE Tcl_Obj *	TclIncrObjVar2 _ANSI_ARGS_((Tcl_Interp *interp,
			    Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr,
			    Tcl_Obj *incrPtr, int flags));
MODULE_SCOPE void	TclInitAlloc _ANSI_ARGS_((void));
MODULE_SCOPE int	TclInitBignumFromDouble _ANSI_ARGS_((Tcl_Interp *interp,
			    double d, mp_int *b));
MODULE_SCOPE void	TclInitDbCkalloc _ANSI_ARGS_((void));
MODULE_SCOPE void	TclInitDoubleConversion _ANSI_ARGS_((void));
MODULE_SCOPE void	TclInitEmbeddedConfigurationInformation 
			    _ANSI_ARGS_((Tcl_Interp *interp));
MODULE_SCOPE void	TclInitEncodingSubsystem _ANSI_ARGS_((void));
MODULE_SCOPE void	TclInitIOSubsystem _ANSI_ARGS_((void));
MODULE_SCOPE void	TclInitLimitSupport _ANSI_ARGS_((Tcl_Interp *interp));
MODULE_SCOPE void	TclInitNamespaceSubsystem _ANSI_ARGS_((void));
MODULE_SCOPE void	TclInitNotifier _ANSI_ARGS_((void));
MODULE_SCOPE void	TclInitObjSubsystem _ANSI_ARGS_((void));
MODULE_SCOPE void	TclInitSubsystems ();
MODULE_SCOPE int	TclInterpReady _ANSI_ARGS_((Tcl_Interp *interp));
MODULE_SCOPE int	TclIsLocalScalar _ANSI_ARGS_((CONST char *src,
			    int len));
MODULE_SCOPE int	TclJoinThread _ANSI_ARGS_((Tcl_ThreadId id,
			    int* result));
MODULE_SCOPE void	TclLimitRemoveAllHandlers _ANSI_ARGS_((
			    Tcl_Interp *interp));
MODULE_SCOPE Tcl_Obj *	TclLindexList _ANSI_ARGS_((Tcl_Interp* interp,
			    Tcl_Obj* listPtr, Tcl_Obj* argPtr));
MODULE_SCOPE Tcl_Obj *	TclLindexFlat _ANSI_ARGS_((Tcl_Interp* interp,
			    Tcl_Obj* listPtr, int indexCount,
			    Tcl_Obj *CONST indexArray[]));
MODULE_SCOPE int	TclLoadFile _ANSI_ARGS_((Tcl_Interp* interp,
			    Tcl_Obj *pathPtr, int symc,
			    CONST char *symbols[],
			    Tcl_PackageInitProc **procPtrs[],
			    Tcl_LoadHandle *handlePtr,
			    ClientData *clientDataPtr,
			    Tcl_FSUnloadFileProc **unloadProcPtr));
MODULE_SCOPE Tcl_Obj *	TclLsetList _ANSI_ARGS_((Tcl_Interp* interp,
			    Tcl_Obj* listPtr, Tcl_Obj* indexPtr,
			    Tcl_Obj* valuePtr));
MODULE_SCOPE Tcl_Obj *	TclLsetFlat _ANSI_ARGS_((Tcl_Interp* interp,
			    Tcl_Obj* listPtr, int indexCount,
			    Tcl_Obj *CONST indexArray[], Tcl_Obj* valuePtr));
MODULE_SCOPE int	TclMergeReturnOptions _ANSI_ARGS_((Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[],
			    Tcl_Obj **optionsPtrPtr, int *codePtr,
			    int *levelPtr));
MODULE_SCOPE int	TclObjInvokeNamespace _ANSI_ARGS_((Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[],
			    Tcl_Namespace *nsPtr, int flags));
MODULE_SCOPE int	TclParseBackslash _ANSI_ARGS_((CONST char *src,
			    int numBytes, int *readPtr, char *dst));
MODULE_SCOPE int	TclParseHex _ANSI_ARGS_((CONST char *src, int numBytes,
			    Tcl_UniChar *resultPtr));
MODULE_SCOPE int	TclParseNumber _ANSI_ARGS_((Tcl_Interp* interp,
						    Tcl_Obj* objPtr,
						    CONST char* type,
						    CONST char* string,
						    size_t length,
						    CONST char** endPtrPtr,
						    int flags));
MODULE_SCOPE void	TclParseInit _ANSI_ARGS_ ((Tcl_Interp *interp,
			    CONST char *string, int numBytes,
			    Tcl_Parse *parsePtr));
#if 0
MODULE_SCOPE int	TclParseInteger _ANSI_ARGS_((CONST char *string,
			    int numBytes));
#endif
MODULE_SCOPE int	TclParseWhiteSpace _ANSI_ARGS_((CONST char *src,
			    int numBytes, Tcl_Parse *parsePtr, char *typePtr));
MODULE_SCOPE int	TclProcessReturn _ANSI_ARGS_((Tcl_Interp *interp,
			    int code, int level, Tcl_Obj *returnOpts));
MODULE_SCOPE int	TclpObjLstat _ANSI_ARGS_((Tcl_Obj *pathPtr, 
			    Tcl_StatBuf *buf));
MODULE_SCOPE int	TclpCheckStackSpace _ANSI_ARGS_((void));
MODULE_SCOPE Tcl_Obj *	TclpTempFileName _ANSI_ARGS_((void));
MODULE_SCOPE Tcl_Obj *	TclNewFSPathObj _ANSI_ARGS_((Tcl_Obj *dirPtr, 
			    CONST char *addStrRep, int len));
MODULE_SCOPE int	TclpDeleteFile _ANSI_ARGS_((CONST char *path));
MODULE_SCOPE void	TclpFinalizeCondition _ANSI_ARGS_((
			    Tcl_Condition *condPtr));
MODULE_SCOPE void	TclpFinalizeMutex _ANSI_ARGS_((Tcl_Mutex *mutexPtr));
MODULE_SCOPE void	TclpFinalizePipes _ANSI_ARGS_((void));
MODULE_SCOPE int	TclpThreadCreate _ANSI_ARGS_((
			    Tcl_ThreadId *idPtr,
			    Tcl_ThreadCreateProc proc,
			    ClientData clientData,
			    int stackSize, int flags));
MODULE_SCOPE int	TclpFindVariable _ANSI_ARGS_((CONST char *name,
			    int *lengthPtr));
MODULE_SCOPE void	TclpInitLibraryPath _ANSI_ARGS_((char **valuePtr,
			    int *lengthPtr, Tcl_Encoding *encodingPtr));
MODULE_SCOPE void	TclpInitLock _ANSI_ARGS_((void));
MODULE_SCOPE void	TclpInitPlatform _ANSI_ARGS_((void));
MODULE_SCOPE void	TclpInitUnlock _ANSI_ARGS_((void));
MODULE_SCOPE int	TclpLoadFile _ANSI_ARGS_((Tcl_Interp *interp, 
			    Tcl_Obj *pathPtr, CONST char *sym1,
			    CONST char *sym2, Tcl_PackageInitProc **proc1Ptr,
			    Tcl_PackageInitProc **proc2Ptr, 
			    ClientData *clientDataPtr,
			    Tcl_FSUnloadFileProc **unloadProcPtr));
MODULE_SCOPE Tcl_Obj *	TclpObjListVolumes _ANSI_ARGS_((void));
MODULE_SCOPE void	TclpMasterLock _ANSI_ARGS_((void));
MODULE_SCOPE void	TclpMasterUnlock _ANSI_ARGS_((void));
MODULE_SCOPE int	TclpMatchFiles _ANSI_ARGS_((Tcl_Interp *interp,
			    char *separators, Tcl_DString *dirPtr,
			    char *pattern, char *tail));
MODULE_SCOPE int	TclpObjNormalizePath _ANSI_ARGS_((Tcl_Interp *interp, 
			    Tcl_Obj *pathPtr, int nextCheckpoint));
MODULE_SCOPE void	TclpNativeJoinPath _ANSI_ARGS_((Tcl_Obj *prefix, 
			    char *joining));
MODULE_SCOPE Tcl_Obj *	TclpNativeSplitPath _ANSI_ARGS_((Tcl_Obj *pathPtr, 
			    int *lenPtr));
MODULE_SCOPE Tcl_PathType TclpGetNativePathType _ANSI_ARGS_((Tcl_Obj *pathPtr,
			    int *driveNameLengthPtr, Tcl_Obj **driveNameRef));
MODULE_SCOPE int 	TclCrossFilesystemCopy _ANSI_ARGS_((
			    Tcl_Interp *interp, Tcl_Obj *source,
			    Tcl_Obj *target));
MODULE_SCOPE int	TclpMatchInDirectory _ANSI_ARGS_((Tcl_Interp *interp, 
			    Tcl_Obj *resultPtr, Tcl_Obj *pathPtr, 
			    CONST char *pattern, Tcl_GlobTypeData *types));
MODULE_SCOPE ClientData	TclpGetNativeCwd _ANSI_ARGS_((ClientData clientData));
MODULE_SCOPE Tcl_FSDupInternalRepProc TclNativeDupInternalRep;
MODULE_SCOPE Tcl_Obj*	TclpObjLink _ANSI_ARGS_((Tcl_Obj *pathPtr, 
			    Tcl_Obj *toPtr, int linkType));
MODULE_SCOPE int	TclpObjChdir _ANSI_ARGS_((Tcl_Obj *pathPtr));
MODULE_SCOPE Tcl_Obj *	TclPathPart _ANSI_ARGS_((Tcl_Interp *interp, 
			    Tcl_Obj *pathPtr, Tcl_PathPart portion));
MODULE_SCOPE void	TclpPanic _ANSI_ARGS_(TCL_VARARGS(CONST char *,
			    format));
MODULE_SCOPE char *	TclpReadlink _ANSI_ARGS_((CONST char *fileName,
			    Tcl_DString *linkPtr));
MODULE_SCOPE void	TclpReleaseFile _ANSI_ARGS_((TclFile file));
MODULE_SCOPE void	TclpSetInterfaces ();
MODULE_SCOPE void	TclpSetVariables _ANSI_ARGS_((Tcl_Interp *interp));
MODULE_SCOPE void	TclpUnloadFile _ANSI_ARGS_((
			    Tcl_LoadHandle loadHandle));
MODULE_SCOPE VOID *	TclpThreadDataKeyGet _ANSI_ARGS_((
			    Tcl_ThreadDataKey *keyPtr));
MODULE_SCOPE void	TclpThreadDataKeySet _ANSI_ARGS_((
			    Tcl_ThreadDataKey *keyPtr, VOID *data));
MODULE_SCOPE void	TclpThreadExit _ANSI_ARGS_((int status));
MODULE_SCOPE int	TclpThreadGetStackSize _ANSI_ARGS_((void));
MODULE_SCOPE void	TclRememberCondition _ANSI_ARGS_((
			    Tcl_Condition *mutex));
MODULE_SCOPE VOID	TclRememberJoinableThread _ANSI_ARGS_((
			    Tcl_ThreadId id));
MODULE_SCOPE void	TclRememberMutex _ANSI_ARGS_((Tcl_Mutex *mutex));
MODULE_SCOPE void	TclRemoveScriptLimitCallbacks _ANSI_ARGS_((
			    Tcl_Interp *interp));
MODULE_SCOPE void	TclSetBgErrorHandler _ANSI_ARGS_((Tcl_Interp *interp,
			    Tcl_Obj *cmdPrefix));
MODULE_SCOPE void	TclSetBignumIntRep _ANSI_ARGS_((Tcl_Obj *objPtr,
			    mp_int *bignumValue));
MODULE_SCOPE void	TclSetProcessGlobalValue _ANSI_ARGS_ ((
			    ProcessGlobalValue *pgvPtr, Tcl_Obj *newValue,
			    Tcl_Encoding encoding));
MODULE_SCOPE VOID	TclSignalExitThread _ANSI_ARGS_((Tcl_ThreadId id,
			    int result));
MODULE_SCOPE int	TclSubstTokens _ANSI_ARGS_((Tcl_Interp *interp,
			    Tcl_Token *tokenPtr, int count,
			    int *tokensLeftPtr));
MODULE_SCOPE void	TclTransferResult _ANSI_ARGS_((
			    Tcl_Interp *sourceInterp, int result,
			    Tcl_Interp *targetInterp));
MODULE_SCOPE Tcl_Obj *	TclpNativeToNormalized _ANSI_ARGS_((
			    ClientData clientData));
MODULE_SCOPE Tcl_Obj *	TclpFilesystemPathType _ANSI_ARGS_((
			    Tcl_Obj* pathPtr));
MODULE_SCOPE Tcl_PackageInitProc* TclpFindSymbol _ANSI_ARGS_((
			    Tcl_Interp *interp, Tcl_LoadHandle loadHandle,
			    CONST char *symbol));
MODULE_SCOPE int	TclpDlopen _ANSI_ARGS_((Tcl_Interp *interp, 
			    Tcl_Obj *pathPtr, Tcl_LoadHandle *loadHandle, 
			    Tcl_FSUnloadFileProc **unloadProcPtr));
MODULE_SCOPE int	TclpUtime _ANSI_ARGS_((Tcl_Obj *pathPtr,
			    struct utimbuf *tval));
#ifdef TCL_LOAD_FROM_MEMORY
MODULE_SCOPE void*	TclpLoadMemoryGetBuffer _ANSI_ARGS_((
			    Tcl_Interp *interp, int size));
MODULE_SCOPE int	TclpLoadMemory _ANSI_ARGS_((Tcl_Interp *interp, 
			    void *buffer, int size, int codeSize, 
			    Tcl_LoadHandle *loadHandle, 
			    Tcl_FSUnloadFileProc **unloadProcPtr));
#endif
MODULE_SCOPE void	TclInitThreadStorage(void);
MODULE_SCOPE void	TclpFinalizeThreadDataThread(void);
MODULE_SCOPE void	TclFinalizeThreadStorage(void);

/*
 *----------------------------------------------------------------
 * Command procedures in the generic core:
 *----------------------------------------------------------------
 */

MODULE_SCOPE int	Tcl_AfterObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_AppendObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_ArrayObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_BinaryObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_BreakObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_CaseObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_CatchObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_CdObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	TclChanTruncateObjCmd _ANSI_ARGS_((
			    ClientData clientData, Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	TclClockClicksObjCmd _ANSI_ARGS_((
			    ClientData clientData, Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	TclClockGetenvObjCmd _ANSI_ARGS_((
			    ClientData clientData, Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	TclClockMicrosecondsObjCmd _ANSI_ARGS_((
			    ClientData clientData, Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	TclClockMillisecondsObjCmd _ANSI_ARGS_((
			    ClientData clientData, Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	TclClockSecondsObjCmd _ANSI_ARGS_((
			    ClientData clientData, Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	TclClockLocaltimeObjCmd _ANSI_ARGS_((
			    ClientData clientData, Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	TclClockMktimeObjCmd _ANSI_ARGS_((
			    ClientData clientData, Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	TclClockOldscanObjCmd _ANSI_ARGS_((
			    ClientData clientData, Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_CloseObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_ConcatObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_ContinueObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE Tcl_TimerToken TclCreateAbsoluteTimerHandler _ANSI_ARGS_((
			    Tcl_Time *timePtr, Tcl_TimerProc *proc,
			    ClientData clientData));
MODULE_SCOPE int	TclDefaultBgErrorHandlerObjCmd _ANSI_ARGS_((
			    ClientData clientData, Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_DictObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_EncodingObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	TclEncodingDirsObjCmd _ANSI_ARGS_((
			    ClientData clientData, Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_EofObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_ErrorObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_EvalObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_ExecObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_ExitObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_ExprObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_FblockedObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_FconfigureObjCmd _ANSI_ARGS_((
			    ClientData clientData, Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_FcopyObjCmd _ANSI_ARGS_((ClientData dummy,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_FileObjCmd _ANSI_ARGS_((ClientData dummy,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_FileEventObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_FlushObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_ForObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_ForeachObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_FormatObjCmd _ANSI_ARGS_((ClientData dummy,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_GetsObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_GlobalObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_GlobObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_IfObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_IncrObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_InfoObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_InterpObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int argc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_JoinObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_LappendObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_LassignObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_LindexObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_LinsertObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_LlengthObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_ListObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_LoadObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_LrangeObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_LrepeatObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_LreplaceObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_LsearchObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_LsetObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp* interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_LsortObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_NamespaceObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_OpenObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_PackageObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_PidObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_PutsObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_PwdObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_ReadObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_RegexpObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_RegsubObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_RenameObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_ReturnObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_ScanObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_SeekObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_SetObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_SplitObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_SocketObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_SourceObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_StringObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_SubstObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_SwitchObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_TellObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_TimeObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_TraceObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_UnloadObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_UnsetObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_UpdateObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_UplevelObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_UpvarObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_VariableObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_VwaitObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));
MODULE_SCOPE int	Tcl_WhileObjCmd _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]));

/*
 *----------------------------------------------------------------
 * Compilation procedures for commands in the generic core:
 *----------------------------------------------------------------
 */

MODULE_SCOPE int	TclCompileAppendCmd _ANSI_ARGS_((Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, struct CompileEnv *envPtr));
MODULE_SCOPE int	TclCompileBreakCmd _ANSI_ARGS_((Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, struct CompileEnv *envPtr));
MODULE_SCOPE int	TclCompileCatchCmd _ANSI_ARGS_((Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, struct CompileEnv *envPtr));
MODULE_SCOPE int	TclCompileContinueCmd _ANSI_ARGS_((Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, struct CompileEnv *envPtr));
MODULE_SCOPE int	TclCompileDictCmd _ANSI_ARGS_((Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, struct CompileEnv *envPtr));
MODULE_SCOPE int	TclCompileExprCmd _ANSI_ARGS_((Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, struct CompileEnv *envPtr));
MODULE_SCOPE int	TclCompileForCmd _ANSI_ARGS_((Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, struct CompileEnv *envPtr));
MODULE_SCOPE int	TclCompileForeachCmd _ANSI_ARGS_((Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, struct CompileEnv *envPtr));
MODULE_SCOPE int	TclCompileIfCmd _ANSI_ARGS_((Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, struct CompileEnv *envPtr));
MODULE_SCOPE int	TclCompileIncrCmd _ANSI_ARGS_((Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, struct CompileEnv *envPtr));
MODULE_SCOPE int	TclCompileLappendCmd _ANSI_ARGS_((Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, struct CompileEnv *envPtr));
MODULE_SCOPE int	TclCompileLassignCmd _ANSI_ARGS_((Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, struct CompileEnv *envPtr));
MODULE_SCOPE int	TclCompileLindexCmd _ANSI_ARGS_((Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, struct CompileEnv *envPtr));
MODULE_SCOPE int	TclCompileListCmd _ANSI_ARGS_((Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, struct CompileEnv *envPtr));
MODULE_SCOPE int	TclCompileLlengthCmd _ANSI_ARGS_((Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, struct CompileEnv *envPtr));
MODULE_SCOPE int	TclCompileLsetCmd _ANSI_ARGS_((Tcl_Interp* interp,
			    Tcl_Parse* parsePtr, struct CompileEnv* envPtr));
MODULE_SCOPE int	TclCompileRegexpCmd _ANSI_ARGS_((Tcl_Interp* interp,
			    Tcl_Parse* parsePtr, struct CompileEnv* envPtr));
MODULE_SCOPE int	TclCompileReturnCmd _ANSI_ARGS_((Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, struct CompileEnv *envPtr));
MODULE_SCOPE int	TclCompileSetCmd _ANSI_ARGS_((Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, struct CompileEnv *envPtr));
MODULE_SCOPE int	TclCompileStringCmd _ANSI_ARGS_((Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, struct CompileEnv *envPtr));
MODULE_SCOPE int	TclCompileSwitchCmd _ANSI_ARGS_((Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, struct CompileEnv *envPtr));
MODULE_SCOPE int	TclCompileWhileCmd _ANSI_ARGS_((Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, struct CompileEnv *envPtr));

/*
 * Functions defined in generic/tclVar.c and currenttly exported only 
 * for use by the bytecode compiler and engine. Some of these could later 
 * be placed in the public interface.
 */

MODULE_SCOPE Var *	TclLookupArrayElement _ANSI_ARGS_((Tcl_Interp *interp,
			    CONST char *arrayName, CONST char *elName,
			    CONST int flags, CONST char *msg,
			    CONST int createPart1, CONST int createPart2,
			    Var *arrayPtr));	
MODULE_SCOPE Var *	TclObjLookupVar _ANSI_ARGS_((Tcl_Interp *interp,
			    Tcl_Obj *part1Ptr, CONST char *part2, int flags,
			    CONST char *msg, CONST int createPart1,
			    CONST int createPart2, Var **arrayPtrPtr));
MODULE_SCOPE Tcl_Obj *	TclPtrGetVar _ANSI_ARGS_((Tcl_Interp *interp,
			    Var *varPtr, Var *arrayPtr, CONST char *part1,
			    CONST char *part2, CONST int flags));
MODULE_SCOPE Tcl_Obj *	TclPtrSetVar _ANSI_ARGS_((Tcl_Interp *interp,
			    Var *varPtr, Var *arrayPtr, CONST char *part1,
			    CONST char *part2, Tcl_Obj *newValuePtr,
			    CONST int flags));
MODULE_SCOPE Tcl_Obj *	TclPtrIncrObjVar _ANSI_ARGS_((Tcl_Interp *interp,
			    Var *varPtr, Var *arrayPtr, CONST char *part1,
			    CONST char *part2, Tcl_Obj *incrPtr,
			    CONST int flags));
#if 0
MODULE_SCOPE Tcl_Obj *	TclPtrIncrVar _ANSI_ARGS_((Tcl_Interp *interp,
			    Var *varPtr, Var *arrayPtr, CONST char *part1,
			    CONST char *part2, CONST long i, CONST int flags));
MODULE_SCOPE Tcl_Obj *	TclPtrIncrWideVar _ANSI_ARGS_((Tcl_Interp *interp,
			    Var *varPtr, Var *arrayPtr, CONST char *part1,
			    CONST char *part2, CONST Tcl_WideInt i,
			    CONST int flags));
#endif
MODULE_SCOPE void	TclInvalidateNsPath _ANSI_ARGS_((Namespace *nsPtr));

/*
 *----------------------------------------------------------------
 * Macros used by the Tcl core to create and release Tcl objects.
 * TclNewObj(objPtr) creates a new object denoting an empty string.
 * TclDecrRefCount(objPtr) decrements the object's reference count,
 * and frees the object if its reference count is zero.
 * These macros are inline versions of Tcl_NewObj() and
 * Tcl_DecrRefCount(). Notice that the names differ in not having
 * a "_" after the "Tcl". Notice also that these macros reference
 * their argument more than once, so you should avoid calling them
 * with an expression that is expensive to compute or has
 * side effects. The ANSI C "prototypes" for these macros are:
 *
 * MODULE_SCOPE void	TclNewObj _ANSI_ARGS_((Tcl_Obj *objPtr));
 * MODULE_SCOPE void	TclDecrRefCount _ANSI_ARGS_((Tcl_Obj *objPtr));
 *
 * These macros are defined in terms of two macros that depend on 
 * memory allocator in use: TclAllocObjStorage, TclFreeObjStorage.
 * They are defined below.
 *----------------------------------------------------------------
 */

#ifdef TCL_COMPILE_STATS
#  define TclIncrObjsAllocated() \
    tclObjsAlloced++
#  define TclIncrObjsFreed() \
................................................................................

# define TclDecrRefCount(objPtr) \
    if (--(objPtr)->refCount <= 0) { \
	if ((objPtr)->typePtr && (objPtr)->typePtr->freeIntRepProc) { \
	    TclFreeObj(objPtr); \
	} else { \
	    if ((objPtr)->bytes \
                    && ((objPtr)->bytes != tclEmptyStringRep)) { \
		ckfree((char *) (objPtr)->bytes); \
	    } \
	    TclFreeObjStorage(objPtr); \
	    TclIncrObjsFreed(); \
	} \
    }
	    
#if defined(PURIFY)

/*
 * The PURIFY mode is like the regular mode, but instead of doing block
 * Tcl_Obj allocation and keeping a freed list for efficiency, it always
 * allocates and frees a single Tcl_Obj so that tools like Purify can
 * better track memory leaks
 */

#  define TclAllocObjStorage(objPtr) \
	(objPtr) = (Tcl_Obj *) Tcl_Alloc(sizeof(Tcl_Obj))

#  define TclFreeObjStorage(objPtr) \
	ckfree((char *) (objPtr))

#elif defined(TCL_THREADS) && defined(USE_THREAD_ALLOC)

/*
 * The TCL_THREADS mode is like the regular mode but allocates Tcl_Obj's
 * from per-thread caches.
 */

MODULE_SCOPE Tcl_Obj *	TclThreadAllocObj _ANSI_ARGS_((void));
MODULE_SCOPE void	TclThreadFreeObj _ANSI_ARGS_((Tcl_Obj *));
MODULE_SCOPE Tcl_Mutex *TclpNewAllocMutex _ANSI_ARGS_((void));
MODULE_SCOPE void   TclFreeAllocCache _ANSI_ARGS_((void *));
MODULE_SCOPE void *	TclpGetAllocCache _ANSI_ARGS_((void));
MODULE_SCOPE void	TclpSetAllocCache _ANSI_ARGS_((void *));
MODULE_SCOPE void	TclFinalizeThreadAlloc _ANSI_ARGS_((void));
MODULE_SCOPE void	TclpFreeAllocMutex _ANSI_ARGS_((Tcl_Mutex* mutex));
MODULE_SCOPE void   TclpFreeAllocCache _ANSI_ARGS_((void *));

#  define TclAllocObjStorage(objPtr) \
	(objPtr) = TclThreadAllocObj()

#  define TclFreeObjStorage(objPtr) \
	TclThreadFreeObj((objPtr))

................................................................................
	Tcl_MutexLock(&tclObjMutex); \
	(objPtr)->internalRep.otherValuePtr = (VOID *) tclFreeObjList; \
	tclFreeObjList = (objPtr); \
	Tcl_MutexUnlock(&tclObjMutex)
#endif

#else /* TCL_MEM_DEBUG */
MODULE_SCOPE void	TclDbInitNewObj _ANSI_ARGS_((Tcl_Obj *objPtr));

# define TclDbNewObj(objPtr, file, line) \
    TclIncrObjsAllocated(); \
    (objPtr) = (Tcl_Obj *) Tcl_DbCkalloc(sizeof(Tcl_Obj), (file), (line)); \
    TclDbInitNewObj(objPtr);

# define TclNewObj(objPtr) \
................................................................................
    TclDbNewListObjDirect(objc, objv, __FILE__, __LINE__)

#undef USE_THREAD_ALLOC
#endif /* TCL_MEM_DEBUG */

/*
 *----------------------------------------------------------------
 * Macro used by the Tcl core to set a Tcl_Obj's string representation
 * to a copy of the "len" bytes starting at "bytePtr". This code
 * works even if the byte array contains NULLs as long as the length
 * is correct. Because "len" is referenced multiple times, it should
 * be as simple an expression as possible. The ANSI C "prototype" for
 * this macro is:
 *
 * MODULE_SCOPE void	TclInitStringRep _ANSI_ARGS_((
 *			    Tcl_Obj *objPtr, char *bytePtr, int len));
 *
 * This macro should only be called on an unshared objPtr where
 *  objPtr->typePtr->freeIntRepProc == NULL
 *----------------------------------------------------------------
 */

#define TclInitStringRep(objPtr, bytePtr, len) \
................................................................................
		(unsigned) (len)); \
	(objPtr)->bytes[len] = '\0'; \
	(objPtr)->length = (len); \
    }

/*
 *----------------------------------------------------------------
 * Macro used by the Tcl core to get the string representation's
 * byte array pointer from a Tcl_Obj. This is an inline version
 * of Tcl_GetString(). The macro's expression result is the string
 * rep's byte pointer which might be NULL. The bytes referenced by 
 * this pointer must not be modified by the caller.
 * The ANSI C "prototype" for this macro is:
 *
 * MODULE_SCOPE char *	TclGetString _ANSI_ARGS_((Tcl_Obj *objPtr));
 *----------------------------------------------------------------
 */

#define TclGetString(objPtr) \
    ((objPtr)->bytes? (objPtr)->bytes : Tcl_GetString((objPtr)))

/*
 *----------------------------------------------------------------
 * Macro used by the Tcl core to clean out an object's internal
 * representation.  Does not actually reset the rep's bytes.
 * The ANSI C "prototype" for this macro is:
 *
 * MODULE_SCOPE void	TclFreeIntRep _ANSI_ARGS_((Tcl_Obj *objPtr));
 *----------------------------------------------------------------
 */

#define TclFreeIntRep(objPtr) \
    if ((objPtr)->typePtr != NULL && \
	    (objPtr)->typePtr->freeIntRepProc != NULL) { \
	(objPtr)->typePtr->freeIntRepProc(objPtr); \
    }

/*
 *----------------------------------------------------------------
 * Macro used by the Tcl core to clean out an object's string
 * representation.  The ANSI C "prototype" for this macro is:
 *
 * MODULE_SCOPE void	TclInvalidateStringRep _ANSI_ARGS_((Tcl_Obj *objPtr));
 *----------------------------------------------------------------
 */

#define TclInvalidateStringRep(objPtr) \
    if (objPtr->bytes != NULL) { \
	if (objPtr->bytes != tclEmptyStringRep) {\
	    ckfree((char *) objPtr->bytes);\
................................................................................
	objPtr->bytes = NULL;\
    }\


#if 0
/*
 *----------------------------------------------------------------
 * Macro used by the Tcl core to get a Tcl_WideInt value out of
 * a Tcl_Obj of the "wideInt" type.  
 *----------------------------------------------------------------
 */

#ifndef NO_WIDE_TYPE
#    define TclGetWide(resultVar, objPtr) \
	(resultVar) = (objPtr)->internalRep.wideValue
#    define TclGetLongFromWide(resultVar, objPtr) \
	(resultVar) = Tcl_WideAsLong((objPtr)->internalRep.wideValue)
#endif
#endif

/*
 *----------------------------------------------------------------
 * Macro used by the Tcl core get a unicode char from a utf string.
 * It checks to see if we have a one-byte utf char before calling
 * the real Tcl_UtfToUniChar, as this will save a lot of time for
 * primarily ascii string handling. The macro's expression result
 * is 1 for the 1-byte case or the result of Tcl_UtfToUniChar.
 * The ANSI C "prototype" for this macro is:
 *
 * MODULE_SCOPE int	TclUtfToUniChar _ANSI_ARGS_((
 *			    CONST char *string, Tcl_UniChar *ch));
 *----------------------------------------------------------------
 */

#define TclUtfToUniChar(str, chPtr) \
	((((unsigned char) *(str)) < 0xC0) ? \
	    ((*(chPtr) = (Tcl_UniChar) *(str)), 1) \
	    : Tcl_UtfToUniChar(str, chPtr))

/*
 *----------------------------------------------------------------
 * Macro used by the Tcl core to compare Unicode strings.  On
 * big-endian systems we can use the more efficient memcmp, but
 * this would not be lexically correct on little-endian systems.
 * The ANSI C "prototype" for this macro is:
 *
 * MODULE_SCOPE int	TclUniCharNcmp _ANSI_ARGS_((
 *			    CONST Tcl_UniChar *cs,
 *			    CONST Tcl_UniChar *ct, unsigned long n));
 *----------------------------------------------------------------
 */

#ifdef WORDS_BIGENDIAN
#   define TclUniCharNcmp(cs,ct,n) memcmp((cs),(ct),(n)*sizeof(Tcl_UniChar))
#else /* !WORDS_BIGENDIAN */
#   define TclUniCharNcmp Tcl_UniCharNcmp
#endif /* WORDS_BIGENDIAN */

/*
 *----------------------------------------------------------------
 * Macro used by the Tcl core to increment a namespace's export
 * export epoch counter.
 * The ANSI C "prototype" for this macro is:
 *
 * MODULE_SCOPE void	TclInvalidateNsCmdLookup _ANSI_ARGS_((
 *			    Namespace *nsPtr));
 *----------------------------------------------------------------
 */

#define TclInvalidateNsCmdLookup(nsPtr) \
    if ((nsPtr)->numExportPatterns) { \
	(nsPtr)->exportLookupEpoch++; \
    }
................................................................................
 *----------------------------------------------------------------------
 *
 * Core procedures added to libtommath for bignum manipulation.
 *
 *----------------------------------------------------------------------
 */

MODULE_SCOPE void* TclBNAlloc( size_t nBytes );
MODULE_SCOPE void* TclBNRealloc( void* oldBlock, size_t newNBytes );
MODULE_SCOPE void TclBNFree( void* block );
MODULE_SCOPE void TclBNInitBignumFromLong( mp_int* bignum, long initVal );
MODULE_SCOPE void TclBNInitBignumFromWideUInt(mp_int* bignum,
					      Tcl_WideUInt initVal);


/*
 *----------------------------------------------------------------
 * Macro used by the Tcl core to check whether a pattern has
 * any characters special to [string match].
 * The ANSI C "prototype" for this macro is:
 *
 * MODULE_SCOPE int	TclMatchIsTrivial _ANSI_ARGS_((
 * 			    CONST char *pattern));
 *----------------------------------------------------------------
 */

#define TclMatchIsTrivial(pattern) strpbrk((pattern), "*[]]?\\") == NULL

/*
 *----------------------------------------------------------------
 * Macro used by the Tcl core to write the string rep of a long
 * integer to a character buffer.
 * The ANSI C "prototype" for this macro is:
 *
 * MODULE_SCOPE int	TclFormatInt _ANSI_ARGS_((char *buf, long n));
 *----------------------------------------------------------------
 */

#define TclFormatInt(buf, n) sprintf((buf), "%ld", (long)(n))

/*
 *----------------------------------------------------------------
 * Macros used by the Tcl core to set a Tcl_Obj's numeric representation
 * avoiding the corresponding function calls in time critical parts of the
 * core. They should only be called on unshared objects. The ANSI C
 * "prototypes" for these macros are:  
 *
 * MODULE_SCOPE void	TclSetIntObj _ANSI_ARGS_((Tcl_Obj *objPtr,
 *                           int intValue));
 * MODULE_SCOPE void	TclSetLongObj _ANSI_ARGS_((Tcl_Obj *objPtr,
 *                           long longValue));
 * MODULE_SCOPE void	TclSetBooleanObj _ANSI_ARGS_((Tcl_Obj *objPtr,
 *                           long boolValue));
 * MODULE_SCOPE void	TclSetWideIntObj _ANSI_ARGS_((Tcl_Obj *objPtr,
 *                          Tcl_WideInt w));
 * MODULE_SCOPE void	TclSetDoubleObj _ANSI_ARGS_((Tcl_Obj *objPtr,
 *                          double d));
 *
 *----------------------------------------------------------------
 */

#define TclSetIntObj(objPtr, i) \
    TclInvalidateStringRep(objPtr);\
    TclFreeIntRep(objPtr); \
    (objPtr)->internalRep.longValue = (long)(i); \
    (objPtr)->typePtr = &tclIntType

#define TclSetLongObj(objPtr, l) \
    TclSetIntObj((objPtr), (l))

/*
 * NOTE: There is to be no such thing as a "pure" boolean.
 * Boolean values set programmatically go straight to being
 * "int" Tcl_Obj's, with value 0 or 1.  The only "boolean"
 * Tcl_Obj's shall be those holding the cached boolean value
 * of strings like: "yes", "no", "true", "false", "on", "off".
 */

#define TclSetBooleanObj(objPtr, b) \
    TclSetIntObj((objPtr), ((b)? 1 : 0));

#ifndef NO_WIDE_TYPE
#define TclSetWideIntObj(objPtr, w) \
    TclInvalidateStringRep(objPtr);\
    TclFreeIntRep(objPtr); \
................................................................................
    TclInvalidateStringRep(objPtr);\
    TclFreeIntRep(objPtr); \
    (objPtr)->internalRep.doubleValue = (double)(d); \
    (objPtr)->typePtr = &tclDoubleType

/*
 *----------------------------------------------------------------
 * Macros used by the Tcl core to create and initialise objects of
 * standard types, avoiding the corresponding function calls in time
 * critical parts of the core. The ANSI C "prototypes" for these
 * macros are: 
 *
 * MODULE_SCOPE void	TclNewIntObj _ANSI_ARGS_((Tcl_Obj *objPtr,
 *                          int i));
 * MODULE_SCOPE void	TclNewLongObj _ANSI_ARGS_((Tcl_Obj *objPtr,
 *                          long l));
 * MODULE_SCOPE void	TclNewBooleanObj _ANSI_ARGS_((Tcl_Obj *objPtr,
 *                          int b));
 * MODULE_SCOPE void	TclNewWideObj _ANSI_ARGS_((Tcl_Obj *objPtr,
 *                          Tcl_WideInt w));
 * MODULE_SCOPE void	TclNewDoubleObj _ANSI_ARGS_((Tcl_Obj *objPtr),
 *                          double d);
 * MODULE_SCOPE void	TclNewStringObj _ANSI_ARGS_((Tcl_Obj *objPtr)
 *                          char *s, int len);
 *
 *----------------------------------------------------------------
 */

#ifndef TCL_MEM_DEBUG
#define TclNewIntObj(objPtr, i) \
    TclIncrObjsAllocated(); \
    TclAllocObjStorage(objPtr); \
    (objPtr)->refCount = 0; \
    (objPtr)->bytes = NULL; \
    (objPtr)->internalRep.longValue = (long)(i); \
................................................................................
#endif

#include "tclPort.h"
#include "tclIntDecls.h"
#include "tclIntPlatDecls.h"

#endif /* _TCLINT */














|
|

|













|
|
|
<
|
|
|







 







|
|










|
|
|
|


|
|
|




|
|
<







 







|
|
<




|
|

<
|



|


<






<
<
|
|
|

<
|
|

|
|
<
|







 







|
|



|
|
|
|
|
|





|
|

|
|
<



|
|
<

|
|
|
<
|
|
|





|
|
|

|
|

|
|
|
|
|
|


|
|

|
|
|
|
|
|
|
|
|
|


|
|
|
|
|

|
|
|
|
|
|

|
|
|
|
|
|







 







|
|







 







|
|

|
|
|
|
|
|
|







 







|
<




|
|
|



|
|


|


|
|



|
|
|



>
|
|
|
|
|
|
>
|
|
|
|
|
|



|
|
<
|
|





|
|
<
|
|
|
|
|
|




|
|
|
|





|
|
<
|
|
|
|



|
|
<




|
|


|
|
|
|
|
|
|
|
|
|
|



|
|
|
|
|
|




|


|
|
|
|
|
|
|


|
|
|
|
<
|
|
|
|



|
|
|
|
|
|
<





|




|
|







|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<

|
|
|
|

|
|
|
|

|
|
|
|
|
|
|
|
<
|
|
>

|
|


|







 







|
|





|
|
|
|
|
|







 







|
|
|
|
|
|
|
|

|







 







|


|







 







|












|
|












|
|

|
|
|
|
|
|




|
|
|

|
|




|









|
|
|
|
|
|
|
|




|
|



|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|



|




|
|










|
|
|
|
|




|
|
<
|
|
|
|
|
|



|
|

|

|
|

|


|
|


|
|
|
|





|



|
|
|
|
|
|
|
|







 







|
|



|
|



|
|
|
|




|
|
|
|
|
<




|
|










|
|
|







|
<




|
|








|
|
|





|
|
|




|
|


|
<
|
|




>
>
|




|
|
<





|
|







|
|


|
|
|
|
|
|
<
|
|
|
|
|




|
|






|
|



|
|
|
|
|
<



|
|
|


|






|
|
|
|
|








|
|
|
|
|
<
|
|
<
|
|
|
<
|
|
<
|
|



|
|
|

|
<
|
|
|
|
|
|
|
|
<










|
|
|
|
|

|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
>
|
|











|
|
|
|
|
>







|
|
|
|
|












|
|




|
|



|
|
|



|
|
|
|




|
|
<
|










|
|





|
|
|
|
|





|

|
|
|
|

|
|
|
|
|



|



>











|
|
|
<
|
|








|
|
|

|
|













|
|
|
<
|




<

|
|
|








|
|






|
|
|
|
|
|
|
|
|
<
|
|
|
|
|
|






|
|


|
|

|
|
|

<
<

|
|




|
|
|




|
|


|
|
|

|
|





|
|


|
|
|


|
|


|


|
|
|
|
|
|
|
|









|


|
|
|
|
|
<
|
|
|
|
|
|
|
|
|
|


|
|

|

|

|


|
|
|

|
|







 







|
|







 







|
|






|
|
>
|
|
|
|



>
|
|
|
|
>
|
|

|
|
|
|



|
|




|
|
|
|






|
|
|
|
|
|
|
|
>







|
|
|



|
|



|
|
|



|
|







|
|
|
|
>


|
|
|
<
>
|
>
|
|
|




|
|
|


|








|
|
|
|
|
|
|
|
|
|
|
|
|
|







 







|
|










|
>

|
>








|









|
|
|











|
|
|










|
|








|
|
|












|
|
|
|
|
|
<
|
|
|
|







|
|
|
|
|







 







|







|
|

|
|
|

|
|
|
|

|
|
<


|
|
|
|

|







<
|
|
|
<
>
|
|



|


|
|
|
|
|


|
|
|
|


|
|




|



|

|
|









|










|
|
|
|
<
<







 







|
|


|
|
|
<
|
>

>

|
|
|
|
|
|

|
<
|
|
|
|
|
|







 







>
|





|







 







|
|
|







|
<



|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<





|
|
<
|
|
|
|
|

|
|

|
|
|







 







|






|





|
|











|
|


|
|
|
|
|
|
|
|
|







 







|







 







|
|
|
|
|
<

<
|







 







|
|
|
<
|
|

|









|
|

|











|
|

|







 







|
|













|
|
|
|
<
|

<
|










|
|
|
|

|
<
|











|
<
|

|
<







 







|
|
|
|
|
|
<



|
<
|

|
<



|



|
<
|

|



|






|

|
<
|
<
|
<
|
<
|
<
<













|
|
<
|
|

>







 







|
|
|
<

|
<
|
<
|
<
|
<
|
<
|
<



>







 







|
>
>
>
>
>
>
>
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

32
33
34
35
36
37
38
39
40
41
..
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96

97
98
99
100
101
102
103
...
109
110
111
112
113
114
115
116
117

118
119
120
121
122
123
124

125
126
127
128
129
130
131

132
133
134
135
136
137


138
139
140
141

142
143
144
145
146

147
148
149
150
151
152
153
154
...
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191

192
193
194
195
196

197
198
199
200

201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
...
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
...
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
...
323
324
325
326
327
328
329
330

331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377

378
379
380
381
382
383
384
385
386

387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407

408
409
410
411
412
413
414
415
416

417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464

465
466
467
468
469
470
471
472
473
474
475
476
477

478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517

518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536

537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
...
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
...
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
...
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
...
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794

795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
...
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876

877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903

904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937

938
939
940
941
942
943
944
945
946
947
948
949
950
951
952

953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976

977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003

1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036

1037
1038

1039
1040
1041

1042
1043

1044
1045
1046
1047
1048
1049
1050
1051
1052
1053

1054
1055
1056
1057
1058
1059
1060
1061

1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166

1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228

1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260

1261
1262
1263
1264
1265

1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294

1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317


1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387

1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
....
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
....
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554

1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
....
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707

1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
....
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763

1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778

1779
1780
1781

1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841


1842
1843
1844
1845
1846
1847
1848
....
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864

1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877

1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
....
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
....
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972

1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560













































2561
2562
2563
2564
2565
2566
2567

2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
....
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
....
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
....
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704

2705

2706
2707
2708
2709
2710
2711
2712
2713
....
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729

2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
....
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795

2796
2797

2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814

2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827

2828
2829
2830

2831
2832
2833
2834
2835
2836
2837
....
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852

2853
2854
2855
2856

2857
2858
2859

2860
2861
2862
2863
2864
2865
2866
2867

2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883

2884

2885

2886

2887


2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902

2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
....
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928

2929
2930

2931

2932

2933

2934

2935

2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
....
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
 *
 * Copyright (c) 1987-1993 The Regents of the University of California.
 * Copyright (c) 1993-1997 Lucent Technologies.
 * Copyright (c) 1994-1998 Sun Microsystems, Inc.
 * Copyright (c) 1998-19/99 by Scriptics Corporation.
 * Copyright (c) 2001, 2002 by Kevin B. Kenny.  All rights reserved.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclInt.h,v 1.202.2.35 2005/08/29 18:38:45 dgp Exp $
 */

#ifndef _TCLINT
#define _TCLINT

/*
 * Some numerics configuration options
 */

#define NO_WIDE_TYPE
#undef	ACCEPT_NAN

/*
 * Common include files needed by most of the Tcl source files are included
 * here, so that system-dependent personalizations for the include files only
 * have to be made in once place. This results in a few extra includes, but

 * greater modularity. The order of the three groups of #includes is
 * important. For example, stdio.h is needed by tcl.h, and the _ANSI_ARGS_
 * declaration in tcl.h is needed by stdlib.h in some configurations.
 */

#ifdef HAVE_TCL_CONFIG_H
#include "tclConfig.h"
#endif
#ifndef _TCL
#include "tcl.h"
................................................................................
#include <stddef.h>
#else
typedef int ptrdiff_t;
#endif

/*
 * Ensure WORDS_BIGENDIAN is defined correcly:
 * Needs to happen here in addition to configure to work with fat compiles on
 * Darwin (i.e. ppc and i386 at the same time).
 */

#ifdef HAVE_SYS_TYPES_H
#    include <sys/types.h>
#endif
#ifdef HAVE_SYS_PARAM_H
#    include <sys/param.h>
#endif
#ifdef BYTE_ORDER
#    ifdef BIG_ENDIAN
#	 if BYTE_ORDER == BIG_ENDIAN
#	     undef WORDS_BIGENDIAN
#	     define WORDS_BIGENDIAN
#	 endif
#    endif
#    ifdef LITTLE_ENDIAN
#	 if BYTE_ORDER == LITTLE_ENDIAN
#	     undef WORDS_BIGENDIAN
#	 endif
#    endif
#endif

/*
 * Used to tag functions that are only to be visible within the module being
 * built and not outside it (where this is supported by the linker).

 */

#ifndef MODULE_SCOPE
#   ifdef __cplusplus
#	define MODULE_SCOPE extern "C"
#   else
#	define MODULE_SCOPE extern
................................................................................
 * having a tclWideIntType separate from the tclIntType.
 */
#ifdef TCL_WIDE_INT_IS_LONG
#define NO_WIDE_TYPE
#endif

/*
 * The following procedures allow namespaces to be customized to support
 * special name resolution rules for commands/variables.

 */

struct Tcl_ResolvedVarInfo;

typedef Tcl_Var (Tcl_ResolveRuntimeVarProc) (Tcl_Interp* interp,
	struct Tcl_ResolvedVarInfo *vinfoPtr);


typedef void (Tcl_ResolveVarDeleteProc)(struct Tcl_ResolvedVarInfo *vinfoPtr);

/*
 * The following structure encapsulates the routines needed to resolve a
 * variable reference at runtime. Any variable specific state will typically
 * be appended to this structure.
 */


typedef struct Tcl_ResolvedVarInfo {
    Tcl_ResolveRuntimeVarProc *fetchProc;
    Tcl_ResolveVarDeleteProc *deleteProc;
} Tcl_ResolvedVarInfo;



typedef int (Tcl_ResolveCompiledVarProc) (Tcl_Interp* interp,
	CONST84 char* name, int length, Tcl_Namespace *context,
	Tcl_ResolvedVarInfo **rPtr);


typedef int (Tcl_ResolveVarProc) (Tcl_Interp* interp, CONST84 char* name,
	Tcl_Namespace *context, int flags, Tcl_Var *rPtr);

typedef int (Tcl_ResolveCmdProc) (Tcl_Interp* interp, CONST84 char* name,
	Tcl_Namespace *context, int flags, Tcl_Command *rPtr);


typedef struct Tcl_ResolverInfo {
    Tcl_ResolveCmdProc *cmdResProc;	/* Procedure handling command name
					 * resolution. */
    Tcl_ResolveVarProc *varResProc;	/* Procedure handling variable name
					 * resolution for variables that
					 * can only be handled at runtime. */
    Tcl_ResolveCompiledVarProc *compiledVarResProc;
................................................................................

typedef struct Tcl_Ensemble Tcl_Ensemble;
typedef struct NamespacePathEntry NamespacePathEntry;

/*
 * The structure below defines a namespace.
 * Note: the first five fields must match exactly the fields in a
 * Tcl_Namespace structure (see tcl.h). If you change one, be sure to change
 * the other.
 */

typedef struct Namespace {
    char *name;			/* The namespace's simple (unqualified) name.
				 * This contains no ::'s. The name of the
				 * global namespace is "" although "::" is an
				 * synonym. */
    char *fullName;		/* The namespace's fully qualified name. This
				 * starts with ::. */
    ClientData clientData;	/* An arbitrary value associated with this
				 * namespace. */
    Tcl_NamespaceDeleteProc *deleteProc;
				/* Procedure invoked when deleting the
				 * namespace to, e.g., free clientData. */
    struct Namespace *parentPtr;/* Points to the namespace that contains this
				 * one. NULL if this is the global
				 * namespace. */
    Tcl_HashTable childTable;	/* Contains any child namespaces. Indexed by
				 * strings; values have type (Namespace *). */

    long nsId;			/* Unique id for the namespace. */
    Tcl_Interp *interp;		/* The interpreter containing this
				 * namespace. */
    int flags;			/* OR-ed combination of the namespace status
				 * flags NS_DYING and NS_DEAD listed below. */

    int activationCount;	/* Number of "activations" or active call
				 * frames for this namespace that are on the
				 * Tcl call stack. The namespace won't be
				 * freed until activationCount becomes zero. */

    int refCount;		/* Count of references by namespaceName
				 * objects. The namespace can't be freed until
				 * refCount becomes zero. */
    Tcl_HashTable cmdTable;	/* Contains all the commands currently
				 * registered in the namespace. Indexed by
				 * strings; values have type (Command *).
				 * Commands imported by Tcl_Import have
				 * Command structures that point (via an
				 * ImportedCmdRef structure) to the Command
				 * structure in the source namespace's command
				 * table. */
    Tcl_HashTable varTable;	/* Contains all the (global) variables
				 * currently in this namespace. Indexed by
				 * strings; values have type (Var *). */
    char **exportArrayPtr;	/* Points to an array of string patterns
				 * specifying which commands are exported. A
				 * pattern may include "string match" style
				 * wildcard characters to specify multiple
				 * commands; however, no namespace qualifiers
				 * are allowed. NULL if no export patterns are
				 * registered. */
    int numExportPatterns;	/* Number of export patterns currently
				 * registered using "namespace export". */
    int maxExportPatterns;	/* Mumber of export patterns for which space
				 * is currently allocated. */
    int cmdRefEpoch;		/* Incremented if a newly added command
				 * shadows a command for which this namespace
				 * has already cached a Command * pointer;
				 * this causes all its cached Command*
				 * pointers to be invalidated. */
    int resolverEpoch;		/* Incremented whenever (a) the name
				 * resolution rules change for this namespace
				 * or (b) a newly added command shadows a
				 * command that is compiled to bytecodes. This
				 * invalidates all byte codes compiled in the
				 * namespace, causing the code to be
				 * recompiled under the new rules.*/
    Tcl_ResolveCmdProc *cmdResProc;
				/* If non-null, this procedure overrides the
				 * usual command resolution mechanism in Tcl.
				 * This procedure is invoked within
				 * Tcl_FindCommand to resolve all command
				 * references within the namespace. */
    Tcl_ResolveVarProc *varResProc;
				/* If non-null, this procedure overrides the
				 * usual variable resolution mechanism in Tcl.
				 * This procedure is invoked within
				 * Tcl_FindNamespaceVar to resolve all
				 * variable references within the namespace at
				 * runtime. */
    Tcl_ResolveCompiledVarProc *compiledVarResProc;
				/* If non-null, this procedure overrides the
				 * usual variable resolution mechanism in Tcl.
				 * This procedure is invoked within
				 * LookupCompiledLocal to resolve variable
				 * references within the namespace at compile
				 * time. */
    int exportLookupEpoch;	/* Incremented whenever a command is added to
				 * a namespace, removed from a namespace or
				 * the exports of a namespace are changed.
				 * Allows TIP#112-driven command lists to be
				 * validated efficiently. */
    Tcl_Ensemble *ensembles;	/* List of structures that contain the details
				 * of the ensembles that are implemented on
................................................................................

/*
 * An entry on a namespace's command resolution path.
 */

struct NamespacePathEntry {
    Namespace *nsPtr;		/* What does this path entry point to? If it
				 * is NULL, this path entry points is
				 * redundant and should be skipped. */
    Namespace *creatorNsPtr;	/* Where does this path entry point from? This
				 * allows for efficient invalidation of
				 * references when the path entry's target
				 * updates its current list of defined
				 * commands. */
    NamespacePathEntry *prevPtr, *nextPtr;
				/* Linked list pointers or NULL at either end
................................................................................
/*
 * Flags used to represent the status of a namespace:
 *
 * NS_DYING -	1 means Tcl_DeleteNamespace has been called to delete the
 *		namespace but there are still active call frames on the Tcl
 *		stack that refer to the namespace. When the last call frame
 *		referring to it has been popped, it's variables and command
 *		will be destroyed and it will be marked "dead" (NS_DEAD). The
 *		namespace can no longer be looked up by name.
 * NS_DEAD -	1 means Tcl_DeleteNamespace has been called to delete the
 *		namespace and no call frames still refer to it. Its variables
 *		and command have already been destroyed. This bit allows the
 *		namespace resolution code to recognize that the namespace is
 *		"deleted". When the last namespaceName object in any byte code
 *		unit that refers to the namespace has been freed (i.e., when
 *		the namespace's refCount is 0), the namespace's storage will
 *		be freed.
 */

#define NS_DYING	0x01
#define NS_DEAD		0x02

/*
 * Flags passed to TclGetNamespaceForQualName:
................................................................................
 */

#define TCL_CREATE_NS_IF_UNKNOWN	0x800
#define TCL_FIND_ONLY_NS		0x1000

/*
 *----------------------------------------------------------------
 * Data structures related to variables. These are used primarily in tclVar.c

 *----------------------------------------------------------------
 */

/*
 * The following structure defines a variable trace, which is used to invoke a
 * specific C procedure whenever certain operations are performed on a
 * variable.
 */

typedef struct VarTrace {
    Tcl_VarTraceProc *traceProc;/* Procedure to call when operations given by
				 * flags are performed on variable. */
    ClientData clientData;	/* Argument to pass to proc. */
    int flags;			/* What events the trace procedure is
				 * interested in: OR-ed combination of
				 * TCL_TRACE_READS, TCL_TRACE_WRITES,
				 * TCL_TRACE_UNSETS and TCL_TRACE_ARRAY. */
    struct VarTrace *nextPtr;	/* Next in list of traces associated with a
				 * particular variable. */
} VarTrace;

/*
 * The following structure defines a command trace, which is used to invoke a
 * specific C procedure whenever certain operations are performed on a
 * command.
 */

typedef struct CommandTrace {
    Tcl_CommandTraceProc *traceProc;
				/* Procedure to call when operations given by
				 * flags are performed on command. */
    ClientData clientData;	/* Argument to pass to proc. */
    int flags;			/* What events the trace procedure is
				 * interested in: OR-ed combination of
				 * TCL_TRACE_RENAME, TCL_TRACE_DELETE. */
    struct CommandTrace *nextPtr;
				/* Next in list of traces associated with a
				 * particular command. */
    int refCount;		/* Used to ensure this structure is not
				 * deleted too early. Keeps track of how many
				 * pieces of code have a pointer to this
				 * structure. */
} CommandTrace;

/*
 * When a command trace is active (i.e. its associated procedure is executing)
 * one of the following structures is linked into a list associated with the

 * command's interpreter. The information in the structure is needed in order
 * for Tcl to behave reasonably if traces are deleted while traces are active.
 */

typedef struct ActiveCommandTrace {
    struct Command *cmdPtr;	/* Command that's being traced. */
    struct ActiveCommandTrace *nextPtr;
				/* Next in list of all active command traces
				 * for the interpreter, or NULL if no more. */

    CommandTrace *nextTracePtr;	/* Next trace to check after current trace
				 * procedure returns; if this trace gets
				 * deleted, must update pointer to avoid using
				 * free'd memory. */
    int reverseScan;		/* Boolean set true when traces are scanning
				 * in reverse order. */
} ActiveCommandTrace;

/*
 * When a variable trace is active (i.e. its associated procedure is
 * executing) one of the following structures is linked into a list associated
 * with the variable's interpreter. The information in the structure is needed
 * in order for Tcl to behave reasonably if traces are deleted while traces
 * are active.
 */

typedef struct ActiveVarTrace {
    struct Var *varPtr;		/* Variable that's being traced. */
    struct ActiveVarTrace *nextPtr;
				/* Next in list of all active variable traces
				 * for the interpreter, or NULL if no more. */

    VarTrace *nextTracePtr;	/* Next trace to check after current trace
				 * procedure returns; if this trace gets
				 * deleted, must update pointer to avoid using
				 * free'd memory. */
} ActiveVarTrace;

/*
 * The following structure describes an enumerative search in progress on an
 * array variable; this are invoked with options to the "array" command.

 */

typedef struct ArraySearch {
    int id;			/* Integer id used to distinguish among
				 * multiple concurrent searches for the same
				 * array. */
    struct Var *varPtr;		/* Pointer to array variable that's being
				 * searched. */
    Tcl_HashSearch search;	/* Info kept by the hash module about progress
				 * through the array. */
    Tcl_HashEntry *nextEntry;	/* Non-null means this is the next element to
				 * be enumerated (it's leftover from the
				 * Tcl_FirstHashEntry call or from an "array
				 * anymore" command). NULL means must call
				 * Tcl_NextHashEntry to get value to
				 * return. */
    struct ArraySearch *nextPtr;/* Next in list of all active searches for
				 * this variable, or NULL if this is the last
				 * one. */
} ArraySearch;

/*
 * The structure below defines a variable, which associates a string name with
 * a Tcl_Obj value. These structures are kept in procedure call frames (for
 * local variables recognized by the compiler) or in the heap (for global
 * variables and any variable not known to the compiler). For each Var
 * structure in the heap, a hash table entry holds the variable name and a
 * pointer to the Var structure.
 */

typedef struct Var {
    union {
	Tcl_Obj *objPtr;	/* The variable's object value. Used for
				 * scalar variables and array elements. */
	Tcl_HashTable *tablePtr;/* For array variables, this points to
				 * information about the hash table used to
				 * implement the associative array. Points to
				 * ckalloc-ed data. */
	struct Var *linkPtr;	/* If this is a global variable being referred
				 * to in a procedure, or a variable created by
				 * "upvar", this field points to the
				 * referenced variable's Var struct. */
    } value;
    char *name;			/* NULL if the variable is in a hashtable,
				 * otherwise points to the variable's name. It
				 * is used, e.g., by TclLookupVar and "info
				 * locals". The storage for the characters of
				 * the name is not owned by the Var and must

				 * not be freed when freeing the Var. */
    Namespace *nsPtr;		/* Points to the namespace that contains this
				 * variable or NULL if the variable is a local
				 * variable in a Tcl procedure. */
    Tcl_HashEntry *hPtr;	/* If variable is in a hashtable, either the
				 * hash table entry that refers to this
				 * variable or NULL if the variable has been
				 * detached from its hash table (e.g. an array
				 * is deleted, but some of its elements are
				 * still referred to in upvars). NULL if the
				 * variable is not in a hashtable. This is
				 * used to delete an variable from its
				 * hashtable if it is no longer needed. */

    int refCount;		/* Counts number of active uses of this
				 * variable, not including its entry in the
				 * call frame or the hash table: 1 for each
				 * additional variable whose linkPtr points
				 * here, 1 for each nested trace active on
				 * variable, and 1 if the variable is a
				 * namespace variable. This record can't be
				 * deleted until refCount becomes 0. */
    VarTrace *tracePtr;		/* First in list of all traces set for this
				 * variable. */
    ArraySearch *searchPtr;	/* First in list of all searches active for
				 * this variable, or NULL if none. */
    int flags;			/* Miscellaneous bits of information about
				 * variable. See below for definitions. */
} Var;

/*
 * Flag bits for variables. The first three (VAR_SCALAR, VAR_ARRAY, and
 * VAR_LINK) are mutually exclusive and give the "type" of the variable.
 * VAR_UNDEFINED is independent of the variable's type.
 *
 * VAR_SCALAR -			1 means this is a scalar variable and not an
 *				array or link. The "objPtr" field points to
 *				the variable's value, a Tcl object.
 * VAR_ARRAY -			1 means this is an array variable rather than
 *				a scalar variable or link. The "tablePtr"
 *				field points to the array's hashtable for its
 *				elements.
 * VAR_LINK -			1 means this Var structure contains a pointer
 *				to another Var structure that either has the
 *				real value or is itself another VAR_LINK
 *				pointer. Variables like this come about
 *				through "upvar" and "global" commands, or
 *				through references to variables in enclosing
 *				namespaces.
 * VAR_UNDEFINED -		1 means that the variable is in the process of
 *				being deleted. An undefined variable logically
 *				does not exist and survives only while it has
 *				a trace, or if it is a global variable
 *				currently being used by some procedure.

 * VAR_IN_HASHTABLE -		1 means this variable is in a hashtable and
 *				the Var structure is malloced. 0 if it is a
 *				local variable that was assigned a slot in a
 *				procedure frame by the compiler so the Var
 *				storage is part of the call frame.
 * VAR_TRACE_ACTIVE -		1 means that trace processing is currently
 *				underway for a read or write access, so new
 *				read or write accesses should not cause trace
 *				procedures to be called and the variable can't
 *				be deleted.
 * VAR_ARRAY_ELEMENT -		1 means that this variable is an array
 *				element, so it is not legal for it to be an
 *				array itself (the VAR_ARRAY flag had better
 *				not be set).
 * VAR_NAMESPACE_VAR -		1 means that this variable was declared as a
 *				namespace variable. This flag ensures it
 *				persists until its namespace is destroyed or
 *				until the variable is unset; it will persist
 *				even if it has not been initialized and is

 *				marked undefined. The variable's refCount is
 *				incremented to reflect the "reference" from
 *				its namespace.
 *
 * The following additional flags are used with the CompiledLocal type defined
 * below:
 *
 * VAR_ARGUMENT -		1 means that this variable holds a procedure
 *				argument.
 * VAR_TEMPORARY -		1 if the local variable is an anonymous
 *				temporary variable. Temporaries have a NULL
 *				name.
 * VAR_RESOLVED -		1 if name resolution has been done for this
 *				variable.
 */

................................................................................
#define VAR_IN_HASHTABLE	0x10
#define VAR_TRACE_ACTIVE	0x20
#define VAR_ARRAY_ELEMENT	0x40
#define VAR_NAMESPACE_VAR	0x80

#define VAR_ARGUMENT		0x100
#define VAR_TEMPORARY		0x200
#define VAR_RESOLVED		0x400
#define VAR_IS_ARGS		0x800

/*
 * Macros to ensure that various flag bits are set properly for variables.
 * The ANSI C "prototypes" for these macros are:
 *
 * MODULE_SCOPE void	TclSetVarScalar(Var *varPtr);
 * MODULE_SCOPE void	TclSetVarArray(Var *varPtr);
 * MODULE_SCOPE void	TclSetVarLink(Var *varPtr);
 * MODULE_SCOPE void	TclSetVarArrayElement(Var *varPtr);
 * MODULE_SCOPE void	TclSetVarUndefined(Var *varPtr);
 * MODULE_SCOPE void	TclClearVarUndefined(Var *varPtr);
 */

#define TclSetVarScalar(varPtr) \
    (varPtr)->flags = ((varPtr)->flags & ~(VAR_ARRAY|VAR_LINK)) | VAR_SCALAR

#define TclSetVarArray(varPtr) \
    (varPtr)->flags = ((varPtr)->flags & ~(VAR_SCALAR|VAR_LINK)) | VAR_ARRAY
................................................................................
#define TclClearVarNamespaceVar(varPtr) \
    (varPtr)->flags &= ~VAR_NAMESPACE_VAR

/*
 * Macros to read various flag bits of variables.
 * The ANSI C "prototypes" for these macros are:
 *
 * MODULE_SCOPE int	TclIsVarScalar(Var *varPtr);
 * MODULE_SCOPE int	TclIsVarLink(Var *varPtr);
 * MODULE_SCOPE int	TclIsVarArray(Var *varPtr);
 * MODULE_SCOPE int	TclIsVarUndefined(Var *varPtr);
 * MODULE_SCOPE int	TclIsVarArrayElement(Var *varPtr);
 * MODULE_SCOPE int	TclIsVarTemporary(Var *varPtr);
 * MODULE_SCOPE int	TclIsVarArgument(Var *varPtr);
 * MODULE_SCOPE int	TclIsVarResolved(Var *varPtr);
 */

#define TclIsVarScalar(varPtr) \
    ((varPtr)->flags & VAR_SCALAR)

#define TclIsVarLink(varPtr) \
    ((varPtr)->flags & VAR_LINK)

#define TclIsVarArray(varPtr) \
................................................................................
    ((varPtr)->flags & VAR_ARRAY_ELEMENT)

#define TclIsVarNamespaceVar(varPtr) \
    ((varPtr)->flags & VAR_NAMESPACE_VAR)

#define TclIsVarTemporary(varPtr) \
    ((varPtr)->flags & VAR_TEMPORARY)

#define TclIsVarArgument(varPtr) \
    ((varPtr)->flags & VAR_ARGUMENT)

#define TclIsVarResolved(varPtr) \
    ((varPtr)->flags & VAR_RESOLVED)

#define TclIsVarTraceActive(varPtr) \
    ((varPtr)->flags & VAR_TRACE_ACTIVE)

#define TclIsVarUntraced(varPtr) \
................................................................................
    ((varPtr)->tracePtr == NULL)

/*
 * Macros for direct variable access by TEBC
 */

#define TclIsVarDirectReadable(varPtr) \
	(TclIsVarScalar(varPtr) \
    && !TclIsVarUndefined(varPtr) \
    && TclIsVarUntraced(varPtr))

#define TclIsVarDirectWritable(varPtr) \
    (   !(((varPtr)->flags & VAR_IN_HASHTABLE) \
		&& ((varPtr)->hPtr == NULL)) \
     && TclIsVarUntraced(varPtr) \
     && (TclIsVarScalar(varPtr) \
	     || TclIsVarUndefined(varPtr)))

/*
 *----------------------------------------------------------------
 * Data structures related to procedures. These are used primarily in
 * tclProc.c, tclCompile.c, and tclExecute.c.
 *----------------------------------------------------------------
 */

/*
 * Forward declaration to prevent an error when the forward reference to
 * Command is encountered in the Proc and ImportRef types declared below.
 */

struct Command;

/*
 * The variable-length structure below describes a local variable of a
 * procedure that was recognized by the compiler. These variables have a name,
 * an element in the array of compiler-assigned local variables in the
 * procedure's call frame, and various other items of information. If the
 * local variable is a formal argument, it may also have a default value. The
 * compiler can't recognize local variables whose names are expressions (these
 * names are only known at runtime when the expressions are evaluated) or
 * local variables that are created as a result of an "upvar" or "uplevel"
 * command. These other local variables are kept separately in a hash table in
 * the call frame.
 */

typedef struct CompiledLocal {
    struct CompiledLocal *nextPtr;
				/* Next compiler-recognized local variable for
				 * this procedure, or NULL if this is the last
				 * local. */
    int nameLength;		/* The number of characters in local
				 * variable's name. Used to speed up variable
				 * lookups. */
    int frameIndex;		/* Index in the array of compiler-assigned
				 * variables in the procedure call frame. */
    int flags;			/* Flag bits for the local variable. Same as
				 * the flags for the Var structure above,
				 * although only VAR_SCALAR, VAR_ARRAY,
				 * VAR_LINK, VAR_ARGUMENT, VAR_TEMPORARY, and
				 * VAR_RESOLVED make sense. */
    Tcl_Obj *defValuePtr;	/* Pointer to the default value of an
				 * argument, if any. NULL if not an argument
				 * or, if an argument, no default value. */
    Tcl_ResolvedVarInfo *resolveInfo;
				/* Customized variable resolution info
				 * supplied by the Tcl_ResolveCompiledVarProc
				 * associated with a namespace. Each variable
				 * is marked by a unique ClientData tag during
				 * compilation, and that same tag is used to
				 * find the variable at runtime. */
    char name[4];		/* Name of the local variable starts here. If
				 * the name is NULL, this will just be '\0'.
				 * The actual size of this field will be large
				 * enough to hold the name. MUST BE THE LAST
				 * FIELD IN THE STRUCTURE! */
} CompiledLocal;

/*
 * The structure below defines a command procedure, which consists of a
 * collection of Tcl commands plus information about arguments and other local
 * variables recognized at compile time.
 */

typedef struct Proc {
    struct Interp *iPtr;	/* Interpreter for which this command is
				 * defined. */
    int refCount;		/* Reference count: 1 if still present in
				 * command table plus 1 for each call to the
				 * procedure that is currently active. This
				 * structure can be freed when refCount
				 * becomes zero. */
    struct Command *cmdPtr;	/* Points to the Command structure for this
				 * procedure. This is used to get the
				 * namespace in which to execute the
				 * procedure. */
    Tcl_Obj *bodyPtr;		/* Points to the ByteCode object for
				 * procedure's body command. */
    int numArgs;		/* Number of formal parameters. */
    int numCompiledLocals;	/* Count of local variables recognized by the
				 * compiler including arguments and
				 * temporaries. */
    CompiledLocal *firstLocalPtr;
				/* Pointer to first of the procedure's
				 * compiler-allocated local variables, or NULL
				 * if none. The first numArgs entries in this
				 * list describe the procedure's formal
				 * arguments. */
    CompiledLocal *lastLocalPtr;/* Pointer to the last allocated local
				 * variable or NULL if none. This has frame
				 * index (numCompiledLocals-1). */
} Proc;

/*
 * The structure below defines a command trace. This is used to allow Tcl
 * clients to find out whenever a command is about to be executed.
 */

typedef struct Trace {
    int level;			/* Only trace commands at nesting level less
				 * than or equal to this. */
    Tcl_CmdObjTraceProc *proc;	/* Procedure to call to trace command. */
    ClientData clientData;	/* Arbitrary value to pass to proc. */
    struct Trace *nextPtr;	/* Next in list of traces for this interp. */
    int flags;			/* Flags governing the trace - see
				 * Tcl_CreateObjTrace for details */
    Tcl_CmdObjTraceDeleteProc* delProc;
				/* Procedure to call when trace is deleted */
} Trace;

/*
 * When an interpreter trace is active (i.e. its associated procedure is
 * executing), one of the following structures is linked into a list
 * associated with the interpreter. The information in the structure is needed
 * in order for Tcl to behave reasonably if traces are deleted while traces
 * are active.
 */

typedef struct ActiveInterpTrace {
    struct ActiveInterpTrace *nextPtr;
				/* Next in list of all active command traces
				 * for the interpreter, or NULL if no more. */

    Trace *nextTracePtr;	/* Next trace to check after current trace
				 * procedure returns; if this trace gets
				 * deleted, must update pointer to avoid using
				 * free'd memory. */
    int reverseScan;		/* Boolean set true when traces are scanning
				 * in reverse order. */
} ActiveInterpTrace;

/*
 * Flag values designating types of execution traces. See tclTrace.c for
 * related flag values.
 *
 * TCL_TRACE_ENTER_EXEC		- triggers enter/enterstep traces.
 * 				- passed to Tcl_CreateObjTrace to set up
 *				  "enterstep" traces.
 * TCL_TRACE_LEAVE_EXEC		- triggers leave/leavestep traces.
 * 				- passed to Tcl_CreateObjTrace to set up
 *				  "leavestep" traces.
 *
 */
#define TCL_TRACE_ENTER_EXEC	1
#define TCL_TRACE_LEAVE_EXEC	2

/*
 * The structure below defines an entry in the assocData hash table which is
 * associated with an interpreter. The entry contains a pointer to a function
 * to call when the interpreter is deleted, and a pointer to a user-defined
 * piece of data.
 */

typedef struct AssocData {
    Tcl_InterpDeleteProc *proc;	/* Proc to call when deleting. */
    ClientData clientData;	/* Value to pass to proc. */
} AssocData;

/*
 * The structure below defines a call frame. A call frame defines a naming
 * context for a procedure call: its local naming scope (for local variables)
 * and its global naming scope (a namespace, perhaps the global :: namespace).
 * A call frame can also define the naming context for a namespace eval or
 * namespace inscope command: the namespace in which the command's code should
 * execute. The Tcl_CallFrame structures exist only while procedures or
 * namespace eval/inscope's are being executed, and provide a kind of Tcl call
 * stack.
 *
 * WARNING!! The structure definition must be kept consistent with the
 * Tcl_CallFrame structure in tcl.h. If you change one, change the other.
 */

typedef struct CallFrame {
    Namespace *nsPtr;		/* Points to the namespace used to resolve
				 * commands and global variables. */
................................................................................
    int isProcCallFrame;	/* If 0, the frame was pushed to execute a
				 * namespace command and var references are
				 * treated as references to namespace vars;
				 * varTablePtr and compiledLocals are ignored.
				 * If FRAME_IS_PROC is set, the frame was
				 * pushed to execute a Tcl procedure and may
				 * have local vars. */
    int objc;			/* This and objv below describe the arguments
				 * for this procedure call. */
    Tcl_Obj *CONST *objv;	/* Array of argument objects. */
    struct CallFrame *callerPtr;
				/* Value of interp->framePtr when this
				 * procedure was invoked (i.e. next higher in
				 * stack of all active procedures). */
    struct CallFrame *callerVarPtr;
				/* Value of interp->varFramePtr when this
				 * procedure was invoked (i.e. determines
				 * variable scoping within caller). Same as
				 * callerPtr unless an "uplevel" command or
				 * something equivalent was active in the
				 * caller). */
    int level;			/* Level of this procedure, for "uplevel"
				 * purposes (i.e. corresponds to nesting of
				 * callerVarPtr's, not callerPtr's). 1 for
				 * outermost procedure, 0 for top-level. */
    Proc *procPtr;		/* Points to the structure defining the called
				 * procedure. Used to get information such as
				 * the number of compiled local variables
				 * (local variables assigned entries ["slots"]
				 * in the compiledLocals array below). */

    Tcl_HashTable *varTablePtr;	/* Hash table containing local variables not
				 * recognized by the compiler, or created at
				 * execution time through, e.g., upvar.
				 * Initially NULL and created if needed. */
    int numCompiledLocals;	/* Count of local variables recognized by the
				 * compiler including arguments. */
    Var* compiledLocals;	/* Points to the array of local variables
				 * recognized by the compiler. The compiler
				 * emits code that refers to these variables
				 * using an index into this array. */
} CallFrame;

#define FRAME_IS_PROC 0x1

/*
 *----------------------------------------------------------------
 * Data structures and procedures related to TclHandles, which are a very
 * lightweight method of preserving enough information to determine if an
 * arbitrary malloc'd block has been deleted.
 *----------------------------------------------------------------
 */

typedef VOID **TclHandle;

/*
 *----------------------------------------------------------------
 * Data structures related to expressions. These are used only in tclExpr.c.

 *----------------------------------------------------------------
 */

/*
 * The data structure below defines a math function (e.g. sin or hypot) for
 * use in Tcl expressions.
 */

#define MAX_MATH_ARGS 5
typedef struct MathFunc {
    int builtinFuncIndex;	/* If this is a builtin math function, its
				 * index in the array of builtin functions.
				 * (tclCompilation.h lists these indices.)
				 * The value is -1 if this is a new function
				 * defined by Tcl_CreateMathFunc. The value is
				 * also -1 if a builtin function is replaced
				 * by a Tcl_CreateMathFunc call. */
    int numArgs;		/* Number of arguments for function. */
    Tcl_ValueType argTypes[MAX_MATH_ARGS];
				/* Acceptable types for each argument. */
    Tcl_MathProc *proc;		/* Procedure that implements this function.
				 * NULL if isBuiltinFunc is 1. */
    ClientData clientData;	/* Additional argument to pass to the function
				 * when invoking it. NULL if isBuiltinFunc is
				 * 1. */
} MathFunc;

/*
 * These are a thin layer over TclpThreadKeyDataGet and TclpThreadKeyDataSet
 * when threads are used, or an emulation if there are no threads. These are
 * really internal and Tcl clients should use Tcl_GetThreadData.
 */

MODULE_SCOPE VOID *	TclThreadDataKeyGet(Tcl_ThreadDataKey *keyPtr);

MODULE_SCOPE void	TclThreadDataKeySet(Tcl_ThreadDataKey *keyPtr,
			    VOID *data);

/*
 * This is a convenience macro used to initialize a thread local storage ptr.
 */

#define TCL_TSD_INIT(keyPtr) \
  (ThreadSpecificData *)Tcl_GetThreadData((keyPtr), sizeof(ThreadSpecificData))


/*
 *----------------------------------------------------------------
 * Data structures related to bytecode compilation and execution. These are
 * used primarily in tclCompile.c, tclExecute.c, and tclBasic.c.

 *----------------------------------------------------------------
 */

/*
 * Forward declaration to prevent errors when the forward references to
 * Tcl_Parse and CompileEnv are encountered in the procedure type CompileProc
 * declared below.
 */

struct CompileEnv;

/*
 * The type of procedures called by the Tcl bytecode compiler to compile
 * commands. Pointers to these procedures are kept in the Command structure
 * describing each command. The integer value returned by a CompileProc must
 * be one of the following:
 *
 * TCL_OK		Compilation completed normally.
 * TCL_ERROR 		Compilation could not be completed. This can be just a
 * 			judgment by the CompileProc that the command is too
 * 			complex to compile effectively, or it can indicate
 * 			that in the current state of the interp, the command
 * 			would raise an error. The bytecode compiler will not
 * 			do any error reporting at compiler time. Error

 * 			reporting is deferred until the actual runtime,
 * 			because by then changes in the interp state may allow
 * 			the command to be successfully evaluated.
 * TCL_OUT_LINE_COMPILE	A source-compatible alias for TCL_ERROR, kept for the
 * 			sake of old code only.
 */

#define TCL_OUT_LINE_COMPILE	TCL_ERROR

typedef int (CompileProc) (Tcl_Interp *interp, Tcl_Parse *parsePtr,
	struct CompileEnv *compEnvPtr);

/*
 * The type of procedure called from the compilation hook point in
 * SetByteCodeFromAny.
 */

typedef int (CompileHookProc) (Tcl_Interp *interp,
	struct CompileEnv *compEnvPtr, ClientData clientData);

/*
 * The data structure defining the execution environment for ByteCode's.
 * There is one ExecEnv structure per Tcl interpreter. It holds the evaluation
 * stack that holds command operands and results. The stack grows towards
 * increasing addresses. The "stackTop" member is cached by TclExecuteByteCode
 * in a local variable: it must be set before calling TclExecuteByteCode and
 * will be restored by TclExecuteByteCode before it returns.

 */

typedef struct ExecEnv {
    Tcl_Obj **stackPtr;		/* Points to the first item in the evaluation
				 * stack on the heap. */
    Tcl_Obj **tosPtr;		/* Points to current top of stack;
				 * (stackPtr-1) when the stack is empty. */
    Tcl_Obj **endPtr;		/* Points to last usable item in stack. */
    Tcl_Obj *constants[2];	/* Pointers to constant "0" and "1" objs. */
} ExecEnv;

/*
 * The definitions for the LiteralTable and LiteralEntry structures. Each
 * interpreter contains a LiteralTable. It is used to reduce the storage
 * needed for all the Tcl objects that hold the literals of scripts compiled
 * by the interpreter. A literal's object is shared by all the ByteCodes that
 * refer to the literal. Each distinct literal has one LiteralEntry entry in
 * the LiteralTable. A literal table is a specialized hash table that is
 * indexed by the literal's string representation, which may contain null
 * characters.
 *
 * Note that we reduce the space needed for literals by sharing literal
 * objects both within a ByteCode (each ByteCode contains a local
 * LiteralTable) and across all an interpreter's ByteCodes (with the
 * interpreter's global LiteralTable).
 */

typedef struct LiteralEntry {
    struct LiteralEntry *nextPtr;
				/* Points to next entry in this hash bucket or
				 * NULL if end of chain. */
    Tcl_Obj *objPtr;		/* Points to Tcl object that holds the
				 * literal's bytes and length. */

    int refCount;		/* If in an interpreter's global literal
				 * table, the number of ByteCode structures

				 * that share the literal object; the literal
				 * entry can be freed when refCount drops to
				 * 0. If in a local literal table, -1. */

    Namespace *nsPtr;		/* Namespace in which this literal is used. We
				 * try to avoid sharing literal non-FQ command

				 * names among different namespaces to reduce
				 * shimmering. */
} LiteralEntry;

typedef struct LiteralTable {
    LiteralEntry **buckets;	/* Pointer to bucket array. Each element
				 * points to first entry in bucket's hash
				 * chain, or NULL. */
    LiteralEntry *staticBuckets[TCL_SMALL_HASH_TABLE];
				/* Bucket array used for small tables to avoid

				 * mallocs and frees. */
    int numBuckets;		/* Total number of buckets allocated at
				 * **buckets. */
    int numEntries;		/* Total number of entries present in
				 * table. */
    int rebuildSize;		/* Enlarge table when numEntries gets to be
				 * this large. */
    int mask;			/* Mask value used in hashing function. */

} LiteralTable;

/*
 * The following structure defines for each Tcl interpreter various
 * statistics-related information about the bytecode compiler and
 * interpreter's operation in that interpreter.
 */

#ifdef TCL_COMPILE_STATS
typedef struct ByteCodeStats {
    long numExecutions;		/* Number of ByteCodes executed. */
    long numCompilations;	/* Number of ByteCodes created. */
    long numByteCodesFreed;	/* Number of ByteCodes destroyed. */
    long instructionCount[256];	/* Number of times each instruction was
				 * executed. */

    double totalSrcBytes;	/* Total source bytes ever compiled. */
    double totalByteCodeBytes;	/* Total bytes for all ByteCodes. */
    double currentSrcBytes;	/* Src bytes for all current ByteCodes. */
    double currentByteCodeBytes;/* Code bytes in all current ByteCodes. */

    long srcCount[32];		/* Source size distribution: # of srcs of
				 * size [2**(n-1)..2**n), n in [0..32). */
    long byteCodeCount[32];	/* ByteCode size distribution. */
    long lifetimeCount[32];	/* ByteCode lifetime distribution (ms). */

    double currentInstBytes;	/* Instruction bytes-current ByteCodes. */
    double currentLitBytes;	/* Current literal bytes. */
    double currentExceptBytes;	/* Current exception table bytes. */
    double currentAuxBytes;	/* Current auxiliary information bytes. */
    double currentCmdMapBytes;	/* Current src<->code map bytes. */

    long numLiteralsCreated;	/* Total literal objects ever compiled. */
    double totalLitStringBytes;	/* Total string bytes in all literals. */
    double currentLitStringBytes;
				/* String bytes in current literals. */
    long literalCount[32];	/* Distribution of literal string sizes. */
} ByteCodeStats;
#endif /* TCL_COMPILE_STATS */

/*
 *----------------------------------------------------------------
 * Data structures related to commands.
 *----------------------------------------------------------------
 */

/*
 * An imported command is created in an namespace when it imports a "real"
 * command from another namespace. An imported command has a Command structure
 * that points (via its ClientData value) to the "real" Command structure in
 * the source namespace's command table. The real command records all the
 * imported commands that refer to it in a list of ImportRef structures so
 * that they can be deleted when the real command is deleted.
 */

typedef struct ImportRef {
    struct Command *importedCmdPtr;
				/* Points to the imported command created in
				 * an importing namespace; this command
				 * redirects its invocations to the "real"
				 * command. */
    struct ImportRef *nextPtr;	/* Next element on the linked list of imported
				 * commands that refer to the "real" command.
				 * The real command deletes these imported
				 * commands on this list when it is
				 * deleted. */
} ImportRef;

/*
 * Data structure used as the ClientData of imported commands: commands
 * created in an namespace when it imports a "real" command from another
 * namespace.
 */

typedef struct ImportedCmdData {
    struct Command *realCmdPtr;	/* "Real" command that this imported command
				 * refers to. */
    struct Command *selfPtr;	/* Pointer to this imported command. Needed
				 * only when deleting it in order to remove it
				 * from the real command's linked list of
				 * imported commands that refer to it. */
} ImportedCmdData;

/*
 * A Command structure exists for each command in a namespace. The Tcl_Command
 * opaque type actually refers to these structures.
 */

typedef struct Command {
    Tcl_HashEntry *hPtr;	/* Pointer to the hash table entry that refers
				 * to this command. The hash table is either a
				 * namespace's command table or an
				 * interpreter's hidden command table. This
				 * pointer is used to get a command's name
				 * from its Tcl_Command handle. NULL means
				 * that the hash table entry has been removed
				 * already (this can happen if deleteProc
				 * causes the command to be deleted or
				 * recreated). */
    Namespace *nsPtr;		/* Points to the namespace containing this
				 * command. */
    int refCount;		/* 1 if in command hashtable plus 1 for each
				 * reference from a CmdName Tcl object
				 * representing a command's name in a ByteCode
				 * instruction sequence. This structure can be

				 * freed when refCount becomes zero. */
    int cmdEpoch;		/* Incremented to invalidate any references
				 * that point to this command when it is
				 * renamed, deleted, hidden, or exposed. */
    CompileProc *compileProc;	/* Procedure called to compile command. NULL
				 * if no compile proc exists for command. */
    Tcl_ObjCmdProc *objProc;	/* Object-based command procedure. */
    ClientData objClientData;	/* Arbitrary value passed to object proc. */
    Tcl_CmdProc *proc;		/* String-based command procedure. */
    ClientData clientData;	/* Arbitrary value passed to string proc. */
    Tcl_CmdDeleteProc *deleteProc;
				/* Procedure invoked when deleting command to,
				 * e.g., free all client data. */
    ClientData deleteData;	/* Arbitrary value passed to deleteProc. */
    int flags;			/* Miscellaneous bits of information about
				 * command. See below for definitions. */
    ImportRef *importRefPtr;	/* List of each imported Command created in
				 * another namespace when this command is
				 * imported. These imported commands redirect
				 * invocations back to this command. The list
				 * is used to remove all those imported
				 * commands when deleting this "real"
				 * command. */
    CommandTrace *tracePtr;	/* First in list of all traces set for this
				 * command. */
} Command;

/*
 * Flag bits for commands.
 *
 * CMD_IS_DELETED -		Means that the command is in the process of
 *				being deleted (its deleteProc is currently
 *				executing). Other attempts to delete the
 *				command should be ignored.
 * CMD_TRACE_ACTIVE -		1 means that trace processing is currently
 *				underway for a rename/delete change. See the
 *				two flags below for which is currently being
 *				processed.
 * CMD_HAS_EXEC_TRACES -	1 means that this command has at least one
 *				execution trace (as opposed to simple
 *				delete/rename traces) in its tracePtr list.
 * TCL_TRACE_RENAME -		A rename trace is in progress. Further
 *				recursive renames will not be traced.
 * TCL_TRACE_DELETE -		A delete trace is in progress. Further
 *				recursive deletes will not be traced.
 * (these last two flags are defined in tcl.h)
 */

#define CMD_IS_DELETED		0x1
#define CMD_TRACE_ACTIVE	0x2
#define CMD_HAS_EXEC_TRACES	0x4

/*
 *----------------------------------------------------------------
 * Data structures related to name resolution procedures.
 *----------------------------------------------------------------
 */

/*
 * The interpreter keeps a linked list of name resolution schemes. The scheme
 * for a namespace is consulted first, followed by the list of schemes in an
 * interpreter, followed by the default name resolution in Tcl. Schemes are

 * added/removed from the interpreter's list by calling Tcl_AddInterpResolver
 * and Tcl_RemoveInterpResolver.
 */

typedef struct ResolverScheme {
    char *name;			/* Name identifying this scheme. */
    Tcl_ResolveCmdProc *cmdResProc;
				/* Procedure handling command name
				 * resolution. */
    Tcl_ResolveVarProc *varResProc;
				/* Procedure handling variable name resolution
				 * for variables that can only be handled at
				 * runtime. */
    Tcl_ResolveCompiledVarProc *compiledVarResProc;
				/* Procedure handling variable name resolution
				 * at compile time. */

    struct ResolverScheme *nextPtr;
				/* Pointer to next record in linked list. */
} ResolverScheme;

/*
 * Forward declaration of the TIP#143 limit handler structure.
 */

typedef struct LimitHandler LimitHandler;

/*
 *----------------------------------------------------------------
 * This structure defines an interpreter, which is a collection of commands
 * plus other state information related to interpreting commands, such as
 * variable storage. Primary responsibility for this data structure is in

 * tclBasic.c, but almost every Tcl source file uses something in here.
 *----------------------------------------------------------------
 */

typedef struct Interp {

    /*
     * Note: the first three fields must match exactly the fields in a
     * Tcl_Interp struct (see tcl.h). If you change one, be sure to change the
     * other.
     *
     * The interpreter's result is held in both the string and the
     * objResultPtr fields. These fields hold, respectively, the result's
     * string or object value. The interpreter's result is always in the
     * result field if that is non-empty, otherwise it is in objResultPtr.
     * The two fields are kept consistent unless some C code sets
     * interp->result directly. Programs should not access result and
     * objResultPtr directly; instead, they should always get and set the
     * result using procedures such as Tcl_SetObjResult, Tcl_GetObjResult, and
     * Tcl_GetStringResult. See the SetResult man page for details.
     */

    char *result;		/* If the last command returned a string
				 * result, this points to it. Should not be
				 * accessed directly; see comment above. */
    Tcl_FreeProc *freeProc;	/* Zero means a string result is statically
				 * allocated. TCL_DYNAMIC means string result
				 * was allocated with ckalloc and should be
				 * freed with ckfree. Other values give
				 * address of procedure to invoke to free the
				 * string result. Tcl_Eval must free it before
				 * executing next command. */
    int errorLine;		/* When TCL_ERROR is returned, this gives the
				 * line number in the command where the error
				 * occurred (1 means first line). */

    struct TclStubs *stubTable;	/* Pointer to the exported Tcl stub table. On
				 * previous versions of Tcl this is a pointer
				 * to the objResultPtr or a pointer to a
				 * buckets array in a hash table. We therefore
				 * have to do some careful checking before we
				 * can use this. */

    TclHandle handle;		/* Handle used to keep track of when this
				 * interp is deleted. */

    Namespace *globalNsPtr;	/* The interpreter's global namespace. */
    Tcl_HashTable *hiddenCmdTablePtr;
				/* Hash table used by tclBasic.c to keep track
				 * of hidden commands on a per-interp
				 * basis. */
    ClientData interpInfo;	/* Information used by tclInterp.c to keep
				 * track of master/slave interps on a
				 * per-interp basis. */
    Tcl_HashTable mathFuncTable;/* Contains all the math functions currently
				 * defined for the interpreter. Indexed by
				 * strings (function names); values have type
				 * (MathFunc *). */



    /*
     * Information related to procedures and variables. See tclProc.c and
     * tclVar.c for usage.
     */

    int numLevels;		/* Keeps track of how many nested calls to
				 * Tcl_Eval are in progress for this
				 * interpreter. It's used to delay deletion of
				 * the table until all Tcl_Eval invocations
				 * are completed. */
    int maxNestingDepth;	/* If numLevels exceeds this value then Tcl
				 * assumes that infinite recursion has
				 * occurred and it generates an error. */
    CallFrame *framePtr;	/* Points to top-most in stack of all nested
				 * procedure invocations. NULL means there are
				 * no active procedures. */
    CallFrame *varFramePtr;	/* Points to the call frame whose variables
				 * are currently in use (same as framePtr
				 * unless an "uplevel" command is executing).
				 * NULL means no procedure is active or
				 * "uplevel 0" is executing. */
    ActiveVarTrace *activeVarTracePtr;
				/* First in list of active traces for interp,
				 * or NULL if no active traces. */
    int returnCode;		/* [return -code] parameter */
    char *unused3;		/* No longer used (was errorInfo) */
    char *unused4;		/* No longer used (was errorCode) */

    /*
     * Information used by Tcl_AppendResult to keep track of partial results.
     * See Tcl_AppendResult code for details.
     */

    char *appendResult;		/* Storage space for results generated by
				 * Tcl_AppendResult. Ckalloc-ed. NULL means
				 * not yet allocated. */
    int appendAvl;		/* Total amount of space available at
				 * partialResult. */
    int appendUsed;		/* Number of non-null bytes currently stored
				 * at partialResult. */

    /*
     * Information about packages. Used only in tclPkg.c.
     */

    Tcl_HashTable packageTable;	/* Describes all of the packages loaded in or
				 * available to this interpreter. Keys are
				 * package names, values are (Package *)
				 * pointers. */
    char *packageUnknown;	/* Command to invoke during "package require"
				 * commands for packages that aren't described
				 * in packageTable. Ckalloc'ed, may be
				 * NULL. */

    /*
     * Miscellaneous information:
     */

    int cmdCount;		/* Total number of times a command procedure
				 * has been called for this interpreter. */
    int evalFlags;		/* Flags to control next call to Tcl_Eval.
				 * Normally zero, but may be set before
				 * calling Tcl_Eval. See below for valid
				 * values. */
    int unused1;		/* No longer used (was termOffset) */
    LiteralTable literalTable;	/* Contains LiteralEntry's describing all Tcl
				 * objects holding literals of scripts
				 * compiled by the interpreter. Indexed by the
				 * string representations of literals. Used to
				 * avoid creating duplicate objects. */

    int compileEpoch;		/* Holds the current "compilation epoch" for
				 * this interpreter. This is incremented to
				 * invalidate existing ByteCodes when, e.g., a
				 * command with a compile procedure is
				 * redefined. */
    Proc *compiledProcPtr;	/* If a procedure is being compiled, a pointer
				 * to its Proc structure; otherwise, this is
				 * NULL. Set by ObjInterpProc in tclProc.c and
				 * used by tclCompile.c to process local
				 * variables appropriately. */
    ResolverScheme *resolverPtr;
				/* Linked list of name resolution schemes
				 * added to this interpreter. Schemes are
				 * added and removed by calling
				 * Tcl_AddInterpResolvers and
				 * Tcl_RemoveInterpResolver respectively. */
    Tcl_Obj *scriptFile;	/* NULL means there is no nested source
				 * command active; otherwise this points to
				 * pathPtr of the file being sourced. */
    int flags;			/* Various flag bits. See below. */
    long randSeed;		/* Seed used for rand() function. */
    Trace *tracePtr;		/* List of traces for this interpreter. */
    Tcl_HashTable *assocData;	/* Hash table for associating data with this
				 * interpreter. Cleaned up when this
				 * interpreter is deleted. */
    struct ExecEnv *execEnvPtr;	/* Execution environment for Tcl bytecode
				 * execution. Contains a pointer to the Tcl
				 * evaluation stack. */
    Tcl_Obj *emptyObjPtr;	/* Points to an object holding an empty
				 * string. Returned by Tcl_ObjSetVar2 when
				 * variable traces change a variable in a
				 * gross way. */
    char resultSpace[TCL_RESULT_SIZE+1];
				/* Static space holding small results. */
    Tcl_Obj *objResultPtr;	/* If the last command returned an object
................................................................................
				 * accessed directly; see comment above. */
    Tcl_ThreadId threadId;	/* ID of thread that owns the interpreter */

    ActiveCommandTrace *activeCmdTracePtr;
				/* First in list of active command traces for
				 * interp, or NULL if no active traces. */
    ActiveInterpTrace *activeInterpTracePtr;
				/* First in list of active traces for interp,
				 * or NULL if no active traces. */

    int tracesForbiddingInline; /* Count of traces (in the list headed by
				 * tracePtr) that forbid inline bytecode
				 * compilation */

    /* Fields used to manage extensible return options (TIP 90) */
    Tcl_Obj *returnOpts;	/* A dictionary holding the options to the
................................................................................
    int returnLevel;		/* [return -level] parameter */

    /*
     * Resource limiting framework support (TIP#143).
     */

    struct {
	int active;		/* Flag values defining which limits have been
				 * set. */
	int granularityTicker;	/* Counter used to determine how often to
				 * check the limits. */
	int exceeded;		/* Which limits have been exceeded, described
				 * as flag values the same as the 'active'
				 * field. */

	int cmdCount;		/* Limit for how many commands to execute in
				 * the interpreter. */
	LimitHandler *cmdHandlers;
				/* Handlers to execute when the limit is
				 * reached. */
	int cmdGranularity;	/* Mod factor used to determine how often to
				 * evaluate the limit check. */

	Tcl_Time time;		/* Time limit for execution within the
				 * interpreter. */
	LimitHandler *timeHandlers;
				/* Handlers to execute when the limit is
				 * reached. */
	int timeGranularity;	/* Mod factor used to determine how often to
				 * evaluate the limit check. */
	Tcl_TimerToken timeEvent;
				/* Handle for a timer callback that will occur
				 * when the time-limit is exceeded. */

	Tcl_HashTable callbacks;/* Mapping from (interp,type) pair to data
				 * used to install a limit handler callback to
				 * run in _this_ interp when the limit is
				 * exceeded. */
    } limit;

    /*
     * Information for improved default error generation from ensembles
     * (TIP#112).
     */

    struct {
	Tcl_Obj * CONST *sourceObjs;
				/* What arguments were actually input into the
				 * *root* ensemble command? (Nested ensembles
				 * don't rewrite this.) NULL if we're not
				 * processing an ensemble. */
	int numRemovedObjs;	/* How many arguments have been stripped off
				 * because of ensemble processing. */
	int numInsertedObjs;	/* How many of the current arguments were
				 * inserted by an ensemble. */
    } ensembleRewrite;

    /*
     * TIP #219 ... Global info for the I/O system ...
     */

    Tcl_Obj* chanMsg;		/* Error message set by channel drivers, for
				 * the propagation of arbitrary Tcl errors.
				 * This information, if present (chanMsg not
				 * NULL), takes precedence over a posix error
				 * code returned by a channel operation. */

    /*
     * Statistical information about the bytecode compiler and interpreter's
     * operation.
     */

#ifdef TCL_COMPILE_STATS
    ByteCodeStats stats;	/* Holds compilation and execution statistics
				 * for this interpreter. */
#endif /* TCL_COMPILE_STATS */
} Interp;

/*
 * General list of interpreters. Doubly linked for easier removal of items
 * deep in the list.
 */

typedef struct InterpList {
    Interp* interpPtr;
    struct InterpList* prevPtr;
    struct InterpList* nextPtr;
} InterpList;

/*
 * Macros for splicing into and out of doubly linked lists. They assume
 * existence of struct items 'prevPtr' and 'nextPtr'.
 *
 * a = element to add or remove.
 * b = list head.
 *
 * TclSpliceIn adds to the head of the list.
 */

#define TclSpliceIn(a,b)			\
    (a)->nextPtr = (b);				\
    if ((b) != NULL) {				\
	(b)->prevPtr = (a);			\
    }						\
    (a)->prevPtr = NULL, (b) = (a);

#define TclSpliceOut(a,b)			\
    if ((a)->prevPtr != NULL) {			\
	(a)->prevPtr->nextPtr = (a)->nextPtr;	\

    } else {					\
	(b) = (a)->nextPtr;			\
    }						\
    if ((a)->nextPtr != NULL) {			\
	(a)->nextPtr->prevPtr = (a)->prevPtr;	\
    }

/*
 * EvalFlag bits for Interp structures:
 *
 * TCL_ALLOW_EXCEPTIONS	1 means it's OK for the script to terminate with a
 *			code other than TCL_OK or TCL_ERROR; 0 means codes
 *			other than these should be turned into errors.
 */

#define TCL_ALLOW_EXCEPTIONS	4

/*
 * Flag bits for Interp structures:
 *
 * DELETED:		Non-zero means the interpreter has been deleted:
 *			don't process any more commands for it, and destroy
 *			the structure as soon as all nested invocations of
 *			Tcl_Eval are done.
 * ERR_ALREADY_LOGGED:	Non-zero means information has already been logged in
 *			iPtr->errorInfo for the current Tcl_Eval instance, so
 *			Tcl_Eval needn't log it (used to implement the "error
 *			message log" command).
 * DONT_COMPILE_CMDS_INLINE: Non-zero means that the bytecode compiler should
 *			not compile any commands into an inline sequence of
 *			instructions. This is set 1, for example, when command
 *			traces are requested.
 * RAND_SEED_INITIALIZED: Non-zero means that the randSeed value of the interp
 *			has not be initialized. This is set 1 when we first
 *			use the rand() or srand() functions.
 * SAFE_INTERP:		Non zero means that the current interp is a safe
 *			interp (i.e. it has only the safe commands installed,
 *			less priviledge than a regular interp).
 * INTERP_TRACE_IN_PROGRESS: Non-zero means that an interp trace is currently
 *			active; so no further trace callbacks should be
 *			invoked.
 * INTERP_ALTERNATE_WRONG_ARGS: Used for listing second and subsequent forms
 *			of the wrong-num-args string in Tcl_WrongNumArgs.
 *			Makes it append instead of replacing and uses
 *			different intermediate text.
................................................................................
#define DONT_COMPILE_CMDS_INLINE	 0x20
#define RAND_SEED_INITIALIZED		 0x40
#define SAFE_INTERP			 0x80
#define INTERP_TRACE_IN_PROGRESS	0x200
#define INTERP_ALTERNATE_WRONG_ARGS	0x400

/*
 * Maximum number of levels of nesting permitted in Tcl commands (used to
 * catch infinite recursion).
 */

#define MAX_NESTING_DEPTH	1000

/*
 * TIP#143 limit handler internal representation.
 */

struct LimitHandler {
    int flags;			/* The state of this particular handler. */
    Tcl_LimitHandlerProc *handlerProc;
				/* The handler callback. */
    ClientData clientData;	/* Opaque argument to the handler callback. */
    Tcl_LimitHandlerDeleteProc *deleteProc;
				/* How to delete the clientData */
    LimitHandler *prevPtr;	/* Previous item in linked list of handlers */
    LimitHandler *nextPtr;	/* Next item in linked list of handlers */
};

/*
 * Values for the LimitHandler flags field.
 *	LIMIT_HANDLER_ACTIVE - Whether the handler is currently being
 *		processed; handlers are never to be entered reentrantly.
 *	LIMIT_HANDLER_DELETED - Whether the handler has been deleted. This
 *		should not normally be observed because when a handler is
 *		deleted it is also spliced out of the list of handlers, but
 *		even so we will be careful.
 */

#define LIMIT_HANDLER_ACTIVE	0x01
#define LIMIT_HANDLER_DELETED	0x02

/*
 * The macro below is used to modify a "char" value (e.g. by casting it to an
 * unsigned character) so that it can be used safely with macros such as
 * isspace.
 */

#define UCHAR(c) ((unsigned char) (c))

/*
 * This macro is used to determine the offset needed to safely allocate any
 * data structure in memory. Given a starting offset or size, it "rounds up"
 * or "aligns" the offset to the next 8-byte boundary so that any data
 * structure can be placed at the resulting offset without fear of an
 * alignment error.
 *
 * WARNING!! DO NOT USE THIS MACRO TO ALIGN POINTERS: it will produce the
 * wrong result on platforms that allocate addresses that are divisible by 4
 * or 2. Only use it for offsets or sizes.
 *
 * This macro is only used by tclCompile.c in the core (Bug 926445). It
 * however not be made file static, as extensions that touch bytecodes
 * (notably tbcload) require it.
 */

#define TCL_ALIGN(x) (((int)(x) + 7) & ~7)


/*
 * The following enum values are used to specify the runtime platform setting
 * of the tclPlatform variable.
 */

typedef enum {
    TCL_PLATFORM_UNIX = 0,	/* Any Unix-like OS. */
    TCL_PLATFORM_WINDOWS = 2	/* Any Microsoft Windows OS. */
} TclPlatformType;

/*
 * The following enum values are used to indicate the translation of a Tcl
 * channel. Declared here so that each platform can define
 * TCL_PLATFORM_TRANSLATION to the native translation on that platform
 */

typedef enum TclEolTranslation {
    TCL_TRANSLATE_AUTO,		/* Eol == \r, \n and \r\n. */
    TCL_TRANSLATE_CR,		/* Eol == \r. */
    TCL_TRANSLATE_LF,		/* Eol == \n. */
    TCL_TRANSLATE_CRLF		/* Eol == \r\n. */
} TclEolTranslation;

/*
 * Flags for TclInvoke:
 *
 * TCL_INVOKE_HIDDEN		Invoke a hidden command; if not set, invokes
 *				an exposed command.
 * TCL_INVOKE_NO_UNKNOWN	If set, "unknown" is not invoked if the
 *				command to be invoked is not found. Only has
 *				an effect if invoking an exposed command,
 *				i.e. if TCL_INVOKE_HIDDEN is not also set.

 * TCL_INVOKE_NO_TRACEBACK	Does not record traceback information if the
 *				invoked command returns an error. Used if the
 *				caller plans on recording its own traceback
 *				information.
 */

#define	TCL_INVOKE_HIDDEN	(1<<0)
#define TCL_INVOKE_NO_UNKNOWN	(1<<1)
#define TCL_INVOKE_NO_TRACEBACK	(1<<2)

/*
 * The structure used as the internal representation of Tcl list objects. This
 * struct is grown (reallocated and copied) as necessary to hold all the
 * list's element pointers. The struct might contain more slots than currently
 * used to hold all element pointers. This is done to make append operations
 * faster.
 */

typedef struct List {
    int refCount;
    int maxElemCount;		/* Total number of element array slots. */
    int elemCount;		/* Current number of list elements. */
    Tcl_Obj *elements;		/* First list element; the struct is grown to
................................................................................
 * Macro used to get the elements of a list object - do NOT forget to verify
 * that it is of list type before using!
 */

#define TclListObjGetElements(listPtr, objc, objv) \
    { \
	List *listRepPtr = \
		(List *) (listPtr)->internalRep.twoPtrValue.ptr1;\
	(objc) = listRepPtr->elemCount;\
	(objv) = &listRepPtr->elements;\
    }

/*
 * Flag values for TclTraceDictPath().
 *
 * DICT_PATH_READ indicates that all entries on the path must exist but no
 * updates will be needed.
 *
 * DICT_PATH_UPDATE indicates that we are going to be doing an update at the
 * tip of the path, so duplication of shared objects should be done along the
 * way.
 *
 * DICT_PATH_EXISTS indicates that we are performing an existance test and a
 * lookup failure should therefore not be an error. If (and only if) this flag
 * is set, TclTraceDictPath() will return the special value
 * DICT_PATH_NON_EXISTENT if the path is not traceable.
 *
 * DICT_PATH_CREATE (which also requires the DICT_PATH_UPDATE bit to be set)
 * indicates that we are to create non-existant dictionaries on the path.

 */

#define DICT_PATH_READ		0
#define DICT_PATH_UPDATE	1
#define DICT_PATH_EXISTS	2
#define DICT_PATH_CREATE	5

#define DICT_PATH_NON_EXISTENT	((Tcl_Obj *) (void *) 1)

/*
 *----------------------------------------------------------------
 * Data structures related to the filesystem internals
 *----------------------------------------------------------------
 */


/*
 * The version_2 filesystem is private to Tcl. As and when these changes have
 * been thoroughly tested and investigated a new public filesystem interface

 * will be released. The aim is more versatile virtual filesystem interfaces,
 * more efficiency in 'path' manipulation and usage, and cleaner filesystem
 * code internally.
 */

#define TCL_FILESYSTEM_VERSION_2	((Tcl_FSVersion) 0x2)
typedef ClientData (TclFSGetCwdProc2) (ClientData clientData);

/*
 * The following types are used for getting and storing platform-specific file
 * attributes in tclFCmd.c and the various platform-versions of that file.
 * This is done to have as much common code as possible in the file attributes
 * code. For more information about the callbacks, see TclFileAttrsCmd in
 * tclFCmd.c.
 */

typedef int (TclGetFileAttrProc) (Tcl_Interp *interp, int objIndex,
	Tcl_Obj *fileName, Tcl_Obj **attrObjPtrPtr);
typedef int (TclSetFileAttrProc) (Tcl_Interp *interp, int objIndex,
	Tcl_Obj *fileName, Tcl_Obj *attrObjPtr);

typedef struct TclFileAttrProcs {
    TclGetFileAttrProc *getProc;/* The procedure for getting attrs. */
    TclSetFileAttrProc *setProc;/* The procedure for setting attrs. */
} TclFileAttrProcs;

/*
 * Opaque handle used in pipeline routines to encapsulate platform-dependent
 * state.
 */

typedef struct TclFile_ *TclFile;

/*
 * The "globParameters" argument of the function TclGlob is an or'ed
 * combination of the following values:
 */

#define TCL_GLOBMODE_NO_COMPLAIN	1
#define TCL_GLOBMODE_JOIN		2
#define TCL_GLOBMODE_DIR		4
#define TCL_GLOBMODE_TAILS		8

typedef enum Tcl_PathPart {
    TCL_PATH_DIRNAME,
    TCL_PATH_TAIL,
    TCL_PATH_EXTENSION,
    TCL_PATH_ROOT
} Tcl_PathPart;

/*
 *----------------------------------------------------------------
 * Data structures related to obsolete filesystem hooks
 *----------------------------------------------------------------
 */

typedef int (TclStatProc_) (CONST char *path, struct stat *buf);
typedef int (TclAccessProc_) (CONST char *path, int mode);
typedef Tcl_Channel (TclOpenFileChannelProc_) (Tcl_Interp *interp,
	CONST char *fileName, CONST char *modeString, int permissions);



/*
 *----------------------------------------------------------------
 * Data structures related to procedures
 *----------------------------------------------------------------
 */

................................................................................

/*
 *----------------------------------------------------------------
 * Data structures for process-global values.
 *----------------------------------------------------------------
 */

typedef void (TclInitProcessGlobalValueProc) (char **valuePtr, int *lengthPtr,
	Tcl_Encoding *encodingPtr);

/*
 * A ProcessGlobalValue struct exists for each internal value in Tcl that is
 * to be shared among several threads. Each thread sees a (Tcl_Obj) copy of
 * the value, and the master is kept as a counted string, with epoch and mutex

 * control. Each ProcessGlobalValue struct should be a static variable in some
 * file.
 */

typedef struct ProcessGlobalValue {
    int epoch;			/* Epoch counter to detect changes in the
				 * master value. */
    int numBytes;		/* Length of the master string. */
    char *value;		/* The master string value. */
    Tcl_Encoding encoding;	/* system encoding when master string was
				 * initialized. */
    TclInitProcessGlobalValueProc *proc;
    				/* A procedure to initialize the master string

				 * copy when a "get" request comes in before
				 * any "set" request has been received. */
    Tcl_Mutex mutex;		/* Enforce orderly access from multiple
				 * threads. */
    Tcl_ThreadDataKey key;	/* Key for per-thread data holding the
				 * (Tcl_Obj) copy for each thread. */
} ProcessGlobalValue;

/*
 *----------------------------------------------------------------------
 * Flags for TclParseNumber
 *----------------------------------------------------------------------
 */
................................................................................

MODULE_SCOPE char *	tclNativeExecutableName;
MODULE_SCOPE int	tclFindExecutableSearchDone;
MODULE_SCOPE char *	tclMemDumpFileName;
MODULE_SCOPE TclPlatformType tclPlatform;
MODULE_SCOPE Tcl_NotifierProcs tclOriginalNotifier;

/*
 * TIP #233 (Virtualized Time)
 * Data for the time hooks, if any.
 */

MODULE_SCOPE Tcl_GetTimeProc*   tclGetTimeProcPtr;
MODULE_SCOPE Tcl_ScaleTimeProc* tclScaleTimeProcPtr;
MODULE_SCOPE ClientData		tclTimeClientData;

/*
 * Variables denoting the Tcl object types defined in the core.
 */

MODULE_SCOPE Tcl_ObjType tclBignumType;
MODULE_SCOPE Tcl_ObjType tclBooleanType;
................................................................................
MODULE_SCOPE long	tclObjsAlloced;
MODULE_SCOPE long	tclObjsFreed;
#define TCL_MAX_SHARED_OBJ_STATS 5
MODULE_SCOPE long	tclObjsShared[TCL_MAX_SHARED_OBJ_STATS];
#endif /* TCL_COMPILE_STATS */

/*
 * Pointer to a heap-allocated string of length zero that the Tcl core uses as
 * the value of an empty string representation for an object. This value is
 * shared by all new objects allocated by Tcl_NewObj.
 */

MODULE_SCOPE char *	tclEmptyStringRep;
MODULE_SCOPE char	tclEmptyString;

/*
 *----------------------------------------------------------------
 * Procedures shared among Tcl modules but not used by the outside world:

 *----------------------------------------------------------------
 */

MODULE_SCOPE void	TclAppendLimitedToObj(Tcl_Obj *objPtr,
			    CONST char *bytes, int length, int limit,
			    CONST char *ellipsis);
MODULE_SCOPE void	TclAppendObjToErrorInfo(Tcl_Interp *interp,
			    Tcl_Obj *objPtr);
MODULE_SCOPE int	TclArraySet(Tcl_Interp *interp,
			    Tcl_Obj *arrayNameObj, Tcl_Obj *arrayElemObj);
MODULE_SCOPE double	TclBignumToDouble(mp_int* bignum);
MODULE_SCOPE double	TclCeil(mp_int* a);
MODULE_SCOPE int	TclCheckBadOctal(Tcl_Interp *interp,CONST char *value);
MODULE_SCOPE int	TclChanCreateObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	TclChanPostEventObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	TclChanCaughtErrorBypass(Tcl_Interp *interp,
			    Tcl_Channel chan);
MODULE_SCOPE void	TclCleanupLiteralTable(Tcl_Interp* interp,
			    LiteralTable* tablePtr);
MODULE_SCOPE int	TclDoubleDigits(char* buf, double value, int* signum);
MODULE_SCOPE void	TclExpandTokenArray(Tcl_Parse *parsePtr);
MODULE_SCOPE int	TclFileAttrsCmd(Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	TclFileCopyCmd(Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	TclFileDeleteCmd(Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	TclFileMakeDirsCmd(Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	TclFileRenameCmd(Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]);
MODULE_SCOPE void	TclFinalizeAllocSubsystem(void);
MODULE_SCOPE void	TclFinalizeAsync(void);
MODULE_SCOPE void	TclFinalizeCompilation(void);
MODULE_SCOPE void	TclFinalizeDoubleConversion(void);
MODULE_SCOPE void	TclFinalizeEncodingSubsystem(void);
MODULE_SCOPE void	TclFinalizeEnvironment(void);
MODULE_SCOPE void	TclFinalizeExecution(void);
MODULE_SCOPE void	TclFinalizeIOSubsystem(void);
MODULE_SCOPE void	TclFinalizeFilesystem(void);
MODULE_SCOPE void	TclResetFilesystem(void);
MODULE_SCOPE void	TclFinalizeLoad(void);
MODULE_SCOPE void	TclFinalizeLock(void);
MODULE_SCOPE void	TclFinalizeMemorySubsystem(void);
MODULE_SCOPE void	TclFinalizeNotifier(void);
MODULE_SCOPE void	TclFinalizeObjects(void);
MODULE_SCOPE void	TclFinalizePreserve(void);
MODULE_SCOPE void	TclFinalizeSynchronization(void);
MODULE_SCOPE void	TclFinalizeThreadData(void);
MODULE_SCOPE double	TclFloor(mp_int* a);
MODULE_SCOPE void	TclFormatNaN(double value, char* buffer);
MODULE_SCOPE int	TclFSFileAttrIndex(Tcl_Obj *pathPtr,
			    CONST char *attributeName, int *indexPtr);
MODULE_SCOPE Tcl_Obj *	TclGetBgErrorHandler(Tcl_Interp *interp);
MODULE_SCOPE int	TclGetEncodingFromObj(Tcl_Interp *interp,
			    Tcl_Obj *objPtr, Tcl_Encoding *encodingPtr);
MODULE_SCOPE int	TclGetNamespaceFromObj(Tcl_Interp *interp,
			    Tcl_Obj *objPtr, Tcl_Namespace **nsPtrPtr);
MODULE_SCOPE int	TclGetOpenModeEx(Tcl_Interp *interp,
			    CONST char *modeString, int *seekFlagPtr,
			    int *binaryPtr);
MODULE_SCOPE Tcl_Obj *	TclGetProcessGlobalValue(ProcessGlobalValue *pgvPtr);
MODULE_SCOPE int	TclGlob(Tcl_Interp *interp, char *pattern,
			    Tcl_Obj *unquotedPrefix, int globFlags,
			    Tcl_GlobTypeData* types);
MODULE_SCOPE int	TclIncrObj(Tcl_Interp *interp, Tcl_Obj *valuePtr,
			    Tcl_Obj *incrPtr);
MODULE_SCOPE Tcl_Obj *	TclIncrObjVar2(Tcl_Interp *interp, Tcl_Obj *part1Ptr,
			    Tcl_Obj *part2Ptr, Tcl_Obj *incrPtr, int flags);
MODULE_SCOPE void	TclInitAlloc(void);
MODULE_SCOPE int	TclInitBignumFromDouble(Tcl_Interp *interp, double d,
			    mp_int *b);
MODULE_SCOPE void	TclInitDbCkalloc(void);
MODULE_SCOPE void	TclInitDoubleConversion(void);
MODULE_SCOPE void	TclInitEmbeddedConfigurationInformation(
			    Tcl_Interp *interp);
MODULE_SCOPE void	TclInitEncodingSubsystem(void);
MODULE_SCOPE void	TclInitIOSubsystem(void);
MODULE_SCOPE void	TclInitLimitSupport(Tcl_Interp *interp);
MODULE_SCOPE void	TclInitNamespaceSubsystem(void);
MODULE_SCOPE void	TclInitNotifier(void);
MODULE_SCOPE void	TclInitObjSubsystem(void);
MODULE_SCOPE void	TclInitSubsystems ();
MODULE_SCOPE int	TclInterpReady(Tcl_Interp *interp);
MODULE_SCOPE int	TclIsLocalScalar(CONST char *src, int len);
MODULE_SCOPE int	TclJoinThread(Tcl_ThreadId id, int* result);
MODULE_SCOPE void	TclLimitRemoveAllHandlers(Tcl_Interp *interp);
MODULE_SCOPE Tcl_Obj *	TclLindexList(Tcl_Interp* interp,
			    Tcl_Obj* listPtr, Tcl_Obj* argPtr);
MODULE_SCOPE Tcl_Obj *	TclLindexFlat(Tcl_Interp* interp, Tcl_Obj* listPtr,
			    int indexCount, Tcl_Obj *CONST indexArray[]);
MODULE_SCOPE int	TclLoadFile(Tcl_Interp* interp, Tcl_Obj *pathPtr,
			    int symc, CONST char *symbols[],
			    Tcl_PackageInitProc **procPtrs[],
			    Tcl_LoadHandle *handlePtr,
			    ClientData *clientDataPtr,
			    Tcl_FSUnloadFileProc **unloadProcPtr);
MODULE_SCOPE Tcl_Obj *	TclLsetList(Tcl_Interp* interp, Tcl_Obj* listPtr,
			    Tcl_Obj* indexPtr, Tcl_Obj* valuePtr);
MODULE_SCOPE Tcl_Obj *	TclLsetFlat(Tcl_Interp* interp, Tcl_Obj* listPtr,
			    int indexCount, Tcl_Obj *CONST indexArray[],
			    Tcl_Obj* valuePtr);
MODULE_SCOPE int	TclMergeReturnOptions(Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[], Tcl_Obj **optionsPtrPtr,
			    int *codePtr, int *levelPtr);
MODULE_SCOPE int	TclObjInvokeNamespace(Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[],
			    Tcl_Namespace *nsPtr, int flags);
MODULE_SCOPE int	TclParseBackslash(CONST char *src,
			    int numBytes, int *readPtr, char *dst);
MODULE_SCOPE int	TclParseHex(CONST char *src, int numBytes,
			    Tcl_UniChar *resultPtr);
MODULE_SCOPE int	TclParseNumber(Tcl_Interp* interp, Tcl_Obj* objPtr,
			    CONST char* type, CONST char* string,
			    size_t length, CONST char** endPtrPtr, int flags);
MODULE_SCOPE void	TclParseInit(Tcl_Interp *interp, CONST char *string,
			    int numBytes, Tcl_Parse *parsePtr);
#if 0
MODULE_SCOPE int	TclParseInteger(CONST char *string, int numBytes);
#endif
MODULE_SCOPE int	TclParseWhiteSpace(CONST char *src,
			    int numBytes, Tcl_Parse *parsePtr, char *typePtr);
MODULE_SCOPE int	TclProcessReturn(Tcl_Interp *interp,
			    int code, int level, Tcl_Obj *returnOpts);
MODULE_SCOPE int	TclpObjLstat(Tcl_Obj *pathPtr, Tcl_StatBuf *buf);
MODULE_SCOPE int	TclpCheckStackSpace(void);
MODULE_SCOPE Tcl_Obj *	TclpTempFileName(void);
MODULE_SCOPE Tcl_Obj *	TclNewFSPathObj(Tcl_Obj *dirPtr, CONST char *addStrRep,
			    int len);
MODULE_SCOPE int	TclpDeleteFile(CONST char *path);
MODULE_SCOPE void	TclpFinalizeCondition(Tcl_Condition *condPtr);
MODULE_SCOPE void	TclpFinalizeMutex(Tcl_Mutex *mutexPtr);
MODULE_SCOPE void	TclpFinalizePipes(void);
MODULE_SCOPE int	TclpThreadCreate(Tcl_ThreadId *idPtr,
			    Tcl_ThreadCreateProc proc, ClientData clientData,
			    int stackSize, int flags);
MODULE_SCOPE int	TclpFindVariable(CONST char *name, int *lengthPtr);
MODULE_SCOPE void	TclpInitLibraryPath(char **valuePtr,
			    int *lengthPtr, Tcl_Encoding *encodingPtr);
MODULE_SCOPE void	TclpInitLock(void);
MODULE_SCOPE void	TclpInitPlatform(void);
MODULE_SCOPE void	TclpInitUnlock(void);
MODULE_SCOPE int	TclpLoadFile(Tcl_Interp *interp, Tcl_Obj *pathPtr,
			    CONST char *sym1, CONST char *sym2,
			    Tcl_PackageInitProc **proc1Ptr,
			    Tcl_PackageInitProc **proc2Ptr,
			    ClientData *clientDataPtr,
			    Tcl_FSUnloadFileProc **unloadProcPtr);
MODULE_SCOPE Tcl_Obj *	TclpObjListVolumes(void);
MODULE_SCOPE void	TclpMasterLock(void);
MODULE_SCOPE void	TclpMasterUnlock(void);
MODULE_SCOPE int	TclpMatchFiles(Tcl_Interp *interp, char *separators,
			    Tcl_DString *dirPtr, char *pattern, char *tail);
MODULE_SCOPE int	TclpObjNormalizePath(Tcl_Interp *interp,
			    Tcl_Obj *pathPtr, int nextCheckpoint);
MODULE_SCOPE void	TclpNativeJoinPath(Tcl_Obj *prefix, char *joining);
MODULE_SCOPE Tcl_Obj *	TclpNativeSplitPath(Tcl_Obj *pathPtr, int *lenPtr);
MODULE_SCOPE Tcl_PathType TclpGetNativePathType(Tcl_Obj *pathPtr,
			    int *driveNameLengthPtr, Tcl_Obj **driveNameRef);
MODULE_SCOPE int 	TclCrossFilesystemCopy(Tcl_Interp *interp,
			    Tcl_Obj *source, Tcl_Obj *target);
MODULE_SCOPE int	TclpMatchInDirectory(Tcl_Interp *interp,
			    Tcl_Obj *resultPtr, Tcl_Obj *pathPtr,
			    CONST char *pattern, Tcl_GlobTypeData *types);
MODULE_SCOPE ClientData	TclpGetNativeCwd(ClientData clientData);
MODULE_SCOPE Tcl_FSDupInternalRepProc TclNativeDupInternalRep;
MODULE_SCOPE Tcl_Obj*	TclpObjLink(Tcl_Obj *pathPtr, Tcl_Obj *toPtr,
			    int linkType);
MODULE_SCOPE int	TclpObjChdir(Tcl_Obj *pathPtr);
MODULE_SCOPE Tcl_Obj *	TclPathPart(Tcl_Interp *interp, Tcl_Obj *pathPtr,
			    Tcl_PathPart portion);
MODULE_SCOPE void	TclpPanic TCL_VARARGS(CONST char *, format);
MODULE_SCOPE char *	TclpReadlink(CONST char *fileName,
			    Tcl_DString *linkPtr);
MODULE_SCOPE void	TclpReleaseFile(TclFile file);
MODULE_SCOPE void	TclpSetInterfaces(void);
MODULE_SCOPE void	TclpSetVariables(Tcl_Interp *interp);
MODULE_SCOPE void	TclpUnloadFile(Tcl_LoadHandle loadHandle);
MODULE_SCOPE VOID *	TclpThreadDataKeyGet(Tcl_ThreadDataKey *keyPtr);
MODULE_SCOPE void	TclpThreadDataKeySet(Tcl_ThreadDataKey *keyPtr,
			    VOID *data);
MODULE_SCOPE void	TclpThreadExit(int status);
MODULE_SCOPE int	TclpThreadGetStackSize(void);
MODULE_SCOPE void	TclRememberCondition(Tcl_Condition *mutex);
MODULE_SCOPE VOID	TclRememberJoinableThread(Tcl_ThreadId id);
MODULE_SCOPE void	TclRememberMutex(Tcl_Mutex *mutex);
MODULE_SCOPE void	TclRemoveScriptLimitCallbacks(Tcl_Interp *interp);
MODULE_SCOPE void	TclSetBgErrorHandler(Tcl_Interp *interp,
			    Tcl_Obj *cmdPrefix);
MODULE_SCOPE void	TclSetBignumIntRep (Tcl_Obj *objPtr,
			    mp_int *bignumValue);
MODULE_SCOPE void	TclSetProcessGlobalValue(ProcessGlobalValue *pgvPtr,
			    Tcl_Obj *newValue, Tcl_Encoding encoding);
MODULE_SCOPE VOID	TclSignalExitThread(Tcl_ThreadId id, int result);
MODULE_SCOPE int	TclSubstTokens(Tcl_Interp *interp, Tcl_Token *tokenPtr,
			    int count, int *tokensLeftPtr);
MODULE_SCOPE void	TclTransferResult(Tcl_Interp *sourceInterp, int result,
			    Tcl_Interp *targetInterp);
MODULE_SCOPE Tcl_Obj *	TclpNativeToNormalized(ClientData clientData);
MODULE_SCOPE Tcl_Obj *	TclpFilesystemPathType(Tcl_Obj* pathPtr);
MODULE_SCOPE Tcl_PackageInitProc* TclpFindSymbol(Tcl_Interp *interp,
			    Tcl_LoadHandle loadHandle, CONST char *symbol);
MODULE_SCOPE int	TclpDlopen(Tcl_Interp *interp, Tcl_Obj *pathPtr,
			    Tcl_LoadHandle *loadHandle,
			    Tcl_FSUnloadFileProc **unloadProcPtr);
MODULE_SCOPE int	TclpUtime(Tcl_Obj *pathPtr, struct utimbuf *tval);
#ifdef TCL_LOAD_FROM_MEMORY
MODULE_SCOPE void*	TclpLoadMemoryGetBuffer(Tcl_Interp *interp, int size);
MODULE_SCOPE int	TclpLoadMemory(Tcl_Interp *interp, void *buffer,
			    int size, int codeSize, Tcl_LoadHandle *loadHandle,
			    Tcl_FSUnloadFileProc **unloadProcPtr);
#endif
MODULE_SCOPE void	TclInitThreadStorage(void);
MODULE_SCOPE void	TclpFinalizeThreadDataThread(void);
MODULE_SCOPE void	TclFinalizeThreadStorage(void);

/*
 *----------------------------------------------------------------
 * Command procedures in the generic core:
 *----------------------------------------------------------------
 */

MODULE_SCOPE int	Tcl_AfterObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_AppendObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_ArrayObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_BinaryObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_BreakObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_CaseObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_CatchObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_CdObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	TclChanTruncateObjCmd(
			    ClientData clientData, Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	TclClockClicksObjCmd(
			    ClientData clientData, Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	TclClockGetenvObjCmd(
			    ClientData clientData, Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	TclClockMicrosecondsObjCmd(
			    ClientData clientData, Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	TclClockMillisecondsObjCmd(
			    ClientData clientData, Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	TclClockSecondsObjCmd(
			    ClientData clientData, Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	TclClockLocaltimeObjCmd(
			    ClientData clientData, Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	TclClockMktimeObjCmd(
			    ClientData clientData, Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	TclClockOldscanObjCmd(
			    ClientData clientData, Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_CloseObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_ConcatObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_ContinueObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE Tcl_TimerToken TclCreateAbsoluteTimerHandler(
			    Tcl_Time *timePtr, Tcl_TimerProc *proc,
			    ClientData clientData);
MODULE_SCOPE int	TclDefaultBgErrorHandlerObjCmd(
			    ClientData clientData, Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_DictObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_EncodingObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	TclEncodingDirsObjCmd(
			    ClientData clientData, Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_EofObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_ErrorObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_EvalObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_ExecObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_ExitObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_ExprObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_FblockedObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_FconfigureObjCmd(
			    ClientData clientData, Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_FcopyObjCmd(ClientData dummy,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_FileObjCmd(ClientData dummy,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_FileEventObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_FlushObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_ForObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_ForeachObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_FormatObjCmd(ClientData dummy,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_GetsObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_GlobalObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_GlobObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_IfObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_IncrObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_InfoObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_InterpObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int argc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_JoinObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_LappendObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_LassignObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_LindexObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_LinsertObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_LlengthObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_ListObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_LoadObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_LrangeObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_LrepeatObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_LreplaceObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_LsearchObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_LsetObjCmd(ClientData clientData,
			    Tcl_Interp* interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_LsortObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_NamespaceObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_OpenObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_PackageObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_PidObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_PutsObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_PwdObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_ReadObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_RegexpObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_RegsubObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_RenameObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_ReturnObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_ScanObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_SeekObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_SetObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_SplitObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_SocketObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_SourceObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_StringObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_SubstObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_SwitchObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_TellObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_TimeObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_TraceObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_UnloadObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_UnsetObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_UpdateObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_UplevelObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_UpvarObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_VariableObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_VwaitObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);
MODULE_SCOPE int	Tcl_WhileObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *CONST objv[]);

/*
 *----------------------------------------------------------------
 * Compilation procedures for commands in the generic core:
 *----------------------------------------------------------------
 */

MODULE_SCOPE int	TclCompileAppendCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileBreakCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileCatchCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileContinueCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileDictCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileExprCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileForCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileForeachCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileIfCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileIncrCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileLappendCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileLassignCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileLindexCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileListCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileLlengthCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileLsetCmd(Tcl_Interp* interp,
			    Tcl_Parse* parsePtr, struct CompileEnv* envPtr);
MODULE_SCOPE int	TclCompileRegexpCmd(Tcl_Interp* interp,
			    Tcl_Parse* parsePtr, struct CompileEnv* envPtr);
MODULE_SCOPE int	TclCompileReturnCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileSetCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileStringCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileSwitchCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileWhileCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, struct CompileEnv *envPtr);

/*
 * Functions defined in generic/tclVar.c and currenttly exported only for use
 * by the bytecode compiler and engine. Some of these could later be placed in
 * the public interface.
 */

MODULE_SCOPE Var *	TclLookupArrayElement(Tcl_Interp *interp,
			    CONST char *arrayName, CONST char *elName,
			    CONST int flags, CONST char *msg,
			    CONST int createPart1, CONST int createPart2,
			    Var *arrayPtr);
MODULE_SCOPE Var *	TclObjLookupVar(Tcl_Interp *interp,
			    Tcl_Obj *part1Ptr, CONST char *part2, int flags,
			    CONST char *msg, CONST int createPart1,
			    CONST int createPart2, Var **arrayPtrPtr);
MODULE_SCOPE Tcl_Obj *	TclPtrGetVar(Tcl_Interp *interp,
			    Var *varPtr, Var *arrayPtr, CONST char *part1,
			    CONST char *part2, CONST int flags);
MODULE_SCOPE Tcl_Obj *	TclPtrSetVar(Tcl_Interp *interp,
			    Var *varPtr, Var *arrayPtr, CONST char *part1,
			    CONST char *part2, Tcl_Obj *newValuePtr,
			    CONST int flags);
MODULE_SCOPE Tcl_Obj *	TclPtrIncrObjVar (Tcl_Interp *interp,
			    Var *varPtr, Var *arrayPtr, CONST char *part1,
			    CONST char *part2, Tcl_Obj *incrPtr,
			    CONST int flags);
#if 0
MODULE_SCOPE Tcl_Obj *	TclPtrIncrVar(Tcl_Interp *interp,
			    Var *varPtr, Var *arrayPtr, CONST char *part1,
			    CONST char *part2, CONST long i, CONST int flags);
MODULE_SCOPE Tcl_Obj *	TclPtrIncrWideVar(Tcl_Interp *interp,
			    Var *varPtr, Var *arrayPtr, CONST char *part1,
			    CONST char *part2, CONST Tcl_WideInt i,
			    CONST int flags);
#endif
MODULE_SCOPE void	TclInvalidateNsPath(Namespace *nsPtr);














































/*
 *----------------------------------------------------------------
 * Macros used by the Tcl core to create and release Tcl objects.
 * TclNewObj(objPtr) creates a new object denoting an empty string.
 * TclDecrRefCount(objPtr) decrements the object's reference count, and frees
 * the object if its reference count is zero. These macros are inline versions

 * of Tcl_NewObj() and Tcl_DecrRefCount(). Notice that the names differ in not
 * having a "_" after the "Tcl". Notice also that these macros reference their
 * argument more than once, so you should avoid calling them with an
 * expression that is expensive to compute or has side effects. The ANSI C
 * "prototypes" for these macros are:
 *
 * MODULE_SCOPE void	TclNewObj(Tcl_Obj *objPtr);
 * MODULE_SCOPE void	TclDecrRefCount(Tcl_Obj *objPtr);
 *
 * These macros are defined in terms of two macros that depend on memory
 * allocator in use: TclAllocObjStorage, TclFreeObjStorage. They are defined
 * below.
 *----------------------------------------------------------------
 */

#ifdef TCL_COMPILE_STATS
#  define TclIncrObjsAllocated() \
    tclObjsAlloced++
#  define TclIncrObjsFreed() \
................................................................................

# define TclDecrRefCount(objPtr) \
    if (--(objPtr)->refCount <= 0) { \
	if ((objPtr)->typePtr && (objPtr)->typePtr->freeIntRepProc) { \
	    TclFreeObj(objPtr); \
	} else { \
	    if ((objPtr)->bytes \
		    && ((objPtr)->bytes != tclEmptyStringRep)) { \
		ckfree((char *) (objPtr)->bytes); \
	    } \
	    TclFreeObjStorage(objPtr); \
	    TclIncrObjsFreed(); \
	} \
    }

#if defined(PURIFY)

/*
 * The PURIFY mode is like the regular mode, but instead of doing block
 * Tcl_Obj allocation and keeping a freed list for efficiency, it always
 * allocates and frees a single Tcl_Obj so that tools like Purify can better
 * track memory leaks
 */

#  define TclAllocObjStorage(objPtr) \
	(objPtr) = (Tcl_Obj *) Tcl_Alloc(sizeof(Tcl_Obj))

#  define TclFreeObjStorage(objPtr) \
	ckfree((char *) (objPtr))

#elif defined(TCL_THREADS) && defined(USE_THREAD_ALLOC)

/*
 * The TCL_THREADS mode is like the regular mode but allocates Tcl_Obj's from
 * per-thread caches.
 */

MODULE_SCOPE Tcl_Obj *	TclThreadAllocObj(void);
MODULE_SCOPE void	TclThreadFreeObj(Tcl_Obj *);
MODULE_SCOPE Tcl_Mutex *TclpNewAllocMutex(void);
MODULE_SCOPE void	TclFreeAllocCache(void *);
MODULE_SCOPE void *	TclpGetAllocCache(void);
MODULE_SCOPE void	TclpSetAllocCache(void *);
MODULE_SCOPE void	TclFinalizeThreadAlloc(void);
MODULE_SCOPE void	TclpFreeAllocMutex(Tcl_Mutex* mutex);
MODULE_SCOPE void	TclpFreeAllocCache(void *);

#  define TclAllocObjStorage(objPtr) \
	(objPtr) = TclThreadAllocObj()

#  define TclFreeObjStorage(objPtr) \
	TclThreadFreeObj((objPtr))

................................................................................
	Tcl_MutexLock(&tclObjMutex); \
	(objPtr)->internalRep.otherValuePtr = (VOID *) tclFreeObjList; \
	tclFreeObjList = (objPtr); \
	Tcl_MutexUnlock(&tclObjMutex)
#endif

#else /* TCL_MEM_DEBUG */
MODULE_SCOPE void	TclDbInitNewObj(Tcl_Obj *objPtr);

# define TclDbNewObj(objPtr, file, line) \
    TclIncrObjsAllocated(); \
    (objPtr) = (Tcl_Obj *) Tcl_DbCkalloc(sizeof(Tcl_Obj), (file), (line)); \
    TclDbInitNewObj(objPtr);

# define TclNewObj(objPtr) \
................................................................................
    TclDbNewListObjDirect(objc, objv, __FILE__, __LINE__)

#undef USE_THREAD_ALLOC
#endif /* TCL_MEM_DEBUG */

/*
 *----------------------------------------------------------------
 * Macro used by the Tcl core to set a Tcl_Obj's string representation to a
 * copy of the "len" bytes starting at "bytePtr". This code works even if the
 * byte array contains NULLs as long as the length is correct. Because "len"
 * is referenced multiple times, it should be as simple an expression as
 * possible. The ANSI C "prototype" for this macro is:

 *

 * MODULE_SCOPE void TclInitStringRep(Tcl_Obj *objPtr, char *bytePtr, int len);
 *
 * This macro should only be called on an unshared objPtr where
 *  objPtr->typePtr->freeIntRepProc == NULL
 *----------------------------------------------------------------
 */

#define TclInitStringRep(objPtr, bytePtr, len) \
................................................................................
		(unsigned) (len)); \
	(objPtr)->bytes[len] = '\0'; \
	(objPtr)->length = (len); \
    }

/*
 *----------------------------------------------------------------
 * Macro used by the Tcl core to get the string representation's byte array
 * pointer from a Tcl_Obj. This is an inline version of Tcl_GetString(). The
 * macro's expression result is the string rep's byte pointer which might be

 * NULL. The bytes referenced by this pointer must not be modified by the
 * caller. The ANSI C "prototype" for this macro is:
 *
 * MODULE_SCOPE char *	TclGetString(Tcl_Obj *objPtr);
 *----------------------------------------------------------------
 */

#define TclGetString(objPtr) \
    ((objPtr)->bytes? (objPtr)->bytes : Tcl_GetString((objPtr)))

/*
 *----------------------------------------------------------------
 * Macro used by the Tcl core to clean out an object's internal
 * representation. Does not actually reset the rep's bytes. The ANSI C
 * "prototype" for this macro is:
 *
 * MODULE_SCOPE void	TclFreeIntRep(Tcl_Obj *objPtr);
 *----------------------------------------------------------------
 */

#define TclFreeIntRep(objPtr) \
    if ((objPtr)->typePtr != NULL && \
	    (objPtr)->typePtr->freeIntRepProc != NULL) { \
	(objPtr)->typePtr->freeIntRepProc(objPtr); \
    }

/*
 *----------------------------------------------------------------
 * Macro used by the Tcl core to clean out an object's string representation.
 * The ANSI C "prototype" for this macro is:
 *
 * MODULE_SCOPE void	TclInvalidateStringRep(Tcl_Obj *objPtr);
 *----------------------------------------------------------------
 */

#define TclInvalidateStringRep(objPtr) \
    if (objPtr->bytes != NULL) { \
	if (objPtr->bytes != tclEmptyStringRep) {\
	    ckfree((char *) objPtr->bytes);\
................................................................................
	objPtr->bytes = NULL;\
    }\


#if 0
/*
 *----------------------------------------------------------------
 * Macro used by the Tcl core to get a Tcl_WideInt value out of a Tcl_Obj of
 * the "wideInt" type.  
 *----------------------------------------------------------------
 */

#ifndef NO_WIDE_TYPE
#    define TclGetWide(resultVar, objPtr) \
	(resultVar) = (objPtr)->internalRep.wideValue
#    define TclGetLongFromWide(resultVar, objPtr) \
	(resultVar) = Tcl_WideAsLong((objPtr)->internalRep.wideValue)
#endif
#endif

/*
 *----------------------------------------------------------------
 * Macro used by the Tcl core get a unicode char from a utf string. It checks
 * to see if we have a one-byte utf char before calling the real
 * Tcl_UtfToUniChar, as this will save a lot of time for primarily ascii
 * string handling. The macro's expression result is 1 for the 1-byte case or

 * the result of Tcl_UtfToUniChar. The ANSI C "prototype" for this macro is:
 *

 * MODULE_SCOPE int	TclUtfToUniChar(CONST char *string, Tcl_UniChar *ch);
 *----------------------------------------------------------------
 */

#define TclUtfToUniChar(str, chPtr) \
	((((unsigned char) *(str)) < 0xC0) ? \
	    ((*(chPtr) = (Tcl_UniChar) *(str)), 1) \
	    : Tcl_UtfToUniChar(str, chPtr))

/*
 *----------------------------------------------------------------
 * Macro used by the Tcl core to compare Unicode strings. On big-endian
 * systems we can use the more efficient memcmp, but this would not be
 * lexically correct on little-endian systems. The ANSI C "prototype" for
 * this macro is:
 *
 * MODULE_SCOPE int	TclUniCharNcmp(CONST Tcl_UniChar *cs,

 *			    CONST Tcl_UniChar *ct, unsigned long n);
 *----------------------------------------------------------------
 */

#ifdef WORDS_BIGENDIAN
#   define TclUniCharNcmp(cs,ct,n) memcmp((cs),(ct),(n)*sizeof(Tcl_UniChar))
#else /* !WORDS_BIGENDIAN */
#   define TclUniCharNcmp Tcl_UniCharNcmp
#endif /* WORDS_BIGENDIAN */

/*
 *----------------------------------------------------------------
 * Macro used by the Tcl core to increment a namespace's export export epoch

 * counter. The ANSI C "prototype" for this macro is:
 *
 * MODULE_SCOPE void	TclInvalidateNsCmdLookup(Namespace *nsPtr);

 *----------------------------------------------------------------
 */

#define TclInvalidateNsCmdLookup(nsPtr) \
    if ((nsPtr)->numExportPatterns) { \
	(nsPtr)->exportLookupEpoch++; \
    }
................................................................................
 *----------------------------------------------------------------------
 *
 * Core procedures added to libtommath for bignum manipulation.
 *
 *----------------------------------------------------------------------
 */

MODULE_SCOPE void *	TclBNAlloc(size_t nBytes);
MODULE_SCOPE void *	TclBNRealloc(void *oldBlock, size_t newNBytes);
MODULE_SCOPE void	TclBNFree(void *block);
MODULE_SCOPE void	TclBNInitBignumFromLong(mp_int *bignum, long initVal);
MODULE_SCOPE void	TclBNInitBignumFromWideUInt(mp_int* bignum,
			    Tcl_WideUInt initVal);


/*
 *----------------------------------------------------------------
 * Macro used by the Tcl core to check whether a pattern has any characters

 * special to [string match]. The ANSI C "prototype" for this macro is:
 *
 * MODULE_SCOPE int	TclMatchIsTrivial(CONST char *pattern);

 *----------------------------------------------------------------
 */

#define TclMatchIsTrivial(pattern)	strpbrk((pattern), "*[]]?\\") == NULL

/*
 *----------------------------------------------------------------
 * Macro used by the Tcl core to write the string rep of a long integer to a

 * character buffer. The ANSI C "prototype" for this macro is:
 *
 * MODULE_SCOPE int	TclFormatInt(char *buf, long n);
 *----------------------------------------------------------------
 */

#define TclFormatInt(buf, n)		sprintf((buf), "%ld", (long)(n))

/*
 *----------------------------------------------------------------
 * Macros used by the Tcl core to set a Tcl_Obj's numeric representation
 * avoiding the corresponding function calls in time critical parts of the
 * core. They should only be called on unshared objects. The ANSI C
 * "prototypes" for these macros are:
 *
 * MODULE_SCOPE void	TclSetIntObj(Tcl_Obj *objPtr, int intValue);

 * MODULE_SCOPE void	TclSetLongObj(Tcl_Obj *objPtr, long longValue);

 * MODULE_SCOPE void	TclSetBooleanObj(Tcl_Obj *objPtr, long boolValue);

 * MODULE_SCOPE void	TclSetWideIntObj(Tcl_Obj *objPtr, Tcl_WideInt w);

 * MODULE_SCOPE void	TclSetDoubleObj(Tcl_Obj *objPtr, double d);


 *----------------------------------------------------------------
 */

#define TclSetIntObj(objPtr, i) \
    TclInvalidateStringRep(objPtr);\
    TclFreeIntRep(objPtr); \
    (objPtr)->internalRep.longValue = (long)(i); \
    (objPtr)->typePtr = &tclIntType

#define TclSetLongObj(objPtr, l) \
    TclSetIntObj((objPtr), (l))

/*
 * NOTE: There is to be no such thing as a "pure" boolean. Boolean values set
 * programmatically go straight to being "int" Tcl_Obj's, with value 0 or 1.

 * The only "boolean" Tcl_Obj's shall be those holding the cached boolean
 * value of strings like: "yes", "no", "true", "false", "on", "off".
 */

#define TclSetBooleanObj(objPtr, b) \
    TclSetIntObj((objPtr), ((b)? 1 : 0));

#ifndef NO_WIDE_TYPE
#define TclSetWideIntObj(objPtr, w) \
    TclInvalidateStringRep(objPtr);\
    TclFreeIntRep(objPtr); \
................................................................................
    TclInvalidateStringRep(objPtr);\
    TclFreeIntRep(objPtr); \
    (objPtr)->internalRep.doubleValue = (double)(d); \
    (objPtr)->typePtr = &tclDoubleType

/*
 *----------------------------------------------------------------
 * Macros used by the Tcl core to create and initialise objects of standard
 * types, avoiding the corresponding function calls in time critical parts of
 * the core. The ANSI C "prototypes" for these macros are:

 *
 * MODULE_SCOPE void	TclNewIntObj(Tcl_Obj *objPtr, int i);

 * MODULE_SCOPE void	TclNewLongObj(Tcl_Obj *objPtr, long l);

 * MODULE_SCOPE void	TclNewBooleanObj(Tcl_Obj *objPtr, int b);

 * MODULE_SCOPE void	TclNewWideObj(Tcl_Obj *objPtr, Tcl_WideInt w);

 * MODULE_SCOPE void	TclNewDoubleObj(Tcl_Obj *objPtr, double d);

 * MODULE_SCOPE void	TclNewStringObj(Tcl_Obj *objPtr, char *s, int len);

 *
 *----------------------------------------------------------------
 */

#ifndef TCL_MEM_DEBUG
#define TclNewIntObj(objPtr, i) \
    TclIncrObjsAllocated(); \
    TclAllocObjStorage(objPtr); \
    (objPtr)->refCount = 0; \
    (objPtr)->bytes = NULL; \
    (objPtr)->internalRep.longValue = (long)(i); \
................................................................................
#endif

#include "tclPort.h"
#include "tclIntDecls.h"
#include "tclIntPlatDecls.h"

#endif /* _TCLINT */
 
/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */

Changes to generic/tclLink.c.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
..
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
..
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
...
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
...
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
...
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
...
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
/* 
 * tclLink.c --
 *
 *	This file implements linked variables (a C variable that is tied to a
 *	Tcl variable).  The idea of linked variables was first suggested by
 *	Andreas Stolcke and this implementation is based heavily on a
 *	prototype implementation provided by him.
 *
 * Copyright (c) 1993 The Regents of the University of California.
 * Copyright (c) 1994-1997 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclLink.c,v 1.8.6.3 2005/08/22 20:50:26 dgp Exp $
 */

#include "tclInt.h"

/*
 * For each linked variable there is a data structure of the following type,
 * which describes the link and is the clientData for the trace set on the Tcl
 * variable.
 */

typedef struct Link {
    Tcl_Interp *interp;		/* Interpreter containing Tcl variable. */
    Tcl_Obj *varName;		/* Name of variable (must be global).  This is
				 * needed during trace callbacks, since the
				 * actual variable may be aliased at that time
				 * via upvar. */
    char *addr;			/* Location of C variable. */
    int type;			/* Type of link (TCL_LINK_INT, etc.). */
    union {
	int i;
................................................................................
#define LINK_READ_ONLY		1
#define LINK_BEING_UPDATED	2

/*
 * Forward references to procedures defined later in this file:
 */

static char *		LinkTraceProc _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, CONST char *name1, 
                            CONST char *name2, int flags));
static Tcl_Obj *	ObjValue _ANSI_ARGS_((Link *linkPtr));
 
/*
 *----------------------------------------------------------------------
 *
 * Tcl_LinkVar --
 *
 *	Link a C variable to a Tcl variable so that changes to either one
................................................................................

int
Tcl_LinkVar(interp, varName, addr, type)
    Tcl_Interp *interp;		/* Interpreter in which varName exists. */
    CONST char *varName;	/* Name of a global variable in interp. */
    char *addr;			/* Address of a C variable to be linked to
				 * varName. */
    int type;			/* Type of C variable: TCL_LINK_INT, etc.
				 * Also may have TCL_LINK_READ_ONLY OR'ed
				 * in. */
{
    Tcl_Obj *objPtr;
    Link *linkPtr;
    int code;

    linkPtr = (Link *) ckalloc(sizeof(Link));
    linkPtr->interp = interp;
................................................................................
 *	Destroy the link between a Tcl variable and a C variable.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	If "varName" was previously linked to a C variable, the link is broken
 *	to make the variable independent.  If there was no previous link for
 *	"varName" then nothing happens.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_UnlinkVar(interp, varName)
................................................................................
 
/*
 *----------------------------------------------------------------------
 *
 * Tcl_UpdateLinkedVar --
 *
 *	This procedure is invoked after a linked variable has been changed by
 *	C code.  It updates the Tcl variable so that traces on the variable
 *	will trigger.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The Tcl variable "varName" is updated from its C value, causing traces
................................................................................
		    |TCL_TRACE_UNSETS, LinkTraceProc, (ClientData) linkPtr);
	}
	return NULL;
    }

    /*
     * If we were invoked because of a call to Tcl_UpdateLinkedVar, then don't
     * do anything at all.  In particular, we don't want to get upset that the
     * variable is being modified, even if it is supposed to be read-only.
     */

    if (linkPtr->flags & LINK_BEING_UPDATED) {
	return NULL;
    }

................................................................................
	    Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
		    TCL_GLOBAL_ONLY);
	}
	return NULL;
    }

    /*
     * For writes, first make sure that the variable is writable.  Then
     * convert the Tcl value to C if possible.  If the variable isn't writable
     * or can't be converted, then restore the varaible's old value and return
     * an error.  Another tricky thing: we have to save and restore the
     * interpreter's result, since the variable access could occur when the
     * result has been partially set.
     */

    if (linkPtr->flags & LINK_READ_ONLY) {
	Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
		TCL_GLOBAL_ONLY);
	return "linked variable is read-only";
    }
|



|









|












|







 







|
<
|
|







 







|
|
<







 







|







 







|







 







|







 







|
|
|
|
|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
..
53
54
55
56
57
58
59
60

61
62
63
64
65
66
67
68
69
..
83
84
85
86
87
88
89
90
91

92
93
94
95
96
97
98
...
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
...
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
...
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
...
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
/*
 * tclLink.c --
 *
 *	This file implements linked variables (a C variable that is tied to a
 *	Tcl variable). The idea of linked variables was first suggested by
 *	Andreas Stolcke and this implementation is based heavily on a
 *	prototype implementation provided by him.
 *
 * Copyright (c) 1993 The Regents of the University of California.
 * Copyright (c) 1994-1997 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclLink.c,v 1.8.6.4 2005/08/29 18:38:45 dgp Exp $
 */

#include "tclInt.h"

/*
 * For each linked variable there is a data structure of the following type,
 * which describes the link and is the clientData for the trace set on the Tcl
 * variable.
 */

typedef struct Link {
    Tcl_Interp *interp;		/* Interpreter containing Tcl variable. */
    Tcl_Obj *varName;		/* Name of variable (must be global). This is
				 * needed during trace callbacks, since the
				 * actual variable may be aliased at that time
				 * via upvar. */
    char *addr;			/* Location of C variable. */
    int type;			/* Type of link (TCL_LINK_INT, etc.). */
    union {
	int i;
................................................................................
#define LINK_READ_ONLY		1
#define LINK_BEING_UPDATED	2

/*
 * Forward references to procedures defined later in this file:
 */

static char *		LinkTraceProc(ClientData clientData,Tcl_Interp *interp,

			    CONST char *name1, CONST char *name2, int flags);
static Tcl_Obj *	ObjValue(Link *linkPtr);
 
/*
 *----------------------------------------------------------------------
 *
 * Tcl_LinkVar --
 *
 *	Link a C variable to a Tcl variable so that changes to either one
................................................................................

int
Tcl_LinkVar(interp, varName, addr, type)
    Tcl_Interp *interp;		/* Interpreter in which varName exists. */
    CONST char *varName;	/* Name of a global variable in interp. */
    char *addr;			/* Address of a C variable to be linked to
				 * varName. */
    int type;			/* Type of C variable: TCL_LINK_INT, etc. Also
				 * may have TCL_LINK_READ_ONLY OR'ed in. */

{
    Tcl_Obj *objPtr;
    Link *linkPtr;
    int code;

    linkPtr = (Link *) ckalloc(sizeof(Link));
    linkPtr->interp = interp;
................................................................................
 *	Destroy the link between a Tcl variable and a C variable.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	If "varName" was previously linked to a C variable, the link is broken
 *	to make the variable independent. If there was no previous link for
 *	"varName" then nothing happens.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_UnlinkVar(interp, varName)
................................................................................
 
/*
 *----------------------------------------------------------------------
 *
 * Tcl_UpdateLinkedVar --
 *
 *	This procedure is invoked after a linked variable has been changed by
 *	C code. It updates the Tcl variable so that traces on the variable
 *	will trigger.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The Tcl variable "varName" is updated from its C value, causing traces
................................................................................
		    |TCL_TRACE_UNSETS, LinkTraceProc, (ClientData) linkPtr);
	}
	return NULL;
    }

    /*
     * If we were invoked because of a call to Tcl_UpdateLinkedVar, then don't
     * do anything at all. In particular, we don't want to get upset that the
     * variable is being modified, even if it is supposed to be read-only.
     */

    if (linkPtr->flags & LINK_BEING_UPDATED) {
	return NULL;
    }

................................................................................
	    Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
		    TCL_GLOBAL_ONLY);
	}
	return NULL;
    }

    /*
     * For writes, first make sure that the variable is writable. Then convert
     * the Tcl value to C if possible. If the variable isn't writable or can't
     * be converted, then restore the varaible's old value and return an
     * error. Another tricky thing: we have to save and restore the interp's
     * result, since the variable access could occur when the result has been
     * partially set.
     */

    if (linkPtr->flags & LINK_READ_ONLY) {
	Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
		TCL_GLOBAL_ONLY);
	return "linked variable is read-only";
    }

Changes to generic/tclListObj.c.

6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
....
1609
1610
1611
1612
1613
1614
1615






1616
1617
1618
1619
1620
1621
1622
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 * Copyright (c) 1998 by Scriptics Corporation.
 * Copyright (c) 2001 by Kevin B. Kenny.  All rights reserved.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclListObj.c,v 1.20.2.2 2005/08/02 18:15:59 dgp Exp $
 */

#include "tclInt.h"

/*
 * Prototypes for functions defined later in this file:
 */
................................................................................
    }
    listPtr->length = 1;
    elemPtrs = &listRepPtr->elements;
    for (i = 0; i < numElems; i++) {
	elem = Tcl_GetStringFromObj(elemPtrs[i], &length);
	listPtr->length += Tcl_ScanCountedElement(elem, length,
		&flagPtr[i]) + 1;






    }

    /*
     * Pass 2: copy into string rep buffer.
     */

    listPtr->bytes = ckalloc((unsigned) listPtr->length);






|







 







>
>
>
>
>
>







6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
....
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 * Copyright (c) 1998 by Scriptics Corporation.
 * Copyright (c) 2001 by Kevin B. Kenny.  All rights reserved.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclListObj.c,v 1.20.2.3 2005/08/29 18:38:45 dgp Exp $
 */

#include "tclInt.h"

/*
 * Prototypes for functions defined later in this file:
 */
................................................................................
    }
    listPtr->length = 1;
    elemPtrs = &listRepPtr->elements;
    for (i = 0; i < numElems; i++) {
	elem = Tcl_GetStringFromObj(elemPtrs[i], &length);
	listPtr->length += Tcl_ScanCountedElement(elem, length,
		&flagPtr[i]) + 1;
	/*
	 * Check for continued sanity. [Bug 1267380]
	 */
	if (listPtr->length < 1) {
	    Tcl_Panic("string representation size exceeds sane bounds");
	}
    }

    /*
     * Pass 2: copy into string rep buffer.
     */

    listPtr->bytes = ckalloc((unsigned) listPtr->length);

Changes to generic/tclNamesp.c.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
..
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
..
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
..
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
...
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
...
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
...
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
...
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
...
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
...
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
...
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
...
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
...
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
...
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
...
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
...
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
....
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
....
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
....
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
....
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
....
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
....
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
....
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
....
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
....
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
....
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
....
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
....
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
....
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
....
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
....
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
....
4472
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484
4485
4486
....
4566
4567
4568
4569
4570
4571
4572
4573
4574
4575
4576
4577
4578
4579
4580
....
4594
4595
4596
4597
4598
4599
4600
4601
4602
4603
4604
4605
4606
4607
4608
4609
....
4610
4611
4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
....
4667
4668
4669
4670
4671
4672
4673
4674
4675
4676
4677
4678
4679
4680
4681
4682
4683
4684
4685
4686
4687
4688
4689
4690
4691
4692
....
4748
4749
4750
4751
4752
4753
4754
4755
4756
4757
4758
4759
4760
4761
4762
4763
4764
4765
4766
4767
4768
4769
4770
....
4878
4879
4880
4881
4882
4883
4884
4885
4886
4887
4888
4889
4890
4891
4892
4893
4894
4895
4896
4897
4898


4899
4900

4901
4902
4903
4904
4905
4906
4907
....
5037
5038
5039
5040
5041
5042
5043
5044
5045
5046
5047
5048
5049
5050
5051
5052
5053
5054
....
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
5226
5227
5228
....
5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
5257
5258
....
5312
5313
5314
5315
5316
5317
5318
5319
5320
5321
5322
5323
5324
5325
5326
....
5377
5378
5379
5380
5381
5382
5383
5384
5385
5386
5387
5388
5389
5390
5391
....
5443
5444
5445
5446
5447
5448
5449
5450
5451
5452
5453
5454
5455
5456
5457
....
5495
5496
5497
5498
5499
5500
5501
5502
5503
5504
5505
5506
5507
5508
5509
....
5802
5803
5804
5805
5806
5807
5808
5809
5810
5811
5812
5813
5814
5815
5816
5817
5818
5819
5820
5821
5822
5823
....
5862
5863
5864
5865
5866
5867
5868
5869
5870
5871
5872
5873
5874
5875
5876
....
5969
5970
5971
5972
5973
5974
5975
5976
5977
5978
5979
5980
5981
5982
5983
....
6048
6049
6050
6051
6052
6053
6054
6055
6056
6057
6058
6059
6060
6061
6062
....
6108
6109
6110
6111
6112
6113
6114
6115
6116
6117
6118
6119
6120
6121
6122
....
6143
6144
6145
6146
6147
6148
6149
6150
6151
6152
6153
6154
6155
6156
6157
....
6282
6283
6284
6285
6286
6287
6288
6289
6290
6291
6292
6293
6294
6295
6296
6297
6298
6299
6300
6301
6302
6303
6304
6305
6306
6307
6308
6309
6310
6311
6312
6313
6314
6315
6316
6317
6318
6319
6320
6321
6322
....
6343
6344
6345
6346
6347
6348
6349
6350
6351
6352
6353
6354
6355
6356
6357
....
6379
6380
6381
6382
6383
6384
6385
6386
6387
6388
6389
6390
6391
6392
6393
6394
....
6397
6398
6399
6400
6401
6402
6403
6404
6405
6406
6407
6408
6409
6410
6411
....
6420
6421
6422
6423
6424
6425
6426
6427
6428
6429
6430
6431
6432
6433
6434
6435
6436
....
6487
6488
6489
6490
6491
6492
6493
6494
6495
6496
6497
6498
6499
6500
6501
6502
6503
6504
6505
6506
6507
6508
6509
6510
6511
6512
....
6558
6559
6560
6561
6562
6563
6564
6565
6566
6567
6568
6569
6570
6571
6572
/*
 * tclNamesp.c --
 *
 *	Contains support for namespaces, which provide a separate context of
 *	commands and global variables. The global :: namespace is the
 *	traditional Tcl "global" scope. Other namespaces are created as
 *	children of the global namespace. These other namespaces contain
 *	special-purpose commands and variables for packages.  Also includes
 *	the TIP#112 ensemble machinery.
 *
 * Copyright (c) 1993-1997 Lucent Technologies.
 * Copyright (c) 1997 Sun Microsystems, Inc.
 * Copyright (c) 1998-1999 by Scriptics Corporation.
 * Copyright (c) 2002-2005 Donal K. Fellows.
 *
................................................................................
 *   Michael J. McLennan
 *   Bell Labs Innovations for Lucent Technologies
 *   [email protected]
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclNamesp.c,v 1.66.2.8 2005/08/02 18:16:01 dgp Exp $
 */

#include "tclInt.h"

/*
 * Initial size of stack allocated space for tail list - used when resetting
 * shadowed command references in the functin: TclResetShadowedCmdRefs.
................................................................................
				 * that has a pointer to this ResolvedNsName
				 * structure as its internal rep. This
				 * structure can be freed when refCount
				 * becomes zero. */
} ResolvedNsName;

/*
 * The client data for an ensemble command.  This consists of the table of
 * commands that are actually exported by the namespace, and an epoch counter
 * that, combined with the exportLookupEpoch field of the namespace structure,
 * defines whether the table contains valid data or will need to be recomputed
 * next time the ensemble command is called.
 */

typedef struct EnsembleConfig {
................................................................................
    Tcl_Command token;		/* The token for the command that provides
				 * ensemble support for the namespace, or NULL
				 * if the command has been deleted (or never
				 * existed; the global namespace never has an
				 * ensemble command.) */
    int epoch;			/* The epoch at which this ensemble's table of
				 * exported commands is valid. */
    char **subcommandArrayPtr;	/* Array of ensemble subcommand names.  At all
				 * consistent points, this will have the same
				 * number of entries as there are entries in
				 * the subcommandTable hash. */
    Tcl_HashTable subcommandTable;
				/* Hash table of ensemble subcommand names,
				 * which are its keys so this also provides
				 * the storage management for those subcommand
				 * names.  The contents of the entry values
				 * are object version the prefix lists to use
				 * when substituting for the
				 * command/subcommand to build the ensemble
				 * implementation command.  Has to be stored
				 * here as well as in subcommandDict because
				 * that field is NULL when we are deriving the
				 * ensemble from the namespace exports list.
				 * FUTURE WORK: use object hash table here. */
    struct EnsembleConfig *next;/* The next ensemble in the linked list of
				 * ensembles associated with a namespace. If
				 * this field points to this ensemble, the
				 * structure has already been unlinked from
				 * all lists, and cannot be found by scanning
				 * the list from the namespace's ensemble
				 * field. */
................................................................................
				 * prefixes, or NULL if we are to build the
				 * map automatically from the namespace
				 * exports. */
    Tcl_Obj *subcmdList;	/* List of commands that this ensemble
				 * actually provides, and whose implementation
				 * will be built using the subcommandDict (if
				 * present and defined) and by simple mapping
				 * to the namespace otherwise.  If NULL,
				 * indicates that we are using the (dynamic)
				 * list of currently exported commands. */
    Tcl_Obj *unknownHandler;	/* Script prefix used to handle the case when
				 * no match is found (according to the rule
				 * defined by flag bit TCL_ENSEMBLE_PREFIX) or
				 * NULL to use the default error-generating
				 * behaviour. The script execution gets all
................................................................................
				 * itself has been updated. */
} EnsembleConfig;

#define ENS_DEAD	0x1	/* Flag value to say that the ensemble is dead
				 * and on its way out. */

/*
 * The data cached in a subcommand's Tcl_Obj rep.  This structure is not
 * shared between Tcl_Objs referring to the same subcommand, even where one is
 * a duplicate of another.
 */

typedef struct EnsembleCmdRep {
    Namespace *nsPtr;		/* The namespace backing the ensemble which
				 * this is a subcommand of. */
    int epoch;			/* Used to confirm when the data in this
				 * really structure matches up with the
................................................................................
				 * subcommand. */
} EnsembleCmdRep;

/*
 * Declarations for functions local to this file:
 */

static void		DeleteImportedCmd _ANSI_ARGS_((ClientData clientData));
static int		DoImport _ANSI_ARGS_((Tcl_Interp *interp,
			    Namespace *nsPtr, Tcl_HashEntry *hPtr,
			    CONST char *cmdName, CONST char *pattern,
			    Namespace *importNsPtr, int allowOverwrite));
static void		DupNsNameInternalRep _ANSI_ARGS_((Tcl_Obj *objPtr,
			    Tcl_Obj *copyPtr));
static char *		ErrorCodeRead _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, CONST char *name1,
			    CONST char *name2, int flags));
static char *		ErrorInfoRead _ANSI_ARGS_((ClientData clientData,
			    Tcl_Interp *interp, CONST char *name1,
			    CONST char *name2, int flags));
static char *		EstablishErrorCodeTraces _ANSI_ARGS_((
			    ClientData clientData, Tcl_Interp *interp,
			    CONST char *name1, CONST char *name2, int flags));
static char *		EstablishErrorInfoTraces _ANSI_ARGS_((
			    ClientData clientData, Tcl_Interp *interp,
			    CONST char *name1, CONST char *name2, int flags));
static void		FreeNsNameInternalRep _ANSI_ARGS_((Tcl_Obj *objPtr));
static int		InvokeImportedCmd _ANSI_ARGS_((
			    ClientData clientData, Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]));
static int		NamespaceChildrenCmd _ANSI_ARGS_((
			    ClientData dummy, Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]));
static int		NamespaceCodeCmd _ANSI_ARGS_((
			    ClientData dummy, Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]));
static int		NamespaceCurrentCmd _ANSI_ARGS_((
			    ClientData dummy, Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]));
static int		NamespaceDeleteCmd _ANSI_ARGS_((
			    ClientData dummy, Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]));
static int		NamespaceEnsembleCmd _ANSI_ARGS_((
			    ClientData dummy, Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]));
static int		NamespaceEvalCmd _ANSI_ARGS_((
			    ClientData dummy, Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]));
static int		NamespaceExistsCmd _ANSI_ARGS_((
			    ClientData dummy, Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]));
static int		NamespaceExportCmd _ANSI_ARGS_((
			    ClientData dummy, Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]));
static int		NamespaceForgetCmd _ANSI_ARGS_((
			    ClientData dummy, Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]));
static void		NamespaceFree _ANSI_ARGS_((Namespace *nsPtr));
static int		NamespaceImportCmd _ANSI_ARGS_((
			    ClientData dummy, Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]));
static int		NamespaceInscopeCmd _ANSI_ARGS_((
			    ClientData dummy, Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]));
static int		NamespaceOriginCmd _ANSI_ARGS_((
			    ClientData dummy, Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]));
static int		NamespaceParentCmd _ANSI_ARGS_((
			    ClientData dummy, Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]));
static int		NamespacePathCmd _ANSI_ARGS_((
			    ClientData dummy, Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]));
static int		NamespaceQualifiersCmd _ANSI_ARGS_((
			    ClientData dummy, Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]));
static int		NamespaceTailCmd _ANSI_ARGS_((
			    ClientData dummy, Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]));
static int		NamespaceWhichCmd _ANSI_ARGS_((
			    ClientData dummy, Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]));
static int		SetNsNameFromAny _ANSI_ARGS_((
			    Tcl_Interp *interp, Tcl_Obj *objPtr));
static void		UpdateStringOfNsName _ANSI_ARGS_((Tcl_Obj *objPtr));
static int		NsEnsembleImplementationCmd _ANSI_ARGS_((
			    ClientData clientData, Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]));
static void		BuildEnsembleConfig _ANSI_ARGS_((
			    EnsembleConfig *ensemblePtr));
static int		NsEnsembleStringOrder _ANSI_ARGS_((CONST VOID *strPtr1,
			    CONST VOID *strPtr2));
static void		DeleteEnsembleConfig _ANSI_ARGS_((
			    ClientData clientData));
static void		MakeCachedEnsembleCommand _ANSI_ARGS_((
			    Tcl_Obj *objPtr, EnsembleConfig *ensemblePtr,
			    CONST char *subcmdName, Tcl_Obj *prefixObjPtr));
static void		FreeEnsembleCmdRep _ANSI_ARGS_((Tcl_Obj *objPtr));
static void		DupEnsembleCmdRep _ANSI_ARGS_((Tcl_Obj *objPtr,
			    Tcl_Obj *copyPtr));
static void		StringOfEnsembleCmdRep _ANSI_ARGS_((Tcl_Obj *objPtr));
static void		UnlinkNsPath _ANSI_ARGS_((Namespace *nsPtr));
static void		SetNsPath _ANSI_ARGS_((Namespace *nsPtr,
			    int pathLength, Tcl_Namespace *pathAry[]));

/*
 * This structure defines a Tcl object type that contains a namespace
 * reference. It is used in commands that take the name of a namespace as an
 * argument. The namespace reference is resolved, and the result in cached in
 * the object.
 */
................................................................................
 *	None.
 *
 *----------------------------------------------------------------------
 */

Tcl_Namespace *
Tcl_GetCurrentNamespace(interp)
    register Tcl_Interp *interp; /* Interpreter whose current namespace is
				  * being queried. */
{
    register Interp *iPtr = (Interp *) interp;
    register Namespace *nsPtr;

    if (iPtr->varFramePtr != NULL) {
	nsPtr = iPtr->varFramePtr->nsPtr;
    } else {
................................................................................
 *	None.
 *
 *----------------------------------------------------------------------
 */

Tcl_Namespace *
Tcl_GetGlobalNamespace(interp)
    register Tcl_Interp *interp; /* Interpreter whose global namespace should
				  * be returned. */
{
    register Interp *iPtr = (Interp *) interp;

    return (Tcl_Namespace *) iPtr->globalNsPtr;
}
 
/*
 *----------------------------------------------------------------------
 *
 * Tcl_PushCallFrame --
 *
 *	Pushes a new call frame onto the interpreter's Tcl call stack.  Called
 *	when executing a Tcl procedure or a "namespace eval" or "namespace
 *	inscope" command.
 *
 * Results:
 *	Returns TCL_OK if successful, or TCL_ERROR (along with an error
 *	message in the interpreter's result object) if something goes wrong.
 *
................................................................................
 *	Modifies the interpreter's Tcl call stack.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_PushCallFrame(interp, callFramePtr, namespacePtr, isProcCallFrame)
    Tcl_Interp *interp;		 /* Interpreter in which the new call frame is
				  * to be pushed. */
    Tcl_CallFrame *callFramePtr; /* Points to a call frame structure to push.
				  * Storage for this has already been
				  * allocated by the caller; typically this is
				  * the address of a CallFrame structure
				  * allocated on the caller's C stack. The
				  * call frame will be initialized by this
				  * function. The caller can pop the frame
				  * later with Tcl_PopCallFrame, and it is
				  * responsible for freeing the frame's
				  * storage. */
    Tcl_Namespace *namespacePtr; /* Points to the namespace in which the frame
				  * will execute. If NULL, the interpreter's
				  * current namespace will be used. */
    int isProcCallFrame;	 /* If nonzero, the frame represents a called
				  * Tcl procedure and may have local vars.
				  * Vars will ordinarily be looked up in the
				  * frame. If new variables are created, they
				  * will be created in the frame. If 0, the
				  * frame is for a "namespace eval" or
				  * "namespace inscope" command and var
				  * references are treated as references to
				  * namespace variables. */
{
    Interp *iPtr = (Interp *) interp;
    register CallFrame *framePtr = (CallFrame *) callFramePtr;
    register Namespace *nsPtr;

    if (namespacePtr == NULL) {
	nsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp);
................................................................................
    framePtr->callerPtr = iPtr->framePtr;
    framePtr->callerVarPtr = iPtr->varFramePtr;
    if (iPtr->varFramePtr != NULL) {
	framePtr->level = (iPtr->varFramePtr->level + 1);
    } else {
	framePtr->level = 1;
    }
    framePtr->procPtr = NULL;	   /* no called procedure */
    framePtr->varTablePtr = NULL;  /* and no local variables */
    framePtr->numCompiledLocals = 0;
    framePtr->compiledLocals = NULL;

    /*
     * Push the new call frame onto the interpreter's stack of procedure call
     * frames making it the current frame.
     */
................................................................................
 *	Modifies the interpreter's Tcl call stack.
 *
 *----------------------------------------------------------------------
 */

int
TclPushStackFrame(interp, framePtrPtr, namespacePtr, isProcCallFrame)
    Tcl_Interp *interp;		 /* Interpreter in which the new call frame is
				  * to be pushed. */
    Tcl_CallFrame **framePtrPtr; /* Place to store a pointer to the stack
				  * allocated call frame.*/
    Tcl_Namespace *namespacePtr; /* Points to the namespace in which the frame
				  * will execute. If NULL, the interpreter's
				  * current namespace will be used. */
    int isProcCallFrame;	 /* If nonzero, the frame represents a called
				  * Tcl procedure and may have local vars.
				  * Vars will ordinarily be looked up in the
				  * frame. If new variables are created, they
				  * will be created in the frame. If 0, the
				  * frame is for a "namespace eval" or
				  * "namespace inscope" command and var
				  * references are treated as references to
				  * namespace variables. */
{
    *framePtrPtr = (Tcl_CallFrame *) TclStackAlloc(interp, sizeof(CallFrame));
    return Tcl_PushCallFrame(interp, *framePtrPtr, namespacePtr,
	    isProcCallFrame);
}

void
................................................................................
				 * reporting. */
    CONST char *name;		/* Name for the new namespace. May be a
				 * qualified name with names of ancestor
				 * namespaces separated by "::"s. */
    ClientData clientData;	/* One-word value to store with namespace. */
    Tcl_NamespaceDeleteProc *deleteProc;
				/* Function called to delete client data when
				 * the namespace is deleted.  NULL if no
				 * function should be called. */
{
    Interp *iPtr = (Interp *) interp;
    register Namespace *nsPtr, *ancestorPtr;
    Namespace *parentPtr, *dummy1Ptr, *dummy2Ptr;
    Namespace *globalNsPtr = iPtr->globalNsPtr;
    CONST char *simpleName;
................................................................................
 *	namespaces are deleted.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_DeleteNamespace(namespacePtr)
    Tcl_Namespace *namespacePtr;   /* Points to the namespace to delete. */
{
    register Namespace *nsPtr = (Namespace *) namespacePtr;
    Interp *iPtr = (Interp *) nsPtr->interp;
    Namespace *globalNsPtr =
	    (Namespace *) Tcl_GetGlobalNamespace((Tcl_Interp *) iPtr);
    Tcl_HashEntry *entryPtr;

    /*
     * If the namespace has associated ensemble commands, delete them first.
     * This leaves the actual contents of the namespace alone (unless they are
     * linked ensemble commands, of course.)  Note that this code is actually
     * reentrant so command delete traces won't purturb things badly.
     */

    while (nsPtr->ensembles != NULL) {
	EnsembleConfig *ensemblePtr = (EnsembleConfig *) nsPtr->ensembles;

	/*
................................................................................

    /*
     * If the namespace is on the call frame stack, it is marked as "dying"
     * (NS_DYING is OR'd into its flags): the namespace can't be looked up by
     * name but its commands and variables are still usable by those active
     * call frames. When all active call frames referring to the namespace
     * have been popped from the Tcl stack, Tcl_PopCallFrame will call this
     * function again to delete everything in the namespace.  If no nsName
     * objects refer to the namespace (i.e., if its refCount is zero), its
     * commands and variables are deleted and the storage for its namespace
     * structure is freed. Otherwise, if its refCount is nonzero, the
     * namespace's commands and variables are deleted but the structure isn't
     * freed. Instead, NS_DEAD is OR'd into the structure's flags to allow the
     * namespace resolution code to recognize that the namespace is "deleted".
     * The structure's storage is freed by FreeNsNameInternalRep when its
................................................................................

	TclTeardownNamespace(nsPtr);

	if ((nsPtr != globalNsPtr) || (iPtr->flags & DELETED)) {
	    /*
	     * If this is the global namespace, then it may have residual
	     * "errorInfo" and "errorCode" variables for errors that occurred
	     * while it was being torn down.  Try to clear the variable list
	     * one last time.
	     */

	    TclDeleteVars((Interp *) nsPtr->interp, &nsPtr->varTable);

	    Tcl_DeleteHashTable(&nsPtr->childTable);
	    Tcl_DeleteHashTable(&nsPtr->cmdTable);
................................................................................
 
/*
 *----------------------------------------------------------------------
 *
 * NamespaceFree --
 *
 *	Called after a namespace has been deleted, when its reference count
 *	reaches 0.  Frees the data structure representing the namespace.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *
................................................................................
 *	Optionally reset the namespace's export pattern list.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_Export(interp, namespacePtr, pattern, resetListFirst)
    Tcl_Interp *interp;		 /* Current interpreter. */
    Tcl_Namespace *namespacePtr; /* Points to the namespace from which
				  * commands are to be exported. NULL for the
				  * current namespace. */
    CONST char *pattern;	 /* String pattern indicating which commands
				  * to export. This pattern may not include
				  * any namespace qualifiers; only commands in
				  * the specified namespace may be
				  * exported. */
    int resetListFirst;		 /* If nonzero, resets the namespace's export
				  * list before appending. */
{
#define INIT_EXPORT_PATTERNS 5
    Namespace *nsPtr, *exportNsPtr, *dummyPtr;
    Namespace *currNsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp);
    CONST char *simplePattern;
    char *patternCpy;
    int neededElems, len, i;
................................................................................
	nsPtr->exportArrayPtr = (char **)
		ckalloc((unsigned) (INIT_EXPORT_PATTERNS * sizeof(char *)));
	nsPtr->numExportPatterns = 0;
	nsPtr->maxExportPatterns = INIT_EXPORT_PATTERNS;
    } else if (neededElems > nsPtr->maxExportPatterns) {
	int numNewElems = 2 * nsPtr->maxExportPatterns;
	size_t currBytes = nsPtr->numExportPatterns * sizeof(char *);
	size_t newBytes  = numNewElems * sizeof(char *);
	char **newPtr = (char **) ckalloc((unsigned) newBytes);

	memcpy((VOID *) newPtr, (VOID *) nsPtr->exportArrayPtr, currBytes);
	ckfree((char *) nsPtr->exportArrayPtr);
	nsPtr->exportArrayPtr = (char **) newPtr;
	nsPtr->maxExportPatterns = numNewElems;
    }
................................................................................
    strcpy(patternCpy, pattern);

    nsPtr->exportArrayPtr[nsPtr->numExportPatterns] = patternCpy;
    nsPtr->numExportPatterns++;

    /*
     * The list of commands actually exported from the namespace might have
     * changed (probably will have!)  However, we do not need to recompute
     * this just yet; next time we need the info will be soon enough.
     */

    TclInvalidateNsCmdLookup(nsPtr);

    return TCL_OK;
#undef INIT_EXPORT_PATTERNS
}
................................................................................
     * Unless there is a name clash, create an imported command in the current
     * namespace that refers to cmdPtr.
     */

    found = Tcl_FindHashEntry(&nsPtr->cmdTable, cmdName);
    if ((found == NULL) || allowOverwrite) {
	/*
	 * Create the imported command and its client data.  To create the new
	 * command in the current namespace, generate a fully qualified name
	 * for it.
	 */

	Tcl_DString ds;
	Tcl_Command importedCmd;
	ImportedCmdData *dataPtr;
................................................................................
 *	names, and a pointer to the simple name of the final component is
 *	stored in *simpleNamePtr.
 *
 * Results:
 *	It sets *nsPtrPtr and *altNsPtrPtr to point to the two possible
 *	namespaces which represent the last (containing) namespace in the
 *	qualified name. If the function sets either *nsPtrPtr or *altNsPtrPtr
 *	to NULL, then the search along that path failed.  The function also
 *	stores a pointer to the simple name of the final component in
 *	*simpleNamePtr. If the qualified name is "::" or was treated as a
 *	namespace reference (TCL_FIND_ONLY_NS), the function stores a pointer
 *	to the namespace in *nsPtrPtr, NULL in *altNsPtrPtr, and sets
 *	*simpleNamePtr to point to an empty string.
 *
 *	If there is an error, this function returns TCL_ERROR. If "flags"
................................................................................
     */

    Tcl_DStringInit(&buffer);
    end = start;
    while (*start != '\0') {
	/*
	 * Find the next namespace qualifier (i.e., a name ending in "::") or
	 * the end of the qualified name (i.e., a name ending in "\0").  Set
	 * len to the number of characters, starting from start, in the name;
	 * set end to point after the "::"s or at the "\0".
	 */

	len = 0;
	for (end = start;  *end != '\0';  end++) {
	    if ((*end == ':') && (*(end+1) == ':')) {
................................................................................

    /*
     * We ignore trailing "::"s in a namespace name, but in a command or
     * variable name, trailing "::"s refer to the cmd or var named {}.
     */

    if ((flags & TCL_FIND_ONLY_NS) || (end>start && *(end-1)!=':')) {
	*simpleNamePtr = NULL; /* found namespace name */
    } else {
	*simpleNamePtr = end;  /* found cmd/var: points to empty string */
    }

    /*
     * As a special case, if we are looking for a namespace and qualName is ""
     * and the current active namespace (nsPtr) is not the global namespace,
     * return NULL (no namespace was found). This is because namespaces can
     * not have empty names except for the global namespace.
................................................................................
    Var *varPtr;
    register int search;
    int result;
    Tcl_Var var;

    /*
     * If this namespace has a variable resolver, then give it first crack at
     * the variable resolution.  It may return a Tcl_Var value, it may signal
     * to continue onward, or it may signal an error.
     */

    if ((flags & TCL_GLOBAL_ONLY) != 0) {
	cxtNsPtr = (Namespace *) Tcl_GetGlobalNamespace(interp);
    } else if (contextNsPtr != NULL) {
	cxtNsPtr = (Namespace *) contextNsPtr;
................................................................................
 *	stack: that is, it can no longer be referenced by name but any
 *	currently executing procedure that refers to it is allowed to do so
 *	until the procedure returns. If the namespace can't be found, this
 *	function returns an error. If no namespaces are specified, this
 *	command does nothing.
 *
 * Results:
 *	Returns TCL_OK if successful, and  TCL_ERROR if anything goes wrong.
 *
 * Side effects:
 *	Deletes the specified namespaces. If anything goes wrong, this
 *	function returns an error message in the interpreter's result object.
 *
 *----------------------------------------------------------------------
 */
................................................................................
				 * incremented here. */

    if (objc == 4) {
	result = Tcl_EvalObjEx(interp, objv[3], 0);
    } else {
	/*
	 * More than one argument: concatenate them together with spaces
	 * between, then evaluate the result.  Tcl_EvalObjEx will delete the
	 * object when it decrements its refcount after eval'ing it.
	 */

	objPtr = Tcl_ConcatObj(objc-3, objv+3);
	result = Tcl_EvalObjEx(interp, objPtr, TCL_EVAL_DIRECT);
    }

................................................................................
 
/*
 *----------------------------------------------------------------------
 *
 * NamespaceExistsCmd --
 *
 *	Invoked to implement the "namespace exists" command that returns true
 *	if the given namespace currently exists, and false otherwise.  Handles
 *	the following syntax:
 *
 *	    namespace exists name
 *
 * Results:
 *	Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
 *
................................................................................
 *	callback scripts. Handles the following syntax:
 *
 *	    namespace inscope name arg ?arg...?
 *
 *	The "namespace inscope" command is much like the "namespace eval"
 *	command except that it has lappend semantics and the namespace must
 *	already exist. It treats the first argument as a list, and appends any
 *	arguments after the first onto the end as proper list elements.  For
 *	example,
 *
 *	    namespace inscope ::foo {a b} c d e
 *
 *	is equivalent to
 *
 *	    namespace eval ::foo [concat {a b} [list c d e]]
................................................................................
 *	the complement of the "namespace tail" command. Note that this command
 *	does not check whether the "namespace" names are, in fact, the names
 *	of currently defined namespaces. Handles the following syntax:
 *
 *	    namespace qualifiers string
 *
 * Results:
 *	Returns TCL_OK if successful, and  TCL_ERROR if anything goes wrong.
 *
 * Side effects:
 *	Returns a result in the interpreter's result object. If anything goes
 *	wrong, the result is an error message.
 *
 *----------------------------------------------------------------------
 */
................................................................................
 *	the namespace, it's structure will be freed.
 *
 *----------------------------------------------------------------------
 */

static void
FreeNsNameInternalRep(objPtr)
    register Tcl_Obj *objPtr;   /* nsName object with internal
				 * representation to free */
{
    register ResolvedNsName *resNamePtr = (ResolvedNsName *)
	    objPtr->internalRep.otherValuePtr;
    Namespace *nsPtr;

    /*
     * Decrement the reference count of the namespace. If there are no more
................................................................................
     */

    if (resNamePtr != NULL) {
	resNamePtr->refCount--;
	if (resNamePtr->refCount == 0) {

	    /*
	     * Decrement the reference count for the cached namespace.  If the
	     * namespace is dead, and there are no more references to it, free
	     * it.
	     */

	    nsPtr = resNamePtr->nsPtr;
	    nsPtr->refCount--;
	    if ((nsPtr->refCount == 0) && (nsPtr->flags & NS_DEAD)) {
................................................................................
    name = objPtr->bytes;
    if (name == NULL) {
	name = TclGetString(objPtr);
    }

    /*
     * Look for the namespace "name" in the current namespace. If there is an
     * error parsing the (possibly qualified) name, return an error.  If the
     * namespace isn't found, we convert the object to an nsName object with a
     * NULL ResolvedNsName* internal rep.
     */

    TclGetNamespaceForQualName(interp, name, (Namespace *) NULL,
	    TCL_FIND_ONLY_NS, &nsPtr, &dummy1Ptr, &dummy2Ptr, &dummy);

................................................................................
	resNamePtr->refNsPtr = currNsPtr;
	resNamePtr->refCount = 1;
    } else {
	resNamePtr = NULL;
    }

    /*
     * Free the old internalRep before setting the new one.  We do this as
     * late as possible to allow the conversion code (in particular,
     * Tcl_GetStringFromObj) to use that old internalRep.
     */

    TclFreeIntRep(objPtr);
    objPtr->internalRep.otherValuePtr = (VOID *) resNamePtr;
    objPtr->typePtr = &tclNsNameType;
    return TCL_OK;
................................................................................
}
 
/*
 *----------------------------------------------------------------------
 *
 * UpdateStringOfNsName --
 *
 *	Updates the string representation for a nsName object.  Note: This
 *	function does not free an existing old string rep so storage will be
 *	lost if this has not already been done.
 *
 * Results:
 *	None.
 *
 * Side effects:
................................................................................
 
/*
 *----------------------------------------------------------------------
 *
 * NamespaceEnsembleCmd --
 *
 *	Invoked to implement the "namespace ensemble" command that creates and
 *	manipulates ensembles built on top of namespaces.  Handles the
 *	following syntax:
 *
 *	    namespace ensemble name ?dictionary?
 *
 * Results:
 *	Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
 *
 * Side effects:
 *	Creates the ensemble for the namespace if one did not previously
 *	exist.  Alternatively, alters the way that the ensemble's subcommand
 *	=> implementation prefix is configured.
 *
 *----------------------------------------------------------------------
 */

static int
NamespaceEnsembleCmd(dummy, interp, objc, objv)
    ClientData dummy;
................................................................................
	int permitPrefix = 1;
	Tcl_Obj *unknownObj = NULL;

	objv += 3;
	objc -= 3;

	/*
	 * Work out what name to use for the command to create.  If supplied,
	 * it is either fully specified or relative to the current namespace.
	 * If not supplied, it is exactly the name of the current namespace.
	 */

	name = nsPtr->fullName;

	/*
	 * Parse the option list, applying type checks as we go.  Note that we
	 * are not incrementing any reference counts in the objects at this
	 * stage, so the presence of an option multiple times won't cause any
	 * memory leaks.
	 */

	for (; objc>1 ; objc-=2,objv+=2 ) {
	    if (Tcl_GetIndexFromObj(interp, objv[0], createOptions, "option",
................................................................................
		}
		unknownObj = (len > 0 ? objv[1] : NULL);
		continue;
	    }
	}

	/*
	 * Create the ensemble.  Note that this might delete another ensemble
	 * linked to the same namespace, so we must be careful.  However, we
	 * should be OK because we only link the namespace into the list once
	 * we've created it (and after any deletions have occurred.)
	 */

	token = Tcl_CreateEnsemble(interp, name, NULL,
		(permitPrefix ? TCL_ENSEMBLE_PREFIX : 0));
	Tcl_SetEnsembleSubcommandList(interp, token, subcmdObj);
	Tcl_SetEnsembleMappingDict(interp, token, mapObj);
	Tcl_SetEnsembleUnknownHandler(interp, token, unknownObj);

	/*
	 * Tricky! Rely on the object result not being shared!


	 */


	Tcl_GetCommandFullName(interp, token, Tcl_GetObjResult(interp));
	return TCL_OK;
    }

    case ENS_EXISTS:
	if (objc != 4) {
	    Tcl_WrongNumArgs(interp, 3, objv, "cmdname");
................................................................................
	    Tcl_GetEnsembleFlags(NULL, token, &flags);
	    permitPrefix = (flags & TCL_ENSEMBLE_PREFIX) != 0;

	    objv += 4;
	    objc -= 4;

	    /*
	     * Parse the option list, applying type checks as we go.  Note
	     * that we are not incrementing any reference counts in the
	     * objects at this stage, so the presence of an option multiple
	     * times won't cause any memory leaks.
	     */

	    for (; objc>0 ; objc-=2,objv+=2 ) {
		if (Tcl_GetIndexFromObj(interp, objv[0], configOptions,
			"option", 0, &index) != TCL_OK) {
		    if (allocatedMapFlag) {
			Tcl_DecrRefCount(mapObj);
................................................................................
    Tcl_Obj *nameObj = NULL;

    if (nsPtr == NULL) {
	nsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp);
    }

    /*
     * Make the name of the ensemble into a fully qualified name.  This might
     * allocate a temporary object.
     */

    if (!(name[0] == ':' && name[1] == ':')) {
	nameObj = Tcl_NewStringObj(nsPtr->fullName, -1);
	if (nsPtr->parentPtr == NULL) {
	    Tcl_AppendStringsToObj(nameObj, name, NULL);
................................................................................
    ensemblePtr->token = Tcl_CreateObjCommand(interp, name,
	    NsEnsembleImplementationCmd, (ClientData)ensemblePtr,
	    DeleteEnsembleConfig);
    ensemblePtr->next = (EnsembleConfig *) nsPtr->ensembles;
    nsPtr->ensembles = (Tcl_Ensemble *) ensemblePtr;

    /*
     * Trigger an eventual recomputation of the ensemble command set.  Note
     * that this is slightly tricky, as it means that we are not actually
     * counting the number of namespace export actions, but it is the simplest
     * way to go!
     */

    nsPtr->exportLookupEpoch++;

................................................................................
	Tcl_IncrRefCount(subcmdList);
    }
    if (oldList != NULL) {
	TclDecrRefCount(oldList);
    }

    /*
     * Trigger an eventual recomputation of the ensemble command set.  Note
     * that this is slightly tricky, as it means that we are not actually
     * counting the number of namespace export actions, but it is the simplest
     * way to go!
     */

    ensemblePtr->nsPtr->exportLookupEpoch++;

................................................................................
	Tcl_IncrRefCount(mapDict);
    }
    if (oldDict != NULL) {
	TclDecrRefCount(oldDict);
    }

    /*
     * Trigger an eventual recomputation of the ensemble command set.  Note
     * that this is slightly tricky, as it means that we are not actually
     * counting the number of namespace export actions, but it is the simplest
     * way to go!
     */

    ensemblePtr->nsPtr->exportLookupEpoch++;

................................................................................
	Tcl_IncrRefCount(unknownList);
    }
    if (oldList != NULL) {
	TclDecrRefCount(oldList);
    }

    /*
     * Trigger an eventual recomputation of the ensemble command set.  Note
     * that this is slightly tricky, as it means that we are not actually
     * counting the number of namespace export actions, but it is the simplest
     * way to go!
     */

    ensemblePtr->nsPtr->exportLookupEpoch++;

................................................................................
    /*
     * This API refuses to set the ENS_DEAD flag...
     */
    ensemblePtr->flags &= ENS_DEAD;
    ensemblePtr->flags |= flags & ~ENS_DEAD;

    /*
     * Trigger an eventual recomputation of the ensemble command set.  Note
     * that this is slightly tricky, as it means that we are not actually
     * counting the number of namespace export actions, but it is the simplest
     * way to go!
     */

    ensemblePtr->nsPtr->exportLookupEpoch++;

................................................................................
 * NsEnsembleImplementationCmd --
 *
 *	Implements an ensemble of commands (being those exported by a
 *	namespace other than the global namespace) as a command with the same
 *	(short) name as the namespace in the parent namespace.
 *
 * Results:
 *	A standard Tcl result code.  Will be TCL_ERROR if the command is not
 *	an unambiguous prefix of any command exported by the ensemble's
 *	namespace.
 *
 * Side effects:
 *	Depends on the command within the namespace that gets executed.  If
 *	the ensemble itself returns TCL_ERROR, a descriptive error message
 *	will be placed in the interpreter's result.
 *
 *----------------------------------------------------------------------
 */

static int
NsEnsembleImplementationCmd(clientData, interp, objc, objv)
    ClientData clientData;
................................................................................

    if (ensemblePtr->epoch != ensemblePtr->nsPtr->exportLookupEpoch) {
	ensemblePtr->epoch = ensemblePtr->nsPtr->exportLookupEpoch;
	BuildEnsembleConfig(ensemblePtr);
    } else {
	/*
	 * Table of subcommands is still valid; therefore there might be a
	 * valid cache of discovered information which we can reuse.  Do the
	 * check here, and if we're still valid, we can jump straight to the
	 * part where we do the invocation of the subcommand.
	 */

	if (objv[1]->typePtr == &ensembleCmdType) {
	    EnsembleCmdRep *ensembleCmd = (EnsembleCmdRep *)
		    objv[1]->internalRep.otherValuePtr;
................................................................................
	MakeCachedEnsembleCommand(objv[1], ensemblePtr, fullName, prefixObj);
    }

    /*
     * Do the real work of execution of the subcommand by building an array of
     * objects (note that this is potentially not the same length as the
     * number of arguments to this ensemble command), populating it and then
     * feeding it back through the main command-lookup engine.  In theory, we
     * could look up the command in the namespace ourselves, as we already
     * have the namespace in which it is guaranteed to exist, but we don't do
     * that (the cacheing of the command object used should help with that.)
     */

    Tcl_IncrRefCount(prefixObj);
  runResultingSubcommand:
................................................................................
		Tcl_SetResult(interp,
			"unknown subcommand handler deleted its ensemble",
			TCL_STATIC);
		return TCL_ERROR;
	    }

	    /*
	     * Namespace is still there.  Check if the result is a valid list.
	     * If it is, and it is non-empty, that list is what we are using
	     * as our replacement.
	     */

	    if (Tcl_ListObjLength(interp, prefixObj, &prefixObjc) != TCL_OK) {
		Tcl_DecrRefCount(prefixObj);
		Tcl_AddErrorInfo(interp,
................................................................................
	Tcl_DecrRefCount(unknownCmd);
	Tcl_Release(ensemblePtr);
	return TCL_ERROR;
    }

    /*
     * Cannot determine what subcommand to hand off to, so generate a
     * (standard) failure message.  Note the one odd case compared with
     * standard ensemble-like command, which is where a namespace has no
     * exported commands at all...
     */

    Tcl_ResetResult(interp);
    if (ensemblePtr->subcommandTable.numEntries == 0) {
	Tcl_AppendResult(interp, "unknown subcommand \"",TclGetString(objv[1]),
................................................................................
 
/*
 *----------------------------------------------------------------------
 *
 * MakeCachedEnsembleCommand --
 *
 *	Cache what we've computed so far; it's not nice to repeatedly copy
 *	strings about.  Note that to do this, we start by deleting any old
 *	representation that there was (though if it was an out of date
 *	ensemble rep, we can skip some of the deallocation process.)
 *
 * Results:
 *	None
 *
 * Side effects:
................................................................................
	Tcl_DecrRefCount(ensemblePtr->subcommandDict);
    }
    if (ensemblePtr->unknownHandler != NULL) {
	Tcl_DecrRefCount(ensemblePtr->unknownHandler);
    }

    /*
     * Arrange for the structure to be reclaimed.  Note that this is complex
     * because we have to make sure that we can react sensibly when an
     * ensemble is deleted during the process of initialising the ensemble
     * (especially the unknown callback.)
     */

    Tcl_EventuallyFree((ClientData) ensemblePtr, TCL_DYNAMIC);
}
 
/*
 *----------------------------------------------------------------------
 *
 * BuildEnsembleConfig -- 
 *
 *	Create the internal data structures that describe how an ensemble
 *	looks, being a hash mapping from the full command name to the Tcl list
 *	that describes the implementation prefix words, and a sorted array of
 *	all the full command names to allow for reasonably efficient
 *	unambiguous prefix handling.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Reallocates and rebuilds the hash table and array stored at the
 *	ensemblePtr argument.  For large ensembles or large namespaces, this
 *	is a potentially expensive operation.
 *
 *----------------------------------------------------------------------
 */

static void
BuildEnsembleConfig(ensemblePtr)
    EnsembleConfig *ensemblePtr;
................................................................................
	    hPtr = Tcl_NextHashEntry(&search);
	}
	Tcl_DeleteHashTable(hash);
	Tcl_InitHashTable(hash, TCL_STRING_KEYS);
    }

    /*
     * See if we've got an export list.  If so, we will only export exactly
     * those commands, which may be either implemented by the prefix in the
     * subcommandDict or mapped directly onto the namespace's commands.
     */

    if (ensemblePtr->subcmdList != NULL) {
	Tcl_Obj **subcmdv, *target, *cmdObj, *cmdPrefixObj;
	int subcmdc;
................................................................................
		    Tcl_SetHashValue(hPtr, (ClientData) target);
		    Tcl_IncrRefCount(target);
		    continue;
		}
	    }

	    /*
	     * Not there, so map onto the namespace.  Note in this case that
	     * we do not guarantee that the command is actually there; that is
	     * the programmer's responsibility (or [::unknown] of course).
	     */

	    cmdObj = Tcl_NewStringObj(ensemblePtr->nsPtr->fullName, -1);
	    if (ensemblePtr->nsPtr->parentPtr != NULL) {
		Tcl_AppendStringsToObj(cmdObj, "::", name, NULL);
	    } else {
................................................................................
	    cmdPrefixObj = Tcl_NewListObj(1, &cmdObj);
	    Tcl_SetHashValue(hPtr, (ClientData) cmdPrefixObj);
	    Tcl_IncrRefCount(cmdPrefixObj);
	}
    } else if (ensemblePtr->subcommandDict != NULL) {
	/*
	 * No subcmd list, but we do have a mapping dictionary so we should
	 * use the keys of that.  Convert the dictionary's contents into the
	 * form required for the ensemble's internal hashtable.
	 */

	Tcl_DictSearch dictSearch;
	Tcl_Obj *keyObj, *valueObj;
	int done;

................................................................................
	    Tcl_DictObjNext(&dictSearch, &keyObj, &valueObj, &done);
	}
    } else {
	/*
	 * Discover what commands are actually exported by the namespace.
	 * What we have is an array of patterns and a hash table whose keys
	 * are the command names exported by the namespace (the contents do
	 * not matter here.)  We must find out what commands are actually
	 * exported by filtering each command in the namespace against each of
	 * the patterns in the export list.  Note that we use an intermediate
	 * hash table to make memory management easier, and because that makes
	 * exact matching far easier too.
	 *
	 * Suggestion for future enhancement: compute the unique prefixes and
	 * place them in the hash too, which should make for even faster
	 * matching.
	 */
................................................................................
     */

    ensemblePtr->subcommandArrayPtr = (char **)
	    ckalloc(sizeof(char *) * hash->numEntries);

    /*
     * Fill array from both ends as this makes us less likely to end up with
     * performance problems in qsort(), which is good.  Note that doing this
     * makes this code much more opaque, but the naive alternatve:
     *
     * for (hPtr=Tcl_FirstHashEntry(hash,&search),i=0 ; 
     *	       hPtr!=NULL ; hPtr=Tcl_NextHashEntry(&search),i++) {
     *     ensemblePtr->subcommandArrayPtr[i] = Tcl_GetHashKey(hash, &hPtr);
     * }
     *
     * can produce long runs of precisely ordered table entries when the
     * commands in the namespace are declared in a sorted fashion (an ordering
     * some people like) and the hashing functions (or the command names
     * themselves) are fairly unfortunate.  By filling from both ends, it
     * requires active malice (and probably a debugger) to get qsort() to have
     * awful runtime behaviour.
     */

    i = 0;
    j = hash->numEntries;
    hPtr = Tcl_FirstHashEntry(hash, &search);
................................................................................
 *	Destroys the internal representation of a Tcl_Obj that has been
 *	holding information about a command in an ensemble.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Memory is deallocated.  If this held the last reference to a
 *	namespace's main structure, that main structure will also be
 *	destroyed.
 *
 *----------------------------------------------------------------------
 */

static void






|







 







|







 







|







 







|







|
|
|
|
|
|
|
|
|







 







|







 







|
|
|







 







|
|


|
|
<
|
<
|
|
<
|
|
|
|
|
|
|
|
|
<
|
|
|
<
<
|
|
|
|
<
|
<
|
|
|
<
<
|
|
|
<
|
|
<
|
|
<
|
|
|
<
|
|
|
<
|
<
|
|
<
|
<
|
|
|
|
<
<
|
|
<
|
|
<
|
|
|
<
|
<
|
|
|
|
<
|
|
|
|
|
<
|
|
|
|







 







|
|







 







|
|











|







 







|
|
|
|
|
|
|
|
|
|
|
<
|
|
|
|
|
|
|
|
|
|
|
|







 







|
|







 







|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|







 







|







 







|










|







 







|







 







|







 







|







 







|
|
|
|
|
|
|
|
<
|
|







 







|







 







|
|







 







|







 







|







 







|







 







|

|







 







|







 







|







 







|







 







|







 







|







 







|







 







|
|







 







|







 







|







 







|
|







 







|







 







|









|
|







 







|







|







 







|
|











|
>
>


>







 







|
|
|
|







 







|







 







|







 







|







 







|







 







|







 







|







 







|
|



|
|
|







 







|







 







|







 







|







 







|







 







|







 







|











|












|
|







 







|







 







|
|







 







|







 







|

|







 







|


|







|







 







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
..
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
..
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
..
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
...
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
...
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
...
172
173
174
175
176
177
178
179
180
181
182
183
184

185

186
187

188
189
190
191
192
193
194
195
196

197
198
199


200
201
202
203

204

205
206
207


208
209
210

211
212

213
214

215
216
217

218
219
220

221

222
223

224

225
226
227
228


229
230

231
232

233
234
235

236

237
238
239
240

241
242
243
244
245

246
247
248
249
250
251
252
253
254
255
256
...
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
...
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
...
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395

396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
...
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
...
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
...
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
...
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
...
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
...
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
....
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
....
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191

1192
1193
1194
1195
1196
1197
1198
1199
1200
....
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
....
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
....
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
....
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
....
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
....
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
....
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
....
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
....
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
....
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
....
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
....
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
....
4427
4428
4429
4430
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
....
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
....
4538
4539
4540
4541
4542
4543
4544
4545
4546
4547
4548
4549
4550
4551
4552
....
4566
4567
4568
4569
4570
4571
4572
4573
4574
4575
4576
4577
4578
4579
4580
4581
....
4582
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
....
4639
4640
4641
4642
4643
4644
4645
4646
4647
4648
4649
4650
4651
4652
4653
4654
4655
4656
4657
4658
4659
4660
4661
4662
4663
4664
....
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742
....
4850
4851
4852
4853
4854
4855
4856
4857
4858
4859
4860
4861
4862
4863
4864
4865
4866
4867
4868
4869
4870
4871
4872
4873
4874
4875
4876
4877
4878
4879
4880
4881
4882
....
5012
5013
5014
5015
5016
5017
5018
5019
5020
5021
5022
5023
5024
5025
5026
5027
5028
5029
....
5189
5190
5191
5192
5193
5194
5195
5196
5197
5198
5199
5200
5201
5202
5203
....
5219
5220
5221
5222
5223
5224
5225
5226
5227
5228
5229
5230
5231
5232
5233
....
5287
5288
5289
5290
5291
5292
5293
5294
5295
5296
5297
5298
5299
5300
5301
....
5352
5353
5354
5355
5356
5357
5358
5359
5360
5361
5362
5363
5364
5365
5366
....
5418
5419
5420
5421
5422
5423
5424
5425
5426
5427
5428
5429
5430
5431
5432
....
5470
5471
5472
5473
5474
5475
5476
5477
5478
5479
5480
5481
5482
5483
5484
....
5777
5778
5779
5780
5781
5782
5783
5784
5785
5786
5787
5788
5789
5790
5791
5792
5793
5794
5795
5796
5797
5798
....
5837
5838
5839
5840
5841
5842
5843
5844
5845
5846
5847
5848
5849
5850
5851
....
5944
5945
5946
5947
5948
5949
5950
5951
5952
5953
5954
5955
5956
5957
5958
....
6023
6024
6025
6026
6027
6028
6029
6030
6031
6032
6033
6034
6035
6036
6037
....
6083
6084
6085
6086
6087
6088
6089
6090
6091
6092
6093
6094
6095
6096
6097
....
6118
6119
6120
6121
6122
6123
6124
6125
6126
6127
6128
6129
6130
6131
6132
....
6257
6258
6259
6260
6261
6262
6263
6264
6265
6266
6267
6268
6269
6270
6271
6272
6273
6274
6275
6276
6277
6278
6279
6280
6281
6282
6283
6284
6285
6286
6287
6288
6289
6290
6291
6292
6293
6294
6295
6296
6297
....
6318
6319
6320
6321
6322
6323
6324
6325
6326
6327
6328
6329
6330
6331
6332
....
6354
6355
6356
6357
6358
6359
6360
6361
6362
6363
6364
6365
6366
6367
6368
6369
....
6372
6373
6374
6375
6376
6377
6378
6379
6380
6381
6382
6383
6384
6385
6386
....
6395
6396
6397
6398
6399
6400
6401
6402
6403
6404
6405
6406
6407
6408
6409
6410
6411
....
6462
6463
6464
6465
6466
6467
6468
6469
6470
6471
6472
6473
6474
6475
6476
6477
6478
6479
6480
6481
6482
6483
6484
6485
6486
6487
....
6533
6534
6535
6536
6537
6538
6539
6540
6541
6542
6543
6544
6545
6546
6547
/*
 * tclNamesp.c --
 *
 *	Contains support for namespaces, which provide a separate context of
 *	commands and global variables. The global :: namespace is the
 *	traditional Tcl "global" scope. Other namespaces are created as
 *	children of the global namespace. These other namespaces contain
 *	special-purpose commands and variables for packages. Also includes
 *	the TIP#112 ensemble machinery.
 *
 * Copyright (c) 1993-1997 Lucent Technologies.
 * Copyright (c) 1997 Sun Microsystems, Inc.
 * Copyright (c) 1998-1999 by Scriptics Corporation.
 * Copyright (c) 2002-2005 Donal K. Fellows.
 *
................................................................................
 *   Michael J. McLennan
 *   Bell Labs Innovations for Lucent Technologies
 *   [email protected]
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclNamesp.c,v 1.66.2.9 2005/08/29 18:38:45 dgp Exp $
 */

#include "tclInt.h"

/*
 * Initial size of stack allocated space for tail list - used when resetting
 * shadowed command references in the functin: TclResetShadowedCmdRefs.
................................................................................
				 * that has a pointer to this ResolvedNsName
				 * structure as its internal rep. This
				 * structure can be freed when refCount
				 * becomes zero. */
} ResolvedNsName;

/*
 * The client data for an ensemble command. This consists of the table of
 * commands that are actually exported by the namespace, and an epoch counter
 * that, combined with the exportLookupEpoch field of the namespace structure,
 * defines whether the table contains valid data or will need to be recomputed
 * next time the ensemble command is called.
 */

typedef struct EnsembleConfig {
................................................................................
    Tcl_Command token;		/* The token for the command that provides
				 * ensemble support for the namespace, or NULL
				 * if the command has been deleted (or never
				 * existed; the global namespace never has an
				 * ensemble command.) */
    int epoch;			/* The epoch at which this ensemble's table of
				 * exported commands is valid. */
    char **subcommandArrayPtr;	/* Array of ensemble subcommand names. At all
				 * consistent points, this will have the same
				 * number of entries as there are entries in
				 * the subcommandTable hash. */
    Tcl_HashTable subcommandTable;
				/* Hash table of ensemble subcommand names,
				 * which are its keys so this also provides
				 * the storage management for those subcommand
				 * names. The contents of the entry values are
				 * object version the prefix lists to use when
				 * substituting for the command/subcommand to
				 * build the ensemble implementation command.
				 * Has to be stored here as well as in
				 * subcommandDict because that field is NULL
				 * when we are deriving the ensemble from the
				 * namespace exports list. FUTURE WORK: use
				 * object hash table here. */
    struct EnsembleConfig *next;/* The next ensemble in the linked list of
				 * ensembles associated with a namespace. If
				 * this field points to this ensemble, the
				 * structure has already been unlinked from
				 * all lists, and cannot be found by scanning
				 * the list from the namespace's ensemble
				 * field. */
................................................................................
				 * prefixes, or NULL if we are to build the
				 * map automatically from the namespace
				 * exports. */
    Tcl_Obj *subcmdList;	/* List of commands that this ensemble
				 * actually provides, and whose implementation
				 * will be built using the subcommandDict (if
				 * present and defined) and by simple mapping
				 * to the namespace otherwise. If NULL,
				 * indicates that we are using the (dynamic)
				 * list of currently exported commands. */
    Tcl_Obj *unknownHandler;	/* Script prefix used to handle the case when
				 * no match is found (according to the rule
				 * defined by flag bit TCL_ENSEMBLE_PREFIX) or
				 * NULL to use the default error-generating
				 * behaviour. The script execution gets all
................................................................................
				 * itself has been updated. */
} EnsembleConfig;

#define ENS_DEAD	0x1	/* Flag value to say that the ensemble is dead
				 * and on its way out. */

/*
 * The data cached in a subcommand's Tcl_Obj rep. This structure is not shared
 * between Tcl_Objs referring to the same subcommand, even where one is a
 * duplicate of another.
 */

typedef struct EnsembleCmdRep {
    Namespace *nsPtr;		/* The namespace backing the ensemble which
				 * this is a subcommand of. */
    int epoch;			/* Used to confirm when the data in this
				 * really structure matches up with the
................................................................................
				 * subcommand. */
} EnsembleCmdRep;

/*
 * Declarations for functions local to this file:
 */

static void		DeleteImportedCmd(ClientData clientData);
static int		DoImport(Tcl_Interp *interp,
			    Namespace *nsPtr, Tcl_HashEntry *hPtr,
			    CONST char *cmdName, CONST char *pattern,
			    Namespace *importNsPtr, int allowOverwrite);
static void		DupNsNameInternalRep(Tcl_Obj *objPtr,Tcl_Obj *copyPtr);

static char *		ErrorCodeRead(ClientData clientData,Tcl_Interp *interp,

			    CONST char *name1, CONST char *name2, int flags);
static char *		ErrorInfoRead(ClientData clientData,Tcl_Interp *interp,

			    CONST char *name1, CONST char *name2, int flags);
static char *		EstablishErrorCodeTraces(ClientData clientData,
			    Tcl_Interp *interp, CONST char *name1,
			    CONST char *name2, int flags);
static char *		EstablishErrorInfoTraces(ClientData clientData,
			    Tcl_Interp *interp, CONST char *name1,
			    CONST char *name2, int flags);
static void		FreeNsNameInternalRep(Tcl_Obj *objPtr);
static int		InvokeImportedCmd(ClientData clientData,

			    Tcl_Interp *interp,int objc,Tcl_Obj *CONST objv[]);
static int		NamespaceChildrenCmd(ClientData dummy,
			    Tcl_Interp *interp,int objc,Tcl_Obj *CONST objv[]);


static int		NamespaceCodeCmd(ClientData dummy, Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]);
static int		NamespaceCurrentCmd(ClientData dummy,
			    Tcl_Interp *interp,int objc,Tcl_Obj *CONST objv[]);

static int		NamespaceDeleteCmd(ClientData dummy,Tcl_Interp *interp,

			    int objc, Tcl_Obj *CONST objv[]);
static int		NamespaceEnsembleCmd(ClientData dummy,
			    Tcl_Interp *interp,int objc,Tcl_Obj *CONST objv[]);


static int		NamespaceEvalCmd(ClientData dummy, Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]);
static int		NamespaceExistsCmd(ClientData dummy,Tcl_Interp *interp,

			    int objc, Tcl_Obj *CONST objv[]);
static int		NamespaceExportCmd(ClientData dummy,Tcl_Interp *interp,

			    int objc, Tcl_Obj *CONST objv[]);
static int		NamespaceForgetCmd(ClientData dummy,Tcl_Interp *interp,

			    int objc, Tcl_Obj *CONST objv[]);
static void		NamespaceFree(Namespace *nsPtr);
static int		NamespaceImportCmd(ClientData dummy,Tcl_Interp *interp,

			    int objc, Tcl_Obj *CONST objv[]);
static int		NamespaceInscopeCmd(ClientData dummy,
			    Tcl_Interp *interp,int objc,Tcl_Obj *CONST objv[]);

static int		NamespaceOriginCmd(ClientData dummy,Tcl_Interp *interp,

			    int objc, Tcl_Obj *CONST objv[]);
static int		NamespaceParentCmd(ClientData dummy,Tcl_Interp *interp,

			    int objc, Tcl_Obj *CONST objv[]);

static int		NamespacePathCmd(ClientData dummy, Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]);
static int		NamespaceQualifiersCmd(ClientData dummy,
			    Tcl_Interp *interp,int objc,Tcl_Obj *CONST objv[]);


static int		NamespaceTailCmd(ClientData dummy, Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]);

static int		NamespaceWhichCmd(ClientData dummy, Tcl_Interp *interp,
			    int objc, Tcl_Obj *CONST objv[]);

static int		SetNsNameFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);
static void		UpdateStringOfNsName(Tcl_Obj *objPtr);
static int		NsEnsembleImplementationCmd(ClientData clientData,

			    Tcl_Interp *interp,int objc,Tcl_Obj *CONST objv[]);

static void		BuildEnsembleConfig(EnsembleConfig *ensemblePtr);
static int		NsEnsembleStringOrder(CONST VOID *strPtr1,
			    CONST VOID *strPtr2);
static void		DeleteEnsembleConfig(ClientData clientData);

static void		MakeCachedEnsembleCommand(Tcl_Obj *objPtr,
			    EnsembleConfig *ensemblePtr,
			    CONST char *subcmdName, Tcl_Obj *prefixObjPtr);
static void		FreeEnsembleCmdRep(Tcl_Obj *objPtr);
static void		DupEnsembleCmdRep(Tcl_Obj *objPtr, Tcl_Obj *copyPtr);

static void		StringOfEnsembleCmdRep(Tcl_Obj *objPtr);
static void		UnlinkNsPath(Namespace *nsPtr);
static void		SetNsPath(Namespace *nsPtr, int pathLength,
			    Tcl_Namespace *pathAry[]);

/*
 * This structure defines a Tcl object type that contains a namespace
 * reference. It is used in commands that take the name of a namespace as an
 * argument. The namespace reference is resolved, and the result in cached in
 * the object.
 */
................................................................................
 *	None.
 *
 *----------------------------------------------------------------------
 */

Tcl_Namespace *
Tcl_GetCurrentNamespace(interp)
    register Tcl_Interp *interp;/* Interpreter whose current namespace is
				 * being queried. */
{
    register Interp *iPtr = (Interp *) interp;
    register Namespace *nsPtr;

    if (iPtr->varFramePtr != NULL) {
	nsPtr = iPtr->varFramePtr->nsPtr;
    } else {
................................................................................
 *	None.
 *
 *----------------------------------------------------------------------
 */

Tcl_Namespace *
Tcl_GetGlobalNamespace(interp)
    register Tcl_Interp *interp;/* Interpreter whose global namespace should
				 * be returned. */
{
    register Interp *iPtr = (Interp *) interp;

    return (Tcl_Namespace *) iPtr->globalNsPtr;
}
 
/*
 *----------------------------------------------------------------------
 *
 * Tcl_PushCallFrame --
 *
 *	Pushes a new call frame onto the interpreter's Tcl call stack. Called
 *	when executing a Tcl procedure or a "namespace eval" or "namespace
 *	inscope" command.
 *
 * Results:
 *	Returns TCL_OK if successful, or TCL_ERROR (along with an error
 *	message in the interpreter's result object) if something goes wrong.
 *
................................................................................
 *	Modifies the interpreter's Tcl call stack.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_PushCallFrame(interp, callFramePtr, namespacePtr, isProcCallFrame)
    Tcl_Interp *interp;		/* Interpreter in which the new call frame is
				 * to be pushed. */
    Tcl_CallFrame *callFramePtr;/* Points to a call frame structure to push.
				 * Storage for this has already been allocated
				 * by the caller; typically this is the
				 * address of a CallFrame structure allocated
				 * on the caller's C stack. The call frame
				 * will be initialized by this function. The
				 * caller can pop the frame later with
				 * Tcl_PopCallFrame, and it is responsible for
				 * freeing the frame's storage. */

    Tcl_Namespace *namespacePtr;/* Points to the namespace in which the frame
				 * will execute. If NULL, the interpreter's
				 * current namespace will be used. */
    int isProcCallFrame;	/* If nonzero, the frame represents a called
				 * Tcl procedure and may have local vars. Vars
				 * will ordinarily be looked up in the frame.
				 * If new variables are created, they will be
				 * created in the frame. If 0, the frame is
				 * for a "namespace eval" or "namespace
				 * inscope" command and var references are
				 * treated as references to namespace
				 * variables. */
{
    Interp *iPtr = (Interp *) interp;
    register CallFrame *framePtr = (CallFrame *) callFramePtr;
    register Namespace *nsPtr;

    if (namespacePtr == NULL) {
	nsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp);
................................................................................
    framePtr->callerPtr = iPtr->framePtr;
    framePtr->callerVarPtr = iPtr->varFramePtr;
    if (iPtr->varFramePtr != NULL) {
	framePtr->level = (iPtr->varFramePtr->level + 1);
    } else {
	framePtr->level = 1;
    }
    framePtr->procPtr = NULL;		/* no called procedure */
    framePtr->varTablePtr = NULL;	/* and no local variables */
    framePtr->numCompiledLocals = 0;
    framePtr->compiledLocals = NULL;

    /*
     * Push the new call frame onto the interpreter's stack of procedure call
     * frames making it the current frame.
     */
................................................................................
 *	Modifies the interpreter's Tcl call stack.
 *
 *----------------------------------------------------------------------
 */

int
TclPushStackFrame(interp, framePtrPtr, namespacePtr, isProcCallFrame)
    Tcl_Interp *interp;		/* Interpreter in which the new call frame is
				 * to be pushed. */
    Tcl_CallFrame **framePtrPtr;/* Place to store a pointer to the stack
				 * allocated call frame.*/
    Tcl_Namespace *namespacePtr;/* Points to the namespace in which the frame
				 * will execute. If NULL, the interpreter's
				 * current namespace will be used. */
    int isProcCallFrame;	/* If nonzero, the frame represents a called
				 * Tcl procedure and may have local vars. Vars
				 * will ordinarily be looked up in the frame.
				 * If new variables are created, they will be
				 * created in the frame. If 0, the frame is
				 * for a "namespace eval" or "namespace
				 * inscope" command and var references are
				 * treated as references to namespace
				 * variables. */
{
    *framePtrPtr = (Tcl_CallFrame *) TclStackAlloc(interp, sizeof(CallFrame));
    return Tcl_PushCallFrame(interp, *framePtrPtr, namespacePtr,
	    isProcCallFrame);
}

void
................................................................................
				 * reporting. */
    CONST char *name;		/* Name for the new namespace. May be a
				 * qualified name with names of ancestor
				 * namespaces separated by "::"s. */
    ClientData clientData;	/* One-word value to store with namespace. */
    Tcl_NamespaceDeleteProc *deleteProc;
				/* Function called to delete client data when
				 * the namespace is deleted. NULL if no
				 * function should be called. */
{
    Interp *iPtr = (Interp *) interp;
    register Namespace *nsPtr, *ancestorPtr;
    Namespace *parentPtr, *dummy1Ptr, *dummy2Ptr;
    Namespace *globalNsPtr = iPtr->globalNsPtr;
    CONST char *simpleName;
................................................................................
 *	namespaces are deleted.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_DeleteNamespace(namespacePtr)
    Tcl_Namespace *namespacePtr;	/* Points to the namespace to delete */
{
    register Namespace *nsPtr = (Namespace *) namespacePtr;
    Interp *iPtr = (Interp *) nsPtr->interp;
    Namespace *globalNsPtr =
	    (Namespace *) Tcl_GetGlobalNamespace((Tcl_Interp *) iPtr);
    Tcl_HashEntry *entryPtr;

    /*
     * If the namespace has associated ensemble commands, delete them first.
     * This leaves the actual contents of the namespace alone (unless they are
     * linked ensemble commands, of course). Note that this code is actually
     * reentrant so command delete traces won't purturb things badly.
     */

    while (nsPtr->ensembles != NULL) {
	EnsembleConfig *ensemblePtr = (EnsembleConfig *) nsPtr->ensembles;

	/*
................................................................................

    /*
     * If the namespace is on the call frame stack, it is marked as "dying"
     * (NS_DYING is OR'd into its flags): the namespace can't be looked up by
     * name but its commands and variables are still usable by those active
     * call frames. When all active call frames referring to the namespace
     * have been popped from the Tcl stack, Tcl_PopCallFrame will call this
     * function again to delete everything in the namespace. If no nsName
     * objects refer to the namespace (i.e., if its refCount is zero), its
     * commands and variables are deleted and the storage for its namespace
     * structure is freed. Otherwise, if its refCount is nonzero, the
     * namespace's commands and variables are deleted but the structure isn't
     * freed. Instead, NS_DEAD is OR'd into the structure's flags to allow the
     * namespace resolution code to recognize that the namespace is "deleted".
     * The structure's storage is freed by FreeNsNameInternalRep when its
................................................................................

	TclTeardownNamespace(nsPtr);

	if ((nsPtr != globalNsPtr) || (iPtr->flags & DELETED)) {
	    /*
	     * If this is the global namespace, then it may have residual
	     * "errorInfo" and "errorCode" variables for errors that occurred
	     * while it was being torn down. Try to clear the variable list
	     * one last time.
	     */

	    TclDeleteVars((Interp *) nsPtr->interp, &nsPtr->varTable);

	    Tcl_DeleteHashTable(&nsPtr->childTable);
	    Tcl_DeleteHashTable(&nsPtr->cmdTable);
................................................................................
 
/*
 *----------------------------------------------------------------------
 *
 * NamespaceFree --
 *
 *	Called after a namespace has been deleted, when its reference count
 *	reaches 0. Frees the data structure representing the namespace.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *
................................................................................
 *	Optionally reset the namespace's export pattern list.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_Export(interp, namespacePtr, pattern, resetListFirst)
    Tcl_Interp *interp;		/* Current interpreter. */
    Tcl_Namespace *namespacePtr;/* Points to the namespace from which commands
				 * are to be exported. NULL for the current
				 * namespace. */
    CONST char *pattern;	/* String pattern indicating which commands to
				 * export. This pattern may not include any
				 * namespace qualifiers; only commands in the
				 * specified namespace may be exported. */

    int resetListFirst;		/* If nonzero, resets the namespace's export
				 * list before appending. */
{
#define INIT_EXPORT_PATTERNS 5
    Namespace *nsPtr, *exportNsPtr, *dummyPtr;
    Namespace *currNsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp);
    CONST char *simplePattern;
    char *patternCpy;
    int neededElems, len, i;
................................................................................
	nsPtr->exportArrayPtr = (char **)
		ckalloc((unsigned) (INIT_EXPORT_PATTERNS * sizeof(char *)));
	nsPtr->numExportPatterns = 0;
	nsPtr->maxExportPatterns = INIT_EXPORT_PATTERNS;
    } else if (neededElems > nsPtr->maxExportPatterns) {
	int numNewElems = 2 * nsPtr->maxExportPatterns;
	size_t currBytes = nsPtr->numExportPatterns * sizeof(char *);
	size_t newBytes = numNewElems * sizeof(char *);
	char **newPtr = (char **) ckalloc((unsigned) newBytes);

	memcpy((VOID *) newPtr, (VOID *) nsPtr->exportArrayPtr, currBytes);
	ckfree((char *) nsPtr->exportArrayPtr);
	nsPtr->exportArrayPtr = (char **) newPtr;
	nsPtr->maxExportPatterns = numNewElems;
    }
................................................................................
    strcpy(patternCpy, pattern);

    nsPtr->exportArrayPtr[nsPtr->numExportPatterns] = patternCpy;
    nsPtr->numExportPatterns++;

    /*
     * The list of commands actually exported from the namespace might have
     * changed (probably will have!) However, we do not need to recompute this
     * just yet; next time we need the info will be soon enough.
     */

    TclInvalidateNsCmdLookup(nsPtr);

    return TCL_OK;
#undef INIT_EXPORT_PATTERNS
}
................................................................................
     * Unless there is a name clash, create an imported command in the current
     * namespace that refers to cmdPtr.
     */

    found = Tcl_FindHashEntry(&nsPtr->cmdTable, cmdName);
    if ((found == NULL) || allowOverwrite) {
	/*
	 * Create the imported command and its client data. To create the new
	 * command in the current namespace, generate a fully qualified name
	 * for it.
	 */

	Tcl_DString ds;
	Tcl_Command importedCmd;
	ImportedCmdData *dataPtr;
................................................................................
 *	names, and a pointer to the simple name of the final component is
 *	stored in *simpleNamePtr.
 *
 * Results:
 *	It sets *nsPtrPtr and *altNsPtrPtr to point to the two possible
 *	namespaces which represent the last (containing) namespace in the
 *	qualified name. If the function sets either *nsPtrPtr or *altNsPtrPtr
 *	to NULL, then the search along that path failed. The function also
 *	stores a pointer to the simple name of the final component in
 *	*simpleNamePtr. If the qualified name is "::" or was treated as a
 *	namespace reference (TCL_FIND_ONLY_NS), the function stores a pointer
 *	to the namespace in *nsPtrPtr, NULL in *altNsPtrPtr, and sets
 *	*simpleNamePtr to point to an empty string.
 *
 *	If there is an error, this function returns TCL_ERROR. If "flags"
................................................................................
     */

    Tcl_DStringInit(&buffer);
    end = start;
    while (*start != '\0') {
	/*
	 * Find the next namespace qualifier (i.e., a name ending in "::") or
	 * the end of the qualified name (i.e., a name ending in "\0"). Set
	 * len to the number of characters, starting from start, in the name;
	 * set end to point after the "::"s or at the "\0".
	 */

	len = 0;
	for (end = start;  *end != '\0';  end++) {
	    if ((*end == ':') && (*(end+1) == ':')) {
................................................................................

    /*
     * We ignore trailing "::"s in a namespace name, but in a command or
     * variable name, trailing "::"s refer to the cmd or var named {}.
     */

    if ((flags & TCL_FIND_ONLY_NS) || (end>start && *(end-1)!=':')) {
	*simpleNamePtr = NULL;	/* found namespace name */
    } else {
	*simpleNamePtr = end;	/* found cmd/var: points to empty string */
    }

    /*
     * As a special case, if we are looking for a namespace and qualName is ""
     * and the current active namespace (nsPtr) is not the global namespace,
     * return NULL (no namespace was found). This is because namespaces can
     * not have empty names except for the global namespace.
................................................................................
    Var *varPtr;
    register int search;
    int result;
    Tcl_Var var;

    /*
     * If this namespace has a variable resolver, then give it first crack at
     * the variable resolution. It may return a Tcl_Var value, it may signal
     * to continue onward, or it may signal an error.
     */

    if ((flags & TCL_GLOBAL_ONLY) != 0) {
	cxtNsPtr = (Namespace *) Tcl_GetGlobalNamespace(interp);
    } else if (contextNsPtr != NULL) {
	cxtNsPtr = (Namespace *) contextNsPtr;
................................................................................
 *	stack: that is, it can no longer be referenced by name but any
 *	currently executing procedure that refers to it is allowed to do so
 *	until the procedure returns. If the namespace can't be found, this
 *	function returns an error. If no namespaces are specified, this
 *	command does nothing.
 *
 * Results:
 *	Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
 *
 * Side effects:
 *	Deletes the specified namespaces. If anything goes wrong, this
 *	function returns an error message in the interpreter's result object.
 *
 *----------------------------------------------------------------------
 */
................................................................................
				 * incremented here. */

    if (objc == 4) {
	result = Tcl_EvalObjEx(interp, objv[3], 0);
    } else {
	/*
	 * More than one argument: concatenate them together with spaces
	 * between, then evaluate the result. Tcl_EvalObjEx will delete the
	 * object when it decrements its refcount after eval'ing it.
	 */

	objPtr = Tcl_ConcatObj(objc-3, objv+3);
	result = Tcl_EvalObjEx(interp, objPtr, TCL_EVAL_DIRECT);
    }

................................................................................
 
/*
 *----------------------------------------------------------------------
 *
 * NamespaceExistsCmd --
 *
 *	Invoked to implement the "namespace exists" command that returns true
 *	if the given namespace currently exists, and false otherwise. Handles
 *	the following syntax:
 *
 *	    namespace exists name
 *
 * Results:
 *	Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
 *
................................................................................
 *	callback scripts. Handles the following syntax:
 *
 *	    namespace inscope name arg ?arg...?
 *
 *	The "namespace inscope" command is much like the "namespace eval"
 *	command except that it has lappend semantics and the namespace must
 *	already exist. It treats the first argument as a list, and appends any
 *	arguments after the first onto the end as proper list elements. For
 *	example,
 *
 *	    namespace inscope ::foo {a b} c d e
 *
 *	is equivalent to
 *
 *	    namespace eval ::foo [concat {a b} [list c d e]]
................................................................................
 *	the complement of the "namespace tail" command. Note that this command
 *	does not check whether the "namespace" names are, in fact, the names
 *	of currently defined namespaces. Handles the following syntax:
 *
 *	    namespace qualifiers string
 *
 * Results:
 *	Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
 *
 * Side effects:
 *	Returns a result in the interpreter's result object. If anything goes
 *	wrong, the result is an error message.
 *
 *----------------------------------------------------------------------
 */
................................................................................
 *	the namespace, it's structure will be freed.
 *
 *----------------------------------------------------------------------
 */

static void
FreeNsNameInternalRep(objPtr)
    register Tcl_Obj *objPtr;	/* nsName object with internal representation
				 * to free */
{
    register ResolvedNsName *resNamePtr = (ResolvedNsName *)
	    objPtr->internalRep.otherValuePtr;
    Namespace *nsPtr;

    /*
     * Decrement the reference count of the namespace. If there are no more
................................................................................
     */

    if (resNamePtr != NULL) {
	resNamePtr->refCount--;
	if (resNamePtr->refCount == 0) {

	    /*
	     * Decrement the reference count for the cached namespace. If the
	     * namespace is dead, and there are no more references to it, free
	     * it.
	     */

	    nsPtr = resNamePtr->nsPtr;
	    nsPtr->refCount--;
	    if ((nsPtr->refCount == 0) && (nsPtr->flags & NS_DEAD)) {
................................................................................
    name = objPtr->bytes;
    if (name == NULL) {
	name = TclGetString(objPtr);
    }

    /*
     * Look for the namespace "name" in the current namespace. If there is an
     * error parsing the (possibly qualified) name, return an error. If the
     * namespace isn't found, we convert the object to an nsName object with a
     * NULL ResolvedNsName* internal rep.
     */

    TclGetNamespaceForQualName(interp, name, (Namespace *) NULL,
	    TCL_FIND_ONLY_NS, &nsPtr, &dummy1Ptr, &dummy2Ptr, &dummy);

................................................................................
	resNamePtr->refNsPtr = currNsPtr;
	resNamePtr->refCount = 1;
    } else {
	resNamePtr = NULL;
    }

    /*
     * Free the old internalRep before setting the new one. We do this as late
     * as possible to allow the conversion code (in particular,
     * Tcl_GetStringFromObj) to use that old internalRep.
     */

    TclFreeIntRep(objPtr);
    objPtr->internalRep.otherValuePtr = (VOID *) resNamePtr;
    objPtr->typePtr = &tclNsNameType;
    return TCL_OK;
................................................................................
}
 
/*
 *----------------------------------------------------------------------
 *
 * UpdateStringOfNsName --
 *
 *	Updates the string representation for a nsName object. Note: This
 *	function does not free an existing old string rep so storage will be
 *	lost if this has not already been done.
 *
 * Results:
 *	None.
 *
 * Side effects:
................................................................................
 
/*
 *----------------------------------------------------------------------
 *
 * NamespaceEnsembleCmd --
 *
 *	Invoked to implement the "namespace ensemble" command that creates and
 *	manipulates ensembles built on top of namespaces. Handles the
 *	following syntax:
 *
 *	    namespace ensemble name ?dictionary?
 *
 * Results:
 *	Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong.
 *
 * Side effects:
 *	Creates the ensemble for the namespace if one did not previously
 *	exist. Alternatively, alters the way that the ensemble's subcommand =>
 *	implementation prefix is configured.
 *
 *----------------------------------------------------------------------
 */

static int
NamespaceEnsembleCmd(dummy, interp, objc, objv)
    ClientData dummy;
................................................................................
	int permitPrefix = 1;
	Tcl_Obj *unknownObj = NULL;

	objv += 3;
	objc -= 3;

	/*
	 * Work out what name to use for the command to create. If supplied,
	 * it is either fully specified or relative to the current namespace.
	 * If not supplied, it is exactly the name of the current namespace.
	 */

	name = nsPtr->fullName;

	/*
	 * Parse the option list, applying type checks as we go. Note that we
	 * are not incrementing any reference counts in the objects at this
	 * stage, so the presence of an option multiple times won't cause any
	 * memory leaks.
	 */

	for (; objc>1 ; objc-=2,objv+=2 ) {
	    if (Tcl_GetIndexFromObj(interp, objv[0], createOptions, "option",
................................................................................
		}
		unknownObj = (len > 0 ? objv[1] : NULL);
		continue;
	    }
	}

	/*
	 * Create the ensemble. Note that this might delete another ensemble
	 * linked to the same namespace, so we must be careful. However, we
	 * should be OK because we only link the namespace into the list once
	 * we've created it (and after any deletions have occurred.)
	 */

	token = Tcl_CreateEnsemble(interp, name, NULL,
		(permitPrefix ? TCL_ENSEMBLE_PREFIX : 0));
	Tcl_SetEnsembleSubcommandList(interp, token, subcmdObj);
	Tcl_SetEnsembleMappingDict(interp, token, mapObj);
	Tcl_SetEnsembleUnknownHandler(interp, token, unknownObj);

	/*
	 * Tricky! Must ensure that the result is not shared (command delete
	 * traces could have corrupted the pristine object that we started
	 * with). [Snit test rename-1.5]
	 */

	Tcl_ResetResult(interp);
	Tcl_GetCommandFullName(interp, token, Tcl_GetObjResult(interp));
	return TCL_OK;
    }

    case ENS_EXISTS:
	if (objc != 4) {
	    Tcl_WrongNumArgs(interp, 3, objv, "cmdname");
................................................................................
	    Tcl_GetEnsembleFlags(NULL, token, &flags);
	    permitPrefix = (flags & TCL_ENSEMBLE_PREFIX) != 0;

	    objv += 4;
	    objc -= 4;

	    /*
	     * Parse the option list, applying type checks as we go. Note that
	     * we are not incrementing any reference counts in the objects at
	     * this stage, so the presence of an option multiple times won't
	     * cause any memory leaks.
	     */

	    for (; objc>0 ; objc-=2,objv+=2 ) {
		if (Tcl_GetIndexFromObj(interp, objv[0], configOptions,
			"option", 0, &index) != TCL_OK) {
		    if (allocatedMapFlag) {
			Tcl_DecrRefCount(mapObj);
................................................................................
    Tcl_Obj *nameObj = NULL;

    if (nsPtr == NULL) {
	nsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp);
    }

    /*
     * Make the name of the ensemble into a fully qualified name. This might
     * allocate a temporary object.
     */

    if (!(name[0] == ':' && name[1] == ':')) {
	nameObj = Tcl_NewStringObj(nsPtr->fullName, -1);
	if (nsPtr->parentPtr == NULL) {
	    Tcl_AppendStringsToObj(nameObj, name, NULL);
................................................................................
    ensemblePtr->token = Tcl_CreateObjCommand(interp, name,
	    NsEnsembleImplementationCmd, (ClientData)ensemblePtr,
	    DeleteEnsembleConfig);
    ensemblePtr->next = (EnsembleConfig *) nsPtr->ensembles;
    nsPtr->ensembles = (Tcl_Ensemble *) ensemblePtr;

    /*
     * Trigger an eventual recomputation of the ensemble command set. Note
     * that this is slightly tricky, as it means that we are not actually
     * counting the number of namespace export actions, but it is the simplest
     * way to go!
     */

    nsPtr->exportLookupEpoch++;

................................................................................
	Tcl_IncrRefCount(subcmdList);
    }
    if (oldList != NULL) {
	TclDecrRefCount(oldList);
    }

    /*
     * Trigger an eventual recomputation of the ensemble command set. Note
     * that this is slightly tricky, as it means that we are not actually
     * counting the number of namespace export actions, but it is the simplest
     * way to go!
     */

    ensemblePtr->nsPtr->exportLookupEpoch++;

................................................................................
	Tcl_IncrRefCount(mapDict);
    }
    if (oldDict != NULL) {
	TclDecrRefCount(oldDict);
    }

    /*
     * Trigger an eventual recomputation of the ensemble command set. Note
     * that this is slightly tricky, as it means that we are not actually
     * counting the number of namespace export actions, but it is the simplest
     * way to go!
     */

    ensemblePtr->nsPtr->exportLookupEpoch++;

................................................................................
	Tcl_IncrRefCount(unknownList);
    }
    if (oldList != NULL) {
	TclDecrRefCount(oldList);
    }

    /*
     * Trigger an eventual recomputation of the ensemble command set. Note
     * that this is slightly tricky, as it means that we are not actually
     * counting the number of namespace export actions, but it is the simplest
     * way to go!
     */

    ensemblePtr->nsPtr->exportLookupEpoch++;

................................................................................
    /*
     * This API refuses to set the ENS_DEAD flag...
     */
    ensemblePtr->flags &= ENS_DEAD;
    ensemblePtr->flags |= flags & ~ENS_DEAD;

    /*
     * Trigger an eventual recomputation of the ensemble command set. Note
     * that this is slightly tricky, as it means that we are not actually
     * counting the number of namespace export actions, but it is the simplest
     * way to go!
     */

    ensemblePtr->nsPtr->exportLookupEpoch++;

................................................................................
 * NsEnsembleImplementationCmd --
 *
 *	Implements an ensemble of commands (being those exported by a
 *	namespace other than the global namespace) as a command with the same
 *	(short) name as the namespace in the parent namespace.
 *
 * Results:
 *	A standard Tcl result code. Will be TCL_ERROR if the command is not an
 *	unambiguous prefix of any command exported by the ensemble's
 *	namespace.
 *
 * Side effects:
 *	Depends on the command within the namespace that gets executed. If the
 *	ensemble itself returns TCL_ERROR, a descriptive error message will be
 *	placed in the interpreter's result.
 *
 *----------------------------------------------------------------------
 */

static int
NsEnsembleImplementationCmd(clientData, interp, objc, objv)
    ClientData clientData;
................................................................................

    if (ensemblePtr->epoch != ensemblePtr->nsPtr->exportLookupEpoch) {
	ensemblePtr->epoch = ensemblePtr->nsPtr->exportLookupEpoch;
	BuildEnsembleConfig(ensemblePtr);
    } else {
	/*
	 * Table of subcommands is still valid; therefore there might be a
	 * valid cache of discovered information which we can reuse. Do the
	 * check here, and if we're still valid, we can jump straight to the
	 * part where we do the invocation of the subcommand.
	 */

	if (objv[1]->typePtr == &ensembleCmdType) {
	    EnsembleCmdRep *ensembleCmd = (EnsembleCmdRep *)
		    objv[1]->internalRep.otherValuePtr;
................................................................................
	MakeCachedEnsembleCommand(objv[1], ensemblePtr, fullName, prefixObj);
    }

    /*
     * Do the real work of execution of the subcommand by building an array of
     * objects (note that this is potentially not the same length as the
     * number of arguments to this ensemble command), populating it and then
     * feeding it back through the main command-lookup engine. In theory, we
     * could look up the command in the namespace ourselves, as we already
     * have the namespace in which it is guaranteed to exist, but we don't do
     * that (the cacheing of the command object used should help with that.)
     */

    Tcl_IncrRefCount(prefixObj);
  runResultingSubcommand:
................................................................................
		Tcl_SetResult(interp,
			"unknown subcommand handler deleted its ensemble",
			TCL_STATIC);
		return TCL_ERROR;
	    }

	    /*
	     * Namespace is still there. Check if the result is a valid list.
	     * If it is, and it is non-empty, that list is what we are using
	     * as our replacement.
	     */

	    if (Tcl_ListObjLength(interp, prefixObj, &prefixObjc) != TCL_OK) {
		Tcl_DecrRefCount(prefixObj);
		Tcl_AddErrorInfo(interp,
................................................................................
	Tcl_DecrRefCount(unknownCmd);
	Tcl_Release(ensemblePtr);
	return TCL_ERROR;
    }

    /*
     * Cannot determine what subcommand to hand off to, so generate a
     * (standard) failure message. Note the one odd case compared with
     * standard ensemble-like command, which is where a namespace has no
     * exported commands at all...
     */

    Tcl_ResetResult(interp);
    if (ensemblePtr->subcommandTable.numEntries == 0) {
	Tcl_AppendResult(interp, "unknown subcommand \"",TclGetString(objv[1]),
................................................................................
 
/*
 *----------------------------------------------------------------------
 *
 * MakeCachedEnsembleCommand --
 *
 *	Cache what we've computed so far; it's not nice to repeatedly copy
 *	strings about. Note that to do this, we start by deleting any old
 *	representation that there was (though if it was an out of date
 *	ensemble rep, we can skip some of the deallocation process.)
 *
 * Results:
 *	None
 *
 * Side effects:
................................................................................
	Tcl_DecrRefCount(ensemblePtr->subcommandDict);
    }
    if (ensemblePtr->unknownHandler != NULL) {
	Tcl_DecrRefCount(ensemblePtr->unknownHandler);
    }

    /*
     * Arrange for the structure to be reclaimed. Note that this is complex
     * because we have to make sure that we can react sensibly when an
     * ensemble is deleted during the process of initialising the ensemble
     * (especially the unknown callback.)
     */

    Tcl_EventuallyFree((ClientData) ensemblePtr, TCL_DYNAMIC);
}
 
/*
 *----------------------------------------------------------------------
 *
 * BuildEnsembleConfig --
 *
 *	Create the internal data structures that describe how an ensemble
 *	looks, being a hash mapping from the full command name to the Tcl list
 *	that describes the implementation prefix words, and a sorted array of
 *	all the full command names to allow for reasonably efficient
 *	unambiguous prefix handling.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Reallocates and rebuilds the hash table and array stored at the
 *	ensemblePtr argument. For large ensembles or large namespaces, this is
 *	a potentially expensive operation.
 *
 *----------------------------------------------------------------------
 */

static void
BuildEnsembleConfig(ensemblePtr)
    EnsembleConfig *ensemblePtr;
................................................................................
	    hPtr = Tcl_NextHashEntry(&search);
	}
	Tcl_DeleteHashTable(hash);
	Tcl_InitHashTable(hash, TCL_STRING_KEYS);
    }

    /*
     * See if we've got an export list. If so, we will only export exactly
     * those commands, which may be either implemented by the prefix in the
     * subcommandDict or mapped directly onto the namespace's commands.
     */

    if (ensemblePtr->subcmdList != NULL) {
	Tcl_Obj **subcmdv, *target, *cmdObj, *cmdPrefixObj;
	int subcmdc;
................................................................................
		    Tcl_SetHashValue(hPtr, (ClientData) target);
		    Tcl_IncrRefCount(target);
		    continue;
		}
	    }

	    /*
	     * Not there, so map onto the namespace. Note in this case that we
	     * do not guarantee that the command is actually there; that is
	     * the programmer's responsibility (or [::unknown] of course).
	     */

	    cmdObj = Tcl_NewStringObj(ensemblePtr->nsPtr->fullName, -1);
	    if (ensemblePtr->nsPtr->parentPtr != NULL) {
		Tcl_AppendStringsToObj(cmdObj, "::", name, NULL);
	    } else {
................................................................................
	    cmdPrefixObj = Tcl_NewListObj(1, &cmdObj);
	    Tcl_SetHashValue(hPtr, (ClientData) cmdPrefixObj);
	    Tcl_IncrRefCount(cmdPrefixObj);
	}
    } else if (ensemblePtr->subcommandDict != NULL) {
	/*
	 * No subcmd list, but we do have a mapping dictionary so we should
	 * use the keys of that. Convert the dictionary's contents into the
	 * form required for the ensemble's internal hashtable.
	 */

	Tcl_DictSearch dictSearch;
	Tcl_Obj *keyObj, *valueObj;
	int done;

................................................................................
	    Tcl_DictObjNext(&dictSearch, &keyObj, &valueObj, &done);
	}
    } else {
	/*
	 * Discover what commands are actually exported by the namespace.
	 * What we have is an array of patterns and a hash table whose keys
	 * are the command names exported by the namespace (the contents do
	 * not matter here.) We must find out what commands are actually
	 * exported by filtering each command in the namespace against each of
	 * the patterns in the export list. Note that we use an intermediate
	 * hash table to make memory management easier, and because that makes
	 * exact matching far easier too.
	 *
	 * Suggestion for future enhancement: compute the unique prefixes and
	 * place them in the hash too, which should make for even faster
	 * matching.
	 */
................................................................................
     */

    ensemblePtr->subcommandArrayPtr = (char **)
	    ckalloc(sizeof(char *) * hash->numEntries);

    /*
     * Fill array from both ends as this makes us less likely to end up with
     * performance problems in qsort(), which is good. Note that doing this
     * makes this code much more opaque, but the naive alternatve:
     *
     * for (hPtr=Tcl_FirstHashEntry(hash,&search),i=0 ;
     *	       hPtr!=NULL ; hPtr=Tcl_NextHashEntry(&search),i++) {
     *     ensemblePtr->subcommandArrayPtr[i] = Tcl_GetHashKey(hash, &hPtr);
     * }
     *
     * can produce long runs of precisely ordered table entries when the
     * commands in the namespace are declared in a sorted fashion (an ordering
     * some people like) and the hashing functions (or the command names
     * themselves) are fairly unfortunate. By filling from both ends, it
     * requires active malice (and probably a debugger) to get qsort() to have
     * awful runtime behaviour.
     */

    i = 0;
    j = hash->numEntries;
    hPtr = Tcl_FirstHashEntry(hash, &search);
................................................................................
 *	Destroys the internal representation of a Tcl_Obj that has been
 *	holding information about a command in an ensemble.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Memory is deallocated. If this held the last reference to a
 *	namespace's main structure, that main structure will also be
 *	destroyed.
 *
 *----------------------------------------------------------------------
 */

static void

Changes to generic/tclThreadTest.c.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
132
133
134
135
136
137
138






139
140
141
142
143
144
145
 *	Conservation Through Innovation, Limited, with their permission.
 *
 * Copyright (c) 1998 by Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclThreadTest.c,v 1.17.2.2 2005/08/25 15:46:31 dgp Exp $
 */

#include "tclInt.h"

#ifdef TCL_THREADS
/*
 * Each thread has an single instance of the following structure.  There
................................................................................
static int	ThreadEventProc _ANSI_ARGS_((Tcl_Event *evPtr, int mask));
static void	ThreadErrorProc _ANSI_ARGS_((Tcl_Interp *interp));
static void	ThreadFreeProc _ANSI_ARGS_((ClientData clientData));
static int	ThreadDeleteEvent _ANSI_ARGS_((Tcl_Event *eventPtr,
	ClientData clientData));
static void	ThreadExitProc _ANSI_ARGS_((ClientData clientData));







 
/*
 *----------------------------------------------------------------------
 *
 * TclThread_Init --
 *
 *	Initialize the test thread command.






|







 







>
>
>
>
>
>







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
 *	Conservation Through Innovation, Limited, with their permission.
 *
 * Copyright (c) 1998 by Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclThreadTest.c,v 1.17.2.3 2005/08/29 18:38:45 dgp Exp $
 */

#include "tclInt.h"

#ifdef TCL_THREADS
/*
 * Each thread has an single instance of the following structure.  There
................................................................................
static int	ThreadEventProc _ANSI_ARGS_((Tcl_Event *evPtr, int mask));
static void	ThreadErrorProc _ANSI_ARGS_((Tcl_Interp *interp));
static void	ThreadFreeProc _ANSI_ARGS_((ClientData clientData));
static int	ThreadDeleteEvent _ANSI_ARGS_((Tcl_Event *eventPtr,
	ClientData clientData));
static void	ThreadExitProc _ANSI_ARGS_((ClientData clientData));


/* Forward declaration of function import from "tclTest.c".
 */

int Tcltest_Init _ANSI_ARGS_((Tcl_Interp *interp));

 
/*
 *----------------------------------------------------------------------
 *
 * TclThread_Init --
 *
 *	Initialize the test thread command.

Changes to tests/expr.test.

6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
....
6478
6479
6480
6481
6482
6483
6484








































































6485
6486
6487
6488
6489
6490
6491
6492
6493
6494
6495
6496
6497
#
# Copyright (c) 1996-1997 Sun Microsystems, Inc.
# Copyright (c) 1998-2000 by Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: expr.test,v 1.30.2.23 2005/08/25 15:46:53 dgp Exp $

if {[lsearch [namespace children] ::tcltest] == -1} {
    package require tcltest 2.1
    namespace import -force ::tcltest::*
}

testConstraint testmathfunctions [expr {
................................................................................
} {1 {integer value too large to represent}}
test expr-45.8 {entier} ieeeFloatingPoint {
    list [catch {expr {entier($ieeeValues(NaN))}} result] $result
} {1 {floating point value is Not a Number}}
test expr-45.9 {entier} ieeeFloatingPoint {
    list [catch {expr {entier($ieeeValues(-NaN))}} result] $result
} {1 {floating point value is Not a Number}}









































































# cleanup
if {[info exists a]} {
    unset a
}
catch {unset min}
catch {unset max}
::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# End:






|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>













6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
....
6478
6479
6480
6481
6482
6483
6484
6485
6486
6487
6488
6489
6490
6491
6492
6493
6494
6495
6496
6497
6498
6499
6500
6501
6502
6503
6504
6505
6506
6507
6508
6509
6510
6511
6512
6513
6514
6515
6516
6517
6518
6519
6520
6521
6522
6523
6524
6525
6526
6527
6528
6529
6530
6531
6532
6533
6534
6535
6536
6537
6538
6539
6540
6541
6542
6543
6544
6545
6546
6547
6548
6549
6550
6551
6552
6553
6554
6555
6556
6557
6558
6559
6560
6561
6562
6563
6564
6565
6566
6567
6568
6569
#
# Copyright (c) 1996-1997 Sun Microsystems, Inc.
# Copyright (c) 1998-2000 by Scriptics Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: expr.test,v 1.30.2.24 2005/08/29 18:38:45 dgp Exp $

if {[lsearch [namespace children] ::tcltest] == -1} {
    package require tcltest 2.1
    namespace import -force ::tcltest::*
}

testConstraint testmathfunctions [expr {
................................................................................
} {1 {integer value too large to represent}}
test expr-45.8 {entier} ieeeFloatingPoint {
    list [catch {expr {entier($ieeeValues(NaN))}} result] $result
} {1 {floating point value is Not a Number}}
test expr-45.9 {entier} ieeeFloatingPoint {
    list [catch {expr {entier($ieeeValues(-NaN))}} result] $result
} {1 {floating point value is Not a Number}}

test expr-46.1 {round() rounds to +-infinity} {
    expr round(0.5)
} 1
test expr-46.2 {round() rounds to +-infinity} {
    expr round(1.5)
} 2
test expr-46.3 {round() rounds to +-infinity} {
    expr round(-0.5)
} -1
test expr-46.4 {round() rounds to +-infinity} {
    expr round(-1.5)
} -2
test expr-46.5 {round() overflow} {
    list [catch {expr round(9.2233720368547758e+018)} result] $result
} {1 {integer value too large to represent}}
test expr-46.6 {round() overflow} {
    list [catch {expr round(-9.2233720368547758e+018)} result] $result
} {1 {integer value too large to represent}}
test expr-46.7 {round() bad value} {
    set x trash
    list [catch {expr {round($x)}} result] $result
} {1 {argument to math function didn't have numeric value}}
test expr-46.8 {round() already an integer} {
    set x 123456789012
    incr x
    expr round($x)
} 123456789013
test expr-46.9 {round() boundary case - 1/2 - 1 ulp} {
    set x 0.25
    set bit 0.125
    while 1 {
	set newx [expr {$x + $bit}]
	if { $newx == $x || $newx == 0.5 } break
	set x $newx
	set bit [expr { $bit / 2.0 }]
    }
    expr {round($x)}
} 0
test expr-46.10 {round() boundary case - 1/2 + 1 ulp} {
    set x 0.75
    set bit 0.125
    while 1 {
	set newx [expr {$x - $bit}]
	if { $newx == $x || $newx == 0.5 } break
	set x $newx
	set bit [expr { $bit / 2.0 }]
    }
    expr {round($x)}
} 1
test expr-46.11 {round() boundary case - -1/2 - 1 ulp} {
    set x -0.75
    set bit 0.125
    while 1 {
	set newx [expr {$x + $bit}]
	if { $newx == $x || $newx == -0.5 } break
	set x $newx
	set bit [expr { $bit / 2.0 }]
    }
    expr {round($x)}
} -1
test expr-46.12 {round() boundary case - -1/2 + 1 ulp} {
    set x -0.25
    set bit 0.125
    while 1 {
	set newx [expr {$x - $bit}]
	if { $newx == $x || $newx == -0.5 } break
	set x $newx
	set bit [expr { $bit / 2.0 }]
    }
    expr {round($x)}
} 0

# cleanup
if {[info exists a]} {
    unset a
}
catch {unset min}
catch {unset max}
::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# End: