summaryrefslogtreecommitdiffstats
path: root/generic/tclPkg.c
diff options
context:
space:
mode:
authordgp <dgp@users.sourceforge.net>2007-09-19 09:23:56 (GMT)
committerdgp <dgp@users.sourceforge.net>2007-09-19 09:23:56 (GMT)
commit5a81901027b82d89f66a96019c153b05eb839c3b (patch)
treedf242d80535462efe828de5bbba900053c0d54ca /generic/tclPkg.c
parentc305f5464ea3858ebfe9fe90c826fff383041cf2 (diff)
downloadtcl-5a81901027b82d89f66a96019c153b05eb839c3b.zip
tcl-5a81901027b82d89f66a96019c153b05eb839c3b.tar.gz
tcl-5a81901027b82d89f66a96019c153b05eb839c3b.tar.bz2
* generic/tclPkg.c: Backport fix for [1573844] to the
* tests/pkg.test: TCL_TIP268 sections.
Diffstat (limited to 'generic/tclPkg.c')
-rw-r--r--generic/tclPkg.c1286
1 files changed, 484 insertions, 802 deletions
diff --git a/generic/tclPkg.c b/generic/tclPkg.c
index df209ea..159c87b 100644
--- a/generic/tclPkg.c
+++ b/generic/tclPkg.c
@@ -10,7 +10,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclPkg.c,v 1.9.2.9 2007/03/19 17:06:26 dgp Exp $
+ * RCS: @(#) $Id: tclPkg.c,v 1.9.2.10 2007/09/19 09:23:59 dgp Exp $
*
* TIP #268.
* Heavily rewritten to handle the extend version numbers, and extended
@@ -64,25 +64,39 @@ static int ComparePkgVersions _ANSI_ARGS_((CONST char *v1,
static Package * FindPackage _ANSI_ARGS_((Tcl_Interp *interp,
CONST char *name));
#else
-static int CheckVersionAndConvert(Tcl_Interp *interp, CONST char *string,
- char** internal, int* stable);
+static int CheckVersionAndConvert(Tcl_Interp *interp,
+ CONST char *string, char** internal, int* stable);
static int CompareVersions(CONST char *v1i, CONST char *v2i,
- int *isMajorPtr);
-static int CheckRequirement(Tcl_Interp *interp, CONST char *string);
-static int CheckAllRequirements(Tcl_Interp* interp,
- int reqc, Tcl_Obj *CONST reqv[]);
-static int RequirementSatisfied(CONST char *havei, CONST char *req);
-static int AllRequirementsSatisfied(CONST char *havei,
- int reqc, Tcl_Obj *CONST reqv[]);
-static void AddRequirementsToResult(Tcl_Interp* interp,
- int reqc, Tcl_Obj *CONST reqv[]);
+ int *isMajorPtr);
+static int CheckRequirement(Tcl_Interp *interp,
+ CONST char *string);
+static int CheckAllRequirements(Tcl_Interp* interp, int reqc,
+ Tcl_Obj *CONST reqv[]);
+static int RequirementSatisfied(char *havei, CONST char *req);
+static int SomeRequirementSatisfied(char *havei, int reqc,
+ Tcl_Obj *CONST reqv[]);
+static void AddRequirementsToResult(Tcl_Interp* interp, int reqc,
+ Tcl_Obj *CONST reqv[]);
static void AddRequirementsToDString(Tcl_DString* dstring,
- int reqc, Tcl_Obj *CONST reqv[]);
+ int reqc, Tcl_Obj *CONST reqv[]);
static Package * FindPackage(Tcl_Interp *interp, CONST char *name);
-static Tcl_Obj* ExactRequirement(CONST char* version);
-static void VersionCleanupProc(ClientData clientData,
- Tcl_Interp *interp);
+static const char * PkgRequireCore(Tcl_Interp *interp, CONST char *name,
+ int reqx, Tcl_Obj *CONST reqv[],
+ ClientData *clientDataPtr);
#endif
+
+/*
+ * Helper macros.
+ */
+
+#define DupBlock(v,s,len) \
+ ((v) = ckalloc(len), memcpy((v),(s),(len)))
+#define DupString(v,s) \
+ do { \
+ unsigned local__len = (unsigned) (strlen(s) + 1); \
+ DupBlock((v),(s),local__len); \
+ } while (0)
+
/*
*----------------------------------------------------------------------
@@ -135,8 +149,7 @@ Tcl_PkgProvideEx(interp, name, version, clientData)
pkgPtr = FindPackage(interp, name);
if (pkgPtr->version == NULL) {
- pkgPtr->version = ckalloc((unsigned) (strlen(version) + 1));
- strcpy(pkgPtr->version, version);
+ DupString(pkgPtr->version, version);
pkgPtr->clientData = clientData;
return TCL_OK;
}
@@ -146,13 +159,13 @@ Tcl_PkgProvideEx(interp, name, version, clientData)
if (CheckVersionAndConvert (interp, pkgPtr->version, &pvi, NULL) != TCL_OK) {
return TCL_ERROR;
} else if (CheckVersionAndConvert (interp, version, &vi, NULL) != TCL_OK) {
- Tcl_Free (pvi);
+ ckfree(pvi);
return TCL_ERROR;
}
res = CompareVersions(pvi, vi, NULL);
- Tcl_Free (pvi);
- Tcl_Free (vi);
+ ckfree(pvi);
+ ckfree(vi);
if (res == 0) {
#endif
@@ -250,7 +263,7 @@ Tcl_PkgRequireEx(interp, name, version, exact, clientDataPtr)
Tcl_DString command;
#else
Tcl_Obj *ov;
- int res;
+ const char *result = NULL;
#endif
/*
@@ -333,65 +346,61 @@ Tcl_PkgRequireEx(interp, name, version, exact, clientDataPtr)
/* Translate between old and new API, and defer to the new function. */
if (version == NULL) {
- res = Tcl_PkgRequireProc(interp, name, 0, NULL, clientDataPtr);
+ result = PkgRequireCore(interp, name, 0, NULL, clientDataPtr);
} else {
+ if (exact && TCL_OK
+ != CheckVersionAndConvert(interp, version, NULL, NULL)) {
+ return NULL;
+ }
+ ov = Tcl_NewStringObj(version, -1);
if (exact) {
- ov = ExactRequirement (version);
- } else {
- ov = Tcl_NewStringObj (version,-1);
+ Tcl_AppendStringsToObj(ov, "-", version, NULL);
}
-
Tcl_IncrRefCount (ov);
- res = Tcl_PkgRequireProc(interp, name, 1, &ov, clientDataPtr);
+ result = PkgRequireCore(interp, name, 1, &ov, clientDataPtr);
Tcl_DecrRefCount (ov);
}
- if (res != TCL_OK) {
- return NULL;
- }
+ return result;
+}
- /* This function returns the version string explictly, and leaves the
- * interpreter result empty. However "Tcl_PkgRequireProc" above returned
- * the version through the interpreter result. Simply resetting the result
- * now potentially deletes the string (obj), and the pointer to its string
- * rep we have, as our result, may be dangling due to this. Our solution
- * is to remember the object in interp associated data, with a proper
- * reference count, and then reset the result. Now pointers will not
- * dangle. It will be a leak however if nothing is done. So the next time
- * we come through here we delete the object remembered by this call, as
- * we can then be sure that there is no pointer to its string around
- * anymore. Beyond that we have a deletion function which cleans up the last
- * remembered object which was not cleaned up directly, here.
- */
+int
+Tcl_PkgRequireProc(
+ Tcl_Interp *interp, /* Interpreter in which package is now
+ * available. */
+ CONST char *name, /* Name of desired package. */
+ int reqc, /* Requirements constraining the desired
+ * version. */
+ Tcl_Obj *CONST reqv[], /* 0 means to use the latest version
+ * available. */
+ ClientData *clientDataPtr)
+{
+ const char *result =
+ PkgRequireCore(interp, name, reqc, reqv, clientDataPtr);
- ov = (Tcl_Obj*) Tcl_GetAssocData (interp, "tcl/Tcl_PkgRequireEx", NULL);
- if (ov != NULL) {
- Tcl_DecrRefCount (ov);
+ if (result == NULL) {
+ return TCL_ERROR;
}
-
- ov = Tcl_GetObjResult (interp);
- Tcl_IncrRefCount (ov);
- Tcl_SetAssocData(interp, "tcl/Tcl_PkgRequireEx", VersionCleanupProc,
- (ClientData) ov);
- Tcl_ResetResult (interp);
-
- return Tcl_GetString (ov);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(result, -1));
+ return TCL_OK;
}
-int
-Tcl_PkgRequireProc(interp,name,reqc,reqv,clientDataPtr)
- Tcl_Interp *interp; /* Interpreter in which package is now
+static const char *
+PkgRequireCore(
+ Tcl_Interp *interp, /* Interpreter in which package is now
* available. */
- CONST char *name; /* Name of desired package. */
- int reqc; /* Requirements constraining the desired version. */
- Tcl_Obj *CONST reqv[]; /* 0 means to use the latest version available. */
- ClientData *clientDataPtr;
+ CONST char *name, /* Name of desired package. */
+ int reqc, /* Requirements constraining the desired
+ * version. */
+ Tcl_Obj *CONST reqv[], /* 0 means to use the latest version
+ * available. */
+ ClientData *clientDataPtr)
{
Interp *iPtr = (Interp *) interp;
Package *pkgPtr;
- PkgAvail *availPtr, *bestPtr, *bestStablePtr;
- char *availVersion, *bestVersion; /* Internal rep. of versions */
- int availStable;
+ PkgAvail *availPtr, *bestPtr, *bestStablePtr;
+ char *availVersion, *bestVersion; /* Internal rep. of versions */
+ int availStable;
char *script;
int code, satisfies, pass;
Tcl_DString command;
@@ -418,17 +427,16 @@ Tcl_PkgRequireProc(interp,name,reqc,reqv,clientDataPtr)
if (pkgPtr->clientData != NULL) {
Tcl_AppendResult(interp, "circular package dependency: ",
- "attempt to provide ", name, " ",
- (char *)(pkgPtr->clientData), " requires ", name, NULL);
+ "attempt to provide ", name, " ",
+ (char *)(pkgPtr->clientData), " requires ", name, NULL);
#ifndef TCL_TIP268
if (version != NULL) {
Tcl_AppendResult(interp, " ", version, NULL);
}
- return NULL;
#else
AddRequirementsToResult (interp, reqc, reqv);
- return TCL_ERROR;
#endif
+ return NULL;
}
/*
@@ -445,16 +453,15 @@ Tcl_PkgRequireProc(interp,name,reqc,reqv,clientDataPtr)
if ((bestPtr != NULL) && (ComparePkgVersions(availPtr->version,
bestPtr->version, (int *) NULL) <= 0)) {
#else
- bestPtr = NULL;
- bestStablePtr = NULL;
- bestVersion = NULL;
-
- for (availPtr = pkgPtr->availPtr;
- availPtr != NULL;
- availPtr = availPtr->nextPtr) {
- if (CheckVersionAndConvert (interp, availPtr->version,
- &availVersion, &availStable) != TCL_OK) {
- /* The provided version number is has invalid syntax. This
+ bestPtr = NULL;
+ bestStablePtr = NULL;
+ bestVersion = NULL;
+
+ for (availPtr = pkgPtr->availPtr; availPtr != NULL;
+ availPtr = availPtr->nextPtr) {
+ if (CheckVersionAndConvert(interp, availPtr->version,
+ &availVersion, &availStable) != TCL_OK) {
+ /* The provided version number has invalid syntax. This
* should not happen. This should have been caught by the
* 'package ifneeded' registering the package.
*/
@@ -469,11 +476,14 @@ Tcl_PkgRequireProc(interp,name,reqc,reqv,clientDataPtr)
#else
if (bestPtr != NULL) {
int res = CompareVersions (availVersion, bestVersion, NULL);
+
/* Note: Use internal reps! */
if (res <= 0) {
- /* The version of the package sought is not as good as the
- * currently selected version. Ignore it. */
- Tcl_Free (availVersion);
+ /*
+ * The version of the package sought is not as good as the
+ * currently selected version. Ignore it.
+ */
+ ckfree(availVersion);
availVersion = NULL;
#endif
continue;
@@ -484,24 +494,30 @@ Tcl_PkgRequireProc(interp,name,reqc,reqv,clientDataPtr)
/* We have found a version which is better than our max. */
if (reqc > 0) {
- /* Check satisfaction of requirements */
- satisfies = AllRequirementsSatisfied (availVersion, reqc, reqv);
+ /* Check satisfaction of requirements. */
+
+ satisfies = SomeRequirementSatisfied(availVersion, reqc, reqv);
#endif
if (!satisfies) {
#ifdef TCL_TIP268
- Tcl_Free (availVersion);
+ ckfree(availVersion);
availVersion = NULL;
#endif
continue;
}
}
+
bestPtr = availPtr;
+
#ifdef TCL_TIP268
- if (bestVersion != NULL) Tcl_Free (bestVersion);
- bestVersion = availVersion;
+ if (bestVersion != NULL) {
+ ckfree(bestVersion);
+ }
+ bestVersion = availVersion;
availVersion = NULL;
- /* If this new best version is stable then it also has to be
+ /*
+ * If this new best version is stable then it also has to be
* better than the max stable version found so far.
*/
@@ -511,7 +527,7 @@ Tcl_PkgRequireProc(interp,name,reqc,reqv,clientDataPtr)
}
if (bestVersion != NULL) {
- Tcl_Free (bestVersion);
+ ckfree(bestVersion);
}
/* Now choose a version among the two best. For 'latest' we simply
@@ -519,7 +535,8 @@ Tcl_PkgRequireProc(interp,name,reqc,reqv,clientDataPtr)
* stable, if there is any, or the best if there is nothing stable.
*/
- if ((iPtr->packagePrefer == PKG_PREFER_STABLE) && (bestStablePtr != NULL)) {
+ if ((iPtr->packagePrefer == PKG_PREFER_STABLE)
+ && (bestStablePtr != NULL)) {
bestPtr = bestStablePtr;
#endif
}
@@ -533,11 +550,13 @@ Tcl_PkgRequireProc(interp,name,reqc,reqv,clientDataPtr)
CONST char *versionToProvide = bestPtr->version;
script = bestPtr->script;
+
pkgPtr->clientData = (ClientData) versionToProvide;
Tcl_Preserve((ClientData) script);
Tcl_Preserve((ClientData) versionToProvide);
code = Tcl_EvalEx(interp, script, -1, TCL_EVAL_GLOBAL);
Tcl_Release((ClientData) script);
+
pkgPtr = FindPackage(interp, name);
if (code == TCL_OK) {
#ifdef TCL_TIP268
@@ -549,9 +568,9 @@ Tcl_PkgRequireProc(interp,name,reqc,reqv,clientDataPtr)
#endif
code = TCL_ERROR;
Tcl_AppendResult(interp, "attempt to provide package ",
- name, " ", versionToProvide,
- " failed: no version of package ", name,
- " provided", NULL);
+ name, " ", versionToProvide,
+ " failed: no version of package ", name,
+ " provided", NULL);
#ifndef TCL_TIP268
} else if (0 != ComparePkgVersions(
pkgPtr->version, versionToProvide, NULL)) {
@@ -592,124 +611,89 @@ Tcl_PkgRequireProc(interp,name,reqc,reqv,clientDataPtr)
" provided instead", NULL);
#else
} else {
- char* pvi;
- char* vi;
+ char *pvi, *vi;
int res;
- if (CheckVersionAndConvert (interp, pkgPtr->version, &pvi, NULL) != TCL_OK) {
+ if (CheckVersionAndConvert(interp, pkgPtr->version, &pvi,
+ NULL) != TCL_OK) {
code = TCL_ERROR;
- } else if (CheckVersionAndConvert (interp, versionToProvide, &vi, NULL) != TCL_OK) {
- Tcl_Free (pvi);
+ } else if (CheckVersionAndConvert(interp,
+ versionToProvide, &vi, NULL) != TCL_OK) {
+ ckfree(pvi);
code = TCL_ERROR;
} else {
res = CompareVersions(pvi, vi, NULL);
- Tcl_Free (vi);
+ ckfree(vi);
if (res != 0) {
/* At this point, it is clear that a prior
* [package ifneeded] command lied to us. It said
* that to get a particular version of a particular
- * package, we needed to evaluate a particular script.
- * However, we evaluated that script and got a different
- * version than we were told. This is an error, and we
- * ought to report it.
+ * package, we needed to evaluate a particular
+ * script. However, we evaluated that script and
+ * got a different version than we were told.
+ * This is an error, and we ought to report it.
*
- * However, we've been letting this type of error slide
- * for a long time, and as a result, a lot of packages
- * suffer from them.
+ * However, we've been letting this type of error
+ * slide for a long time, and as a result, a lot
+ * of packages suffer from them.
*
* It's a bit too harsh to make a large number of
* existing packages start failing by releasing a
- * new patch release, so we forgive this type of error
- * for the rest of the Tcl 8.4 series.
+ * new patch release, so we forgive this type of
+ * error for the rest of the Tcl 8.4 series.
*
- * We considered reporting a warning, but in practice
- * even that appears too harsh a change for a patch release.
+ * We considered reporting a warning, but in
+ * practice even that appears too harsh a change
+ * for a patch release.
*
- * We limit the error reporting to only
- * the situation where a broken ifneeded script leads
+ * We limit the error reporting to only the
+ * situation where a broken ifneeded script leads
* to a failure to satisfy the requirement.
*/
if (reqc > 0) {
- satisfies = AllRequirementsSatisfied (pvi, reqc, reqv);
+ satisfies = SomeRequirementSatisfied(pvi,
+ reqc, reqv);
if (!satisfies) {
- Tcl_ResetResult(interp);
code = TCL_ERROR;
Tcl_AppendResult(interp,
- "attempt to provide package ", name, " ",
- versionToProvide, " failed: package ",
- name, " ", pkgPtr->version,
- " provided instead", NULL);
+ "attempt to provide package ",
+ name, " ", versionToProvide,
+ " failed: package ", name, " ",
+ pkgPtr->version,
+ " provided instead", NULL);
}
}
- /*
- * Warning generation now disabled
- if (code == TCL_OK) {
- Tcl_Obj *msg = Tcl_NewStringObj(
- "attempt to provide package ", -1);
- Tcl_Obj *cmdPtr = Tcl_NewListObj(0, NULL);
- Tcl_ListObjAppendElement(NULL, cmdPtr,
- Tcl_NewStringObj("tclLog", -1));
- Tcl_AppendStringsToObj(msg, name, " ", versionToProvide,
- " failed: package ", name, " ",
- pkgPtr->version, " provided instead", NULL);
- Tcl_ListObjAppendElement(NULL, cmdPtr, msg);
- Tcl_IncrRefCount(cmdPtr);
- Tcl_EvalObjEx(interp, cmdPtr, TCL_EVAL_GLOBAL);
- Tcl_DecrRefCount(cmdPtr);
- Tcl_ResetResult(interp);
- }
- */
#endif
}
#ifdef TCL_TIP268
- Tcl_Free (pvi);
+ ckfree(pvi);
#endif
}
-#ifndef TCL_TIP268
- /*
- * Warning generation now disabled
- if (code == TCL_OK) {
- Tcl_Obj *msg = Tcl_NewStringObj(
- "attempt to provide package ", -1);
- Tcl_Obj *cmdPtr = Tcl_NewListObj(0, NULL);
- Tcl_ListObjAppendElement(NULL, cmdPtr,
- Tcl_NewStringObj("tclLog", -1));
- Tcl_AppendStringsToObj(msg, name, " ", versionToProvide,
- " failed: package ", name, " ",
- pkgPtr->version, " provided instead", NULL);
- Tcl_ListObjAppendElement(NULL, cmdPtr, msg);
- Tcl_IncrRefCount(cmdPtr);
- Tcl_EvalObjEx(interp, cmdPtr, TCL_EVAL_GLOBAL);
- Tcl_DecrRefCount(cmdPtr);
- Tcl_ResetResult(interp);
- }
- */
-#endif
}
} else if (code != TCL_ERROR) {
Tcl_Obj *codePtr = Tcl_NewIntObj(code);
Tcl_ResetResult(interp);
Tcl_AppendResult(interp, "attempt to provide package ",
- name, " ", versionToProvide, " failed: ",
- "bad return code: ", Tcl_GetString(codePtr), NULL);
+ name, " ", versionToProvide, " failed: ",
+ "bad return code: ", Tcl_GetString(codePtr), NULL);
Tcl_DecrRefCount(codePtr);
code = TCL_ERROR;
}
+
Tcl_Release((ClientData) versionToProvide);
if (code != TCL_OK) {
/*
- * Take a non-TCL_OK code from the script as an
- * indication the package wasn't loaded properly,
- * so the package system should not remember an
- * improper load.
+ * Take a non-TCL_OK code from the script as an indication the
+ * package wasn't loaded properly, so the package system
+ * should not remember an improper load.
*
- * This is consistent with our returning NULL.
- * If we're not willing to tell our caller we
- * got a particular version, we shouldn't store
- * that version for telling future callers either.
+ * This is consistent with our returning NULL. If we're not
+ * willing to tell our caller we got a particular version, we
+ * shouldn't store that version for telling future callers
+ * either.
*/
Tcl_AddErrorInfo(interp, "\n (\"package ifneeded\" script)");
if (pkgPtr->version != NULL) {
@@ -717,12 +701,9 @@ Tcl_PkgRequireProc(interp,name,reqc,reqv,clientDataPtr)
pkgPtr->version = NULL;
}
pkgPtr->clientData = NULL;
-#ifndef TCL_TIP268
return NULL;
-#else
- return TCL_ERROR;
-#endif
}
+
break;
}
@@ -735,6 +716,7 @@ Tcl_PkgRequireProc(interp,name,reqc,reqv,clientDataPtr)
if (pass > 1) {
break;
}
+
script = ((Interp *) interp)->packageUnknown;
if (script != NULL) {
Tcl_DStringInit(&command);
@@ -753,21 +735,18 @@ Tcl_PkgRequireProc(interp,name,reqc,reqv,clientDataPtr)
code = Tcl_EvalEx(interp, Tcl_DStringValue(&command),
Tcl_DStringLength(&command), TCL_EVAL_GLOBAL);
Tcl_DStringFree(&command);
+
if ((code != TCL_OK) && (code != TCL_ERROR)) {
Tcl_Obj *codePtr = Tcl_NewIntObj(code);
Tcl_ResetResult(interp);
Tcl_AppendResult(interp, "bad return code: ",
- Tcl_GetString(codePtr), NULL);
+ Tcl_GetString(codePtr), NULL);
Tcl_DecrRefCount(codePtr);
code = TCL_ERROR;
}
if (code == TCL_ERROR) {
Tcl_AddErrorInfo(interp, "\n (\"package unknown\" script)");
-#ifndef TCL_TIP268
return NULL;
-#else
- return TCL_ERROR;
-#endif
}
Tcl_ResetResult(interp);
}
@@ -779,11 +758,10 @@ Tcl_PkgRequireProc(interp,name,reqc,reqv,clientDataPtr)
if (version != NULL) {
Tcl_AppendResult(interp, " ", version, (char *) NULL);
}
- return NULL;
#else
AddRequirementsToResult(interp, reqc, reqv);
- return TCL_ERROR;
#endif
+ return NULL;
}
/*
@@ -801,10 +779,10 @@ Tcl_PkgRequireProc(interp,name,reqc,reqv,clientDataPtr)
if (reqc == 0) {
satisfies = 1;
} else {
- CheckVersionAndConvert (interp, pkgPtr->version, &pkgVersionI, NULL);
- satisfies = AllRequirementsSatisfied (pkgVersionI, reqc, reqv);
+ CheckVersionAndConvert(interp, pkgPtr->version, &pkgVersionI, NULL);
+ satisfies = SomeRequirementSatisfied(pkgVersionI, reqc, reqv);
- Tcl_Free (pkgVersionI);
+ ckfree(pkgVersionI);
#endif
}
#ifndef TCL_TIP268
@@ -816,23 +794,17 @@ Tcl_PkgRequireProc(interp,name,reqc,reqv,clientDataPtr)
if (clientDataPtr) {
*clientDataPtr = pkgPtr->clientData;
}
-#ifndef TCL_TIP268
return pkgPtr->version;
-#else
- Tcl_SetObjResult (interp, Tcl_NewStringObj (pkgPtr->version, -1));
- return TCL_OK;
-#endif
}
- Tcl_AppendResult(interp, "version conflict for package \"",
- name, "\": have ", pkgPtr->version,
+ Tcl_AppendResult(interp, "version conflict for package \"", name,
+ "\": have ", pkgPtr->version,
#ifndef TCL_TIP268
- ", need ", version, (char *) NULL);
- return NULL;
+ ", need ", version, (char *) NULL);
#else
- ", need", (char*) NULL);
+ ", need", (char*) NULL);
AddRequirementsToResult (interp, reqc, reqv);
- return TCL_ERROR;
#endif
+ return NULL;
}
/*
@@ -891,64 +863,28 @@ Tcl_PkgPresentEx(interp, name, version, exact, clientDataPtr)
Interp *iPtr = (Interp *) interp;
Tcl_HashEntry *hPtr;
Package *pkgPtr;
- int satisfies, result;
hPtr = Tcl_FindHashEntry(&iPtr->packageTable, name);
if (hPtr) {
pkgPtr = (Package *) Tcl_GetHashValue(hPtr);
if (pkgPtr->version != NULL) {
-#ifdef TCL_TIP268
- char* pvi;
- char* vi;
- int thisIsMajor;
-#endif
/*
* At this point we know that the package is present. Make sure
- * that the provided version meets the current requirement.
+ * that the provided version meets the current requirement by
+ * calling Tcl_PkgRequireEx() to check for us.
*/
- if (version == NULL) {
- if (clientDataPtr) {
- *clientDataPtr = pkgPtr->clientData;
- }
-
- return pkgPtr->version;
- }
-#ifndef TCL_TIP268
- result = ComparePkgVersions(pkgPtr->version, version, &satisfies);
-#else
- if (CheckVersionAndConvert (interp, pkgPtr->version, &pvi, NULL) != TCL_OK) {
- return NULL;
- } else if (CheckVersionAndConvert (interp, version, &vi, NULL) != TCL_OK) {
- Tcl_Free (pvi);
- return NULL;
- }
- result = CompareVersions(pvi, vi, &thisIsMajor);
- Tcl_Free (pvi);
- Tcl_Free (vi);
- satisfies = (result == 0) || ((result == 1) && !thisIsMajor);
-#endif
- if ((satisfies && !exact) || (result == 0)) {
- if (clientDataPtr) {
- *clientDataPtr = pkgPtr->clientData;
- }
-
- return pkgPtr->version;
- }
- Tcl_AppendResult(interp, "version conflict for package \"",
- name, "\": have ", pkgPtr->version,
- ", need ", version, (char *) NULL);
- return NULL;
+ return Tcl_PkgRequireEx(interp, name, version, exact,
+ clientDataPtr);
}
}
if (version != NULL) {
Tcl_AppendResult(interp, "package ", name, " ", version,
- " is not present", (char *) NULL);
+ " is not present", NULL);
} else {
- Tcl_AppendResult(interp, "package ", name, " is not present",
- (char *) NULL);
+ Tcl_AppendResult(interp, "package ", name, " is not present", NULL);
}
return NULL;
}
@@ -1018,31 +954,6 @@ Tcl_PackageObjCmd(dummy, interp, objc, objv)
return TCL_ERROR;
}
switch ((enum pkgOptions) optionIndex) {
-#ifndef TCL_TIP268
- case PKG_FORGET: {
- char *keyString;
- for (i = 2; i < objc; i++) {
- keyString = Tcl_GetString(objv[i]);
- hPtr = Tcl_FindHashEntry(&iPtr->packageTable, keyString);
- if (hPtr == NULL) {
- continue;
- }
- pkgPtr = (Package *) Tcl_GetHashValue(hPtr);
- Tcl_DeleteHashEntry(hPtr);
- if (pkgPtr->version != NULL) {
- ckfree(pkgPtr->version);
- }
- while (pkgPtr->availPtr != NULL) {
- availPtr = pkgPtr->availPtr;
- pkgPtr->availPtr = availPtr->nextPtr;
- Tcl_EventuallyFree((ClientData)availPtr->version, TCL_DYNAMIC);
- Tcl_EventuallyFree((ClientData)availPtr->script, TCL_DYNAMIC);
- ckfree((char *) availPtr);
- }
- ckfree((char *) pkgPtr);
- }
- break;
-#else
case PKG_FORGET: {
char *keyString;
for (i = 2; i < objc; i++) {
@@ -1069,140 +980,87 @@ Tcl_PackageObjCmd(dummy, interp, objc, objv)
}
case PKG_IFNEEDED: {
int length;
- char* argv3i;
- char* avi;
+#ifdef TCL_TIP268
int res;
+ char *argv3i, *avi;
+#endif
if ((objc != 4) && (objc != 5)) {
Tcl_WrongNumArgs(interp, 2, objv, "package version ?script?");
return TCL_ERROR;
}
argv3 = Tcl_GetString(objv[3]);
+#ifdef TCL_TIP268
if (CheckVersionAndConvert(interp, argv3, &argv3i, NULL) != TCL_OK) {
- return TCL_ERROR;
+#else
+ if (CheckVersion(interp, argv3) != TCL_OK) {
#endif
+ return TCL_ERROR;
}
-#ifndef TCL_TIP268
- case PKG_IFNEEDED: {
- int length;
- if ((objc != 4) && (objc != 5)) {
- Tcl_WrongNumArgs(interp, 2, objv, "package version ?script?");
- return TCL_ERROR;
-#else
argv2 = Tcl_GetString(objv[2]);
if (objc == 4) {
hPtr = Tcl_FindHashEntry(&iPtr->packageTable, argv2);
if (hPtr == NULL) {
- Tcl_Free (argv3i);
- return TCL_OK;
+#ifdef TCL_TIP268
+ ckfree(argv3i);
#endif
+ return TCL_OK;
}
-#ifndef TCL_TIP268
- argv3 = Tcl_GetString(objv[3]);
- if (CheckVersion(interp, argv3) != TCL_OK) {
-#else
pkgPtr = (Package *) Tcl_GetHashValue(hPtr);
} else {
pkgPtr = FindPackage(interp, argv2);
}
argv3 = Tcl_GetStringFromObj(objv[3], &length);
- for (availPtr = pkgPtr->availPtr, prevPtr = NULL;
- availPtr != NULL;
+ for (availPtr = pkgPtr->availPtr, prevPtr = NULL; availPtr != NULL;
prevPtr = availPtr, availPtr = availPtr->nextPtr) {
- if (CheckVersionAndConvert (interp, availPtr->version, &avi, NULL) != TCL_OK) {
- Tcl_Free (argv3i);
-#endif
+#ifdef TCL_TIP268
+ if (CheckVersionAndConvert(interp, availPtr->version, &avi,
+ NULL) != TCL_OK) {
+ ckfree(argv3i);
return TCL_ERROR;
}
-#ifndef TCL_TIP268
- argv2 = Tcl_GetString(objv[2]);
- if (objc == 4) {
- hPtr = Tcl_FindHashEntry(&iPtr->packageTable, argv2);
- if (hPtr == NULL) {
-#else
res = CompareVersions(avi, argv3i, NULL);
- Tcl_Free (avi);
+ ckfree(avi);
if (res == 0){
+#else
+ if (ComparePkgVersions(availPtr->version, argv3, (int *) NULL)
+ == 0) {
+#endif
if (objc == 4) {
- Tcl_Free (argv3i);
- Tcl_SetResult(interp, availPtr->script, TCL_VOLATILE);
+#ifdef TCL_TIP268
+ ckfree(argv3i);
#endif
+ Tcl_SetResult(interp, availPtr->script, TCL_VOLATILE);
return TCL_OK;
}
-#ifndef TCL_TIP268
- pkgPtr = (Package *) Tcl_GetHashValue(hPtr);
- } else {
- pkgPtr = FindPackage(interp, argv2);
- }
- argv3 = Tcl_GetStringFromObj(objv[3], &length);
- for (availPtr = pkgPtr->availPtr, prevPtr = NULL; availPtr != NULL;
- prevPtr = availPtr, availPtr = availPtr->nextPtr) {
- if (ComparePkgVersions(availPtr->version, argv3, (int *) NULL)
- == 0) {
- if (objc == 4) {
- Tcl_SetResult(interp, availPtr->script, TCL_VOLATILE);
- return TCL_OK;
- }
- Tcl_EventuallyFree((ClientData)availPtr->script, TCL_DYNAMIC);
- break;
- }
- }
- if (objc == 4) {
- return TCL_OK;
-#else
Tcl_EventuallyFree((ClientData)availPtr->script, TCL_DYNAMIC);
break;
-#endif
}
-#ifndef TCL_TIP268
- if (availPtr == NULL) {
- availPtr = (PkgAvail *) ckalloc(sizeof(PkgAvail));
- availPtr->version = ckalloc((unsigned) (length + 1));
- strcpy(availPtr->version, argv3);
- if (prevPtr == NULL) {
- availPtr->nextPtr = pkgPtr->availPtr;
- pkgPtr->availPtr = availPtr;
- } else {
- availPtr->nextPtr = prevPtr->nextPtr;
- prevPtr->nextPtr = availPtr;
- }
-#else
}
- Tcl_Free (argv3i);
+#ifdef TCL_TIP268
+ ckfree(argv3i);
+#endif
if (objc == 4) {
return TCL_OK;
}
if (availPtr == NULL) {
availPtr = (PkgAvail *) ckalloc(sizeof(PkgAvail));
- availPtr->version = ckalloc((unsigned) (length + 1));
- strcpy(availPtr->version, argv3);
+ DupBlock(availPtr->version, argv3, (unsigned) length + 1);
+
if (prevPtr == NULL) {
availPtr->nextPtr = pkgPtr->availPtr;
pkgPtr->availPtr = availPtr;
} else {
availPtr->nextPtr = prevPtr->nextPtr;
prevPtr->nextPtr = availPtr;
-#endif
}
-#ifndef TCL_TIP268
- argv4 = Tcl_GetStringFromObj(objv[4], &length);
- availPtr->script = ckalloc((unsigned) (length + 1));
- strcpy(availPtr->script, argv4);
- break;
-#endif
}
-#ifndef TCL_TIP268
- case PKG_NAMES: {
- if (objc != 2) {
- Tcl_WrongNumArgs(interp, 2, objv, NULL);
-#else
argv4 = Tcl_GetStringFromObj(objv[4], &length);
- availPtr->script = ckalloc((unsigned) (length + 1));
- strcpy(availPtr->script, argv4);
+ DupBlock(availPtr->script, argv4, (unsigned) length + 1);
break;
}
case PKG_NAMES: {
@@ -1221,42 +1079,58 @@ Tcl_PackageObjCmd(dummy, interp, objc, objv)
break;
}
case PKG_PRESENT: {
+ const char *name;
if (objc < 3) {
- presentSyntax:
- Tcl_WrongNumArgs(interp, 2, objv, "?-exact? package ?version?");
- return TCL_ERROR;
+ goto require;
}
argv2 = Tcl_GetString(objv[2]);
if ((argv2[0] == '-') && (strcmp(argv2, "-exact") == 0)) {
+ if (objc != 5) {
+ goto requireSyntax;
+ }
exact = 1;
+ name = TclGetString(objv[3]);
} else {
exact = 0;
+ name = argv2;
+ }
+
+ hPtr = Tcl_FindHashEntry(&iPtr->packageTable, name);
+ if (hPtr != NULL) {
+ pkgPtr = Tcl_GetHashValue(hPtr);
+ if (pkgPtr->version != NULL) {
+ goto require;
+ }
}
+#ifndef TCL_TIP268
version = NULL;
if (objc == (4 + exact)) {
version = Tcl_GetString(objv[3 + exact]);
- if (CheckVersionAndConvert(interp, version, NULL, NULL) != TCL_OK) {
-#endif
+ if (CheckVersion(interp, version) != TCL_OK) {
return TCL_ERROR;
}
-#ifndef TCL_TIP268
- tablePtr = &iPtr->packageTable;
- for (hPtr = Tcl_FirstHashEntry(tablePtr, &search); hPtr != NULL;
- hPtr = Tcl_NextHashEntry(&search)) {
-#else
} else if ((objc != 3) || exact) {
- goto presentSyntax;
+ goto requireSyntax;
}
+#else
+ version = NULL;
if (exact) {
- argv3 = Tcl_GetString(objv[3]);
- version = Tcl_PkgPresent(interp, argv3, version, exact);
+ version = Tcl_GetString(objv[4]);
+ if (CheckVersionAndConvert(interp, version, NULL, NULL) != TCL_OK) {
+ return TCL_ERROR;
+ }
} else {
- version = Tcl_PkgPresent(interp, argv2, version, exact);
- }
- if (version == NULL) {
- return TCL_ERROR;
+ if (CheckAllRequirements(interp, objc-3, objv+3) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if ((objc > 3) && (CheckVersionAndConvert(interp,
+ TclGetString(objv[3]), NULL, NULL) == TCL_OK)) {
+ version = TclGetString(objv[3]);
+ }
}
- Tcl_SetObjResult( interp, Tcl_NewStringObj( version, -1 ) );
+#endif
+ Tcl_PkgPresent(interp, name, version, exact);
+ return TCL_ERROR;
break;
}
case PKG_PROVIDE: {
@@ -1268,87 +1142,81 @@ Tcl_PackageObjCmd(dummy, interp, objc, objv)
if (objc == 3) {
hPtr = Tcl_FindHashEntry(&iPtr->packageTable, argv2);
if (hPtr != NULL) {
-#endif
pkgPtr = (Package *) Tcl_GetHashValue(hPtr);
-#ifndef TCL_TIP268
- if ((pkgPtr->version != NULL) || (pkgPtr->availPtr != NULL)) {
- Tcl_AppendElement(interp, Tcl_GetHashKey(tablePtr, hPtr));
-#else
if (pkgPtr->version != NULL) {
Tcl_SetResult(interp, pkgPtr->version, TCL_VOLATILE);
-#endif
}
}
-#ifndef TCL_TIP268
- break;
-#else
return TCL_OK;
-#endif
}
+ argv3 = Tcl_GetString(objv[3]);
#ifndef TCL_TIP268
- case PKG_PRESENT: {
- if (objc < 3) {
- presentSyntax:
- Tcl_WrongNumArgs(interp, 2, objv, "?-exact? package ?version?");
- return TCL_ERROR;
+ if (CheckVersion(interp, argv3) != TCL_OK) {
#else
- argv3 = Tcl_GetString(objv[3]);
if (CheckVersionAndConvert(interp, argv3, NULL, NULL) != TCL_OK) {
+#endif
return TCL_ERROR;
}
return Tcl_PkgProvide(interp, argv2, argv3);
}
case PKG_REQUIRE: {
+ require:
if (objc < 3) {
requireSyntax:
- Tcl_WrongNumArgs(interp, 2, objv, "?-exact? package ?requirement...?");
+#ifndef TCL_TIP268
+ Tcl_WrongNumArgs(interp, 2, objv, "?-exact? package ?version?");
+#else
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "?-exact? package ?requirement...?");
+#endif
+ return TCL_ERROR;
+ }
+#ifndef TCL_TIP268
+ argv2 = Tcl_GetString(objv[2]);
+ if ((argv2[0] == '-') && (strcmp(argv2, "-exact") == 0)) {
+ exact = 1;
+ } else {
+ exact = 0;
+ }
+ version = NULL;
+ if (objc == (4 + exact)) {
+ version = Tcl_GetString(objv[3 + exact]);
+ if (CheckVersion(interp, version) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ } else if ((objc != 3) || exact) {
+ goto requireSyntax;
+ }
+ if (exact) {
+ argv3 = Tcl_GetString(objv[3]);
+ version = Tcl_PkgRequire(interp, argv3, version, exact);
+ } else {
+ version = Tcl_PkgRequire(interp, argv2, version, exact);
+ }
+ if (version == NULL) {
return TCL_ERROR;
}
+ Tcl_SetObjResult( interp, Tcl_NewStringObj( version, -1 ) );
+#else
version = NULL;
- argv2 = Tcl_GetString(objv[2]);
+ argv2 = Tcl_GetString(objv[2]);
if ((argv2[0] == '-') && (strcmp(argv2, "-exact") == 0)) {
Tcl_Obj* ov;
int res;
if (objc != 5) {
goto requireSyntax;
-#endif
}
-#ifndef TCL_TIP268
- argv2 = Tcl_GetString(objv[2]);
- if ((argv2[0] == '-') && (strcmp(argv2, "-exact") == 0)) {
- exact = 1;
- } else {
- exact = 0;
-#else
version = Tcl_GetString(objv[4]);
if (CheckVersionAndConvert(interp, version, NULL, NULL) != TCL_OK) {
return TCL_ERROR;
-#endif
}
-#ifdef TCL_TIP268
+
/* Create a new-style requirement for the exact version. */
- ov = ExactRequirement (version);
-#endif
+ ov = Tcl_NewStringObj(version, -1);
+ Tcl_AppendStringsToObj(ov, "-", version, NULL);
version = NULL;
-#ifndef TCL_TIP268
- if (objc == (4 + exact)) {
- version = Tcl_GetString(objv[3 + exact]);
- if (CheckVersion(interp, version) != TCL_OK) {
- return TCL_ERROR;
- }
- } else if ((objc != 3) || exact) {
- goto presentSyntax;
- }
- if (exact) {
- argv3 = Tcl_GetString(objv[3]);
- version = Tcl_PkgPresent(interp, argv3, version, exact);
- } else {
- version = Tcl_PkgPresent(interp, argv2, version, exact);
- }
- if (version == NULL) {
-#else
argv3 = Tcl_GetString(objv[3]);
Tcl_IncrRefCount (ov);
@@ -1357,21 +1225,11 @@ Tcl_PackageObjCmd(dummy, interp, objc, objv)
return res;
} else {
if (CheckAllRequirements (interp, objc-3, objv+3) != TCL_OK) {
-#endif
return TCL_ERROR;
}
-#ifndef TCL_TIP268
- Tcl_SetObjResult( interp, Tcl_NewStringObj( version, -1 ) );
- break;
-#else
return Tcl_PkgRequireProc(interp, argv2, objc-3, objv+3, NULL);
-#endif
}
-#ifndef TCL_TIP268
- case PKG_PROVIDE: {
- if ((objc != 3) && (objc != 4)) {
- Tcl_WrongNumArgs(interp, 2, objv, "package ?version?");
-#else
+#endif
break;
}
case PKG_UNKNOWN: {
@@ -1388,9 +1246,7 @@ Tcl_PackageObjCmd(dummy, interp, objc, objv)
if (argv2[0] == 0) {
iPtr->packageUnknown = NULL;
} else {
- iPtr->packageUnknown = (char *) ckalloc((unsigned)
- (length + 1));
- strcpy(iPtr->packageUnknown, argv2);
+ DupBlock(iPtr->packageUnknown, argv2, (unsigned) length + 1);
}
} else {
Tcl_WrongNumArgs(interp, 2, objv, "?command?");
@@ -1398,6 +1254,7 @@ Tcl_PackageObjCmd(dummy, interp, objc, objv)
}
break;
}
+#ifdef TCL_TIP268
case PKG_PREFER: {
/* See tclInt.h for the enum, just before Interp */
static CONST char *pkgPreferOptions[] = {
@@ -1410,148 +1267,58 @@ Tcl_PackageObjCmd(dummy, interp, objc, objv)
} else if (objc == 3) {
/* Set value. */
int new;
- if (Tcl_GetIndexFromObj(interp, objv[2], pkgPreferOptions, "preference", 0,
- &new) != TCL_OK) {
-#endif
+ if (Tcl_GetIndexFromObj(interp, objv[2], pkgPreferOptions,
+ "preference", 0, &new) != TCL_OK) {
return TCL_ERROR;
}
-#ifndef TCL_TIP268
- argv2 = Tcl_GetString(objv[2]);
- if (objc == 3) {
- hPtr = Tcl_FindHashEntry(&iPtr->packageTable, argv2);
- if (hPtr != NULL) {
- pkgPtr = (Package *) Tcl_GetHashValue(hPtr);
- if (pkgPtr->version != NULL) {
- Tcl_SetResult(interp, pkgPtr->version, TCL_VOLATILE);
- }
- }
- return TCL_OK;
-#else
if (new < iPtr->packagePrefer) {
iPtr->packagePrefer = new;
-#endif
- }
-#ifndef TCL_TIP268
- argv3 = Tcl_GetString(objv[3]);
- if (CheckVersion(interp, argv3) != TCL_OK) {
- return TCL_ERROR;
}
- return Tcl_PkgProvide(interp, argv2, argv3);
-#endif
}
-#ifndef TCL_TIP268
- case PKG_REQUIRE: {
- if (objc < 3) {
- requireSyntax:
- Tcl_WrongNumArgs(interp, 2, objv, "?-exact? package ?version?");
- return TCL_ERROR;
- }
- argv2 = Tcl_GetString(objv[2]);
- if ((argv2[0] == '-') && (strcmp(argv2, "-exact") == 0)) {
- exact = 1;
- } else {
- exact = 0;
- }
- version = NULL;
- if (objc == (4 + exact)) {
- version = Tcl_GetString(objv[3 + exact]);
- if (CheckVersion(interp, version) != TCL_OK) {
- return TCL_ERROR;
- }
- } else if ((objc != 3) || exact) {
- goto requireSyntax;
- }
- if (exact) {
- argv3 = Tcl_GetString(objv[3]);
- version = Tcl_PkgRequire(interp, argv3, version, exact);
- } else {
- version = Tcl_PkgRequire(interp, argv2, version, exact);
- }
- if (version == NULL) {
- return TCL_ERROR;
- }
- Tcl_SetObjResult( interp, Tcl_NewStringObj( version, -1 ) );
- break;
-#else
/* Always return current value. */
- Tcl_SetObjResult(interp, Tcl_NewStringObj (pkgPreferOptions [iPtr->packagePrefer], -1));
+ Tcl_SetObjResult(interp,
+ Tcl_NewStringObj(pkgPreferOptions[iPtr->packagePrefer], -1));
break;
}
+#endif
case PKG_VCOMPARE: {
if (objc != 4) {
Tcl_WrongNumArgs(interp, 2, objv, "version1 version2");
return TCL_ERROR;
-#endif
}
-#ifndef TCL_TIP268
- case PKG_UNKNOWN: {
- int length;
- if (objc == 2) {
- if (iPtr->packageUnknown != NULL) {
- Tcl_SetResult(interp, iPtr->packageUnknown, TCL_VOLATILE);
- }
- } else if (objc == 3) {
- if (iPtr->packageUnknown != NULL) {
- ckfree(iPtr->packageUnknown);
- }
- argv2 = Tcl_GetStringFromObj(objv[2], &length);
- if (argv2[0] == 0) {
- iPtr->packageUnknown = NULL;
- } else {
- iPtr->packageUnknown = (char *) ckalloc((unsigned)
- (length + 1));
- strcpy(iPtr->packageUnknown, argv2);
- }
- } else {
- Tcl_WrongNumArgs(interp, 2, objv, "?command?");
- return TCL_ERROR;
- }
- break;
-#else
argv3 = Tcl_GetString(objv[3]);
argv2 = Tcl_GetString(objv[2]);
- if ((CheckVersionAndConvert (interp, argv2, &iva, NULL) != TCL_OK) ||
- (CheckVersionAndConvert (interp, argv3, &ivb, NULL) != TCL_OK)) {
- if (iva != NULL) { Tcl_Free (iva); }
- /* ivb cannot be set in this branch */
+#ifndef TCL_TIP268
+ if ((CheckVersion(interp, argv2) != TCL_OK)
+ || (CheckVersion(interp, argv3) != TCL_OK)) {
return TCL_ERROR;
-#endif
}
-#ifndef TCL_TIP268
- case PKG_VCOMPARE: {
- if (objc != 4) {
- Tcl_WrongNumArgs(interp, 2, objv, "version1 version2");
- return TCL_ERROR;
- }
- argv3 = Tcl_GetString(objv[3]);
- argv2 = Tcl_GetString(objv[2]);
- if ((CheckVersion(interp, argv2) != TCL_OK)
- || (CheckVersion(interp, argv3) != TCL_OK)) {
- return TCL_ERROR;
- }
- Tcl_SetIntObj(Tcl_GetObjResult(interp),
- ComparePkgVersions(argv2, argv3, (int *) NULL));
- break;
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(
+ ComparePkgVersions(argv2, argv3, (int *) NULL)));
#else
+ if ((CheckVersionAndConvert (interp, argv2, &iva, NULL) != TCL_OK)
+ || (CheckVersionAndConvert (interp, argv3, &ivb, NULL)
+ != TCL_OK)) {
+ if (iva != NULL) {
+ ckfree(iva);
+ }
+ /* ivb cannot be set in this branch */
+ return TCL_ERROR;
+ }
/* Comparison is done on the internal representation */
- Tcl_SetObjResult(interp,Tcl_NewIntObj(CompareVersions(iva, ivb, NULL)));
- Tcl_Free (iva);
- Tcl_Free (ivb);
+ Tcl_SetObjResult(interp,
+ Tcl_NewIntObj(CompareVersions(iva, ivb, NULL)));
+ ckfree(iva);
+ ckfree(ivb);
+#endif
break;
}
case PKG_VERSIONS: {
if (objc != 3) {
Tcl_WrongNumArgs(interp, 2, objv, "package");
return TCL_ERROR;
-#endif
}
-#ifndef TCL_TIP268
- case PKG_VERSIONS: {
- if (objc != 3) {
- Tcl_WrongNumArgs(interp, 2, objv, "package");
- return TCL_ERROR;
-#else
argv2 = Tcl_GetString(objv[2]);
hPtr = Tcl_FindHashEntry(&iPtr->packageTable, argv2);
if (hPtr != NULL) {
@@ -1559,72 +1326,50 @@ Tcl_PackageObjCmd(dummy, interp, objc, objv)
for (availPtr = pkgPtr->availPtr; availPtr != NULL;
availPtr = availPtr->nextPtr) {
Tcl_AppendElement(interp, availPtr->version);
-#endif
- }
-#ifndef TCL_TIP268
- argv2 = Tcl_GetString(objv[2]);
- hPtr = Tcl_FindHashEntry(&iPtr->packageTable, argv2);
- if (hPtr != NULL) {
- pkgPtr = (Package *) Tcl_GetHashValue(hPtr);
- for (availPtr = pkgPtr->availPtr; availPtr != NULL;
- availPtr = availPtr->nextPtr) {
- Tcl_AppendElement(interp, availPtr->version);
- }
}
- break;
-#endif
}
-#ifndef TCL_TIP268
- case PKG_VSATISFIES: {
- if (objc != 4) {
- Tcl_WrongNumArgs(interp, 2, objv, "version1 version2");
- return TCL_ERROR;
- }
- argv3 = Tcl_GetString(objv[3]);
- argv2 = Tcl_GetString(objv[2]);
- if ((CheckVersion(interp, argv2) != TCL_OK)
- || (CheckVersion(interp, argv3) != TCL_OK)) {
- return TCL_ERROR;
- }
- ComparePkgVersions(argv2, argv3, &satisfies);
- Tcl_SetIntObj(Tcl_GetObjResult(interp), satisfies);
- break;
-#else
break;
}
case PKG_VSATISFIES: {
+#ifdef TCL_TIP268
char* argv2i = NULL;
if (objc < 4) {
- Tcl_WrongNumArgs(interp, 2, objv, "version requirement requirement...");
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "version requirement requirement...");
return TCL_ERROR;
-#endif
}
-#ifndef TCL_TIP268
- default: {
- panic("Tcl_PackageObjCmd: bad option index to pkgOptions");
-#else
argv2 = Tcl_GetString(objv[2]);
if ((CheckVersionAndConvert(interp, argv2, &argv2i, NULL) != TCL_OK)) {
return TCL_ERROR;
- } else if (CheckAllRequirements (interp, objc-3, objv+3) != TCL_OK) {
- Tcl_Free (argv2i);
+ } else if (CheckAllRequirements(interp, objc-3, objv+3) != TCL_OK) {
+ ckfree(argv2i);
return TCL_ERROR;
-#endif
}
-#ifdef TCL_TIP268
- satisfies = AllRequirementsSatisfied (argv2i, objc-3, objv+3);
- Tcl_Free (argv2i);
+ satisfies = SomeRequirementSatisfied(argv2i, objc-3, objv+3);
+ ckfree (argv2i);
+#else
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 2, objv, "version1 version2");
+ return TCL_ERROR;
+ }
+ argv3 = Tcl_GetString(objv[3]);
+ argv2 = Tcl_GetString(objv[2]);
+ if ((CheckVersion(interp, argv2) != TCL_OK)
+ || (CheckVersion(interp, argv3) != TCL_OK)) {
+ return TCL_ERROR;
+ }
+ ComparePkgVersions(argv2, argv3, &satisfies);
+#endif
- Tcl_SetIntObj(Tcl_GetObjResult(interp), satisfies);
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(satisfies));
break;
}
default: {
panic("Tcl_PackageObjCmd: bad option index to pkgOptions");
}
-#endif
}
return TCL_OK;
}
@@ -1738,32 +1483,54 @@ TclFreePackageInfo(iPtr)
*----------------------------------------------------------------------
*/
-static int
#ifndef TCL_TIP268
+static int
CheckVersion(interp, string)
Tcl_Interp *interp; /* Used for error reporting. */
CONST char *string; /* Supposedly a version number, which is
* groups of decimal digits separated
* by dots. */
+{
+ CONST char *p = string;
+ char prevChar;
+ if (!isdigit(UCHAR(*p))) { /* INTL: digit */
+ goto error;
+ }
+ for (prevChar = *p, p++; *p != 0; p++) {
+ if (!isdigit(UCHAR(*p)) &&
+ ((*p != '.') || (prevChar == '.'))) { /* INTL: digit */
+ goto error;
+ }
+ prevChar = *p;
+ }
+ if (prevChar != '.') {
+ return TCL_OK;
+ }
+
+ error:
+ Tcl_AppendResult(interp, "expected version number but got \"",
+ string, "\"", (char *) NULL);
+ return TCL_ERROR;
+}
#else
+static int
CheckVersionAndConvert(interp, string, internal, stable)
Tcl_Interp *interp; /* Used for error reporting. */
CONST char *string; /* Supposedly a version number, which is
* groups of decimal digits separated by
* dots. */
char** internal; /* Internal normalized representation */
- int* stable; /* Flag: Version is (un)stable. */
-#endif
+ int* stable; /* Flag: Version is (un)stable. */
{
CONST char *p = string;
char prevChar;
-#ifdef TCL_TIP268
int hasunstable = 0;
- /* 4* assuming that each char is a separator (a,b become ' -x ').
+ /*
+ * 4* assuming that each char is a separator (a,b become ' -x ').
* 4+ to have spce for an additional -2 at the end
*/
- char* ibuf = ckalloc (4+4*strlen(string));
- char* ip = ibuf;
+ char* ibuf = ckalloc(4+4*strlen(string));
+ char* ip = ibuf;
/* Basic rules
* (1) First character has to be a digit.
@@ -1778,68 +1545,68 @@ CheckVersionAndConvert(interp, string, internal, stable)
* (5) Neither 'a', nor 'b' may occur before or after a '.'
*/
-#endif
if (!isdigit(UCHAR(*p))) { /* INTL: digit */
goto error;
}
-#ifdef TCL_TIP268
*ip++ = *p;
-#endif
for (prevChar = *p, p++; *p != 0; p++) {
-#ifndef TCL_TIP268
- if (!isdigit(UCHAR(*p)) &&
- ((*p != '.') || (prevChar == '.'))) { /* INTL: digit */
-#else
- if (
- (!isdigit(UCHAR(*p))) &&
- (((*p != '.') && (*p != 'a') && (*p != 'b')) ||
- ((hasunstable && ((*p == 'a') || (*p == 'b'))) ||
- (((prevChar == 'a') || (prevChar == 'b') || (prevChar == '.')) && (*p == '.')) ||
- (((*p == 'a') || (*p == 'b') || (*p == '.')) && (prevChar == '.'))))
- ) {
+ if ((!isdigit(UCHAR(*p))) && (((*p != '.') && (*p != 'a')
+ && (*p != 'b')) || ((hasunstable && ((*p == 'a')
+ || (*p == 'b'))) || (((prevChar == 'a') || (prevChar == 'b')
+ || (prevChar == '.')) && (*p == '.')) || (((*p == 'a')
+ || (*p == 'b') || (*p == '.')) && (prevChar == '.'))))) {
/* INTL: digit */
-#endif
goto error;
}
-#ifdef TCL_TIP268
- if ((*p == 'a') || (*p == 'b')) { hasunstable = 1 ; }
+ if ((*p == 'a') || (*p == 'b')) {
+ hasunstable = 1;
+ }
- /* Translation to the internal rep. Regular version chars are copied
+ /*
+ * Translation to the internal rep. Regular version chars are copied
* as is. The separators are translated to numerics. The new separator
- * for all parts is space. */
+ * for all parts is space.
+ */
- if (*p == '.') { *ip++ = ' '; *ip++ = '0'; *ip++ = ' '; }
- else if (*p == 'a') { *ip++ = ' '; *ip++ = '-'; *ip++ = '2'; *ip++ = ' '; }
- else if (*p == 'b') { *ip++ = ' '; *ip++ = '-'; *ip++ = '1'; *ip++ = ' '; }
- else { *ip++ = *p; }
-#endif
+ if (*p == '.') {
+ *ip++ = ' ';
+ *ip++ = '0';
+ *ip++ = ' ';
+ } else if (*p == 'a') {
+ *ip++ = ' ';
+ *ip++ = '-';
+ *ip++ = '2';
+ *ip++ = ' ';
+ } else if (*p == 'b') {
+ *ip++ = ' ';
+ *ip++ = '-';
+ *ip++ = '1';
+ *ip++ = ' ';
+ } else {
+ *ip++ = *p;
+ }
prevChar = *p;
}
-#ifndef TCL_TIP268
- if (prevChar != '.') {
-#else
if ((prevChar != '.') && (prevChar != 'a') && (prevChar != 'b')) {
*ip = '\0';
if (internal != NULL) {
*internal = ibuf;
} else {
- Tcl_Free (ibuf);
+ ckfree(ibuf);
}
if (stable != NULL) {
*stable = !hasunstable;
}
-#endif
return TCL_OK;
}
error:
-#ifdef TCL_TIP268
- ckfree (ibuf);
-#endif
+ ckfree(ibuf);
Tcl_AppendResult(interp, "expected version number but got \"",
string, "\"", (char *) NULL);
return TCL_ERROR;
}
+#endif
/*
*----------------------------------------------------------------------
@@ -1861,8 +1628,8 @@ CheckVersionAndConvert(interp, string, internal, stable)
*----------------------------------------------------------------------
*/
-static int
#ifndef TCL_TIP268
+static int
ComparePkgVersions(v1, v2, satPtr)
CONST char *v1;
CONST char *v2; /* Versions strings, of form 2.1.3 (any
@@ -1872,24 +1639,74 @@ ComparePkgVersions(v1, v2, satPtr)
* v1 "satisfies" v2: v1 is greater than
* or equal to v2 and both version numbers
* have the same major number. */
+{
+ int thisIsMajor, n1, n2;
+
+ /*
+ * Each iteration of the following loop processes one number from each
+ * string, terminated by a " " (space). If those numbers don't match then
+ * the comparison is over; otherwise, we loop back for the next number.
+ */
+
+ thisIsMajor = 1;
+ while (1) {
+ /* Parse one decimal number from the front of each string. */
+
+ n1 = n2 = 0;
+ while ((*v1 != 0) && (*v1 != '.')) {
+ n1 = 10*n1 + (*v1 - '0');
+ v1++;
+ }
+ while ((*v2 != 0) && (*v2 != '.')) {
+ n2 = 10*n2 + (*v2 - '0');
+ v2++;
+ }
+
+ /*
+ * Compare and go on to the next version number if the current numbers
+ * match.
+ */
+
+ if (n1 != n2) {
+ break;
+ }
+ if (*v1 != 0) {
+ v1++;
+ } else if (*v2 == 0) {
+ break;
+ }
+ if (*v2 != 0) {
+ v2++;
+ }
+ thisIsMajor = 0;
+ }
+ if (satPtr != NULL) {
+ *satPtr = (n1 == n2) || ((n1 > n2) && !thisIsMajor);
+ }
+ if (n1 > n2) {
+ return 1;
+ } else if (n1 == n2) {
+ return 0;
+ } else {
+ return -1;
+ }
+}
#else
+static int
CompareVersions(v1, v2, isMajorPtr)
CONST char *v1; /* Versions strings, of form 2.1.3 (any number */
CONST char *v2; /* of version numbers). */
int *isMajorPtr; /* If non-null, the word pointed to is filled
* in with a 0/1 value. 1 means that the difference
* occured in the first element. */
-#endif
{
int thisIsMajor, n1, n2;
-#ifdef TCL_TIP268
int res, flip;
-#endif
/*
* Each iteration of the following loop processes one number from each
- * string, terminated by a " " (space). If those numbers don't match then the
- * comparison is over; otherwise, we loop back for the next number.
+ * string, terminated by a " " (space). If those numbers don't match then
+ * the comparison is over; otherwise, we loop back for the next number.
*
* TIP 268.
* This is identical the function 'ComparePkgVersion', but using the new
@@ -1904,35 +1721,23 @@ CompareVersions(v1, v2, isMajorPtr)
thisIsMajor = 1;
while (1) {
- /*
- * Parse one decimal number from the front of each string.
- */
+ /* Parse one decimal number from the front of each string. */
n1 = n2 = 0;
-#ifndef TCL_TIP268
- while ((*v1 != 0) && (*v1 != '.')) {
-#else
flip = 0;
while ((*v1 != 0) && (*v1 != ' ')) {
if (*v1 == '-') {flip = 1 ; v1++ ; continue;}
-#endif
n1 = 10*n1 + (*v1 - '0');
v1++;
}
-#ifndef TCL_TIP268
- while ((*v2 != 0) && (*v2 != '.')) {
-#else
if (flip) n1 = -n1;
flip = 0;
while ((*v2 != 0) && (*v2 != ' ')) {
if (*v2 == '-') {flip = 1; v2++ ; continue;}
-#endif
n2 = 10*n2 + (*v2 - '0');
v2++;
}
-#ifdef TCL_TIP268
if (flip) n2 = -n2;
-#endif
/*
* Compare and go on to the next version number if the current numbers
@@ -1952,27 +1757,11 @@ CompareVersions(v1, v2, isMajorPtr)
}
thisIsMajor = 0;
}
-#ifndef TCL_TIP268
- if (satPtr != NULL) {
- *satPtr = (n1 == n2) || ((n1 > n2) && !thisIsMajor);
- }
-#endif
if (n1 > n2) {
-#ifndef TCL_TIP268
- return 1;
-#else
res = 1;
-#endif
} else if (n1 == n2) {
-#ifndef TCL_TIP268
- return 0;
-#else
res = 0;
-#endif
} else {
-#ifndef TCL_TIP268
- return -1;
-#else
res = -1;
}
@@ -2055,35 +1844,31 @@ CheckRequirement(interp, string)
}
if (strchr (dash+1, '-') != NULL) {
/* More dashes found after the first. This is wrong. */
- Tcl_AppendResult(interp, "expected versionMin-versionMax but got \"", string,
- "\"", NULL);
+ Tcl_AppendResult(interp, "expected versionMin-versionMax but got \"",
+ string, "\"", NULL);
return TCL_ERROR;
-#endif
}
-#ifdef TCL_TIP268
/* Exactly one dash is present. Copy the string, split at the location of
* dash and check that both parts are versions. Note that the max part can
* be empty.
*/
- buf = strdup (string);
- dash = buf + (dash - string);
+ DupString(buf, string);
+ dash = buf + (dash - string);
*dash = '\0'; /* buf now <=> min part */
dash ++; /* dash now <=> max part */
- if ((CheckVersionAndConvert(interp, buf, NULL, NULL) != TCL_OK) ||
- ((*dash != '\0') &&
- (CheckVersionAndConvert(interp, dash, NULL, NULL) != TCL_OK))) {
- free (buf);
+ if ((CheckVersionAndConvert(interp, buf, NULL, NULL) != TCL_OK)
+ || ((*dash != '\0')
+ && (CheckVersionAndConvert(interp, dash, NULL, NULL) != TCL_OK))) {
+ ckfree(buf);
return TCL_ERROR;
}
- free (buf);
+ ckfree(buf);
return TCL_OK;
-#endif
}
-#ifdef TCL_TIP268
/*
*----------------------------------------------------------------------
@@ -2104,13 +1889,21 @@ CheckRequirement(interp, string)
static void
AddRequirementsToResult(interp, reqc, reqv)
Tcl_Interp* interp;
- int reqc; /* Requirements constraining the desired version. */
- Tcl_Obj *CONST reqv[]; /* 0 means to use the latest version available. */
+ int reqc; /* Requirements constraining the desired version. */
+ Tcl_Obj *CONST reqv[]; /* 0 means use the latest version available. */
{
if (reqc > 0) {
int i;
for (i = 0; i < reqc; i++) {
- Tcl_AppendResult(interp, " ", TclGetString(reqv[i]), NULL);
+ int length;
+ char *v = Tcl_GetStringFromObj(reqv[i], &length);
+
+ if ((length & 0x1) && (v[length/2] == '-')
+ && (strncmp(v, v+((length+1)/2), length/2) == 0)) {
+ Tcl_AppendResult(interp, " ", v+((length+1)/2), NULL);
+ } else {
+ Tcl_AppendResult(interp, " ", v, NULL);
+ }
}
}
}
@@ -2134,8 +1927,8 @@ AddRequirementsToResult(interp, reqc, reqv)
static void
AddRequirementsToDString(dstring, reqc, reqv)
Tcl_DString* dstring;
- int reqc; /* Requirements constraining the desired version. */
- Tcl_Obj *CONST reqv[]; /* 0 means to use the latest version available. */
+ int reqc; /* Requirements constraining the desired version. */
+ Tcl_Obj *CONST reqv[]; /* 0 means use the latest version available. */
{
if (reqc > 0) {
int i;
@@ -2151,7 +1944,7 @@ AddRequirementsToDString(dstring, reqc, reqv)
/*
*----------------------------------------------------------------------
*
- * AllRequirementSatisfied --
+ * SomeRequirementSatisfied --
*
* This function checks to see whether a version satisfies at
* least one of a set of requirements.
@@ -2169,18 +1962,21 @@ AddRequirementsToDString(dstring, reqc, reqv)
*/
static int
-AllRequirementsSatisfied(availVersionI, reqc, reqv)
- CONST char* availVersionI; /* Candidate version to check against the requirements */
- int reqc; /* Requirements constraining the desired version. */
- Tcl_Obj *CONST reqv[]; /* 0 means to use the latest version available. */
+SomeRequirementSatisfied(availVersionI, reqc, reqv)
+ char *availVersionI; /* Candidate version to check against the
+ * requirements. */
+ int reqc; /* Requirements constraining the desired
+ * version. */
+ Tcl_Obj *CONST reqv[]; /* 0 means use the latest version available. */
{
- int i, satisfies;
+ int i;
- for (satisfies = i = 0; i < reqc; i++) {
- satisfies = RequirementSatisfied(availVersionI, Tcl_GetString(reqv[i]));
- if (satisfies) break;
+ for (i = 0; i < reqc; i++) {
+ if (RequirementSatisfied(availVersionI, Tcl_GetString(reqv[i]))) {
+ return 1;
+ }
}
- return satisfies;
+ return 0;
}
/*
@@ -2204,7 +2000,7 @@ AllRequirementsSatisfied(availVersionI, reqc, reqv)
static int
RequirementSatisfied(havei, req)
- CONST char *havei; /* Version string, of candidate package we have */
+ char *havei; /* Version string, of candidate package we have */
CONST char *req; /* Requirement string the candidate has to satisfy */
{
/* The have candidate is already in internal rep. */
@@ -2226,9 +2022,9 @@ RequirementSatisfied(havei, req)
CheckVersionAndConvert (NULL, req, &reqi, NULL);
strcat (reqi, " -2");
- res = CompareVersions(havei, reqi, &thisIsMajor);
+ res = CompareVersions(havei, reqi, &thisIsMajor);
satisfied = (res == 0) || ((res == 1) && !thisIsMajor);
- Tcl_Free (reqi);
+ ckfree(reqi);
return satisfied;
}
@@ -2237,7 +2033,7 @@ RequirementSatisfied(havei, req)
* versions. Note that the max part can be empty.
*/
- buf = strdup (req);
+ DupString(buf, req);
dash = buf + (dash - req);
*dash = '\0'; /* buf now <=> min part */
dash ++; /* dash now <=> max part */
@@ -2252,8 +2048,8 @@ RequirementSatisfied(havei, req)
CheckVersionAndConvert (NULL, buf, &min, NULL);
strcat (min, " -2");
satisfied = (CompareVersions(havei, min, NULL) >= 0);
- Tcl_Free (min);
- free (buf);
+ ckfree(min);
+ ckfree(buf);
return satisfied;
}
@@ -2274,127 +2070,13 @@ RequirementSatisfied(havei, req)
(CompareVersions(havei, max, NULL) < 0));
}
- Tcl_Free (min);
- Tcl_Free (max);
- free (buf);
+ ckfree(min);
+ ckfree(max);
+ ckfree(buf);
return satisfied;
}
/*
- *----------------------------------------------------------------------
- *
- * ExactRequirement --
- *
- * This function is the core for the translation of -exact requests.
- * It translates the request of the version into a range of versions.
- * The translation was chosen for backwards compatibility.
- *
- * Results:
- * A Tcl_Obj containing the version range as string.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-static Tcl_Obj*
-ExactRequirement(version)
- CONST char* version;
-{
- /* A -exact request for a version X.y is translated into the range
- * X.y-X.(y+1). For example -exact 8.4 means the range "8.4-8.5".
- *
- * This translation was chosen to prevent packages which currently use a
- * 'package require -exact tclversion' from being affected by the core now
- * registering itself as 8.4.x (patchlevel) instead of 8.4
- * (version). Examples are tbcload, compiler, and ITcl.
- *
- * Translating -exact 8.4 to the range "8.4-8.4" instead would require us
- * and everyone else to rebuild these packages to require -exact 8.4.14,
- * or whatever the exact current patchlevel is. A backward compatibility
- * issue with effects similar to the bugfix made in 8.5 now requiring
- * ifneeded and provided versions to match. Instead we have chosen to
- * interpret exactness to not be exactly equal, but to be exact only
- * within the specified level, and allowing variation in the deeper
- * level. More examples:
- *
- * -exact 8 => "8-9"
- * -exact 8.4 => "8.4-8.5"
- * -exact 8.4.14 => "8.4.14-8.4.15"
- * -exact 8.0a2 => "8.0a2-8.0a3"
- */
-
- char* iv;
- int lc, i;
- CONST char** lv;
- char buf [30];
- Tcl_Obj* o = Tcl_NewStringObj (version,-1);
- Tcl_AppendStringsToObj (o, "-", NULL);
-
- /* Assuming valid syntax here */
- CheckVersionAndConvert (NULL, version, &iv, NULL);
-
- /* Split the list into components */
- Tcl_SplitList (NULL, iv, &lc, &lv);
-
- /* Iterate over the components and make them parts of the result. Except
- * for the last, which is handled separately, to allow the
- * incrementation.
- */
-
- for (i=0; i < (lc-1); i++) {
- /* Regular component */
- Tcl_AppendStringsToObj (o, lv[i], NULL);
- /* Separator component */
- i ++;
- if (0 == strcmp ("-1", lv[i])) {
- Tcl_AppendStringsToObj (o, "b", NULL);
- } else if (0 == strcmp ("-2", lv[i])) {
- Tcl_AppendStringsToObj (o, "a", NULL);
- } else {
- Tcl_AppendStringsToObj (o, ".", NULL);
- }
- }
- /* Regular component, last */
- sprintf (buf, "%d", atoi (lv [lc-1]) + 1);
- Tcl_AppendStringsToObj (o, buf, NULL);
-
- ckfree ((char*) lv);
- return o;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * VersionCleanupProc --
- *
- * This function is called to delete the last remember package version
- * string for an interpreter when the interpreter is deleted. It gets
- * invoked via the Tcl AssocData mechanism.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Storage for the version object for interp get deleted.
- *
- *----------------------------------------------------------------------
- */
-
-static void
-VersionCleanupProc (
- ClientData clientData, /* Pointer to remembered version string object
- * for interp. */
- Tcl_Interp *interp) /* Interpreter that is being deleted. */
-{
- Tcl_Obj* ov = (Tcl_Obj*) clientData;
- if (ov != NULL) {
- Tcl_DecrRefCount (ov);
- }
-}
-
-/*
* Local Variables:
* mode: c
* c-basic-offset: 4