Compare commits
188
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
05a3b529de | ||
|
|
ddd37fb237 | ||
|
|
63be474164 | ||
|
|
5e3ca11761 | ||
|
|
6ab540f5ff | ||
|
|
63b0fef31a | ||
|
|
bb503004b6 | ||
|
|
267cdaec03 | ||
|
|
a2ce3dab9b | ||
|
|
6a4d06759e | ||
|
|
6966f0a2b1 | ||
|
|
89a84af271 | ||
|
|
bb5d24622f | ||
|
|
813979693c | ||
|
|
c8da3bbfaf | ||
|
|
35f5b82868 | ||
|
|
5e7a1545a6 | ||
|
|
f4651a5660 | ||
|
|
a0290b85c5 | ||
|
|
8145564d30 | ||
|
|
66ef201ad7 | ||
|
|
6d943ef7b5 | ||
|
|
1c13d543f4 | ||
|
|
263de53394 | ||
|
|
a410c0d8d5 | ||
|
|
ecec1703aa | ||
|
|
585b8a5fbd | ||
|
|
36a1a69178 | ||
|
|
edb38932e8 | ||
|
|
46aab3eb09 | ||
|
|
ce025f259b | ||
|
|
f6af18a947 | ||
|
|
b729965a3c | ||
|
|
0cab7d260b | ||
|
|
708eadd19e | ||
|
|
7bbadfe0e0 | ||
|
|
4523d8df2c | ||
|
|
791f1c2741 | ||
|
|
d431841a06 | ||
|
|
dffe6bc7f1 | ||
|
|
423f761169 | ||
|
|
ba42e43e97 | ||
|
|
4f1ea4779b | ||
|
|
e6fdfbe93b | ||
|
|
bd706be303 | ||
|
|
4e12ee1bc4 | ||
|
|
7672af7212 | ||
|
|
eae621b175 | ||
|
|
5eef06ea24 | ||
|
|
9333525d11 | ||
|
|
911c1c6237 | ||
|
|
49a9e59311 | ||
|
|
242d4d7095 | ||
|
|
6ebe30b989 | ||
|
|
9cb3b15616 | ||
|
|
6d0cc0c589 | ||
|
|
d9bc6cbae2 | ||
|
|
388266030b | ||
|
|
ede72e80ac | ||
|
|
7bf3f83abd | ||
|
|
d3fd405e6b | ||
|
|
eed54b6281 | ||
|
|
6dbdfc31d2 | ||
|
|
35d6c2453e | ||
|
|
f7f4cbb151 | ||
|
|
f5e8751307 | ||
|
|
7855612da6 | ||
|
|
7f26fedbcc | ||
|
|
47e9dbdc37 | ||
|
|
8fd1568405 | ||
|
|
78ee8c697e | ||
|
|
08f43a1ff4 | ||
|
|
1f71d7079b | ||
|
|
5cef8b0f8e | ||
|
|
5f0cf291f5 | ||
|
|
5500074eff | ||
|
|
db133f0144 | ||
|
|
66525c95ee | ||
|
|
86c6a11cdb | ||
|
|
13bdb0305c | ||
|
|
2a19591dc7 | ||
|
|
411bfad9f4 | ||
|
|
f58e9ed842 | ||
|
|
e383cd7b26 | ||
|
|
3a3fd2954f | ||
|
|
d2aab73f0d | ||
|
|
f44e7c1795 | ||
|
|
04604552b2 | ||
|
|
b5d6b4f138 | ||
|
|
ad02c0b532 | ||
|
|
28e500cbf9 | ||
|
|
637c7dbc7e | ||
|
|
49879791f4 | ||
|
|
8262e514d0 | ||
|
|
5a8d06b076 | ||
|
|
008f1c98d0 | ||
|
|
383c53f80e | ||
|
|
ba9cf35aa3 | ||
|
|
db41a49d9c | ||
|
|
cbbab84b71 | ||
|
|
47152d94c1 | ||
|
|
22b7cdc32a | ||
|
|
5b5bd699ff | ||
|
|
69868ee129 | ||
|
|
1dd89810eb | ||
|
|
53795bd199 | ||
|
|
603e23c2a9 | ||
|
|
3f03f8189e | ||
|
|
c576cbec93 | ||
|
|
5c4f8d88b5 | ||
|
|
9c5c1a721f | ||
|
|
bf868c1c56 | ||
|
|
a69614b432 | ||
|
|
4e0ad3f7f9 | ||
|
|
ef7ea2c390 | ||
|
|
5470f13299 | ||
|
|
c0effc5b46 | ||
|
|
15f27ca8f2 | ||
|
|
b5273bc1fa | ||
|
|
d9a0c170ba | ||
|
|
0df7499357 | ||
|
|
efd9f86a13 | ||
|
|
6d3cc4a73e | ||
|
|
350c397278 | ||
|
|
c40cd22276 | ||
|
|
931b6206fc | ||
|
|
199f12cfe6 | ||
|
|
bdcb5b999f | ||
|
|
a26718d29f | ||
|
|
ec1d2ba767 | ||
|
|
1286a4eb13 | ||
|
|
cdba31b9d5 | ||
|
|
bb504b06b4 | ||
|
|
55717aeaea | ||
|
|
8615597984 | ||
|
|
a333bbaa12 | ||
|
|
2bc847ac57 | ||
|
|
9283692888 | ||
|
|
017b8b10b6 | ||
|
|
4ddfe70ae2 | ||
|
|
53dc25e532 | ||
|
|
542b57cf21 | ||
|
|
e36fd891e4 | ||
|
|
954b241f34 | ||
|
|
3f56494834 | ||
|
|
6a811b97b9 | ||
|
|
1900da6d24 | ||
|
|
8f38d12eee | ||
|
|
3f5f45f002 | ||
|
|
e6528cb48d | ||
|
|
041184928d | ||
|
|
b108063f75 | ||
|
|
9ce336b3d1 | ||
|
|
b5da760544 | ||
|
|
7e520e2089 | ||
|
|
07af7d5337 | ||
|
|
696a9ba3f9 | ||
|
|
9db6776dbe | ||
|
|
1c6a242b2e | ||
|
|
a58db736cf | ||
|
|
449ea43718 | ||
|
|
260c2634b9 | ||
|
|
6d0db57c02 | ||
|
|
11593d64b8 | ||
|
|
e4a0b9dbfd | ||
|
|
bb770e33f8 | ||
|
|
d048128004 | ||
|
|
eecece2afe | ||
|
|
74c7068a25 | ||
|
|
59360240b3 | ||
|
|
91ba235b3c | ||
|
|
d13fe1e431 | ||
|
|
f361c1805c | ||
|
|
52b8ad45d1 | ||
|
|
9b6c85d82e | ||
|
|
88b8fc30a2 | ||
|
|
1a0463ea04 | ||
|
|
cab91124b4 | ||
|
|
8d9ea7c132 | ||
|
|
c5558280d7 | ||
|
|
3913f5f7ae | ||
|
|
e8c69aa654 | ||
|
|
b2b37d97cf | ||
|
|
4796adf5cb | ||
|
|
2c02c2ae5d | ||
|
|
ef824b7395 | ||
|
|
2930daf68c | ||
|
|
0481e3ca74 |
+31
-13
@@ -9,18 +9,18 @@
|
||||
.BS
|
||||
'\" Note: do not modify the .SH NAME line immediately below!
|
||||
.SH NAME
|
||||
Tcl_ClassSetConstructor, Tcl_ClassSetDestructor, Tcl_MethodDeclarerClass, Tcl_MethodDeclarerObject, Tcl_MethodIsPublic, Tcl_MethodIsType, Tcl_MethodName, Tcl_NewInstanceMethod, Tcl_NewMethod, Tcl_ObjectContextInvokeNext, Tcl_ObjectContextIsFiltering, Tcl_ObjectContextMethod, Tcl_ObjectContextObject, Tcl_ObjectContextSkippedArgs \- manipulate methods and method-call contexts
|
||||
Tcl_ClassSetConstructor, Tcl_ClassSetDestructor, Tcl_MethodDeclarerClass, Tcl_MethodDeclarerObject, Tcl_MethodIsPublic, Tcl_MethodIsPrivate, Tcl_MethodIsType, Tcl_MethodName, Tcl_NewInstanceMethod, Tcl_NewMethod, Tcl_ObjectContextInvokeNext, Tcl_ObjectContextIsFiltering, Tcl_ObjectContextMethod, Tcl_ObjectContextObject, Tcl_ObjectContextSkippedArgs \- manipulate methods and method-call contexts
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
\fB#include <tclOO.h>\fR
|
||||
.sp
|
||||
Tcl_Method
|
||||
\fBTcl_NewMethod\fR(\fIinterp, class, nameObj, isPublic,
|
||||
methodTypePtr, clientData\fR)
|
||||
\fBTcl_NewMethod\fR(\fIinterp, class, nameObj, flags, methodTypePtr,
|
||||
clientData\fR)
|
||||
.sp
|
||||
Tcl_Method
|
||||
\fBTcl_NewInstanceMethod\fR(\fIinterp, object, nameObj, isPublic,
|
||||
methodTypePtr, clientData\fR)
|
||||
\fBTcl_NewInstanceMethod\fR(\fIinterp, object, nameObj, flags, methodTypePtr,
|
||||
clientData\fR)
|
||||
.sp
|
||||
\fBTcl_ClassSetConstructor\fR(\fIinterp, class, method\fR)
|
||||
.sp
|
||||
@@ -35,8 +35,13 @@ Tcl_Object
|
||||
Tcl_Obj *
|
||||
\fBTcl_MethodName\fR(\fImethod\fR)
|
||||
.sp
|
||||
.VS TIP500
|
||||
int
|
||||
\fBTcl_MethodIsPublic\fR(\fImethod\fR)
|
||||
.VE TIP500
|
||||
.sp
|
||||
int
|
||||
\fBTcl_MethodIsPrivate\fR(\fImethod\fR)
|
||||
.sp
|
||||
int
|
||||
\fBTcl_MethodIsType\fR(\fImethod, methodTypePtr, clientDataPtr\fR)
|
||||
@@ -66,10 +71,15 @@ The class to create the method in.
|
||||
.AP Tcl_Obj *nameObj in
|
||||
The name of the method to create. Should not be NULL unless creating
|
||||
constructors or destructors.
|
||||
.AP int isPublic in
|
||||
A flag saying what the visibility of the method is. The only supported public
|
||||
values of this flag are 0 for a non-exported method, and 1 for an exported
|
||||
method.
|
||||
.AP int flags in
|
||||
A flag saying (currently) what the visibility of the method is. The supported
|
||||
public values of this flag are \fBTCL_OO_METHOD_PUBLIC\fR (which is fixed at 1
|
||||
for backward compatibility) for an exported method,
|
||||
\fBTCL_OO_METHOD_UNEXPORTED\fR (which is fixed at 0 for backward
|
||||
compatibility) for a non-exported method,
|
||||
.VS TIP500
|
||||
and \fBTCL_OO_METHOD_PRIVATE\fR for a private method.
|
||||
.VE TIP500
|
||||
.AP Tcl_MethodType *methodTypePtr in
|
||||
A description of the type of the method to create, or the type of method to
|
||||
compare against.
|
||||
@@ -105,8 +115,12 @@ Given a method, the entity that declared it can be found using
|
||||
attached to (or NULL if the method is not attached to any class) and
|
||||
\fBTcl_MethodDeclarerObject\fR which returns the object that the method is
|
||||
attached to (or NULL if the method is not attached to an object). The name of
|
||||
the method can be retrieved with \fBTcl_MethodName\fR and whether the method
|
||||
is exported is retrieved with \fBTcl_MethodIsPublic\fR. The type of the method
|
||||
the method can be retrieved with \fBTcl_MethodName\fR, whether the method
|
||||
is exported is retrieved with \fBTcl_MethodIsPublic\fR,
|
||||
.VS TIP500
|
||||
and whether the method is private is retrieved with \fBTcl_MethodIsPrivate\fR.
|
||||
.VE TIP500
|
||||
The type of the method
|
||||
can also be introspected upon to a limited degree; the function
|
||||
\fBTcl_MethodIsType\fR returns whether a method is of a particular type,
|
||||
assigning the per-method \fIclientData\fR to the variable pointed to by
|
||||
@@ -117,8 +131,12 @@ Methods are created by \fBTcl_NewMethod\fR and \fBTcl_NewInstanceMethod\fR,
|
||||
which
|
||||
create a method attached to a class or an object respectively. In both cases,
|
||||
the \fInameObj\fR argument gives the name of the method to create, the
|
||||
\fIisPublic\fR argument states whether the method should be exported
|
||||
initially, the \fImethodTypePtr\fR argument describes the implementation of
|
||||
\fIflags\fR argument states whether the method should be exported
|
||||
initially
|
||||
.VS TIP500
|
||||
or be marked as a private method,
|
||||
.VE TIP500
|
||||
the \fImethodTypePtr\fR argument describes the implementation of
|
||||
the method (see the \fBMETHOD TYPES\fR section below) and the \fIclientData\fR
|
||||
argument gives some implementation-specific data that is passed on to the
|
||||
implementation of the method when it is called.
|
||||
|
||||
+12
-1
@@ -7,7 +7,7 @@
|
||||
.BS
|
||||
'\" Note: do not modify the .SH NAME line immediately below!
|
||||
.SH NAME
|
||||
Tcl_Panic, Tcl_PanicVA, Tcl_SetPanicProc \- report fatal error and abort
|
||||
Tcl_Panic, Tcl_PanicVA, Tcl_SetPanicProc, Tcl_ConsolePanic \- report fatal error and abort
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
\fB#include <tcl.h>\fR
|
||||
@@ -21,6 +21,9 @@ void
|
||||
void
|
||||
\fBTcl_SetPanicProc\fR(\fIpanicProc\fR)
|
||||
.sp
|
||||
void
|
||||
\fBTcl_ConsolePanic\fR(\fIformat\fR, \fIarg\fR, \fIarg\fR, \fI...\fR)
|
||||
.sp
|
||||
.SH ARGUMENTS
|
||||
.AS Tcl_PanicProc *panicProc
|
||||
.AP "const char*" format in
|
||||
@@ -54,6 +57,14 @@ message is sent to the debugger in stead. If the windows executable
|
||||
does not have a stderr channel (e.g. \fBwish.exe\fR), then a
|
||||
system dialog box is used to display the panic message.
|
||||
.PP
|
||||
If your application doesn't use \fBTcl_Main\fR or \fBTk_Main\fR
|
||||
and you want to implicitly use the stderr channel of your
|
||||
application's C runtime (in stead of the stderr channel of the
|
||||
C runtime used by Tcl), you can call \fBTcl_SetPanicProc\fR
|
||||
with \fBTcl_ConsolePanic\fR as its argument. On platforms which
|
||||
only have one C runtime (almost all platforms except Windows)
|
||||
\fBTcl_ConsolePanic\fR is equivalent to NULL.
|
||||
.PP
|
||||
\fBTcl_SetPanicProc\fR may be used to modify the behavior of
|
||||
\fBTcl_Panic\fR. The \fIpanicProc\fR argument should match the
|
||||
type \fBTcl_PanicProc\fR:
|
||||
|
||||
+124
-37
@@ -82,17 +82,14 @@ by a superclass; subclass exports override superclass visibility, and may in
|
||||
turn be overridden by instances.
|
||||
.TP
|
||||
\fBfilter\fR ?\fI\-slotOperation\fR? ?\fImethodName ...\fR?
|
||||
.VS
|
||||
.
|
||||
This slot (see \fBSLOTTED DEFINITIONS\fR below)
|
||||
.VE
|
||||
sets or updates the list of method names that are used to guard whether
|
||||
method call to instances of the class may be called and what the method's
|
||||
results are. Each \fImethodName\fR names a single filtering method (which may
|
||||
be exposed or not exposed); it is not an error for a non-existent method to be
|
||||
named since they may be defined by subclasses.
|
||||
.VS
|
||||
By default, this slot works by appending.
|
||||
.VE
|
||||
.TP
|
||||
\fBforward\fI name cmdName \fR?\fIarg ...\fR?
|
||||
.
|
||||
@@ -105,6 +102,13 @@ fully-qualified, the command will be searched for in each object's namespace,
|
||||
using the instances' namespace's path, or by looking in the global namespace.
|
||||
The method will be exported if \fIname\fR starts with a lower-case letter, and
|
||||
non-exported otherwise.
|
||||
.RS
|
||||
.PP
|
||||
.VS TIP500
|
||||
If in a private definition context (see the \fBprivate\fR definition command,
|
||||
below), this command creates private forwarded methods.
|
||||
.VE TIP500
|
||||
.RE
|
||||
.TP
|
||||
\fBmethod\fI name argList bodyScript\fR
|
||||
.
|
||||
@@ -117,17 +121,40 @@ be a namespace that is unique to the current object. The method will be
|
||||
exported if \fIname\fR starts with a lower-case letter, and non-exported
|
||||
otherwise; this behavior can be overridden via \fBexport\fR and
|
||||
\fBunexport\fR.
|
||||
.RS
|
||||
.PP
|
||||
.VS TIP500
|
||||
If in a private definition context (see the \fBprivate\fR definition command,
|
||||
below), this command creates private procedure-like methods.
|
||||
.VE TIP500
|
||||
.RE
|
||||
.TP
|
||||
\fBmixin\fR ?\fI\-slotOperation\fR? ?\fIclassName ...\fR?
|
||||
.VS
|
||||
.
|
||||
This slot (see \fBSLOTTED DEFINITIONS\fR below)
|
||||
.VE
|
||||
sets or updates the list of additional classes that are to be mixed into
|
||||
all the instances of the class being defined. Each \fIclassName\fR argument
|
||||
names a single class that is to be mixed in.
|
||||
.VS
|
||||
By default, this slot works by replacement.
|
||||
.VE
|
||||
.TP
|
||||
\fBprivate \fIcmd arg...\fR
|
||||
.TP
|
||||
\fBprivate \fIscript\fR
|
||||
.
|
||||
.VS TIP500
|
||||
This evaluates the \fIscript\fR (or the list of command and arguments given by
|
||||
\fIcmd\fR and \fIarg\fRs) in a context where the definitions made on the
|
||||
current class will be private definitions.
|
||||
.RS
|
||||
.PP
|
||||
The following class definition commands are affected by \fBprivate\fR:
|
||||
\fBforward\fR, \fBmethod\fR, \fBself\fR, and \fBvariable\fR. Nesting
|
||||
\fBprivate\fR inside \fBprivate\fR has no cumulative effect; the innermost
|
||||
definition context is just a private definition context. All other definition
|
||||
commands have no difference in behavior when used in a private definition
|
||||
context.
|
||||
.RE
|
||||
.VE TIP500
|
||||
.TP
|
||||
\fBrenamemethod\fI fromName toName\fR
|
||||
.
|
||||
@@ -159,21 +186,23 @@ operates identically to
|
||||
If no arguments at all are used, this gives the name of the class currently
|
||||
being configured.
|
||||
.VE TIP470
|
||||
.VS TIP500
|
||||
If in a private definition context (see the \fBprivate\fR definition command,
|
||||
below), the definitions on the class object will also be made in a private
|
||||
definition context.
|
||||
.VE TIP500
|
||||
.RE
|
||||
.TP
|
||||
\fBsuperclass\fR ?\fI\-slotOperation\fR? ?\fIclassName ...\fR?
|
||||
.VS
|
||||
.
|
||||
This slot (see \fBSLOTTED DEFINITIONS\fR below)
|
||||
.VE
|
||||
allows the alteration of the superclasses of the class being defined.
|
||||
Each \fIclassName\fR argument names one class that is to be a superclass of
|
||||
the defined class. Note that objects must not be changed from being classes to
|
||||
being non-classes or vice-versa, that an empty parent class is equivalent to
|
||||
\fBoo::object\fR, and that the parent classes of \fBoo::object\fR and
|
||||
\fBoo::class\fR may not be modified.
|
||||
.VS
|
||||
By default, this slot works by replacement.
|
||||
.VE
|
||||
.TP
|
||||
\fBunexport\fI name \fR?\fIname ...\fR?
|
||||
.
|
||||
@@ -185,18 +214,31 @@ actually defined by a superclass; subclass unexports override superclass
|
||||
visibility, and may be overridden by instance unexports.
|
||||
.TP
|
||||
\fBvariable\fR ?\fI\-slotOperation\fR? ?\fIname ...\fR?
|
||||
.VS
|
||||
.
|
||||
This slot (see \fBSLOTTED DEFINITIONS\fR below) arranges for each of the named
|
||||
variables to be automatically made
|
||||
available in the methods, constructor and destructor declared by the class
|
||||
being defined. Each variable name must not have any namespace
|
||||
separators and must not look like an array access. All variables will be
|
||||
actually present in the instance object on which the method is executed. Note
|
||||
actually present in the namespace of the instance object on which the method
|
||||
is executed. Note
|
||||
that the variable lists declared by a superclass or subclass are completely
|
||||
disjoint, as are variable lists declared by instances; the list of variable
|
||||
names is just for methods (and constructors and destructors) declared by this
|
||||
class. By default, this slot works by appending.
|
||||
.VE
|
||||
.RS
|
||||
.PP
|
||||
.VS TIP500
|
||||
If in a private definition context (see the \fBprivate\fR definition command,
|
||||
below), this slot manipulates the list of private variable bindings for this
|
||||
class. In a private variable binding, the name of the variable within the
|
||||
instance object is different to the name given in the definition; the name
|
||||
used in the definition is the name that you use to access the variable within
|
||||
the methods of this class, and the name of the variable in the instance
|
||||
namespace has a unique prefix that makes accidental use from other classes
|
||||
extremely unlikely.
|
||||
.VE TIP500
|
||||
.RE
|
||||
.SS "CONFIGURING OBJECTS"
|
||||
.PP
|
||||
The following commands are supported in the \fIdefScript\fR for
|
||||
@@ -223,18 +265,15 @@ being defined. Note that the methods themselves may be actually defined by a
|
||||
class or superclass; object exports override class visibility.
|
||||
.TP
|
||||
\fBfilter\fR ?\fI\-slotOperation\fR? ?\fImethodName ...\fR?
|
||||
.VS
|
||||
.
|
||||
This slot (see \fBSLOTTED DEFINITIONS\fR below)
|
||||
.VE
|
||||
sets or updates the list of method names that are used to guard whether a
|
||||
method call to the object may be called and what the method's results are.
|
||||
Each \fImethodName\fR names a single filtering method (which may be exposed or
|
||||
not exposed); it is not an error for a non-existent method to be named. Note
|
||||
that the actual list of filters also depends on the filters set upon any
|
||||
classes that the object is an instance of.
|
||||
.VS
|
||||
By default, this slot works by appending.
|
||||
.VE
|
||||
.TP
|
||||
\fBforward\fI name cmdName \fR?\fIarg ...\fR?
|
||||
.
|
||||
@@ -244,6 +283,13 @@ additional arguments, \fIarg\fR etc., added before those arguments specified
|
||||
by the caller of the method. Forwarded methods should be deleted using the
|
||||
\fBmethod\fR subcommand. The method will be exported if \fIname\fR starts with
|
||||
a lower-case letter, and non-exported otherwise.
|
||||
.RS
|
||||
.PP
|
||||
.VS TIP500
|
||||
If in a private definition context (see the \fBprivate\fR definition command,
|
||||
below), this command creates private forwarded methods.
|
||||
.VE TIP500
|
||||
.RE
|
||||
.TP
|
||||
\fBmethod\fI name argList bodyScript\fR
|
||||
.
|
||||
@@ -254,17 +300,38 @@ method will be \fIbodyScript\fR. When the body of the method is evaluated, the
|
||||
current namespace of the method will be a namespace that is unique to the
|
||||
object. The method will be exported if \fIname\fR starts with a lower-case
|
||||
letter, and non-exported otherwise.
|
||||
.RS
|
||||
.PP
|
||||
.VS TIP500
|
||||
If in a private definition context (see the \fBprivate\fR definition command,
|
||||
below), this command creates private procedure-like methods.
|
||||
.VE TIP500
|
||||
.RE
|
||||
.TP
|
||||
\fBmixin\fR ?\fI\-slotOperation\fR? ?\fIclassName ...\fR?
|
||||
.VS
|
||||
.
|
||||
This slot (see \fBSLOTTED DEFINITIONS\fR below)
|
||||
.VE
|
||||
sets or updates a per-object list of additional classes that are to be
|
||||
mixed into the object. Each argument, \fIclassName\fR, names a single class
|
||||
that is to be mixed in.
|
||||
.VS
|
||||
By default, this slot works by replacement.
|
||||
.VE
|
||||
.TP
|
||||
\fBprivate \fIcmd arg...\fR
|
||||
.TP
|
||||
\fBprivate \fIscript\fR
|
||||
.VS TIP500
|
||||
This evaluates the \fIscript\fR (or the list of command and arguments given by
|
||||
\fIcmd\fR and \fIarg\fRs) in a context where the definitions made on the
|
||||
current object will be private definitions.
|
||||
.RS
|
||||
.PP
|
||||
The following class definition commands are affected by \fBprivate\fR:
|
||||
\fBforward\fR, \fBmethod\fR, and \fBvariable\fR. Nesting \fBprivate\fR inside
|
||||
\fBprivate\fR has no cumulative effect; the innermost definition context is
|
||||
just a private definition context. All other definition commands have no
|
||||
difference in behavior when used in a private definition context.
|
||||
.RE
|
||||
.VE TIP500
|
||||
.TP
|
||||
\fBrenamemethod\fI fromName toName\fR
|
||||
.
|
||||
@@ -275,7 +342,6 @@ that the object is an instance of. Does not change the export status of the
|
||||
method; if it was exported before, it will be afterwards.
|
||||
.TP
|
||||
\fBself \fR
|
||||
.
|
||||
.VS TIP470
|
||||
This gives the name of the object currently being configured.
|
||||
.VE TIP470
|
||||
@@ -289,15 +355,42 @@ object being defined. Note that the methods themselves may be actually defined
|
||||
by a class; instance unexports override class visibility.
|
||||
.TP
|
||||
\fBvariable\fR ?\fI\-slotOperation\fR? ?\fIname ...\fR?
|
||||
.VS
|
||||
.
|
||||
This slot (see \fBSLOTTED DEFINITIONS\fR below) arranges for each of the named
|
||||
variables to be automatically made available in the methods declared by the
|
||||
object being defined. Each variable name must not have any namespace
|
||||
separators and must not look like an array access. All variables will be
|
||||
actually present in the object on which the method is executed. Note that the
|
||||
actually present in the namespace of the object on which the method is
|
||||
executed. Note that the
|
||||
variable lists declared by the classes and mixins of which the object is an
|
||||
instance are completely disjoint; the list of variable names is just for
|
||||
methods declared by this object. By default, this slot works by appending.
|
||||
.RS
|
||||
.PP
|
||||
.VS TIP500
|
||||
If in a private definition context (see the \fBprivate\fR definition command,
|
||||
below), this slot manipulates the list of private variable bindings for this
|
||||
object. In a private variable binding, the name of the variable within the
|
||||
instance object is different to the name given in the definition; the name
|
||||
used in the definition is the name that you use to access the variable within
|
||||
the methods of this instance object, and the name of the variable in the
|
||||
instance namespace has a unique prefix that makes accidental use from
|
||||
superclass methods extremely unlikely.
|
||||
.VE TIP500
|
||||
.RE
|
||||
.SH "PRIVATE METHODS"
|
||||
.VS TIP500
|
||||
When a class or instance has a private method, that private method can only be
|
||||
invoked from within methods of that class or instance. Other callers of the
|
||||
object's methods \fIcannot\fR invoke private methods, it is as if the private
|
||||
methods do not exist. However, a private method of a class \fIcan\fR be
|
||||
invoked from the class's methods when those methods are being used on another
|
||||
instance object; this means that a class can use them to coordinate behaviour
|
||||
between several instances of itself without interfering with how other
|
||||
classes (especially either subclasses or superclasses) interact. Private
|
||||
methods precede all mixed in classes in the method call order (as reported by
|
||||
\fBself call\fR).
|
||||
.VE TIP500
|
||||
.SH "SLOTTED DEFINITIONS"
|
||||
Some of the configurable definitions of a class or object are \fIslotted
|
||||
definitions\fR. This means that the configuration is implemented by a slot
|
||||
@@ -305,20 +398,17 @@ object, that is an instance of the class \fBoo::Slot\fR, which manages a list
|
||||
of values (class names, variable names, etc.) that comprises the contents of
|
||||
the slot. The class defines three operations (as methods) that may be done on
|
||||
the slot:
|
||||
.VE
|
||||
.TP
|
||||
\fIslot\fR \fB\-append\fR ?\fImember ...\fR?
|
||||
.VS
|
||||
.
|
||||
This appends the given \fImember\fR elements to the slot definition.
|
||||
.VE
|
||||
.TP
|
||||
\fIslot\fR \fB\-clear\fR
|
||||
.VS
|
||||
.
|
||||
This sets the slot definition to the empty list.
|
||||
.VE
|
||||
.TP
|
||||
\fIslot\fR \fB\-set\fR ?\fImember ...\fR?
|
||||
.VS
|
||||
.
|
||||
This replaces the slot definition with the given \fImember\fR elements.
|
||||
.PP
|
||||
A consequence of this is that any use of a slot's default operation where the
|
||||
@@ -331,17 +421,15 @@ which is forwarded to the default operation of the slot (thus, for the class
|
||||
slot, this is forwarded to
|
||||
.QW "\fBmy \-append\fR" ),
|
||||
and these methods which provide the implementation interface:
|
||||
.VE
|
||||
.TP
|
||||
\fIslot\fR \fBGet\fR
|
||||
.VS
|
||||
.
|
||||
Returns a list that is the current contents of the slot. This method must
|
||||
always be called from a stack frame created by a call to \fBoo::define\fR or
|
||||
\fBoo::objdefine\fR.
|
||||
.VE
|
||||
.TP
|
||||
\fIslot\fR \fBSet \fIelementList\fR
|
||||
.VS
|
||||
.
|
||||
Sets the contents of the slot to the list \fIelementList\fR and returns the
|
||||
empty string. This method must always be called from a stack frame created by
|
||||
a call to \fBoo::define\fR or \fBoo::objdefine\fR.
|
||||
@@ -352,7 +440,6 @@ an unknown method handler to tie all these pieces together, and they hide
|
||||
their \fBdestroy\fR method so that it is not invoked inadvertently. It is
|
||||
\fIrecommended\fR that any user changes to the slot mechanism be restricted to
|
||||
defining new operations whose names start with a hyphen.
|
||||
.VE
|
||||
.SH EXAMPLES
|
||||
This example demonstrates how to use both forms of the \fBoo::define\fR and
|
||||
\fBoo::objdefine\fR commands (they work in the same way), as well as
|
||||
|
||||
+152
-98
@@ -35,10 +35,9 @@ Returns the body of procedure \fIprocname\fR. \fIProcname\fR must be
|
||||
the name of a Tcl command procedure.
|
||||
.TP
|
||||
\fBinfo class\fI subcommand class\fR ?\fIarg ...\fR
|
||||
.VS 8.6
|
||||
.
|
||||
Returns information about the class, \fIclass\fR. The \fIsubcommand\fRs are
|
||||
described in \fBCLASS INTROSPECTION\fR below.
|
||||
.VE 8.6
|
||||
.TP
|
||||
\fBinfo cmdcount\fR
|
||||
.
|
||||
@@ -78,11 +77,10 @@ command is not complete, the script can delay evaluating it until additional
|
||||
lines have been typed to complete the command.
|
||||
.TP
|
||||
\fBinfo coroutine\fR
|
||||
.VS 8.6
|
||||
.
|
||||
Returns the name of the currently executing \fBcoroutine\fR, or the empty
|
||||
string if either no coroutine is currently executing, or the current coroutine
|
||||
has been deleted (but has not yet returned or yielded since deletion).
|
||||
.VE 8.6
|
||||
.TP
|
||||
\fBinfo default \fIprocname arg varname\fR
|
||||
.
|
||||
@@ -93,7 +91,7 @@ Otherwise it returns \fB1\fR and places the default value of \fIarg\fR
|
||||
into variable \fIvarname\fR.
|
||||
.TP
|
||||
\fBinfo errorstack \fR?\fIinterp\fR?
|
||||
.VS 8.6
|
||||
.
|
||||
Returns, in a form that is programmatically easy to parse, the function names
|
||||
and arguments at each level from the call stack of the last error in the given
|
||||
\fIinterp\fR, or in the current one if not specified.
|
||||
@@ -118,7 +116,6 @@ options dictionary returned by 3-argument \fBcatch\fR; \fBinfo errorstack\fR
|
||||
is a convenient way of retrieving it for uncaught errors at top-level in an
|
||||
interactive \fBtclsh\fR.
|
||||
.RE
|
||||
.VE 8.6
|
||||
.TP
|
||||
\fBinfo exists \fIvarName\fR
|
||||
.
|
||||
@@ -329,10 +326,9 @@ was invoked. If Tcl was unable to identify the file, then an empty
|
||||
string is returned.
|
||||
.TP
|
||||
\fBinfo object\fI subcommand object\fR ?\fIarg ...\fR
|
||||
.VS 8.6
|
||||
.
|
||||
Returns information about the object, \fIobject\fR. The \fIsubcommand\fRs are
|
||||
described in \fBOBJECT INTROSPECTION\fR below.
|
||||
.VE 8.6
|
||||
.TP
|
||||
\fBinfo patchlevel\fR
|
||||
.
|
||||
@@ -399,20 +395,22 @@ Note that a currently-visible variable may not yet
|
||||
if it has not
|
||||
been set (e.g. a variable declared but not set by \fBvariable\fR).
|
||||
.SS "CLASS INTROSPECTION"
|
||||
.VS 8.6
|
||||
.PP
|
||||
The following \fIsubcommand\fR values are supported by \fBinfo class\fR:
|
||||
.VE 8.6
|
||||
.TP
|
||||
\fBinfo class call\fI class method\fR
|
||||
.VS
|
||||
.
|
||||
Returns a description of the method implementations that are used to provide a
|
||||
stereotypical instance of \fIclass\fR's implementation of \fImethod\fR
|
||||
(stereotypical instances being objects instantiated by a class without having
|
||||
any object-specific definitions added). This consists of a list of lists of
|
||||
four elements, where each sublist consists of a word that describes the
|
||||
general type of method implementation (being one of \fBmethod\fR for an
|
||||
ordinary method, \fBfilter\fR for an applied filter, and \fBunknown\fR for a
|
||||
ordinary method, \fBfilter\fR for an applied filter,
|
||||
.VS TIP500
|
||||
\fBprivate\fR for a private method,
|
||||
.VE TIP500
|
||||
and \fBunknown\fR for a
|
||||
method that is invoked as part of unknown method handling), a word giving the
|
||||
name of the particular method invoked (which is always the same as
|
||||
\fImethod\fR for the \fBmethod\fR type, and
|
||||
@@ -423,122 +421,149 @@ implementation (see \fBinfo class methodtype\fR).
|
||||
.RS
|
||||
.PP
|
||||
Note that there is no inspection of whether the method implementations
|
||||
actually use \fBnext\fR to transfer control along the call chain.
|
||||
actually use \fBnext\fR to transfer control along the call chain,
|
||||
.VS TIP500
|
||||
and the call chains that this command files do not actually contain private
|
||||
methods.
|
||||
.VE TIP500
|
||||
.RE
|
||||
.VE 8.6
|
||||
.TP
|
||||
\fBinfo class constructor\fI class\fR
|
||||
.VS 8.6
|
||||
.
|
||||
This subcommand returns a description of the definition of the constructor of
|
||||
class \fIclass\fR. The definition is described as a two element list; the first
|
||||
element is the list of arguments to the constructor in a form suitable for
|
||||
passing to another call to \fBproc\fR or a method definition, and the second
|
||||
element is the body of the constructor. If no constructor is present, this
|
||||
returns the empty list.
|
||||
.VE 8.6
|
||||
.TP
|
||||
\fBinfo class definition\fI class method\fR
|
||||
.VS 8.6
|
||||
.
|
||||
This subcommand returns a description of the definition of the method named
|
||||
\fImethod\fR of class \fIclass\fR. The definition is described as a two element
|
||||
list; the first element is the list of arguments to the method in a form
|
||||
suitable for passing to another call to \fBproc\fR or a method definition, and
|
||||
the second element is the body of the method.
|
||||
.VE 8.6
|
||||
.TP
|
||||
\fBinfo class destructor\fI class\fR
|
||||
.VS 8.6
|
||||
.
|
||||
This subcommand returns the body of the destructor of class \fIclass\fR. If no
|
||||
destructor is present, this returns the empty string.
|
||||
.VE 8.6
|
||||
.TP
|
||||
\fBinfo class filters\fI class\fR
|
||||
.VS 8.6
|
||||
.
|
||||
This subcommand returns the list of filter methods set on the class.
|
||||
.VE 8.6
|
||||
.TP
|
||||
\fBinfo class forward\fI class method\fR
|
||||
.VS 8.6
|
||||
.
|
||||
This subcommand returns the argument list for the method forwarding called
|
||||
\fImethod\fR that is set on the class called \fIclass\fR.
|
||||
.VE 8.6
|
||||
.TP
|
||||
\fBinfo class instances\fI class\fR ?\fIpattern\fR?
|
||||
.VS 8.6
|
||||
.
|
||||
This subcommand returns a list of instances of class \fIclass\fR. If the
|
||||
optional \fIpattern\fR argument is present, it constrains the list of returned
|
||||
instances to those that match it according to the rules of \fBstring match\fR.
|
||||
.VE 8.6
|
||||
.TP
|
||||
\fBinfo class methods\fI class\fR ?\fIoptions...\fR?
|
||||
.VS 8.6
|
||||
.
|
||||
This subcommand returns a list of all public (i.e. exported) methods of the
|
||||
class called \fIclass\fR. Any of the following \fIoption\fRs may be
|
||||
specified, controlling exactly which method names are returned:
|
||||
.RS
|
||||
.VE 8.6
|
||||
.TP
|
||||
\fB\-all\fR
|
||||
.VS 8.6
|
||||
If the \fB\-all\fR flag is given, the list of methods will include those
|
||||
.
|
||||
If the \fB\-all\fR flag is given,
|
||||
.VS TIP500
|
||||
and the \fB\-scope\fR flag is not given,
|
||||
.VE TIP500
|
||||
the list of methods will include those
|
||||
methods defined not just by the class, but also by the class's superclasses
|
||||
and mixins.
|
||||
.VE 8.6
|
||||
.TP
|
||||
\fB\-private\fR
|
||||
.VS 8.6
|
||||
If the \fB\-private\fR flag is given, the list of methods will also include
|
||||
the private (i.e. non-exported) methods of the class (and superclasses and
|
||||
.
|
||||
If the \fB\-private\fR flag is given,
|
||||
.VS TIP500
|
||||
and the \fB\-scope\fR flag is not given,
|
||||
.VE TIP500
|
||||
the list of methods will also include
|
||||
the non-exported methods of the class (and superclasses and
|
||||
mixins, if \fB\-all\fR is also given).
|
||||
.VS TIP500
|
||||
Note that this naming is an unfortunate clash with true private methods; this
|
||||
option name is retained for backward compatibility.
|
||||
.VE TIP500
|
||||
.TP
|
||||
\fB\-scope\fI scope\fR
|
||||
.VS TIP500
|
||||
Returns a list of all methods on \fIclass\fR that have the given visibility
|
||||
\fIscope\fR. When this option is supplied, both the \fB\-all\fR and
|
||||
\fB\-private\fR options are ignored. The valid values for \fIscope\fR are:
|
||||
.RS
|
||||
.IP \fBpublic\fR 3
|
||||
Only methods with \fIpublic\fR scope (i.e., callable from anywhere by any instance
|
||||
of this class) are to be returned.
|
||||
.IP \fBunexported\fR 3
|
||||
Only methods with \fIunexported\fR scope (i.e., only callable via \fBmy\fR) are to
|
||||
be returned.
|
||||
.IP \fBprivate\fR 3
|
||||
Only methods with \fIprivate\fR scope (i.e., only callable from within this class's
|
||||
methods) are to be returned.
|
||||
.RE
|
||||
.VE TIP500
|
||||
.RE
|
||||
.VE 8.6
|
||||
.TP
|
||||
\fBinfo class methodtype\fI class method\fR
|
||||
.VS 8.6
|
||||
.
|
||||
This subcommand returns a description of the type of implementation used for
|
||||
the method named \fImethod\fR of class \fIclass\fR. When the result is
|
||||
\fBmethod\fR, further information can be discovered with \fBinfo class
|
||||
definition\fR, and when the result is \fBforward\fR, further information can
|
||||
be discovered with \fBinfo class forward\fR.
|
||||
.VE 8.6
|
||||
.TP
|
||||
\fBinfo class mixins\fI class\fR
|
||||
.VS 8.6
|
||||
.
|
||||
This subcommand returns a list of all classes that have been mixed into the
|
||||
class named \fIclass\fR.
|
||||
.VE 8.6
|
||||
.TP
|
||||
\fBinfo class subclasses\fI class\fR ?\fIpattern\fR?
|
||||
.VS 8.6
|
||||
.
|
||||
This subcommand returns a list of direct subclasses of class \fIclass\fR. If
|
||||
the optional \fIpattern\fR argument is present, it constrains the list of
|
||||
returned classes to those that match it according to the rules of
|
||||
\fBstring match\fR.
|
||||
.VE 8.6
|
||||
.TP
|
||||
\fBinfo class superclasses\fI class\fR
|
||||
.VS 8.6
|
||||
.
|
||||
This subcommand returns a list of direct superclasses of class \fIclass\fR in
|
||||
inheritance precedence order.
|
||||
.VE 8.6
|
||||
.TP
|
||||
\fBinfo class variables\fI class\fR
|
||||
.VS 8.6
|
||||
\fBinfo class variables\fI class\fR ?\fB\-private\fR?
|
||||
.
|
||||
This subcommand returns a list of all variables that have been declared for
|
||||
the class named \fIclass\fR (i.e. that are automatically present in the
|
||||
class's methods, constructor and destructor).
|
||||
.VS TIP500
|
||||
If the \fB\-private\fR option is specified, this lists the private variables
|
||||
declared instead.
|
||||
.VE TIP500
|
||||
.SS "OBJECT INTROSPECTION"
|
||||
.PP
|
||||
The following \fIsubcommand\fR values are supported by \fBinfo object\fR:
|
||||
.VE 8.6
|
||||
.TP
|
||||
\fBinfo object call\fI object method\fR
|
||||
.VS 8.6
|
||||
.
|
||||
Returns a description of the method implementations that are used to provide
|
||||
\fIobject\fR's implementation of \fImethod\fR. This consists of a list of
|
||||
lists of four elements, where each sublist consists of a word that describes
|
||||
the general type of method implementation (being one of \fBmethod\fR for an
|
||||
ordinary method, \fBfilter\fR for an applied filter, and \fBunknown\fR for a
|
||||
ordinary method, \fBfilter\fR for an applied filter,
|
||||
.VS TIP500
|
||||
\fBprivate\fR for a private method,
|
||||
.VE TIP500
|
||||
and \fBunknown\fR for a
|
||||
method that is invoked as part of unknown method handling), a word giving the
|
||||
name of the particular method invoked (which is always the same as
|
||||
\fImethod\fR for the \fBmethod\fR type, and
|
||||
@@ -550,128 +575,160 @@ implementation (see \fBinfo object methodtype\fR).
|
||||
.RS
|
||||
.PP
|
||||
Note that there is no inspection of whether the method implementations
|
||||
actually use \fBnext\fR to transfer control along the call chain.
|
||||
actually use \fBnext\fR to transfer control along the call chain,
|
||||
.VS TIP500
|
||||
and the call chains that this command files do not actually contain private
|
||||
methods.
|
||||
.VE TIP500
|
||||
.RE
|
||||
.VE 8.6
|
||||
.TP
|
||||
\fBinfo object class\fI object\fR ?\fIclassName\fR?
|
||||
.VS 8.6
|
||||
.
|
||||
If \fIclassName\fR is unspecified, this subcommand returns class of the
|
||||
\fIobject\fR object. If \fIclassName\fR is present, this subcommand returns a
|
||||
boolean value indicating whether the \fIobject\fR is of that class.
|
||||
.VE 8.6
|
||||
.TP
|
||||
\fBinfo object creationid\fI object\fR
|
||||
.VS TIP500
|
||||
Returns the unique creation identifier for the \fIobject\fR object. This
|
||||
creation identifier is unique to the object (within a Tcl interpreter) and
|
||||
cannot be controlled at object creation time or altered afterwards.
|
||||
.RS
|
||||
.PP
|
||||
\fIImplementation note:\fR the creation identifier is used to generate unique
|
||||
identifiers associated with the object, especially for private variables.
|
||||
.RE
|
||||
.VE TIP500
|
||||
.TP
|
||||
\fBinfo object definition\fI object method\fR
|
||||
.VS 8.6
|
||||
.
|
||||
This subcommand returns a description of the definition of the method named
|
||||
\fImethod\fR of object \fIobject\fR. The definition is described as a two
|
||||
element list; the first element is the list of arguments to the method in a
|
||||
form suitable for passing to another call to \fBproc\fR or a method definition,
|
||||
and the second element is the body of the method.
|
||||
.VE 8.6
|
||||
.TP
|
||||
\fBinfo object filters\fI object\fR
|
||||
.VS 8.6
|
||||
.
|
||||
This subcommand returns the list of filter methods set on the object.
|
||||
.VE 8.6
|
||||
.TP
|
||||
\fBinfo object forward\fI object method\fR
|
||||
.VS 8.6
|
||||
.
|
||||
This subcommand returns the argument list for the method forwarding called
|
||||
\fImethod\fR that is set on the object called \fIobject\fR.
|
||||
.VE 8.6
|
||||
.TP
|
||||
\fBinfo object isa\fI category object\fR ?\fIarg\fR?
|
||||
.VS 8.6
|
||||
.
|
||||
This subcommand tests whether an object belongs to a particular category,
|
||||
returning a boolean value that indicates whether the \fIobject\fR argument
|
||||
meets the criteria for the category. The supported categories are:
|
||||
.VE 8.6
|
||||
.RS
|
||||
.TP
|
||||
\fBinfo object isa class\fI object\fR
|
||||
.VS 8.6
|
||||
.
|
||||
This returns whether \fIobject\fR is a class (i.e. an instance of
|
||||
\fBoo::class\fR or one of its subclasses).
|
||||
.VE 8.6
|
||||
.TP
|
||||
\fBinfo object isa metaclass\fI object\fR
|
||||
.VS 8.6
|
||||
.
|
||||
This returns whether \fIobject\fR is a class that can manufacture classes
|
||||
(i.e. is \fBoo::class\fR or a subclass of it).
|
||||
.VE 8.6
|
||||
.TP
|
||||
\fBinfo object isa mixin\fI object class\fR
|
||||
.VS 8.6
|
||||
.
|
||||
This returns whether \fIclass\fR is directly mixed into \fIobject\fR.
|
||||
.VE 8.6
|
||||
.TP
|
||||
\fBinfo object isa object\fI object\fR
|
||||
.VS 8.6
|
||||
.
|
||||
This returns whether \fIobject\fR really is an object.
|
||||
.VE 8.6
|
||||
.TP
|
||||
\fBinfo object isa typeof\fI object class\fR
|
||||
.VS 8.6
|
||||
.
|
||||
This returns whether \fIclass\fR is the type of \fIobject\fR (i.e. whether
|
||||
\fIobject\fR is an instance of \fIclass\fR or one of its subclasses, whether
|
||||
direct or indirect).
|
||||
.RE
|
||||
.VE 8.6
|
||||
.TP
|
||||
\fBinfo object methods\fI object\fR ?\fIoption...\fR?
|
||||
.VS 8.6
|
||||
.
|
||||
This subcommand returns a list of all public (i.e. exported) methods of the
|
||||
object called \fIobject\fR. Any of the following \fIoption\fRs may be
|
||||
specified, controlling exactly which method names are returned:
|
||||
.RS
|
||||
.VE 8.6
|
||||
.TP
|
||||
\fB\-all\fR
|
||||
.VS 8.6
|
||||
If the \fB\-all\fR flag is given, the list of methods will include those
|
||||
.
|
||||
If the \fB\-all\fR flag is given,
|
||||
.VS TIP500
|
||||
and the \fB\-scope\fR flag is not given,
|
||||
.VE TIP500
|
||||
the list of methods will include those
|
||||
methods defined not just by the object, but also by the object's class and
|
||||
mixins, plus the superclasses of those classes.
|
||||
.VE 8.6
|
||||
.TP
|
||||
\fB\-private\fR
|
||||
.VS 8.6
|
||||
If the \fB\-private\fR flag is given, the list of methods will also include
|
||||
the private (i.e. non-exported) methods of the object (and classes, if
|
||||
.
|
||||
If the \fB\-private\fR flag is given,
|
||||
.VS TIP500
|
||||
and the \fB\-scope\fR flag is not given,
|
||||
.VE TIP500
|
||||
the list of methods will also include
|
||||
the non-exported methods of the object (and classes, if
|
||||
\fB\-all\fR is also given).
|
||||
.VS TIP500
|
||||
Note that this naming is an unfortunate clash with true private methods; this
|
||||
option name is retained for backward compatibility.
|
||||
.VE TIP500
|
||||
.TP
|
||||
\fB\-scope\fI scope\fR
|
||||
.VS TIP500
|
||||
Returns a list of all methods on \fIobject\fR that have the given visibility
|
||||
\fIscope\fR. When this option is supplied, both the \fB\-all\fR and
|
||||
\fB\-private\fR options are ignored. The valid values for \fIscope\fR are:
|
||||
.RS
|
||||
.IP \fBpublic\fR 3
|
||||
Only methods with \fIpublic\fR scope (i.e., callable from anywhere) are to be
|
||||
returned.
|
||||
.IP \fBunexported\fR 3
|
||||
Only methods with \fIunexported\fR scope (i.e., only callable via \fBmy\fR) are to
|
||||
be returned.
|
||||
.IP \fBprivate\fR 3
|
||||
Only methods with \fIprivate\fR scope (i.e., only callable from within this object's
|
||||
instance methods) are to be returned.
|
||||
.RE
|
||||
.VE TIP500
|
||||
.RE
|
||||
.VE 8.6
|
||||
.TP
|
||||
\fBinfo object methodtype\fI object method\fR
|
||||
.VS 8.6
|
||||
.
|
||||
This subcommand returns a description of the type of implementation used for
|
||||
the method named \fImethod\fR of object \fIobject\fR. When the result is
|
||||
\fBmethod\fR, further information can be discovered with \fBinfo object
|
||||
definition\fR, and when the result is \fBforward\fR, further information can
|
||||
be discovered with \fBinfo object forward\fR.
|
||||
.VE 8.6
|
||||
.TP
|
||||
\fBinfo object mixins\fI object\fR
|
||||
.VS 8.6
|
||||
.
|
||||
This subcommand returns a list of all classes that have been mixed into the
|
||||
object named \fIobject\fR.
|
||||
.VE 8.6
|
||||
.TP
|
||||
\fBinfo object namespace\fI object\fR
|
||||
.VS 8.6
|
||||
.
|
||||
This subcommand returns the name of the internal namespace of the object named
|
||||
\fIobject\fR.
|
||||
.VE 8.6
|
||||
.TP
|
||||
\fBinfo object variables\fI object\fR
|
||||
.VS 8.6
|
||||
\fBinfo object variables\fI object\fRR ?\fB\-private\fR?
|
||||
.
|
||||
This subcommand returns a list of all variables that have been declared for
|
||||
the object named \fIobject\fR (i.e. that are automatically present in the
|
||||
object's methods).
|
||||
.VE 8.6
|
||||
.VS TIP500
|
||||
If the \fB\-private\fR option is specified, this lists the private variables
|
||||
declared instead.
|
||||
.VE TIP500
|
||||
.TP
|
||||
\fBinfo object vars\fI object\fR ?\fIpattern\fR?
|
||||
.VS 8.6
|
||||
.
|
||||
This subcommand returns a list of all variables in the private namespace of
|
||||
the object named \fIobject\fR. If the optional \fIpattern\fR argument is
|
||||
given, it is a filter (in the syntax of a \fBstring match\fR glob pattern)
|
||||
@@ -680,7 +737,6 @@ from the list returned by \fBinfo object variables\fR; that can include
|
||||
variables that are currently unset, whereas this can include variables that
|
||||
are not automatically included by any of \fIobject\fR's methods (or those of
|
||||
its class, superclasses or mixins).
|
||||
.VE 8.6
|
||||
.SH EXAMPLES
|
||||
.PP
|
||||
This command prints out a procedure suitable for saving in a Tcl
|
||||
@@ -703,7 +759,6 @@ proc printProc {procName} {
|
||||
}
|
||||
.CE
|
||||
.SS "EXAMPLES WITH OBJECTS"
|
||||
.VS 8.6
|
||||
.PP
|
||||
Every object necessarily knows what its class is; this information is
|
||||
trivially extractable through introspection:
|
||||
@@ -724,8 +779,10 @@ method and get how it is defined. This procedure illustrates how:
|
||||
proc getDef {obj method} {
|
||||
foreach inf [\fBinfo object call\fR $obj $method] {
|
||||
lassign $inf calltype name locus methodtype
|
||||
|
||||
# Assume no forwards or filters, and hence no $calltype
|
||||
# or $methodtype checks...
|
||||
|
||||
if {$locus eq "object"} {
|
||||
return [\fBinfo object definition\fR $obj $name]
|
||||
} else {
|
||||
@@ -748,7 +805,9 @@ proc getDef {obj method} {
|
||||
# Assume no forwards
|
||||
return [\fBinfo object definition\fR $obj $method]
|
||||
}
|
||||
|
||||
set cls [\fBinfo object class\fR $obj]
|
||||
|
||||
while {$method ni [\fBinfo class methods\fR $cls]} {
|
||||
# Assume the simple case
|
||||
set cls [lindex [\fBinfo class superclass\fR $cls] 0]
|
||||
@@ -756,22 +815,17 @@ proc getDef {obj method} {
|
||||
error "no definition for $method"
|
||||
}
|
||||
}
|
||||
|
||||
# Assume no forwards
|
||||
return [\fBinfo class definition\fR $cls $method]
|
||||
}
|
||||
.CE
|
||||
.VE 8.6
|
||||
.SH "SEE ALSO"
|
||||
.VS 8.6
|
||||
global(n), oo::class(n), oo::define(n), oo::object(n), proc(n), self(n),
|
||||
.VE 8.6
|
||||
tcl_library(n), tcl_patchLevel(n), tcl_version(n)
|
||||
.SH KEYWORDS
|
||||
command, information, interpreter, introspection, level, namespace,
|
||||
.VS 8.6
|
||||
object,
|
||||
.VE 8.6
|
||||
procedure, variable
|
||||
object, procedure, variable
|
||||
'\" Local Variables:
|
||||
'\" mode: nroff
|
||||
'\" fill-column: 78
|
||||
|
||||
@@ -19,13 +19,18 @@ package require TclOO
|
||||
.BE
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
The \fBmy\fR command is used to allow methods of objects to invoke any method
|
||||
The \fBmy\fR command is used to allow methods of objects to invoke methods
|
||||
of the object (or its class). In particular, the set of valid values for
|
||||
\fImethodName\fR is the set of all methods supported by an object and its
|
||||
superclasses, including those that are not exported. The object upon which the
|
||||
method is invoked is always the one that is the current context of the method
|
||||
(i.e. the object that is returned by \fBself object\fR) from which the
|
||||
\fBmy\fR command is invoked.
|
||||
superclasses, including those that are not exported
|
||||
.VS TIP500
|
||||
and private methods of the object or class when used within another method
|
||||
defined by that object or class.
|
||||
.VE TIP500
|
||||
The object upon which the method is invoked is the one that owns the namespace
|
||||
that the \fBmy\fR command is contained in initially (\fBNB:\fR the link
|
||||
remains if the command is renamed), which is the currently invoked object by
|
||||
default.
|
||||
.PP
|
||||
Each object has its own \fBmy\fR command, contained in its instance namespace.
|
||||
.SH EXAMPLES
|
||||
@@ -40,16 +45,38 @@ oo::class create c {
|
||||
puts [incr counter]
|
||||
}
|
||||
}
|
||||
|
||||
c create o
|
||||
o count \fI\(-> prints "1"\fR
|
||||
o count \fI\(-> prints "2"\fR
|
||||
o count \fI\(-> prints "3"\fR
|
||||
.CE
|
||||
.PP
|
||||
This example shows how you can use \fBmy\fR to make callbacks to private
|
||||
methods from outside the object (from a \fBtrace\fR), using
|
||||
\fBnamespace code\fR to enter the correct context:
|
||||
.PP
|
||||
.CS
|
||||
oo::class create HasCallback {
|
||||
method makeCallback {} {
|
||||
return [namespace code {
|
||||
\fBmy\fR Callback
|
||||
}]
|
||||
}
|
||||
|
||||
method Callback {args} {
|
||||
puts "callback: $args"
|
||||
}
|
||||
}
|
||||
|
||||
set o [HasCallback new]
|
||||
trace add variable xyz write [$o makeCallback]
|
||||
set xyz "called" \fI\(-> prints "callback: xyz {} write"\fR
|
||||
.CE
|
||||
.SH "SEE ALSO"
|
||||
next(n), oo::object(n), self(n)
|
||||
.SH KEYWORDS
|
||||
method, method visibility, object, private method, public method
|
||||
|
||||
.\" Local variables:
|
||||
.\" mode: nroff
|
||||
.\" fill-column: 78
|
||||
|
||||
@@ -112,6 +112,7 @@ oo::class create theSuperclass {
|
||||
puts "in the superclass, args = $args"
|
||||
}
|
||||
}
|
||||
|
||||
oo::class create theSubclass {
|
||||
superclass theSuperclass
|
||||
method example {args} {
|
||||
@@ -121,6 +122,7 @@ oo::class create theSubclass {
|
||||
puts "after chaining from subclass"
|
||||
}
|
||||
}
|
||||
|
||||
theSubclass create obj
|
||||
oo::objdefine obj method example args {
|
||||
puts "per-object method, args = $args"
|
||||
@@ -167,6 +169,7 @@ oo::class create cache {
|
||||
\fI# Compute value, insert into cache, and return it\fR
|
||||
return [set ValueCache($key) [\fBnext\fR {*}$args]]
|
||||
}
|
||||
|
||||
method flushCache {} {
|
||||
my variable ValueCache
|
||||
unset ValueCache
|
||||
@@ -178,10 +181,12 @@ oo::class create cache {
|
||||
oo::object create demo
|
||||
oo::objdefine demo {
|
||||
mixin cache
|
||||
|
||||
method compute {a b c} {
|
||||
after 3000 \fI;# Simulate deep thought\fR
|
||||
return [expr {$a + $b * $c}]
|
||||
}
|
||||
|
||||
method compute2 {a b c} {
|
||||
after 3000 \fI;# Simulate deep thought\fR
|
||||
return [expr {$a * $b + $c}]
|
||||
|
||||
+131
@@ -0,0 +1,131 @@
|
||||
'\"
|
||||
'\" Copyright (c) 2017 Frederic Bonnet.
|
||||
'\"
|
||||
'\" See the file "license.terms" for information on usage and redistribution
|
||||
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
'\"
|
||||
.TH process n 8.7 Tcl "Tcl Built-In Commands"
|
||||
.so man.macros
|
||||
.BS
|
||||
'\" Note: do not modify the .SH NAME line immediately below!
|
||||
.SH NAME
|
||||
tcl::process \- Subprocess management
|
||||
.SH SYNOPSIS
|
||||
\fB::tcl::process \fIoption \fR?\fIarg arg ...\fR?
|
||||
.BE
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
This command provides a way to manage subprocesses created by the \fBopen\fR
|
||||
and \fBexec\fR commands. The legal \fIoptions\fR (which may be abbreviated) are:
|
||||
.TP
|
||||
\fB::tcl::process list\fR
|
||||
.
|
||||
Returns the list of subprocess PIDs.
|
||||
.TP
|
||||
\fB::tcl::process status\fR ?\fIswitches\fR? ?\fIpids\fR?
|
||||
.
|
||||
Returns a dictionary mapping subprocess PIDs to their respective status. If
|
||||
\fIpids\fR is specified as a list of PIDs then the command only returns the
|
||||
status of the matching subprocesses if they exist, and raises an error
|
||||
otherwise. For active processes, the status is an empty value. For terminated
|
||||
processes, the status is a list with the following format:
|
||||
.QW "{code ?\fImsg errorCode\fR?}" ,
|
||||
where:
|
||||
.RS
|
||||
.TP
|
||||
\fBcode\fR\0
|
||||
.
|
||||
is a standard Tcl return code,
|
||||
.TP
|
||||
\fBmsg\fR\0
|
||||
.
|
||||
is the human-readable error message,
|
||||
.TP
|
||||
\fBerrorCode\fR\0
|
||||
.
|
||||
uses the same format as the \fBerrorCode\fR global variable
|
||||
.RE
|
||||
Note that \fBmsg\fR and \fBerrorCode\fR are only present for abnormally
|
||||
terminated processes (i.e. those where \fBcode\fR is nonzero). Under the hood
|
||||
this command calls \fBTcl_WaitPid\fR with the \fBWNOHANG\fR flag set for
|
||||
non-blocking behavior, unless the \fB\-wait\fR switch is set (see below).
|
||||
.RS
|
||||
.PP
|
||||
Additionally, \fB::tcl::process status\fR accepts the following switches:
|
||||
.TP
|
||||
\fB\-wait\fR\0
|
||||
.
|
||||
By default the command returns immediately (the underlying \fBTcl_WaitPid\fR is
|
||||
called with the \fBWNOHANG\fR flag set) unless this switch is set. If \fBpids\fR
|
||||
is specified as a list of PIDs then the command waits until the status of the
|
||||
matching subprocesses are available. If \fBpids\fR is not specified then it
|
||||
waits for all known subprocesses.
|
||||
.TP
|
||||
\fB\-\|\-\fR
|
||||
.
|
||||
Marks the end of switches. The argument following this one will
|
||||
be treated as the first \fIarg\fR even if it starts with a \fB\-\fR.
|
||||
.RE
|
||||
.TP
|
||||
\fB::tcl::process purge ?\fIpids\fR?
|
||||
.
|
||||
Cleans up all data associated with terminated subprocesses. If \fBpids\fR is
|
||||
specified as a list of PIDs then the command only cleanup data for the matching
|
||||
subprocesses if they exist, and raises an error otherwise. If the process is
|
||||
still active then it does nothing.
|
||||
.TP
|
||||
\fB::tcl::process autopurge ?\fIflag\fR?
|
||||
.
|
||||
Automatic purge facility. If \fBflag\fR is specified as a boolean value then it
|
||||
activates or deactivate autopurge. In all cases it returns the current status as
|
||||
a boolean value. When autopurge is active, \fBTcl_ReapDetachedProcs\fR is called
|
||||
each time the exec command is executed or a pipe channel created by open is
|
||||
closed. When autopurge is inactive, \fB::tcl::process\fR purge must be called
|
||||
explicitly. By default autopurge is active.
|
||||
.RE
|
||||
.SH "EXAMPLES"
|
||||
.PP
|
||||
.CS
|
||||
\fB::tcl::process autopurge\fR
|
||||
\fI\(-> true\fR
|
||||
\fB::tcl::process autopurge\fR false
|
||||
\fI\(-> false\fR
|
||||
|
||||
set pid1 [exec command1 a b c | command2 d e f &]
|
||||
\fI\(-> 123 456\fR
|
||||
set chan [open "|command1 a b c | command2 d e f"]
|
||||
\fI\(-> file123\fR
|
||||
set pid2 [pid $chan]
|
||||
\fI\(-> 789 1011\fR
|
||||
|
||||
\fB::tcl::process list\fR
|
||||
\fI\(-> 123 456 789 1011\fR
|
||||
|
||||
\fB::tcl::process status\fR
|
||||
\fI\(-> 123 0 456 {1 "child killed: write on pipe with no readers" {CHILDKILLED 456 SIGPIPE "write on pipe with no readers"}} 789 {1 "child suspended: background tty read" {CHILDSUSP 789 SIGTTIN "background tty read"}} 1011 {}\fR
|
||||
|
||||
\fB::tcl::process status\fR 123
|
||||
\fI\(-> 123 0\fR
|
||||
|
||||
\fB::tcl::process status\fR 1011
|
||||
\fI\(-> 1011 {}\fR
|
||||
|
||||
\fB::tcl::process status\fR -wait
|
||||
\fI\(-> 123 0 456 {1 "child killed: write on pipe with no readers" {CHILDKILLED 456 SIGPIPE "write on pipe with no readers"}} 789 {1 "child suspended: background tty read" {CHILDSUSP 789 SIGTTIN "background tty read"}} 1011 {1 "child process exited abnormally" {CHILDSTATUS 1011 -1}}\fR
|
||||
|
||||
\fB::tcl::process status\fR 1011
|
||||
\fI\(-> 1011 {1 "child process exited abnormally" {CHILDSTATUS 1011 -1}}\fR
|
||||
|
||||
\fB::tcl::process purge\fR
|
||||
exec command1 1 2 3 &
|
||||
\fI\(-> 1213\fR
|
||||
\fB::tcl::process list\fR
|
||||
\fI\(-> 1213\fR
|
||||
.CE
|
||||
.SH "SEE ALSO"
|
||||
exec(n), open(n), Tcl_DetachPids(3), Tcl_WaitPid(3), Tcl_ReapDetachedProcs(3)
|
||||
.SH "KEYWORDS"
|
||||
background, child, detach, process, wait
|
||||
'\" Local Variables:
|
||||
'\" mode: nroff
|
||||
'\" End:
|
||||
+6
-1
@@ -32,7 +32,12 @@ implement the current call chain. The first element is the same as would be
|
||||
reported by \fBinfo object\fR \fBcall\fR for the current method (except that this
|
||||
also reports useful values from within constructors and destructors, whose
|
||||
names are reported as \fB<constructor>\fR and \fB<destructor>\fR
|
||||
respectively), and the second element is an index into the first element's
|
||||
respectively,
|
||||
.VS TIP500
|
||||
and for private methods, which are described as being \fBprivate\fR instead of
|
||||
being a \fBmethod\fR),
|
||||
.VE TIP500
|
||||
and the second element is an index into the first element's
|
||||
list that indicates which actual implementation is currently executing (the
|
||||
first implementation to execute is always at index 0).
|
||||
.TP
|
||||
|
||||
@@ -2330,6 +2330,12 @@ declare 631 {
|
||||
ClientData callbackData)
|
||||
}
|
||||
|
||||
# TIP #312
|
||||
declare 633 {
|
||||
int Tcl_LinkArray(Tcl_Interp *interp, const char *varName, char *addr,
|
||||
int type, size_t size)
|
||||
}
|
||||
|
||||
# ----- BASELINE -- FOR -- 8.7.0 ----- #
|
||||
|
||||
|
||||
|
||||
+77
-48
@@ -89,6 +89,10 @@ extern "C" {
|
||||
# define JOIN(a,b) JOIN1(a,b)
|
||||
# define JOIN1(a,b) a##b
|
||||
#endif
|
||||
|
||||
#ifndef TCL_THREADS
|
||||
# define TCL_THREADS 1
|
||||
#endif
|
||||
#endif /* !TCL_NO_DEPRECATED */
|
||||
|
||||
/*
|
||||
@@ -103,15 +107,10 @@ extern "C" {
|
||||
#ifndef RC_INVOKED
|
||||
|
||||
/*
|
||||
* Special macro to define mutexes, that doesn't do anything if we are not
|
||||
* using threads.
|
||||
* Special macro to define mutexes.
|
||||
*/
|
||||
|
||||
#ifdef TCL_THREADS
|
||||
#define TCL_DECLARE_MUTEX(name) static Tcl_Mutex name;
|
||||
#else
|
||||
#define TCL_DECLARE_MUTEX(name)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Tcl's public routine Tcl_FSSeek() uses the values SEEK_SET, SEEK_CUR, and
|
||||
@@ -1083,30 +1082,76 @@ typedef struct Tcl_DString {
|
||||
# define TCL_PARSE_PART1 0x400
|
||||
#endif /* !TCL_NO_DEPRECATED */
|
||||
|
||||
/*
|
||||
* Types for Tcl_GetValue():
|
||||
*/
|
||||
|
||||
#define TCL_TYPE_I(type) (0x100 | (int)sizeof(type)) /* signed integer */
|
||||
#define TCL_TYPE_U(type) (0x200 | (int)sizeof(type)) /* unsigned integer */
|
||||
#define TCL_TYPE_D(type) (0x300 | (int)sizeof(type)) /* float/double/long double */
|
||||
|
||||
/*
|
||||
* Types for linked variables:
|
||||
*/
|
||||
|
||||
#define TCL_LINK_INT 1
|
||||
#define TCL_LINK_DOUBLE 2
|
||||
#define TCL_LINK_BOOLEAN 3
|
||||
#define TCL_LINK_STRING 4
|
||||
#define TCL_LINK_WIDE_INT 5
|
||||
#define TCL_LINK_CHAR 6
|
||||
#define TCL_LINK_UCHAR 7
|
||||
#define TCL_LINK_SHORT 8
|
||||
#define TCL_LINK_USHORT 9
|
||||
#define TCL_LINK_UINT 10
|
||||
#define TCL_TYPE_X(type) (0x400 | (int)sizeof(type)) /* Hexadecimal */
|
||||
#define TCL_TYPE_B(type) (0x500 | (int)sizeof(type)) /* Boolean */
|
||||
#define TCL_TYPE_C(type) (0xa00 | (int)sizeof(type)) /* Complex */
|
||||
|
||||
#if !defined(TCL_NO_DEPRECATED) && !defined(BUILD_tcl)
|
||||
/* Here are the legacy values 1-14, will be removed in Tcl 9.0 */
|
||||
#define TCL_LINK_INT 1 /* 32bit int -> int */
|
||||
#define TCL_LINK_DOUBLE 2 /* 64bit double -> double */
|
||||
#define TCL_LINK_BOOLEAN 3 /* tcl boolean -> int */
|
||||
#define TCL_LINK_STRING 4 /* 8bit chars -> ckalloc'd string */
|
||||
#define TCL_LINK_WIDE_INT 5 /* 64bit int -> Tcl_WideInt */
|
||||
#define TCL_LINK_CHAR 6 /* 8bit int -> char */
|
||||
#define TCL_LINK_UCHAR 7 /* 8bit uint -> unsigned char */
|
||||
#define TCL_LINK_SHORT 8 /* 16bit int -> short */
|
||||
#define TCL_LINK_USHORT 9 /* 16bit int -> unsigned short */
|
||||
#define TCL_LINK_UINT 10 /* 32bit uint -> int */
|
||||
#if defined(TCL_WIDE_INT_IS_LONG) || defined(_WIN32) || defined(__CYGWIN__)
|
||||
#define TCL_LINK_LONG ((sizeof(long) != sizeof(int)) ? TCL_LINK_WIDE_INT : TCL_LINK_INT)
|
||||
#define TCL_LINK_ULONG ((sizeof(long) != sizeof(int)) ? TCL_LINK_WIDE_UINT : TCL_LINK_UINT)
|
||||
#define TCL_LINK_LONG ((sizeof(long) != sizeof(int)) ? TCL_LINK_WIDE_INT : TCL_LINK_INT)
|
||||
#define TCL_LINK_ULONG ((sizeof(long) != sizeof(int)) ? TCL_LINK_WIDE_UINT : TCL_LINK_UINT)
|
||||
#else
|
||||
#define TCL_LINK_LONG 11
|
||||
#define TCL_LINK_ULONG 12
|
||||
#define TCL_LINK_LONG 11 /* long -> long */
|
||||
#define TCL_LINK_ULONG 12 /* unsigned long -> unsigned long */
|
||||
#endif
|
||||
#define TCL_LINK_FLOAT 13
|
||||
#define TCL_LINK_WIDE_UINT 14
|
||||
#define TCL_LINK_READ_ONLY 0x80
|
||||
#define TCL_LINK_FLOAT 13 /* 32bit float -> double */
|
||||
#define TCL_LINK_WIDE_UINT 14 /* 64bit uint -> wide TODO bignum */
|
||||
#else
|
||||
|
||||
/* These are the new values, available starting with Tcl 8.7 */
|
||||
#define TCL_LINK_INT TCL_TYPE_I(int) /* 32bit int -> int */
|
||||
#define TCL_LINK_DOUBLE TCL_TYPE_D(double) /* 64bit double -> double */
|
||||
#define TCL_LINK_BOOLEAN TCL_TYPE_B(int) /* tcl boolean -> int */
|
||||
#define TCL_LINK_STRING 0 /* 8bit chars -> ckalloc'd string */
|
||||
#define TCL_LINK_WIDE_INT TCL_TYPE_I(Tcl_WideInt) /* 64bit int -> Tcl_WideInt */
|
||||
#define TCL_LINK_CHAR TCL_TYPE_I(char) /* 8bit int -> char */
|
||||
#define TCL_LINK_UCHAR TCL_TYPE_U(char) /* 8bit uint -> unsigned char */
|
||||
#define TCL_LINK_SHORT TCL_TYPE_I(short) /* 16bit int -> short */
|
||||
#define TCL_LINK_USHORT TCL_TYPE_U(short) /* 16bit int -> unsigned short */
|
||||
#define TCL_LINK_UINT TCL_TYPE_U(int) /* 32bit uint -> int */
|
||||
#define TCL_LINK_LONG TCL_TYPE_I(long)
|
||||
#define TCL_LINK_ULONG TCL_TYPE_U(long)
|
||||
#define TCL_LINK_FLOAT TCL_TYPE_D(float) /* 32bit float -> double */
|
||||
#define TCL_LINK_WIDE_UINT TCL_TYPE_U(Tcl_WideInt) /* 64bit uint -> wide TODO bignum */
|
||||
#endif
|
||||
|
||||
#define TCL_LINK_CHARS 0x901 /* 8bit chars -> null terminated string
|
||||
last char will always set to \0 */
|
||||
#define TCL_LINK_BINARY 0x601 /* fixed size binary byte array */
|
||||
#define TCL_LINK_BITARRAY8 0x701 /* 8bit uint -> string, 8 chars 0|1 */
|
||||
#define TCL_LINK_BITARRAY16 0x702 /* 16bit uint -> string, 16 chars 0|1 */
|
||||
#define TCL_LINK_BITARRAY32 0x704 /* 32bit uint -> string, 32 chars 0|1 */
|
||||
#define TCL_LINK_BITARRAY64 0x708 /* 64bit uint -> string, 64 chars 0|1 */
|
||||
#define TCL_LINK_BIT8 0x801 /* bit in 8bit uint -> int (0|1) */
|
||||
#define TCL_LINK_BIT16 0x802 /* bit in 16bit uint -> int (0|1) */
|
||||
#define TCL_LINK_BIT32 0x804 /* bit in 32bit uint -> int (0|1) */
|
||||
#define TCL_LINK_BIT64 0x808 /* bit in 64bit uint -> int (0|1) */
|
||||
#define TCL_LINK_S5FLOAT 0x904 /* Siemens S5 32bit uint -> double */
|
||||
#define TCL_LINK_S5TIME 0x902 /* Siemens S5 16bit uint -> double */
|
||||
#define TCL_LINK_READ_ONLY 0x80
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------------
|
||||
@@ -2146,9 +2191,9 @@ typedef struct Tcl_EncodingType {
|
||||
|
||||
/*
|
||||
* The maximum number of bytes that are necessary to represent a single
|
||||
* Unicode character in UTF-8. The valid values should be 3, 4 or 6
|
||||
* (or perhaps 1 if we want to support a non-unicode enabled core). If 3 or
|
||||
* 4, then Tcl_UniChar must be 2-bytes in size (UCS-2) (the default). If 6,
|
||||
* Unicode character in UTF-8. The valid values are 4 and 6
|
||||
* (or perhaps 1 if we want to support a non-unicode enabled core). If 4,
|
||||
* then Tcl_UniChar must be 2-bytes in size (UCS-2) (the default). If 6,
|
||||
* then Tcl_UniChar must be 4-bytes in size (UCS-4). At this time UCS-2 mode
|
||||
* is the default and recommended mode. UCS-4 is experimental and not
|
||||
* recommended. It works for the core, but most extensions expect UCS-2.
|
||||
@@ -2361,6 +2406,11 @@ const char * Tcl_InitStubs(Tcl_Interp *interp, const char *version,
|
||||
int exact, int magic);
|
||||
const char * TclTomMathInitializeStubs(Tcl_Interp *interp,
|
||||
const char *version, int epoch, int revision);
|
||||
#if defined(_WIN32)
|
||||
TCL_NORETURN void Tcl_ConsolePanic(const char *format, ...);
|
||||
#else
|
||||
# define Tcl_ConsolePanic ((Tcl_PanicProc *)0)
|
||||
#endif
|
||||
|
||||
#ifdef USE_TCL_STUBS
|
||||
#if TCL_RELEASE_LEVEL == TCL_FINAL_RELEASE
|
||||
@@ -2392,7 +2442,7 @@ const char * TclTomMathInitializeStubs(Tcl_Interp *interp,
|
||||
*/
|
||||
|
||||
#define Tcl_Main(argc, argv, proc) Tcl_MainEx(argc, argv, proc, \
|
||||
((Tcl_CreateInterp)()))
|
||||
((Tcl_SetPanicProc(Tcl_ConsolePanic), Tcl_CreateInterp)()))
|
||||
EXTERN void Tcl_MainEx(int argc, char **argv,
|
||||
Tcl_AppInitProc *appInitProc, Tcl_Interp *interp);
|
||||
EXTERN const char * Tcl_PkgInitStubsCheck(Tcl_Interp *interp,
|
||||
@@ -2550,27 +2600,6 @@ EXTERN void Tcl_GetMemoryInfo(Tcl_DString *dsPtr);
|
||||
#define Tcl_CreateHashEntry(tablePtr, key, newPtr) \
|
||||
(*((tablePtr)->createProc))(tablePtr, (const char *)(key), newPtr)
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------------
|
||||
* Macros that eliminate the overhead of the thread synchronization functions
|
||||
* when compiling without thread support.
|
||||
*/
|
||||
|
||||
#ifndef TCL_THREADS
|
||||
#undef Tcl_MutexLock
|
||||
#define Tcl_MutexLock(mutexPtr)
|
||||
#undef Tcl_MutexUnlock
|
||||
#define Tcl_MutexUnlock(mutexPtr)
|
||||
#undef Tcl_MutexFinalize
|
||||
#define Tcl_MutexFinalize(mutexPtr)
|
||||
#undef Tcl_ConditionNotify
|
||||
#define Tcl_ConditionNotify(condPtr)
|
||||
#undef Tcl_ConditionWait
|
||||
#define Tcl_ConditionWait(condPtr, mutexPtr, timePtr)
|
||||
#undef Tcl_ConditionFinalize
|
||||
#define Tcl_ConditionFinalize(condPtr)
|
||||
#endif /* TCL_THREADS */
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------------
|
||||
* Deprecated Tcl functions:
|
||||
|
||||
+3
-3
@@ -22,7 +22,7 @@
|
||||
*/
|
||||
|
||||
#include "tclInt.h"
|
||||
#if !defined(TCL_THREADS) || !defined(USE_THREAD_ALLOC)
|
||||
#if !TCL_THREADS || !defined(USE_THREAD_ALLOC)
|
||||
|
||||
#if USE_TCLALLOC
|
||||
|
||||
@@ -121,7 +121,7 @@ static struct block bigBlocks={ /* Big blocks aren't suballocated. */
|
||||
* variable.
|
||||
*/
|
||||
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
static Tcl_Mutex *allocMutexPtr;
|
||||
#endif
|
||||
static int allocInit = 0;
|
||||
@@ -171,7 +171,7 @@ TclInitAlloc(void)
|
||||
{
|
||||
if (!allocInit) {
|
||||
allocInit = 1;
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
allocMutexPtr = Tcl_GetAllocMutex();
|
||||
#endif
|
||||
}
|
||||
|
||||
+37
-29
@@ -749,7 +749,7 @@ Tcl_CreateInterp(void)
|
||||
* cache was already initialised by the call to alloc the interp struct.
|
||||
*/
|
||||
|
||||
#if defined(TCL_THREADS) && defined(USE_THREAD_ALLOC)
|
||||
#if TCL_THREADS && defined(USE_THREAD_ALLOC)
|
||||
iPtr->allocCache = TclpGetAllocCache();
|
||||
#else
|
||||
iPtr->allocCache = NULL;
|
||||
@@ -964,7 +964,7 @@ Tcl_CreateInterp(void)
|
||||
#endif /* !TCL_NO_DEPRECATED */
|
||||
TclpSetVariables(interp);
|
||||
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
/*
|
||||
* The existence of the "threaded" element of the tcl_platform array
|
||||
* indicates that this particular Tcl shell has been compiled with threads
|
||||
@@ -2295,30 +2295,33 @@ Tcl_CreateObjCommand(
|
||||
}
|
||||
|
||||
Tcl_Command
|
||||
TclCreateObjCommandInNs (
|
||||
TclCreateObjCommandInNs(
|
||||
Tcl_Interp *interp,
|
||||
const char *cmdName, /* Name of command, without any namespace components */
|
||||
const char *cmdName, /* Name of command, without any namespace
|
||||
* components. */
|
||||
Tcl_Namespace *namespace, /* The namespace to create the command in */
|
||||
Tcl_ObjCmdProc *proc, /* Object-based function to associate with
|
||||
* name. */
|
||||
ClientData clientData, /* Arbitrary value to pass to object
|
||||
* function. */
|
||||
Tcl_CmdDeleteProc *deleteProc
|
||||
Tcl_CmdDeleteProc *deleteProc)
|
||||
/* If not NULL, gives a function to call when
|
||||
* this command is deleted. */
|
||||
) {
|
||||
{
|
||||
int deleted = 0, isNew = 0;
|
||||
Command *cmdPtr;
|
||||
ImportRef *oldRefPtr = NULL;
|
||||
ImportedCmdData *dataPtr;
|
||||
Tcl_HashEntry *hPtr;
|
||||
Namespace *nsPtr = (Namespace *) namespace;
|
||||
|
||||
/*
|
||||
* If the command name we seek to create already exists, we need to
|
||||
* delete that first. That can be tricky in the presence of traces.
|
||||
* Loop until we no longer find an existing command in the way, or
|
||||
* until we've deleted one command and that didn't finish the job.
|
||||
* If the command name we seek to create already exists, we need to delete
|
||||
* that first. That can be tricky in the presence of traces. Loop until we
|
||||
* no longer find an existing command in the way, or until we've deleted
|
||||
* one command and that didn't finish the job.
|
||||
*/
|
||||
|
||||
while (1) {
|
||||
hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, cmdName, &isNew);
|
||||
|
||||
@@ -2330,16 +2333,18 @@ TclCreateObjCommandInNs (
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* An existing command conflicts. Try to delete it.
|
||||
*/
|
||||
|
||||
/* An existing command conflicts. Try to delete it.. */
|
||||
cmdPtr = Tcl_GetHashValue(hPtr);
|
||||
|
||||
/*
|
||||
* [***] This is wrong. See Tcl Bug a16752c252.
|
||||
* However, this buggy behavior is kept under particular
|
||||
* circumstances to accommodate deployed binaries of the
|
||||
* "tclcompiler" program. http://sourceforge.net/projects/tclpro/
|
||||
* that crash if the bug is fixed.
|
||||
* [***] This is wrong. See Tcl Bug a16752c252. However, this buggy
|
||||
* behavior is kept under particular circumstances to accommodate
|
||||
* deployed binaries of the "tclcompiler" program
|
||||
* http://sourceforge.net/projects/tclpro/
|
||||
* that crash if the bug is fixed.
|
||||
*/
|
||||
|
||||
if (cmdPtr->objProc == TclInvokeStringCommand
|
||||
@@ -2363,12 +2368,15 @@ TclCreateObjCommandInNs (
|
||||
cmdPtr->flags |= CMD_REDEF_IN_PROGRESS;
|
||||
}
|
||||
|
||||
/* Make sure namespace doesn't get deallocated. */
|
||||
/*
|
||||
* Make sure namespace doesn't get deallocated.
|
||||
*/
|
||||
|
||||
cmdPtr->nsPtr->refCount++;
|
||||
|
||||
Tcl_DeleteCommandFromToken(interp, (Tcl_Command) cmdPtr);
|
||||
nsPtr = (Namespace *) TclEnsureNamespace(interp,
|
||||
(Tcl_Namespace *)cmdPtr->nsPtr);
|
||||
(Tcl_Namespace *) cmdPtr->nsPtr);
|
||||
TclNsDecrRefCount(cmdPtr->nsPtr);
|
||||
|
||||
if (cmdPtr->flags & CMD_REDEF_IN_PROGRESS) {
|
||||
@@ -2380,9 +2388,9 @@ TclCreateObjCommandInNs (
|
||||
}
|
||||
if (!isNew) {
|
||||
/*
|
||||
* If the deletion callback recreated the command, just throw away
|
||||
* the new command (if we try to delete it again, we could get
|
||||
* stuck in an infinite loop).
|
||||
* If the deletion callback recreated the command, just throw away the
|
||||
* new command (if we try to delete it again, we could get stuck in an
|
||||
* infinite loop).
|
||||
*/
|
||||
|
||||
ckfree(Tcl_GetHashValue(hPtr));
|
||||
@@ -2437,6 +2445,7 @@ TclCreateObjCommandInNs (
|
||||
cmdPtr->importRefPtr = oldRefPtr;
|
||||
while (oldRefPtr != NULL) {
|
||||
Command *refCmdPtr = oldRefPtr->importedCmdPtr;
|
||||
|
||||
dataPtr = refCmdPtr->objClientData;
|
||||
dataPtr->realCmdPtr = cmdPtr;
|
||||
oldRefPtr = oldRefPtr->nextPtr;
|
||||
@@ -8276,23 +8285,26 @@ Tcl_NRCreateCommand(
|
||||
* this command is deleted. */
|
||||
{
|
||||
Command *cmdPtr = (Command *)
|
||||
Tcl_CreateObjCommand(interp,cmdName,proc,clientData,deleteProc);
|
||||
Tcl_CreateObjCommand(interp, cmdName, proc, clientData,
|
||||
deleteProc);
|
||||
|
||||
cmdPtr->nreProc = nreProc;
|
||||
return (Tcl_Command) cmdPtr;
|
||||
}
|
||||
|
||||
Tcl_Command
|
||||
TclNRCreateCommandInNs (
|
||||
TclNRCreateCommandInNs(
|
||||
Tcl_Interp *interp,
|
||||
const char *cmdName,
|
||||
Tcl_Namespace *nsPtr,
|
||||
Tcl_ObjCmdProc *proc,
|
||||
Tcl_ObjCmdProc *nreProc,
|
||||
ClientData clientData,
|
||||
Tcl_CmdDeleteProc *deleteProc) {
|
||||
Tcl_CmdDeleteProc *deleteProc)
|
||||
{
|
||||
Command *cmdPtr = (Command *)
|
||||
TclCreateObjCommandInNs(interp,cmdName,nsPtr,proc,clientData,deleteProc);
|
||||
TclCreateObjCommandInNs(interp, cmdName, nsPtr, proc, clientData,
|
||||
deleteProc);
|
||||
|
||||
cmdPtr->nreProc = nreProc;
|
||||
return (Tcl_Command) cmdPtr;
|
||||
@@ -8396,7 +8408,6 @@ TclPushTailcallPoint(
|
||||
TclNRAddCallback(interp, NRCommand, NULL, NULL, NULL, NULL);
|
||||
((Interp *) interp)->numLevels++;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
@@ -8432,7 +8443,6 @@ TclSetTailcall(
|
||||
}
|
||||
runPtr->data[1] = listPtr;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
@@ -8508,7 +8518,6 @@ TclNRTailcallObjCmd(
|
||||
}
|
||||
return TCL_RETURN;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
@@ -8576,7 +8585,6 @@ TclNRReleaseValues(
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Tcl_NRAddCallback(
|
||||
|
||||
@@ -156,7 +156,7 @@ TclInitDbCkalloc(void)
|
||||
if (!ckallocInit) {
|
||||
ckallocInit = 1;
|
||||
ckallocMutexPtr = Tcl_GetAllocMutex();
|
||||
#ifndef TCL_THREADS
|
||||
#if !TCL_THREADS
|
||||
/* Silence compiler warning */
|
||||
(void)ckallocMutexPtr;
|
||||
#endif
|
||||
|
||||
+46
-178
@@ -597,9 +597,9 @@ Tcl_RegsubObjCmd(
|
||||
* slightly modified version of the one pair STR_MAP code.
|
||||
*/
|
||||
|
||||
int slen, nocase;
|
||||
int slen, nocase, wsrclc;
|
||||
int (*strCmpFn)(const Tcl_UniChar*,const Tcl_UniChar*,unsigned long);
|
||||
Tcl_UniChar *p, wsrclc;
|
||||
Tcl_UniChar *p;
|
||||
|
||||
numMatches = 0;
|
||||
nocase = (cflags & TCL_REG_NOCASE);
|
||||
@@ -2001,8 +2001,8 @@ StringMapCmd(
|
||||
* larger strings.
|
||||
*/
|
||||
|
||||
int mapLen;
|
||||
Tcl_UniChar *mapString, u2lc;
|
||||
int mapLen, u2lc;
|
||||
Tcl_UniChar *mapString;
|
||||
|
||||
ustring2 = Tcl_GetUnicodeFromObj(mapElemv[0], &length2);
|
||||
p = ustring1;
|
||||
@@ -2033,8 +2033,8 @@ StringMapCmd(
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Tcl_UniChar **mapStrings, *u2lc = NULL;
|
||||
int *mapLens;
|
||||
Tcl_UniChar **mapStrings;
|
||||
int *mapLens, *u2lc = NULL;
|
||||
|
||||
/*
|
||||
* Precompute pointers to the unicode string and length. This saves us
|
||||
@@ -2046,7 +2046,7 @@ StringMapCmd(
|
||||
mapStrings = TclStackAlloc(interp, mapElemc*2*sizeof(Tcl_UniChar *));
|
||||
mapLens = TclStackAlloc(interp, mapElemc * 2 * sizeof(int));
|
||||
if (nocase) {
|
||||
u2lc = TclStackAlloc(interp, mapElemc * sizeof(Tcl_UniChar));
|
||||
u2lc = TclStackAlloc(interp, mapElemc * sizeof(int));
|
||||
}
|
||||
for (index = 0; index < mapElemc; index++) {
|
||||
mapStrings[index] = Tcl_GetUnicodeFromObj(mapElemv[index],
|
||||
@@ -2546,10 +2546,8 @@ StringEqualCmd(
|
||||
* the expr string comparison in INST_EQ/INST_NEQ/INST_LT/...).
|
||||
*/
|
||||
|
||||
const char *string1, *string2;
|
||||
int length1, length2, i, match, length, nocase = 0, reqlength = -1;
|
||||
typedef int (*strCmpFn_t)(const char *, const char *, unsigned int);
|
||||
strCmpFn_t strCmpFn;
|
||||
const char *string2;
|
||||
int length, i, match, nocase = 0, reqlength = -1;
|
||||
|
||||
if (objc < 3 || objc > 6) {
|
||||
str_cmp_args:
|
||||
@@ -2559,11 +2557,11 @@ StringEqualCmd(
|
||||
}
|
||||
|
||||
for (i = 1; i < objc-2; i++) {
|
||||
string2 = TclGetStringFromObj(objv[i], &length2);
|
||||
if ((length2 > 1) && !strncmp(string2, "-nocase", (size_t)length2)) {
|
||||
string2 = TclGetStringFromObj(objv[i], &length);
|
||||
if ((length > 1) && !strncmp(string2, "-nocase", (size_t)length)) {
|
||||
nocase = 1;
|
||||
} else if ((length2 > 1)
|
||||
&& !strncmp(string2, "-length", (size_t)length2)) {
|
||||
} else if ((length > 1)
|
||||
&& !strncmp(string2, "-length", (size_t)length)) {
|
||||
if (i+1 >= objc-2) {
|
||||
goto str_cmp_args;
|
||||
}
|
||||
@@ -2588,78 +2586,7 @@ StringEqualCmd(
|
||||
|
||||
objv += objc-2;
|
||||
|
||||
if ((reqlength == 0) || (objv[0] == objv[1])) {
|
||||
/*
|
||||
* Always match at 0 chars of if it is the same obj.
|
||||
*/
|
||||
|
||||
Tcl_SetObjResult(interp, Tcl_NewBooleanObj(1));
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
if (!nocase && TclIsPureByteArray(objv[0]) &&
|
||||
TclIsPureByteArray(objv[1])) {
|
||||
/*
|
||||
* 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 NUL (\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 *) TclGetStringFromObj(objv[0], &length1);
|
||||
string2 = (char *) TclGetStringFromObj(objv[1], &length2);
|
||||
if ((reqlength < 0) && !nocase) {
|
||||
strCmpFn = (strCmpFn_t) TclpUtfNcmp2;
|
||||
} else {
|
||||
length1 = Tcl_NumUtfChars(string1, length1);
|
||||
length2 = Tcl_NumUtfChars(string2, length2);
|
||||
strCmpFn = (strCmpFn_t) (nocase ? Tcl_UtfNcasecmp : Tcl_UtfNcmp);
|
||||
}
|
||||
}
|
||||
|
||||
if ((reqlength < 0) && (length1 != length2)) {
|
||||
match = 1; /* This will be reversed below. */
|
||||
} else {
|
||||
length = (length1 < length2) ? length1 : length2;
|
||||
if (reqlength > 0 && reqlength < length) {
|
||||
length = reqlength;
|
||||
} else if (reqlength < 0) {
|
||||
/*
|
||||
* The requested length is negative, so we ignore it by setting it
|
||||
* to length + 1 so we correct the match var.
|
||||
*/
|
||||
|
||||
reqlength = length + 1;
|
||||
}
|
||||
|
||||
match = strCmpFn(string1, string2, (unsigned) length);
|
||||
if ((match == 0) && (reqlength > length)) {
|
||||
match = length1 - length2;
|
||||
}
|
||||
}
|
||||
match = TclStringCmp(objv[0], objv[1], 0, nocase, reqlength);
|
||||
|
||||
Tcl_SetObjResult(interp, Tcl_NewBooleanObj(match ? 0 : 1));
|
||||
return TCL_OK;
|
||||
@@ -2696,11 +2623,31 @@ StringCmpCmd(
|
||||
* the expr string comparison in INST_EQ/INST_NEQ/INST_LT/...).
|
||||
*/
|
||||
|
||||
const char *string1, *string2;
|
||||
int length1, length2, i, match, length, nocase = 0, reqlength = -1;
|
||||
typedef int (*strCmpFn_t)(const char *, const char *, unsigned int);
|
||||
strCmpFn_t strCmpFn;
|
||||
int match, nocase, reqlength, status;
|
||||
|
||||
status = TclStringCmpOpts(interp, objc, objv, &nocase, &reqlength);
|
||||
if (status != TCL_OK) {
|
||||
return status;
|
||||
}
|
||||
|
||||
objv += objc-2;
|
||||
match = TclStringCmp(objv[0], objv[1], 0, nocase, reqlength);
|
||||
Tcl_SetObjResult(interp, Tcl_NewIntObj(match));
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
int TclStringCmpOpts(
|
||||
Tcl_Interp *interp, /* Current interpreter. */
|
||||
int objc, /* Number of arguments. */
|
||||
Tcl_Obj *const objv[], /* Argument objects. */
|
||||
int *nocase,
|
||||
int *reqlength)
|
||||
{
|
||||
int i, length;
|
||||
const char *string;
|
||||
|
||||
*reqlength = -1;
|
||||
*nocase = 0;
|
||||
if (objc < 3 || objc > 6) {
|
||||
str_cmp_args:
|
||||
Tcl_WrongNumArgs(interp, 1, objv,
|
||||
@@ -2709,106 +2656,27 @@ StringCmpCmd(
|
||||
}
|
||||
|
||||
for (i = 1; i < objc-2; i++) {
|
||||
string2 = TclGetStringFromObj(objv[i], &length2);
|
||||
if ((length2 > 1) && !strncmp(string2, "-nocase", (size_t)length2)) {
|
||||
nocase = 1;
|
||||
} else if ((length2 > 1)
|
||||
&& !strncmp(string2, "-length", (size_t)length2)) {
|
||||
string = TclGetStringFromObj(objv[i], &length);
|
||||
if ((length > 1) && !strncmp(string, "-nocase", (size_t)length)) {
|
||||
*nocase = 1;
|
||||
} else if ((length > 1)
|
||||
&& !strncmp(string, "-length", (size_t)length)) {
|
||||
if (i+1 >= objc-2) {
|
||||
goto str_cmp_args;
|
||||
}
|
||||
i++;
|
||||
if (TclGetIntFromObj(interp, objv[i], &reqlength) != TCL_OK) {
|
||||
if (TclGetIntFromObj(interp, objv[i], reqlength) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
} else {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"bad option \"%s\": must be -nocase or -length",
|
||||
string2));
|
||||
string));
|
||||
Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "INDEX", "option",
|
||||
string2, NULL);
|
||||
string, NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* From now on, we only access the two objects at the end of the argument
|
||||
* array.
|
||||
*/
|
||||
|
||||
objv += objc-2;
|
||||
|
||||
if ((reqlength == 0) || (objv[0] == objv[1])) {
|
||||
/*
|
||||
* Always match at 0 chars of if it is the same obj.
|
||||
*/
|
||||
|
||||
Tcl_SetObjResult(interp, Tcl_NewBooleanObj(0));
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
if (!nocase && TclIsPureByteArray(objv[0]) &&
|
||||
TclIsPureByteArray(objv[1])) {
|
||||
/*
|
||||
* 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 NUL (\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 *) TclGetStringFromObj(objv[0], &length1);
|
||||
string2 = (char *) TclGetStringFromObj(objv[1], &length2);
|
||||
if ((reqlength < 0) && !nocase) {
|
||||
strCmpFn = (strCmpFn_t) TclpUtfNcmp2;
|
||||
} else {
|
||||
length1 = Tcl_NumUtfChars(string1, length1);
|
||||
length2 = Tcl_NumUtfChars(string2, length2);
|
||||
strCmpFn = (strCmpFn_t) (nocase ? Tcl_UtfNcasecmp : Tcl_UtfNcmp);
|
||||
}
|
||||
}
|
||||
|
||||
length = (length1 < length2) ? length1 : length2;
|
||||
if (reqlength > 0 && reqlength < length) {
|
||||
length = reqlength;
|
||||
} else if (reqlength < 0) {
|
||||
/*
|
||||
* The requested length is negative, so we ignore it by setting it to
|
||||
* length + 1 so we correct the match var.
|
||||
*/
|
||||
|
||||
reqlength = length + 1;
|
||||
}
|
||||
|
||||
match = strCmpFn(string1, string2, (unsigned) length);
|
||||
if ((match == 0) && (reqlength > length)) {
|
||||
match = length1 - length2;
|
||||
}
|
||||
|
||||
Tcl_SetObjResult(interp,
|
||||
Tcl_NewIntObj((match > 0) ? 1 : (match < 0) ? -1 : 0));
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
|
||||
+23
-21
@@ -27,7 +27,6 @@ static void CompileReturnInternal(CompileEnv *envPtr,
|
||||
Tcl_Obj *returnOpts);
|
||||
static int IndexTailVarIfKnown(Tcl_Interp *interp,
|
||||
Tcl_Token *varTokenPtr, CompileEnv *envPtr);
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
@@ -127,9 +126,12 @@ TclCompileGlobalCmd(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/* TODO: Consider what value can pass through the
|
||||
* IndexTailVarIfKnown() screen. Full CompileWord()
|
||||
* likely does not apply here. Push known value instead. */
|
||||
/*
|
||||
* TODO: Consider what value can pass through the
|
||||
* IndexTailVarIfKnown() screen. Full CompileWord() likely does not
|
||||
* apply here. Push known value instead.
|
||||
*/
|
||||
|
||||
CompileWord(envPtr, varTokenPtr, interp, i);
|
||||
TclEmitInstInt4( INST_NSUPVAR, localIndex, envPtr);
|
||||
}
|
||||
@@ -270,7 +272,7 @@ TclCompileIfCmd(
|
||||
jumpIndex = jumpFalseFixupArray.next;
|
||||
jumpFalseFixupArray.next++;
|
||||
TclEmitForwardJump(envPtr, TCL_FALSE_JUMP,
|
||||
jumpFalseFixupArray.fixup+jumpIndex);
|
||||
jumpFalseFixupArray.fixup + jumpIndex);
|
||||
}
|
||||
code = TCL_OK;
|
||||
}
|
||||
@@ -317,7 +319,7 @@ TclCompileIfCmd(
|
||||
}
|
||||
jumpEndFixupArray.next++;
|
||||
TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP,
|
||||
jumpEndFixupArray.fixup+jumpIndex);
|
||||
jumpEndFixupArray.fixup + jumpIndex);
|
||||
|
||||
/*
|
||||
* Fix the target of the jumpFalse after the test. Generate a 4
|
||||
@@ -329,7 +331,7 @@ TclCompileIfCmd(
|
||||
|
||||
TclAdjustStackDepth(-1, envPtr);
|
||||
if (TclFixupForwardJumpToHere(envPtr,
|
||||
jumpFalseFixupArray.fixup+jumpIndex, 120)) {
|
||||
jumpFalseFixupArray.fixup + jumpIndex, 120)) {
|
||||
/*
|
||||
* Adjust the code offset for the proceeding jump to the end
|
||||
* of the "if" command.
|
||||
@@ -412,7 +414,7 @@ TclCompileIfCmd(
|
||||
for (j = jumpEndFixupArray.next; j > 0; j--) {
|
||||
jumpIndex = (j - 1); /* i.e. process the closest jump first. */
|
||||
if (TclFixupForwardJumpToHere(envPtr,
|
||||
jumpEndFixupArray.fixup+jumpIndex, 127)) {
|
||||
jumpEndFixupArray.fixup + jumpIndex, 127)) {
|
||||
/*
|
||||
* Adjust the immediately preceeding "ifFalse" jump. We moved it's
|
||||
* target (just after this jump) down three bytes.
|
||||
@@ -920,7 +922,7 @@ TclCompileLappendCmd(
|
||||
CompileWord(envPtr, valueTokenPtr, interp, i);
|
||||
valueTokenPtr = TokenAfter(valueTokenPtr);
|
||||
}
|
||||
TclEmitInstInt4( INST_LIST, numWords-2, envPtr);
|
||||
TclEmitInstInt4( INST_LIST, numWords - 2, envPtr);
|
||||
if (isScalar) {
|
||||
if (localIndex < 0) {
|
||||
TclEmitOpcode( INST_LAPPEND_LIST_STK, envPtr);
|
||||
@@ -997,7 +999,7 @@ TclCompileLassignCmd(
|
||||
*/
|
||||
|
||||
PushVarNameWord(interp, tokenPtr, envPtr, 0, &localIndex,
|
||||
&isScalar, idx+2);
|
||||
&isScalar, idx + 2);
|
||||
|
||||
/*
|
||||
* Emit instructions to get the idx'th item out of the list value on
|
||||
@@ -1414,7 +1416,7 @@ TclCompileLinsertCmd(
|
||||
tokenPtr = TokenAfter(tokenPtr);
|
||||
CompileWord(envPtr, tokenPtr, interp, i);
|
||||
}
|
||||
TclEmitInstInt4( INST_LIST, i-3, envPtr);
|
||||
TclEmitInstInt4( INST_LIST, i - 3, envPtr);
|
||||
|
||||
if (idx == TCL_INDEX_START) {
|
||||
TclEmitInstInt4( INST_REVERSE, 2, envPtr);
|
||||
@@ -1439,7 +1441,7 @@ TclCompileLinsertCmd(
|
||||
}
|
||||
TclEmitInstInt4( INST_OVER, 1, envPtr);
|
||||
TclEmitInstInt4( INST_LIST_RANGE_IMM, 0, envPtr);
|
||||
TclEmitInt4( idx-1, envPtr);
|
||||
TclEmitInt4( idx - 1, envPtr);
|
||||
TclEmitInstInt4( INST_REVERSE, 3, envPtr);
|
||||
TclEmitInstInt4( INST_LIST_RANGE_IMM, idx, envPtr);
|
||||
TclEmitInt4( TCL_INDEX_END, envPtr);
|
||||
@@ -2234,7 +2236,7 @@ TclCompileRegexpCmd(
|
||||
}
|
||||
|
||||
if (!simple) {
|
||||
CompileWord(envPtr, varTokenPtr, interp, parsePtr->numWords-2);
|
||||
CompileWord(envPtr, varTokenPtr, interp, parsePtr->numWords - 2);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2242,7 +2244,7 @@ TclCompileRegexpCmd(
|
||||
*/
|
||||
|
||||
varTokenPtr = TokenAfter(varTokenPtr);
|
||||
CompileWord(envPtr, varTokenPtr, interp, parsePtr->numWords-1);
|
||||
CompileWord(envPtr, varTokenPtr, interp, parsePtr->numWords - 1);
|
||||
|
||||
if (simple) {
|
||||
if (exact && !nocase) {
|
||||
@@ -2426,7 +2428,7 @@ TclCompileRegsubCmd(
|
||||
PushLiteral(envPtr, bytes, len);
|
||||
bytes = TclGetStringFromObj(replacementObj, &len);
|
||||
PushLiteral(envPtr, bytes, len);
|
||||
CompileWord(envPtr, stringTokenPtr, interp, parsePtr->numWords-2);
|
||||
CompileWord(envPtr, stringTokenPtr, interp, parsePtr->numWords - 2);
|
||||
TclEmitOpcode( INST_STR_MAP, envPtr);
|
||||
|
||||
done:
|
||||
@@ -2555,7 +2557,7 @@ TclCompileReturnCmd(
|
||||
*/
|
||||
|
||||
if (explicitResult) {
|
||||
CompileWord(envPtr, wordTokenPtr, interp, numWords-1);
|
||||
CompileWord(envPtr, wordTokenPtr, interp, numWords - 1);
|
||||
} else {
|
||||
/*
|
||||
* No explict result argument, so default result is empty string.
|
||||
@@ -2633,7 +2635,7 @@ TclCompileReturnCmd(
|
||||
*/
|
||||
|
||||
if (explicitResult) {
|
||||
CompileWord(envPtr, wordTokenPtr, interp, numWords-1);
|
||||
CompileWord(envPtr, wordTokenPtr, interp, numWords - 1);
|
||||
} else {
|
||||
PushStringLiteral(envPtr, "");
|
||||
}
|
||||
@@ -2864,12 +2866,12 @@ TclCompileVariableCmd(
|
||||
CompileWord(envPtr, varTokenPtr, interp, i);
|
||||
TclEmitInstInt4( INST_VARIABLE, localIndex, envPtr);
|
||||
|
||||
if (i+1 < numWords) {
|
||||
if (i + 1 < numWords) {
|
||||
/*
|
||||
* A value has been given: set the variable, pop the value
|
||||
*/
|
||||
|
||||
CompileWord(envPtr, valueTokenPtr, interp, i+1);
|
||||
CompileWord(envPtr, valueTokenPtr, interp, i + 1);
|
||||
Emit14Inst( INST_STORE_SCALAR, localIndex, envPtr);
|
||||
TclEmitOpcode( INST_POP, envPtr);
|
||||
}
|
||||
@@ -2945,7 +2947,7 @@ IndexTailVarIfKnown(
|
||||
tailName = TclGetStringFromObj(tailPtr, &len);
|
||||
|
||||
if (len) {
|
||||
if (*(tailName+len-1) == ')') {
|
||||
if (*(tailName + len - 1) == ')') {
|
||||
/*
|
||||
* Possible array: bail out
|
||||
*/
|
||||
@@ -2959,7 +2961,7 @@ IndexTailVarIfKnown(
|
||||
*/
|
||||
|
||||
for (p = tailName + len -1; p > tailName; p--) {
|
||||
if ((*p == ':') && (*(p-1) == ':')) {
|
||||
if ((*p == ':') && (*(p - 1) == ':')) {
|
||||
p++;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1838,6 +1838,11 @@ EXTERN Tcl_Channel Tcl_OpenTcpServerEx(Tcl_Interp *interp,
|
||||
unsigned int flags,
|
||||
Tcl_TcpAcceptProc *acceptProc,
|
||||
ClientData callbackData);
|
||||
/* Slot 632 is reserved */
|
||||
/* 633 */
|
||||
EXTERN int Tcl_LinkArray(Tcl_Interp *interp,
|
||||
const char *varName, char *addr, int type,
|
||||
size_t size);
|
||||
|
||||
typedef struct {
|
||||
const struct TclPlatStubs *tclPlatStubs;
|
||||
@@ -2505,6 +2510,8 @@ typedef struct TclStubs {
|
||||
int (*tcl_FSUnloadFile) (Tcl_Interp *interp, Tcl_LoadHandle handlePtr); /* 629 */
|
||||
void (*tcl_ZlibStreamSetCompressionDictionary) (Tcl_ZlibStream zhandle, Tcl_Obj *compressionDictionaryObj); /* 630 */
|
||||
Tcl_Channel (*tcl_OpenTcpServerEx) (Tcl_Interp *interp, const char *service, const char *host, unsigned int flags, Tcl_TcpAcceptProc *acceptProc, ClientData callbackData); /* 631 */
|
||||
void (*reserved632)(void);
|
||||
int (*tcl_LinkArray) (Tcl_Interp *interp, const char *varName, char *addr, int type, size_t size); /* 633 */
|
||||
} TclStubs;
|
||||
|
||||
extern const TclStubs *tclStubsPtr;
|
||||
@@ -3799,6 +3806,9 @@ extern const TclStubs *tclStubsPtr;
|
||||
(tclStubsPtr->tcl_ZlibStreamSetCompressionDictionary) /* 630 */
|
||||
#define Tcl_OpenTcpServerEx \
|
||||
(tclStubsPtr->tcl_OpenTcpServerEx) /* 631 */
|
||||
/* Slot 632 is reserved */
|
||||
#define Tcl_LinkArray \
|
||||
(tclStubsPtr->tcl_LinkArray) /* 633 */
|
||||
|
||||
#endif /* defined(USE_TCL_STUBS) */
|
||||
|
||||
|
||||
+57
-51
@@ -87,8 +87,8 @@ static const Tcl_ObjType ensembleCmdType = {
|
||||
};
|
||||
|
||||
/*
|
||||
* The internal rep for caching ensemble subcommand lookups and
|
||||
* spell corrections.
|
||||
* The internal rep for caching ensemble subcommand lookups and spelling
|
||||
* corrections.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
@@ -98,10 +98,9 @@ typedef struct {
|
||||
Command *token; /* Reference to the command for which this
|
||||
* structure is a cache of the resolution. */
|
||||
Tcl_Obj *fix; /* Corrected spelling, if needed. */
|
||||
Tcl_HashEntry *hPtr; /* Direct link to entry in the subcommand
|
||||
* hash table. */
|
||||
Tcl_HashEntry *hPtr; /* Direct link to entry in the subcommand hash
|
||||
* table. */
|
||||
} EnsembleCmdRep;
|
||||
|
||||
|
||||
static inline Tcl_Obj *
|
||||
NewNsObj(
|
||||
@@ -111,9 +110,8 @@ NewNsObj(
|
||||
|
||||
if (namespacePtr == TclGetGlobalNamespace(nsPtr->interp)) {
|
||||
return Tcl_NewStringObj("::", 2);
|
||||
} else {
|
||||
return Tcl_NewStringObj(nsPtr->fullName, -1);
|
||||
}
|
||||
return Tcl_NewStringObj(nsPtr->fullName, -1);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -147,7 +145,7 @@ TclNamespaceEnsembleCmd(
|
||||
{
|
||||
Tcl_Namespace *namespacePtr;
|
||||
Namespace *nsPtr = (Namespace *) TclGetCurrentNamespace(interp), *cxtPtr,
|
||||
*foundNsPtr, *altFoundNsPtr, *actualCxtPtr;
|
||||
*foundNsPtr, *altFoundNsPtr, *actualCxtPtr;
|
||||
Tcl_Command token;
|
||||
Tcl_DictSearch search;
|
||||
Tcl_Obj *listObj;
|
||||
@@ -302,7 +300,8 @@ TclNamespaceEnsembleCmd(
|
||||
Tcl_DictObjPut(NULL, patchedDict, subcmdWordsObj,
|
||||
newList);
|
||||
}
|
||||
Tcl_DictObjNext(&search, &subcmdWordsObj,&listObj, &done);
|
||||
Tcl_DictObjNext(&search, &subcmdWordsObj, &listObj,
|
||||
&done);
|
||||
} while (!done);
|
||||
|
||||
if (allocatedMapFlag) {
|
||||
@@ -336,8 +335,8 @@ TclNamespaceEnsembleCmd(
|
||||
}
|
||||
|
||||
TclGetNamespaceForQualName(interp, name, cxtPtr,
|
||||
TCL_CREATE_NS_IF_UNKNOWN, &foundNsPtr, &altFoundNsPtr, &actualCxtPtr,
|
||||
&simpleName);
|
||||
TCL_CREATE_NS_IF_UNKNOWN, &foundNsPtr, &altFoundNsPtr,
|
||||
&actualCxtPtr, &simpleName);
|
||||
|
||||
/*
|
||||
* Create the ensemble. Note that this might delete another ensemble
|
||||
@@ -347,8 +346,8 @@ TclNamespaceEnsembleCmd(
|
||||
*/
|
||||
|
||||
token = TclCreateEnsembleInNs(interp, simpleName,
|
||||
(Tcl_Namespace *) foundNsPtr, (Tcl_Namespace *) nsPtr,
|
||||
(permitPrefix ? TCL_ENSEMBLE_PREFIX : 0));
|
||||
(Tcl_Namespace *) foundNsPtr, (Tcl_Namespace *) nsPtr,
|
||||
(permitPrefix ? TCL_ENSEMBLE_PREFIX : 0));
|
||||
Tcl_SetEnsembleSubcommandList(interp, token, subcmdObj);
|
||||
Tcl_SetEnsembleMappingDict(interp, token, mapObj);
|
||||
Tcl_SetEnsembleUnknownHandler(interp, token, unknownObj);
|
||||
@@ -576,7 +575,8 @@ TclNamespaceEnsembleCmd(
|
||||
Tcl_AppendStringsToObj(newCmd, "::", NULL);
|
||||
}
|
||||
Tcl_AppendObjToObj(newCmd, listv[0]);
|
||||
Tcl_ListObjReplace(NULL, newList, 0,1, 1,&newCmd);
|
||||
Tcl_ListObjReplace(NULL, newList, 0, 1, 1,
|
||||
&newCmd);
|
||||
if (patchedDict == NULL) {
|
||||
patchedDict = Tcl_DuplicateObj(objv[1]);
|
||||
}
|
||||
@@ -650,15 +650,13 @@ TclNamespaceEnsembleCmd(
|
||||
Tcl_Command
|
||||
TclCreateEnsembleInNs(
|
||||
Tcl_Interp *interp,
|
||||
|
||||
const char *name, /* Simple name of command to create (no */
|
||||
/* namespace components). */
|
||||
Tcl_Namespace /* Name of namespace to create the command in. */
|
||||
*nameNsPtr,
|
||||
Tcl_Namespace
|
||||
*ensembleNsPtr, /* Name of the namespace for the ensemble. */
|
||||
int flags
|
||||
)
|
||||
const char *name, /* Simple name of command to create (no
|
||||
* namespace components). */
|
||||
Tcl_Namespace *nameNsPtr, /* Name of namespace to create the command
|
||||
* in. */
|
||||
Tcl_Namespace *ensembleNsPtr,
|
||||
/* Name of the namespace for the ensemble. */
|
||||
int flags)
|
||||
{
|
||||
Namespace *nsPtr = (Namespace *) ensembleNsPtr;
|
||||
EnsembleConfig *ensemblePtr;
|
||||
@@ -666,8 +664,8 @@ TclCreateEnsembleInNs(
|
||||
|
||||
ensemblePtr = ckalloc(sizeof(EnsembleConfig));
|
||||
token = TclNRCreateCommandInNs(interp, name,
|
||||
(Tcl_Namespace *) nameNsPtr, NsEnsembleImplementationCmd,
|
||||
NsEnsembleImplementationCmdNR, ensemblePtr, DeleteEnsembleConfig);
|
||||
(Tcl_Namespace *) nameNsPtr, NsEnsembleImplementationCmd,
|
||||
NsEnsembleImplementationCmdNR, ensemblePtr, DeleteEnsembleConfig);
|
||||
if (token == NULL) {
|
||||
ckfree(ensemblePtr);
|
||||
return NULL;
|
||||
@@ -701,18 +699,15 @@ TclCreateEnsembleInNs(
|
||||
}
|
||||
|
||||
return ensemblePtr->token;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* Tcl_CreateEnsemble
|
||||
*
|
||||
* Create a simple ensemble attached to the given namespace.
|
||||
*
|
||||
* Deprecated by TclCreateEnsembleInNs.
|
||||
* Create a simple ensemble attached to the given namespace. Deprecated
|
||||
* (internally) by TclCreateEnsembleInNs.
|
||||
*
|
||||
* Value
|
||||
*
|
||||
@@ -732,8 +727,8 @@ Tcl_CreateEnsemble(
|
||||
Tcl_Namespace *namespacePtr,
|
||||
int flags)
|
||||
{
|
||||
Namespace *nsPtr = (Namespace *)namespacePtr, *foundNsPtr, *altNsPtr,
|
||||
*actualNsPtr;
|
||||
Namespace *nsPtr = (Namespace *) namespacePtr, *foundNsPtr, *altNsPtr,
|
||||
*actualNsPtr;
|
||||
const char * simpleName;
|
||||
|
||||
if (nsPtr == NULL) {
|
||||
@@ -741,11 +736,10 @@ Tcl_CreateEnsemble(
|
||||
}
|
||||
|
||||
TclGetNamespaceForQualName(interp, name, nsPtr, TCL_CREATE_NS_IF_UNKNOWN,
|
||||
&foundNsPtr, &altNsPtr, &actualNsPtr, &simpleName);
|
||||
&foundNsPtr, &altNsPtr, &actualNsPtr, &simpleName);
|
||||
return TclCreateEnsembleInNs(interp, simpleName,
|
||||
(Tcl_Namespace *) foundNsPtr, (Tcl_Namespace *) nsPtr, flags);
|
||||
(Tcl_Namespace *) foundNsPtr, (Tcl_Namespace *) nsPtr, flags);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
@@ -2117,22 +2111,27 @@ TclSpellFix(
|
||||
iPtr->ensembleRewrite.numInsertedObjs = 0;
|
||||
}
|
||||
|
||||
/* Compute the valid length of the ensemble root */
|
||||
/*
|
||||
* Compute the valid length of the ensemble root.
|
||||
*/
|
||||
|
||||
size = iPtr->ensembleRewrite.numRemovedObjs + objc
|
||||
- iPtr->ensembleRewrite.numInsertedObjs;
|
||||
- iPtr->ensembleRewrite.numInsertedObjs;
|
||||
|
||||
search = iPtr->ensembleRewrite.sourceObjs;
|
||||
if (search[0] == NULL) {
|
||||
/* Awful casting abuse here */
|
||||
/*
|
||||
* Awful casting abuse here...
|
||||
*/
|
||||
search = (Tcl_Obj *const *) search[1];
|
||||
}
|
||||
|
||||
if (badIdx < iPtr->ensembleRewrite.numInsertedObjs) {
|
||||
/*
|
||||
* Misspelled value was inserted. We cannot directly jump
|
||||
* to the bad value, but have to search.
|
||||
* Misspelled value was inserted. We cannot directly jump to the bad
|
||||
* value, but have to search.
|
||||
*/
|
||||
|
||||
idx = 1;
|
||||
while (idx < size) {
|
||||
if (search[idx] == bad) {
|
||||
@@ -2156,13 +2155,14 @@ TclSpellFix(
|
||||
|
||||
search = iPtr->ensembleRewrite.sourceObjs;
|
||||
if (search[0] == NULL) {
|
||||
store = (Tcl_Obj **)search[2];
|
||||
} else {
|
||||
store = (Tcl_Obj **) search[2];
|
||||
} else {
|
||||
Tcl_Obj **tmp = ckalloc(3 * sizeof(Tcl_Obj *));
|
||||
|
||||
tmp[0] = NULL;
|
||||
tmp[1] = (Tcl_Obj *)iPtr->ensembleRewrite.sourceObjs;
|
||||
tmp[2] = (Tcl_Obj *)ckalloc(size * sizeof(Tcl_Obj *));
|
||||
memcpy(tmp[2], tmp[1], size*sizeof(Tcl_Obj *));
|
||||
tmp[1] = (Tcl_Obj *) iPtr->ensembleRewrite.sourceObjs;
|
||||
tmp[2] = (Tcl_Obj *) ckalloc(size * sizeof(Tcl_Obj *));
|
||||
memcpy(tmp[2], tmp[1], size * sizeof(Tcl_Obj *));
|
||||
|
||||
iPtr->ensembleRewrite.sourceObjs = (Tcl_Obj *const *) tmp;
|
||||
TclNRAddCallback(interp, FreeER, tmp, NULL, NULL, NULL);
|
||||
@@ -2589,7 +2589,9 @@ BuildEnsembleConfig(
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Usual case where we can freely act on the list and dict. */
|
||||
/*
|
||||
* Usual case where we can freely act on the list and dict.
|
||||
*/
|
||||
|
||||
for (i = 0; i < subc; i++) {
|
||||
name = TclGetString(subv[i]);
|
||||
@@ -2598,7 +2600,10 @@ BuildEnsembleConfig(
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Lookup target in the dictionary */
|
||||
/*
|
||||
* Lookup target in the dictionary.
|
||||
*/
|
||||
|
||||
if (mapDict) {
|
||||
Tcl_DictObjGet(NULL, mapDict, subv[i], &target);
|
||||
if (target) {
|
||||
@@ -2610,10 +2615,11 @@ BuildEnsembleConfig(
|
||||
|
||||
/*
|
||||
* target was not in the dictionary 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).
|
||||
* 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(name, -1);
|
||||
cmdPrefixObj = Tcl_NewListObj(1, &cmdObj);
|
||||
Tcl_SetHashValue(hPtr, cmdPrefixObj);
|
||||
|
||||
+5
-5
@@ -100,7 +100,7 @@ typedef struct ThreadSpecificData {
|
||||
} ThreadSpecificData;
|
||||
static Tcl_ThreadDataKey dataKey;
|
||||
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
typedef struct {
|
||||
Tcl_ThreadCreateProc *proc; /* Main() function of the thread */
|
||||
ClientData clientData; /* The one argument to Main() */
|
||||
@@ -1043,7 +1043,7 @@ TclInitSubsystems(void)
|
||||
#if USE_TCLALLOC
|
||||
TclInitAlloc(); /* Process wide mutex init */
|
||||
#endif
|
||||
#if defined(TCL_THREADS) && defined(USE_THREAD_ALLOC)
|
||||
#if TCL_THREADS && defined(USE_THREAD_ALLOC)
|
||||
TclInitThreadAlloc(); /* Setup thread allocator caches */
|
||||
#endif
|
||||
#ifdef TCL_MEM_DEBUG
|
||||
@@ -1220,7 +1220,7 @@ Tcl_Finalize(void)
|
||||
* Close down the thread-specific object allocator.
|
||||
*/
|
||||
|
||||
#if defined(TCL_THREADS) && defined(USE_THREAD_ALLOC)
|
||||
#if TCL_THREADS && defined(USE_THREAD_ALLOC)
|
||||
TclFinalizeThreadAlloc();
|
||||
#endif
|
||||
|
||||
@@ -1538,7 +1538,7 @@ Tcl_UpdateObjCmd(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
@@ -1601,7 +1601,7 @@ Tcl_CreateThread(
|
||||
int flags) /* Flags controlling behaviour of the new
|
||||
* thread. */
|
||||
{
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
ThreadClientData *cdPtr = ckalloc(sizeof(ThreadClientData));
|
||||
int result;
|
||||
|
||||
|
||||
+10
-80
@@ -5088,88 +5088,10 @@ TEBCresume(
|
||||
value2Ptr = OBJ_AT_TOS;
|
||||
valuePtr = OBJ_UNDER_TOS;
|
||||
|
||||
if (valuePtr == value2Ptr) {
|
||||
match = 0;
|
||||
} else {
|
||||
/*
|
||||
* We only need to check (in)equality when we have equal length
|
||||
* strings. We can use memcmp in all (n)eq cases because we
|
||||
* don't need to worry about lexical LE/BE variance.
|
||||
*/
|
||||
|
||||
typedef int (*memCmpFn_t)(const void*, const void*, size_t);
|
||||
memCmpFn_t memCmpFn;
|
||||
{
|
||||
int checkEq = ((*pc == INST_EQ) || (*pc == INST_NEQ)
|
||||
|| (*pc == INST_STR_EQ) || (*pc == INST_STR_NEQ));
|
||||
|
||||
if (TclIsPureByteArray(valuePtr)
|
||||
&& TclIsPureByteArray(value2Ptr)) {
|
||||
s1 = (char *) Tcl_GetByteArrayFromObj(valuePtr, &s1len);
|
||||
s2 = (char *) Tcl_GetByteArrayFromObj(value2Ptr, &s2len);
|
||||
memCmpFn = memcmp;
|
||||
} else if ((valuePtr->typePtr == &tclStringType)
|
||||
&& (value2Ptr->typePtr == &tclStringType)) {
|
||||
/*
|
||||
* Do a unicode-specific comparison if both of the args are of
|
||||
* String type. If the char length == byte length, we can do a
|
||||
* memcmp. In benchmark testing this proved the most efficient
|
||||
* check between the unicode and string comparison operations.
|
||||
*/
|
||||
|
||||
s1len = Tcl_GetCharLength(valuePtr);
|
||||
s2len = Tcl_GetCharLength(value2Ptr);
|
||||
if ((s1len == valuePtr->length)
|
||||
&& (valuePtr->bytes != NULL)
|
||||
&& (s2len == value2Ptr->length)
|
||||
&& (value2Ptr->bytes != NULL)) {
|
||||
s1 = valuePtr->bytes;
|
||||
s2 = value2Ptr->bytes;
|
||||
memCmpFn = memcmp;
|
||||
} else {
|
||||
s1 = (char *) Tcl_GetUnicode(valuePtr);
|
||||
s2 = (char *) Tcl_GetUnicode(value2Ptr);
|
||||
if (
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
1
|
||||
#else
|
||||
checkEq
|
||||
#endif
|
||||
) {
|
||||
memCmpFn = memcmp;
|
||||
s1len *= sizeof(Tcl_UniChar);
|
||||
s2len *= sizeof(Tcl_UniChar);
|
||||
} else {
|
||||
memCmpFn = (memCmpFn_t) Tcl_UniCharNcmp;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* strcmp can't do a simple memcmp in order to handle the
|
||||
* special Tcl \xC0\x80 null encoding for utf-8.
|
||||
*/
|
||||
|
||||
s1 = TclGetStringFromObj(valuePtr, &s1len);
|
||||
s2 = TclGetStringFromObj(value2Ptr, &s2len);
|
||||
if (checkEq) {
|
||||
memCmpFn = memcmp;
|
||||
} else {
|
||||
memCmpFn = (memCmpFn_t) TclpUtfNcmp2;
|
||||
}
|
||||
}
|
||||
|
||||
if (checkEq && (s1len != s2len)) {
|
||||
match = 1;
|
||||
} else {
|
||||
/*
|
||||
* The comparison function should compare up to the minimum
|
||||
* byte length only.
|
||||
*/
|
||||
match = memCmpFn(s1, s2,
|
||||
(size_t) ((s1len < s2len) ? s1len : s2len));
|
||||
if (match == 0) {
|
||||
match = s1len - s2len;
|
||||
}
|
||||
}
|
||||
match = TclStringCmp(valuePtr, value2Ptr, checkEq, 0, -1);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -5739,6 +5661,14 @@ TEBCresume(
|
||||
value2Ptr = OBJ_AT_TOS;
|
||||
valuePtr = OBJ_UNDER_TOS;
|
||||
|
||||
/*
|
||||
Try to determine, without triggering generation of a string
|
||||
representation, whether one value is not a number.
|
||||
*/
|
||||
if (TclCheckEmptyString(valuePtr) > 0 || TclCheckEmptyString(value2Ptr) > 0) {
|
||||
goto stringCompare;
|
||||
}
|
||||
|
||||
if (GetNumberFromObj(NULL, valuePtr, &ptr1, &type1) != TCL_OK
|
||||
|| GetNumberFromObj(NULL, value2Ptr, &ptr2, &type2) != TCL_OK) {
|
||||
/*
|
||||
|
||||
+24
-24
@@ -39,7 +39,7 @@ static int ReflectOutput(ClientData clientData, const char *buf,
|
||||
int toWrite, int *errorCodePtr);
|
||||
static void ReflectWatch(ClientData clientData, int mask);
|
||||
static int ReflectBlock(ClientData clientData, int mode);
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
static void ReflectThread(ClientData clientData, int action);
|
||||
static int ReflectEventRun(Tcl_Event *ev, int flags);
|
||||
static int ReflectEventDelete(Tcl_Event *ev, ClientData cd);
|
||||
@@ -76,7 +76,7 @@ static const Tcl_ChannelType tclRChannelType = {
|
||||
NULL, /* Flush channel. Not used by core. NULL'able */
|
||||
NULL, /* Handle events. NULL'able */
|
||||
ReflectSeekWide, /* Move access point (64 bit). NULL'able */
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
ReflectThread, /* thread action, tracking owner */
|
||||
#else
|
||||
NULL, /* thread action */
|
||||
@@ -97,7 +97,7 @@ typedef struct {
|
||||
* interpreter/thread containing its Tcl
|
||||
* command is gone.
|
||||
*/
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
Tcl_ThreadId thread; /* Thread the 'interp' belongs to. == Handler thread */
|
||||
Tcl_ThreadId owner; /* Thread owning the structure. == Channel thread */
|
||||
#endif
|
||||
@@ -201,7 +201,7 @@ typedef enum {
|
||||
#define NEGIMPL(a,b)
|
||||
#define HAS(x,f) (x & FLAG(f))
|
||||
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
/*
|
||||
* Thread specific types and structures.
|
||||
*
|
||||
@@ -451,7 +451,7 @@ static const char *msg_read_toomuch = "{read delivered more than requested}";
|
||||
static const char *msg_write_toomuch = "{write wrote more than requested}";
|
||||
static const char *msg_write_nothing = "{write wrote nothing}";
|
||||
static const char *msg_seek_beforestart = "{Tried to seek before origin}";
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
static const char *msg_send_originlost = "{Channel thread lost}";
|
||||
#endif /* TCL_THREADS */
|
||||
static const char *msg_send_dstlost = "{Owner lost}";
|
||||
@@ -706,7 +706,7 @@ TclChanCreateObjCmd(
|
||||
Tcl_Panic("TclChanCreateObjCmd: duplicate channel names");
|
||||
}
|
||||
Tcl_SetHashValue(hPtr, chan);
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
rcmPtr = GetThreadReflectedChannelMap();
|
||||
hPtr = Tcl_CreateHashEntry(&rcmPtr->map, chanPtr->state->channelName,
|
||||
&isNew);
|
||||
@@ -750,7 +750,7 @@ TclChanCreateObjCmd(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
typedef struct {
|
||||
Tcl_Event header;
|
||||
ReflectedChannel *rcPtr;
|
||||
@@ -917,11 +917,11 @@ TclChanPostEventObjCmd(
|
||||
* We have the channel and the events to post.
|
||||
*/
|
||||
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
if (rcPtr->owner == rcPtr->thread) {
|
||||
#endif
|
||||
Tcl_NotifyChannel(chan, events);
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
} else {
|
||||
ReflectEvent *ev = ckalloc(sizeof(ReflectEvent));
|
||||
|
||||
@@ -1137,7 +1137,7 @@ ReflectClose(
|
||||
* if lost?
|
||||
*/
|
||||
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
if (rcPtr->thread != Tcl_GetCurrentThread()) {
|
||||
ForwardParam p;
|
||||
|
||||
@@ -1169,7 +1169,7 @@ ReflectClose(
|
||||
* Are we in the correct thread?
|
||||
*/
|
||||
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
if (rcPtr->thread != Tcl_GetCurrentThread()) {
|
||||
ForwardParam p;
|
||||
|
||||
@@ -1216,7 +1216,7 @@ ReflectClose(
|
||||
Tcl_DeleteHashEntry(hPtr);
|
||||
}
|
||||
}
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
rcmPtr = GetThreadReflectedChannelMap();
|
||||
hPtr = Tcl_FindHashEntry(&rcmPtr->map,
|
||||
Tcl_GetChannelName(rcPtr->chan));
|
||||
@@ -1267,7 +1267,7 @@ ReflectInput(
|
||||
* Are we in the correct thread?
|
||||
*/
|
||||
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
if (rcPtr->thread != Tcl_GetCurrentThread()) {
|
||||
ForwardParam p;
|
||||
|
||||
@@ -1373,7 +1373,7 @@ ReflectOutput(
|
||||
* Are we in the correct thread?
|
||||
*/
|
||||
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
if (rcPtr->thread != Tcl_GetCurrentThread()) {
|
||||
ForwardParam p;
|
||||
|
||||
@@ -1502,7 +1502,7 @@ ReflectSeekWide(
|
||||
* Are we in the correct thread?
|
||||
*/
|
||||
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
if (rcPtr->thread != Tcl_GetCurrentThread()) {
|
||||
ForwardParam p;
|
||||
|
||||
@@ -1625,7 +1625,7 @@ ReflectWatch(
|
||||
* Are we in the correct thread?
|
||||
*/
|
||||
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
if (rcPtr->thread != Tcl_GetCurrentThread()) {
|
||||
ForwardParam p;
|
||||
|
||||
@@ -1683,7 +1683,7 @@ ReflectBlock(
|
||||
* Are we in the correct thread?
|
||||
*/
|
||||
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
if (rcPtr->thread != Tcl_GetCurrentThread()) {
|
||||
ForwardParam p;
|
||||
|
||||
@@ -1719,7 +1719,7 @@ ReflectBlock(
|
||||
return errorNum;
|
||||
}
|
||||
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
@@ -1789,7 +1789,7 @@ ReflectSetOption(
|
||||
* Are we in the correct thread?
|
||||
*/
|
||||
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
if (rcPtr->thread != Tcl_GetCurrentThread()) {
|
||||
ForwardParam p;
|
||||
|
||||
@@ -1868,7 +1868,7 @@ ReflectGetOption(
|
||||
* Are we in the correct thread?
|
||||
*/
|
||||
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
if (rcPtr->thread != Tcl_GetCurrentThread()) {
|
||||
int opcode;
|
||||
ForwardParam p;
|
||||
@@ -2131,7 +2131,7 @@ NewReflectedChannel(
|
||||
rcPtr->chan = NULL;
|
||||
rcPtr->interp = interp;
|
||||
rcPtr->dead = 0;
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
rcPtr->thread = Tcl_GetCurrentThread();
|
||||
#endif
|
||||
rcPtr->mode = mode;
|
||||
@@ -2506,7 +2506,7 @@ DeleteReflectedChannelMap(
|
||||
Tcl_HashEntry *hPtr; /* Search variable. */
|
||||
ReflectedChannel *rcPtr;
|
||||
Tcl_Channel chan;
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
ForwardingResult *resultPtr;
|
||||
ForwardingEvent *evPtr;
|
||||
ForwardParam *paramPtr;
|
||||
@@ -2536,7 +2536,7 @@ DeleteReflectedChannelMap(
|
||||
Tcl_DeleteHashTable(&rcmPtr->map);
|
||||
ckfree(&rcmPtr->map);
|
||||
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
/*
|
||||
* The origin interpreter for one or more reflected channels is gone.
|
||||
*/
|
||||
@@ -2622,7 +2622,7 @@ DeleteReflectedChannelMap(
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
|
||||
+19
-19
@@ -127,7 +127,7 @@ typedef struct {
|
||||
* in the argv, see below. The separate field
|
||||
* gives us direct access, needed when working
|
||||
* with the reflection maps. */
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
Tcl_ThreadId thread; /* Thread the 'interp' belongs to. */
|
||||
#endif
|
||||
|
||||
@@ -220,7 +220,7 @@ typedef enum {
|
||||
#define NEGIMPL(a,b)
|
||||
#define HAS(x,f) (x & FLAG(f))
|
||||
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
/*
|
||||
* Thread specific types and structures.
|
||||
*
|
||||
@@ -438,7 +438,7 @@ static void DeleteReflectedTransformMap(ClientData clientData,
|
||||
|
||||
static const char *msg_read_unsup = "{read not supported by Tcl driver}";
|
||||
static const char *msg_write_unsup = "{write not supported by Tcl driver}";
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
static const char *msg_send_originlost = "{Channel thread lost}";
|
||||
static const char *msg_send_dstlost = "{Owner lost}";
|
||||
#endif /* TCL_THREADS */
|
||||
@@ -699,7 +699,7 @@ TclChanPushObjCmd(
|
||||
Tcl_Panic("TclChanPushObjCmd: duplicate transformation handle");
|
||||
}
|
||||
Tcl_SetHashValue(hPtr, rtPtr);
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
rtmPtr = GetThreadReflectedTransformMap();
|
||||
hPtr = Tcl_CreateHashEntry(&rtmPtr->map, TclGetString(rtId), &isNew);
|
||||
Tcl_SetHashValue(hPtr, rtPtr);
|
||||
@@ -911,7 +911,7 @@ ReflectClose(
|
||||
* if lost?
|
||||
*/
|
||||
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
if (rtPtr->thread != Tcl_GetCurrentThread()) {
|
||||
ForwardParam p;
|
||||
|
||||
@@ -938,7 +938,7 @@ ReflectClose(
|
||||
|
||||
if (HAS(rtPtr->methods, METH_DRAIN) && !rtPtr->readIsDrained) {
|
||||
if (!TransformDrain(rtPtr, &errorCode)) {
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
if (rtPtr->thread != Tcl_GetCurrentThread()) {
|
||||
Tcl_EventuallyFree(rtPtr,
|
||||
(Tcl_FreeProc *) FreeReflectedTransform);
|
||||
@@ -952,7 +952,7 @@ ReflectClose(
|
||||
|
||||
if (HAS(rtPtr->methods, METH_FLUSH)) {
|
||||
if (!TransformFlush(rtPtr, &errorCode, FLUSH_WRITE)) {
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
if (rtPtr->thread != Tcl_GetCurrentThread()) {
|
||||
Tcl_EventuallyFree(rtPtr,
|
||||
(Tcl_FreeProc *) FreeReflectedTransform);
|
||||
@@ -968,7 +968,7 @@ ReflectClose(
|
||||
* Are we in the correct thread?
|
||||
*/
|
||||
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
if (rtPtr->thread != Tcl_GetCurrentThread()) {
|
||||
ForwardParam p;
|
||||
|
||||
@@ -1025,7 +1025,7 @@ ReflectClose(
|
||||
* under a channel by deleting the owning thread.
|
||||
*/
|
||||
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
rtmPtr = GetThreadReflectedTransformMap();
|
||||
hPtr = Tcl_FindHashEntry(&rtmPtr->map, TclGetString(rtPtr->handle));
|
||||
if (hPtr) {
|
||||
@@ -1767,7 +1767,7 @@ NewReflectedTransform(
|
||||
|
||||
rtPtr->chan = NULL;
|
||||
rtPtr->methods = 0;
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
rtPtr->thread = Tcl_GetCurrentThread();
|
||||
#endif
|
||||
rtPtr->parent = parentChan;
|
||||
@@ -2152,7 +2152,7 @@ DeleteReflectedTransformMap(
|
||||
Tcl_HashSearch hSearch; /* Search variable. */
|
||||
Tcl_HashEntry *hPtr; /* Search variable. */
|
||||
ReflectedTransform *rtPtr;
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
ForwardingResult *resultPtr;
|
||||
ForwardingEvent *evPtr;
|
||||
ForwardParam *paramPtr;
|
||||
@@ -2182,7 +2182,7 @@ DeleteReflectedTransformMap(
|
||||
Tcl_DeleteHashTable(&rtmPtr->map);
|
||||
ckfree(&rtmPtr->map);
|
||||
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
/*
|
||||
* The origin interpreter for one or more reflected channels is gone.
|
||||
*/
|
||||
@@ -2254,7 +2254,7 @@ DeleteReflectedTransformMap(
|
||||
#endif /* TCL_THREADS */
|
||||
}
|
||||
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
@@ -3088,7 +3088,7 @@ TransformRead(
|
||||
* Are we in the correct thread?
|
||||
*/
|
||||
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
if (rtPtr->thread != Tcl_GetCurrentThread()) {
|
||||
ForwardParam p;
|
||||
|
||||
@@ -3144,7 +3144,7 @@ TransformWrite(
|
||||
* Are we in the correct thread?
|
||||
*/
|
||||
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
if (rtPtr->thread != Tcl_GetCurrentThread()) {
|
||||
ForwardParam p;
|
||||
|
||||
@@ -3210,7 +3210,7 @@ TransformDrain(
|
||||
* Are we in the correct thread?
|
||||
*/
|
||||
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
if (rtPtr->thread != Tcl_GetCurrentThread()) {
|
||||
ForwardParam p;
|
||||
|
||||
@@ -3260,7 +3260,7 @@ TransformFlush(
|
||||
* Are we in the correct thread?
|
||||
*/
|
||||
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
if (rtPtr->thread != Tcl_GetCurrentThread()) {
|
||||
ForwardParam p;
|
||||
|
||||
@@ -3315,7 +3315,7 @@ TransformClear(
|
||||
* Are we in the correct thread?
|
||||
*/
|
||||
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
if (rtPtr->thread != Tcl_GetCurrentThread()) {
|
||||
ForwardParam p;
|
||||
|
||||
@@ -3347,7 +3347,7 @@ TransformLimit(
|
||||
* Are we in the correct thread?
|
||||
*/
|
||||
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
if (rtPtr->thread != Tcl_GetCurrentThread()) {
|
||||
ForwardParam p;
|
||||
|
||||
|
||||
+2
-2
@@ -3197,8 +3197,8 @@ TclSkipUnlink(
|
||||
#ifndef AUFS_SUPER_MAGIC
|
||||
#define AUFS_SUPER_MAGIC ('a' << 24 | 'u' << 16 | 'f' << 8 | 's')
|
||||
#endif /* AUFS_SUPER_MAGIC */
|
||||
if ((statfs(Tcl_GetString (shlibFile), &fs) == 0) &&
|
||||
(fs.f_type == AUFS_SUPER_MAGIC)) {
|
||||
if ((statfs(Tcl_GetString(shlibFile), &fs) == 0)
|
||||
&& (fs.f_type == AUFS_SUPER_MAGIC)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1075,7 +1075,7 @@ declare 9 win {
|
||||
}
|
||||
# new for 8.4.20+/8.5.12+ Cygwin only
|
||||
declare 10 win {
|
||||
Tcl_DirEntry *TclpReaddir(DIR *dir)
|
||||
Tcl_DirEntry *TclpReaddir(TclDIR *dir)
|
||||
}
|
||||
# Removed in 8.3.1 (for Win32s only):
|
||||
#declare 10 win {
|
||||
@@ -1212,7 +1212,7 @@ declare 9 unix {
|
||||
# Added in 8.4:
|
||||
|
||||
declare 10 unix {
|
||||
Tcl_DirEntry *TclpReaddir(DIR *dir)
|
||||
Tcl_DirEntry *TclpReaddir(TclDIR *dir)
|
||||
}
|
||||
# Slots 11 and 12 are forwarders for functions that were promoted to
|
||||
# generic Stubs
|
||||
|
||||
+60
-27
@@ -136,6 +136,26 @@ typedef int ptrdiff_t;
|
||||
# define vsnprintf _vsnprintf
|
||||
#endif
|
||||
|
||||
#if !defined(TCL_THREADS)
|
||||
# define TCL_THREADS 1
|
||||
#endif
|
||||
#if !TCL_THREADS
|
||||
# undef TCL_DECLARE_MUTEX
|
||||
# define TCL_DECLARE_MUTEX(name)
|
||||
# undef Tcl_MutexLock
|
||||
# define Tcl_MutexLock(mutexPtr)
|
||||
# undef Tcl_MutexUnlock
|
||||
# define Tcl_MutexUnlock(mutexPtr)
|
||||
# undef Tcl_MutexFinalize
|
||||
# define Tcl_MutexFinalize(mutexPtr)
|
||||
# undef Tcl_ConditionNotify
|
||||
# define Tcl_ConditionNotify(condPtr)
|
||||
# undef Tcl_ConditionWait
|
||||
# define Tcl_ConditionWait(condPtr, mutexPtr, timePtr)
|
||||
# undef Tcl_ConditionFinalize
|
||||
# define Tcl_ConditionFinalize(condPtr)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The following procedures allow namespaces to be customized to support
|
||||
* special name resolution rules for commands/variables.
|
||||
@@ -1146,6 +1166,10 @@ typedef struct CallFrame {
|
||||
* field contains an Object reference that has
|
||||
* been confirmed to refer to a class. Part of
|
||||
* TIP#257. */
|
||||
#define FRAME_IS_PRIVATE_DEFINE 0x10
|
||||
/* Marks this frame as being used for private
|
||||
* declarations with [oo::define]. Usually
|
||||
* OR'd with FRAME_IS_OO_DEFINE. TIP#500. */
|
||||
|
||||
/*
|
||||
* TIP #280
|
||||
@@ -2760,6 +2784,10 @@ MODULE_SCOPE long tclObjsShared[TCL_MAX_SHARED_OBJ_STATS];
|
||||
|
||||
MODULE_SCOPE char tclEmptyString;
|
||||
|
||||
enum CheckEmptyStringResult {
|
||||
TCL_EMPTYSTRING_UNKNOWN = -1, TCL_EMPTYSTRING_NO, TCL_EMPTYSTRING_YES
|
||||
};
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------
|
||||
* Procedures shared among Tcl modules but not used by the outside world,
|
||||
@@ -2900,6 +2928,7 @@ MODULE_SCOPE int TclCheckArrayTraces(Tcl_Interp *interp, Var *varPtr,
|
||||
Var *arrayPtr, Tcl_Obj *name, int index);
|
||||
MODULE_SCOPE int TclCheckBadOctal(Tcl_Interp *interp,
|
||||
const char *value);
|
||||
MODULE_SCOPE int TclCheckEmptyString(Tcl_Obj *objPtr);
|
||||
MODULE_SCOPE int TclChanCaughtErrorBypass(Tcl_Interp *interp,
|
||||
Tcl_Channel chan);
|
||||
MODULE_SCOPE Tcl_ObjCmdProc TclChannelNamesCmd;
|
||||
@@ -2915,19 +2944,13 @@ MODULE_SCOPE void TclContinuationsCopy(Tcl_Obj *objPtr,
|
||||
Tcl_Obj *originObjPtr);
|
||||
MODULE_SCOPE int TclConvertElement(const char *src, int length,
|
||||
char *dst, int flags);
|
||||
MODULE_SCOPE Tcl_Command TclCreateObjCommandInNs (
|
||||
Tcl_Interp *interp,
|
||||
const char *cmdName,
|
||||
Tcl_Namespace *nsPtr,
|
||||
Tcl_ObjCmdProc *proc,
|
||||
ClientData clientData,
|
||||
MODULE_SCOPE Tcl_Command TclCreateObjCommandInNs(Tcl_Interp *interp,
|
||||
const char *cmdName, Tcl_Namespace *nsPtr,
|
||||
Tcl_ObjCmdProc *proc, ClientData clientData,
|
||||
Tcl_CmdDeleteProc *deleteProc);
|
||||
MODULE_SCOPE Tcl_Command TclCreateEnsembleInNs(
|
||||
Tcl_Interp *interp,
|
||||
const char *name,
|
||||
Tcl_Namespace *nameNamespacePtr,
|
||||
Tcl_Namespace *ensembleNamespacePtr,
|
||||
int flags);
|
||||
MODULE_SCOPE Tcl_Command TclCreateEnsembleInNs(Tcl_Interp *interp,
|
||||
const char *name, Tcl_Namespace *nameNamespacePtr,
|
||||
Tcl_Namespace *ensembleNamespacePtr, int flags);
|
||||
MODULE_SCOPE void TclDeleteNamespaceVars(Namespace *nsPtr);
|
||||
MODULE_SCOPE int TclFindDictElement(Tcl_Interp *interp,
|
||||
const char *dict, int dictLength,
|
||||
@@ -2954,9 +2977,9 @@ MODULE_SCOPE char * TclDStringAppendObj(Tcl_DString *dsPtr,
|
||||
MODULE_SCOPE char * TclDStringAppendDString(Tcl_DString *dsPtr,
|
||||
Tcl_DString *toAppendPtr);
|
||||
MODULE_SCOPE Tcl_Obj * TclDStringToObj(Tcl_DString *dsPtr);
|
||||
MODULE_SCOPE Tcl_Obj *const * TclFetchEnsembleRoot(Tcl_Interp *interp,
|
||||
MODULE_SCOPE Tcl_Obj *const *TclFetchEnsembleRoot(Tcl_Interp *interp,
|
||||
Tcl_Obj *const *objv, int objc, int *objcPtr);
|
||||
MODULE_SCOPE Tcl_Namespace * TclEnsureNamespace(Tcl_Interp *interp,
|
||||
MODULE_SCOPE Tcl_Namespace *TclEnsureNamespace(Tcl_Interp *interp,
|
||||
Tcl_Namespace *namespacePtr);
|
||||
MODULE_SCOPE void TclFinalizeAllocSubsystem(void);
|
||||
MODULE_SCOPE void TclFinalizeAsync(void);
|
||||
@@ -2984,15 +3007,11 @@ MODULE_SCOPE double TclFloor(const 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_Command TclNRCreateCommandInNs (
|
||||
Tcl_Interp *interp,
|
||||
const char *cmdName,
|
||||
Tcl_Namespace *nsPtr,
|
||||
Tcl_ObjCmdProc *proc,
|
||||
Tcl_ObjCmdProc *nreProc,
|
||||
MODULE_SCOPE Tcl_Command TclNRCreateCommandInNs(Tcl_Interp *interp,
|
||||
const char *cmdName, Tcl_Namespace *nsPtr,
|
||||
Tcl_ObjCmdProc *proc, Tcl_ObjCmdProc *nreProc,
|
||||
ClientData clientData,
|
||||
Tcl_CmdDeleteProc *deleteProc);
|
||||
|
||||
MODULE_SCOPE int TclNREvalFile(Tcl_Interp *interp, Tcl_Obj *pathPtr,
|
||||
const char *encodingName);
|
||||
MODULE_SCOPE void TclFSUnloadTempFile(Tcl_LoadHandle loadHandle);
|
||||
@@ -3173,7 +3192,8 @@ MODULE_SCOPE void TclSetBgErrorHandler(Tcl_Interp *interp,
|
||||
Tcl_Obj *cmdPrefix);
|
||||
MODULE_SCOPE void TclSetBignumIntRep(Tcl_Obj *objPtr,
|
||||
mp_int *bignumValue);
|
||||
MODULE_SCOPE int TclSetBooleanFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);
|
||||
MODULE_SCOPE int TclSetBooleanFromAny(Tcl_Interp *interp,
|
||||
Tcl_Obj *objPtr);
|
||||
MODULE_SCOPE void TclSetCmdNameObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
|
||||
Command *cmdPtr);
|
||||
MODULE_SCOPE void TclSetDuplicateObj(Tcl_Obj *dupPtr, Tcl_Obj *objPtr);
|
||||
@@ -3185,6 +3205,12 @@ MODULE_SCOPE void TclSpellFix(Tcl_Interp *interp,
|
||||
Tcl_Obj *bad, Tcl_Obj *fix);
|
||||
MODULE_SCOPE void * TclStackRealloc(Tcl_Interp *interp, void *ptr,
|
||||
int numBytes);
|
||||
typedef int (*memCmpFn_t)(const void*, const void*, size_t);
|
||||
MODULE_SCOPE int TclStringCmp(Tcl_Obj *value1Ptr, Tcl_Obj *value2Ptr,
|
||||
int checkEq, int nocase, int reqlength);
|
||||
MODULE_SCOPE int TclStringCmpOpts(Tcl_Interp *interp, int objc,
|
||||
Tcl_Obj *const objv[], int *nocase,
|
||||
int *reqlength);
|
||||
MODULE_SCOPE int TclStringMatch(const char *str, int strLen,
|
||||
const char *pattern, int ptnLen, int flags);
|
||||
MODULE_SCOPE int TclStringMatchObj(Tcl_Obj *stringObj,
|
||||
@@ -3233,8 +3259,8 @@ MODULE_SCOPE void * TclpThreadCreateKey(void);
|
||||
MODULE_SCOPE void TclpThreadDeleteKey(void *keyPtr);
|
||||
MODULE_SCOPE void TclpThreadSetMasterTSD(void *tsdKeyPtr, void *ptr);
|
||||
MODULE_SCOPE void * TclpThreadGetMasterTSD(void *tsdKeyPtr);
|
||||
|
||||
MODULE_SCOPE void TclErrorStackResetIf(Tcl_Interp *interp, const char *msg, int length);
|
||||
MODULE_SCOPE void TclErrorStackResetIf(Tcl_Interp *interp,
|
||||
const char *msg, int length);
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------
|
||||
@@ -4087,7 +4113,7 @@ typedef enum TclProcessWaitStatus {
|
||||
TCL_PROCESS_EXITED = 1, /* Process has exited. */
|
||||
TCL_PROCESS_SIGNALED = 2, /* Child killed because of a signal. */
|
||||
TCL_PROCESS_STOPPED = 3, /* Child suspended because of a signal. */
|
||||
TCL_PROCESS_UNKNOWN_STATUS = 4
|
||||
TCL_PROCESS_UNKNOWN_STATUS = 4
|
||||
/* Child wait status didn't make sense. */
|
||||
} TclProcessWaitStatus;
|
||||
|
||||
@@ -4198,6 +4224,10 @@ typedef const char *TclDTraceStr;
|
||||
} \
|
||||
}
|
||||
|
||||
#if TCL_THREADS && !defined(USE_THREAD_ALLOC)
|
||||
# define USE_THREAD_ALLOC 1
|
||||
#endif
|
||||
|
||||
#if defined(PURIFY)
|
||||
|
||||
/*
|
||||
@@ -4215,7 +4245,7 @@ typedef const char *TclDTraceStr;
|
||||
|
||||
#undef USE_THREAD_ALLOC
|
||||
#undef USE_TCLALLOC
|
||||
#elif defined(TCL_THREADS) && defined(USE_THREAD_ALLOC)
|
||||
#elif TCL_THREADS && defined(USE_THREAD_ALLOC)
|
||||
|
||||
/*
|
||||
* The TCL_THREADS mode is like the regular mode but allocates Tcl_Obj's from
|
||||
@@ -4280,7 +4310,7 @@ MODULE_SCOPE void TclpFreeAllocCache(void *);
|
||||
# define USE_TCLALLOC 0
|
||||
#endif
|
||||
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
/* declared in tclObj.c */
|
||||
MODULE_SCOPE Tcl_Mutex tclObjMutex;
|
||||
#endif
|
||||
@@ -4540,6 +4570,9 @@ MODULE_SCOPE void TclDbInitNewObj(Tcl_Obj *objPtr, const char *file,
|
||||
*/
|
||||
|
||||
MODULE_SCOPE int TclIsPureByteArray(Tcl_Obj *objPtr);
|
||||
#define TclIsPureDict(objPtr) \
|
||||
(((objPtr)->bytes==NULL) && ((objPtr)->typePtr==&tclDictType))
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------
|
||||
|
||||
@@ -13,11 +13,6 @@
|
||||
#ifndef _TCLINTPLATDECLS
|
||||
#define _TCLINTPLATDECLS
|
||||
|
||||
#ifdef _WIN32
|
||||
# define Tcl_DirEntry void
|
||||
# define DIR void
|
||||
#endif
|
||||
|
||||
#undef TCL_STORAGE_CLASS
|
||||
#ifdef BUILD_tcl
|
||||
# define TCL_STORAGE_CLASS DLLEXPORT
|
||||
@@ -72,7 +67,7 @@ EXTERN int TclUnixWaitForFile(int fd, int mask, int timeout);
|
||||
/* 9 */
|
||||
EXTERN TclFile TclpCreateTempFile(const char *contents);
|
||||
/* 10 */
|
||||
EXTERN Tcl_DirEntry * TclpReaddir(DIR *dir);
|
||||
EXTERN Tcl_DirEntry * TclpReaddir(TclDIR *dir);
|
||||
/* 11 */
|
||||
EXTERN struct tm * TclpLocaltime_unix(const time_t *clock);
|
||||
/* 12 */
|
||||
@@ -129,7 +124,7 @@ EXTERN int TclpGetPid(Tcl_Pid pid);
|
||||
/* 9 */
|
||||
EXTERN int TclWinGetPlatformId(void);
|
||||
/* 10 */
|
||||
EXTERN Tcl_DirEntry * TclpReaddir(DIR *dir);
|
||||
EXTERN Tcl_DirEntry * TclpReaddir(TclDIR *dir);
|
||||
/* 11 */
|
||||
EXTERN void TclGetAndDetachPids(Tcl_Interp *interp,
|
||||
Tcl_Channel chan);
|
||||
@@ -206,7 +201,7 @@ EXTERN int TclUnixWaitForFile(int fd, int mask, int timeout);
|
||||
/* 9 */
|
||||
EXTERN TclFile TclpCreateTempFile(const char *contents);
|
||||
/* 10 */
|
||||
EXTERN Tcl_DirEntry * TclpReaddir(DIR *dir);
|
||||
EXTERN Tcl_DirEntry * TclpReaddir(TclDIR *dir);
|
||||
/* 11 */
|
||||
EXTERN struct tm * TclpLocaltime_unix(const time_t *clock);
|
||||
/* 12 */
|
||||
@@ -269,7 +264,7 @@ typedef struct TclIntPlatStubs {
|
||||
TclFile (*tclpOpenFile) (const char *fname, int mode); /* 7 */
|
||||
int (*tclUnixWaitForFile) (int fd, int mask, int timeout); /* 8 */
|
||||
TclFile (*tclpCreateTempFile) (const char *contents); /* 9 */
|
||||
Tcl_DirEntry * (*tclpReaddir) (DIR *dir); /* 10 */
|
||||
Tcl_DirEntry * (*tclpReaddir) (TclDIR *dir); /* 10 */
|
||||
struct tm * (*tclpLocaltime_unix) (const time_t *clock); /* 11 */
|
||||
struct tm * (*tclpGmtime_unix) (const time_t *clock); /* 12 */
|
||||
char * (*tclpInetNtoa) (struct in_addr addr); /* 13 */
|
||||
@@ -302,7 +297,7 @@ typedef struct TclIntPlatStubs {
|
||||
int (*tclWinSetSockOpt) (SOCKET s, int level, int optname, const char *optval, int optlen); /* 7 */
|
||||
int (*tclpGetPid) (Tcl_Pid pid); /* 8 */
|
||||
int (*tclWinGetPlatformId) (void); /* 9 */
|
||||
Tcl_DirEntry * (*tclpReaddir) (DIR *dir); /* 10 */
|
||||
Tcl_DirEntry * (*tclpReaddir) (TclDIR *dir); /* 10 */
|
||||
void (*tclGetAndDetachPids) (Tcl_Interp *interp, Tcl_Channel chan); /* 11 */
|
||||
int (*tclpCloseFile) (TclFile file); /* 12 */
|
||||
Tcl_Channel (*tclpCreateCommandChannel) (TclFile readFile, TclFile writeFile, TclFile errorFile, int numPids, Tcl_Pid *pidPtr); /* 13 */
|
||||
@@ -335,7 +330,7 @@ typedef struct TclIntPlatStubs {
|
||||
TclFile (*tclpOpenFile) (const char *fname, int mode); /* 7 */
|
||||
int (*tclUnixWaitForFile) (int fd, int mask, int timeout); /* 8 */
|
||||
TclFile (*tclpCreateTempFile) (const char *contents); /* 9 */
|
||||
Tcl_DirEntry * (*tclpReaddir) (DIR *dir); /* 10 */
|
||||
Tcl_DirEntry * (*tclpReaddir) (TclDIR *dir); /* 10 */
|
||||
struct tm * (*tclpLocaltime_unix) (const time_t *clock); /* 11 */
|
||||
struct tm * (*tclpGmtime_unix) (const time_t *clock); /* 12 */
|
||||
char * (*tclpInetNtoa) (struct in_addr addr); /* 13 */
|
||||
|
||||
+2019
-294
File diff suppressed because it is too large
Load Diff
+67
-8
@@ -31,6 +31,7 @@ static const struct {
|
||||
{"export", TclOODefineExportObjCmd, 0},
|
||||
{"forward", TclOODefineForwardObjCmd, 0},
|
||||
{"method", TclOODefineMethodObjCmd, 0},
|
||||
{"private", TclOODefinePrivateObjCmd, 0},
|
||||
{"renamemethod", TclOODefineRenameMethodObjCmd, 0},
|
||||
{"self", TclOODefineSelfObjCmd, 0},
|
||||
{"unexport", TclOODefineUnexportObjCmd, 0},
|
||||
@@ -41,6 +42,7 @@ static const struct {
|
||||
{"export", TclOODefineExportObjCmd, 1},
|
||||
{"forward", TclOODefineForwardObjCmd, 1},
|
||||
{"method", TclOODefineMethodObjCmd, 1},
|
||||
{"private", TclOODefinePrivateObjCmd, 1},
|
||||
{"renamemethod", TclOODefineRenameMethodObjCmd, 1},
|
||||
{"self", TclOODefineObjSelfObjCmd, 0},
|
||||
{"unexport", TclOODefineUnexportObjCmd, 1},
|
||||
@@ -993,6 +995,7 @@ ReleaseClassContents(
|
||||
Method *mPtr;
|
||||
Foundation *fPtr = oPtr->fPtr;
|
||||
Tcl_Obj *variableObj;
|
||||
PrivateVariableMapping *privateVariable;
|
||||
|
||||
/*
|
||||
* Sanity check!
|
||||
@@ -1099,6 +1102,14 @@ ReleaseClassContents(
|
||||
ckfree(clsPtr->variables.list);
|
||||
}
|
||||
|
||||
FOREACH_STRUCT(privateVariable, clsPtr->privateVariables) {
|
||||
TclDecrRefCount(privateVariable->variableObj);
|
||||
TclDecrRefCount(privateVariable->fullNameObj);
|
||||
}
|
||||
if (i) {
|
||||
ckfree(clsPtr->privateVariables.list);
|
||||
}
|
||||
|
||||
if (IsRootClass(oPtr) && !Deleted(fPtr->objectCls->thisPtr)) {
|
||||
Tcl_DeleteCommandFromToken(interp, fPtr->objectCls->thisPtr->command);
|
||||
}
|
||||
@@ -1128,6 +1139,7 @@ ObjectNamespaceDeleted(
|
||||
Class *mixinPtr;
|
||||
Method *mPtr;
|
||||
Tcl_Obj *filterObj, *variableObj;
|
||||
PrivateVariableMapping *privateVariable;
|
||||
Tcl_Interp *interp = oPtr->fPtr->interp;
|
||||
int i;
|
||||
|
||||
@@ -1162,7 +1174,7 @@ ObjectNamespaceDeleted(
|
||||
|
||||
if (!Tcl_InterpDeleted(interp) && !(oPtr->flags & DESTRUCTOR_CALLED)) {
|
||||
CallContext *contextPtr =
|
||||
TclOOGetCallContext(oPtr, NULL, DESTRUCTOR, NULL);
|
||||
TclOOGetCallContext(oPtr, NULL, DESTRUCTOR, NULL, NULL, NULL);
|
||||
int result;
|
||||
|
||||
Tcl_InterpState state;
|
||||
@@ -1248,6 +1260,14 @@ ObjectNamespaceDeleted(
|
||||
ckfree(oPtr->variables.list);
|
||||
}
|
||||
|
||||
FOREACH_STRUCT(privateVariable, oPtr->privateVariables) {
|
||||
TclDecrRefCount(privateVariable->variableObj);
|
||||
TclDecrRefCount(privateVariable->fullNameObj);
|
||||
}
|
||||
if (i) {
|
||||
ckfree(oPtr->privateVariables.list);
|
||||
}
|
||||
|
||||
if (oPtr->chainCache) {
|
||||
TclOODeleteChainCache(oPtr->chainCache);
|
||||
}
|
||||
@@ -1631,7 +1651,7 @@ Tcl_NewObjectInstance(
|
||||
|
||||
if (objc >= 0) {
|
||||
CallContext *contextPtr =
|
||||
TclOOGetCallContext(oPtr, NULL, CONSTRUCTOR, NULL);
|
||||
TclOOGetCallContext(oPtr, NULL, CONSTRUCTOR, NULL, NULL, NULL);
|
||||
|
||||
if (contextPtr != NULL) {
|
||||
int isRoot, result;
|
||||
@@ -1704,7 +1724,7 @@ TclNRNewObjectInstance(
|
||||
*objectPtr = (Tcl_Object) oPtr;
|
||||
return TCL_OK;
|
||||
}
|
||||
contextPtr = TclOOGetCallContext(oPtr, NULL, CONSTRUCTOR, NULL);
|
||||
contextPtr = TclOOGetCallContext(oPtr, NULL, CONSTRUCTOR, NULL, NULL, NULL);
|
||||
if (contextPtr == NULL) {
|
||||
*objectPtr = (Tcl_Object) oPtr;
|
||||
return TCL_OK;
|
||||
@@ -1884,6 +1904,7 @@ Tcl_CopyObjectInstance(
|
||||
Class *mixinPtr;
|
||||
CallContext *contextPtr;
|
||||
Tcl_Obj *keyPtr, *filterObj, *variableObj, *args[3];
|
||||
PrivateVariableMapping *privateVariable;
|
||||
int i, result;
|
||||
|
||||
/*
|
||||
@@ -1953,7 +1974,7 @@ Tcl_CopyObjectInstance(
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy the object's variable resolution list to the new object.
|
||||
* Copy the object's variable resolution lists to the new object.
|
||||
*/
|
||||
|
||||
DUPLICATE(o2Ptr->variables, oPtr->variables, Tcl_Obj *);
|
||||
@@ -1961,6 +1982,13 @@ Tcl_CopyObjectInstance(
|
||||
Tcl_IncrRefCount(variableObj);
|
||||
}
|
||||
|
||||
DUPLICATE(o2Ptr->privateVariables, oPtr->privateVariables,
|
||||
PrivateVariableMapping);
|
||||
FOREACH_STRUCT(privateVariable, o2Ptr->privateVariables) {
|
||||
Tcl_IncrRefCount(privateVariable->variableObj);
|
||||
Tcl_IncrRefCount(privateVariable->fullNameObj);
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy the object's flags to the new object, clearing those that must be
|
||||
* kept object-local. The duplicate is never deleted at this point, nor is
|
||||
@@ -2049,7 +2077,7 @@ Tcl_CopyObjectInstance(
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy the source class's variable resolution list.
|
||||
* Copy the source class's variable resolution lists.
|
||||
*/
|
||||
|
||||
DUPLICATE(cls2Ptr->variables, clsPtr->variables, Tcl_Obj *);
|
||||
@@ -2057,6 +2085,13 @@ Tcl_CopyObjectInstance(
|
||||
Tcl_IncrRefCount(variableObj);
|
||||
}
|
||||
|
||||
DUPLICATE(cls2Ptr->privateVariables, clsPtr->privateVariables,
|
||||
PrivateVariableMapping);
|
||||
FOREACH_STRUCT(privateVariable, cls2Ptr->privateVariables) {
|
||||
Tcl_IncrRefCount(privateVariable->variableObj);
|
||||
Tcl_IncrRefCount(privateVariable->fullNameObj);
|
||||
}
|
||||
|
||||
/*
|
||||
* Duplicate the source class's mixins (which cannot be circular
|
||||
* references to the duplicate).
|
||||
@@ -2129,7 +2164,8 @@ Tcl_CopyObjectInstance(
|
||||
}
|
||||
|
||||
TclResetRewriteEnsemble(interp, 1);
|
||||
contextPtr = TclOOGetCallContext(o2Ptr, oPtr->fPtr->clonedName, 0, NULL);
|
||||
contextPtr = TclOOGetCallContext(o2Ptr, oPtr->fPtr->clonedName, 0, NULL,
|
||||
NULL, NULL);
|
||||
if (contextPtr) {
|
||||
args[0] = TclOOObjectName(interp, o2Ptr);
|
||||
args[1] = oPtr->fPtr->clonedName;
|
||||
@@ -2526,6 +2562,9 @@ TclOOObjectCmdCore(
|
||||
{
|
||||
CallContext *contextPtr;
|
||||
Tcl_Obj *methodNamePtr;
|
||||
CallFrame *framePtr = ((Interp *) interp)->varFramePtr;
|
||||
Object *callerObjPtr = NULL;
|
||||
Class *callerClsPtr = NULL;
|
||||
int result;
|
||||
|
||||
/*
|
||||
@@ -2539,6 +2578,24 @@ TclOOObjectCmdCore(
|
||||
goto noMapping;
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine if we're in a context that can see the extra, private methods
|
||||
* in this class.
|
||||
*/
|
||||
|
||||
if (framePtr->isProcCallFrame & FRAME_IS_METHOD) {
|
||||
CallContext *callerContextPtr = framePtr->clientData;
|
||||
Method *callerMethodPtr =
|
||||
callerContextPtr->callPtr->chain[callerContextPtr->index].mPtr;
|
||||
|
||||
if (callerMethodPtr->declaringObjectPtr) {
|
||||
callerObjPtr = callerMethodPtr->declaringObjectPtr;
|
||||
}
|
||||
if (callerMethodPtr->declaringClassPtr) {
|
||||
callerClsPtr = callerMethodPtr->declaringClassPtr;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Give plugged in code a chance to remap the method name.
|
||||
*/
|
||||
@@ -2566,7 +2623,8 @@ TclOOObjectCmdCore(
|
||||
|
||||
Tcl_IncrRefCount(mappedMethodName);
|
||||
contextPtr = TclOOGetCallContext(oPtr, mappedMethodName,
|
||||
flags | (oPtr->flags & FILTER_HANDLING), methodNamePtr);
|
||||
flags | (oPtr->flags & FILTER_HANDLING), callerObjPtr,
|
||||
callerClsPtr, methodNamePtr);
|
||||
TclDecrRefCount(mappedMethodName);
|
||||
if (contextPtr == NULL) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
@@ -2583,7 +2641,8 @@ TclOOObjectCmdCore(
|
||||
|
||||
noMapping:
|
||||
contextPtr = TclOOGetCallContext(oPtr, methodNamePtr,
|
||||
flags | (oPtr->flags & FILTER_HANDLING), NULL);
|
||||
flags | (oPtr->flags & FILTER_HANDLING), callerObjPtr,
|
||||
callerClsPtr, NULL);
|
||||
if (contextPtr == NULL) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"impossible to invoke method \"%s\": no defined method or"
|
||||
|
||||
+5
-2
@@ -58,12 +58,12 @@ declare 10 {
|
||||
}
|
||||
declare 11 {
|
||||
Tcl_Method Tcl_NewInstanceMethod(Tcl_Interp *interp, Tcl_Object object,
|
||||
Tcl_Obj *nameObj, int isPublic, const Tcl_MethodType *typePtr,
|
||||
Tcl_Obj *nameObj, int flags, const Tcl_MethodType *typePtr,
|
||||
ClientData clientData)
|
||||
}
|
||||
declare 12 {
|
||||
Tcl_Method Tcl_NewMethod(Tcl_Interp *interp, Tcl_Class cls,
|
||||
Tcl_Obj *nameObj, int isPublic, const Tcl_MethodType *typePtr,
|
||||
Tcl_Obj *nameObj, int flags, const Tcl_MethodType *typePtr,
|
||||
ClientData clientData)
|
||||
}
|
||||
declare 13 {
|
||||
@@ -126,6 +126,9 @@ declare 27 {
|
||||
declare 28 {
|
||||
Tcl_Obj *Tcl_GetObjectName(Tcl_Interp *interp, Tcl_Object object)
|
||||
}
|
||||
declare 29 {
|
||||
int Tcl_MethodIsPrivate(Tcl_Method method)
|
||||
}
|
||||
|
||||
######################################################################
|
||||
# Private API, exposed to support advanced OO systems that plug in on top of
|
||||
|
||||
@@ -99,6 +99,15 @@ typedef struct {
|
||||
*/
|
||||
|
||||
#define TCL_OO_METHOD_VERSION_CURRENT 1
|
||||
|
||||
/*
|
||||
* Visibility constants for the flags parameter to Tcl_NewMethod and
|
||||
* Tcl_NewInstanceMethod.
|
||||
*/
|
||||
|
||||
#define TCL_OO_METHOD_PUBLIC 1
|
||||
#define TCL_OO_METHOD_UNEXPORTED 0
|
||||
#define TCL_OO_METHOD_PRIVATE 0x20
|
||||
|
||||
/*
|
||||
* The type of some object (or class) metadata. This describes how to delete
|
||||
|
||||
+84
-16
@@ -347,7 +347,8 @@ TclOO_Object_Destroy(
|
||||
}
|
||||
if (!(oPtr->flags & DESTRUCTOR_CALLED)) {
|
||||
oPtr->flags |= DESTRUCTOR_CALLED;
|
||||
contextPtr = TclOOGetCallContext(oPtr, NULL, DESTRUCTOR, NULL);
|
||||
contextPtr = TclOOGetCallContext(oPtr, NULL, DESTRUCTOR, NULL, NULL,
|
||||
NULL);
|
||||
if (contextPtr != NULL) {
|
||||
contextPtr->callPtr->flags |= DESTRUCTOR;
|
||||
contextPtr->skip = 0;
|
||||
@@ -499,9 +500,12 @@ TclOO_Object_Unknown(
|
||||
Tcl_Obj *const *objv) /* The actual arguments. */
|
||||
{
|
||||
CallContext *contextPtr = (CallContext *) context;
|
||||
Object *callerObj = NULL;
|
||||
Class *callerCls = NULL;
|
||||
Object *oPtr = contextPtr->oPtr;
|
||||
const char **methodNames;
|
||||
int numMethodNames, i, skip = Tcl_ObjectContextSkippedArgs(context);
|
||||
CallFrame *framePtr = ((Interp *) interp)->varFramePtr;
|
||||
Tcl_Obj *errorMsg;
|
||||
|
||||
/*
|
||||
@@ -515,11 +519,32 @@ TclOO_Object_Unknown(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine if the calling context should know about extra private
|
||||
* methods, and if so, which.
|
||||
*/
|
||||
|
||||
if (framePtr->isProcCallFrame & FRAME_IS_METHOD) {
|
||||
CallContext *callerContext = framePtr->clientData;
|
||||
Method *mPtr = callerContext->callPtr->chain[
|
||||
callerContext->index].mPtr;
|
||||
|
||||
if (mPtr->declaringObjectPtr) {
|
||||
if (oPtr == mPtr->declaringObjectPtr) {
|
||||
callerObj = mPtr->declaringObjectPtr;
|
||||
}
|
||||
} else {
|
||||
if (TclOOIsReachable(mPtr->declaringClassPtr, oPtr->selfCls)) {
|
||||
callerCls = mPtr->declaringClassPtr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the list of methods that we want to know about.
|
||||
*/
|
||||
|
||||
numMethodNames = TclOOGetSortedMethodList(oPtr,
|
||||
numMethodNames = TclOOGetSortedMethodList(oPtr, callerObj, callerCls,
|
||||
contextPtr->callPtr->flags & PUBLIC_METHOD, &methodNames);
|
||||
|
||||
/*
|
||||
@@ -684,6 +709,7 @@ TclOO_Object_VarName(
|
||||
{
|
||||
Var *varPtr, *aryVar;
|
||||
Tcl_Obj *varNamePtr, *argPtr;
|
||||
CallFrame *framePtr = ((Interp *) interp)->varFramePtr;
|
||||
const char *arg;
|
||||
|
||||
if (Tcl_ObjectContextSkippedArgs(context)+1 != objc) {
|
||||
@@ -709,6 +735,58 @@ TclOO_Object_VarName(
|
||||
Tcl_Namespace *namespacePtr =
|
||||
Tcl_GetObjectNamespace(Tcl_ObjectContextObject(context));
|
||||
|
||||
/*
|
||||
* Private method handling. [TIP 500]
|
||||
*
|
||||
* If we're in a context that can see some private methods of an
|
||||
* object, we may need to precede a variable name with its prefix.
|
||||
* This is a little tricky as we need to check through the inheritance
|
||||
* hierarchy when the method was declared by a class to see if the
|
||||
* current object is an instance of that class.
|
||||
*/
|
||||
|
||||
if (framePtr->isProcCallFrame & FRAME_IS_METHOD) {
|
||||
Object *oPtr = (Object *) Tcl_ObjectContextObject(context);
|
||||
CallContext *callerContext = framePtr->clientData;
|
||||
Method *mPtr = callerContext->callPtr->chain[
|
||||
callerContext->index].mPtr;
|
||||
PrivateVariableMapping *pvPtr;
|
||||
int i;
|
||||
|
||||
if (mPtr->declaringObjectPtr == oPtr) {
|
||||
FOREACH_STRUCT(pvPtr, oPtr->privateVariables) {
|
||||
if (!strcmp(Tcl_GetString(pvPtr->variableObj),
|
||||
Tcl_GetString(argPtr))) {
|
||||
argPtr = pvPtr->fullNameObj;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (mPtr->declaringClassPtr &&
|
||||
mPtr->declaringClassPtr->privateVariables.num) {
|
||||
Class *clsPtr = mPtr->declaringClassPtr;
|
||||
int isInstance = TclOOIsReachable(clsPtr, oPtr->selfCls);
|
||||
Class *mixinCls;
|
||||
|
||||
if (!isInstance) {
|
||||
FOREACH(mixinCls, oPtr->mixins) {
|
||||
if (TclOOIsReachable(clsPtr, mixinCls)) {
|
||||
isInstance = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isInstance) {
|
||||
FOREACH_STRUCT(pvPtr, clsPtr->privateVariables) {
|
||||
if (!strcmp(Tcl_GetString(pvPtr->variableObj),
|
||||
Tcl_GetString(argPtr))) {
|
||||
argPtr = pvPtr->fullNameObj;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
varNamePtr = Tcl_NewStringObj(namespacePtr->fullName, -1);
|
||||
Tcl_AppendToObj(varNamePtr, "::", 2);
|
||||
Tcl_AppendObjToObj(varNamePtr, argPtr);
|
||||
@@ -729,26 +807,16 @@ TclOO_Object_VarName(
|
||||
|
||||
varNamePtr = Tcl_NewObj();
|
||||
if (aryVar != NULL) {
|
||||
Tcl_HashEntry *hPtr;
|
||||
Tcl_HashSearch search;
|
||||
|
||||
Tcl_GetVariableFullName(interp, (Tcl_Var) aryVar, varNamePtr);
|
||||
|
||||
/*
|
||||
* WARNING! This code pokes inside the implementation of hash tables!
|
||||
*/
|
||||
|
||||
hPtr = Tcl_FirstHashEntry((Tcl_HashTable *) aryVar->value.tablePtr,
|
||||
&search);
|
||||
while (hPtr != NULL) {
|
||||
if (varPtr == Tcl_GetHashValue(hPtr)) {
|
||||
Tcl_AppendToObj(varNamePtr, "(", -1);
|
||||
Tcl_AppendObjToObj(varNamePtr, hPtr->key.objPtr);
|
||||
Tcl_AppendToObj(varNamePtr, ")", -1);
|
||||
break;
|
||||
}
|
||||
hPtr = Tcl_NextHashEntry(&search);
|
||||
}
|
||||
Tcl_AppendToObj(varNamePtr, "(", -1);
|
||||
Tcl_AppendObjToObj(varNamePtr, ((VarInHash *)
|
||||
varPtr)->entry.key.objPtr);
|
||||
Tcl_AppendToObj(varNamePtr, ")", -1);
|
||||
} else {
|
||||
Tcl_GetVariableFullName(interp, (Tcl_Var) varPtr, varNamePtr);
|
||||
}
|
||||
|
||||
+470
-212
File diff suppressed because it is too large
Load Diff
@@ -59,11 +59,11 @@ TCLAPI Tcl_Obj * Tcl_MethodName(Tcl_Method method);
|
||||
/* 11 */
|
||||
TCLAPI Tcl_Method Tcl_NewInstanceMethod(Tcl_Interp *interp,
|
||||
Tcl_Object object, Tcl_Obj *nameObj,
|
||||
int isPublic, const Tcl_MethodType *typePtr,
|
||||
int flags, const Tcl_MethodType *typePtr,
|
||||
ClientData clientData);
|
||||
/* 12 */
|
||||
TCLAPI Tcl_Method Tcl_NewMethod(Tcl_Interp *interp, Tcl_Class cls,
|
||||
Tcl_Obj *nameObj, int isPublic,
|
||||
Tcl_Obj *nameObj, int flags,
|
||||
const Tcl_MethodType *typePtr,
|
||||
ClientData clientData);
|
||||
/* 13 */
|
||||
@@ -116,6 +116,8 @@ TCLAPI void Tcl_ClassSetDestructor(Tcl_Interp *interp,
|
||||
/* 28 */
|
||||
TCLAPI Tcl_Obj * Tcl_GetObjectName(Tcl_Interp *interp,
|
||||
Tcl_Object object);
|
||||
/* 29 */
|
||||
TCLAPI int Tcl_MethodIsPrivate(Tcl_Method method);
|
||||
|
||||
typedef struct {
|
||||
const struct TclOOIntStubs *tclOOIntStubs;
|
||||
@@ -136,8 +138,8 @@ typedef struct TclOOStubs {
|
||||
int (*tcl_MethodIsPublic) (Tcl_Method method); /* 8 */
|
||||
int (*tcl_MethodIsType) (Tcl_Method method, const Tcl_MethodType *typePtr, ClientData *clientDataPtr); /* 9 */
|
||||
Tcl_Obj * (*tcl_MethodName) (Tcl_Method method); /* 10 */
|
||||
Tcl_Method (*tcl_NewInstanceMethod) (Tcl_Interp *interp, Tcl_Object object, Tcl_Obj *nameObj, int isPublic, const Tcl_MethodType *typePtr, ClientData clientData); /* 11 */
|
||||
Tcl_Method (*tcl_NewMethod) (Tcl_Interp *interp, Tcl_Class cls, Tcl_Obj *nameObj, int isPublic, const Tcl_MethodType *typePtr, ClientData clientData); /* 12 */
|
||||
Tcl_Method (*tcl_NewInstanceMethod) (Tcl_Interp *interp, Tcl_Object object, Tcl_Obj *nameObj, int flags, const Tcl_MethodType *typePtr, ClientData clientData); /* 11 */
|
||||
Tcl_Method (*tcl_NewMethod) (Tcl_Interp *interp, Tcl_Class cls, Tcl_Obj *nameObj, int flags, const Tcl_MethodType *typePtr, ClientData clientData); /* 12 */
|
||||
Tcl_Object (*tcl_NewObjectInstance) (Tcl_Interp *interp, Tcl_Class cls, const char *nameStr, const char *nsNameStr, int objc, Tcl_Obj *const *objv, int skip); /* 13 */
|
||||
int (*tcl_ObjectDeleted) (Tcl_Object object); /* 14 */
|
||||
int (*tcl_ObjectContextIsFiltering) (Tcl_ObjectContext context); /* 15 */
|
||||
@@ -154,6 +156,7 @@ typedef struct TclOOStubs {
|
||||
void (*tcl_ClassSetConstructor) (Tcl_Interp *interp, Tcl_Class clazz, Tcl_Method method); /* 26 */
|
||||
void (*tcl_ClassSetDestructor) (Tcl_Interp *interp, Tcl_Class clazz, Tcl_Method method); /* 27 */
|
||||
Tcl_Obj * (*tcl_GetObjectName) (Tcl_Interp *interp, Tcl_Object object); /* 28 */
|
||||
int (*tcl_MethodIsPrivate) (Tcl_Method method); /* 29 */
|
||||
} TclOOStubs;
|
||||
|
||||
extern const TclOOStubs *tclOOStubsPtr;
|
||||
@@ -226,6 +229,8 @@ extern const TclOOStubs *tclOOStubsPtr;
|
||||
(tclOOStubsPtr->tcl_ClassSetDestructor) /* 27 */
|
||||
#define Tcl_GetObjectName \
|
||||
(tclOOStubsPtr->tcl_GetObjectName) /* 28 */
|
||||
#define Tcl_MethodIsPrivate \
|
||||
(tclOOStubsPtr->tcl_MethodIsPrivate) /* 29 */
|
||||
|
||||
#endif /* defined(USE_TCLOO_STUBS) */
|
||||
|
||||
|
||||
+284
-100
@@ -16,6 +16,12 @@
|
||||
#include "tclInt.h"
|
||||
#include "tclOOInt.h"
|
||||
|
||||
/*
|
||||
* The actual value used to mark private declaration frames.
|
||||
*/
|
||||
|
||||
#define PRIVATE_FRAME (FRAME_IS_OO_DEFINE | FRAME_IS_PRIVATE_DEFINE)
|
||||
|
||||
/*
|
||||
* The maximum length of fully-qualified object name to use in an errorinfo
|
||||
* message. Longer than this will be curtailed.
|
||||
@@ -118,6 +124,35 @@ static const struct DeclaredSlot slots[] = {
|
||||
SLOT("objdefine::variable", ObjVarsGet, ObjVarsSet),
|
||||
{NULL, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}}
|
||||
};
|
||||
|
||||
/*
|
||||
* How to build the in-namespace name of a private variable. This is a pattern
|
||||
* used with Tcl_ObjPrintf().
|
||||
*/
|
||||
|
||||
#define PRIVATE_VARIABLE_PATTERN "%d : %s"
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* IsPrivateDefine --
|
||||
*
|
||||
* Extracts whether the current context is handling private definitions.
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static inline int
|
||||
IsPrivateDefine(
|
||||
Tcl_Interp *interp)
|
||||
{
|
||||
Interp *iPtr = (Interp *) interp;
|
||||
|
||||
if (!iPtr->varFramePtr) {
|
||||
return 0;
|
||||
}
|
||||
return iPtr->varFramePtr->isProcCallFrame == PRIVATE_FRAME;
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------
|
||||
@@ -416,6 +451,123 @@ TclOOClassSetMixins(
|
||||
BumpGlobalEpoch(interp, classPtr);
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* InstallStandardVariableMapping, InstallPrivateVariableMapping --
|
||||
*
|
||||
* Helpers for installing standard and private variable maps.
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*/
|
||||
static inline void
|
||||
InstallStandardVariableMapping(
|
||||
VariableNameList *vnlPtr,
|
||||
int varc,
|
||||
Tcl_Obj *const *varv)
|
||||
{
|
||||
Tcl_Obj *variableObj;
|
||||
int i, n, created;
|
||||
Tcl_HashTable uniqueTable;
|
||||
|
||||
for (i=0 ; i<varc ; i++) {
|
||||
Tcl_IncrRefCount(varv[i]);
|
||||
}
|
||||
FOREACH(variableObj, *vnlPtr) {
|
||||
Tcl_DecrRefCount(variableObj);
|
||||
}
|
||||
if (i != varc) {
|
||||
if (varc == 0) {
|
||||
ckfree(vnlPtr->list);
|
||||
} else if (i) {
|
||||
vnlPtr->list = ckrealloc(vnlPtr->list, sizeof(Tcl_Obj *) * varc);
|
||||
} else {
|
||||
vnlPtr->list = ckalloc(sizeof(Tcl_Obj *) * varc);
|
||||
}
|
||||
}
|
||||
vnlPtr->num = 0;
|
||||
if (varc > 0) {
|
||||
Tcl_InitObjHashTable(&uniqueTable);
|
||||
for (i=n=0 ; i<varc ; i++) {
|
||||
Tcl_CreateHashEntry(&uniqueTable, varv[i], &created);
|
||||
if (created) {
|
||||
vnlPtr->list[n++] = varv[i];
|
||||
} else {
|
||||
Tcl_DecrRefCount(varv[i]);
|
||||
}
|
||||
}
|
||||
vnlPtr->num = n;
|
||||
|
||||
/*
|
||||
* Shouldn't be necessary, but maintain num/list invariant.
|
||||
*/
|
||||
|
||||
if (n != varc) {
|
||||
vnlPtr->list = ckrealloc(vnlPtr->list, sizeof(Tcl_Obj *) * n);
|
||||
}
|
||||
Tcl_DeleteHashTable(&uniqueTable);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
InstallPrivateVariableMapping(
|
||||
PrivateVariableList *pvlPtr,
|
||||
int varc,
|
||||
Tcl_Obj *const *varv,
|
||||
int creationEpoch)
|
||||
{
|
||||
PrivateVariableMapping *privatePtr;
|
||||
int i, n, created;
|
||||
Tcl_HashTable uniqueTable;
|
||||
|
||||
for (i=0 ; i<varc ; i++) {
|
||||
Tcl_IncrRefCount(varv[i]);
|
||||
}
|
||||
FOREACH_STRUCT(privatePtr, *pvlPtr) {
|
||||
Tcl_DecrRefCount(privatePtr->variableObj);
|
||||
Tcl_DecrRefCount(privatePtr->fullNameObj);
|
||||
}
|
||||
if (i != varc) {
|
||||
if (varc == 0) {
|
||||
ckfree(pvlPtr->list);
|
||||
} else if (i) {
|
||||
pvlPtr->list = ckrealloc(pvlPtr->list,
|
||||
sizeof(PrivateVariableMapping) * varc);
|
||||
} else {
|
||||
pvlPtr->list = ckalloc(sizeof(PrivateVariableMapping) * varc);
|
||||
}
|
||||
}
|
||||
|
||||
pvlPtr->num = 0;
|
||||
if (varc > 0) {
|
||||
Tcl_InitObjHashTable(&uniqueTable);
|
||||
for (i=n=0 ; i<varc ; i++) {
|
||||
Tcl_CreateHashEntry(&uniqueTable, varv[i], &created);
|
||||
if (created) {
|
||||
privatePtr = &(pvlPtr->list[n++]);
|
||||
privatePtr->variableObj = varv[i];
|
||||
privatePtr->fullNameObj = Tcl_ObjPrintf(
|
||||
PRIVATE_VARIABLE_PATTERN,
|
||||
creationEpoch, Tcl_GetString(varv[i]));
|
||||
Tcl_IncrRefCount(privatePtr->fullNameObj);
|
||||
} else {
|
||||
Tcl_DecrRefCount(varv[i]);
|
||||
}
|
||||
}
|
||||
pvlPtr->num = n;
|
||||
|
||||
/*
|
||||
* Shouldn't be necessary, but maintain num/list invariant.
|
||||
*/
|
||||
|
||||
if (n != varc) {
|
||||
pvlPtr->list = ckrealloc(pvlPtr->list,
|
||||
sizeof(PrivateVariableMapping) * n);
|
||||
}
|
||||
Tcl_DeleteHashTable(&uniqueTable);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
@@ -708,7 +860,8 @@ TclOOGetDefineCmdContext(
|
||||
Tcl_Object object;
|
||||
|
||||
if ((iPtr->varFramePtr == NULL)
|
||||
|| (iPtr->varFramePtr->isProcCallFrame != FRAME_IS_OO_DEFINE)) {
|
||||
|| (iPtr->varFramePtr->isProcCallFrame != FRAME_IS_OO_DEFINE
|
||||
&& iPtr->varFramePtr->isProcCallFrame != PRIVATE_FRAME)) {
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
||||
"this command may only be called from within the context of"
|
||||
" an ::oo::define or ::oo::objdefine command", -1));
|
||||
@@ -749,7 +902,8 @@ GetClassInOuterContext(
|
||||
Object *oPtr;
|
||||
CallFrame *savedFramePtr = iPtr->varFramePtr;
|
||||
|
||||
while (iPtr->varFramePtr->isProcCallFrame == FRAME_IS_OO_DEFINE) {
|
||||
while (iPtr->varFramePtr->isProcCallFrame == FRAME_IS_OO_DEFINE
|
||||
|| iPtr->varFramePtr->isProcCallFrame == PRIVATE_FRAME) {
|
||||
if (iPtr->varFramePtr->callerVarPtr == NULL) {
|
||||
Tcl_Panic("getting outer context when already in global context");
|
||||
}
|
||||
@@ -1038,7 +1192,7 @@ TclOODefineSelfObjCmd(
|
||||
{
|
||||
Foundation *fPtr = TclOOGetFoundation(interp);
|
||||
Object *oPtr;
|
||||
int result;
|
||||
int result, private;
|
||||
|
||||
oPtr = (Object *) TclOOGetDefineCmdContext(interp);
|
||||
if (oPtr == NULL) {
|
||||
@@ -1050,6 +1204,8 @@ TclOODefineSelfObjCmd(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
private = IsPrivateDefine(interp);
|
||||
|
||||
/*
|
||||
* Make the oo::objdefine namespace the current namespace and evaluate the
|
||||
* command(s).
|
||||
@@ -1058,6 +1214,9 @@ TclOODefineSelfObjCmd(
|
||||
if (InitDefineContext(interp, fPtr->objdefNs, oPtr, objc,objv) != TCL_OK){
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (private) {
|
||||
((Interp *) interp)->varFramePtr->isProcCallFrame = PRIVATE_FRAME;
|
||||
}
|
||||
|
||||
AddRef(oPtr);
|
||||
if (objc == 2) {
|
||||
@@ -1065,7 +1224,7 @@ TclOODefineSelfObjCmd(
|
||||
|
||||
Tcl_IncrRefCount(objNameObj);
|
||||
result = TclEvalObjEx(interp, objv[1], 0,
|
||||
((Interp *)interp)->cmdFramePtr, 2);
|
||||
((Interp *)interp)->cmdFramePtr, 1);
|
||||
if (result == TCL_ERROR) {
|
||||
GenerateErrorInfo(interp, oPtr, objNameObj, "class object");
|
||||
}
|
||||
@@ -1117,6 +1276,79 @@ TclOODefineObjSelfObjCmd(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* TclOODefinePrivateObjCmd --
|
||||
*
|
||||
* Implementation of the "private" subcommand of the "oo::define"
|
||||
* and "oo::objdefine" commands.
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
TclOODefinePrivateObjCmd(
|
||||
ClientData clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *const *objv)
|
||||
{
|
||||
int isInstancePrivate = (clientData != NULL);
|
||||
/* Just so that we can generate the correct
|
||||
* error message depending on the context of
|
||||
* usage of this function. */
|
||||
Interp *iPtr = (Interp *) interp;
|
||||
Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp);
|
||||
int saved; /* The saved flag. We restore it on exit so
|
||||
* that [private private ...] doesn't make
|
||||
* things go weird. */
|
||||
int result;
|
||||
|
||||
if (oPtr == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (objc == 1) {
|
||||
Tcl_SetObjResult(interp, Tcl_NewBooleanObj(IsPrivateDefine(interp)));
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Change the frame type flag while evaluating the body.
|
||||
*/
|
||||
|
||||
saved = iPtr->varFramePtr->isProcCallFrame;
|
||||
iPtr->varFramePtr->isProcCallFrame = PRIVATE_FRAME;
|
||||
|
||||
/*
|
||||
* Evaluate the body; standard pattern.
|
||||
*/
|
||||
|
||||
AddRef(oPtr);
|
||||
if (objc == 2) {
|
||||
Tcl_Obj *objNameObj = TclOOObjectName(interp, oPtr);
|
||||
|
||||
Tcl_IncrRefCount(objNameObj);
|
||||
result = TclEvalObjEx(interp, objv[1], 0, iPtr->cmdFramePtr, 1);
|
||||
if (result == TCL_ERROR) {
|
||||
GenerateErrorInfo(interp, oPtr, objNameObj,
|
||||
isInstancePrivate ? "object" : "class");
|
||||
}
|
||||
TclDecrRefCount(objNameObj);
|
||||
} else {
|
||||
result = MagicDefinitionInvoke(interp, TclGetCurrentNamespace(interp),
|
||||
1, objc, objv);
|
||||
}
|
||||
TclOODecrRefCount(oPtr);
|
||||
|
||||
/*
|
||||
* Restore the frame type flag to what it was previously.
|
||||
*/
|
||||
|
||||
iPtr->varFramePtr->isProcCallFrame = saved;
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
@@ -1460,8 +1692,9 @@ TclOODefineExportObjCmd(
|
||||
} else {
|
||||
mPtr = Tcl_GetHashValue(hPtr);
|
||||
}
|
||||
if (isNew || !(mPtr->flags & PUBLIC_METHOD)) {
|
||||
if (isNew || !(mPtr->flags & (PUBLIC_METHOD | PRIVATE_METHOD))) {
|
||||
mPtr->flags |= PUBLIC_METHOD;
|
||||
mPtr->flags &= ~TRUE_PRIVATE_METHOD;
|
||||
changed = 1;
|
||||
}
|
||||
}
|
||||
@@ -1521,6 +1754,9 @@ TclOODefineForwardObjCmd(
|
||||
}
|
||||
isPublic = Tcl_StringMatch(TclGetString(objv[1]), "[a-z]*")
|
||||
? PUBLIC_METHOD : 0;
|
||||
if (IsPrivateDefine(interp)) {
|
||||
isPublic = TRUE_PRIVATE_METHOD;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create the method structure.
|
||||
@@ -1580,6 +1816,9 @@ TclOODefineMethodObjCmd(
|
||||
}
|
||||
isPublic = Tcl_StringMatch(TclGetString(objv[1]), "[a-z]*")
|
||||
? PUBLIC_METHOD : 0;
|
||||
if (IsPrivateDefine(interp)) {
|
||||
isPublic = TRUE_PRIVATE_METHOD;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create the method by using the right back-end API.
|
||||
@@ -1795,8 +2034,8 @@ TclOODefineUnexportObjCmd(
|
||||
} else {
|
||||
mPtr = Tcl_GetHashValue(hPtr);
|
||||
}
|
||||
if (isNew || mPtr->flags & PUBLIC_METHOD) {
|
||||
mPtr->flags &= ~PUBLIC_METHOD;
|
||||
if (isNew || mPtr->flags & (PUBLIC_METHOD | TRUE_PRIVATE_METHOD)) {
|
||||
mPtr->flags &= ~(PUBLIC_METHOD | TRUE_PRIVATE_METHOD);
|
||||
changed = 1;
|
||||
}
|
||||
}
|
||||
@@ -2288,7 +2527,7 @@ ClassVarsGet(
|
||||
Tcl_Obj *const *objv)
|
||||
{
|
||||
Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp);
|
||||
Tcl_Obj *resultObj, *variableObj;
|
||||
Tcl_Obj *resultObj;
|
||||
int i;
|
||||
|
||||
if (Tcl_ObjectContextSkippedArgs(context) != objc) {
|
||||
@@ -2306,8 +2545,18 @@ ClassVarsGet(
|
||||
}
|
||||
|
||||
resultObj = Tcl_NewObj();
|
||||
FOREACH(variableObj, oPtr->classPtr->variables) {
|
||||
Tcl_ListObjAppendElement(NULL, resultObj, variableObj);
|
||||
if (IsPrivateDefine(interp)) {
|
||||
PrivateVariableMapping *privatePtr;
|
||||
|
||||
FOREACH_STRUCT(privatePtr, oPtr->classPtr->privateVariables) {
|
||||
Tcl_ListObjAppendElement(NULL, resultObj, privatePtr->variableObj);
|
||||
}
|
||||
} else {
|
||||
Tcl_Obj *variableObj;
|
||||
|
||||
FOREACH(variableObj, oPtr->classPtr->variables) {
|
||||
Tcl_ListObjAppendElement(NULL, resultObj, variableObj);
|
||||
}
|
||||
}
|
||||
Tcl_SetObjResult(interp, resultObj);
|
||||
return TCL_OK;
|
||||
@@ -2323,7 +2572,7 @@ ClassVarsSet(
|
||||
{
|
||||
Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp);
|
||||
int varc;
|
||||
Tcl_Obj **varv, *variableObj;
|
||||
Tcl_Obj **varv;
|
||||
int i;
|
||||
|
||||
if (Tcl_ObjectContextSkippedArgs(context)+1 != objc) {
|
||||
@@ -2364,49 +2613,11 @@ ClassVarsSet(
|
||||
}
|
||||
}
|
||||
|
||||
for (i=0 ; i<varc ; i++) {
|
||||
Tcl_IncrRefCount(varv[i]);
|
||||
}
|
||||
FOREACH(variableObj, oPtr->classPtr->variables) {
|
||||
Tcl_DecrRefCount(variableObj);
|
||||
}
|
||||
if (i != varc) {
|
||||
if (varc == 0) {
|
||||
ckfree(oPtr->classPtr->variables.list);
|
||||
} else if (i) {
|
||||
oPtr->classPtr->variables.list = (Tcl_Obj **)
|
||||
ckrealloc((char *) oPtr->classPtr->variables.list,
|
||||
sizeof(Tcl_Obj *) * varc);
|
||||
} else {
|
||||
oPtr->classPtr->variables.list = (Tcl_Obj **)
|
||||
ckalloc(sizeof(Tcl_Obj *) * varc);
|
||||
}
|
||||
}
|
||||
|
||||
oPtr->classPtr->variables.num = 0;
|
||||
if (varc > 0) {
|
||||
int created, n;
|
||||
Tcl_HashTable uniqueTable;
|
||||
|
||||
Tcl_InitObjHashTable(&uniqueTable);
|
||||
for (i=n=0 ; i<varc ; i++) {
|
||||
Tcl_CreateHashEntry(&uniqueTable, varv[i], &created);
|
||||
if (created) {
|
||||
oPtr->classPtr->variables.list[n++] = varv[i];
|
||||
} else {
|
||||
Tcl_DecrRefCount(varv[i]);
|
||||
}
|
||||
}
|
||||
oPtr->classPtr->variables.num = n;
|
||||
|
||||
/*
|
||||
* Shouldn't be necessary, but maintain num/list invariant.
|
||||
*/
|
||||
|
||||
oPtr->classPtr->variables.list = (Tcl_Obj **)
|
||||
ckrealloc((char *) oPtr->classPtr->variables.list,
|
||||
sizeof(Tcl_Obj *) * n);
|
||||
Tcl_DeleteHashTable(&uniqueTable);
|
||||
if (IsPrivateDefine(interp)) {
|
||||
InstallPrivateVariableMapping(&oPtr->classPtr->privateVariables,
|
||||
varc, varv, oPtr->classPtr->thisPtr->creationEpoch);
|
||||
} else {
|
||||
InstallStandardVariableMapping(&oPtr->classPtr->variables, varc, varv);
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
@@ -2585,7 +2796,7 @@ ObjVarsGet(
|
||||
Tcl_Obj *const *objv)
|
||||
{
|
||||
Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp);
|
||||
Tcl_Obj *resultObj, *variableObj;
|
||||
Tcl_Obj *resultObj;
|
||||
int i;
|
||||
|
||||
if (Tcl_ObjectContextSkippedArgs(context) != objc) {
|
||||
@@ -2597,8 +2808,18 @@ ObjVarsGet(
|
||||
}
|
||||
|
||||
resultObj = Tcl_NewObj();
|
||||
FOREACH(variableObj, oPtr->variables) {
|
||||
Tcl_ListObjAppendElement(NULL, resultObj, variableObj);
|
||||
if (IsPrivateDefine(interp)) {
|
||||
PrivateVariableMapping *privatePtr;
|
||||
|
||||
FOREACH_STRUCT(privatePtr, oPtr->privateVariables) {
|
||||
Tcl_ListObjAppendElement(NULL, resultObj, privatePtr->variableObj);
|
||||
}
|
||||
} else {
|
||||
Tcl_Obj *variableObj;
|
||||
|
||||
FOREACH(variableObj, oPtr->variables) {
|
||||
Tcl_ListObjAppendElement(NULL, resultObj, variableObj);
|
||||
}
|
||||
}
|
||||
Tcl_SetObjResult(interp, resultObj);
|
||||
return TCL_OK;
|
||||
@@ -2614,7 +2835,7 @@ ObjVarsSet(
|
||||
{
|
||||
Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp);
|
||||
int varc, i;
|
||||
Tcl_Obj **varv, *variableObj;
|
||||
Tcl_Obj **varv;
|
||||
|
||||
if (Tcl_ObjectContextSkippedArgs(context)+1 != objc) {
|
||||
Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv,
|
||||
@@ -2647,49 +2868,12 @@ ObjVarsSet(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
}
|
||||
for (i=0 ; i<varc ; i++) {
|
||||
Tcl_IncrRefCount(varv[i]);
|
||||
}
|
||||
|
||||
FOREACH(variableObj, oPtr->variables) {
|
||||
Tcl_DecrRefCount(variableObj);
|
||||
}
|
||||
if (i != varc) {
|
||||
if (varc == 0) {
|
||||
ckfree(oPtr->variables.list);
|
||||
} else if (i) {
|
||||
oPtr->variables.list = (Tcl_Obj **)
|
||||
ckrealloc((char *) oPtr->variables.list,
|
||||
sizeof(Tcl_Obj *) * varc);
|
||||
} else {
|
||||
oPtr->variables.list = (Tcl_Obj **)
|
||||
ckalloc(sizeof(Tcl_Obj *) * varc);
|
||||
}
|
||||
}
|
||||
oPtr->variables.num = 0;
|
||||
if (varc > 0) {
|
||||
int created, n;
|
||||
Tcl_HashTable uniqueTable;
|
||||
|
||||
Tcl_InitObjHashTable(&uniqueTable);
|
||||
for (i=n=0 ; i<varc ; i++) {
|
||||
Tcl_CreateHashEntry(&uniqueTable, varv[i], &created);
|
||||
if (created) {
|
||||
oPtr->variables.list[n++] = varv[i];
|
||||
} else {
|
||||
Tcl_DecrRefCount(varv[i]);
|
||||
}
|
||||
}
|
||||
oPtr->variables.num = n;
|
||||
|
||||
/*
|
||||
* Shouldn't be necessary, but maintain num/list invariant.
|
||||
*/
|
||||
|
||||
oPtr->variables.list = (Tcl_Obj **)
|
||||
ckrealloc((char *) oPtr->variables.list,
|
||||
sizeof(Tcl_Obj *) * n);
|
||||
Tcl_DeleteHashTable(&uniqueTable);
|
||||
if (IsPrivateDefine(interp)) {
|
||||
InstallPrivateVariableMapping(&oPtr->privateVariables, varc, varv,
|
||||
oPtr->creationEpoch);
|
||||
} else {
|
||||
InstallStandardVariableMapping(&oPtr->variables, varc, varv);
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
+165
-27
@@ -22,6 +22,7 @@ static Tcl_ObjCmdProc InfoObjectClassCmd;
|
||||
static Tcl_ObjCmdProc InfoObjectDefnCmd;
|
||||
static Tcl_ObjCmdProc InfoObjectFiltersCmd;
|
||||
static Tcl_ObjCmdProc InfoObjectForwardCmd;
|
||||
static Tcl_ObjCmdProc InfoObjectIdCmd;
|
||||
static Tcl_ObjCmdProc InfoObjectIsACmd;
|
||||
static Tcl_ObjCmdProc InfoObjectMethodsCmd;
|
||||
static Tcl_ObjCmdProc InfoObjectMethodTypeCmd;
|
||||
@@ -50,6 +51,7 @@ static Tcl_ObjCmdProc InfoClassVariablesCmd;
|
||||
static const EnsembleImplMap infoObjectCmds[] = {
|
||||
{"call", InfoObjectCallCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0},
|
||||
{"class", InfoObjectClassCmd, TclCompileInfoObjectClassCmd, NULL, NULL, 0},
|
||||
{"creationid", InfoObjectIdCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
|
||||
{"definition", InfoObjectDefnCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0},
|
||||
{"filters", InfoObjectFiltersCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
|
||||
{"forward", InfoObjectForwardCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0},
|
||||
@@ -58,7 +60,7 @@ static const EnsembleImplMap infoObjectCmds[] = {
|
||||
{"methodtype", InfoObjectMethodTypeCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0},
|
||||
{"mixins", InfoObjectMixinsCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
|
||||
{"namespace", InfoObjectNsCmd, TclCompileInfoObjectNamespaceCmd, NULL, NULL, 0},
|
||||
{"variables", InfoObjectVariablesCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
|
||||
{"variables", InfoObjectVariablesCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0},
|
||||
{"vars", InfoObjectVarsCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0},
|
||||
{NULL, NULL, NULL, NULL, NULL, 0}
|
||||
};
|
||||
@@ -80,7 +82,7 @@ static const EnsembleImplMap infoClassCmds[] = {
|
||||
{"mixins", InfoClassMixinsCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
|
||||
{"subclasses", InfoClassSubsCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0},
|
||||
{"superclasses", InfoClassSupersCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
|
||||
{"variables", InfoClassVariablesCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
|
||||
{"variables", InfoClassVariablesCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0},
|
||||
{NULL, NULL, NULL, NULL, NULL, 0}
|
||||
};
|
||||
|
||||
@@ -517,15 +519,22 @@ InfoObjectMethodsCmd(
|
||||
Tcl_Obj *const objv[])
|
||||
{
|
||||
Object *oPtr;
|
||||
int flag = PUBLIC_METHOD, recurse = 0;
|
||||
int flag = PUBLIC_METHOD, recurse = 0, scope = -1;
|
||||
FOREACH_HASH_DECLS;
|
||||
Tcl_Obj *namePtr, *resultObj;
|
||||
Method *mPtr;
|
||||
static const char *const options[] = {
|
||||
"-all", "-localprivate", "-private", NULL
|
||||
"-all", "-localprivate", "-private", "-scope", NULL
|
||||
};
|
||||
enum Options {
|
||||
OPT_ALL, OPT_LOCALPRIVATE, OPT_PRIVATE
|
||||
OPT_ALL, OPT_LOCALPRIVATE, OPT_PRIVATE, OPT_SCOPE
|
||||
};
|
||||
static const char *const scopes[] = {
|
||||
"private", "public", "unexported"
|
||||
};
|
||||
enum Scopes {
|
||||
SCOPE_PRIVATE, SCOPE_PUBLIC, SCOPE_UNEXPORTED,
|
||||
SCOPE_LOCALPRIVATE
|
||||
};
|
||||
|
||||
if (objc < 2) {
|
||||
@@ -554,14 +563,45 @@ InfoObjectMethodsCmd(
|
||||
case OPT_PRIVATE:
|
||||
flag = 0;
|
||||
break;
|
||||
case OPT_SCOPE:
|
||||
if (++i >= objc) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"missing option for -scope"));
|
||||
Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "MISSING",
|
||||
NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (Tcl_GetIndexFromObj(interp, objv[i], scopes, "scope", 0,
|
||||
&scope) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (scope != -1) {
|
||||
recurse = 0;
|
||||
switch (scope) {
|
||||
case SCOPE_PRIVATE:
|
||||
flag = TRUE_PRIVATE_METHOD;
|
||||
break;
|
||||
case SCOPE_PUBLIC:
|
||||
flag = PUBLIC_METHOD;
|
||||
break;
|
||||
case SCOPE_LOCALPRIVATE:
|
||||
flag = PRIVATE_METHOD;
|
||||
break;
|
||||
case SCOPE_UNEXPORTED:
|
||||
flag = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
resultObj = Tcl_NewObj();
|
||||
if (recurse) {
|
||||
const char **names;
|
||||
int i, numNames = TclOOGetSortedMethodList(oPtr, flag, &names);
|
||||
int i, numNames = TclOOGetSortedMethodList(oPtr, NULL, NULL, flag,
|
||||
&names);
|
||||
|
||||
for (i=0 ; i<numNames ; i++) {
|
||||
Tcl_ListObjAppendElement(NULL, resultObj,
|
||||
@@ -572,7 +612,7 @@ InfoObjectMethodsCmd(
|
||||
}
|
||||
} else if (oPtr->methodsPtr) {
|
||||
FOREACH_HASH(namePtr, mPtr, oPtr->methodsPtr) {
|
||||
if (mPtr->typePtr != NULL && (mPtr->flags & flag) == flag) {
|
||||
if (mPtr->typePtr && (mPtr->flags & SCOPE_FLAGS) == flag) {
|
||||
Tcl_ListObjAppendElement(NULL, resultObj, namePtr);
|
||||
}
|
||||
}
|
||||
@@ -681,6 +721,38 @@ InfoObjectMixinsCmd(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* InfoObjectIdCmd --
|
||||
*
|
||||
* Implements [info object creationid $objName]
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static int
|
||||
InfoObjectIdCmd(
|
||||
ClientData clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *const objv[])
|
||||
{
|
||||
Object *oPtr;
|
||||
|
||||
if (objc != 2) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "objName");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
oPtr = (Object *) Tcl_GetObjectFromObj(interp, objv[1]);
|
||||
if (oPtr == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
Tcl_SetObjResult(interp, Tcl_NewIntObj(oPtr->creationEpoch));
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
@@ -719,7 +791,7 @@ InfoObjectNsCmd(
|
||||
*
|
||||
* InfoObjectVariablesCmd --
|
||||
*
|
||||
* Implements [info object variables $objName]
|
||||
* Implements [info object variables $objName ?-private?]
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*/
|
||||
@@ -732,21 +804,37 @@ InfoObjectVariablesCmd(
|
||||
Tcl_Obj *const objv[])
|
||||
{
|
||||
Object *oPtr;
|
||||
Tcl_Obj *variableObj, *resultObj;
|
||||
int i;
|
||||
Tcl_Obj *resultObj;
|
||||
int i, private = 0;
|
||||
|
||||
if (objc != 2) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "objName");
|
||||
if (objc != 2 && objc != 3) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "objName ?-private?");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (objc == 3) {
|
||||
if (strcmp("-private", Tcl_GetString(objv[2])) != 0) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
private = 1;
|
||||
}
|
||||
oPtr = (Object *) Tcl_GetObjectFromObj(interp, objv[1]);
|
||||
if (oPtr == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
resultObj = Tcl_NewObj();
|
||||
FOREACH(variableObj, oPtr->variables) {
|
||||
Tcl_ListObjAppendElement(NULL, resultObj, variableObj);
|
||||
if (private) {
|
||||
PrivateVariableMapping *privatePtr;
|
||||
|
||||
FOREACH_STRUCT(privatePtr, oPtr->privateVariables) {
|
||||
Tcl_ListObjAppendElement(NULL, resultObj, privatePtr->variableObj);
|
||||
}
|
||||
} else {
|
||||
Tcl_Obj *variableObj;
|
||||
|
||||
FOREACH(variableObj, oPtr->variables) {
|
||||
Tcl_ListObjAppendElement(NULL, resultObj, variableObj);
|
||||
}
|
||||
}
|
||||
Tcl_SetObjResult(interp, resultObj);
|
||||
return TCL_OK;
|
||||
@@ -1128,7 +1216,7 @@ InfoClassInstancesCmd(
|
||||
*
|
||||
* InfoClassMethodsCmd --
|
||||
*
|
||||
* Implements [info class methods $clsName ?-private?]
|
||||
* Implements [info class methods $clsName ?options...?]
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*/
|
||||
@@ -1140,15 +1228,21 @@ InfoClassMethodsCmd(
|
||||
int objc,
|
||||
Tcl_Obj *const objv[])
|
||||
{
|
||||
int flag = PUBLIC_METHOD, recurse = 0;
|
||||
int flag = PUBLIC_METHOD, recurse = 0, scope = -1;
|
||||
Tcl_Obj *namePtr, *resultObj;
|
||||
Method *mPtr;
|
||||
Class *clsPtr;
|
||||
static const char *const options[] = {
|
||||
"-all", "-localprivate", "-private", NULL
|
||||
"-all", "-localprivate", "-private", "-scope", NULL
|
||||
};
|
||||
enum Options {
|
||||
OPT_ALL, OPT_LOCALPRIVATE, OPT_PRIVATE
|
||||
OPT_ALL, OPT_LOCALPRIVATE, OPT_PRIVATE, OPT_SCOPE
|
||||
};
|
||||
static const char *const scopes[] = {
|
||||
"private", "public", "unexported"
|
||||
};
|
||||
enum Scopes {
|
||||
SCOPE_PRIVATE, SCOPE_PUBLIC, SCOPE_UNEXPORTED
|
||||
};
|
||||
|
||||
if (objc < 2) {
|
||||
@@ -1177,9 +1271,36 @@ InfoClassMethodsCmd(
|
||||
case OPT_PRIVATE:
|
||||
flag = 0;
|
||||
break;
|
||||
case OPT_SCOPE:
|
||||
if (++i >= objc) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"missing option for -scope"));
|
||||
Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "MISSING",
|
||||
NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (Tcl_GetIndexFromObj(interp, objv[i], scopes, "scope", 0,
|
||||
&scope) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (scope != -1) {
|
||||
recurse = 0;
|
||||
switch (scope) {
|
||||
case SCOPE_PRIVATE:
|
||||
flag = TRUE_PRIVATE_METHOD;
|
||||
break;
|
||||
case SCOPE_PUBLIC:
|
||||
flag = PUBLIC_METHOD;
|
||||
break;
|
||||
case SCOPE_UNEXPORTED:
|
||||
flag = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
resultObj = Tcl_NewObj();
|
||||
if (recurse) {
|
||||
@@ -1197,7 +1318,7 @@ InfoClassMethodsCmd(
|
||||
FOREACH_HASH_DECLS;
|
||||
|
||||
FOREACH_HASH(namePtr, mPtr, &clsPtr->classMethods) {
|
||||
if (mPtr->typePtr != NULL && (mPtr->flags & flag) == flag) {
|
||||
if (mPtr->typePtr && (mPtr->flags & SCOPE_FLAGS) == flag) {
|
||||
Tcl_ListObjAppendElement(NULL, resultObj, namePtr);
|
||||
}
|
||||
}
|
||||
@@ -1399,7 +1520,7 @@ InfoClassSupersCmd(
|
||||
*
|
||||
* InfoClassVariablesCmd --
|
||||
*
|
||||
* Implements [info class variables $clsName]
|
||||
* Implements [info class variables $clsName ?-private?]
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*/
|
||||
@@ -1412,21 +1533,37 @@ InfoClassVariablesCmd(
|
||||
Tcl_Obj *const objv[])
|
||||
{
|
||||
Class *clsPtr;
|
||||
Tcl_Obj *variableObj, *resultObj;
|
||||
int i;
|
||||
Tcl_Obj *resultObj;
|
||||
int i, private = 0;
|
||||
|
||||
if (objc != 2) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "className");
|
||||
if (objc != 2 && objc != 3) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "className ?-private?");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (objc == 3) {
|
||||
if (strcmp("-private", Tcl_GetString(objv[2])) != 0) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
private = 1;
|
||||
}
|
||||
clsPtr = GetClassFromObj(interp, objv[1]);
|
||||
if (clsPtr == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
resultObj = Tcl_NewObj();
|
||||
FOREACH(variableObj, clsPtr->variables) {
|
||||
Tcl_ListObjAppendElement(NULL, resultObj, variableObj);
|
||||
if (private) {
|
||||
PrivateVariableMapping *privatePtr;
|
||||
|
||||
FOREACH_STRUCT(privatePtr, clsPtr->privateVariables) {
|
||||
Tcl_ListObjAppendElement(NULL, resultObj, privatePtr->variableObj);
|
||||
}
|
||||
} else {
|
||||
Tcl_Obj *variableObj;
|
||||
|
||||
FOREACH(variableObj, clsPtr->variables) {
|
||||
Tcl_ListObjAppendElement(NULL, resultObj, variableObj);
|
||||
}
|
||||
}
|
||||
Tcl_SetObjResult(interp, resultObj);
|
||||
return TCL_OK;
|
||||
@@ -1465,7 +1602,8 @@ InfoObjectCallCmd(
|
||||
* Get the call context and render its call chain.
|
||||
*/
|
||||
|
||||
contextPtr = TclOOGetCallContext(oPtr, objv[2], PUBLIC_METHOD, NULL);
|
||||
contextPtr = TclOOGetCallContext(oPtr, objv[2], PUBLIC_METHOD, NULL, NULL,
|
||||
NULL);
|
||||
if (contextPtr == NULL) {
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
||||
"cannot construct any call chain", -1));
|
||||
|
||||
+54
-4
@@ -124,6 +124,18 @@ typedef struct ForwardMethod {
|
||||
* non-empty list. */
|
||||
} ForwardMethod;
|
||||
|
||||
/*
|
||||
* Structure used in private variable mappings. Describes the mapping of a
|
||||
* single variable from the user's local name to the system's storage name.
|
||||
* [TIP #500]
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
Tcl_Obj *variableObj; /* Name used within methods. This is the part
|
||||
* that is properly under user control. */
|
||||
Tcl_Obj *fullNameObj; /* Name used at the instance namespace level. */
|
||||
} PrivateVariableMapping;
|
||||
|
||||
/*
|
||||
* Helper definitions that declare a "list" array. The two varieties are
|
||||
* either optimized for simplicity (in the case that the whole array is
|
||||
@@ -141,6 +153,13 @@ typedef struct ForwardMethod {
|
||||
#define LIST_DYNAMIC(listType_t) \
|
||||
struct { int num, size; listType_t *list; }
|
||||
|
||||
/*
|
||||
* These types are needed in function arguments.
|
||||
*/
|
||||
|
||||
typedef LIST_STATIC(Tcl_Obj *) VariableNameList;
|
||||
typedef LIST_STATIC(PrivateVariableMapping) PrivateVariableList;
|
||||
|
||||
/*
|
||||
* Now, the definition of what an object actually is.
|
||||
*/
|
||||
@@ -186,7 +205,10 @@ typedef struct Object {
|
||||
Tcl_ObjectMapMethodNameProc *mapMethodNameProc;
|
||||
/* Function to allow remapping of method
|
||||
* names. For itcl-ng. */
|
||||
LIST_STATIC(Tcl_Obj *) variables;
|
||||
VariableNameList variables;
|
||||
PrivateVariableList privateVariables;
|
||||
/* Configurations for the variable resolver
|
||||
* used inside methods. */
|
||||
} Object;
|
||||
|
||||
#define OBJECT_DELETED 1 /* Flag to say that an object has been
|
||||
@@ -214,6 +236,10 @@ typedef struct Object {
|
||||
* other spots). */
|
||||
#define FORCE_UNKNOWN 0x10000 /* States that we are *really* looking up the
|
||||
* unknown method handler at that point. */
|
||||
#define HAS_PRIVATE_METHODS 0x20000
|
||||
/* Object/class has (or had) private methods,
|
||||
* and so shouldn't be cached so
|
||||
* aggressively. */
|
||||
|
||||
/*
|
||||
* And the definition of a class. Note that every class also has an associated
|
||||
@@ -268,7 +294,10 @@ typedef struct Class {
|
||||
* object doesn't override with its own mixins
|
||||
* (and filters and method implementations for
|
||||
* when getting method chains). */
|
||||
LIST_STATIC(Tcl_Obj *) variables;
|
||||
VariableNameList variables;
|
||||
PrivateVariableList privateVariables;
|
||||
/* Configurations for the variable resolver
|
||||
* used inside methods. */
|
||||
} Class;
|
||||
|
||||
/*
|
||||
@@ -370,10 +399,15 @@ typedef struct CallContext {
|
||||
|
||||
#define PUBLIC_METHOD 0x01 /* This is a public (exported) method. */
|
||||
#define PRIVATE_METHOD 0x02 /* This is a private (class's direct instances
|
||||
* only) method. */
|
||||
* only) method. Supports itcl. */
|
||||
#define OO_UNKNOWN_METHOD 0x04 /* This is an unknown method. */
|
||||
#define CONSTRUCTOR 0x08 /* This is a constructor. */
|
||||
#define DESTRUCTOR 0x10 /* This is a destructor. */
|
||||
#define TRUE_PRIVATE_METHOD 0x20
|
||||
/* This is a private method only accessible
|
||||
* from other methods defined on this class
|
||||
* or instance. [TIP #500] */
|
||||
#define SCOPE_FLAGS (PUBLIC_METHOD | PRIVATE_METHOD | TRUE_PRIVATE_METHOD)
|
||||
|
||||
/*
|
||||
* Structure containing definition information about basic class methods.
|
||||
@@ -431,6 +465,9 @@ MODULE_SCOPE int TclOODefineSelfObjCmd(ClientData clientData,
|
||||
MODULE_SCOPE int TclOODefineObjSelfObjCmd(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc,
|
||||
Tcl_Obj *const *objv);
|
||||
MODULE_SCOPE int TclOODefinePrivateObjCmd(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc,
|
||||
Tcl_Obj *const *objv);
|
||||
MODULE_SCOPE int TclOOUnknownDefinition(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc,
|
||||
Tcl_Obj *const *objv);
|
||||
@@ -504,6 +541,7 @@ MODULE_SCOPE void TclOODeleteContext(CallContext *contextPtr);
|
||||
MODULE_SCOPE void TclOODelMethodRef(Method *method);
|
||||
MODULE_SCOPE CallContext *TclOOGetCallContext(Object *oPtr,
|
||||
Tcl_Obj *methodNameObj, int flags,
|
||||
Object *contextObjPtr, Class *contextClsPtr,
|
||||
Tcl_Obj *cacheInThisObj);
|
||||
MODULE_SCOPE CallChain *TclOOGetStereotypeCallChain(Class *clsPtr,
|
||||
Tcl_Obj *methodNameObj, int flags);
|
||||
@@ -513,7 +551,8 @@ MODULE_SCOPE Proc * TclOOGetProcFromMethod(Method *mPtr);
|
||||
MODULE_SCOPE Tcl_Obj * TclOOGetMethodBody(Method *mPtr);
|
||||
MODULE_SCOPE int TclOOGetSortedClassMethodList(Class *clsPtr,
|
||||
int flags, const char ***stringsPtr);
|
||||
MODULE_SCOPE int TclOOGetSortedMethodList(Object *oPtr, int flags,
|
||||
MODULE_SCOPE int TclOOGetSortedMethodList(Object *oPtr,
|
||||
Object *contextObj, Class *contextCls, int flags,
|
||||
const char ***stringsPtr);
|
||||
MODULE_SCOPE int TclOOInit(Tcl_Interp *interp);
|
||||
MODULE_SCOPE void TclOOInitInfo(Tcl_Interp *interp);
|
||||
@@ -560,11 +599,22 @@ MODULE_SCOPE void TclOOSetupVariableResolver(Tcl_Namespace *nsPtr);
|
||||
continue; \
|
||||
} else if (var = (ary).list[i], 1)
|
||||
|
||||
/*
|
||||
* A variation where the array is an array of structs. There's no issue with
|
||||
* possible NULLs; every element of the array will be iterated over and the
|
||||
* varable set to a pointer to each of those elements in turn.
|
||||
* REQUIRES DECLARATION: int i;
|
||||
*/
|
||||
|
||||
#define FOREACH_STRUCT(var,ary) \
|
||||
for(i=0 ; var=&((ary).list[i]), i<(ary).num; i++)
|
||||
|
||||
/*
|
||||
* Convenience macros for iterating through hash tables. FOREACH_HASH_DECLS
|
||||
* sets up the declarations needed for the main macro, FOREACH_HASH, which
|
||||
* does the actual iteration. FOREACH_HASH_VALUE is a restricted version that
|
||||
* only iterates over values.
|
||||
* REQUIRES DECLARATION: FOREACH_HASH_DECLS;
|
||||
*/
|
||||
|
||||
#define FOREACH_HASH_DECLS \
|
||||
|
||||
+36
-3
@@ -186,7 +186,11 @@ Tcl_NewInstanceMethod(
|
||||
mPtr->declaringObjectPtr = oPtr;
|
||||
mPtr->declaringClassPtr = NULL;
|
||||
if (flags) {
|
||||
mPtr->flags |= flags & (PUBLIC_METHOD | PRIVATE_METHOD);
|
||||
mPtr->flags |= flags &
|
||||
(PUBLIC_METHOD | PRIVATE_METHOD | TRUE_PRIVATE_METHOD);
|
||||
if (flags & TRUE_PRIVATE_METHOD) {
|
||||
oPtr->flags |= HAS_PRIVATE_METHODS;
|
||||
}
|
||||
}
|
||||
oPtr->epoch++;
|
||||
return (Tcl_Method) mPtr;
|
||||
@@ -250,7 +254,11 @@ Tcl_NewMethod(
|
||||
mPtr->declaringObjectPtr = NULL;
|
||||
mPtr->declaringClassPtr = clsPtr;
|
||||
if (flags) {
|
||||
mPtr->flags |= flags & (PUBLIC_METHOD | PRIVATE_METHOD);
|
||||
mPtr->flags |= flags &
|
||||
(PUBLIC_METHOD | PRIVATE_METHOD | TRUE_PRIVATE_METHOD);
|
||||
if (flags & TRUE_PRIVATE_METHOD) {
|
||||
clsPtr->flags |= HAS_PRIVATE_METHODS;
|
||||
}
|
||||
}
|
||||
|
||||
return (Tcl_Method) mPtr;
|
||||
@@ -928,7 +936,7 @@ PushMethodCallFrame(
|
||||
* variables used in methods. The compiled variable resolver is more
|
||||
* important, but both are needed as it is possible to have a variable
|
||||
* that is only referred to in ways that aren't compilable and we can't
|
||||
* force LVT presence. [TIP #320]
|
||||
* force LVT presence. [TIP #320, #500]
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*/
|
||||
@@ -986,6 +994,7 @@ ProcedureMethodCompiledVarConnect(
|
||||
CallFrame *framePtr = iPtr->varFramePtr;
|
||||
CallContext *contextPtr;
|
||||
Tcl_Obj *variableObj;
|
||||
PrivateVariableMapping *privateVar;
|
||||
Tcl_HashEntry *hPtr;
|
||||
int i, isNew, cacheIt, varLen, len;
|
||||
const char *match, *varName;
|
||||
@@ -1019,6 +1028,15 @@ ProcedureMethodCompiledVarConnect(
|
||||
varName = TclGetStringFromObj(infoPtr->variableObj, &varLen);
|
||||
if (contextPtr->callPtr->chain[contextPtr->index]
|
||||
.mPtr->declaringClassPtr != NULL) {
|
||||
FOREACH_STRUCT(privateVar, contextPtr->callPtr->chain[contextPtr->index]
|
||||
.mPtr->declaringClassPtr->privateVariables) {
|
||||
match = TclGetStringFromObj(privateVar->variableObj, &len);
|
||||
if ((len == varLen) && !memcmp(match, varName, len)) {
|
||||
variableObj = privateVar->fullNameObj;
|
||||
cacheIt = 0;
|
||||
goto gotMatch;
|
||||
}
|
||||
}
|
||||
FOREACH(variableObj, contextPtr->callPtr->chain[contextPtr->index]
|
||||
.mPtr->declaringClassPtr->variables) {
|
||||
match = TclGetStringFromObj(variableObj, &len);
|
||||
@@ -1028,6 +1046,14 @@ ProcedureMethodCompiledVarConnect(
|
||||
}
|
||||
}
|
||||
} else {
|
||||
FOREACH_STRUCT(privateVar, contextPtr->oPtr->privateVariables) {
|
||||
match = TclGetStringFromObj(privateVar->variableObj, &len);
|
||||
if ((len == varLen) && !memcmp(match, varName, len)) {
|
||||
variableObj = privateVar->fullNameObj;
|
||||
cacheIt = 1;
|
||||
goto gotMatch;
|
||||
}
|
||||
}
|
||||
FOREACH(variableObj, contextPtr->oPtr->variables) {
|
||||
match = TclGetStringFromObj(variableObj, &len);
|
||||
if ((len == varLen) && !memcmp(match, varName, len)) {
|
||||
@@ -1673,6 +1699,13 @@ Tcl_MethodIsPublic(
|
||||
{
|
||||
return (((Method *)method)->flags & PUBLIC_METHOD) ? 1 : 0;
|
||||
}
|
||||
|
||||
int
|
||||
Tcl_MethodIsPrivate(
|
||||
Tcl_Method method)
|
||||
{
|
||||
return (((Method *)method)->flags & TRUE_PRIVATE_METHOD) ? 1 : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Extended method construction for itcl-ng.
|
||||
|
||||
@@ -73,6 +73,7 @@ const TclOOStubs tclOOStubs = {
|
||||
Tcl_ClassSetConstructor, /* 26 */
|
||||
Tcl_ClassSetDestructor, /* 27 */
|
||||
Tcl_GetObjectName, /* 28 */
|
||||
Tcl_MethodIsPrivate, /* 29 */
|
||||
};
|
||||
|
||||
/* !END!: Do not edit above this line. */
|
||||
|
||||
+11
-11
@@ -37,7 +37,7 @@ Tcl_Obj *tclFreeObjList = NULL;
|
||||
* TclNewObj macro, however, so must be visible.
|
||||
*/
|
||||
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
MODULE_SCOPE Tcl_Mutex tclObjMutex;
|
||||
Tcl_Mutex tclObjMutex;
|
||||
#endif
|
||||
@@ -50,7 +50,7 @@ Tcl_Mutex tclObjMutex;
|
||||
|
||||
char tclEmptyString = '\0';
|
||||
|
||||
#if defined(TCL_MEM_DEBUG) && defined(TCL_THREADS)
|
||||
#if TCL_THREADS && defined(TCL_MEM_DEBUG)
|
||||
/*
|
||||
* Structure for tracking the source file and line number where a given
|
||||
* Tcl_Obj was allocated. We also track the pointer to the Tcl_Obj itself,
|
||||
@@ -87,7 +87,7 @@ typedef struct {
|
||||
* tclCompile.h for the definition of this
|
||||
* structure, and for references to all
|
||||
* related places in the core. */
|
||||
#if defined(TCL_MEM_DEBUG) && defined(TCL_THREADS)
|
||||
#if TCL_THREADS && defined(TCL_MEM_DEBUG)
|
||||
Tcl_HashTable *objThreadMap;/* Thread local table that is used to check
|
||||
* that a Tcl_Obj was not allocated by some
|
||||
* other thread. */
|
||||
@@ -156,7 +156,7 @@ typedef struct PendingObjData {
|
||||
/*
|
||||
* Macro to set up the local reference to the deletion context.
|
||||
*/
|
||||
#ifndef TCL_THREADS
|
||||
#if !TCL_THREADS
|
||||
static PendingObjData pendingObjData;
|
||||
#define ObjInitDeletionContext(contextPtr) \
|
||||
PendingObjData *const contextPtr = &pendingObjData
|
||||
@@ -452,7 +452,7 @@ TclInitObjSubsystem(void)
|
||||
void
|
||||
TclFinalizeThreadObjects(void)
|
||||
{
|
||||
#if defined(TCL_MEM_DEBUG) && defined(TCL_THREADS)
|
||||
#if TCL_THREADS && defined(TCL_MEM_DEBUG)
|
||||
Tcl_HashEntry *hPtr;
|
||||
Tcl_HashSearch hSearch;
|
||||
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
|
||||
@@ -1009,7 +1009,7 @@ void
|
||||
TclDbDumpActiveObjects(
|
||||
FILE *outFile)
|
||||
{
|
||||
#if defined(TCL_MEM_DEBUG) && defined(TCL_THREADS)
|
||||
#if TCL_THREADS && defined(TCL_MEM_DEBUG)
|
||||
Tcl_HashSearch hSearch;
|
||||
Tcl_HashEntry *hPtr;
|
||||
Tcl_HashTable *tablePtr;
|
||||
@@ -1069,7 +1069,7 @@ TclDbInitNewObj(
|
||||
objPtr->length = 0;
|
||||
objPtr->typePtr = NULL;
|
||||
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
/*
|
||||
* Add entry to a thread local map used to check if a Tcl_Obj was
|
||||
* allocated by the currently executing thread.
|
||||
@@ -1305,7 +1305,7 @@ TclFreeObj(
|
||||
|
||||
ObjInitDeletionContext(context);
|
||||
|
||||
# ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
/*
|
||||
* Check to make sure that the Tcl_Obj was allocated by the current
|
||||
* thread. Don't do this check when shutting down since thread local
|
||||
@@ -3598,7 +3598,7 @@ Tcl_DbIncrRefCount(
|
||||
Tcl_Panic("incrementing refCount of previously disposed object");
|
||||
}
|
||||
|
||||
# ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
/*
|
||||
* Check to make sure that the Tcl_Obj was allocated by the current
|
||||
* thread. Don't do this check when shutting down since thread local
|
||||
@@ -3661,7 +3661,7 @@ Tcl_DbDecrRefCount(
|
||||
Tcl_Panic("decrementing refCount of previously disposed object");
|
||||
}
|
||||
|
||||
# ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
/*
|
||||
* Check to make sure that the Tcl_Obj was allocated by the current
|
||||
* thread. Don't do this check when shutting down since thread local
|
||||
@@ -3726,7 +3726,7 @@ Tcl_DbIsShared(
|
||||
Tcl_Panic("checking whether previously disposed object is shared");
|
||||
}
|
||||
|
||||
# ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
/*
|
||||
* Check to make sure that the Tcl_Obj was allocated by the current
|
||||
* thread. Don't do this check when shutting down since thread local
|
||||
|
||||
+3
-2
@@ -23,8 +23,8 @@
|
||||
* procedure.
|
||||
*/
|
||||
|
||||
#if defined(__CYGWIN__)
|
||||
static TCL_NORETURN Tcl_PanicProc *panicProc = tclWinDebugPanic;
|
||||
#if defined(__CYGWIN__) || (defined(_WIN32) && (defined(TCL_NO_DEPRECATED) || TCL_MAJOR_VERSION > 8))
|
||||
static TCL_NORETURN1 Tcl_PanicProc *panicProc = tclWinDebugPanic;
|
||||
#else
|
||||
static TCL_NORETURN1 Tcl_PanicProc *panicProc = NULL;
|
||||
#endif
|
||||
@@ -45,6 +45,7 @@ static TCL_NORETURN1 Tcl_PanicProc *panicProc = NULL;
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#undef Tcl_SetPanicProc
|
||||
void
|
||||
Tcl_SetPanicProc(
|
||||
TCL_NORETURN1 Tcl_PanicProc *proc)
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
* configuration information.
|
||||
*/
|
||||
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
# define CFG_THREADED "1"
|
||||
#else
|
||||
# define CFG_THREADED "0"
|
||||
|
||||
+2
-2
@@ -4543,7 +4543,7 @@ Tcl_InitBignumFromDouble(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
fract = frexp(d,&expt);
|
||||
fract = frexp(d, &expt);
|
||||
if (expt <= 0) {
|
||||
mp_init(b);
|
||||
mp_zero(b);
|
||||
@@ -4883,7 +4883,7 @@ Pow10TimesFrExp(
|
||||
* Multiply by 10**exponent.
|
||||
*/
|
||||
|
||||
retval = frexp(retval * pow10vals[exponent&0xf], &j);
|
||||
retval = frexp(retval * pow10vals[exponent & 0xf], &j);
|
||||
expt += j;
|
||||
for (i=4; i<9; ++i) {
|
||||
if (exponent & (1<<i)) {
|
||||
|
||||
+342
-85
@@ -455,6 +455,48 @@ Tcl_GetCharLength(
|
||||
return numChars;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TclCheckEmptyString --
|
||||
*
|
||||
* Determine whether the string value of an object is or would be the
|
||||
* empty string, without generating a string representation.
|
||||
*
|
||||
* Results:
|
||||
* Returns 1 if empty, 0 if not, and -1 if unknown.
|
||||
*
|
||||
* Side effects:
|
||||
* None.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
int
|
||||
TclCheckEmptyString(
|
||||
Tcl_Obj *objPtr)
|
||||
{
|
||||
int length = -1;
|
||||
|
||||
if (objPtr->bytes == &tclEmptyString) {
|
||||
return TCL_EMPTYSTRING_YES;
|
||||
}
|
||||
|
||||
if (TclListObjIsCanonical(objPtr)) {
|
||||
Tcl_ListObjLength(NULL, objPtr, &length);
|
||||
return length == 0;
|
||||
}
|
||||
|
||||
if (TclIsPureDict(objPtr)) {
|
||||
Tcl_DictObjSize(NULL, objPtr, &length);
|
||||
return length == 0;
|
||||
}
|
||||
|
||||
if (objPtr->bytes == NULL) {
|
||||
return TCL_EMPTYSTRING_UNKNOWN;
|
||||
}
|
||||
return objPtr->length == 0;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
@@ -525,20 +567,22 @@ Tcl_GetUniChar(
|
||||
if (index >= stringPtr->numChars) {
|
||||
return -1;
|
||||
}
|
||||
ch = stringPtr->unicode[index];
|
||||
ch = stringPtr->unicode[index];
|
||||
#if TCL_UTF_MAX <= 4
|
||||
/* See: bug [11ae2be95dac9417] */
|
||||
if ((ch&0xF800) == 0xD800) {
|
||||
if (ch&0x400) {
|
||||
if ((index > 0) && ((stringPtr->unicode[index-1]&0xFC00) == 0xD800)) {
|
||||
ch = -1; /* low surrogate preceded by high surrogate */
|
||||
}
|
||||
} else if ((++index < stringPtr->numChars)
|
||||
&& ((stringPtr->unicode[index]&0xFC00) == 0xDC00)) {
|
||||
/* high surrogate followed by low surrogate */
|
||||
ch = (((ch & 0x3FF) << 10) | (stringPtr->unicode[index] & 0x3FF)) + 0x10000;
|
||||
/* See: bug [11ae2be95dac9417] */
|
||||
if ((ch & 0xF800) == 0xD800) {
|
||||
if (ch & 0x400) {
|
||||
if ((index > 0)
|
||||
&& ((stringPtr->unicode[index-1] & 0xFC00) == 0xD800)) {
|
||||
ch = -1; /* low surrogate preceded by high surrogate */
|
||||
}
|
||||
} else if ((++index < stringPtr->numChars)
|
||||
&& ((stringPtr->unicode[index] & 0xFC00) == 0xDC00)) {
|
||||
/* high surrogate followed by low surrogate */
|
||||
ch = (((ch & 0x3FF) << 10) |
|
||||
(stringPtr->unicode[index] & 0x3FF)) + 0x10000;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return ch;
|
||||
}
|
||||
@@ -644,7 +688,8 @@ Tcl_GetRange(
|
||||
|
||||
if (first < 0) {
|
||||
first = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Optimize the case where we're really dealing with a bytearray object
|
||||
* we don't need to convert to a string to perform the substring operation.
|
||||
@@ -652,13 +697,14 @@ Tcl_GetRange(
|
||||
|
||||
if (TclIsPureByteArray(objPtr)) {
|
||||
unsigned char *bytes = Tcl_GetByteArrayFromObj(objPtr, &length);
|
||||
|
||||
if (last >= length) {
|
||||
last = length - 1;
|
||||
}
|
||||
if (last < first) {
|
||||
return Tcl_NewObj();
|
||||
}
|
||||
return Tcl_NewByteArrayObj(bytes+first, last-first+1);
|
||||
return Tcl_NewByteArrayObj(bytes + first, last - first + 1);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -697,24 +743,25 @@ Tcl_GetRange(
|
||||
FillUnicodeRep(objPtr);
|
||||
stringPtr = GET_STRING(objPtr);
|
||||
}
|
||||
if (last > stringPtr->numChars) {
|
||||
last = stringPtr->numChars;
|
||||
}
|
||||
if (last < first) {
|
||||
return Tcl_NewObj();
|
||||
}
|
||||
if (last > stringPtr->numChars) {
|
||||
last = stringPtr->numChars;
|
||||
}
|
||||
if (last < first) {
|
||||
return Tcl_NewObj();
|
||||
}
|
||||
#if TCL_UTF_MAX <= 4
|
||||
/* See: bug [11ae2be95dac9417] */
|
||||
if ((first>0) && ((stringPtr->unicode[first]&0xFC00) == 0xDC00)
|
||||
&& ((stringPtr->unicode[first-1]&0xFC00) == 0xD800)) {
|
||||
++first;
|
||||
}
|
||||
if ((last+1<stringPtr->numChars) && ((stringPtr->unicode[last+1]&0xFC00) == 0xDC00)
|
||||
&& ((stringPtr->unicode[last]&0xFC00) == 0xD800)) {
|
||||
++last;
|
||||
}
|
||||
/* See: bug [11ae2be95dac9417] */
|
||||
if ((first > 0) && ((stringPtr->unicode[first] & 0xFC00) == 0xDC00)
|
||||
&& ((stringPtr->unicode[first-1] & 0xFC00) == 0xD800)) {
|
||||
++first;
|
||||
}
|
||||
if ((last + 1 < stringPtr->numChars)
|
||||
&& ((stringPtr->unicode[last+1] & 0xFC00) == 0xDC00)
|
||||
&& ((stringPtr->unicode[last] & 0xFC00) == 0xD800)) {
|
||||
++last;
|
||||
}
|
||||
#endif
|
||||
return Tcl_NewUnicodeObj(stringPtr->unicode + first, last-first+1);
|
||||
return Tcl_NewUnicodeObj(stringPtr->unicode + first, last - first + 1);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1272,45 +1319,51 @@ Tcl_AppendObjToObj(
|
||||
/*
|
||||
* Handle append of one bytearray object to another as a special case.
|
||||
* Note that we only do this when the objects are pure so that the
|
||||
* bytearray faithfully represent the true value; Otherwise
|
||||
* appending the byte arrays together could lose information;
|
||||
* bytearray faithfully represent the true value; Otherwise appending the
|
||||
* byte arrays together could lose information;
|
||||
*/
|
||||
|
||||
if ((TclIsPureByteArray(objPtr) || objPtr->bytes == &tclEmptyString)
|
||||
&& TclIsPureByteArray(appendObjPtr)) {
|
||||
|
||||
/*
|
||||
* You might expect the code here to be
|
||||
*
|
||||
* bytes = Tcl_GetByteArrayFromObj(appendObjPtr, &length);
|
||||
* TclAppendBytesToByteArray(objPtr, bytes, length);
|
||||
*
|
||||
* and essentially all of the time that would be fine. However,
|
||||
* it would run into trouble in the case where objPtr and
|
||||
* appendObjPtr point to the same thing. That may never be a
|
||||
* good idea. It seems to violate Copy On Write, and we don't
|
||||
* have any tests for the situation, since making any Tcl commands
|
||||
* that call Tcl_AppendObjToObj() do that appears impossible
|
||||
* (They honor Copy On Write!). For the sake of extensions that
|
||||
* go off into that realm, though, here's a more complex approach
|
||||
* that can handle all the cases.
|
||||
* and essentially all of the time that would be fine. However, it
|
||||
* would run into trouble in the case where objPtr and appendObjPtr
|
||||
* point to the same thing. That may never be a good idea. It seems to
|
||||
* violate Copy On Write, and we don't have any tests for the
|
||||
* situation, since making any Tcl commands that call
|
||||
* Tcl_AppendObjToObj() do that appears impossible (They honor Copy On
|
||||
* Write!). For the sake of extensions that go off into that realm,
|
||||
* though, here's a more complex approach that can handle all the
|
||||
* cases.
|
||||
*
|
||||
* First, get the lengths.
|
||||
*/
|
||||
|
||||
/* Get lengths */
|
||||
int lengthSrc;
|
||||
|
||||
(void) Tcl_GetByteArrayFromObj(objPtr, &length);
|
||||
(void) Tcl_GetByteArrayFromObj(appendObjPtr, &lengthSrc);
|
||||
|
||||
/* Grow buffer enough for the append */
|
||||
/*
|
||||
* Grow buffer enough for the append.
|
||||
*/
|
||||
|
||||
TclAppendBytesToByteArray(objPtr, NULL, lengthSrc);
|
||||
|
||||
/* Reset objPtr back to the original value */
|
||||
/*
|
||||
* Reset objPtr back to the original value.
|
||||
*/
|
||||
|
||||
Tcl_SetByteArrayLength(objPtr, length);
|
||||
|
||||
/*
|
||||
* Now do the append knowing that buffer growth cannot cause
|
||||
* any trouble.
|
||||
* Now do the append knowing that buffer growth cannot cause any
|
||||
* trouble.
|
||||
*/
|
||||
|
||||
TclAppendBytesToByteArray(objPtr,
|
||||
@@ -1358,6 +1411,7 @@ Tcl_AppendObjToObj(
|
||||
numChars = stringPtr->numChars;
|
||||
if ((numChars >= 0) && (appendObjPtr->typePtr == &tclStringType)) {
|
||||
String *appendStringPtr = GET_STRING(appendObjPtr);
|
||||
|
||||
appendNumChars = appendStringPtr->numChars;
|
||||
}
|
||||
|
||||
@@ -1943,7 +1997,8 @@ Tcl_AppendFormatToObj(
|
||||
format += step;
|
||||
step = TclUtfToUniChar(format, &ch);
|
||||
}
|
||||
} else if ((ch == 't') || (ch == 'z') || (ch == 'q') || (ch == 'j') || (ch == 'L')) {
|
||||
} else if ((ch == 't') || (ch == 'z') || (ch == 'q') || (ch == 'j')
|
||||
|| (ch == 'L')) {
|
||||
format += step;
|
||||
step = TclUtfToUniChar(format, &ch);
|
||||
useBig = 1;
|
||||
@@ -2468,7 +2523,7 @@ Tcl_AppendFormatToObj(
|
||||
/*
|
||||
*---------------------------------------------------------------------------
|
||||
*
|
||||
* Tcl_Format--
|
||||
* Tcl_Format --
|
||||
*
|
||||
* Results:
|
||||
* A refcount zero Tcl_Obj.
|
||||
@@ -2859,7 +2914,10 @@ TclStringRepeat(
|
||||
Tcl_GetByteArrayFromObj(objResultPtr, NULL),
|
||||
(count - done) * length);
|
||||
} else if (unichar) {
|
||||
/* Efficiently produce a pure Tcl_UniChar array result */
|
||||
/*
|
||||
* Efficiently produce a pure Tcl_UniChar array result.
|
||||
*/
|
||||
|
||||
if (!inPlace || Tcl_IsShared(objPtr)) {
|
||||
objResultPtr = Tcl_NewUnicodeObj(Tcl_GetUnicode(objPtr), length);
|
||||
} else {
|
||||
@@ -2885,7 +2943,10 @@ TclStringRepeat(
|
||||
Tcl_AppendUnicodeToObj(objResultPtr, Tcl_GetUnicode(objResultPtr),
|
||||
(count - done) * length);
|
||||
} else {
|
||||
/* Efficiently concatenate string reps */
|
||||
/*
|
||||
* Efficiently concatenate string reps.
|
||||
*/
|
||||
|
||||
if (!inPlace || Tcl_IsShared(objPtr)) {
|
||||
objResultPtr = Tcl_NewStringObj(Tcl_GetString(objPtr), length);
|
||||
} else {
|
||||
@@ -2969,9 +3030,10 @@ TclStringCat(
|
||||
/* Value has a string rep. */
|
||||
if (objPtr->length) {
|
||||
/*
|
||||
* Non-empty string rep. Not a pure bytearray, so we
|
||||
* won't create a pure bytearray
|
||||
* Non-empty string rep. Not a pure bytearray, so we won't
|
||||
* create a pure bytearray.
|
||||
*/
|
||||
|
||||
binary = 0;
|
||||
if ((objPtr->typePtr) && (objPtr->typePtr != &tclStringType)) {
|
||||
/* Prevent shimmer of non-string types. */
|
||||
@@ -2992,8 +3054,12 @@ TclStringCat(
|
||||
} while (--oc && (binary || allowUniChar));
|
||||
|
||||
if (binary) {
|
||||
/* Result will be pure byte array. Pre-size it */
|
||||
ov = objv; oc = objc;
|
||||
/*
|
||||
* Result will be pure byte array. Pre-size it
|
||||
*/
|
||||
|
||||
ov = objv;
|
||||
oc = objc;
|
||||
do {
|
||||
Tcl_Obj *objPtr = *ov++;
|
||||
|
||||
@@ -3013,8 +3079,12 @@ TclStringCat(
|
||||
}
|
||||
} while (--oc);
|
||||
} else if (allowUniChar && requestUniChar) {
|
||||
/* Result will be pure Tcl_UniChar array. Pre-size it. */
|
||||
ov = objv; oc = objc;
|
||||
/*
|
||||
* Result will be pure Tcl_UniChar array. Pre-size it.
|
||||
*/
|
||||
|
||||
ov = objv;
|
||||
oc = objc;
|
||||
do {
|
||||
Tcl_Obj *objPtr = *ov++;
|
||||
|
||||
@@ -3059,9 +3129,9 @@ TclStringCat(
|
||||
} while (--oc && (length == 0) && (pendingPtr == NULL));
|
||||
|
||||
/*
|
||||
* Either we found a possibly non-empty value, and we
|
||||
* remember this index as the first and last such value so
|
||||
* far seen, or (oc == 0) and all values are known empty,
|
||||
* Either we found a possibly non-empty value, and we remember
|
||||
* this index as the first and last such value so far seen,
|
||||
* or (oc == 0) and all values are known empty,
|
||||
* so first = last = objc - 1 signals the right quick return.
|
||||
*/
|
||||
|
||||
@@ -3073,10 +3143,9 @@ TclStringCat(
|
||||
/* assert ( pendingPtr != NULL ) */
|
||||
|
||||
/*
|
||||
* There's a pending value followed by more values.
|
||||
* Loop over remaining values generating strings until
|
||||
* a non-empty value is found, or the pending value gets
|
||||
* its string generated.
|
||||
* There's a pending value followed by more values. Loop over
|
||||
* remaining values generating strings until a non-empty value
|
||||
* is found, or the pending value gets its string generated.
|
||||
*/
|
||||
|
||||
do {
|
||||
@@ -3132,10 +3201,10 @@ TclStringCat(
|
||||
unsigned char *dst;
|
||||
|
||||
/*
|
||||
* Broken interface! Byte array value routines offer no way
|
||||
* to handle failure to allocate enough space. Following
|
||||
* stanza may panic.
|
||||
* Broken interface! Byte array value routines offer no way to handle
|
||||
* failure to allocate enough space. Following stanza may panic.
|
||||
*/
|
||||
|
||||
if (inPlace && !Tcl_IsShared(*objv)) {
|
||||
int start;
|
||||
|
||||
@@ -3250,6 +3319,7 @@ TclStringCat(
|
||||
if ((objPtr->bytes == NULL) || (objPtr->length)) {
|
||||
int more;
|
||||
char *src = Tcl_GetStringFromObj(objPtr, &more);
|
||||
|
||||
memcpy(dst, src, (size_t) more);
|
||||
dst += more;
|
||||
}
|
||||
@@ -3268,6 +3338,187 @@ TclStringCat(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
*---------------------------------------------------------------------------
|
||||
*
|
||||
* TclStringCmp --
|
||||
* Compare two Tcl_Obj values as strings.
|
||||
*
|
||||
* Results:
|
||||
* Like memcmp, return -1, 0, or 1.
|
||||
*
|
||||
* Side effects:
|
||||
* String representations may be generated. Internal representation may
|
||||
* be changed.
|
||||
*
|
||||
*---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int TclStringCmp(
|
||||
Tcl_Obj *value1Ptr,
|
||||
Tcl_Obj *value2Ptr,
|
||||
int checkEq, /* comparison is only for equality */
|
||||
int nocase, /* comparison is not case sensitive */
|
||||
int reqlength) /* requested length */
|
||||
{
|
||||
char *s1, *s2;
|
||||
int empty, length, match, s1len, s2len;
|
||||
memCmpFn_t memCmpFn;
|
||||
|
||||
if ((reqlength == 0) || (value1Ptr == value2Ptr)) {
|
||||
/*
|
||||
* Always match at 0 chars of if it is the same obj.
|
||||
*/
|
||||
match = 0;
|
||||
} else {
|
||||
|
||||
if (!nocase && TclIsPureByteArray(value1Ptr)
|
||||
&& TclIsPureByteArray(value2Ptr)) {
|
||||
/*
|
||||
* 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... :^)
|
||||
*/
|
||||
|
||||
s1 = (char *) Tcl_GetByteArrayFromObj(value1Ptr, &s1len);
|
||||
s2 = (char *) Tcl_GetByteArrayFromObj(value2Ptr, &s2len);
|
||||
memCmpFn = memcmp;
|
||||
} else if ((value1Ptr->typePtr == &tclStringType)
|
||||
&& (value2Ptr->typePtr == &tclStringType)) {
|
||||
/*
|
||||
* Do a unicode-specific comparison if both of the args are of
|
||||
* String type. If the char length == byte length, we can do a
|
||||
* memcmp. In benchmark testing this proved the most efficient
|
||||
* check between the unicode and string comparison operations.
|
||||
*/
|
||||
|
||||
if (nocase) {
|
||||
s1 = (char *) Tcl_GetUnicodeFromObj(value1Ptr, &s1len);
|
||||
s2 = (char *) Tcl_GetUnicodeFromObj(value2Ptr, &s2len);
|
||||
memCmpFn = (memCmpFn_t)Tcl_UniCharNcasecmp;
|
||||
} else {
|
||||
s1len = Tcl_GetCharLength(value1Ptr);
|
||||
s2len = Tcl_GetCharLength(value2Ptr);
|
||||
if ((s1len == value1Ptr->length)
|
||||
&& (value1Ptr->bytes != NULL)
|
||||
&& (s2len == value2Ptr->length)
|
||||
&& (value2Ptr->bytes != NULL)) {
|
||||
s1 = value1Ptr->bytes;
|
||||
s2 = value2Ptr->bytes;
|
||||
memCmpFn = memcmp;
|
||||
} else {
|
||||
s1 = (char *) Tcl_GetUnicode(value1Ptr);
|
||||
s2 = (char *) Tcl_GetUnicode(value2Ptr);
|
||||
if (
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
1
|
||||
#else
|
||||
checkEq
|
||||
#endif
|
||||
) {
|
||||
memCmpFn = memcmp;
|
||||
s1len *= sizeof(Tcl_UniChar);
|
||||
s2len *= sizeof(Tcl_UniChar);
|
||||
} else {
|
||||
memCmpFn = (memCmpFn_t) Tcl_UniCharNcmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ((empty = TclCheckEmptyString(value1Ptr)) > 0) {
|
||||
switch (TclCheckEmptyString(value2Ptr)) {
|
||||
case -1:
|
||||
s1 = 0;
|
||||
s1len = 0;
|
||||
s2 = TclGetStringFromObj(value2Ptr, &s2len);
|
||||
break;
|
||||
case 0:
|
||||
match = -1;
|
||||
goto matchdone;
|
||||
case 1:
|
||||
default: /* avoid warn: `s2` may be used uninitialized */
|
||||
match = 0;
|
||||
goto matchdone;
|
||||
}
|
||||
} else if (TclCheckEmptyString(value2Ptr) > 0) {
|
||||
switch (empty) {
|
||||
case -1:
|
||||
s2 = 0;
|
||||
s2len = 0;
|
||||
s1 = TclGetStringFromObj(value1Ptr, &s1len);
|
||||
break;
|
||||
case 0:
|
||||
match = 1;
|
||||
goto matchdone;
|
||||
case 1:
|
||||
default: /* avoid warn: `s1` may be used uninitialized */
|
||||
match = 0;
|
||||
goto matchdone;
|
||||
}
|
||||
} else {
|
||||
s1 = TclGetStringFromObj(value1Ptr, &s1len);
|
||||
s2 = TclGetStringFromObj(value2Ptr, &s2len);
|
||||
}
|
||||
if (!nocase && checkEq) {
|
||||
/*
|
||||
* When we have equal-length we can check only for
|
||||
* (in)equality. We can use memcmp in all (n)eq cases because
|
||||
* we don't need to worry about lexical LE/BE variance.
|
||||
*/
|
||||
|
||||
memCmpFn = memcmp;
|
||||
} else {
|
||||
/*
|
||||
* As a catch-all we will work with UTF-8. We cannot use
|
||||
* memcmp() as that is unsafe with any string containing NUL
|
||||
* (\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.
|
||||
*/
|
||||
|
||||
if ((reqlength < 0) && !nocase) {
|
||||
memCmpFn = (memCmpFn_t) TclpUtfNcmp2;
|
||||
} else {
|
||||
s1len = Tcl_NumUtfChars(s1, s1len);
|
||||
s2len = Tcl_NumUtfChars(s2, s2len);
|
||||
memCmpFn = (memCmpFn_t)
|
||||
(nocase ? Tcl_UtfNcasecmp : Tcl_UtfNcmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
length = (s1len < s2len) ? s1len : s2len;
|
||||
if (reqlength > 0 && reqlength < length) {
|
||||
length = reqlength;
|
||||
} else if (reqlength < 0) {
|
||||
/*
|
||||
* The requested length is negative, so we ignore it by setting it
|
||||
* to length + 1 so we correct the match var.
|
||||
*/
|
||||
|
||||
reqlength = length + 1;
|
||||
}
|
||||
|
||||
if (checkEq && (s1len != s2len)) {
|
||||
match = 1; /* This will be reversed below. */
|
||||
} else {
|
||||
/*
|
||||
* The comparison function should compare up to the minimum byte
|
||||
* length only.
|
||||
*/
|
||||
|
||||
match = memCmpFn(s1, s2, (size_t) length);
|
||||
}
|
||||
if ((match == 0) && (reqlength > length)) {
|
||||
match = s1len - s2len;
|
||||
}
|
||||
match = (match > 0) ? 1 : (match < 0) ? -1 : 0;
|
||||
}
|
||||
matchdone:
|
||||
return match;
|
||||
}
|
||||
|
||||
/*
|
||||
*---------------------------------------------------------------------------
|
||||
*
|
||||
@@ -3462,18 +3713,20 @@ static void
|
||||
ReverseBytes(
|
||||
unsigned char *to, /* Copy bytes into here... */
|
||||
unsigned char *from, /* ...from here... */
|
||||
int count) /* Until this many are copied, */
|
||||
int count) /* Until this many are copied, */
|
||||
/* reversing as you go. */
|
||||
{
|
||||
unsigned char *src = from + count;
|
||||
|
||||
if (to == from) {
|
||||
/* Reversing in place */
|
||||
while (--src > to) {
|
||||
unsigned char c = *src;
|
||||
|
||||
*src = *to;
|
||||
*to++ = c;
|
||||
}
|
||||
} else {
|
||||
} else {
|
||||
while (--src >= from) {
|
||||
*to++ = *src;
|
||||
}
|
||||
@@ -3522,7 +3775,10 @@ TclStringReverse(
|
||||
*to++ = *src;
|
||||
}
|
||||
} else {
|
||||
/* Reversing in place */
|
||||
/*
|
||||
* Reversing in place.
|
||||
*/
|
||||
|
||||
while (--src > from) {
|
||||
ch = *src;
|
||||
*src = *from;
|
||||
@@ -3546,20 +3802,22 @@ TclStringReverse(
|
||||
/*
|
||||
* Either numChars == -1 and we don't know how many chars are
|
||||
* represented by objPtr->bytes and we need Pass 1 just in case,
|
||||
* or numChars >= 0 and we know we have fewer chars than bytes,
|
||||
* so we know there's a multibyte character needing Pass 1.
|
||||
* or numChars >= 0 and we know we have fewer chars than bytes, so
|
||||
* we know there's a multibyte character needing Pass 1.
|
||||
*
|
||||
* Pass 1. Reverse the bytes of each multi-byte character.
|
||||
*/
|
||||
|
||||
int charCount = 0;
|
||||
int bytesLeft = numBytes;
|
||||
|
||||
while (bytesLeft) {
|
||||
/*
|
||||
* NOTE: We know that the from buffer is NUL-terminated.
|
||||
* It's part of the contract for objPtr->bytes values.
|
||||
* Thus, we can skip calling Tcl_UtfCharComplete() here.
|
||||
* NOTE: We know that the from buffer is NUL-terminated. It's
|
||||
* part of the contract for objPtr->bytes values. Thus, we can
|
||||
* skip calling Tcl_UtfCharComplete() here.
|
||||
*/
|
||||
|
||||
int bytesInChar = TclUtfToUniChar(from, &ch);
|
||||
|
||||
ReverseBytes((unsigned char *)to, (unsigned char *)from,
|
||||
@@ -3589,19 +3847,18 @@ TclStringReverse(
|
||||
*
|
||||
* The result is a concatenation of a prefix from objPtr, characters
|
||||
* 0 through first-1, the insertPtr string value, and a suffix from
|
||||
* objPtr, characters from first + count to the end. The effect is
|
||||
* as if the inner substring of characters first through first+count-1
|
||||
* are removed and replaced with insertPtr.
|
||||
* If insertPtr is NULL, it is treated as an empty string.
|
||||
* When passed the flag TCL_STRING_IN_PLACE, this routine will try
|
||||
* to do the work within objPtr, so long as no sharing forbids it.
|
||||
* Without that request, or as needed, a new Tcl value will be allocated
|
||||
* to be the result.
|
||||
* objPtr, characters from first + count to the end. The effect is as if
|
||||
* the inner substring of characters first through first+count-1 are
|
||||
* removed and replaced with insertPtr. If insertPtr is NULL, it is
|
||||
* treated as an empty string. When passed the flag TCL_STRING_IN_PLACE,
|
||||
* this routine will try to do the work within objPtr, so long as no
|
||||
* sharing forbids it. Without that request, or as needed, a new Tcl
|
||||
* value will be allocated to be the result.
|
||||
*
|
||||
* Results:
|
||||
* A Tcl value that is the result of the substring replacement.
|
||||
* May return NULL in case of an error. When NULL is returned and
|
||||
* interp is non-NULL, error information is left in interp
|
||||
* A Tcl value that is the result of the substring replacement. May
|
||||
* return NULL in case of an error. When NULL is returned and interp is
|
||||
* non-NULL, error information is left in interp
|
||||
*
|
||||
*---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#undef Tcl_CreateHashEntry
|
||||
#undef Tcl_Panic
|
||||
#undef Tcl_FindExecutable
|
||||
#undef Tcl_SetPanicProc
|
||||
#undef TclpGetPid
|
||||
#undef TclSockMinimumBuffers
|
||||
#undef Tcl_SetIntObj
|
||||
@@ -454,6 +455,15 @@ tellOld(
|
||||
MODULE_SCOPE const TclStubs tclStubs;
|
||||
MODULE_SCOPE const TclTomMathStubs tclTomMathStubs;
|
||||
|
||||
#ifdef __GNUC__
|
||||
/*
|
||||
* The rest of this file shouldn't warn about deprecated functions; they're
|
||||
* there because we intend them to be so and know that this file is OK to
|
||||
* touch those fields.
|
||||
*/
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
#endif
|
||||
|
||||
/* !BEGIN!: Do not edit below this line. */
|
||||
|
||||
static const TclIntStubs tclIntStubs = {
|
||||
@@ -1577,6 +1587,8 @@ const TclStubs tclStubs = {
|
||||
Tcl_FSUnloadFile, /* 629 */
|
||||
Tcl_ZlibStreamSetCompressionDictionary, /* 630 */
|
||||
Tcl_OpenTcpServerEx, /* 631 */
|
||||
0, /* 632 */
|
||||
Tcl_LinkArray, /* 633 */
|
||||
};
|
||||
|
||||
/* !END!: Do not edit above this line. */
|
||||
|
||||
+156
-4
@@ -161,7 +161,7 @@ static TestChannel *firstDetached;
|
||||
|
||||
static int AsyncHandlerProc(ClientData clientData,
|
||||
Tcl_Interp *interp, int code);
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
static Tcl_ThreadCreateType AsyncThreadProc(ClientData);
|
||||
#endif
|
||||
static void CleanupTestSetassocdataTests(
|
||||
@@ -302,6 +302,9 @@ static int TestinterpdeleteCmd(ClientData dummy,
|
||||
Tcl_Interp *interp, int argc, const char **argv);
|
||||
static int TestlinkCmd(ClientData dummy,
|
||||
Tcl_Interp *interp, int argc, const char **argv);
|
||||
static int TestlinkarrayCmd(ClientData dummy,
|
||||
Tcl_Interp *interp, int objc,
|
||||
Tcl_Obj *const objv[]);
|
||||
static int TestlocaleCmd(ClientData dummy,
|
||||
Tcl_Interp *interp, int objc,
|
||||
Tcl_Obj *const objv[]);
|
||||
@@ -652,6 +655,7 @@ Tcltest_Init(
|
||||
Tcl_CreateCommand(interp, "testinterpdelete", TestinterpdeleteCmd,
|
||||
NULL, NULL);
|
||||
Tcl_CreateCommand(interp, "testlink", TestlinkCmd, NULL, NULL);
|
||||
Tcl_CreateObjCommand(interp, "testlinkarray", TestlinkarrayCmd, NULL, NULL);
|
||||
Tcl_CreateObjCommand(interp, "testlocale", TestlocaleCmd, NULL,
|
||||
NULL);
|
||||
Tcl_CreateCommand(interp, "testpanic", TestpanicCmd, NULL, NULL);
|
||||
@@ -722,7 +726,7 @@ Tcltest_Init(
|
||||
if (Procbodytest_Init(interp) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
if (TclThread_Init(interp) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
@@ -902,7 +906,7 @@ TestasyncCmd(
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(argv[3], -1));
|
||||
Tcl_MutexUnlock(&asyncTestMutex);
|
||||
return code;
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
} else if (strcmp(argv[1], "marklater") == 0) {
|
||||
if (argc != 3) {
|
||||
goto wrongNumArgs;
|
||||
@@ -999,7 +1003,7 @@ AsyncHandlerProc(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
static Tcl_ThreadCreateType
|
||||
AsyncThreadProc(
|
||||
ClientData clientData) /* Parameter is the id of a
|
||||
@@ -3269,6 +3273,154 @@ TestlinkCmd(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TestlinkarrayCmd --
|
||||
* This procedure implements the "testlinkarray" command. It is used
|
||||
* to test Tcl_LinkArray and related library procedures.
|
||||
* Additionally it can be used as an example on how to implement
|
||||
* a script link command with access to internal TCL_Link* functions.
|
||||
* It is not a global tcl command because of security reasons.
|
||||
* Use it in your extension on your own risk.
|
||||
*
|
||||
* Usage:
|
||||
* testlinkobj update <name> ..
|
||||
* Update given Tcl-variables with content from C-address
|
||||
* testlinkobj remove <name> ..
|
||||
* Remove link to C-variable. Free C-variable if it was created in
|
||||
* "create" command.
|
||||
* testlinkobj create ?-readonly? <type> <size> <name> ?address?
|
||||
* Create new linked variable. If "-readonly" is given variable can
|
||||
* only be read from tcl side. If address is given use it as address of
|
||||
* C-variable. Otherwise create a new C-variable of needed size.
|
||||
* testlinkobj types
|
||||
* Return list of available types.
|
||||
* Results:
|
||||
* A standard Tcl result.
|
||||
*
|
||||
* Side effects:
|
||||
* Creates and deletes various variable links, plus returns
|
||||
* values of the linked variables.
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
static int
|
||||
TestlinkarrayCmd(
|
||||
ClientData dummy, /* Not used. */
|
||||
Tcl_Interp *interp, /* Current interpreter. */
|
||||
int objc, /* Number of arguments. */
|
||||
Tcl_Obj * const objv[]) /* Argument strings. */
|
||||
{
|
||||
static const char *LinkOption[] = {
|
||||
"update", "remove", "create", "types", NULL
|
||||
};
|
||||
enum LinkOption
|
||||
{ LINK_UPDATE, LINK_REMOVE, LINK_CREATE, LINK_TYPES };
|
||||
static const char *LinkType[] = {
|
||||
"int", "double", "bool", "string",
|
||||
"wideint", "char", "uchar",
|
||||
"short", "ushort", "uint",
|
||||
"long", "ulong", "float",
|
||||
"uint", "chars",
|
||||
"complex32", "complex64", "binary"
|
||||
"hex8", "hex16", "hex32", "hex64",
|
||||
"bitarray8", "bitarray16", "bitarray32", "bitarray64",
|
||||
"bool8", "bool16", "bool32", "bool64",
|
||||
"bit8", "bit16", "bit32", "bit64",
|
||||
"s5float", "s5time", NULL
|
||||
};
|
||||
static const int LinkTypes[] = {
|
||||
TCL_LINK_INT, TCL_LINK_DOUBLE, TCL_LINK_BOOLEAN, TCL_LINK_STRING,
|
||||
TCL_LINK_WIDE_INT, TCL_LINK_CHAR, TCL_LINK_UCHAR,
|
||||
TCL_LINK_SHORT, TCL_LINK_USHORT, TCL_LINK_UINT,
|
||||
TCL_LINK_LONG, TCL_LINK_ULONG, TCL_LINK_FLOAT,
|
||||
TCL_LINK_WIDE_UINT, TCL_LINK_CHARS,
|
||||
TCL_TYPE_C(float), TCL_TYPE_C(double), TCL_LINK_BINARY ,
|
||||
TCL_TYPE_X(char), TCL_TYPE_X(short), TCL_TYPE_X(int), TCL_TYPE_X(Tcl_WideInt),
|
||||
TCL_LINK_BITARRAY8, TCL_LINK_BITARRAY16,
|
||||
TCL_LINK_BITARRAY32, TCL_LINK_BITARRAY64,
|
||||
TCL_TYPE_B(char), TCL_TYPE_B(short), TCL_TYPE_B(int), TCL_TYPE_B(Tcl_WideInt),
|
||||
TCL_LINK_BIT8, TCL_LINK_BIT16, TCL_LINK_BIT32, TCL_LINK_BIT64,
|
||||
TCL_LINK_S5FLOAT, TCL_LINK_S5TIME
|
||||
};
|
||||
int optionIndex;
|
||||
int typeIndex;
|
||||
int readonly;
|
||||
int i;
|
||||
char *name;
|
||||
Tcl_WideInt addr;
|
||||
int size;
|
||||
char *arg;
|
||||
int length;
|
||||
|
||||
if (objc < 2) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "option args");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (Tcl_GetIndexFromObj(interp, objv[1], LinkOption, "option", 0,
|
||||
&optionIndex) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
switch ((enum LinkOption) optionIndex) {
|
||||
case LINK_UPDATE:
|
||||
for (i = 2; i < objc; i++) {
|
||||
Tcl_UpdateLinkedVar(interp, Tcl_GetString(objv[i]));
|
||||
}
|
||||
return TCL_OK;
|
||||
case LINK_REMOVE:
|
||||
for (i = 2; i < objc; i++) {
|
||||
Tcl_UnlinkVar(interp, Tcl_GetString(objv[i]));
|
||||
}
|
||||
return TCL_OK;
|
||||
case LINK_TYPES:
|
||||
Tcl_AppendResult(interp, "int double bool string wideint char uchar short ushort uint long ulong float uint chars complex32 complex64 binary hex8 hex16 hex32 hex64 bitarray8 bitarray16 bitarray32 bitarray64 bool8 bool16 bool32 bool64 bit8 bit16 bit32 bit64 s5float s5time", NULL);
|
||||
return TCL_OK;
|
||||
case LINK_CREATE:
|
||||
if (objc < 4) {
|
||||
goto wrongArgs;
|
||||
}
|
||||
readonly = 0;
|
||||
i = 2;
|
||||
/* test on switch -r... */
|
||||
arg = Tcl_GetStringFromObj(objv[i], &length);
|
||||
if (length < 2) {
|
||||
goto wrongArgs;
|
||||
}
|
||||
if (arg[0] == '-') {
|
||||
if (arg[1] != 'r') {
|
||||
goto wrongArgs;
|
||||
}
|
||||
readonly = TCL_LINK_READ_ONLY;
|
||||
i++;
|
||||
}
|
||||
if (Tcl_GetIndexFromObj(interp, objv[i++], LinkType, "type", 0,
|
||||
&typeIndex) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (Tcl_GetIntFromObj(interp, objv[i++], &size) == TCL_ERROR) {
|
||||
Tcl_AppendResult(interp, "wrong size value", NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
name = Tcl_GetString(objv[i++]);
|
||||
/* if no address is given request one in the underlying function */
|
||||
if (i < objc) {
|
||||
if (Tcl_GetWideIntFromObj(interp, objv[i], &addr) == TCL_ERROR) {
|
||||
Tcl_AppendResult(interp, "wrong address value", NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
} else {
|
||||
addr = 0;
|
||||
}
|
||||
return Tcl_LinkArray(interp, name, (char *) addr,
|
||||
LinkTypes[typeIndex] | readonly, size);
|
||||
}
|
||||
return TCL_OK;
|
||||
|
||||
wrongArgs:
|
||||
Tcl_WrongNumArgs(interp, 2, objv, "?-readonly? type size name ?address?");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
|
||||
+10
-25
@@ -40,21 +40,6 @@ static void ForgetSyncObject(void *objPtr, SyncObjRecord *recPtr);
|
||||
static void RememberSyncObject(void *objPtr,
|
||||
SyncObjRecord *recPtr);
|
||||
|
||||
/*
|
||||
* Several functions are #defined to nothing in tcl.h if TCL_THREADS is not
|
||||
* specified. Here we undo that so the functions are defined in the stubs
|
||||
* table.
|
||||
*/
|
||||
|
||||
#ifndef TCL_THREADS
|
||||
#undef Tcl_MutexLock
|
||||
#undef Tcl_MutexUnlock
|
||||
#undef Tcl_MutexFinalize
|
||||
#undef Tcl_ConditionNotify
|
||||
#undef Tcl_ConditionWait
|
||||
#undef Tcl_ConditionFinalize
|
||||
#endif
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
@@ -79,7 +64,7 @@ Tcl_GetThreadData(
|
||||
int size) /* Size of storage block */
|
||||
{
|
||||
void *result;
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
/*
|
||||
* Initialize the key for this thread.
|
||||
*/
|
||||
@@ -126,7 +111,7 @@ TclThreadDataKeyGet(
|
||||
Tcl_ThreadDataKey *keyPtr) /* Identifier for the data chunk. */
|
||||
|
||||
{
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
return TclThreadStorageKeyGet(keyPtr);
|
||||
#else /* TCL_THREADS */
|
||||
return *keyPtr;
|
||||
@@ -269,11 +254,12 @@ TclRememberMutex(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#undef Tcl_MutexFinalize
|
||||
void
|
||||
Tcl_MutexFinalize(
|
||||
Tcl_Mutex *mutexPtr)
|
||||
{
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
TclpFinalizeMutex(mutexPtr);
|
||||
#endif
|
||||
TclpMasterLock();
|
||||
@@ -322,11 +308,12 @@ TclRememberCondition(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#undef Tcl_ConditionFinalize
|
||||
void
|
||||
Tcl_ConditionFinalize(
|
||||
Tcl_Condition *condPtr)
|
||||
{
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
TclpFinalizeCondition(condPtr);
|
||||
#endif
|
||||
TclpMasterLock();
|
||||
@@ -356,7 +343,7 @@ void
|
||||
TclFinalizeThreadData(int quick)
|
||||
{
|
||||
TclFinalizeThreadDataThread();
|
||||
#if defined(TCL_THREADS) && defined(USE_THREAD_ALLOC)
|
||||
#if TCL_THREADS && defined(USE_THREAD_ALLOC)
|
||||
if (!quick) {
|
||||
/*
|
||||
* Quick exit principle makes it useless to terminate allocators
|
||||
@@ -389,7 +376,7 @@ TclFinalizeSynchronization(void)
|
||||
int i;
|
||||
void *blockPtr;
|
||||
Tcl_ThreadDataKey *keyPtr;
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
Tcl_Mutex *mutexPtr;
|
||||
Tcl_Condition *condPtr;
|
||||
|
||||
@@ -413,7 +400,7 @@ TclFinalizeSynchronization(void)
|
||||
keyRecord.max = 0;
|
||||
keyRecord.num = 0;
|
||||
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
/*
|
||||
* Call thread storage master cleanup.
|
||||
*/
|
||||
@@ -473,12 +460,10 @@ Tcl_ExitThread(
|
||||
int status)
|
||||
{
|
||||
Tcl_FinalizeThread();
|
||||
#ifdef TCL_THREADS
|
||||
TclpThreadExit(status);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef TCL_THREADS
|
||||
#if !TCL_THREADS
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
*/
|
||||
|
||||
#include "tclInt.h"
|
||||
#if defined(TCL_THREADS) && defined(USE_THREAD_ALLOC)
|
||||
#if TCL_THREADS && defined(USE_THREAD_ALLOC)
|
||||
|
||||
/*
|
||||
* If range checking is enabled, an additional byte will be allocated to store
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
#include "tclInt.h"
|
||||
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
#include <signal.h>
|
||||
|
||||
/*
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
#endif
|
||||
#include "tclInt.h"
|
||||
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
/*
|
||||
* Each thread has an single instance of the following structure. There is one
|
||||
* instance of this structure per thread even if that thread contains multiple
|
||||
|
||||
+2
-2
@@ -1034,8 +1034,8 @@ Tcl_UtfToTitle(
|
||||
lowChar = (((lowChar & 0x3ff) << 10) | (ch & 0x3ff)) + 0x10000;
|
||||
}
|
||||
#endif
|
||||
/* Special exception for Gregorian characters, which don't have titlecase */
|
||||
if ((lowChar < 0x1C90) || (lowChar >= 0x1CC0)) {
|
||||
/* Special exception for Georgian Asomtavruli chars, no titlecase. */
|
||||
if ((unsigned)(lowChar - 0x1C90) >= 0x30) {
|
||||
lowChar = Tcl_UniCharToLower(lowChar);
|
||||
}
|
||||
|
||||
|
||||
+174
-143
@@ -60,14 +60,12 @@ VarHashCreateVar(
|
||||
Tcl_Obj *key,
|
||||
int *newPtr)
|
||||
{
|
||||
Tcl_HashEntry *hPtr = Tcl_CreateHashEntry(&tablePtr->table,
|
||||
key, newPtr);
|
||||
Tcl_HashEntry *hPtr = Tcl_CreateHashEntry(&tablePtr->table, key, newPtr);
|
||||
|
||||
if (hPtr) {
|
||||
return VarHashGetValue(hPtr);
|
||||
} else {
|
||||
if (!hPtr) {
|
||||
return NULL;
|
||||
}
|
||||
return VarHashGetValue(hPtr);
|
||||
}
|
||||
|
||||
#define VarHashFindVar(tablePtr, key) \
|
||||
@@ -92,11 +90,10 @@ VarHashFirstVar(
|
||||
{
|
||||
Tcl_HashEntry *hPtr = VarHashFirstEntry(tablePtr, searchPtr);
|
||||
|
||||
if (hPtr) {
|
||||
return VarHashGetValue(hPtr);
|
||||
} else {
|
||||
if (!hPtr) {
|
||||
return NULL;
|
||||
}
|
||||
return VarHashGetValue(hPtr);
|
||||
}
|
||||
|
||||
static inline Var *
|
||||
@@ -105,11 +102,10 @@ VarHashNextVar(
|
||||
{
|
||||
Tcl_HashEntry *hPtr = VarHashNextEntry(searchPtr);
|
||||
|
||||
if (hPtr) {
|
||||
return VarHashGetValue(hPtr);
|
||||
} else {
|
||||
if (!hPtr) {
|
||||
return NULL;
|
||||
}
|
||||
return VarHashGetValue(hPtr);
|
||||
}
|
||||
|
||||
#define VarHashGetKey(varPtr) \
|
||||
@@ -174,10 +170,14 @@ typedef struct ArraySearch {
|
||||
|
||||
static void AppendLocals(Tcl_Interp *interp, Tcl_Obj *listPtr,
|
||||
Tcl_Obj *patternPtr, int includeLinks);
|
||||
static void ArrayPopulateSearch(Tcl_Interp *interp, Tcl_Obj *arrayNameObj, Var *varPtr, ArraySearch *searchPtr);
|
||||
static void ArrayDoneSearch (Interp *iPtr, Var *varPtr, ArraySearch *searchPtr);
|
||||
static void ArrayPopulateSearch(Tcl_Interp *interp,
|
||||
Tcl_Obj *arrayNameObj, Var *varPtr,
|
||||
ArraySearch *searchPtr);
|
||||
static void ArrayDoneSearch(Interp *iPtr, Var *varPtr,
|
||||
ArraySearch *searchPtr);
|
||||
static Tcl_NRPostProc ArrayForLoopCallback;
|
||||
static int ArrayForNRCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv);
|
||||
static int ArrayForNRCmd(ClientData dummy, Tcl_Interp *interp,
|
||||
int objc, Tcl_Obj *const *objv);
|
||||
static void DeleteSearches(Interp *iPtr, Var *arrayVarPtr);
|
||||
static void DeleteArray(Interp *iPtr, Tcl_Obj *arrayNamePtr,
|
||||
Var *varPtr, int flags, int index);
|
||||
@@ -322,7 +322,8 @@ CleanupVar(
|
||||
{
|
||||
if (TclIsVarUndefined(varPtr) && TclIsVarInHash(varPtr)
|
||||
&& !TclIsVarTraced(varPtr)
|
||||
&& (VarHashRefCount(varPtr) == (unsigned)!TclIsVarDeadHash(varPtr))) {
|
||||
&& (VarHashRefCount(varPtr) == (unsigned)
|
||||
!TclIsVarDeadHash(varPtr))) {
|
||||
if (VarHashRefCount(varPtr) == 0) {
|
||||
ckfree(varPtr);
|
||||
} else {
|
||||
@@ -331,7 +332,8 @@ CleanupVar(
|
||||
}
|
||||
if (arrayPtr != NULL && TclIsVarUndefined(arrayPtr) &&
|
||||
TclIsVarInHash(arrayPtr) && !TclIsVarTraced(arrayPtr) &&
|
||||
(VarHashRefCount(arrayPtr) == (unsigned)!TclIsVarDeadHash(arrayPtr))) {
|
||||
(VarHashRefCount(arrayPtr) == (unsigned)
|
||||
!TclIsVarDeadHash(arrayPtr))) {
|
||||
if (VarHashRefCount(arrayPtr) == 0) {
|
||||
ckfree(arrayPtr);
|
||||
} else {
|
||||
@@ -607,7 +609,6 @@ TclObjLookupVarEx(
|
||||
}
|
||||
|
||||
if (!parsed) {
|
||||
|
||||
/*
|
||||
* part1Ptr is possibly an unparsed array element.
|
||||
*/
|
||||
@@ -615,12 +616,11 @@ TclObjLookupVarEx(
|
||||
int len;
|
||||
const char *part1 = TclGetStringFromObj(part1Ptr, &len);
|
||||
|
||||
if (len > 1 && (part1[len - 1] == ')')) {
|
||||
if ((len > 1) && (part1[len - 1] == ')')) {
|
||||
const char *part2 = strchr(part1, '(');
|
||||
|
||||
const char *part2 = strchr(part1, '(');
|
||||
|
||||
if (part2) {
|
||||
Tcl_Obj *arrayPtr;
|
||||
if (part2) {
|
||||
Tcl_Obj *arrayPtr;
|
||||
|
||||
if (part2Ptr != NULL) {
|
||||
if (flags & TCL_LEAVE_ERR_MSG) {
|
||||
@@ -632,19 +632,20 @@ TclObjLookupVarEx(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
arrayPtr = Tcl_NewStringObj(part1, (part2 - part1));
|
||||
part2Ptr = Tcl_NewStringObj(part2 + 1, len - (part2 - part1) - 2);
|
||||
arrayPtr = Tcl_NewStringObj(part1, (part2 - part1));
|
||||
part2Ptr = Tcl_NewStringObj(part2 + 1,
|
||||
len - (part2 - part1) - 2);
|
||||
|
||||
TclFreeIntRep(part1Ptr);
|
||||
TclFreeIntRep(part1Ptr);
|
||||
|
||||
Tcl_IncrRefCount(arrayPtr);
|
||||
part1Ptr->internalRep.twoPtrValue.ptr1 = arrayPtr;
|
||||
Tcl_IncrRefCount(part2Ptr);
|
||||
part1Ptr->internalRep.twoPtrValue.ptr2 = part2Ptr;
|
||||
part1Ptr->typePtr = &tclParsedVarNameType;
|
||||
Tcl_IncrRefCount(arrayPtr);
|
||||
part1Ptr->internalRep.twoPtrValue.ptr1 = arrayPtr;
|
||||
Tcl_IncrRefCount(part2Ptr);
|
||||
part1Ptr->internalRep.twoPtrValue.ptr2 = part2Ptr;
|
||||
part1Ptr->typePtr = &tclParsedVarNameType;
|
||||
|
||||
part1Ptr = arrayPtr;
|
||||
}
|
||||
part1Ptr = arrayPtr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -674,6 +675,7 @@ TclObjLookupVarEx(
|
||||
/*
|
||||
* An indexed local variable.
|
||||
*/
|
||||
|
||||
Tcl_Obj *cachedNamePtr = localName(varFramePtr, index);
|
||||
|
||||
part1Ptr->typePtr = &localVarNameType;
|
||||
@@ -682,7 +684,7 @@ TclObjLookupVarEx(
|
||||
Tcl_IncrRefCount(cachedNamePtr);
|
||||
if (cachedNamePtr->typePtr != &localVarNameType
|
||||
|| cachedNamePtr->internalRep.twoPtrValue.ptr1 != NULL) {
|
||||
TclFreeIntRep(cachedNamePtr);
|
||||
TclFreeIntRep(cachedNamePtr);
|
||||
}
|
||||
} else {
|
||||
part1Ptr->internalRep.twoPtrValue.ptr1 = NULL;
|
||||
@@ -877,38 +879,41 @@ TclLookupSimpleVar(
|
||||
if (varPtr == NULL) {
|
||||
Tcl_Obj *tailPtr;
|
||||
|
||||
if (create) { /* Var wasn't found so create it. */
|
||||
TclGetNamespaceForQualName(interp, varName, cxtNsPtr,
|
||||
flags, &varNsPtr, &dummy1Ptr, &dummy2Ptr, &tail);
|
||||
if (varNsPtr == NULL) {
|
||||
*errMsgPtr = badNamespace;
|
||||
return NULL;
|
||||
} else if (tail == NULL) {
|
||||
*errMsgPtr = missingName;
|
||||
return NULL;
|
||||
}
|
||||
if (tail != varName) {
|
||||
tailPtr = Tcl_NewStringObj(tail, -1);
|
||||
} else {
|
||||
tailPtr = varNamePtr;
|
||||
}
|
||||
varPtr = VarHashCreateVar(&varNsPtr->varTable, tailPtr,
|
||||
&isNew);
|
||||
if (lookGlobal) {
|
||||
/*
|
||||
* The variable was created starting from the global
|
||||
* namespace: a global reference is returned even if it
|
||||
* wasn't explicitly requested.
|
||||
*/
|
||||
|
||||
*indexPtr = -1;
|
||||
} else {
|
||||
*indexPtr = -2;
|
||||
}
|
||||
} else { /* Var wasn't found and not to create it. */
|
||||
if (!create) { /* Var wasn't found and not to create it. */
|
||||
*errMsgPtr = noSuchVar;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Var wasn't found so create it.
|
||||
*/
|
||||
|
||||
TclGetNamespaceForQualName(interp, varName, cxtNsPtr, flags,
|
||||
&varNsPtr, &dummy1Ptr, &dummy2Ptr, &tail);
|
||||
if (varNsPtr == NULL) {
|
||||
*errMsgPtr = badNamespace;
|
||||
return NULL;
|
||||
} else if (tail == NULL) {
|
||||
*errMsgPtr = missingName;
|
||||
return NULL;
|
||||
}
|
||||
if (tail != varName) {
|
||||
tailPtr = Tcl_NewStringObj(tail, -1);
|
||||
} else {
|
||||
tailPtr = varNamePtr;
|
||||
}
|
||||
varPtr = VarHashCreateVar(&varNsPtr->varTable, tailPtr, &isNew);
|
||||
if (lookGlobal) {
|
||||
/*
|
||||
* The variable was created starting from the global
|
||||
* namespace: a global reference is returned even if it wasn't
|
||||
* explicitly requested.
|
||||
*/
|
||||
|
||||
*indexPtr = -1;
|
||||
} else {
|
||||
*indexPtr = -2;
|
||||
}
|
||||
}
|
||||
} else { /* Local var: look in frame varFramePtr. */
|
||||
int localLen, localCt = varFramePtr->numCompiledLocals;
|
||||
@@ -2167,7 +2172,6 @@ TclPtrIncrObjVarIdx(
|
||||
} else {
|
||||
/* Unshared - can Incr in place */
|
||||
if (TCL_OK == TclIncrObj(interp, varValuePtr, incrPtr)) {
|
||||
|
||||
/*
|
||||
* This seems dumb to write the incremeted value into the var
|
||||
* after we just adjusted the value in place, but the spec for
|
||||
@@ -2909,27 +2913,24 @@ Tcl_LappendObjCmd(
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* ArrayForObjCmd
|
||||
* ArrayForNRCmd
|
||||
* ArrayForLoopCallback
|
||||
* ArrayObjNext
|
||||
* ArrayForObjCmd, ArrayForNRCmd, ArrayForLoopCallback, ArrayObjNext --
|
||||
*
|
||||
* These functions implement the "array for" Tcl command.
|
||||
* array for {k v} a {}
|
||||
* The array for command iterates over the array, setting the
|
||||
* the specified loop variables, and executing the body each iteration.
|
||||
* These functions implement the "array for" Tcl command.
|
||||
* array for {k v} a {}
|
||||
* The array for command iterates over the array, setting the the
|
||||
* specified loop variables, and executing the body each iteration.
|
||||
*
|
||||
* ArrayForObjCmd() is the standard wrapper around ArrayForNRCmd().
|
||||
* ArrayForObjCmd() is the standard wrapper around ArrayForNRCmd().
|
||||
*
|
||||
* ArrayForNRCmd() sets up the ArraySearch structure, sets arrayNamePtr
|
||||
* inside the structure and calls VarHashFirstEntry to start the hash
|
||||
* iteration.
|
||||
* ArrayForNRCmd() sets up the ArraySearch structure, sets arrayNamePtr
|
||||
* inside the structure and calls VarHashFirstEntry to start the hash
|
||||
* iteration.
|
||||
*
|
||||
* ArrayForNRCmd() does not execute the body or set the loop variables,
|
||||
* it only initializes the iterator.
|
||||
* ArrayForNRCmd() does not execute the body or set the loop variables,
|
||||
* it only initializes the iterator.
|
||||
*
|
||||
* ArrayForLoopCallback() iterates over the entire array, executing
|
||||
* the body each time.
|
||||
* ArrayForLoopCallback() iterates over the entire array, executing the
|
||||
* body each time.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
@@ -2937,39 +2938,39 @@ Tcl_LappendObjCmd(
|
||||
static int
|
||||
ArrayObjNext(
|
||||
Tcl_Interp *interp,
|
||||
Tcl_Obj *arrayNameObj, /* array */
|
||||
Var *varPtr, /* array */
|
||||
Tcl_Obj *arrayNameObj, /* array */
|
||||
Var *varPtr, /* array */
|
||||
ArraySearch *searchPtr,
|
||||
Tcl_Obj **keyPtrPtr, /* Pointer to a variable to have the key
|
||||
* written into, or NULL. */
|
||||
Tcl_Obj **valuePtrPtr /* Pointer to a variable to have the
|
||||
Tcl_Obj **valuePtrPtr) /* Pointer to a variable to have the
|
||||
* value written into, or NULL.*/
|
||||
)
|
||||
{
|
||||
Tcl_Obj *keyObj;
|
||||
Tcl_Obj *valueObj = NULL;
|
||||
int gotValue;
|
||||
int donerc;
|
||||
int gotValue;
|
||||
int donerc;
|
||||
|
||||
donerc = TCL_BREAK;
|
||||
|
||||
if ((varPtr->flags & VAR_SEARCH_ACTIVE) != VAR_SEARCH_ACTIVE) {
|
||||
donerc = TCL_ERROR;
|
||||
return donerc;
|
||||
donerc = TCL_ERROR;
|
||||
return donerc;
|
||||
}
|
||||
|
||||
gotValue = 0;
|
||||
while (1) {
|
||||
Tcl_HashEntry *hPtr = searchPtr->nextEntry;
|
||||
if (hPtr != NULL) {
|
||||
searchPtr->nextEntry = NULL;
|
||||
} else {
|
||||
hPtr = Tcl_NextHashEntry(&searchPtr->search);
|
||||
if (hPtr == NULL) {
|
||||
gotValue = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (hPtr != NULL) {
|
||||
searchPtr->nextEntry = NULL;
|
||||
} else {
|
||||
hPtr = Tcl_NextHashEntry(&searchPtr->search);
|
||||
if (hPtr == NULL) {
|
||||
gotValue = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
varPtr = VarHashGetValue(hPtr);
|
||||
if (!TclIsVarUndefined(varPtr)) {
|
||||
gotValue = 1;
|
||||
@@ -2977,7 +2978,7 @@ ArrayObjNext(
|
||||
}
|
||||
}
|
||||
|
||||
if (! gotValue) {
|
||||
if (!gotValue) {
|
||||
return donerc;
|
||||
}
|
||||
|
||||
@@ -2985,8 +2986,8 @@ ArrayObjNext(
|
||||
|
||||
keyObj = VarHashGetKey(varPtr);
|
||||
*keyPtrPtr = keyObj;
|
||||
valueObj = Tcl_ObjGetVar2(interp, arrayNameObj,
|
||||
keyObj, TCL_LEAVE_ERR_MSG);
|
||||
valueObj = Tcl_ObjGetVar2(interp, arrayNameObj, keyObj,
|
||||
TCL_LEAVE_ERR_MSG);
|
||||
*valuePtrPtr = valueObj;
|
||||
|
||||
return donerc;
|
||||
@@ -3019,8 +3020,7 @@ ArrayForNRCmd(
|
||||
*/
|
||||
|
||||
if (objc != 4) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv,
|
||||
"{key value} arrayName script");
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "{key value} arrayName script");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
@@ -3054,7 +3054,7 @@ ArrayForNRCmd(
|
||||
*/
|
||||
|
||||
searchPtr = ckalloc(sizeof(ArraySearch));
|
||||
ArrayPopulateSearch (interp, arrayNameObj, varPtr, searchPtr);
|
||||
ArrayPopulateSearch(interp, arrayNameObj, varPtr, searchPtr);
|
||||
|
||||
/*
|
||||
* Make sure that these objects (which we need throughout the body of the
|
||||
@@ -3120,35 +3120,37 @@ ArrayForLoopCallback(
|
||||
varPtr = TclObjLookupVarEx(interp, arrayNameObj, NULL, /*flags*/ 0,
|
||||
/*msg*/ 0, /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr);
|
||||
if (varPtr == NULL) {
|
||||
done = TCL_ERROR;
|
||||
done = TCL_ERROR;
|
||||
} else {
|
||||
done = ArrayObjNext (interp, arrayNameObj, varPtr,
|
||||
searchPtr, &keyObj, &valueObj);
|
||||
done = ArrayObjNext(interp, arrayNameObj, varPtr, searchPtr, &keyObj,
|
||||
&valueObj);
|
||||
}
|
||||
|
||||
result = TCL_OK;
|
||||
if (done != TCL_CONTINUE) {
|
||||
Tcl_ResetResult(interp);
|
||||
if (done == TCL_ERROR) {
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
||||
"array changed during iteration", -1));
|
||||
Tcl_SetErrorCode(interp, "TCL", "READ", "array", "for", NULL);
|
||||
varPtr->flags |= TCL_LEAVE_ERR_MSG;
|
||||
result = done;
|
||||
}
|
||||
if (done == TCL_ERROR) {
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
||||
"array changed during iteration", -1));
|
||||
Tcl_SetErrorCode(interp, "TCL", "READ", "array", "for", NULL);
|
||||
varPtr->flags |= TCL_LEAVE_ERR_MSG;
|
||||
result = done;
|
||||
}
|
||||
goto arrayfordone;
|
||||
}
|
||||
|
||||
Tcl_ListObjGetElements(NULL, varListObj, &varc, &varv);
|
||||
if (Tcl_ObjSetVar2(interp, varv[0], NULL, keyObj, TCL_LEAVE_ERR_MSG) == NULL) {
|
||||
result = TCL_ERROR;
|
||||
goto arrayfordone;
|
||||
if (Tcl_ObjSetVar2(interp, varv[0], NULL, keyObj,
|
||||
TCL_LEAVE_ERR_MSG) == NULL) {
|
||||
result = TCL_ERROR;
|
||||
goto arrayfordone;
|
||||
}
|
||||
if (valueObj != NULL) {
|
||||
if (Tcl_ObjSetVar2(interp, varv[1], NULL, valueObj, TCL_LEAVE_ERR_MSG) == NULL) {
|
||||
result = TCL_ERROR;
|
||||
goto arrayfordone;
|
||||
}
|
||||
if (Tcl_ObjSetVar2(interp, varv[1], NULL, valueObj,
|
||||
TCL_LEAVE_ERR_MSG) == NULL) {
|
||||
result = TCL_ERROR;
|
||||
goto arrayfordone;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3164,13 +3166,15 @@ ArrayForLoopCallback(
|
||||
*/
|
||||
|
||||
arrayfordone:
|
||||
/* if the search was terminated by an array change, the
|
||||
* VAR_SEARCH_ACTIVE flag will no longer be set
|
||||
*/
|
||||
if (done != TCL_ERROR) {
|
||||
ArrayDoneSearch (iPtr, varPtr, searchPtr);
|
||||
/*
|
||||
* If the search was terminated by an array change, the
|
||||
* VAR_SEARCH_ACTIVE flag will no longer be set.
|
||||
*/
|
||||
|
||||
ArrayDoneSearch(iPtr, varPtr, searchPtr);
|
||||
Tcl_DecrRefCount(searchPtr->name);
|
||||
ckfree(searchPtr);
|
||||
ckfree(searchPtr);
|
||||
}
|
||||
|
||||
TclDecrRefCount(varListObj);
|
||||
@@ -3181,14 +3185,15 @@ ArrayForLoopCallback(
|
||||
/*
|
||||
* ArrayPopulateSearch
|
||||
*/
|
||||
|
||||
static void
|
||||
ArrayPopulateSearch(
|
||||
Tcl_Interp *interp,
|
||||
Tcl_Obj *arrayNameObj,
|
||||
Var *varPtr,
|
||||
Tcl_Interp *interp,
|
||||
Tcl_Obj *arrayNameObj,
|
||||
Var *varPtr,
|
||||
ArraySearch *searchPtr)
|
||||
{
|
||||
Interp *iPtr = (Interp *)interp;
|
||||
Interp *iPtr = (Interp *) interp;
|
||||
Tcl_HashEntry *hPtr;
|
||||
int isNew;
|
||||
|
||||
@@ -3206,7 +3211,7 @@ ArrayPopulateSearch(
|
||||
&searchPtr->search);
|
||||
Tcl_SetHashValue(hPtr, searchPtr);
|
||||
searchPtr->name = Tcl_ObjPrintf("s-%d-%s", searchPtr->id,
|
||||
TclGetString(arrayNameObj));
|
||||
TclGetString(arrayNameObj));
|
||||
Tcl_IncrRefCount(searchPtr->name);
|
||||
}
|
||||
/*
|
||||
@@ -3258,7 +3263,7 @@ ArrayStartSearchCmd(
|
||||
*/
|
||||
|
||||
searchPtr = ckalloc(sizeof(ArraySearch));
|
||||
ArrayPopulateSearch (interp, objv[1], varPtr, searchPtr);
|
||||
ArrayPopulateSearch(interp, objv[1], varPtr, searchPtr);
|
||||
Tcl_SetObjResult(interp, searchPtr->name);
|
||||
return TCL_OK;
|
||||
}
|
||||
@@ -3268,12 +3273,12 @@ ArrayStartSearchCmd(
|
||||
*
|
||||
* ArrayDoneSearch --
|
||||
*
|
||||
* Removes the search from the hash of active searches.
|
||||
* Removes the search from the hash of active searches.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
static void
|
||||
ArrayDoneSearch (
|
||||
ArrayDoneSearch(
|
||||
Interp *iPtr,
|
||||
Var *varPtr,
|
||||
ArraySearch *searchPtr)
|
||||
@@ -3288,7 +3293,7 @@ ArrayDoneSearch (
|
||||
|
||||
hPtr = Tcl_FindHashEntry(&iPtr->varSearches, varPtr);
|
||||
if (hPtr == NULL) {
|
||||
return;
|
||||
return;
|
||||
}
|
||||
if (searchPtr == Tcl_GetHashValue(hPtr)) {
|
||||
if (searchPtr->nextPtr) {
|
||||
@@ -3522,7 +3527,7 @@ ArrayDoneSearchCmd(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
ArrayDoneSearch (iPtr, varPtr, searchPtr);
|
||||
ArrayDoneSearch(iPtr, varPtr, searchPtr);
|
||||
Tcl_DecrRefCount(searchPtr->name);
|
||||
ckfree(searchPtr);
|
||||
return TCL_OK;
|
||||
@@ -4034,7 +4039,8 @@ ArraySetCmd(
|
||||
|
||||
if ((elemVarPtr == NULL) ||
|
||||
(TclPtrSetVarIdx(interp, elemVarPtr, varPtr, arrayNameObj,
|
||||
elemPtrs[i],elemPtrs[i+1],TCL_LEAVE_ERR_MSG,-1) == NULL)){
|
||||
elemPtrs[i], elemPtrs[i+1], TCL_LEAVE_ERR_MSG,
|
||||
-1) == NULL)) {
|
||||
result = TCL_ERROR;
|
||||
break;
|
||||
}
|
||||
@@ -6024,7 +6030,7 @@ TclInfoVarsCmd(
|
||||
*/
|
||||
|
||||
if ((nsPtr != globalNsPtr) && !specificNsInPattern) {
|
||||
varPtr = VarHashFirstVar(&globalNsPtr->varTable,&search);
|
||||
varPtr = VarHashFirstVar(&globalNsPtr->varTable, &search);
|
||||
while (varPtr) {
|
||||
if (!TclIsVarUndefined(varPtr)
|
||||
|| TclIsVarNamespaceVar(varPtr)) {
|
||||
@@ -6317,25 +6323,50 @@ AppendLocals(
|
||||
}
|
||||
|
||||
if (iPtr->varFramePtr->isProcCallFrame & FRAME_IS_METHOD) {
|
||||
CallContext *contextPtr = iPtr->varFramePtr->clientData;
|
||||
Method *mPtr = contextPtr->callPtr->chain[contextPtr->index].mPtr;
|
||||
Method *mPtr = (Method *)
|
||||
Tcl_ObjectContextMethod(iPtr->varFramePtr->clientData);
|
||||
PrivateVariableMapping *privatePtr;
|
||||
|
||||
if (mPtr->declaringObjectPtr) {
|
||||
FOREACH(objNamePtr, mPtr->declaringObjectPtr->variables) {
|
||||
Object *oPtr = mPtr->declaringObjectPtr;
|
||||
|
||||
FOREACH(objNamePtr, oPtr->variables) {
|
||||
Tcl_CreateHashEntry(&addedTable, objNamePtr, &added);
|
||||
if (added && (!pattern ||
|
||||
Tcl_StringMatch(TclGetString(objNamePtr), pattern))) {
|
||||
Tcl_ListObjAppendElement(interp, listPtr, objNamePtr);
|
||||
}
|
||||
}
|
||||
FOREACH_STRUCT(privatePtr, oPtr->privateVariables) {
|
||||
Tcl_CreateHashEntry(&addedTable, privatePtr->variableObj,
|
||||
&added);
|
||||
if (added && (!pattern ||
|
||||
Tcl_StringMatch(TclGetString(privatePtr->variableObj),
|
||||
pattern))) {
|
||||
Tcl_ListObjAppendElement(interp, listPtr,
|
||||
privatePtr->variableObj);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
FOREACH(objNamePtr, mPtr->declaringClassPtr->variables) {
|
||||
Class *clsPtr = mPtr->declaringClassPtr;
|
||||
|
||||
FOREACH(objNamePtr, clsPtr->variables) {
|
||||
Tcl_CreateHashEntry(&addedTable, objNamePtr, &added);
|
||||
if (added && (!pattern ||
|
||||
Tcl_StringMatch(TclGetString(objNamePtr), pattern))) {
|
||||
Tcl_ListObjAppendElement(interp, listPtr, objNamePtr);
|
||||
}
|
||||
}
|
||||
FOREACH_STRUCT(privatePtr, clsPtr->privateVariables) {
|
||||
Tcl_CreateHashEntry(&addedTable, privatePtr->variableObj,
|
||||
&added);
|
||||
if (added && (!pattern ||
|
||||
Tcl_StringMatch(TclGetString(privatePtr->variableObj),
|
||||
pattern))) {
|
||||
Tcl_ListObjAppendElement(interp, listPtr,
|
||||
privatePtr->variableObj);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Tcl_DeleteHashTable(&addedTable);
|
||||
@@ -6408,9 +6439,9 @@ CompareVarKeys(
|
||||
/*
|
||||
* If the object pointers are the same then they match.
|
||||
* OPT: this comparison was moved to the caller
|
||||
|
||||
if (objPtr1 == objPtr2) return 1;
|
||||
*/
|
||||
*
|
||||
* if (objPtr1 == objPtr2) return 1;
|
||||
*/
|
||||
|
||||
/*
|
||||
* Don't use Tcl_GetStringFromObj as it would prevent l1 and l2 being in a
|
||||
|
||||
+1
-1
@@ -132,7 +132,7 @@ ${objdir}/Makefile: ${UNIX_DIR}/Makefile.in ${UNIX_DIR}/configure \
|
||||
mkdir -p "${OBJ_DIR}" && cd "${OBJ_DIR}" && \
|
||||
if [ ${UNIX_DIR}/configure -nt config.status ]; then ${UNIX_DIR}/configure -C \
|
||||
--prefix="${PREFIX}" --bindir="${BINDIR}" --libdir="${LIBDIR}" \
|
||||
--mandir="${MANDIR}" --enable-threads --enable-framework --enable-dtrace \
|
||||
--mandir="${MANDIR}" --enable-framework --enable-dtrace \
|
||||
${CONFIGURE_ARGS} ${EXTRA_CONFIGURE_ARGS}; else ./config.status; fi
|
||||
|
||||
build-${PROJECT}: ${objdir}/Makefile
|
||||
|
||||
@@ -30,7 +30,7 @@ MANDIR = $(PREFIX)/man
|
||||
PER_ARCH_CFLAGS_ppc = -mcpu=G3 -mtune=G4 $(PER_ARCH_CFLAGS_ppc)
|
||||
PER_ARCH_CFLAGS_ppc64 = -mcpu=G5 -mpowerpc64 $(PER_ARCH_CFLAGS_ppc64)
|
||||
PREFIX = /usr/local
|
||||
TCL_CONFIGURE_ARGS = --enable-threads --enable-dtrace
|
||||
TCL_CONFIGURE_ARGS = --enable-dtrace
|
||||
TCL_LIBRARY = $(LIBDIR)/tcl$(VERSION)
|
||||
TCL_PACKAGE_PATH = "$(LIBDIR)"
|
||||
TCL_DEFS = HAVE_TCL_CONFIG_H
|
||||
|
||||
+3
-4
@@ -20,7 +20,6 @@ if {[lsearch [namespace children] ::tcltest] == -1} {
|
||||
catch [list package require -exact Tcltest [info patchlevel]]
|
||||
|
||||
testConstraint testasync [llength [info commands testasync]]
|
||||
testConstraint threaded [::tcl::pkgconfig get threaded]
|
||||
|
||||
proc async1 {result code} {
|
||||
global aresult acode
|
||||
@@ -149,7 +148,7 @@ test async-3.1 {deleting handlers} testasync {
|
||||
} {3 del2 {0 0 0 del1 del2}}
|
||||
|
||||
test async-4.1 {async interrupting bytecode sequence} -constraints {
|
||||
testasync threaded
|
||||
testasync
|
||||
} -setup {
|
||||
set hm [testasync create async3]
|
||||
proc nothing {} {
|
||||
@@ -171,7 +170,7 @@ test async-4.1 {async interrupting bytecode sequence} -constraints {
|
||||
testasync delete $hm
|
||||
}
|
||||
test async-4.2 {async interrupting straight bytecode sequence} -constraints {
|
||||
testasync threaded
|
||||
testasync
|
||||
} -setup {
|
||||
set hm [testasync create async3]
|
||||
} -body {
|
||||
@@ -188,7 +187,7 @@ test async-4.2 {async interrupting straight bytecode sequence} -constraints {
|
||||
testasync delete $hm
|
||||
}
|
||||
test async-4.3 {async interrupting loop-less bytecode sequence} -constraints {
|
||||
testasync threaded
|
||||
testasync
|
||||
} -setup {
|
||||
set hm [testasync create async3]
|
||||
} -body {
|
||||
|
||||
@@ -264,6 +264,12 @@ removeDirectory dir.dir
|
||||
test filesystem-1.30 {normalisation of nonexistent user} -body {
|
||||
file normalize ~noonewiththisname
|
||||
} -returnCodes error -result {user "noonewiththisname" doesn't exist}
|
||||
test filesystem-1.30.1 {normalisation of existing user} -body {
|
||||
catch {file normalize ~$::tcl_platform(user)}
|
||||
} -result {0}
|
||||
test filesystem-1.30.2 {normalisation of nonexistent user specified as user@domain} -body {
|
||||
file normalize ~nonexistentuser@nonexistentdomain
|
||||
} -returnCodes error -result {user "nonexistentuser@nonexistentdomain" doesn't exist}
|
||||
test filesystem-1.31 {link normalisation: link near filesystem root} {testsetplatform} {
|
||||
testsetplatform unix
|
||||
file normalize /foo/../bar
|
||||
|
||||
+744
-1
@@ -2202,7 +2202,7 @@ test oo-16.2 {OO: object introspection} -body {
|
||||
} -returnCodes 1 -result {NOTANOBJECT does not refer to an object}
|
||||
test oo-16.3 {OO: object introspection} -body {
|
||||
info object gorp oo::object
|
||||
} -returnCodes 1 -result {unknown or ambiguous subcommand "gorp": must be call, class, definition, filters, forward, isa, methods, methodtype, mixins, namespace, variables, or vars}
|
||||
} -returnCodes 1 -result {unknown or ambiguous subcommand "gorp": must be call, class, creationid, definition, filters, forward, isa, methods, methodtype, mixins, namespace, variables, or vars}
|
||||
test oo-16.4 {OO: object introspection} -setup {
|
||||
oo::class create meta { superclass oo::class }
|
||||
[meta create instance1] create instance2
|
||||
@@ -2332,6 +2332,73 @@ test oo-16.14 {OO: object introspection: TIP #436} -setup {
|
||||
} -cleanup {
|
||||
meta destroy
|
||||
} -result {class {0 0} meta {0 0 0} type {0 0 0 0 0 0} mix {0 0 0 0 0 0}}
|
||||
test oo-16.15 {OO: object introspection: creationid #500} -setup {
|
||||
oo::class create cls
|
||||
} -body {
|
||||
info object creationid [cls new]
|
||||
} -cleanup {
|
||||
cls destroy
|
||||
} -result {^\d+$} -match regexp
|
||||
test oo-16.16 {OO: object introspection: creationid #500} -setup {
|
||||
oo::class create cls
|
||||
} -body {
|
||||
set obj [cls new]
|
||||
set id [info object creationid $obj]
|
||||
rename $obj gorp
|
||||
set id2 [info object creationid gorp]
|
||||
list $id $id2
|
||||
} -cleanup {
|
||||
cls destroy
|
||||
} -result {^(\d+) \1$} -match regexp
|
||||
test oo-16.17 {OO: object introspection: creationid #500} -body {
|
||||
info object creationid nosuchobject
|
||||
} -returnCodes error -result {nosuchobject does not refer to an object}
|
||||
test oo-16.18 {OO: object introspection: creationid #500} -body {
|
||||
info object creationid
|
||||
} -returnCodes error -result {wrong # args: should be "info object creationid objName"}
|
||||
test oo-16.18 {OO: object introspection: creationid #500} -body {
|
||||
info object creationid oo::object gorp
|
||||
} -returnCodes error -result {wrong # args: should be "info object creationid objName"}
|
||||
test oo-16.19 {OO: object introspection: creationid #500} -setup {
|
||||
oo::class create cls
|
||||
} -body {
|
||||
set id1 [info object creationid [set o1 [cls new]]]
|
||||
set id2 [info object creationid [set o2 [cls new]]]
|
||||
if {$id1 == $id2} {
|
||||
format "objects %s and %s have same creation id: %d" $o1 $o2 $id1
|
||||
} else {
|
||||
string cat not-equal
|
||||
}
|
||||
} -cleanup {
|
||||
cls destroy
|
||||
} -result not-equal
|
||||
test oo-16.20 {OO: object introspection: creationid #500} -setup {
|
||||
oo::class create cls
|
||||
} -body {
|
||||
set id1 [info object creationid [set o1 [cls new]]]
|
||||
$o1 destroy
|
||||
set id2 [info object creationid [set o2 [cls new]]]
|
||||
if {$id1 == $id2} {
|
||||
format "objects %s and %s have same creation id: %d" $o1 $o2 $id1
|
||||
} else {
|
||||
string cat not-equal
|
||||
}
|
||||
} -cleanup {
|
||||
cls destroy
|
||||
} -result not-equal
|
||||
test oo-16.21 {OO: object introspection: creationid #500} -setup {
|
||||
oo::class create cls
|
||||
} -body {
|
||||
set id1 [info object creationid [set o1 [cls new]]]
|
||||
set id2 [info object creationid [set o2 [oo::copy $o1]]]
|
||||
if {$id1 == $id2} {
|
||||
format "objects %s and %s have same creation id: %d" $o1 $o2 $id1
|
||||
} else {
|
||||
string cat not-equal
|
||||
}
|
||||
} -cleanup {
|
||||
cls destroy
|
||||
} -result not-equal
|
||||
|
||||
test oo-17.1 {OO: class introspection} -body {
|
||||
info class
|
||||
@@ -4102,6 +4169,682 @@ test oo-36.10 {TIP #470: introspection within oo::define} -setup {
|
||||
Cls destroy
|
||||
catch {rename oo::objdefine::testself {}}
|
||||
} -result {{} {1 {this command may only be called from within the context of an ::oo::define or ::oo::objdefine command} 0 ::obj}}
|
||||
|
||||
test oo-37.1 {TIP 500: private command propagates errors} -setup {
|
||||
oo::class create cls
|
||||
} -body {
|
||||
oo::define cls {
|
||||
private ::error "this is an error"
|
||||
}
|
||||
} -cleanup {
|
||||
cls destroy
|
||||
} -returnCodes error -result {this is an error}
|
||||
test oo-37.2 {TIP 500: private command propagates errors} -setup {
|
||||
oo::class create cls
|
||||
} -body {
|
||||
oo::define cls {
|
||||
private {
|
||||
::error "this is an error"
|
||||
}
|
||||
}
|
||||
} -cleanup {
|
||||
cls destroy
|
||||
} -returnCodes error -result {this is an error}
|
||||
test oo-37.3 {TIP 500: private command propagates errors} -setup {
|
||||
oo::object create obj
|
||||
} -body {
|
||||
oo::objdefine obj {
|
||||
private ::error "this is an error"
|
||||
}
|
||||
} -cleanup {
|
||||
obj destroy
|
||||
} -returnCodes error -result {this is an error}
|
||||
test oo-37.4 {TIP 500: private command propagates errors} -setup {
|
||||
oo::object create obj
|
||||
} -body {
|
||||
oo::objdefine obj {
|
||||
private {
|
||||
::error "this is an error"
|
||||
}
|
||||
}
|
||||
} -cleanup {
|
||||
obj destroy
|
||||
} -returnCodes error -result {this is an error}
|
||||
test oo-37.5 {TIP 500: private command can't be used outside definitions} -body {
|
||||
oo::define::private error "xyz"
|
||||
} -returnCodes error -result {this command may only be called from within the context of an ::oo::define or ::oo::objdefine command}
|
||||
test oo-37.6 {TIP 500: private command can't be used outside definitions} -body {
|
||||
oo::objdefine::private error "xyz"
|
||||
} -returnCodes error -result {this command may only be called from within the context of an ::oo::define or ::oo::objdefine command}
|
||||
|
||||
test oo-38.1 {TIP 500: private variables don't cross-interfere with each other or normal ones} -setup {
|
||||
oo::class create parent
|
||||
} -body {
|
||||
oo::class create clsA {
|
||||
superclass parent
|
||||
private variable x
|
||||
constructor {} {
|
||||
set x 1
|
||||
}
|
||||
method getA {} {
|
||||
return $x
|
||||
}
|
||||
}
|
||||
oo::class create clsB {
|
||||
superclass clsA
|
||||
private {
|
||||
variable x
|
||||
}
|
||||
constructor {} {
|
||||
set x 2
|
||||
next
|
||||
}
|
||||
method getB {} {
|
||||
return $x
|
||||
}
|
||||
}
|
||||
oo::class create clsC {
|
||||
superclass clsB
|
||||
variable x
|
||||
constructor {} {
|
||||
set x 3
|
||||
next
|
||||
}
|
||||
method getC {} {
|
||||
return $x
|
||||
}
|
||||
}
|
||||
clsC create obj
|
||||
oo::objdefine obj {
|
||||
private {
|
||||
variable x
|
||||
}
|
||||
method setup {} {
|
||||
set x 4
|
||||
}
|
||||
method getO {} {
|
||||
return $x
|
||||
}
|
||||
}
|
||||
obj setup
|
||||
list [obj getA] [obj getB] [obj getC] [obj getO] \
|
||||
[lsort [string map [list [info object creationid clsA] CLASS-A \
|
||||
[info object creationid clsB] CLASS-B \
|
||||
[info object creationid obj] OBJ] \
|
||||
[info object vars obj]]]
|
||||
} -cleanup {
|
||||
parent destroy
|
||||
} -result {1 2 3 4 {{CLASS-A : x} {CLASS-B : x} {OBJ : x} x}}
|
||||
test oo-38.2 {TIP 500: private variables introspection} -setup {
|
||||
oo::class create parent
|
||||
} -body {
|
||||
oo::class create cls {
|
||||
superclass parent
|
||||
private {
|
||||
variable x1
|
||||
variable x2
|
||||
}
|
||||
variable y1 y2
|
||||
}
|
||||
cls create obj
|
||||
oo::objdefine obj {
|
||||
private variable a1 a2
|
||||
variable b1 b2
|
||||
}
|
||||
list [lsort [info class variables cls]] \
|
||||
[lsort [info class variables cls -private]] \
|
||||
[lsort [info object variables obj]] \
|
||||
[lsort [info object variables obj -private]]
|
||||
} -cleanup {
|
||||
parent destroy
|
||||
} -result {{y1 y2} {x1 x2} {b1 b2} {a1 a2}}
|
||||
test oo-38.3 {TIP 500: private variables and oo::object·varname} -setup {
|
||||
oo::class create parent
|
||||
} -body {
|
||||
oo::class create clsA {
|
||||
superclass parent
|
||||
private {
|
||||
variable x
|
||||
}
|
||||
method getx {} {
|
||||
set x 1
|
||||
my varname x
|
||||
}
|
||||
method readx {} {
|
||||
return $x
|
||||
}
|
||||
}
|
||||
oo::class create clsB {
|
||||
superclass clsA
|
||||
variable x
|
||||
method gety {} {
|
||||
set x 1
|
||||
my varname x
|
||||
}
|
||||
method ready {} {
|
||||
return $x
|
||||
}
|
||||
}
|
||||
clsB create obj
|
||||
set [obj getx] 2
|
||||
set [obj gety] 3
|
||||
list [obj readx] [obj ready]
|
||||
} -cleanup {
|
||||
parent destroy
|
||||
} -result {2 3}
|
||||
test oo-38.4 {TIP 500: private variables introspection} -setup {
|
||||
oo::class create parent
|
||||
} -body {
|
||||
oo::class create cls {
|
||||
superclass parent
|
||||
private {
|
||||
variable x1 x2
|
||||
}
|
||||
variable y1 y2
|
||||
constructor {} {
|
||||
variable z boo
|
||||
set x1 a
|
||||
set y1 c
|
||||
}
|
||||
method list {} {
|
||||
variable z
|
||||
set ok 1
|
||||
list [info locals] [lsort [info vars]] [info exist x2]
|
||||
}
|
||||
}
|
||||
cls create obj
|
||||
oo::objdefine obj {
|
||||
private variable a1 a2
|
||||
variable b1 b2
|
||||
method init {} {
|
||||
# Because we don't have a constructor to do this setup for us
|
||||
set a1 p
|
||||
set b1 r
|
||||
}
|
||||
method list {} {
|
||||
variable z
|
||||
set yes 1
|
||||
list {*}[next] [info locals] [lsort [info vars]] [info exist a2]
|
||||
}
|
||||
}
|
||||
obj init
|
||||
obj list
|
||||
} -cleanup {
|
||||
parent destroy
|
||||
} -result {ok {ok x1 x2 y1 y2 z} 0 yes {a1 a2 b1 b2 yes z} 0}
|
||||
test oo-38.5 {TIP 500: private variables and oo::object·variable} -setup {
|
||||
oo::class create parent
|
||||
} -body {
|
||||
oo::class create cls1 {
|
||||
superclass parent
|
||||
private variable x
|
||||
method abc val {
|
||||
my variable x
|
||||
set x $val
|
||||
}
|
||||
method def val {
|
||||
my variable y
|
||||
set y $val
|
||||
}
|
||||
method get1 {} {
|
||||
my variable x y
|
||||
return [list $x $y]
|
||||
}
|
||||
}
|
||||
oo::class create cls2 {
|
||||
superclass cls1
|
||||
private variable x
|
||||
method x-exists {} {
|
||||
return [info exists x],[uplevel 1 {info exists x}]
|
||||
}
|
||||
method ghi x {
|
||||
# Additional instrumentation to show that we're not using the
|
||||
# resolved variable until we ask for it; the argument nixed that
|
||||
# happening by default.
|
||||
set val $x
|
||||
set before [my x-exists]
|
||||
unset x
|
||||
set x $val
|
||||
set mid [my x-exists]
|
||||
unset x
|
||||
set mid2 [my x-exists]
|
||||
my variable x
|
||||
set x $val
|
||||
set after [my x-exists]
|
||||
return "$before;$mid;$mid2;$after"
|
||||
}
|
||||
method jkl val {
|
||||
my variable y
|
||||
set y $val
|
||||
}
|
||||
method get2 {} {
|
||||
my variable x y
|
||||
return [list $x $y]
|
||||
}
|
||||
}
|
||||
cls2 create a
|
||||
a abc 123
|
||||
a def 234
|
||||
set tmp [a ghi 345]
|
||||
a jkl 456
|
||||
list $tmp [a get1] [a get2]
|
||||
} -cleanup {
|
||||
parent destroy
|
||||
} -result {{0,1;0,1;0,0;1,1} {123 456} {345 456}}
|
||||
|
||||
test oo-39.1 {TIP 500: private methods internal call; class private} -setup {
|
||||
oo::class create parent
|
||||
} -body {
|
||||
oo::class create clsA {
|
||||
superclass parent
|
||||
variable x
|
||||
constructor {} {
|
||||
set x 1
|
||||
}
|
||||
method act {} {
|
||||
my step
|
||||
my step
|
||||
my step
|
||||
return
|
||||
}
|
||||
private {
|
||||
method step {} {
|
||||
incr x 2
|
||||
}
|
||||
}
|
||||
method x {} {
|
||||
return $x
|
||||
}
|
||||
}
|
||||
clsA create obj
|
||||
obj act
|
||||
list [obj x] [catch {obj step} msg] $msg
|
||||
} -cleanup {
|
||||
parent destroy
|
||||
} -result {7 1 {unknown method "step": must be act, destroy or x}}
|
||||
test oo-39.2 {TIP 500: private methods internal call; class private} -setup {
|
||||
oo::class create parent
|
||||
} -body {
|
||||
oo::class create clsA {
|
||||
superclass parent
|
||||
variable x
|
||||
constructor {} {
|
||||
set x 1
|
||||
}
|
||||
method act {} {
|
||||
my step
|
||||
my step
|
||||
my step
|
||||
return
|
||||
}
|
||||
private {
|
||||
method step {} {
|
||||
incr x 2
|
||||
}
|
||||
}
|
||||
method x {} {
|
||||
return $x
|
||||
}
|
||||
}
|
||||
oo::class create clsB {
|
||||
superclass clsA
|
||||
variable x
|
||||
method step {} {
|
||||
incr x 5
|
||||
}
|
||||
}
|
||||
clsB create obj
|
||||
obj act
|
||||
list [obj x] [obj step]
|
||||
} -cleanup {
|
||||
parent destroy
|
||||
} -result {7 12}
|
||||
test oo-39.3 {TIP 500: private methods internal call; class private} -setup {
|
||||
oo::class create parent
|
||||
} -body {
|
||||
oo::class create clsA {
|
||||
superclass parent
|
||||
variable x
|
||||
constructor {} {
|
||||
set x 1
|
||||
}
|
||||
method act {} {
|
||||
my Step
|
||||
my Step
|
||||
my Step
|
||||
return
|
||||
}
|
||||
method x {} {
|
||||
return $x
|
||||
}
|
||||
}
|
||||
oo::class create clsB {
|
||||
superclass clsA
|
||||
variable x
|
||||
method Step {} {
|
||||
incr x 5
|
||||
}
|
||||
}
|
||||
clsB create obj
|
||||
obj act
|
||||
set result [obj x]
|
||||
oo::define clsA {
|
||||
private {
|
||||
method Step {} {
|
||||
incr x 2
|
||||
}
|
||||
}
|
||||
}
|
||||
obj act
|
||||
lappend result [obj x]
|
||||
} -cleanup {
|
||||
parent destroy
|
||||
} -result {16 22}
|
||||
test oo-39.4 {TIP 500: private methods internal call; instance private} -setup {
|
||||
oo::class create parent
|
||||
} -body {
|
||||
oo::class create clsA {
|
||||
superclass parent
|
||||
variable x
|
||||
constructor {} {
|
||||
set x 1
|
||||
}
|
||||
method act {} {
|
||||
my step
|
||||
return
|
||||
}
|
||||
method step {} {
|
||||
incr x
|
||||
}
|
||||
method x {} {
|
||||
return $x
|
||||
}
|
||||
}
|
||||
clsA create obj
|
||||
obj act
|
||||
set result [obj x]
|
||||
oo::objdefine obj {
|
||||
variable x
|
||||
private {
|
||||
method step {} {
|
||||
incr x 2
|
||||
}
|
||||
}
|
||||
}
|
||||
obj act
|
||||
lappend result [obj x]
|
||||
oo::objdefine obj {
|
||||
method act {} {
|
||||
my step
|
||||
next
|
||||
}
|
||||
}
|
||||
obj act
|
||||
lappend result [obj x]
|
||||
} -cleanup {
|
||||
parent destroy
|
||||
} -result {2 3 6}
|
||||
test oo-39.5 {TIP 500: private methods internal call; cross object} -setup {
|
||||
oo::class create parent
|
||||
} -body {
|
||||
oo::class create cls {
|
||||
superclass parent
|
||||
variable x
|
||||
constructor {val} {
|
||||
set x $val
|
||||
}
|
||||
private method x {} {
|
||||
return $x
|
||||
}
|
||||
method equal {other} {
|
||||
expr {$x == [$other x]}
|
||||
}
|
||||
}
|
||||
cls create a 1
|
||||
cls create b 2
|
||||
cls create c 1
|
||||
list [a equal b] [b equal c] [c equal a] [catch {a x} msg] $msg
|
||||
} -cleanup {
|
||||
parent destroy
|
||||
} -result {0 0 1 1 {unknown method "x": must be destroy or equal}}
|
||||
test oo-39.6 {TIP 500: private methods internal call; error reporting} -setup {
|
||||
oo::class create parent
|
||||
} -body {
|
||||
oo::class create cls {
|
||||
superclass parent
|
||||
variable x
|
||||
constructor {val} {
|
||||
set x $val
|
||||
}
|
||||
private method x {} {
|
||||
return $x
|
||||
}
|
||||
method equal {other} {
|
||||
expr {$x == [$other y]}
|
||||
}
|
||||
}
|
||||
cls create a 1
|
||||
cls create b 2
|
||||
a equal b
|
||||
} -returnCodes error -cleanup {
|
||||
parent destroy
|
||||
} -result {unknown method "y": must be destroy, equal or x}
|
||||
test oo-39.7 {TIP 500: private methods internal call; error reporting} -setup {
|
||||
oo::class create parent
|
||||
} -body {
|
||||
oo::class create cls {
|
||||
superclass parent
|
||||
variable x
|
||||
constructor {val} {
|
||||
set x $val
|
||||
}
|
||||
private method x {} {
|
||||
return $x
|
||||
}
|
||||
method equal {other} {
|
||||
expr {[[self] y] == [$other x]}
|
||||
}
|
||||
}
|
||||
cls create a 1
|
||||
cls create b 2
|
||||
a equal b
|
||||
} -returnCodes error -cleanup {
|
||||
parent destroy
|
||||
} -result {unknown method "y": must be destroy, equal or x}
|
||||
test oo-39.8 {TIP 500: private methods internal call; error reporting} -setup {
|
||||
oo::class create parent
|
||||
} -body {
|
||||
oo::class create cls {
|
||||
superclass parent
|
||||
variable x
|
||||
constructor {val} {
|
||||
set x $val
|
||||
}
|
||||
private method x {} {
|
||||
return $x
|
||||
}
|
||||
method equal {other} {
|
||||
expr {[my y] == [$other x]}
|
||||
}
|
||||
}
|
||||
cls create a 1
|
||||
cls create b 2
|
||||
a equal b
|
||||
} -returnCodes error -cleanup {
|
||||
parent destroy
|
||||
} -result {unknown method "y": must be <cloned>, destroy, equal, eval, unknown, variable, varname or x}
|
||||
test oo-39.9 {TIP 500: private methods internal call; error reporting} -setup {
|
||||
oo::class create parent
|
||||
} -body {
|
||||
oo::class create cls {
|
||||
superclass parent
|
||||
variable x
|
||||
constructor {val} {
|
||||
set x $val
|
||||
}
|
||||
private method x {} {
|
||||
return $x
|
||||
}
|
||||
}
|
||||
oo::class create cls2 {
|
||||
superclass cls
|
||||
method equal {other} {
|
||||
expr {[my y] == [$other x]}
|
||||
}
|
||||
}
|
||||
cls2 create a 1
|
||||
cls2 create b 2
|
||||
a equal b
|
||||
} -returnCodes error -cleanup {
|
||||
parent destroy
|
||||
} -result {unknown method "y": must be <cloned>, destroy, equal, eval, unknown, variable or varname}
|
||||
test oo-39.10 {TIP 500: private methods internal call; error reporting} -setup {
|
||||
oo::class create parent
|
||||
} -body {
|
||||
oo::class create cls {
|
||||
superclass parent
|
||||
variable x
|
||||
constructor {val} {
|
||||
set x $val
|
||||
}
|
||||
private method x {} {
|
||||
return $x
|
||||
}
|
||||
}
|
||||
oo::class create cls2 {
|
||||
superclass cls
|
||||
method equal {other} {
|
||||
expr {[my x] == [$other x]}
|
||||
}
|
||||
}
|
||||
cls2 create a 1
|
||||
cls2 create b 2
|
||||
a equal b
|
||||
} -returnCodes error -cleanup {
|
||||
parent destroy
|
||||
} -result {unknown method "x": must be <cloned>, destroy, equal, eval, unknown, variable or varname}
|
||||
test oo-39.11 {TIP 500: private methods; call chain caching and reporting} -setup {
|
||||
oo::class create parent
|
||||
} -body {
|
||||
oo::class create cls {
|
||||
superclass parent
|
||||
method chain {} {
|
||||
return [self call]
|
||||
}
|
||||
}
|
||||
oo::class create cls2 {
|
||||
superclass cls
|
||||
private method chain {} {
|
||||
next
|
||||
}
|
||||
method chain2 {} {
|
||||
my chain
|
||||
}
|
||||
method chain3 {} {
|
||||
[self] chain
|
||||
}
|
||||
}
|
||||
cls create a
|
||||
cls2 create b
|
||||
list [a chain] [b chain] [b chain2] [b chain3]
|
||||
} -cleanup {
|
||||
parent destroy
|
||||
} -result {{{{method chain ::cls method}} 0} {{{method chain ::cls method}} 0} {{{private chain ::cls2 method} {method chain ::cls method}} 1} {{{private chain ::cls2 method} {method chain ::cls method}} 1}}
|
||||
test oo-39.12 {TIP 500: private methods; introspection} -setup {
|
||||
oo::class create parent
|
||||
} -body {
|
||||
oo::class create cls {
|
||||
superclass parent
|
||||
method chain {} {
|
||||
return [self call]
|
||||
}
|
||||
private method abc {} {}
|
||||
}
|
||||
oo::class create cls2 {
|
||||
superclass cls
|
||||
method chain2 {} {
|
||||
my chain
|
||||
}
|
||||
method chain3 {} {
|
||||
[self] chain
|
||||
}
|
||||
private method def {} {}
|
||||
unexport chain3
|
||||
}
|
||||
cls create a
|
||||
cls2 create b
|
||||
oo::objdefine b {
|
||||
private method ghi {} {}
|
||||
method ABC {} {}
|
||||
method foo {} {}
|
||||
}
|
||||
set scopes {public unexported private}
|
||||
list a: [lmap s $scopes {info object methods a -scope $s}] \
|
||||
b: [lmap s $scopes {info object methods b -scope $s}] \
|
||||
cls: [lmap s $scopes {info class methods cls -scope $s}] \
|
||||
cls2: [lmap s $scopes {info class methods cls2 -scope $s}] \
|
||||
} -cleanup {
|
||||
parent destroy
|
||||
} -result {a: {{} {} {}} b: {foo ABC ghi} cls: {chain {} abc} cls2: {chain2 chain3 def}}
|
||||
|
||||
test oo-40.1 {TIP 500: private and self} -setup {
|
||||
oo::class create cls
|
||||
} -body {
|
||||
oo::define cls {
|
||||
self {
|
||||
private {
|
||||
variable a
|
||||
}
|
||||
variable b
|
||||
}
|
||||
private {
|
||||
self {
|
||||
variable c
|
||||
}
|
||||
variable d
|
||||
}
|
||||
variable e
|
||||
}
|
||||
list \
|
||||
[lsort [info class variables cls]] \
|
||||
[lsort [info class variables cls -private]] \
|
||||
[lsort [info object variables cls]] \
|
||||
[lsort [info object variables cls -private]]
|
||||
} -cleanup {
|
||||
cls destroy
|
||||
} -result {e d b {a c}}
|
||||
test oo-40.2 {TIP 500: private and export} -setup {
|
||||
oo::class create cls
|
||||
} -body {
|
||||
oo::define cls {
|
||||
private method foo {} {}
|
||||
}
|
||||
set result [lmap s {public unexported private} {
|
||||
info class methods cls -scope $s}]
|
||||
oo::define cls {
|
||||
export foo
|
||||
}
|
||||
lappend result {*}[lmap s {public unexported private} {
|
||||
info class methods cls -scope $s}]
|
||||
} -cleanup {
|
||||
cls destroy
|
||||
} -result {{} {} foo foo {} {}}
|
||||
test oo-40.3 {TIP 500: private and unexport} -setup {
|
||||
oo::class create cls
|
||||
} -body {
|
||||
oo::define cls {
|
||||
private method foo {} {}
|
||||
}
|
||||
set result [lmap s {public unexported private} {
|
||||
info class methods cls -scope $s}]
|
||||
oo::define cls {
|
||||
unexport foo
|
||||
}
|
||||
lappend result {*}[lmap s {public unexported private} {
|
||||
info class methods cls -scope $s}]
|
||||
} -cleanup {
|
||||
cls destroy
|
||||
} -result {{} {} foo {} foo {}}
|
||||
|
||||
cleanupTests
|
||||
return
|
||||
|
||||
+259
-6
@@ -13,19 +13,272 @@ if {[lsearch [namespace children] ::tcltest] == -1} {
|
||||
namespace import -force ::tcltest::*
|
||||
}
|
||||
|
||||
# Utilities
|
||||
set path(sleep) [makeFile {
|
||||
after [expr $argv*1000]
|
||||
exit
|
||||
} sleep]
|
||||
set path(exit) [makeFile {
|
||||
exit $argv
|
||||
} exit]
|
||||
|
||||
# Basic syntax checking
|
||||
test process-1.1 {tcl::process command basic syntax} -returnCodes error -body {
|
||||
tcl::process
|
||||
} -result {wrong # args: should be "tcl::process subcommand ?arg ...?"}
|
||||
test process-1.2 {tcl::process command basic syntax} -returnCodes error -body {
|
||||
test process-1.2 {tcl::process subcommands} -returnCodes error -body {
|
||||
tcl::process ?
|
||||
} -match glob -result {unknown or ambiguous subcommand "?": must be autopurge, list, purge, or status}
|
||||
|
||||
test process-2.1 {tcl::process autopurge get} {tcl::process autopurge} {1}
|
||||
test process-2.2 {tcl::process autopurge set true} {
|
||||
# Autopurge flag
|
||||
# - Default state
|
||||
test process-2.1 {autopurge default} -body {
|
||||
tcl::process autopurge
|
||||
} -result {1}
|
||||
# - Enabling autopurge
|
||||
test process-2.2 {enable autopurge} -body {
|
||||
tcl::process autopurge true
|
||||
tcl::process autopurge
|
||||
} {1}
|
||||
test process-2.3 {tcl::process autopurge set false} {
|
||||
} -result {1}
|
||||
# - Disabling autopurge
|
||||
test process-2.3 {disable autopurge} -body {
|
||||
tcl::process autopurge false
|
||||
tcl::process autopurge
|
||||
} {0}
|
||||
} -result {0} -cleanup {tcl::process autopurge true}
|
||||
|
||||
# Subprocess list & status
|
||||
test process-3.1 {empty subprocess list} -body {
|
||||
llength [tcl::process list]
|
||||
} -result {0}
|
||||
test process-3.2 {empty subprocess status} -body {
|
||||
dict size [tcl::process status]
|
||||
} -result {0}
|
||||
|
||||
# Spawn subprocesses using [exec]
|
||||
# - One child
|
||||
test process-4.1 {exec one child} -body {
|
||||
tcl::process autopurge 0
|
||||
set pid [exec [interpreter] $path(exit) 0 &]
|
||||
set list [tcl::process list]
|
||||
set statuses [tcl::process status -wait]
|
||||
set status [lindex [tcl::process status $pid] 1]
|
||||
expr {
|
||||
[llength $list] eq 1
|
||||
&& [lindex $list 0] eq $pid
|
||||
&& [dict size $statuses] eq 1
|
||||
&& [dict get $statuses $pid] eq $status
|
||||
&& $status eq 0
|
||||
}
|
||||
} -result {1} -cleanup {
|
||||
tcl::process purge
|
||||
tcl::process autopurge 1
|
||||
}
|
||||
# - Two children
|
||||
test process-4.2 {exec two children in parallel} -body {
|
||||
tcl::process autopurge 0
|
||||
set pid1 [exec [interpreter] $path(exit) 0 &]
|
||||
set pid2 [exec [interpreter] $path(exit) 0 &]
|
||||
set list [tcl::process list]
|
||||
set statuses [tcl::process status -wait]
|
||||
set status1 [lindex [tcl::process status $pid1] 1]
|
||||
set status2 [lindex [tcl::process status $pid2] 1]
|
||||
expr {
|
||||
[llength $list] eq 2
|
||||
&& [lsearch $list $pid1] >= 0
|
||||
&& [lsearch $list $pid2] >= 0
|
||||
&& [dict size $statuses] eq 2
|
||||
&& [dict get $statuses $pid1] eq $status1
|
||||
&& [dict get $statuses $pid2] eq $status2
|
||||
&& $status1 eq 0
|
||||
&& $status2 eq 0
|
||||
}
|
||||
} -result {1} -cleanup {
|
||||
tcl::process purge
|
||||
tcl::process autopurge 1
|
||||
}
|
||||
# - 3-stage pipe
|
||||
test process-4.3 {exec 3-stage pipe} -body {
|
||||
tcl::process autopurge 0
|
||||
set pids [exec \
|
||||
[interpreter] $path(exit) 0 \
|
||||
| [interpreter] $path(exit) 0 \
|
||||
| [interpreter] $path(exit) 0 \
|
||||
&]
|
||||
lassign $pids pid1 pid2 pid3
|
||||
set list [tcl::process list]
|
||||
set statuses [tcl::process status -wait]
|
||||
set status1 [lindex [tcl::process status $pid1] 1]
|
||||
set status2 [lindex [tcl::process status $pid2] 1]
|
||||
set status3 [lindex [tcl::process status $pid3] 1]
|
||||
expr {
|
||||
[llength $pids] eq 3
|
||||
&& [llength $list] eq 3
|
||||
&& [lsearch $list $pid1] >= 0
|
||||
&& [lsearch $list $pid2] >= 0
|
||||
&& [lsearch $list $pid3] >= 0
|
||||
&& [dict size $statuses] eq 3
|
||||
&& [dict get $statuses $pid1] eq $status1
|
||||
&& [dict get $statuses $pid2] eq $status2
|
||||
&& [dict get $statuses $pid3] eq $status3
|
||||
&& $status1 eq 0
|
||||
&& $status2 eq 0
|
||||
&& $status3 eq 0
|
||||
}
|
||||
} -result {1} -cleanup {
|
||||
tcl::process purge
|
||||
tcl::process autopurge 1
|
||||
}
|
||||
|
||||
# Spawn subprocesses using [open "|"]
|
||||
# - One child
|
||||
test process-5.1 {exec one child} -body {
|
||||
tcl::process autopurge 0
|
||||
set f [open "|\"[interpreter]\" \"$path(exit)\" 0"]
|
||||
set pid [pid $f]
|
||||
set list [tcl::process list]
|
||||
set statuses [tcl::process status -wait]
|
||||
set status [lindex [tcl::process status $pid] 1]
|
||||
expr {
|
||||
[llength $list] eq 1
|
||||
&& [lindex $list 0] eq $pid
|
||||
&& [dict size $statuses] eq 1
|
||||
&& [dict get $statuses $pid] eq $status
|
||||
&& $status eq 0
|
||||
}
|
||||
} -result {1} -cleanup {
|
||||
close $f
|
||||
tcl::process purge
|
||||
tcl::process autopurge 1
|
||||
}
|
||||
# - Two children
|
||||
test process-5.2 {exec two children in parallel} -body {
|
||||
tcl::process autopurge 0
|
||||
set f1 [open "|\"[interpreter]\" \"$path(exit)\" 0"]
|
||||
set f2 [open "|\"[interpreter]\" \"$path(exit)\" 0"]
|
||||
set pid1 [pid $f1]
|
||||
set pid2 [pid $f2]
|
||||
set list [tcl::process list]
|
||||
set statuses [tcl::process status -wait]
|
||||
set status1 [lindex [tcl::process status $pid1] 1]
|
||||
set status2 [lindex [tcl::process status $pid2] 1]
|
||||
expr {
|
||||
[llength $list] eq 2
|
||||
&& [lsearch $list $pid1] >= 0
|
||||
&& [lsearch $list $pid2] >= 0
|
||||
&& [dict size $statuses] eq 2
|
||||
&& [dict get $statuses $pid1] eq $status1
|
||||
&& [dict get $statuses $pid2] eq $status2
|
||||
&& $status1 eq 0
|
||||
&& $status2 eq 0
|
||||
}
|
||||
} -result {1} -cleanup {
|
||||
close $f1
|
||||
close $f2
|
||||
tcl::process purge
|
||||
tcl::process autopurge 1
|
||||
}
|
||||
# - 3-stage pipe
|
||||
test process-5.3 {exec 3-stage pipe} -body {
|
||||
tcl::process autopurge 0
|
||||
set f [open "|
|
||||
\"[interpreter]\" \"$path(exit)\" 0
|
||||
| \"[interpreter]\" \"$path(exit)\" 0
|
||||
| \"[interpreter]\" \"$path(exit)\" 0
|
||||
"]
|
||||
set pids [pid $f]
|
||||
lassign $pids pid1 pid2 pid3
|
||||
set list [tcl::process list]
|
||||
set statuses [tcl::process status -wait]
|
||||
set status1 [lindex [tcl::process status $pid1] 1]
|
||||
set status2 [lindex [tcl::process status $pid2] 1]
|
||||
set status3 [lindex [tcl::process status $pid3] 1]
|
||||
expr {
|
||||
[llength $pids] eq 3
|
||||
&& [llength $list] eq 3
|
||||
&& [lsearch $list $pid1] >= 0
|
||||
&& [lsearch $list $pid2] >= 0
|
||||
&& [lsearch $list $pid3] >= 0
|
||||
&& [dict size $statuses] eq 3
|
||||
&& [dict get $statuses $pid1] eq $status1
|
||||
&& [dict get $statuses $pid2] eq $status2
|
||||
&& [dict get $statuses $pid3] eq $status3
|
||||
&& $status1 eq 0
|
||||
&& $status2 eq 0
|
||||
&& $status3 eq 0
|
||||
}
|
||||
} -result {1} -cleanup {
|
||||
close $f
|
||||
tcl::process purge
|
||||
tcl::process autopurge 1
|
||||
}
|
||||
|
||||
# Async child status
|
||||
test process-6.1 {async status} -body {
|
||||
tcl::process autopurge 0
|
||||
set pid [exec [interpreter] $path(sleep) 1 &]
|
||||
set status1 [lindex [tcl::process status $pid] 1]
|
||||
set status2 [lindex [tcl::process status -wait $pid] 1]
|
||||
expr {
|
||||
$status1 eq {}
|
||||
&& $status2 eq 0
|
||||
}
|
||||
} -result {1} -cleanup {
|
||||
tcl::process purge
|
||||
tcl::process autopurge 1
|
||||
}
|
||||
test process-6.2 {selective wait} -body {
|
||||
tcl::process autopurge 0
|
||||
# Child 1 sleeps 1s
|
||||
set pid1 [exec [interpreter] $path(sleep) 1 &]
|
||||
# Child 2 sleeps 1s
|
||||
set pid2 [exec [interpreter] $path(sleep) 2 &]
|
||||
# Initial status
|
||||
set status1_1 [lindex [tcl::process status $pid1] 1]
|
||||
set status1_2 [lindex [tcl::process status $pid2] 1]
|
||||
# Wait until child 1 termination
|
||||
set status2_1 [lindex [tcl::process status -wait $pid1] 1]
|
||||
set status2_2 [lindex [tcl::process status $pid2] 1]
|
||||
# Wait until child 2 termination
|
||||
set status3_2 [lindex [tcl::process status -wait $pid2] 1]
|
||||
set status3_1 [lindex [tcl::process status $pid1] 1]
|
||||
expr {
|
||||
$status1_1 eq {}
|
||||
&& $status1_2 eq {}
|
||||
&& $status2_1 eq 0
|
||||
&& $status2_2 eq {}
|
||||
&& $status3_1 eq 0
|
||||
&& $status3_2 eq 0
|
||||
}
|
||||
} -result {1} -cleanup {
|
||||
tcl::process purge
|
||||
tcl::process autopurge 1
|
||||
}
|
||||
|
||||
# Error codes
|
||||
test process-7.1 {normal exit} -body {
|
||||
tcl::process autopurge 0
|
||||
set pid [exec [interpreter] $path(exit) 0 &]
|
||||
lindex [tcl::process status -wait $pid] 1
|
||||
} -result {0} -cleanup {
|
||||
tcl::process purge
|
||||
tcl::process autopurge 1
|
||||
}
|
||||
test process-7.2 {abnormal exit} -body {
|
||||
tcl::process autopurge 0
|
||||
set pid [exec [interpreter] $path(exit) 1 &]
|
||||
lindex [tcl::process status -wait $pid] 1
|
||||
} -match glob -result {1 {child process exited abnormally} {CHILDSTATUS * 1}} -cleanup {
|
||||
tcl::process purge
|
||||
tcl::process autopurge 1
|
||||
}
|
||||
test process-7.3 {child killed} -constraints {win} -body {
|
||||
tcl::process autopurge 0
|
||||
set pid [exec [interpreter] $path(exit) -1 &]
|
||||
lindex [tcl::process status -wait $pid] 1
|
||||
} -match glob -result {1 {child killed: unknown signal} {CHILDKILLED * {unknown signal} {unknown signal}}} -cleanup {
|
||||
tcl::process purge
|
||||
tcl::process autopurge 1
|
||||
}
|
||||
|
||||
::tcltest::cleanupTests
|
||||
return
|
||||
|
||||
@@ -18,16 +18,11 @@ if {[lsearch [namespace children] ::tcltest] == -1} {
|
||||
# When run in a Tk shell, these tests hang.
|
||||
testConstraint noTk [expr {0 != [catch {package present Tk}]}]
|
||||
testConstraint thread [expr {0 == [catch {package require Thread 2.7-}]}]
|
||||
# Darwin always uses a threaded notifier
|
||||
testConstraint unthreaded [expr {
|
||||
![::tcl::pkgconfig get threaded]
|
||||
&& $tcl_platform(os) ne "Darwin"
|
||||
}]
|
||||
|
||||
# The next two tests will hang if threads are enabled because the notifier
|
||||
# will not necessarily wait for ever in this case, so it does not generate
|
||||
# an error.
|
||||
test unixNotfy-1.1 {Tcl_DeleteFileHandler} -constraints {noTk unix unthreaded} -body {
|
||||
test unixNotfy-1.1 {Tcl_DeleteFileHandler} -constraints nonPortable -body {
|
||||
catch {vwait x}
|
||||
set f [open [makeFile "" foo] w]
|
||||
fileevent $f writable {set x 1}
|
||||
@@ -38,7 +33,7 @@ test unixNotfy-1.1 {Tcl_DeleteFileHandler} -constraints {noTk unix unthreaded} -
|
||||
catch { close $f }
|
||||
catch { removeFile foo }
|
||||
}
|
||||
test unixNotfy-1.2 {Tcl_DeleteFileHandler} -constraints {noTk unix unthreaded} -body {
|
||||
test unixNotfy-1.2 {Tcl_DeleteFileHandler} -constraints nonPortable -body {
|
||||
catch {vwait x}
|
||||
set f1 [open [makeFile "" foo] w]
|
||||
set f2 [open [makeFile "" foo2] w]
|
||||
|
||||
+8
-10
@@ -41,7 +41,7 @@ test utf-1.5 {Tcl_UniCharToUtf: overflowed Tcl_UniChar} testbytestring {
|
||||
test utf-1.6 {Tcl_UniCharToUtf: negative Tcl_UniChar} testbytestring {
|
||||
expr {[format %c -1] eq [testbytestring "\xef\xbf\xbd"]}
|
||||
} 1
|
||||
test utf-1.7 {Tcl_UniCharToUtf: 4 byte sequences} -constraints {tip389 testbytestring} -body {
|
||||
test utf-1.7 {Tcl_UniCharToUtf: 4 byte sequences} -constraints testbytestring -body {
|
||||
expr {"\U014e4e" eq [testbytestring "\xf0\x94\xb9\x8e"]}
|
||||
} -result 1
|
||||
|
||||
@@ -228,15 +228,13 @@ bsCheck \U4e21 20001
|
||||
bsCheck \U004e21 20001
|
||||
bsCheck \U00004e21 20001
|
||||
bsCheck \U0000004e21 78
|
||||
if {[testConstraint tip389]} {
|
||||
bsCheck \U00110000 69632
|
||||
bsCheck \U01100000 69632
|
||||
bsCheck \U11000000 69632
|
||||
bsCheck \U0010FFFF 1114111
|
||||
bsCheck \U010FFFF0 1114111
|
||||
bsCheck \U10FFFF00 1114111
|
||||
bsCheck \UFFFFFFFF 1048575
|
||||
}
|
||||
bsCheck \U00110000 69632
|
||||
bsCheck \U01100000 69632
|
||||
bsCheck \U11000000 69632
|
||||
bsCheck \U0010FFFF 1114111
|
||||
bsCheck \U010FFFF0 1114111
|
||||
bsCheck \U10FFFF00 1114111
|
||||
bsCheck \UFFFFFFFF 1048575
|
||||
|
||||
test utf-11.1 {Tcl_UtfToUpper} {
|
||||
string toupper {}
|
||||
|
||||
+1
-1
@@ -1061,7 +1061,7 @@ test winFCmd-12.6.2 {ConvertFileNameFormat: absolute path with drive (in temp fo
|
||||
} -constraints {win} -body {
|
||||
createfile $::env(TEMP)/td1 {}
|
||||
string equal [string tolower [file attributes $::env(TEMP)/td1 -longname]] \
|
||||
[string tolower [file normalize $::env(TEMP)]/td1]]
|
||||
[string tolower [file normalize $::env(TEMP)]/td1]
|
||||
} -cleanup {
|
||||
file delete -force -- $::env(TEMP)/td1
|
||||
} -result 1
|
||||
|
||||
+1
-1
@@ -1759,7 +1759,7 @@ configure-packages:
|
||||
$$i/configure --with-tcl=../.. \
|
||||
--with-tclinclude=$(GENERIC_DIR) \
|
||||
$(PKG_CFG_ARGS) --libdir=$(PACKAGE_DIR) \
|
||||
--enable-shared --enable-threads; ) || exit $$?; \
|
||||
--enable-shared; ) || exit $$?; \
|
||||
fi; \
|
||||
fi; \
|
||||
fi; \
|
||||
|
||||
@@ -45,8 +45,6 @@ How To Compile And Install Tcl:
|
||||
refer to the autoconf documentation (not included here). Tcl's "configure"
|
||||
supports the following special switches in addition to the standard ones:
|
||||
|
||||
--enable-threads If this switch is set, Tcl will compile itself
|
||||
with multithreading support.
|
||||
--disable-load If this switch is specified then Tcl will
|
||||
configure itself not to allow dynamic loading,
|
||||
even if your system appears to support it.
|
||||
|
||||
Vendored
+301
-382
@@ -699,7 +699,6 @@ ZLIB_INCLUDE
|
||||
ZLIB_SRCS
|
||||
ZLIB_OBJS
|
||||
TCLSH_PROG
|
||||
TCL_THREADS
|
||||
EGREP
|
||||
GREP
|
||||
CPP
|
||||
@@ -755,7 +754,6 @@ enable_option_checking
|
||||
enable_man_symlinks
|
||||
enable_man_compression
|
||||
enable_man_suffix
|
||||
enable_threads
|
||||
with_encoding
|
||||
enable_shared
|
||||
enable_64bit
|
||||
@@ -1395,7 +1393,6 @@ Optional Features:
|
||||
use STRING as a suffix to manpage file names
|
||||
(default: no, tcl if enabled without
|
||||
specifying STRING)
|
||||
--enable-threads build with threads (default: on)
|
||||
--enable-shared build and link with shared libraries (default: on)
|
||||
--enable-64bit enable 64bit support (default: off)
|
||||
--enable-64bit-vis enable 64bit Sparc VIS support (default: off)
|
||||
@@ -3910,323 +3907,6 @@ $as_echo "$tcl_cv_cc_pipe" >&6; }
|
||||
fi
|
||||
fi
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
# Threads support
|
||||
#------------------------------------------------------------------------
|
||||
|
||||
|
||||
# Check whether --enable-threads was given.
|
||||
if test "${enable_threads+set}" = set; then :
|
||||
enableval=$enable_threads; tcl_ok=$enableval
|
||||
else
|
||||
tcl_ok=yes
|
||||
fi
|
||||
|
||||
|
||||
if test "${TCL_THREADS}" = 1; then
|
||||
tcl_threaded_core=1;
|
||||
fi
|
||||
|
||||
if test "$tcl_ok" = "yes" -o "${TCL_THREADS}" = 1; then
|
||||
TCL_THREADS=1
|
||||
# USE_THREAD_ALLOC tells us to try the special thread-based
|
||||
# allocator that significantly reduces lock contention
|
||||
|
||||
$as_echo "#define USE_THREAD_ALLOC 1" >>confdefs.h
|
||||
|
||||
|
||||
$as_echo "#define _REENTRANT 1" >>confdefs.h
|
||||
|
||||
if test "`uname -s`" = "SunOS" ; then
|
||||
|
||||
$as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
|
||||
$as_echo "#define _THREAD_SAFE 1" >>confdefs.h
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lpthread" >&5
|
||||
$as_echo_n "checking for pthread_mutex_init in -lpthread... " >&6; }
|
||||
if ${ac_cv_lib_pthread_pthread_mutex_init+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
ac_check_lib_save_LIBS=$LIBS
|
||||
LIBS="-lpthread $LIBS"
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
|
||||
/* Override any GCC internal prototype to avoid an error.
|
||||
Use char because int might match the return type of a GCC
|
||||
builtin and then its argument prototype would still apply. */
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
char pthread_mutex_init ();
|
||||
int
|
||||
main ()
|
||||
{
|
||||
return pthread_mutex_init ();
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_link "$LINENO"; then :
|
||||
ac_cv_lib_pthread_pthread_mutex_init=yes
|
||||
else
|
||||
ac_cv_lib_pthread_pthread_mutex_init=no
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
LIBS=$ac_check_lib_save_LIBS
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_mutex_init" >&5
|
||||
$as_echo "$ac_cv_lib_pthread_pthread_mutex_init" >&6; }
|
||||
if test "x$ac_cv_lib_pthread_pthread_mutex_init" = xyes; then :
|
||||
tcl_ok=yes
|
||||
else
|
||||
tcl_ok=no
|
||||
fi
|
||||
|
||||
if test "$tcl_ok" = "no"; then
|
||||
# Check a little harder for __pthread_mutex_init in the same
|
||||
# library, as some systems hide it there until pthread.h is
|
||||
# defined. We could alternatively do an AC_TRY_COMPILE with
|
||||
# pthread.h, but that will work with libpthread really doesn't
|
||||
# exist, like AIX 4.2. [Bug: 4359]
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __pthread_mutex_init in -lpthread" >&5
|
||||
$as_echo_n "checking for __pthread_mutex_init in -lpthread... " >&6; }
|
||||
if ${ac_cv_lib_pthread___pthread_mutex_init+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
ac_check_lib_save_LIBS=$LIBS
|
||||
LIBS="-lpthread $LIBS"
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
|
||||
/* Override any GCC internal prototype to avoid an error.
|
||||
Use char because int might match the return type of a GCC
|
||||
builtin and then its argument prototype would still apply. */
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
char __pthread_mutex_init ();
|
||||
int
|
||||
main ()
|
||||
{
|
||||
return __pthread_mutex_init ();
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_link "$LINENO"; then :
|
||||
ac_cv_lib_pthread___pthread_mutex_init=yes
|
||||
else
|
||||
ac_cv_lib_pthread___pthread_mutex_init=no
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
LIBS=$ac_check_lib_save_LIBS
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread___pthread_mutex_init" >&5
|
||||
$as_echo "$ac_cv_lib_pthread___pthread_mutex_init" >&6; }
|
||||
if test "x$ac_cv_lib_pthread___pthread_mutex_init" = xyes; then :
|
||||
tcl_ok=yes
|
||||
else
|
||||
tcl_ok=no
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
if test "$tcl_ok" = "yes"; then
|
||||
# The space is needed
|
||||
THREADS_LIBS=" -lpthread"
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lpthreads" >&5
|
||||
$as_echo_n "checking for pthread_mutex_init in -lpthreads... " >&6; }
|
||||
if ${ac_cv_lib_pthreads_pthread_mutex_init+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
ac_check_lib_save_LIBS=$LIBS
|
||||
LIBS="-lpthreads $LIBS"
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
|
||||
/* Override any GCC internal prototype to avoid an error.
|
||||
Use char because int might match the return type of a GCC
|
||||
builtin and then its argument prototype would still apply. */
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
char pthread_mutex_init ();
|
||||
int
|
||||
main ()
|
||||
{
|
||||
return pthread_mutex_init ();
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_link "$LINENO"; then :
|
||||
ac_cv_lib_pthreads_pthread_mutex_init=yes
|
||||
else
|
||||
ac_cv_lib_pthreads_pthread_mutex_init=no
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
LIBS=$ac_check_lib_save_LIBS
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthreads_pthread_mutex_init" >&5
|
||||
$as_echo "$ac_cv_lib_pthreads_pthread_mutex_init" >&6; }
|
||||
if test "x$ac_cv_lib_pthreads_pthread_mutex_init" = xyes; then :
|
||||
tcl_ok=yes
|
||||
else
|
||||
tcl_ok=no
|
||||
fi
|
||||
|
||||
if test "$tcl_ok" = "yes"; then
|
||||
# The space is needed
|
||||
THREADS_LIBS=" -lpthreads"
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lc" >&5
|
||||
$as_echo_n "checking for pthread_mutex_init in -lc... " >&6; }
|
||||
if ${ac_cv_lib_c_pthread_mutex_init+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
ac_check_lib_save_LIBS=$LIBS
|
||||
LIBS="-lc $LIBS"
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
|
||||
/* Override any GCC internal prototype to avoid an error.
|
||||
Use char because int might match the return type of a GCC
|
||||
builtin and then its argument prototype would still apply. */
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
char pthread_mutex_init ();
|
||||
int
|
||||
main ()
|
||||
{
|
||||
return pthread_mutex_init ();
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_link "$LINENO"; then :
|
||||
ac_cv_lib_c_pthread_mutex_init=yes
|
||||
else
|
||||
ac_cv_lib_c_pthread_mutex_init=no
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
LIBS=$ac_check_lib_save_LIBS
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_pthread_mutex_init" >&5
|
||||
$as_echo "$ac_cv_lib_c_pthread_mutex_init" >&6; }
|
||||
if test "x$ac_cv_lib_c_pthread_mutex_init" = xyes; then :
|
||||
tcl_ok=yes
|
||||
else
|
||||
tcl_ok=no
|
||||
fi
|
||||
|
||||
if test "$tcl_ok" = "no"; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lc_r" >&5
|
||||
$as_echo_n "checking for pthread_mutex_init in -lc_r... " >&6; }
|
||||
if ${ac_cv_lib_c_r_pthread_mutex_init+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
ac_check_lib_save_LIBS=$LIBS
|
||||
LIBS="-lc_r $LIBS"
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
|
||||
/* Override any GCC internal prototype to avoid an error.
|
||||
Use char because int might match the return type of a GCC
|
||||
builtin and then its argument prototype would still apply. */
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
char pthread_mutex_init ();
|
||||
int
|
||||
main ()
|
||||
{
|
||||
return pthread_mutex_init ();
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_link "$LINENO"; then :
|
||||
ac_cv_lib_c_r_pthread_mutex_init=yes
|
||||
else
|
||||
ac_cv_lib_c_r_pthread_mutex_init=no
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
LIBS=$ac_check_lib_save_LIBS
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_r_pthread_mutex_init" >&5
|
||||
$as_echo "$ac_cv_lib_c_r_pthread_mutex_init" >&6; }
|
||||
if test "x$ac_cv_lib_c_r_pthread_mutex_init" = xyes; then :
|
||||
tcl_ok=yes
|
||||
else
|
||||
tcl_ok=no
|
||||
fi
|
||||
|
||||
if test "$tcl_ok" = "yes"; then
|
||||
# The space is needed
|
||||
THREADS_LIBS=" -pthread"
|
||||
else
|
||||
TCL_THREADS=0
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Don't know how to find pthread lib on your system - you must disable thread support or edit the LIBS in the Makefile..." >&5
|
||||
$as_echo "$as_me: WARNING: Don't know how to find pthread lib on your system - you must disable thread support or edit the LIBS in the Makefile..." >&2;}
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Does the pthread-implementation provide
|
||||
# 'pthread_attr_setstacksize' ?
|
||||
|
||||
ac_saved_libs=$LIBS
|
||||
LIBS="$LIBS $THREADS_LIBS"
|
||||
for ac_func in pthread_attr_setstacksize pthread_atfork
|
||||
do :
|
||||
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
|
||||
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
|
||||
if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
|
||||
_ACEOF
|
||||
|
||||
fi
|
||||
done
|
||||
|
||||
LIBS=$ac_saved_libs
|
||||
else
|
||||
TCL_THREADS=0
|
||||
fi
|
||||
# Do checking message here to not mess up interleaved configure output
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for building with threads" >&5
|
||||
$as_echo_n "checking for building with threads... " >&6; }
|
||||
if test "${TCL_THREADS}" = 1; then
|
||||
|
||||
$as_echo "#define TCL_THREADS 1" >>confdefs.h
|
||||
|
||||
if test "${tcl_threaded_core}" = 1; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes (threaded core)" >&5
|
||||
$as_echo "yes (threaded core)" >&6; }
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }
|
||||
fi
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
fi
|
||||
|
||||
|
||||
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
# Embedded configuration information, encoding to use for the values, TIP #59
|
||||
#------------------------------------------------------------------------
|
||||
@@ -4454,6 +4134,269 @@ fi
|
||||
|
||||
|
||||
|
||||
$as_echo "#define _REENTRANT 1" >>confdefs.h
|
||||
|
||||
|
||||
$as_echo "#define _THREAD_SAFE 1" >>confdefs.h
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lpthread" >&5
|
||||
$as_echo_n "checking for pthread_mutex_init in -lpthread... " >&6; }
|
||||
if ${ac_cv_lib_pthread_pthread_mutex_init+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
ac_check_lib_save_LIBS=$LIBS
|
||||
LIBS="-lpthread $LIBS"
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
|
||||
/* Override any GCC internal prototype to avoid an error.
|
||||
Use char because int might match the return type of a GCC
|
||||
builtin and then its argument prototype would still apply. */
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
char pthread_mutex_init ();
|
||||
int
|
||||
main ()
|
||||
{
|
||||
return pthread_mutex_init ();
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_link "$LINENO"; then :
|
||||
ac_cv_lib_pthread_pthread_mutex_init=yes
|
||||
else
|
||||
ac_cv_lib_pthread_pthread_mutex_init=no
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
LIBS=$ac_check_lib_save_LIBS
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_mutex_init" >&5
|
||||
$as_echo "$ac_cv_lib_pthread_pthread_mutex_init" >&6; }
|
||||
if test "x$ac_cv_lib_pthread_pthread_mutex_init" = xyes; then :
|
||||
tcl_ok=yes
|
||||
else
|
||||
tcl_ok=no
|
||||
fi
|
||||
|
||||
if test "$tcl_ok" = "no"; then
|
||||
# Check a little harder for __pthread_mutex_init in the same
|
||||
# library, as some systems hide it there until pthread.h is
|
||||
# defined. We could alternatively do an AC_TRY_COMPILE with
|
||||
# pthread.h, but that will work with libpthread really doesn't
|
||||
# exist, like AIX 4.2. [Bug: 4359]
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __pthread_mutex_init in -lpthread" >&5
|
||||
$as_echo_n "checking for __pthread_mutex_init in -lpthread... " >&6; }
|
||||
if ${ac_cv_lib_pthread___pthread_mutex_init+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
ac_check_lib_save_LIBS=$LIBS
|
||||
LIBS="-lpthread $LIBS"
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
|
||||
/* Override any GCC internal prototype to avoid an error.
|
||||
Use char because int might match the return type of a GCC
|
||||
builtin and then its argument prototype would still apply. */
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
char __pthread_mutex_init ();
|
||||
int
|
||||
main ()
|
||||
{
|
||||
return __pthread_mutex_init ();
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_link "$LINENO"; then :
|
||||
ac_cv_lib_pthread___pthread_mutex_init=yes
|
||||
else
|
||||
ac_cv_lib_pthread___pthread_mutex_init=no
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
LIBS=$ac_check_lib_save_LIBS
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread___pthread_mutex_init" >&5
|
||||
$as_echo "$ac_cv_lib_pthread___pthread_mutex_init" >&6; }
|
||||
if test "x$ac_cv_lib_pthread___pthread_mutex_init" = xyes; then :
|
||||
tcl_ok=yes
|
||||
else
|
||||
tcl_ok=no
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
if test "$tcl_ok" = "yes"; then
|
||||
# The space is needed
|
||||
THREADS_LIBS=" -lpthread"
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lpthreads" >&5
|
||||
$as_echo_n "checking for pthread_mutex_init in -lpthreads... " >&6; }
|
||||
if ${ac_cv_lib_pthreads_pthread_mutex_init+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
ac_check_lib_save_LIBS=$LIBS
|
||||
LIBS="-lpthreads $LIBS"
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
|
||||
/* Override any GCC internal prototype to avoid an error.
|
||||
Use char because int might match the return type of a GCC
|
||||
builtin and then its argument prototype would still apply. */
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
char pthread_mutex_init ();
|
||||
int
|
||||
main ()
|
||||
{
|
||||
return pthread_mutex_init ();
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_link "$LINENO"; then :
|
||||
ac_cv_lib_pthreads_pthread_mutex_init=yes
|
||||
else
|
||||
ac_cv_lib_pthreads_pthread_mutex_init=no
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
LIBS=$ac_check_lib_save_LIBS
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthreads_pthread_mutex_init" >&5
|
||||
$as_echo "$ac_cv_lib_pthreads_pthread_mutex_init" >&6; }
|
||||
if test "x$ac_cv_lib_pthreads_pthread_mutex_init" = xyes; then :
|
||||
_ok=yes
|
||||
else
|
||||
tcl_ok=no
|
||||
fi
|
||||
|
||||
if test "$tcl_ok" = "yes"; then
|
||||
# The space is needed
|
||||
THREADS_LIBS=" -lpthreads"
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lc" >&5
|
||||
$as_echo_n "checking for pthread_mutex_init in -lc... " >&6; }
|
||||
if ${ac_cv_lib_c_pthread_mutex_init+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
ac_check_lib_save_LIBS=$LIBS
|
||||
LIBS="-lc $LIBS"
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
|
||||
/* Override any GCC internal prototype to avoid an error.
|
||||
Use char because int might match the return type of a GCC
|
||||
builtin and then its argument prototype would still apply. */
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
char pthread_mutex_init ();
|
||||
int
|
||||
main ()
|
||||
{
|
||||
return pthread_mutex_init ();
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_link "$LINENO"; then :
|
||||
ac_cv_lib_c_pthread_mutex_init=yes
|
||||
else
|
||||
ac_cv_lib_c_pthread_mutex_init=no
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
LIBS=$ac_check_lib_save_LIBS
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_pthread_mutex_init" >&5
|
||||
$as_echo "$ac_cv_lib_c_pthread_mutex_init" >&6; }
|
||||
if test "x$ac_cv_lib_c_pthread_mutex_init" = xyes; then :
|
||||
tcl_ok=yes
|
||||
else
|
||||
tcl_ok=no
|
||||
fi
|
||||
|
||||
if test "$tcl_ok" = "no"; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lc_r" >&5
|
||||
$as_echo_n "checking for pthread_mutex_init in -lc_r... " >&6; }
|
||||
if ${ac_cv_lib_c_r_pthread_mutex_init+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
ac_check_lib_save_LIBS=$LIBS
|
||||
LIBS="-lc_r $LIBS"
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
|
||||
/* Override any GCC internal prototype to avoid an error.
|
||||
Use char because int might match the return type of a GCC
|
||||
builtin and then its argument prototype would still apply. */
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
char pthread_mutex_init ();
|
||||
int
|
||||
main ()
|
||||
{
|
||||
return pthread_mutex_init ();
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_link "$LINENO"; then :
|
||||
ac_cv_lib_c_r_pthread_mutex_init=yes
|
||||
else
|
||||
ac_cv_lib_c_r_pthread_mutex_init=no
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
LIBS=$ac_check_lib_save_LIBS
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_r_pthread_mutex_init" >&5
|
||||
$as_echo "$ac_cv_lib_c_r_pthread_mutex_init" >&6; }
|
||||
if test "x$ac_cv_lib_c_r_pthread_mutex_init" = xyes; then :
|
||||
tcl_ok=yes
|
||||
else
|
||||
tcl_ok=no
|
||||
fi
|
||||
|
||||
if test "$tcl_ok" = "yes"; then
|
||||
# The space is needed
|
||||
THREADS_LIBS=" -pthread"
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Don't know how to find pthread lib on your system - you must edit the LIBS in the Makefile..." >&5
|
||||
$as_echo "$as_me: WARNING: Don't know how to find pthread lib on your system - you must edit the LIBS in the Makefile..." >&2;}
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Does the pthread-implementation provide
|
||||
# 'pthread_attr_setstacksize' ?
|
||||
|
||||
ac_saved_libs=$LIBS
|
||||
LIBS="$LIBS $THREADS_LIBS"
|
||||
for ac_func in pthread_attr_setstacksize pthread_atfork
|
||||
do :
|
||||
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
|
||||
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
|
||||
if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
|
||||
_ACEOF
|
||||
|
||||
fi
|
||||
done
|
||||
|
||||
LIBS=$ac_saved_libs
|
||||
|
||||
|
||||
# Add the threads support libraries
|
||||
LIBS="$LIBS$THREADS_LIBS"
|
||||
|
||||
@@ -5033,7 +4976,7 @@ fi
|
||||
fi
|
||||
case $system in
|
||||
AIX-*)
|
||||
if test "${TCL_THREADS}" = "1" -a "$GCC" != "yes"; then :
|
||||
if test "$GCC" != "yes"; then :
|
||||
|
||||
# AIX requires the _r compiler when gcc isn't being used
|
||||
case "${CC}" in
|
||||
@@ -5235,9 +5178,6 @@ $as_echo "$ac_cv_cygwin" >&6; }
|
||||
if test "$ac_cv_cygwin" = "no"; then
|
||||
as_fn_error $? "${CC} is not a cygwin compiler." "$LINENO" 5
|
||||
fi
|
||||
if test "x${TCL_THREADS}" = "x0"; then
|
||||
as_fn_error $? "CYGWIN compile is only supported with --enable-threads" "$LINENO" 5
|
||||
fi
|
||||
do64bit_ok=yes
|
||||
if test "x${SHARED_BUILD}" = "x1"; then
|
||||
echo "running cd ../win; ${CONFIG_SHELL-/bin/sh} ./configure $ac_configure_args"
|
||||
@@ -5684,14 +5624,10 @@ fi
|
||||
SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so.${SHLIB_VERSION}'
|
||||
LDFLAGS="-Wl,-export-dynamic"
|
||||
CFLAGS_OPTIMIZE="-O2"
|
||||
if test "${TCL_THREADS}" = "1"; then :
|
||||
|
||||
# On OpenBSD: Compile with -pthread
|
||||
# Don't link with -lpthread
|
||||
LIBS=`echo $LIBS | sed s/-lpthread//`
|
||||
CFLAGS="$CFLAGS -pthread"
|
||||
|
||||
fi
|
||||
# On OpenBSD: Compile with -pthread
|
||||
# Don't link with -lpthread
|
||||
LIBS=`echo $LIBS | sed s/-lpthread//`
|
||||
CFLAGS="$CFLAGS -pthread"
|
||||
# OpenBSD doesn't do version numbers with dots.
|
||||
UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
|
||||
TCL_LIB_VERSIONS_OK=nodots
|
||||
@@ -5709,14 +5645,10 @@ fi
|
||||
CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
|
||||
fi
|
||||
LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
|
||||
if test "${TCL_THREADS}" = "1"; then :
|
||||
|
||||
# The -pthread needs to go in the CFLAGS, not LIBS
|
||||
LIBS=`echo $LIBS | sed s/-pthread//`
|
||||
CFLAGS="$CFLAGS -pthread"
|
||||
LDFLAGS="$LDFLAGS -pthread"
|
||||
|
||||
fi
|
||||
# The -pthread needs to go in the CFLAGS, not LIBS
|
||||
LIBS=`echo $LIBS | sed s/-pthread//`
|
||||
CFLAGS="$CFLAGS -pthread"
|
||||
LDFLAGS="$LDFLAGS -pthread"
|
||||
;;
|
||||
FreeBSD-*)
|
||||
# This configuration from FreeBSD Ports.
|
||||
@@ -5732,13 +5664,10 @@ fi
|
||||
CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
|
||||
LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
|
||||
fi
|
||||
if test "${TCL_THREADS}" = "1"; then :
|
||||
|
||||
# The -pthread needs to go in the LDFLAGS, not LIBS
|
||||
LIBS=`echo $LIBS | sed s/-pthread//`
|
||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||
LDFLAGS="$LDFLAGS $PTHREAD_LIBS"
|
||||
fi
|
||||
# The -pthread needs to go in the LDFLAGS, not LIBS
|
||||
LIBS=`echo $LIBS | sed s/-pthread//`
|
||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||
LDFLAGS="$LDFLAGS $PTHREAD_LIBS"
|
||||
case $system in
|
||||
FreeBSD-3.*)
|
||||
# Version numbers are dot-stripped by system policy.
|
||||
@@ -6100,21 +6029,17 @@ else
|
||||
CFLAGS="$CFLAGS -DHAVE_TZSET -std1 -ieee"
|
||||
fi
|
||||
# see pthread_intro(3) for pthread support on osf1, k.furukawa
|
||||
if test "${TCL_THREADS}" = 1; then :
|
||||
CFLAGS="$CFLAGS -DHAVE_PTHREAD_ATTR_SETSTACKSIZE"
|
||||
CFLAGS="$CFLAGS -DTCL_THREAD_STACK_MIN=PTHREAD_STACK_MIN*64"
|
||||
LIBS=`echo $LIBS | sed s/-lpthreads//`
|
||||
if test "$GCC" = yes; then :
|
||||
|
||||
CFLAGS="$CFLAGS -DHAVE_PTHREAD_ATTR_SETSTACKSIZE"
|
||||
CFLAGS="$CFLAGS -DTCL_THREAD_STACK_MIN=PTHREAD_STACK_MIN*64"
|
||||
LIBS=`echo $LIBS | sed s/-lpthreads//`
|
||||
if test "$GCC" = yes; then :
|
||||
|
||||
LIBS="$LIBS -lpthread -lmach -lexc"
|
||||
LIBS="$LIBS -lpthread -lmach -lexc"
|
||||
|
||||
else
|
||||
|
||||
CFLAGS="$CFLAGS -pthread"
|
||||
LDFLAGS="$LDFLAGS -pthread"
|
||||
|
||||
fi
|
||||
CFLAGS="$CFLAGS -pthread"
|
||||
LDFLAGS="$LDFLAGS -pthread"
|
||||
|
||||
fi
|
||||
;;
|
||||
@@ -7373,7 +7298,7 @@ $as_echo "#define NO_UNAME 1" >>confdefs.h
|
||||
fi
|
||||
|
||||
|
||||
if test "`uname -s`" = "Darwin" && test "${TCL_THREADS}" = 1 && \
|
||||
if test "`uname -s`" = "Darwin" && \
|
||||
test "`uname -r | awk -F. '{print $1}'`" -lt 7; then
|
||||
# prior to Darwin 7, realpath is not threadsafe, so don't
|
||||
# use it when threads are enabled, c.f. bug # 711232
|
||||
@@ -7496,8 +7421,7 @@ fi
|
||||
# Look for thread-safe variants of some library functions.
|
||||
#--------------------------------------------------------------------
|
||||
|
||||
if test "${TCL_THREADS}" = 1; then
|
||||
ac_fn_c_check_func "$LINENO" "getpwuid_r" "ac_cv_func_getpwuid_r"
|
||||
ac_fn_c_check_func "$LINENO" "getpwuid_r" "ac_cv_func_getpwuid_r"
|
||||
if test "x$ac_cv_func_getpwuid_r" = xyes; then :
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for getpwuid_r with 5 args" >&5
|
||||
@@ -7593,7 +7517,7 @@ $as_echo "#define HAVE_GETPWUID_R 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
|
||||
ac_fn_c_check_func "$LINENO" "getpwnam_r" "ac_cv_func_getpwnam_r"
|
||||
ac_fn_c_check_func "$LINENO" "getpwnam_r" "ac_cv_func_getpwnam_r"
|
||||
if test "x$ac_cv_func_getpwnam_r" = xyes; then :
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for getpwnam_r with 5 args" >&5
|
||||
@@ -7689,7 +7613,7 @@ $as_echo "#define HAVE_GETPWNAM_R 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
|
||||
ac_fn_c_check_func "$LINENO" "getgrgid_r" "ac_cv_func_getgrgid_r"
|
||||
ac_fn_c_check_func "$LINENO" "getgrgid_r" "ac_cv_func_getgrgid_r"
|
||||
if test "x$ac_cv_func_getgrgid_r" = xyes; then :
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for getgrgid_r with 5 args" >&5
|
||||
@@ -7785,7 +7709,7 @@ $as_echo "#define HAVE_GETGRGID_R 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
|
||||
ac_fn_c_check_func "$LINENO" "getgrnam_r" "ac_cv_func_getgrnam_r"
|
||||
ac_fn_c_check_func "$LINENO" "getgrnam_r" "ac_cv_func_getgrnam_r"
|
||||
if test "x$ac_cv_func_getgrnam_r" = xyes; then :
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for getgrnam_r with 5 args" >&5
|
||||
@@ -7881,11 +7805,11 @@ $as_echo "#define HAVE_GETGRNAM_R 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
|
||||
if test "`uname -s`" = "Darwin" && \
|
||||
test "`uname -r | awk -F. '{print $1}'`" -gt 5; then
|
||||
# Starting with Darwin 6 (Mac OSX 10.2), gethostbyX
|
||||
# are actually MT-safe as they always return pointers
|
||||
# from TSD instead of static storage.
|
||||
if test "`uname -s`" = "Darwin" && \
|
||||
test "`uname -r | awk -F. '{print $1}'`" -gt 5; then
|
||||
# Starting with Darwin 6 (Mac OSX 10.2), gethostbyX
|
||||
# are actually MT-safe as they always return pointers
|
||||
# from TSD instead of static storage.
|
||||
|
||||
$as_echo "#define HAVE_MTSAFE_GETHOSTBYNAME 1" >>confdefs.h
|
||||
|
||||
@@ -7893,11 +7817,11 @@ $as_echo "#define HAVE_MTSAFE_GETHOSTBYNAME 1" >>confdefs.h
|
||||
$as_echo "#define HAVE_MTSAFE_GETHOSTBYADDR 1" >>confdefs.h
|
||||
|
||||
|
||||
elif test "`uname -s`" = "HP-UX" && \
|
||||
test "`uname -r|sed -e 's|B\.||' -e 's|\..*$||'`" -gt 10; then
|
||||
# Starting with HPUX 11.00 (we believe), gethostbyX
|
||||
# are actually MT-safe as they always return pointers
|
||||
# from TSD instead of static storage.
|
||||
elif test "`uname -s`" = "HP-UX" && \
|
||||
test "`uname -r|sed -e 's|B\.||' -e 's|\..*$||'`" -gt 10; then
|
||||
# Starting with HPUX 11.00 (we believe), gethostbyX
|
||||
# are actually MT-safe as they always return pointers
|
||||
# from TSD instead of static storage.
|
||||
|
||||
$as_echo "#define HAVE_MTSAFE_GETHOSTBYNAME 1" >>confdefs.h
|
||||
|
||||
@@ -7905,8 +7829,8 @@ $as_echo "#define HAVE_MTSAFE_GETHOSTBYNAME 1" >>confdefs.h
|
||||
$as_echo "#define HAVE_MTSAFE_GETHOSTBYADDR 1" >>confdefs.h
|
||||
|
||||
|
||||
else
|
||||
ac_fn_c_check_func "$LINENO" "gethostbyname_r" "ac_cv_func_gethostbyname_r"
|
||||
else
|
||||
ac_fn_c_check_func "$LINENO" "gethostbyname_r" "ac_cv_func_gethostbyname_r"
|
||||
if test "x$ac_cv_func_gethostbyname_r" = xyes; then :
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyname_r with 6 args" >&5
|
||||
@@ -8043,7 +7967,7 @@ $as_echo "#define HAVE_GETHOSTBYNAME_R 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
|
||||
ac_fn_c_check_func "$LINENO" "gethostbyaddr_r" "ac_cv_func_gethostbyaddr_r"
|
||||
ac_fn_c_check_func "$LINENO" "gethostbyaddr_r" "ac_cv_func_gethostbyaddr_r"
|
||||
if test "x$ac_cv_func_gethostbyaddr_r" = xyes; then :
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyaddr_r with 7 args" >&5
|
||||
@@ -8145,7 +8069,6 @@ $as_echo "#define HAVE_GETHOSTBYADDR_R 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
|
||||
fi
|
||||
fi
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
@@ -8337,10 +8260,6 @@ fi;;
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: OSX" >&5
|
||||
$as_echo "OSX" >&6; };;
|
||||
*)
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define NOTIFIER_SELECT 1
|
||||
_ACEOF
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5
|
||||
$as_echo "none" >&6; };;
|
||||
esac
|
||||
|
||||
+26
-35
@@ -119,12 +119,6 @@ if test -z "$no_pipe" && test -n "$GCC"; then
|
||||
fi
|
||||
fi
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
# Threads support
|
||||
#------------------------------------------------------------------------
|
||||
|
||||
SC_ENABLE_THREADS
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
# Embedded configuration information, encoding to use for the values, TIP #59
|
||||
#------------------------------------------------------------------------
|
||||
@@ -215,7 +209,7 @@ AC_CHECK_FUNC(getwd, , [AC_DEFINE(NO_GETWD, 1, [Do we have getwd()])])
|
||||
AC_CHECK_FUNC(wait3, , [AC_DEFINE(NO_WAIT3, 1, [Do we have wait3()])])
|
||||
AC_CHECK_FUNC(uname, , [AC_DEFINE(NO_UNAME, 1, [Do we have uname()])])
|
||||
|
||||
if test "`uname -s`" = "Darwin" && test "${TCL_THREADS}" = 1 && \
|
||||
if test "`uname -s`" = "Darwin" && \
|
||||
test "`uname -r | awk -F. '{print [$]1}'`" -lt 7; then
|
||||
# prior to Darwin 7, realpath is not threadsafe, so don't
|
||||
# use it when threads are enabled, c.f. bug # 711232
|
||||
@@ -229,35 +223,33 @@ SC_TCL_IPV6
|
||||
# Look for thread-safe variants of some library functions.
|
||||
#--------------------------------------------------------------------
|
||||
|
||||
if test "${TCL_THREADS}" = 1; then
|
||||
SC_TCL_GETPWUID_R
|
||||
SC_TCL_GETPWNAM_R
|
||||
SC_TCL_GETGRGID_R
|
||||
SC_TCL_GETGRNAM_R
|
||||
if test "`uname -s`" = "Darwin" && \
|
||||
test "`uname -r | awk -F. '{print [$]1}'`" -gt 5; then
|
||||
# Starting with Darwin 6 (Mac OSX 10.2), gethostbyX
|
||||
# are actually MT-safe as they always return pointers
|
||||
# from TSD instead of static storage.
|
||||
AC_DEFINE(HAVE_MTSAFE_GETHOSTBYNAME, 1,
|
||||
[Do we have MT-safe gethostbyname() ?])
|
||||
AC_DEFINE(HAVE_MTSAFE_GETHOSTBYADDR, 1,
|
||||
[Do we have MT-safe gethostbyaddr() ?])
|
||||
SC_TCL_GETPWUID_R
|
||||
SC_TCL_GETPWNAM_R
|
||||
SC_TCL_GETGRGID_R
|
||||
SC_TCL_GETGRNAM_R
|
||||
if test "`uname -s`" = "Darwin" && \
|
||||
test "`uname -r | awk -F. '{print [$]1}'`" -gt 5; then
|
||||
# Starting with Darwin 6 (Mac OSX 10.2), gethostbyX
|
||||
# are actually MT-safe as they always return pointers
|
||||
# from TSD instead of static storage.
|
||||
AC_DEFINE(HAVE_MTSAFE_GETHOSTBYNAME, 1,
|
||||
[Do we have MT-safe gethostbyname() ?])
|
||||
AC_DEFINE(HAVE_MTSAFE_GETHOSTBYADDR, 1,
|
||||
[Do we have MT-safe gethostbyaddr() ?])
|
||||
|
||||
elif test "`uname -s`" = "HP-UX" && \
|
||||
test "`uname -r|sed -e 's|B\.||' -e 's|\..*$||'`" -gt 10; then
|
||||
# Starting with HPUX 11.00 (we believe), gethostbyX
|
||||
# are actually MT-safe as they always return pointers
|
||||
# from TSD instead of static storage.
|
||||
AC_DEFINE(HAVE_MTSAFE_GETHOSTBYNAME, 1,
|
||||
[Do we have MT-safe gethostbyname() ?])
|
||||
AC_DEFINE(HAVE_MTSAFE_GETHOSTBYADDR, 1,
|
||||
[Do we have MT-safe gethostbyaddr() ?])
|
||||
elif test "`uname -s`" = "HP-UX" && \
|
||||
test "`uname -r|sed -e 's|B\.||' -e 's|\..*$||'`" -gt 10; then
|
||||
# Starting with HPUX 11.00 (we believe), gethostbyX
|
||||
# are actually MT-safe as they always return pointers
|
||||
# from TSD instead of static storage.
|
||||
AC_DEFINE(HAVE_MTSAFE_GETHOSTBYNAME, 1,
|
||||
[Do we have MT-safe gethostbyname() ?])
|
||||
AC_DEFINE(HAVE_MTSAFE_GETHOSTBYADDR, 1,
|
||||
[Do we have MT-safe gethostbyaddr() ?])
|
||||
|
||||
else
|
||||
SC_TCL_GETHOSTBYNAME_R
|
||||
SC_TCL_GETHOSTBYADDR_R
|
||||
fi
|
||||
else
|
||||
SC_TCL_GETHOSTBYNAME_R
|
||||
SC_TCL_GETHOSTBYADDR_R
|
||||
fi
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
@@ -327,7 +319,6 @@ case x`uname -s` in
|
||||
# of wider impact).
|
||||
AC_MSG_RESULT([OSX]);;
|
||||
*)
|
||||
AC_DEFINE_UNQUOTED(NOTIFIER_SELECT)
|
||||
AC_MSG_RESULT([none]);;
|
||||
esac
|
||||
|
||||
|
||||
+75
-139
@@ -592,113 +592,6 @@ AC_DEFUN([SC_ENABLE_FRAMEWORK], [
|
||||
fi
|
||||
])
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
# SC_ENABLE_THREADS --
|
||||
#
|
||||
# Specify if thread support should be enabled
|
||||
#
|
||||
# Arguments:
|
||||
# none
|
||||
#
|
||||
# Results:
|
||||
#
|
||||
# Adds the following arguments to configure:
|
||||
# --enable-threads
|
||||
#
|
||||
# Sets the following vars:
|
||||
# THREADS_LIBS Thread library(s)
|
||||
#
|
||||
# Defines the following vars:
|
||||
# TCL_THREADS
|
||||
# _REENTRANT
|
||||
# _THREAD_SAFE
|
||||
#------------------------------------------------------------------------
|
||||
|
||||
AC_DEFUN([SC_ENABLE_THREADS], [
|
||||
AC_ARG_ENABLE(threads,
|
||||
AC_HELP_STRING([--enable-threads],
|
||||
[build with threads (default: on)]),
|
||||
[tcl_ok=$enableval], [tcl_ok=yes])
|
||||
|
||||
if test "${TCL_THREADS}" = 1; then
|
||||
tcl_threaded_core=1;
|
||||
fi
|
||||
|
||||
if test "$tcl_ok" = "yes" -o "${TCL_THREADS}" = 1; then
|
||||
TCL_THREADS=1
|
||||
# USE_THREAD_ALLOC tells us to try the special thread-based
|
||||
# allocator that significantly reduces lock contention
|
||||
AC_DEFINE(USE_THREAD_ALLOC, 1,
|
||||
[Do we want to use the threaded memory allocator?])
|
||||
AC_DEFINE(_REENTRANT, 1, [Do we want the reentrant OS API?])
|
||||
if test "`uname -s`" = "SunOS" ; then
|
||||
AC_DEFINE(_POSIX_PTHREAD_SEMANTICS, 1,
|
||||
[Do we really want to follow the standard? Yes we do!])
|
||||
fi
|
||||
AC_DEFINE(_THREAD_SAFE, 1, [Do we want the thread-safe OS API?])
|
||||
AC_CHECK_LIB(pthread,pthread_mutex_init,tcl_ok=yes,tcl_ok=no)
|
||||
if test "$tcl_ok" = "no"; then
|
||||
# Check a little harder for __pthread_mutex_init in the same
|
||||
# library, as some systems hide it there until pthread.h is
|
||||
# defined. We could alternatively do an AC_TRY_COMPILE with
|
||||
# pthread.h, but that will work with libpthread really doesn't
|
||||
# exist, like AIX 4.2. [Bug: 4359]
|
||||
AC_CHECK_LIB(pthread, __pthread_mutex_init,
|
||||
tcl_ok=yes, tcl_ok=no)
|
||||
fi
|
||||
|
||||
if test "$tcl_ok" = "yes"; then
|
||||
# The space is needed
|
||||
THREADS_LIBS=" -lpthread"
|
||||
else
|
||||
AC_CHECK_LIB(pthreads, pthread_mutex_init,
|
||||
tcl_ok=yes, tcl_ok=no)
|
||||
if test "$tcl_ok" = "yes"; then
|
||||
# The space is needed
|
||||
THREADS_LIBS=" -lpthreads"
|
||||
else
|
||||
AC_CHECK_LIB(c, pthread_mutex_init,
|
||||
tcl_ok=yes, tcl_ok=no)
|
||||
if test "$tcl_ok" = "no"; then
|
||||
AC_CHECK_LIB(c_r, pthread_mutex_init,
|
||||
tcl_ok=yes, tcl_ok=no)
|
||||
if test "$tcl_ok" = "yes"; then
|
||||
# The space is needed
|
||||
THREADS_LIBS=" -pthread"
|
||||
else
|
||||
TCL_THREADS=0
|
||||
AC_MSG_WARN([Don't know how to find pthread lib on your system - you must disable thread support or edit the LIBS in the Makefile...])
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Does the pthread-implementation provide
|
||||
# 'pthread_attr_setstacksize' ?
|
||||
|
||||
ac_saved_libs=$LIBS
|
||||
LIBS="$LIBS $THREADS_LIBS"
|
||||
AC_CHECK_FUNCS(pthread_attr_setstacksize pthread_atfork)
|
||||
LIBS=$ac_saved_libs
|
||||
else
|
||||
TCL_THREADS=0
|
||||
fi
|
||||
# Do checking message here to not mess up interleaved configure output
|
||||
AC_MSG_CHECKING([for building with threads])
|
||||
if test "${TCL_THREADS}" = 1; then
|
||||
AC_DEFINE(TCL_THREADS, 1, [Are we building with threads enabled?])
|
||||
if test "${tcl_threaded_core}" = 1; then
|
||||
AC_MSG_RESULT([yes (threaded core)])
|
||||
else
|
||||
AC_MSG_RESULT([yes])
|
||||
fi
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
fi
|
||||
|
||||
AC_SUBST(TCL_THREADS)
|
||||
])
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
# SC_ENABLE_SYMBOLS --
|
||||
#
|
||||
@@ -1101,7 +994,7 @@ AC_DEFUN([SC_CONFIG_CFLAGS], [
|
||||
AS_IF([test "x${SHLIB_VERSION}" = x], [SHLIB_VERSION="1.0"])
|
||||
case $system in
|
||||
AIX-*)
|
||||
AS_IF([test "${TCL_THREADS}" = "1" -a "$GCC" != "yes"], [
|
||||
AS_IF([test "$GCC" != "yes"], [
|
||||
# AIX requires the _r compiler when gcc isn't being used
|
||||
case "${CC}" in
|
||||
*_r|*_r\ *)
|
||||
@@ -1222,9 +1115,6 @@ AC_DEFUN([SC_CONFIG_CFLAGS], [
|
||||
if test "$ac_cv_cygwin" = "no"; then
|
||||
AC_MSG_ERROR([${CC} is not a cygwin compiler.])
|
||||
fi
|
||||
if test "x${TCL_THREADS}" = "x0"; then
|
||||
AC_MSG_ERROR([CYGWIN compile is only supported with --enable-threads])
|
||||
fi
|
||||
do64bit_ok=yes
|
||||
if test "x${SHARED_BUILD}" = "x1"; then
|
||||
echo "running cd ../win; ${CONFIG_SHELL-/bin/sh} ./configure $ac_configure_args"
|
||||
@@ -1454,12 +1344,10 @@ AC_DEFUN([SC_CONFIG_CFLAGS], [
|
||||
SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so.${SHLIB_VERSION}'
|
||||
LDFLAGS="-Wl,-export-dynamic"
|
||||
CFLAGS_OPTIMIZE="-O2"
|
||||
AS_IF([test "${TCL_THREADS}" = "1"], [
|
||||
# On OpenBSD: Compile with -pthread
|
||||
# Don't link with -lpthread
|
||||
LIBS=`echo $LIBS | sed s/-lpthread//`
|
||||
CFLAGS="$CFLAGS -pthread"
|
||||
])
|
||||
# On OpenBSD: Compile with -pthread
|
||||
# Don't link with -lpthread
|
||||
LIBS=`echo $LIBS | sed s/-lpthread//`
|
||||
CFLAGS="$CFLAGS -pthread"
|
||||
# OpenBSD doesn't do version numbers with dots.
|
||||
UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
|
||||
TCL_LIB_VERSIONS_OK=nodots
|
||||
@@ -1475,12 +1363,10 @@ AC_DEFUN([SC_CONFIG_CFLAGS], [
|
||||
AS_IF([test $doRpath = yes], [
|
||||
CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])
|
||||
LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
|
||||
AS_IF([test "${TCL_THREADS}" = "1"], [
|
||||
# The -pthread needs to go in the CFLAGS, not LIBS
|
||||
LIBS=`echo $LIBS | sed s/-pthread//`
|
||||
CFLAGS="$CFLAGS -pthread"
|
||||
LDFLAGS="$LDFLAGS -pthread"
|
||||
])
|
||||
# The -pthread needs to go in the CFLAGS, not LIBS
|
||||
LIBS=`echo $LIBS | sed s/-pthread//`
|
||||
CFLAGS="$CFLAGS -pthread"
|
||||
LDFLAGS="$LDFLAGS -pthread"
|
||||
;;
|
||||
FreeBSD-*)
|
||||
# This configuration from FreeBSD Ports.
|
||||
@@ -1494,11 +1380,10 @@ AC_DEFUN([SC_CONFIG_CFLAGS], [
|
||||
AS_IF([test $doRpath = yes], [
|
||||
CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
|
||||
LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])
|
||||
AS_IF([test "${TCL_THREADS}" = "1"], [
|
||||
# The -pthread needs to go in the LDFLAGS, not LIBS
|
||||
LIBS=`echo $LIBS | sed s/-pthread//`
|
||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||
LDFLAGS="$LDFLAGS $PTHREAD_LIBS"])
|
||||
# The -pthread needs to go in the LDFLAGS, not LIBS
|
||||
LIBS=`echo $LIBS | sed s/-pthread//`
|
||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||
LDFLAGS="$LDFLAGS $PTHREAD_LIBS"
|
||||
case $system in
|
||||
FreeBSD-3.*)
|
||||
# Version numbers are dot-stripped by system policy.
|
||||
@@ -1670,16 +1555,14 @@ AC_DEFUN([SC_CONFIG_CFLAGS], [
|
||||
AS_IF([test "$GCC" = yes], [CFLAGS="$CFLAGS -mieee"], [
|
||||
CFLAGS="$CFLAGS -DHAVE_TZSET -std1 -ieee"])
|
||||
# see pthread_intro(3) for pthread support on osf1, k.furukawa
|
||||
AS_IF([test "${TCL_THREADS}" = 1], [
|
||||
CFLAGS="$CFLAGS -DHAVE_PTHREAD_ATTR_SETSTACKSIZE"
|
||||
CFLAGS="$CFLAGS -DTCL_THREAD_STACK_MIN=PTHREAD_STACK_MIN*64"
|
||||
LIBS=`echo $LIBS | sed s/-lpthreads//`
|
||||
AS_IF([test "$GCC" = yes], [
|
||||
LIBS="$LIBS -lpthread -lmach -lexc"
|
||||
], [
|
||||
CFLAGS="$CFLAGS -pthread"
|
||||
LDFLAGS="$LDFLAGS -pthread"
|
||||
])
|
||||
CFLAGS="$CFLAGS -DHAVE_PTHREAD_ATTR_SETSTACKSIZE"
|
||||
CFLAGS="$CFLAGS -DTCL_THREAD_STACK_MIN=PTHREAD_STACK_MIN*64"
|
||||
LIBS=`echo $LIBS | sed s/-lpthreads//`
|
||||
AS_IF([test "$GCC" = yes], [
|
||||
LIBS="$LIBS -lpthread -lmach -lexc"
|
||||
], [
|
||||
CFLAGS="$CFLAGS -pthread"
|
||||
LDFLAGS="$LDFLAGS -pthread"
|
||||
])
|
||||
;;
|
||||
QNX-6*)
|
||||
@@ -2350,13 +2233,20 @@ AC_DEFUN([SC_BUGGY_STRTOD], [
|
||||
#
|
||||
# Search for the libraries needed to link the Tcl shell.
|
||||
# Things like the math library (-lm) and socket stuff (-lsocket vs.
|
||||
# -lnsl) are dealt with here.
|
||||
# -lnsl) or thread library (-lpthread) are dealt with here.
|
||||
#
|
||||
# Arguments:
|
||||
# None.
|
||||
#
|
||||
# Results:
|
||||
#
|
||||
# Sets the following vars:
|
||||
# THREADS_LIBS Thread library(s)
|
||||
#
|
||||
# Defines the following vars:
|
||||
# _REENTRANT
|
||||
# _THREAD_SAFE
|
||||
#
|
||||
# Might append to the following vars:
|
||||
# LIBS
|
||||
# MATH_LIBS
|
||||
@@ -2414,6 +2304,52 @@ AC_DEFUN([SC_TCL_LINK_LIBS], [
|
||||
fi
|
||||
AC_CHECK_FUNC(gethostbyname, , [AC_CHECK_LIB(nsl, gethostbyname,
|
||||
[LIBS="$LIBS -lnsl"])])
|
||||
|
||||
AC_DEFINE(_REENTRANT, 1, [Do we want the reentrant OS API?])
|
||||
AC_DEFINE(_THREAD_SAFE, 1, [Do we want the thread-safe OS API?])
|
||||
AC_CHECK_LIB(pthread,pthread_mutex_init,tcl_ok=yes,tcl_ok=no)
|
||||
if test "$tcl_ok" = "no"; then
|
||||
# Check a little harder for __pthread_mutex_init in the same
|
||||
# library, as some systems hide it there until pthread.h is
|
||||
# defined. We could alternatively do an AC_TRY_COMPILE with
|
||||
# pthread.h, but that will work with libpthread really doesn't
|
||||
# exist, like AIX 4.2. [Bug: 4359]
|
||||
AC_CHECK_LIB(pthread, __pthread_mutex_init,
|
||||
tcl_ok=yes, tcl_ok=no)
|
||||
fi
|
||||
|
||||
if test "$tcl_ok" = "yes"; then
|
||||
# The space is needed
|
||||
THREADS_LIBS=" -lpthread"
|
||||
else
|
||||
AC_CHECK_LIB(pthreads, pthread_mutex_init,
|
||||
_ok=yes, tcl_ok=no)
|
||||
if test "$tcl_ok" = "yes"; then
|
||||
# The space is needed
|
||||
THREADS_LIBS=" -lpthreads"
|
||||
else
|
||||
AC_CHECK_LIB(c, pthread_mutex_init,
|
||||
tcl_ok=yes, tcl_ok=no)
|
||||
if test "$tcl_ok" = "no"; then
|
||||
AC_CHECK_LIB(c_r, pthread_mutex_init,
|
||||
tcl_ok=yes, tcl_ok=no)
|
||||
if test "$tcl_ok" = "yes"; then
|
||||
# The space is needed
|
||||
THREADS_LIBS=" -pthread"
|
||||
else
|
||||
AC_MSG_WARN([Don't know how to find pthread lib on your system - you must edit the LIBS in the Makefile...])
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Does the pthread-implementation provide
|
||||
# 'pthread_attr_setstacksize' ?
|
||||
|
||||
ac_saved_libs=$LIBS
|
||||
LIBS="$LIBS $THREADS_LIBS"
|
||||
AC_CHECK_FUNCS(pthread_attr_setstacksize pthread_atfork)
|
||||
LIBS=$ac_saved_libs
|
||||
])
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
|
||||
@@ -385,9 +385,6 @@
|
||||
/* What is the default extension for shared libraries? */
|
||||
#undef TCL_SHLIB_EXT
|
||||
|
||||
/* Are we building with threads enabled? */
|
||||
#undef TCL_THREADS
|
||||
|
||||
/* Do we allow unloading of shared libraries? */
|
||||
#undef TCL_UNLOAD_DLLS
|
||||
|
||||
|
||||
@@ -164,6 +164,3 @@ TCL_BUILD_STUB_LIB_PATH='@TCL_BUILD_STUB_LIB_PATH@'
|
||||
|
||||
# Path to the Tcl stub library in the install directory.
|
||||
TCL_STUB_LIB_PATH='@TCL_STUB_LIB_PATH@'
|
||||
|
||||
# Flag, 1: we built Tcl with threads enabled, 0 we didn't
|
||||
TCL_THREADS=@TCL_THREADS@
|
||||
|
||||
@@ -12,10 +12,10 @@
|
||||
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
*/
|
||||
|
||||
#ifdef NOTIFIER_EPOLL
|
||||
#include "tclInt.h"
|
||||
#if defined(NOTIFIER_EPOLL) && TCL_THREADS
|
||||
|
||||
#define _GNU_SOURCE /* For pipe2(2) */
|
||||
#include "tclInt.h"
|
||||
#ifndef HAVE_COREFOUNDATION /* Darwin/Mac OS X CoreFoundation notifier is
|
||||
* in tclMacOSXNotify.c */
|
||||
#include <fcntl.h>
|
||||
@@ -88,6 +88,7 @@ typedef struct {
|
||||
|
||||
LIST_HEAD(PlatformReadyFileHandlerList, FileHandler);
|
||||
typedef struct ThreadSpecificData {
|
||||
FileHandler *triggerFilePtr;
|
||||
FileHandler *firstFileHandlerPtr;
|
||||
/* Pointer to head of file handler list. */
|
||||
struct PlatformReadyFileHandlerList firstReadyFileHandlerPtr;
|
||||
@@ -306,6 +307,8 @@ PlatformEventsFinalize(
|
||||
tsdPtr->triggerPipe[1] = -1;
|
||||
}
|
||||
#endif /* HAVE_EVENTFD */
|
||||
ckfree(tsdPtr->triggerFilePtr->pedPtr);
|
||||
ckfree(tsdPtr->triggerFilePtr);
|
||||
if (tsdPtr->eventsFd > 0) {
|
||||
close(tsdPtr->eventsFd);
|
||||
tsdPtr->eventsFd = 0;
|
||||
@@ -368,6 +371,7 @@ PlatformEventsInit(
|
||||
}
|
||||
filePtr->fd = tsdPtr->triggerPipe[0];
|
||||
#endif
|
||||
tsdPtr->triggerFilePtr = filePtr;
|
||||
if ((tsdPtr->eventsFd = epoll_create1(EPOLL_CLOEXEC)) == -1) {
|
||||
Tcl_Panic("epoll_create1: %s", strerror(errno));
|
||||
}
|
||||
|
||||
@@ -13,9 +13,9 @@
|
||||
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
*/
|
||||
|
||||
#ifdef NOTIFIER_KQUEUE
|
||||
|
||||
#include "tclInt.h"
|
||||
#if defined(NOTIFIER_KQUEUE) && TCL_THREADS
|
||||
|
||||
#ifndef HAVE_COREFOUNDATION /* Darwin/Mac OS X CoreFoundation notifier is
|
||||
* in tclMacOSXNotify.c */
|
||||
#include <signal.h>
|
||||
|
||||
+14
-14
@@ -11,9 +11,9 @@
|
||||
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
*/
|
||||
|
||||
#if !defined(NOTIFIER_EPOLL) && !defined(NOTIFIER_KQUEUE)
|
||||
|
||||
#include "tclInt.h"
|
||||
#if (!defined(NOTIFIER_EPOLL) && !defined(NOTIFIER_KQUEUE)) || !TCL_THREADS
|
||||
|
||||
#ifndef HAVE_COREFOUNDATION /* Darwin/Mac OS X CoreFoundation notifier is
|
||||
* in tclMacOSXNotify.c */
|
||||
#include <signal.h>
|
||||
@@ -81,7 +81,7 @@ typedef struct ThreadSpecificData {
|
||||
int numFdBits; /* Number of valid bits in checkMasks (one
|
||||
* more than highest fd for which
|
||||
* Tcl_WatchFile has been called). */
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
int onList; /* True if it is in this list */
|
||||
unsigned int pollState; /* pollState is used to implement a polling
|
||||
* handshake between each thread and the
|
||||
@@ -112,7 +112,7 @@ typedef struct ThreadSpecificData {
|
||||
|
||||
static Tcl_ThreadDataKey dataKey;
|
||||
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
/*
|
||||
* The following static indicates the number of threads that have initialized
|
||||
* notifiers.
|
||||
@@ -193,7 +193,7 @@ static Tcl_ThreadId notifierThread;
|
||||
* Static routines defined in this file.
|
||||
*/
|
||||
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
static TCL_NORETURN void NotifierThreadProc(ClientData clientData);
|
||||
#if defined(HAVE_PTHREAD_ATFORK)
|
||||
static int atForkInit = 0;
|
||||
@@ -206,7 +206,7 @@ static int FileHandlerEventProc(Tcl_Event *evPtr, int flags);
|
||||
* Import of Windows API when building threaded with Cygwin.
|
||||
*/
|
||||
|
||||
#if defined(TCL_THREADS) && defined(__CYGWIN__)
|
||||
#if defined(__CYGWIN__)
|
||||
typedef struct {
|
||||
void *hwnd;
|
||||
unsigned int *message;
|
||||
@@ -285,7 +285,7 @@ Tcl_InitNotifier(void)
|
||||
} else {
|
||||
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
|
||||
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
tsdPtr->eventReady = 0;
|
||||
|
||||
/*
|
||||
@@ -370,7 +370,7 @@ Tcl_FinalizeNotifier(
|
||||
tclNotifierHooks.finalizeNotifierProc(clientData);
|
||||
return;
|
||||
} else {
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
|
||||
|
||||
pthread_mutex_lock(¬ifierInitMutex);
|
||||
@@ -587,7 +587,7 @@ Tcl_DeleteFileHandler(
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(TCL_THREADS) && defined(__CYGWIN__)
|
||||
#if defined(__CYGWIN__)
|
||||
|
||||
static DWORD __stdcall
|
||||
NotifierProc(
|
||||
@@ -640,7 +640,7 @@ Tcl_WaitForEvent(
|
||||
FileHandler *filePtr;
|
||||
int mask;
|
||||
Tcl_Time vTime;
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
int waitForFiles;
|
||||
# ifdef __CYGWIN__
|
||||
MSG msg;
|
||||
@@ -675,7 +675,7 @@ Tcl_WaitForEvent(
|
||||
tclScaleTimeProcPtr(&vTime, tclTimeClientData);
|
||||
timePtr = &vTime;
|
||||
}
|
||||
#ifndef TCL_THREADS
|
||||
#if !TCL_THREADS
|
||||
timeout.tv_sec = timePtr->sec;
|
||||
timeout.tv_usec = timePtr->usec;
|
||||
timeoutPtr = &timeout;
|
||||
@@ -694,7 +694,7 @@ Tcl_WaitForEvent(
|
||||
#endif /* !TCL_THREADS */
|
||||
}
|
||||
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
/*
|
||||
* Start notifier thread and place this thread on the list of
|
||||
* interested threads, signal the notifier thread, and wait for a
|
||||
@@ -885,14 +885,14 @@ Tcl_WaitForEvent(
|
||||
}
|
||||
filePtr->readyMask = mask;
|
||||
}
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
pthread_mutex_unlock(¬ifierMutex);
|
||||
#endif /* TCL_THREADS */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
* library calls.
|
||||
*/
|
||||
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
|
||||
typedef struct {
|
||||
struct passwd pwd;
|
||||
@@ -182,7 +182,7 @@ struct passwd *
|
||||
TclpGetPwNam(
|
||||
const char *name)
|
||||
{
|
||||
#if !defined(TCL_THREADS)
|
||||
#if !TCL_THREADS
|
||||
return getpwnam(name);
|
||||
#else
|
||||
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
|
||||
@@ -262,7 +262,7 @@ struct passwd *
|
||||
TclpGetPwUid(
|
||||
uid_t uid)
|
||||
{
|
||||
#if !defined(TCL_THREADS)
|
||||
#if !TCL_THREADS
|
||||
return getpwuid(uid);
|
||||
#else
|
||||
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
|
||||
@@ -365,7 +365,7 @@ struct group *
|
||||
TclpGetGrNam(
|
||||
const char *name)
|
||||
{
|
||||
#if !defined(TCL_THREADS)
|
||||
#if !TCL_THREADS
|
||||
return getgrnam(name);
|
||||
#else
|
||||
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
|
||||
@@ -445,7 +445,7 @@ struct group *
|
||||
TclpGetGrGid(
|
||||
gid_t gid)
|
||||
{
|
||||
#if !defined(TCL_THREADS)
|
||||
#if !TCL_THREADS
|
||||
return getgrgid(gid);
|
||||
#else
|
||||
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
|
||||
@@ -548,7 +548,7 @@ struct hostent *
|
||||
TclpGetHostByName(
|
||||
const char *name)
|
||||
{
|
||||
#if !defined(TCL_THREADS) || defined(HAVE_MTSAFE_GETHOSTBYNAME)
|
||||
#if !TCL_THREADS || defined(HAVE_MTSAFE_GETHOSTBYNAME)
|
||||
return gethostbyname(name);
|
||||
#else
|
||||
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
|
||||
@@ -618,7 +618,7 @@ TclpGetHostByAddr(
|
||||
int length,
|
||||
int type)
|
||||
{
|
||||
#if !defined(TCL_THREADS) || defined(HAVE_MTSAFE_GETHOSTBYADDR)
|
||||
#if !TCL_THREADS || defined(HAVE_MTSAFE_GETHOSTBYADDR)
|
||||
return gethostbyaddr(addr, length, type);
|
||||
#else
|
||||
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
|
||||
|
||||
+16
-16
@@ -256,7 +256,7 @@ Realpath(
|
||||
#endif /* PURIFY */
|
||||
|
||||
#ifndef NO_REALPATH
|
||||
#if defined(__APPLE__) && defined(TCL_THREADS) && \
|
||||
#if defined(__APPLE__) && TCL_THREADS && \
|
||||
defined(MAC_OS_X_VERSION_MIN_REQUIRED) && \
|
||||
MAC_OS_X_VERSION_MIN_REQUIRED < 1030
|
||||
/*
|
||||
@@ -369,13 +369,13 @@ DoRenameFile(
|
||||
|
||||
if (errno == EINVAL && haveRealpath) {
|
||||
char srcPath[MAXPATHLEN], dstPath[MAXPATHLEN];
|
||||
DIR *dirPtr;
|
||||
TclDIR *dirPtr;
|
||||
Tcl_DirEntry *dirEntPtr;
|
||||
|
||||
if ((Realpath((char *) src, srcPath) != NULL) /* INTL: Native. */
|
||||
&& (Realpath((char *) dst, dstPath) != NULL) /* INTL: Native */
|
||||
&& (strncmp(srcPath, dstPath, strlen(srcPath)) != 0)) {
|
||||
dirPtr = opendir(dst); /* INTL: Native. */
|
||||
dirPtr = TclOSopendir(dst); /* INTL: Native. */
|
||||
if (dirPtr != NULL) {
|
||||
while (1) {
|
||||
dirEntPtr = TclOSreaddir(dirPtr); /* INTL: Native. */
|
||||
@@ -385,11 +385,11 @@ DoRenameFile(
|
||||
if ((strcmp(dirEntPtr->d_name, ".") != 0) &&
|
||||
(strcmp(dirEntPtr->d_name, "..") != 0)) {
|
||||
errno = EEXIST;
|
||||
closedir(dirPtr);
|
||||
TclOSclosedir(dirPtr);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
}
|
||||
closedir(dirPtr);
|
||||
TclOSclosedir(dirPtr);
|
||||
}
|
||||
}
|
||||
errno = EINVAL;
|
||||
@@ -965,7 +965,7 @@ TraverseUnixTree(
|
||||
#ifndef HAVE_FTS
|
||||
int numProcessed = 0;
|
||||
Tcl_DirEntry *dirEntPtr;
|
||||
DIR *dirPtr;
|
||||
TclDIR *dirPtr;
|
||||
#else
|
||||
const char *paths[2] = {NULL, NULL};
|
||||
FTS *fts = NULL;
|
||||
@@ -990,7 +990,7 @@ TraverseUnixTree(
|
||||
errorPtr);
|
||||
}
|
||||
#ifndef HAVE_FTS
|
||||
dirPtr = opendir(source); /* INTL: Native. */
|
||||
dirPtr = TclOSopendir(source); /* INTL: Native. */
|
||||
if (dirPtr == NULL) {
|
||||
/*
|
||||
* Can't read directory
|
||||
@@ -1002,7 +1002,7 @@ TraverseUnixTree(
|
||||
result = traverseProc(sourcePtr, targetPtr, &statBuf, DOTREE_PRED,
|
||||
errorPtr);
|
||||
if (result != TCL_OK) {
|
||||
closedir(dirPtr);
|
||||
TclOSclosedir(dirPtr);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1052,11 +1052,11 @@ TraverseUnixTree(
|
||||
* NULL-return that may a symptom of a buggy readdir.
|
||||
*/
|
||||
|
||||
rewinddir(dirPtr);
|
||||
TclOSrewinddir(dirPtr);
|
||||
numProcessed = 0;
|
||||
}
|
||||
}
|
||||
closedir(dirPtr);
|
||||
TclOSclosedir(dirPtr);
|
||||
|
||||
/*
|
||||
* Strip off the trailing slash we added
|
||||
@@ -2302,7 +2302,8 @@ winPathFromObj(
|
||||
}
|
||||
|
||||
static const int attributeArray[] = {
|
||||
0x20, 0, 2, 0, 0, 1, 4};
|
||||
0x20, 0, 2, 0, 0, 1, 4
|
||||
};
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
@@ -2339,8 +2340,8 @@ GetUnixFileAttributes(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
*attributePtrPtr = Tcl_NewIntObj((fileAttributes&attributeArray[objIndex])!=0);
|
||||
|
||||
*attributePtrPtr = Tcl_NewIntObj(
|
||||
(fileAttributes & attributeArray[objIndex]) != 0);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
@@ -2397,7 +2398,7 @@ SetUnixFileAttributes(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
ckfree(winPath);
|
||||
ckfree(winPath);
|
||||
return TCL_OK;
|
||||
}
|
||||
#elif defined(HAVE_CHFLAGS) && defined(UF_IMMUTABLE)
|
||||
@@ -2439,8 +2440,7 @@ GetUnixFileAttributes(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
*attributePtrPtr = Tcl_NewBooleanObj(statBuf.st_flags&UF_IMMUTABLE);
|
||||
|
||||
*attributePtrPtr = Tcl_NewBooleanObj(statBuf.st_flags & UF_IMMUTABLE);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -259,7 +259,7 @@ TclpMatchInDirectory(
|
||||
Tcl_DecrRefCount(tailPtr);
|
||||
Tcl_DecrRefCount(fileNamePtr);
|
||||
} else {
|
||||
DIR *d;
|
||||
TclDIR *d;
|
||||
Tcl_DirEntry *entryPtr;
|
||||
const char *dirName;
|
||||
size_t dirLength, nativeDirLen;
|
||||
@@ -310,7 +310,7 @@ TclpMatchInDirectory(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
d = opendir(native); /* INTL: Native. */
|
||||
d = TclOSopendir(native); /* INTL: Native. */
|
||||
if (d == NULL) {
|
||||
Tcl_DStringFree(&ds);
|
||||
if (interp != NULL) {
|
||||
@@ -388,7 +388,7 @@ TclpMatchInDirectory(
|
||||
}
|
||||
}
|
||||
|
||||
closedir(d);
|
||||
TclOSclosedir(d);
|
||||
Tcl_DStringFree(&ds);
|
||||
Tcl_DStringFree(&dsOrig);
|
||||
Tcl_DecrRefCount(fileNamePtr);
|
||||
|
||||
+1
-1
@@ -316,7 +316,7 @@ static int MacOSXGetLibraryPath(Tcl_Interp *interp,
|
||||
#endif /* HAVE_COREFOUNDATION */
|
||||
#if defined(__APPLE__) && (defined(TCL_LOAD_FROM_MEMORY) || ( \
|
||||
defined(MAC_OS_X_VERSION_MIN_REQUIRED) && ( \
|
||||
(defined(TCL_THREADS) && MAC_OS_X_VERSION_MIN_REQUIRED < 1030) || \
|
||||
(TCL_THREADS && MAC_OS_X_VERSION_MIN_REQUIRED < 1030) || \
|
||||
(defined(__LP64__) && MAC_OS_X_VERSION_MIN_REQUIRED < 1050) || \
|
||||
(defined(HAVE_COREFOUNDATION) && MAC_OS_X_VERSION_MIN_REQUIRED < 1050)\
|
||||
)))
|
||||
|
||||
+14
-14
@@ -12,29 +12,30 @@
|
||||
*/
|
||||
|
||||
#include <poll.h>
|
||||
#include "tclInt.h"
|
||||
|
||||
/*
|
||||
* Static routines defined in this file.
|
||||
*/
|
||||
|
||||
#ifdef NOTIFIER_SELECT
|
||||
#ifdef TCL_THREADS
|
||||
static TCL_NORETURN void NotifierThreadProc(ClientData clientData);
|
||||
#if defined(HAVE_PTHREAD_ATFORK)
|
||||
static void AtForkChild(void);
|
||||
#endif /* HAVE_PTHREAD_ATFORK */
|
||||
#endif /* TCL_THREADS */
|
||||
#endif /* NOTIFIER_SELECT */
|
||||
static int FileHandlerEventProc(Tcl_Event *evPtr, int flags);
|
||||
#if !TCL_THREADS
|
||||
# undef NOTIFIER_EPOLL
|
||||
# undef NOTIFIER_KQUEUE
|
||||
# define NOTIFIER_SELECT
|
||||
#elif !defined(NOTIFIER_EPOLL) && !defined(NOTIFIER_KQUEUE)
|
||||
# define NOTIFIER_SELECT
|
||||
static TCL_NORETURN void NotifierThreadProc(ClientData clientData);
|
||||
# if defined(HAVE_PTHREAD_ATFORK)
|
||||
static void AtForkChild(void);
|
||||
# endif /* HAVE_PTHREAD_ATFORK */
|
||||
|
||||
#ifdef NOTIFIER_SELECT
|
||||
#if TCL_THREADS
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* StartNotifierThread --
|
||||
*
|
||||
* Start a notfier thread and wait for the notifier pipe to be created.
|
||||
* Start a notifier thread and wait for the notifier pipe to be created.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
@@ -70,7 +71,6 @@ StartNotifierThread(const char *proc)
|
||||
pthread_mutex_unlock(¬ifierInitMutex);
|
||||
}
|
||||
}
|
||||
#endif /* TCL_THREADS */
|
||||
#endif /* NOTIFIER_SELECT */
|
||||
|
||||
/*
|
||||
@@ -107,7 +107,7 @@ Tcl_AlertNotifier(
|
||||
return;
|
||||
} else {
|
||||
#ifdef NOTIFIER_SELECT
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
ThreadSpecificData *tsdPtr = clientData;
|
||||
|
||||
pthread_mutex_lock(¬ifierMutex);
|
||||
@@ -280,7 +280,7 @@ FileHandlerEventProc(
|
||||
}
|
||||
|
||||
#ifdef NOTIFIER_SELECT
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
|
||||
+11
-5
@@ -57,11 +57,19 @@
|
||||
*/
|
||||
|
||||
#ifdef HAVE_STRUCT_DIRENT64
|
||||
typedef DIR64 TclDIR;
|
||||
typedef struct dirent64 Tcl_DirEntry;
|
||||
# define TclOSreaddir readdir64
|
||||
# define TclOSopendir opendir64
|
||||
# define TclOSrewinddir rewinddir64
|
||||
# define TclOSclosedir closedir64
|
||||
#else
|
||||
typedef DIR TclDIR;
|
||||
typedef struct dirent Tcl_DirEntry;
|
||||
# define TclOSreaddir readdir
|
||||
# define TclOSopendir opendir
|
||||
# define TclOSrewinddir rewinddir
|
||||
# define TclOSclosedir closedir
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_TYPE_OFF64_T
|
||||
@@ -602,10 +610,8 @@ extern char ** environ;
|
||||
# undef HAVE_COPYFILE
|
||||
# endif
|
||||
# if MAC_OS_X_VERSION_MAX_ALLOWED < 1030
|
||||
# ifdef TCL_THREADS
|
||||
/* prior to 10.3, realpath is not threadsafe, c.f. bug 711232 */
|
||||
# define NO_REALPATH 1
|
||||
# endif
|
||||
/* prior to 10.3, realpath is not threadsafe, c.f. bug 711232 */
|
||||
# define NO_REALPATH 1
|
||||
# undef HAVE_LANGINFO
|
||||
# endif
|
||||
# endif /* MAC_OS_X_VERSION_MAX_ALLOWED */
|
||||
@@ -678,7 +684,7 @@ typedef int socklen_t;
|
||||
|
||||
#define TclpExit exit
|
||||
|
||||
#ifdef TCL_THREADS
|
||||
#if !defined(TCL_THREADS) || TCL_THREADS
|
||||
# include <pthread.h>
|
||||
#endif /* TCL_THREADS */
|
||||
|
||||
|
||||
+18
-16
@@ -13,7 +13,7 @@
|
||||
|
||||
#include "tclInt.h"
|
||||
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
typedef struct {
|
||||
@@ -74,7 +74,7 @@ TclpThreadCreate(
|
||||
int flags) /* Flags controlling behaviour of the new
|
||||
* thread. */
|
||||
{
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
pthread_attr_t attr;
|
||||
pthread_t theThread;
|
||||
int result;
|
||||
@@ -152,7 +152,7 @@ Tcl_JoinThread(
|
||||
* thread we wait upon will be written into.
|
||||
* May be NULL. */
|
||||
{
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
int result;
|
||||
unsigned long retcode, *retcodePtr = &retcode;
|
||||
|
||||
@@ -166,7 +166,6 @@ Tcl_JoinThread(
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef TCL_THREADS
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
@@ -187,9 +186,12 @@ void
|
||||
TclpThreadExit(
|
||||
int status)
|
||||
{
|
||||
#if TCL_THREADS
|
||||
pthread_exit(INT2PTR(status));
|
||||
}
|
||||
#else /* TCL_THREADS */
|
||||
exit(status);
|
||||
#endif /* TCL_THREADS */
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
@@ -210,7 +212,7 @@ TclpThreadExit(
|
||||
Tcl_ThreadId
|
||||
Tcl_GetCurrentThread(void)
|
||||
{
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
return (Tcl_ThreadId) pthread_self();
|
||||
#else
|
||||
return (Tcl_ThreadId) 0;
|
||||
@@ -239,7 +241,7 @@ Tcl_GetCurrentThread(void)
|
||||
void
|
||||
TclpInitLock(void)
|
||||
{
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
pthread_mutex_lock(&initLock);
|
||||
#endif
|
||||
}
|
||||
@@ -265,7 +267,7 @@ TclpInitLock(void)
|
||||
void
|
||||
TclFinalizeLock(void)
|
||||
{
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
/*
|
||||
* You do not need to destroy mutexes that were created with the
|
||||
* PTHREAD_MUTEX_INITIALIZER macro. These mutexes do not need any
|
||||
@@ -296,7 +298,7 @@ TclFinalizeLock(void)
|
||||
void
|
||||
TclpInitUnlock(void)
|
||||
{
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
pthread_mutex_unlock(&initLock);
|
||||
#endif
|
||||
}
|
||||
@@ -325,7 +327,7 @@ TclpInitUnlock(void)
|
||||
void
|
||||
TclpMasterLock(void)
|
||||
{
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
pthread_mutex_lock(&masterLock);
|
||||
#endif
|
||||
}
|
||||
@@ -351,7 +353,7 @@ TclpMasterLock(void)
|
||||
void
|
||||
TclpMasterUnlock(void)
|
||||
{
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
pthread_mutex_unlock(&masterLock);
|
||||
#endif
|
||||
}
|
||||
@@ -378,7 +380,7 @@ TclpMasterUnlock(void)
|
||||
Tcl_Mutex *
|
||||
Tcl_GetAllocMutex(void)
|
||||
{
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
pthread_mutex_t **allocLockPtrPtr = &allocLockPtr;
|
||||
return (Tcl_Mutex *) allocLockPtrPtr;
|
||||
#else
|
||||
@@ -386,7 +388,7 @@ Tcl_GetAllocMutex(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
@@ -649,7 +651,7 @@ TclpFinalizeCondition(
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
Tcl_DirEntry *
|
||||
TclpReaddir(
|
||||
DIR * dir)
|
||||
TclDIR * dir)
|
||||
{
|
||||
return TclOSreaddir(dir);
|
||||
}
|
||||
@@ -659,7 +661,7 @@ char *
|
||||
TclpInetNtoa(
|
||||
struct in_addr addr)
|
||||
{
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
|
||||
unsigned char *b = (unsigned char*) &addr.s_addr;
|
||||
|
||||
@@ -671,7 +673,7 @@ TclpInetNtoa(
|
||||
}
|
||||
#endif /* TCL_NO_DEPRECATED */
|
||||
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
/*
|
||||
* Additions by AOL for specialized thread memory allocator.
|
||||
*/
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
/*
|
||||
* tclUnixThrd.h --
|
||||
*
|
||||
* This header file defines things for thread support.
|
||||
*
|
||||
* Copyright (c) 1998 Sun Microsystems, Inc.
|
||||
*
|
||||
* See the file "license.terms" for information on usage and redistribution
|
||||
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
*/
|
||||
|
||||
#ifndef _TCLUNIXTHRD
|
||||
#define _TCLUNIXTHRD
|
||||
|
||||
#ifdef TCL_THREADS
|
||||
|
||||
|
||||
#endif /* TCL_THREADS */
|
||||
#endif /* _TCLUNIXTHRD */
|
||||
+6
-2
@@ -401,7 +401,8 @@ REG_OBJS = tclWinReg.$(OBJEXT)
|
||||
STUB_OBJS = \
|
||||
tclStubLib.$(OBJEXT) \
|
||||
tclTomMathStubLib.$(OBJEXT) \
|
||||
tclOOStubLib.$(OBJEXT)
|
||||
tclOOStubLib.$(OBJEXT) \
|
||||
tclWinPanic.$(OBJEXT)
|
||||
|
||||
TCLSH_OBJS = tclAppInit.$(OBJEXT)
|
||||
|
||||
@@ -538,6 +539,9 @@ tclTomMathStubLib.${OBJEXT}: tclTomMathStubLib.c
|
||||
tclOOStubLib.${OBJEXT}: tclOOStubLib.c
|
||||
$(CC) -c $(CC_SWITCHES) -DSTATIC_BUILD @DEPARG@ $(CC_OBJNAME)
|
||||
|
||||
tclWinPanic.${OBJEXT}: tclWinPanic.c
|
||||
$(CC) -c $(CC_SWITCHES) -DSTATIC_BUILD @DEPARG@ $(CC_OBJNAME)
|
||||
|
||||
# Implicit rule for all object files that will end up in the Tcl library
|
||||
|
||||
%.${OBJEXT}: %.c
|
||||
@@ -770,7 +774,7 @@ packages:
|
||||
if [ ! -f $(PKG_DIR)/$$pkg/Makefile ]; then \
|
||||
( cd $(PKG_DIR)/$$pkg; \
|
||||
echo "Configuring package '$$i' wd = `$(CYGPATH) $$(pwd -P)`"; \
|
||||
$$i/configure --with-tcl=$$builddir --with-tclinclude=$(GENERIC_DIR_NATIVE) $(PKG_CFG_ARGS) --enable-shared --enable-threads; ) \
|
||||
$$i/configure --with-tcl=$$builddir --with-tclinclude=$(GENERIC_DIR_NATIVE) $(PKG_CFG_ARGS) --enable-shared; ) \
|
||||
fi ; \
|
||||
echo "Building package '$$pkg'"; \
|
||||
( cd $(PKG_DIR)/$$pkg; $(MAKE); ) \
|
||||
|
||||
Vendored
-36
@@ -707,7 +707,6 @@ CFLAGS_OPTIMIZE
|
||||
CFLAGS_DEBUG
|
||||
DL_LIBS
|
||||
CYGPATH
|
||||
TCL_THREADS
|
||||
SET_MAKE
|
||||
RC
|
||||
RANLIB
|
||||
@@ -763,7 +762,6 @@ SHELL'
|
||||
ac_subst_files=''
|
||||
ac_user_opts='
|
||||
enable_option_checking
|
||||
enable_threads
|
||||
with_encoding
|
||||
enable_shared
|
||||
enable_64bit
|
||||
@@ -1386,7 +1384,6 @@ Optional Features:
|
||||
--disable-option-checking ignore unrecognized --enable/--with options
|
||||
--disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
|
||||
--enable-FEATURE[=ARG] include FEATURE [ARG=yes]
|
||||
--enable-threads build with threads (default: on)
|
||||
--enable-shared build and link with shared libraries (default: on)
|
||||
--enable-64bit enable 64bit support (where applicable)
|
||||
--enable-symbols build with debugging symbols (default: off)
|
||||
@@ -3673,39 +3670,6 @@ fi
|
||||
|
||||
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Check whether --enable-threads or --disable-threads was given.
|
||||
#--------------------------------------------------------------------
|
||||
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for building with threads" >&5
|
||||
$as_echo_n "checking for building with threads... " >&6; }
|
||||
# Check whether --enable-threads was given.
|
||||
if test "${enable_threads+set}" = set; then :
|
||||
enableval=$enable_threads; tcl_ok=$enableval
|
||||
else
|
||||
tcl_ok=yes
|
||||
fi
|
||||
|
||||
|
||||
if test "$tcl_ok" = "yes"; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes (default)" >&5
|
||||
$as_echo "yes (default)" >&6; }
|
||||
TCL_THREADS=1
|
||||
$as_echo "#define TCL_THREADS 1" >>confdefs.h
|
||||
|
||||
# USE_THREAD_ALLOC tells us to try the special thread-based
|
||||
# allocator that significantly reduces lock contention
|
||||
$as_echo "#define USE_THREAD_ALLOC 1" >>confdefs.h
|
||||
|
||||
else
|
||||
TCL_THREADS=0
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
fi
|
||||
|
||||
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
# Embedded configuration information, encoding to use for the values, TIP #59
|
||||
#------------------------------------------------------------------------
|
||||
|
||||
@@ -78,12 +78,6 @@ AC_PROG_MAKE_SET
|
||||
AC_OBJEXT
|
||||
AC_EXEEXT
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Check whether --enable-threads or --disable-threads was given.
|
||||
#--------------------------------------------------------------------
|
||||
|
||||
SC_ENABLE_THREADS
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
# Embedded configuration information, encoding to use for the values, TIP #59
|
||||
#------------------------------------------------------------------------
|
||||
|
||||
+7
-4
@@ -350,7 +350,8 @@ TCLOBJS = $(COREOBJS) $(ZLIBOBJS) $(TOMMATHOBJS) $(PLATFORMOBJS)
|
||||
TCLSTUBOBJS = \
|
||||
$(TMP_DIR)\tclStubLib.obj \
|
||||
$(TMP_DIR)\tclTomMathStubLib.obj \
|
||||
$(TMP_DIR)\tclOOStubLib.obj
|
||||
$(TMP_DIR)\tclOOStubLib.obj \
|
||||
$(TMP_DIR)\tclWinPanic.obj
|
||||
|
||||
### The following paths CANNOT have spaces in them as they appear on
|
||||
### the left side of implicit rules.
|
||||
@@ -581,7 +582,6 @@ $(OUT_DIR)\tcl.nmake:
|
||||
@type << >$@
|
||||
CORE_MACHINE = $(MACHINE)
|
||||
CORE_DEBUG = $(DEBUG)
|
||||
CORE_TCL_THREADS = $(TCL_THREADS)
|
||||
CORE_USE_THREAD_ALLOC = $(USE_THREAD_ALLOC)
|
||||
CORE_USE_WIDECHAR_API = $(USE_WIDECHAR_API)
|
||||
<<
|
||||
@@ -637,7 +637,6 @@ $(OUT_DIR)\tclConfig.sh: $(WINDIR)\tclConfig.sh.in
|
||||
@TCL_STUB_LIB_FILE@ $(TCLSTUBLIBNAME)
|
||||
@TCL_STUB_LIB_FLAG@ $(TCLSTUBLIBNAME)
|
||||
@TCL_STUB_LIB_SPEC@ -L$(LIB_INSTALL_DIR) $(TCLSTUBLIBNAME)
|
||||
@TCL_THREADS@ $(TCL_THREADS)
|
||||
@TCL_BUILD_STUB_LIB_SPEC@ -L$(OUT_DIR) $(TCLSTUBLIBNAME)
|
||||
@TCL_BUILD_STUB_LIB_PATH@ $(TCLSTUBLIB)
|
||||
@TCL_STUB_LIB_PATH@ $(LIB_INSTALL_DIR)\$(TCLSTUBLIBNAME)
|
||||
@@ -710,7 +709,6 @@ $(TMP_DIR)\tclAppInit.obj: $(WINDIR)\tclAppInit.c
|
||||
-Fo$@ $?
|
||||
|
||||
### The following objects should be built using the stub interfaces
|
||||
### *ALL* extensions need to built with -DTCL_THREADS=1
|
||||
|
||||
$(TMP_DIR)\tclWinReg.obj: $(WINDIR)\tclWinReg.c
|
||||
!if $(STATIC_BUILD)
|
||||
@@ -741,6 +739,9 @@ $(TMP_DIR)\tclTomMathStubLib.obj: $(GENERICDIR)\tclTomMathStubLib.c
|
||||
$(TMP_DIR)\tclOOStubLib.obj: $(GENERICDIR)\tclOOStubLib.c
|
||||
$(cc32) $(stubscflags) -Fo$@ $?
|
||||
|
||||
$(TMP_DIR)\tclWinPanic.obj: $(WINDIR)\tclWinPanic.c
|
||||
$(cc32) $(stubscflags) -Fo$@ $?
|
||||
|
||||
$(TMP_DIR)\tclsh.exe.manifest: $(WINDIR)\tclsh.exe.manifest.in
|
||||
@nmakehlp -s << $** >$@
|
||||
@MACHINE@ $(MACHINE:IX86=X86)
|
||||
@@ -832,6 +833,8 @@ install-libraries: tclConfig tcl-nmake install-msgs install-tzdata
|
||||
$(MKDIR) "$(SCRIPT_INSTALL_DIR)\..\tcl8\8.5"
|
||||
@if not exist "$(SCRIPT_INSTALL_DIR)\..\tcl8\8.6" \
|
||||
$(MKDIR) "$(SCRIPT_INSTALL_DIR)\..\tcl8\8.6"
|
||||
@if not exist "$(SCRIPT_INSTALL_DIR)\..\tcl8\8.7" \
|
||||
$(MKDIR) "$(SCRIPT_INSTALL_DIR)\..\tcl8\8.7"
|
||||
@if not exist "$(LIB_INSTALL_DIR)\nmake" \
|
||||
$(MKDIR) "$(LIB_INSTALL_DIR)\nmake"
|
||||
@echo Installing header files
|
||||
|
||||
+12
-36
@@ -24,7 +24,7 @@ _RULES_VC = 1
|
||||
# For modifications that are not backward-compatible, you *must* change
|
||||
# the major version.
|
||||
RULES_VERSION_MAJOR = 1
|
||||
RULES_VERSION_MINOR = 2
|
||||
RULES_VERSION_MINOR = 3
|
||||
|
||||
# The PROJECT macro must be defined by parent makefile.
|
||||
!if "$(PROJECT)" == ""
|
||||
@@ -730,15 +730,6 @@ TCL_USE_STATIC_PACKAGES = 1
|
||||
TCL_USE_STATIC_PACKAGES = 0
|
||||
!endif
|
||||
|
||||
!if [nmakehlp -f $(OPTS) "nothreads"]
|
||||
!message *** Compile explicitly for non-threaded tcl
|
||||
TCL_THREADS = 0
|
||||
USE_THREAD_ALLOC= 0
|
||||
!else
|
||||
TCL_THREADS = 1
|
||||
USE_THREAD_ALLOC= 1
|
||||
!endif
|
||||
|
||||
!if [nmakehlp -f $(OPTS) "symbols"]
|
||||
!message *** Doing symbols
|
||||
DEBUG = 1
|
||||
@@ -774,12 +765,6 @@ PGO = 0
|
||||
!message *** Warning: ignoring option "loimpact" - deprecated on modern Windows.
|
||||
!endif
|
||||
|
||||
# TBD - should get rid of this option
|
||||
!if [nmakehlp -f $(OPTS) "thrdalloc"]
|
||||
!message *** Doing thrdalloc
|
||||
USE_THREAD_ALLOC = 1
|
||||
!endif
|
||||
|
||||
!if [nmakehlp -f $(OPTS) "tclalloc"]
|
||||
USE_THREAD_ALLOC = 0
|
||||
!endif
|
||||
@@ -970,7 +955,7 @@ VERSION = $(DOTVERSION:.=)
|
||||
# different compilers, build configurations etc.,
|
||||
#
|
||||
# Naming convention (suffixes):
|
||||
# t = full thread support.
|
||||
# t = full thread support. (Not used for Tcl >= 8.7)
|
||||
# s = static library (as opposed to an import library)
|
||||
# g = linked to the debug enabled C run-time.
|
||||
# x = special static build when it links to the dynamic C run-time.
|
||||
@@ -1028,7 +1013,7 @@ SUFX = $(SUFX:x=)
|
||||
!endif
|
||||
!endif
|
||||
|
||||
!if !$(TCL_THREADS)
|
||||
!if !$(TCL_THREADS) || $(TCL_VERSION) > 86
|
||||
TMP_DIRFULL = $(TMP_DIRFULL:Threaded=)
|
||||
SUFX = $(SUFX:t=)
|
||||
!endif
|
||||
@@ -1078,20 +1063,17 @@ TCL_INCLUDES = -I"$(WINDIR)" -I"$(GENERICDIR)"
|
||||
# When building extensions, we need to locate tclsh. Depending on version
|
||||
# of Tcl we are building against, this may or may not have a "t" suffix.
|
||||
# Try various possibilities in turn.
|
||||
TCLSH = $(_TCLDIR)\bin\tclsh$(TCL_VERSION)$(SUFX).exe
|
||||
!if !exist("$(TCLSH)") && $(TCL_THREADS)
|
||||
TCLSH = $(_TCLDIR)\bin\tclsh$(TCL_VERSION)t$(SUFX).exe
|
||||
!endif
|
||||
TCLSH = $(_TCLDIR)\bin\tclsh$(TCL_VERSION)$(SUFX:t=).exe
|
||||
!if !exist("$(TCLSH)")
|
||||
TCLSH = $(_TCLDIR)\bin\tclsh$(TCL_VERSION)$(SUFX:t=).exe
|
||||
TCLSH = $(_TCLDIR)\bin\tclsh$(TCL_VERSION)t$(SUFX:t=).exe
|
||||
!endif
|
||||
|
||||
TCLSTUBLIB = $(_TCLDIR)\lib\tclstub$(TCL_VERSION).lib
|
||||
TCLIMPLIB = $(_TCLDIR)\lib\tcl$(TCL_VERSION)$(SUFX).lib
|
||||
TCLIMPLIB = $(_TCLDIR)\lib\tcl$(TCL_VERSION)$(SUFX:t=).lib
|
||||
# When building extensions, may be linking against Tcl that does not add
|
||||
# "t" suffix (e.g. 8.5 or 8.7). If lib not found check for that possibility.
|
||||
!if !exist("$(TCLIMPLIB)")
|
||||
TCLIMPLIB = $(_TCLDIR)\lib\tcl$(TCL_VERSION)$(SUFX:t=).lib
|
||||
TCLIMPLIB = $(_TCLDIR)\lib\tcl$(TCL_VERSION)t$(SUFX:t=).lib
|
||||
!endif
|
||||
TCL_LIBRARY = $(_TCLDIR)\lib
|
||||
TCLREGLIB = $(_TCLDIR)\lib\tclreg13$(SUFX:t=).lib
|
||||
@@ -1101,19 +1083,16 @@ TCL_INCLUDES = -I"$(_TCLDIR)\include"
|
||||
|
||||
!else # Building against Tcl sources
|
||||
|
||||
TCLSH = $(_TCLDIR)\win\$(BUILDDIRTOP)\tclsh$(TCL_VERSION)$(SUFX).exe
|
||||
!if !exist($(TCLSH)) && $(TCL_THREADS)
|
||||
TCLSH = $(_TCLDIR)\win\$(BUILDDIRTOP)\tclsh$(TCL_VERSION)t$(SUFX).exe
|
||||
!endif
|
||||
!if !exist($(TCLSH))
|
||||
TCLSH = $(_TCLDIR)\win\$(BUILDDIRTOP)\tclsh$(TCL_VERSION)$(SUFX:t=).exe
|
||||
!if !exist($(TCLSH))
|
||||
TCLSH = $(_TCLDIR)\win\$(BUILDDIRTOP)\tclsh$(TCL_VERSION)t$(SUFX:t=).exe
|
||||
!endif
|
||||
TCLSTUBLIB = $(_TCLDIR)\win\$(BUILDDIRTOP)\tclstub$(TCL_VERSION).lib
|
||||
TCLIMPLIB = $(_TCLDIR)\win\$(BUILDDIRTOP)\tcl$(TCL_VERSION)$(SUFX).lib
|
||||
TCLIMPLIB = $(_TCLDIR)\win\$(BUILDDIRTOP)\tcl$(TCL_VERSION)$(SUFX:t=).lib
|
||||
# When building extensions, may be linking against Tcl that does not add
|
||||
# "t" suffix (e.g. 8.5 or 8.7). If lib not found check for that possibility.
|
||||
!if !exist("$(TCLIMPLIB)")
|
||||
TCLIMPLIB = $(_TCLDIR)\win\$(BUILDDIRTOP)\tcl$(TCL_VERSION)$(SUFX:t=).lib
|
||||
TCLIMPLIB = $(_TCLDIR)\win\$(BUILDDIRTOP)\tcl$(TCL_VERSION)t$(SUFX:t=).lib
|
||||
!endif
|
||||
TCL_LIBRARY = $(_TCLDIR)\library
|
||||
TCLREGLIB = $(_TCLDIR)\win\$(BUILDDIRTOP)\tclreg13$(SUFX:t=).lib
|
||||
@@ -1264,7 +1243,7 @@ OPTDEFINES = $(OPTDEFINES) -DTCL_MEM_DEBUG
|
||||
!if $(TCL_COMPILE_DEBUG)
|
||||
OPTDEFINES = $(OPTDEFINES) -DTCL_COMPILE_DEBUG -DTCL_COMPILE_STATS
|
||||
!endif
|
||||
!if $(TCL_THREADS)
|
||||
!if $(TCL_THREADS) && $(TCL_VERSION) < 86
|
||||
OPTDEFINES = $(OPTDEFINES) -DTCL_THREADS=1
|
||||
!if $(USE_THREAD_ALLOC)
|
||||
OPTDEFINES = $(OPTDEFINES) -DUSE_THREAD_ALLOC=1
|
||||
@@ -1708,9 +1687,6 @@ TCLNMAKECONFIG = "$(OUT_DIR)\tcl.nmake"
|
||||
!if defined(CORE_MACHINE) && "$(CORE_MACHINE)" != "$(MACHINE)"
|
||||
!error ERROR: Build target ($(MACHINE)) does not match the Tcl library architecture ($(CORE_MACHINE)).
|
||||
!endif
|
||||
!if defined(CORE_USE_THREAD_ALLOC) && $(CORE_USE_THREAD_ALLOC) != $(USE_THREAD_ALLOC)
|
||||
!message WARNING: Value of USE_THREAD_ALLOC ($(USE_THREAD_ALLOC)) does not match its Tcl core value ($(CORE_USE_THREAD_ALLOC)).
|
||||
!endif
|
||||
!if defined(CORE_DEBUG) && $(CORE_DEBUG) != $(DEBUG)
|
||||
!message WARNING: Value of DEBUG ($(DEBUG)) does not match its Tcl library configuration ($(DEBUG)).
|
||||
!endif
|
||||
|
||||
@@ -1528,6 +1528,10 @@ SOURCE=.\tclWinNotify.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\tclWinPanic.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\tclWinPipe.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
-36
@@ -382,42 +382,6 @@ AC_DEFUN([SC_ENABLE_SHARED], [
|
||||
fi
|
||||
])
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
# SC_ENABLE_THREADS --
|
||||
#
|
||||
# Specify if thread support should be enabled
|
||||
#
|
||||
# Arguments:
|
||||
# none
|
||||
#
|
||||
# Results:
|
||||
#
|
||||
# Adds the following arguments to configure:
|
||||
# --enable-threads=yes|no
|
||||
#
|
||||
# Defines the following vars:
|
||||
# TCL_THREADS
|
||||
#------------------------------------------------------------------------
|
||||
|
||||
AC_DEFUN([SC_ENABLE_THREADS], [
|
||||
AC_MSG_CHECKING(for building with threads)
|
||||
AC_ARG_ENABLE(threads, [ --enable-threads build with threads (default: on)],
|
||||
[tcl_ok=$enableval], [tcl_ok=yes])
|
||||
|
||||
if test "$tcl_ok" = "yes"; then
|
||||
AC_MSG_RESULT([yes (default)])
|
||||
TCL_THREADS=1
|
||||
AC_DEFINE(TCL_THREADS)
|
||||
# USE_THREAD_ALLOC tells us to try the special thread-based
|
||||
# allocator that significantly reduces lock contention
|
||||
AC_DEFINE(USE_THREAD_ALLOC)
|
||||
else
|
||||
TCL_THREADS=0
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
AC_SUBST(TCL_THREADS)
|
||||
])
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
# SC_ENABLE_SYMBOLS --
|
||||
#
|
||||
|
||||
+1
-7
@@ -7,19 +7,13 @@
|
||||
//
|
||||
// build-up the name suffix that defines the type of build this is.
|
||||
//
|
||||
#if TCL_THREADS
|
||||
#define SUFFIX_THREADS "t"
|
||||
#else
|
||||
#define SUFFIX_THREADS ""
|
||||
#endif
|
||||
|
||||
#if DEBUG && !UNCHECKED
|
||||
#define SUFFIX_DEBUG "g"
|
||||
#else
|
||||
#define SUFFIX_DEBUG ""
|
||||
#endif
|
||||
|
||||
#define SUFFIX SUFFIX_THREADS SUFFIX_DEBUG
|
||||
#define SUFFIX SUFFIX_DEBUG
|
||||
|
||||
|
||||
LANGUAGE 0x9, 0x1 /* LANG_ENGLISH, SUBLANG_DEFAULT */
|
||||
|
||||
@@ -175,7 +175,3 @@ TCL_BUILD_STUB_LIB_PATH='@TCL_BUILD_STUB_LIB_PATH@'
|
||||
|
||||
# Path to the Tcl stub library in the install directory.
|
||||
TCL_STUB_LIB_PATH='@TCL_STUB_LIB_PATH@'
|
||||
|
||||
# Flag, 1: we built Tcl with threads enabled, 0 we didn't
|
||||
TCL_THREADS=@TCL_THREADS@
|
||||
|
||||
|
||||
@@ -406,6 +406,9 @@ tclWinDebugPanic(
|
||||
}
|
||||
OutputDebugStringW(msgString);
|
||||
} else {
|
||||
if (!isatty(fileno(stderr))) {
|
||||
fprintf(stderr, "\xef\xbb\xbf");
|
||||
}
|
||||
vfprintf(stderr, format, argList);
|
||||
fprintf(stderr, "\n");
|
||||
fflush(stderr);
|
||||
|
||||
+49
-18
@@ -867,6 +867,7 @@ TclpFindExecutable(
|
||||
*/
|
||||
|
||||
if (argv0 == NULL) {
|
||||
# undef Tcl_SetPanicProc
|
||||
Tcl_SetPanicProc(tclWinDebugPanic);
|
||||
}
|
||||
|
||||
@@ -1436,48 +1437,78 @@ TclpGetUserHome(
|
||||
Tcl_DString *bufferPtr) /* Uninitialized or free DString filled with
|
||||
* name of user's home directory. */
|
||||
{
|
||||
const char *result = NULL;
|
||||
USER_INFO_1 *uiPtr, **uiPtrPtr = &uiPtr;
|
||||
char *result = NULL;
|
||||
USER_INFO_1 *uiPtr;
|
||||
Tcl_DString ds;
|
||||
int nameLen = -1;
|
||||
int badDomain = 0;
|
||||
char *domain;
|
||||
WCHAR *wName, *wHomeDir, *wDomain, **wDomainPtr = &wDomain;
|
||||
int rc = 0;
|
||||
const char *domain;
|
||||
WCHAR *wName, *wHomeDir, *wDomain;
|
||||
WCHAR buf[MAX_PATH];
|
||||
|
||||
Tcl_DStringInit(bufferPtr);
|
||||
|
||||
wDomain = NULL;
|
||||
domain = strchr(name, '@');
|
||||
if (domain != NULL) {
|
||||
domain = Tcl_UtfFindFirst(name, '@');
|
||||
if (domain == NULL) {
|
||||
const char *ptr;
|
||||
|
||||
/* no domain - firstly check it's the current user */
|
||||
if ( (ptr = TclpGetUserName(&ds)) != NULL
|
||||
&& strcasecmp(name, ptr) == 0
|
||||
) {
|
||||
/* try safest and fastest way to get current user home */
|
||||
ptr = TclGetEnv("HOME", &ds);
|
||||
if (ptr != NULL) {
|
||||
Tcl_JoinPath(1, &ptr, bufferPtr);
|
||||
rc = 1;
|
||||
result = Tcl_DStringValue(bufferPtr);
|
||||
}
|
||||
}
|
||||
Tcl_DStringFree(&ds);
|
||||
} else {
|
||||
Tcl_DStringInit(&ds);
|
||||
wName = Tcl_UtfToUniCharDString(domain + 1, -1, &ds);
|
||||
badDomain = NetGetDCName(NULL, wName, (LPBYTE *) wDomainPtr);
|
||||
rc = NetGetDCName(NULL, wName, (LPBYTE *) &wDomain);
|
||||
Tcl_DStringFree(&ds);
|
||||
nameLen = domain - name;
|
||||
}
|
||||
if (badDomain == 0) {
|
||||
if (rc == 0) {
|
||||
Tcl_DStringInit(&ds);
|
||||
wName = Tcl_UtfToUniCharDString(name, nameLen, &ds);
|
||||
if (NetUserGetInfo(wDomain, wName, 1, (LPBYTE *) uiPtrPtr) == 0) {
|
||||
while (NetUserGetInfo(wDomain, wName, 1, (LPBYTE *) &uiPtr) != 0) {
|
||||
/*
|
||||
* user does not exists - if domain was not specified,
|
||||
* try again using current domain.
|
||||
*/
|
||||
rc = 1;
|
||||
if (domain != NULL) break;
|
||||
/* get current domain */
|
||||
rc = NetGetDCName(NULL, NULL, (LPBYTE *) &wDomain);
|
||||
if (rc != 0) break;
|
||||
domain = INT2PTR(-1); /* repeat once */
|
||||
}
|
||||
if (rc == 0) {
|
||||
DWORD i, size = MAX_PATH;
|
||||
wHomeDir = uiPtr->usri1_home_dir;
|
||||
if ((wHomeDir != NULL) && (wHomeDir[0] != L'\0')) {
|
||||
Tcl_UniCharToUtfDString(wHomeDir, lstrlenW(wHomeDir),
|
||||
bufferPtr);
|
||||
size = lstrlenW(wHomeDir);
|
||||
Tcl_UniCharToUtfDString(wHomeDir, size, bufferPtr);
|
||||
} else {
|
||||
/*
|
||||
* User exists but has no home dir. Return
|
||||
* "{GetProfilesDirectory}/<user>".
|
||||
*/
|
||||
DWORD i, size = MAX_PATH;
|
||||
GetProfilesDirectoryW(buf, &size);
|
||||
for (i = 0; i < size; ++i){
|
||||
if (buf[i] == '\\') buf[i] = '/';
|
||||
}
|
||||
Tcl_UniCharToUtfDString(buf, size-1, bufferPtr);
|
||||
Tcl_DStringAppend(bufferPtr, "/", -1);
|
||||
Tcl_DStringAppend(bufferPtr, name, -1);
|
||||
Tcl_DStringAppend(bufferPtr, "/", 1);
|
||||
Tcl_DStringAppend(bufferPtr, name, nameLen);
|
||||
}
|
||||
result = Tcl_DStringValue(bufferPtr);
|
||||
/* be sure we returns normalized path */
|
||||
for (i = 0; i < size; ++i){
|
||||
if (result[i] == '\\') result[i] = '/';
|
||||
}
|
||||
NetApiBufferFree((void *) uiPtr);
|
||||
}
|
||||
Tcl_DStringFree(&ds);
|
||||
|
||||
+23
-11
@@ -503,6 +503,27 @@ Tcl_GetEncodingNameFromEnvironment(
|
||||
return Tcl_DStringValue(bufPtr);
|
||||
}
|
||||
|
||||
const char *
|
||||
TclpGetUserName(
|
||||
Tcl_DString *bufferPtr) /* Uninitialized or free DString filled with
|
||||
* the name of user. */
|
||||
{
|
||||
Tcl_DStringInit(bufferPtr);
|
||||
|
||||
if (TclGetEnv("USERNAME", bufferPtr) == NULL) {
|
||||
TCHAR szUserName[UNLEN+1];
|
||||
DWORD cchUserNameLen = UNLEN;
|
||||
|
||||
if (!GetUserName(szUserName, &cchUserNameLen)) {
|
||||
return NULL;
|
||||
}
|
||||
cchUserNameLen--;
|
||||
cchUserNameLen *= sizeof(TCHAR);
|
||||
Tcl_WinTCharToUtf(szUserName, cchUserNameLen, bufferPtr);
|
||||
}
|
||||
return Tcl_DStringValue(bufferPtr);
|
||||
}
|
||||
|
||||
/*
|
||||
*---------------------------------------------------------------------------
|
||||
*
|
||||
@@ -533,8 +554,6 @@ TclpSetVariables(
|
||||
static OSVERSIONINFOW osInfo;
|
||||
static int osInfoInitialized = 0;
|
||||
Tcl_DString ds;
|
||||
TCHAR szUserName[UNLEN+1];
|
||||
DWORD cchUserNameLen = UNLEN;
|
||||
|
||||
Tcl_SetVar2Ex(interp, "tclDefaultLibrary", NULL,
|
||||
TclGetProcessGlobalValue(&defaultLibraryDir), TCL_GLOBAL_ONLY);
|
||||
@@ -609,15 +628,8 @@ TclpSetVariables(
|
||||
* Note: cchUserNameLen is number of characters including nul terminator.
|
||||
*/
|
||||
|
||||
Tcl_DStringInit(&ds);
|
||||
if (TclGetEnv("USERNAME", &ds) == NULL) {
|
||||
if (GetUserName(szUserName, &cchUserNameLen) != 0) {
|
||||
int cbUserNameLen = cchUserNameLen - 1;
|
||||
cbUserNameLen *= sizeof(TCHAR);
|
||||
Tcl_WinTCharToUtf(szUserName, cbUserNameLen, &ds);
|
||||
}
|
||||
}
|
||||
Tcl_SetVar2(interp, "tcl_platform", "user", Tcl_DStringValue(&ds),
|
||||
ptr = TclpGetUserName(&ds);
|
||||
Tcl_SetVar2(interp, "tcl_platform", "user", ptr ? ptr : "",
|
||||
TCL_GLOBAL_ONLY);
|
||||
Tcl_DStringFree(&ds);
|
||||
|
||||
|
||||
+2
-7
@@ -63,13 +63,8 @@ MODULE_SCOPE int TclWinSymLinkCopyDirectory(const TCHAR *LinkOriginal,
|
||||
MODULE_SCOPE int TclWinSymLinkDelete(const TCHAR *LinkOriginal,
|
||||
int linkOnly);
|
||||
MODULE_SCOPE int TclWinFileOwned(Tcl_Obj *);
|
||||
#if defined(TCL_THREADS) && defined(USE_THREAD_ALLOC)
|
||||
MODULE_SCOPE void TclWinFreeAllocCache(void);
|
||||
MODULE_SCOPE void TclFreeAllocCache(void *);
|
||||
MODULE_SCOPE Tcl_Mutex *TclpNewAllocMutex(void);
|
||||
MODULE_SCOPE void * TclpGetAllocCache(void);
|
||||
MODULE_SCOPE void TclpSetAllocCache(void *);
|
||||
#endif /* TCL_THREADS */
|
||||
|
||||
MODULE_SCOPE const char*TclpGetUserName(Tcl_DString *bufferPtr);
|
||||
|
||||
/* Needed by tclWinFile.c and tclWinFCmd.c */
|
||||
#ifndef FILE_ATTRIBUTE_REPARSE_POINT
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* tclWinPanic.c --
|
||||
*
|
||||
* Contains the Windows-specific command-line panic proc.
|
||||
*
|
||||
* Copyright (c) 2013 by Jan Nijtmans.
|
||||
* All rights reserved.
|
||||
*
|
||||
* See the file "license.terms" for information on usage and redistribution of
|
||||
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
*/
|
||||
|
||||
#include "tclInt.h"
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* Tcl_ConsolePanic --
|
||||
*
|
||||
* Display a message. If a debugger is present, present it directly to
|
||||
* the debugger, otherwise send it to stderr.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
* None.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
Tcl_ConsolePanic(
|
||||
const char *format, ...)
|
||||
{
|
||||
#define TCL_MAX_WARN_LEN 26000
|
||||
va_list argList;
|
||||
WCHAR msgString[TCL_MAX_WARN_LEN];
|
||||
char buf[TCL_MAX_WARN_LEN * TCL_UTF_MAX];
|
||||
HANDLE handle = GetStdHandle(STD_ERROR_HANDLE);
|
||||
DWORD dummy;
|
||||
|
||||
va_start(argList, format);
|
||||
vsnprintf(buf+3, sizeof(buf)-3, format, argList);
|
||||
buf[sizeof(buf)-1] = 0;
|
||||
msgString[TCL_MAX_WARN_LEN-1] = L'\0';
|
||||
MultiByteToWideChar(CP_UTF8, 0, buf+3, -1, msgString, TCL_MAX_WARN_LEN);
|
||||
|
||||
/*
|
||||
* Truncate MessageBox string if it is too long to not overflow the buffer.
|
||||
*/
|
||||
|
||||
if (msgString[TCL_MAX_WARN_LEN-1] != L'\0') {
|
||||
memcpy(msgString + (TCL_MAX_WARN_LEN - 5), L" ...", 5 * sizeof(WCHAR));
|
||||
}
|
||||
|
||||
if (IsDebuggerPresent()) {
|
||||
OutputDebugStringW(msgString);
|
||||
} else if (_isatty(2)) {
|
||||
WriteConsoleW(handle, msgString, wcslen(msgString), &dummy, 0);
|
||||
} else {
|
||||
buf[0] = 0xEF; buf[1] = 0xBB; buf[2] = 0xBF; /* UTF-8 bom */
|
||||
WriteFile(handle, buf, strlen(buf), &dummy, 0);
|
||||
WriteFile(handle, "\n", 1, &dummy, 0);
|
||||
FlushFileBuffers(handle);
|
||||
}
|
||||
# if defined(__GNUC__)
|
||||
__builtin_trap();
|
||||
# elif defined(_WIN64)
|
||||
__debugbreak();
|
||||
# elif defined(_MSC_VER)
|
||||
_asm {int 3}
|
||||
# else
|
||||
DebugBreak();
|
||||
# endif
|
||||
#if defined(_WIN32)
|
||||
ExitProcess(1);
|
||||
#else
|
||||
abort();
|
||||
#endif
|
||||
}
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: c
|
||||
* c-basic-offset: 4
|
||||
* fill-column: 78
|
||||
* tab-width: 8
|
||||
* End:
|
||||
*/
|
||||
@@ -568,4 +568,7 @@ typedef DWORD_PTR * PDWORD_PTR;
|
||||
# define LABEL_SECURITY_INFORMATION (0x00000010L)
|
||||
#endif
|
||||
|
||||
#define Tcl_DirEntry void
|
||||
#define TclDIR void
|
||||
|
||||
#endif /* _TCLWINPORT */
|
||||
|
||||
+5
-5
@@ -41,7 +41,7 @@ static CRITICAL_SECTION initLock;
|
||||
* obvious reasons, cannot use any dyamically allocated storage.
|
||||
*/
|
||||
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
|
||||
static struct Tcl_Mutex_ {
|
||||
CRITICAL_SECTION crit;
|
||||
@@ -76,7 +76,7 @@ static CRITICAL_SECTION joinLock;
|
||||
* The per-thread event and queue pointers.
|
||||
*/
|
||||
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
|
||||
typedef struct ThreadSpecificData {
|
||||
HANDLE condEvent; /* Per-thread condition event */
|
||||
@@ -474,7 +474,7 @@ TclpMasterUnlock(void)
|
||||
Tcl_Mutex *
|
||||
Tcl_GetAllocMutex(void)
|
||||
{
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
if (!allocOnce) {
|
||||
InitializeCriticalSection(&allocLock.crit);
|
||||
allocOnce = 1;
|
||||
@@ -516,7 +516,7 @@ TclFinalizeLock(void)
|
||||
DeleteCriticalSection(&masterLock);
|
||||
initialized = 0;
|
||||
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
if (allocOnce) {
|
||||
DeleteCriticalSection(&allocLock.crit);
|
||||
allocOnce = 0;
|
||||
@@ -532,7 +532,7 @@ TclFinalizeLock(void)
|
||||
DeleteCriticalSection(&initLock);
|
||||
}
|
||||
|
||||
#ifdef TCL_THREADS
|
||||
#if TCL_THREADS
|
||||
|
||||
/* locally used prototype */
|
||||
static void FinalizeConditionEvent(ClientData data);
|
||||
|
||||
+1
-7
@@ -8,12 +8,6 @@
|
||||
//
|
||||
// build-up the name suffix that defines the type of build this is.
|
||||
//
|
||||
#if TCL_THREADS
|
||||
#define SUFFIX_THREADS "t"
|
||||
#else
|
||||
#define SUFFIX_THREADS ""
|
||||
#endif
|
||||
|
||||
#if STATIC_BUILD
|
||||
#define SUFFIX_STATIC "s"
|
||||
#else
|
||||
@@ -26,7 +20,7 @@
|
||||
#define SUFFIX_DEBUG ""
|
||||
#endif
|
||||
|
||||
#define SUFFIX SUFFIX_THREADS SUFFIX_STATIC SUFFIX_DEBUG
|
||||
#define SUFFIX SUFFIX_STATIC SUFFIX_DEBUG
|
||||
|
||||
|
||||
LANGUAGE 0x9, 0x1 /* LANG_ENGLISH, SUBLANG_DEFAULT */
|
||||
|
||||
Reference in New Issue
Block a user