summaryrefslogtreecommitdiffstats
path: root/generic/tclOODefineCmds.c
diff options
context:
space:
mode:
Diffstat (limited to 'generic/tclOODefineCmds.c')
-rw-r--r--generic/tclOODefineCmds.c239
1 files changed, 151 insertions, 88 deletions
diff --git a/generic/tclOODefineCmds.c b/generic/tclOODefineCmds.c
index 3d72690..c022e6b 100644
--- a/generic/tclOODefineCmds.c
+++ b/generic/tclOODefineCmds.c
@@ -17,6 +17,13 @@
#include "tclOOInt.h"
/*
+ * The maximum length of fully-qualified object name to use in an errorinfo
+ * message. Longer than this will be curtailed.
+ */
+
+#define OBJNAME_LENGTH_IN_ERRORINFO_LIMIT 30
+
+/*
* Some things that make it easier to declare a slot.
*/
@@ -40,6 +47,8 @@ struct DeclaredSlot {
static inline void BumpGlobalEpoch(Tcl_Interp *interp, Class *classPtr);
static Tcl_Command FindCommand(Tcl_Interp *interp, Tcl_Obj *stringObj,
Tcl_Namespace *const namespacePtr);
+static void GenerateErrorInfo(Tcl_Interp *interp, Object *oPtr,
+ Tcl_Obj *savedNameObj, const char *typeOfSubject);
static inline Class * GetClassInOuterContext(Tcl_Interp *interp,
Tcl_Obj *className, const char *errMsg);
static inline int InitDefineContext(Tcl_Interp *interp,
@@ -414,8 +423,8 @@ RenameDeleteMethod(
if (!useClass) {
if (!oPtr->methodsPtr) {
noSuchMethod:
- Tcl_AppendResult(interp, "method ", TclGetString(fromPtr),
- " does not exist", NULL);
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "method %s does not exist", TclGetString(fromPtr)));
Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "METHOD",
TclGetString(fromPtr), NULL);
return TCL_ERROR;
@@ -429,14 +438,15 @@ RenameDeleteMethod(
&isNew);
if (hPtr == newHPtr) {
renameToSelf:
- Tcl_AppendResult(interp, "cannot rename method to itself",
- NULL);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "cannot rename method to itself", -1));
Tcl_SetErrorCode(interp, "TCL", "OO", "RENAME_TO_SELF", NULL);
return TCL_ERROR;
} else if (!isNew) {
renameToExisting:
- Tcl_AppendResult(interp, "method called ",
- TclGetString(toPtr), " already exists", NULL);
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "method called %s already exists",
+ TclGetString(toPtr)));
Tcl_SetErrorCode(interp, "TCL", "OO", "RENAME_OVER", NULL);
return TCL_ERROR;
}
@@ -504,7 +514,8 @@ TclOOUnknownDefinition(
const char *soughtStr, *matchedStr = NULL;
if (objc < 2) {
- Tcl_AppendResult(interp, "bad call of unknown handler", NULL);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "bad call of unknown handler", -1));
Tcl_SetErrorCode(interp, "TCL", "OO", "BAD_UNKNOWN", NULL);
return TCL_ERROR;
}
@@ -549,7 +560,8 @@ TclOOUnknownDefinition(
}
noMatch:
- Tcl_AppendResult(interp, "invalid command name \"",soughtStr,"\"", NULL);
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "invalid command name \"%s\"", soughtStr));
Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "COMMAND", soughtStr, NULL);
return TCL_ERROR;
}
@@ -637,9 +649,9 @@ InitDefineContext(
int result;
if (namespacePtr == NULL) {
- Tcl_AppendResult(interp,
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
"cannot process definitions; support namespace deleted",
- NULL);
+ -1));
Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL);
return TCL_ERROR;
}
@@ -673,16 +685,25 @@ TclOOGetDefineCmdContext(
Tcl_Interp *interp)
{
Interp *iPtr = (Interp *) interp;
+ Tcl_Object object;
if ((iPtr->varFramePtr == NULL)
|| (iPtr->varFramePtr->isProcCallFrame != FRAME_IS_OO_DEFINE)) {
- Tcl_AppendResult(interp, "this command may only be called from within"
- " the context of an ::oo::define or ::oo::objdefine command",
- NULL);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "this command may only be called from within the context of"
+ " an ::oo::define or ::oo::objdefine command", -1));
Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL);
return NULL;
}
- return (Tcl_Object) iPtr->varFramePtr->clientData;
+ object = iPtr->varFramePtr->clientData;
+ if (Tcl_ObjectDeleted(object)) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "this command cannot be called when the object has been"
+ " deleted", -1));
+ Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL);
+ return NULL;
+ }
+ return object;
}
/*
@@ -719,7 +740,7 @@ GetClassInOuterContext(
return NULL;
}
if (oPtr->classPtr == NULL) {
- Tcl_AppendResult(interp, errMsg, NULL);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(errMsg, -1));
Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "CLASS",
TclGetString(className), NULL);
return NULL;
@@ -730,6 +751,44 @@ GetClassInOuterContext(
/*
* ----------------------------------------------------------------------
*
+ * GenerateErrorInfo --
+ * Factored out code to generate part of the error trace messages.
+ *
+ * ----------------------------------------------------------------------
+ */
+
+static void
+GenerateErrorInfo(
+ Tcl_Interp *interp, /* Where to store the error info trace. */
+ Object *oPtr, /* What object (or class) was being configured
+ * when the error occurred? */
+ Tcl_Obj *savedNameObj, /* Name of object saved from before script was
+ * evaluated, which is needed if the object
+ * goes away part way through execution. OTOH,
+ * if the object isn't deleted then its
+ * current name (post-execution) has to be
+ * used. This matters, because the object
+ * could have been renamed... */
+ const char *typeOfSubject) /* Part of the message, saying whether it was
+ * an object, class or class-as-object that
+ * was being configured. */
+{
+ int length;
+ Tcl_Obj *realNameObj = Tcl_ObjectDeleted((Tcl_Object) oPtr)
+ ? savedNameObj : TclOOObjectName(interp, oPtr);
+ const char *objName = Tcl_GetStringFromObj(realNameObj, &length);
+ int limit = OBJNAME_LENGTH_IN_ERRORINFO_LIMIT;
+ int overflow = (length > limit);
+
+ Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
+ "\n (in definition script for %s \"%.*s%s\" line %d)",
+ typeOfSubject, (overflow ? limit : length), objName,
+ (overflow ? "..." : ""), Tcl_GetErrorLine(interp)));
+}
+
+/*
+ * ----------------------------------------------------------------------
+ *
* TclOODefineObjCmd --
* Implementation of the "oo::define" command. Works by effectively doing
* the same as 'namespace eval', but with extra magic applied so that the
@@ -761,8 +820,8 @@ TclOODefineObjCmd(
return TCL_ERROR;
}
if (oPtr->classPtr == NULL) {
- Tcl_AppendResult(interp, TclGetString(objv[1]),
- " does not refer to a class", NULL);
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "%s does not refer to a class",TclGetString(objv[1])));
Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "CLASS",
TclGetString(objv[1]), NULL);
return TCL_ERROR;
@@ -779,20 +838,15 @@ TclOODefineObjCmd(
AddRef(oPtr);
if (objc == 3) {
+ Tcl_Obj *objNameObj = TclOOObjectName(interp, oPtr);
+
+ Tcl_IncrRefCount(objNameObj);
result = TclEvalObjEx(interp, objv[2], 0,
((Interp *)interp)->cmdFramePtr, 2);
-
if (result == TCL_ERROR) {
- int length;
- const char *objName = Tcl_GetStringFromObj(objv[1], &length);
- int limit = 60;
- int overflow = (length > limit);
-
- Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
- "\n (in definition script for object \"%.*s%s\" line %d)",
- (overflow ? limit : length), objName,
- (overflow ? "..." : ""), Tcl_GetErrorLine(interp)));
+ GenerateErrorInfo(interp, oPtr, objNameObj, "class");
}
+ TclDecrRefCount(objNameObj);
} else {
Tcl_Obj *objPtr, *obj2Ptr, **objs;
Interp *iPtr = (Interp *) interp;
@@ -898,20 +952,15 @@ TclOOObjDefObjCmd(
AddRef(oPtr);
if (objc == 3) {
+ Tcl_Obj *objNameObj = TclOOObjectName(interp, oPtr);
+
+ Tcl_IncrRefCount(objNameObj);
result = TclEvalObjEx(interp, objv[2], 0,
((Interp *)interp)->cmdFramePtr, 2);
-
if (result == TCL_ERROR) {
- int length;
- const char *objName = Tcl_GetStringFromObj(objv[1], &length);
- int limit = 60;
- int overflow = (length > limit);
-
- Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
- "\n (in definition script for object \"%.*s%s\" line %d)",
- (overflow ? limit : length), objName,
- (overflow ? "..." : ""), Tcl_GetErrorLine(interp)));
+ GenerateErrorInfo(interp, oPtr, objNameObj, "object");
}
+ TclDecrRefCount(objNameObj);
} else {
Tcl_Obj *objPtr, *obj2Ptr, **objs;
Interp *iPtr = (Interp *) interp;
@@ -1017,21 +1066,15 @@ TclOODefineSelfObjCmd(
AddRef(oPtr);
if (objc == 2) {
+ Tcl_Obj *objNameObj = TclOOObjectName(interp, oPtr);
+
+ Tcl_IncrRefCount(objNameObj);
result = TclEvalObjEx(interp, objv[1], 0,
((Interp *)interp)->cmdFramePtr, 2);
-
if (result == TCL_ERROR) {
- int length;
- const char *objName = Tcl_GetStringFromObj(
- TclOOObjectName(interp, oPtr), &length);
- int limit = 60;
- int overflow = (length > limit);
-
- Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
- "\n (in definition script for object \"%.*s%s\" line %d)",
- (overflow ? limit : length), objName,
- (overflow ? "..." : ""), Tcl_GetErrorLine(interp)));
+ GenerateErrorInfo(interp, oPtr, objNameObj, "class object");
}
+ TclDecrRefCount(objNameObj);
} else {
Tcl_Obj *objPtr, *obj2Ptr, **objs;
Interp *iPtr = (Interp *) interp;
@@ -1122,14 +1165,14 @@ TclOODefineClassObjCmd(
return TCL_ERROR;
}
if (oPtr->flags & ROOT_OBJECT) {
- Tcl_AppendResult(interp,
- "may not modify the class of the root object class", NULL);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "may not modify the class of the root object class", -1));
Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL);
return TCL_ERROR;
}
if (oPtr->flags & ROOT_CLASS) {
- Tcl_AppendResult(interp,
- "may not modify the class of the class of classes", NULL);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "may not modify the class of the class of classes", -1));
Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL);
return TCL_ERROR;
}
@@ -1155,9 +1198,10 @@ TclOODefineClassObjCmd(
*/
if ((oPtr->classPtr==NULL) == TclOOIsReachable(fPtr->classCls, clsPtr)) {
- Tcl_AppendResult(interp, "may not change a ",
- (oPtr->classPtr==NULL ? "non-" : ""), "class object into a ",
- (oPtr->classPtr==NULL ? "" : "non-"), "class object", NULL);
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "may not change a %sclass object into a %sclass object",
+ (oPtr->classPtr==NULL ? "non-" : ""),
+ (oPtr->classPtr==NULL ? "" : "non-")));
Tcl_SetErrorCode(interp, "TCL", "OO", "TRANSMUTATION", NULL);
return TCL_ERROR;
}
@@ -1278,7 +1322,8 @@ TclOODefineDeleteMethodObjCmd(
return TCL_ERROR;
}
if (!isInstanceDeleteMethod && !oPtr->classPtr) {
- Tcl_AppendResult(interp, "attempt to misuse API", NULL);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "attempt to misuse API", -1));
Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL);
return TCL_ERROR;
}
@@ -1401,7 +1446,8 @@ TclOODefineExportObjCmd(
}
clsPtr = oPtr->classPtr;
if (!isInstanceExport && !clsPtr) {
- Tcl_AppendResult(interp, "attempt to misuse API", NULL);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "attempt to misuse API", -1));
Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL);
return TCL_ERROR;
}
@@ -1492,7 +1538,8 @@ TclOODefineForwardObjCmd(
return TCL_ERROR;
}
if (!isInstanceForward && !oPtr->classPtr) {
- Tcl_AppendResult(interp, "attempt to misuse API", NULL);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "attempt to misuse API", -1));
Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL);
return TCL_ERROR;
}
@@ -1549,7 +1596,8 @@ TclOODefineMethodObjCmd(
return TCL_ERROR;
}
if (!isInstanceMethod && !oPtr->classPtr) {
- Tcl_AppendResult(interp, "attempt to misuse API", NULL);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "attempt to misuse API", -1));
Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL);
return TCL_ERROR;
}
@@ -1600,7 +1648,8 @@ TclOODefineMixinObjCmd(
return TCL_ERROR;
}
if (!isInstanceMixin && !oPtr->classPtr) {
- Tcl_AppendResult(interp, "attempt to misuse API", NULL);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "attempt to misuse API", -1));
Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL);
return TCL_ERROR;
}
@@ -1614,7 +1663,8 @@ TclOODefineMixinObjCmd(
goto freeAndError;
}
if (!isInstanceMixin && TclOOIsReachable(oPtr->classPtr, clsPtr)) {
- Tcl_AppendResult(interp, "may not mix a class into itself", NULL);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "may not mix a class into itself", -1));
Tcl_SetErrorCode(interp, "TCL", "OO", "SELF_MIXIN", NULL);
goto freeAndError;
}
@@ -1665,7 +1715,8 @@ TclOODefineRenameMethodObjCmd(
return TCL_ERROR;
}
if (!isInstanceRenameMethod && !oPtr->classPtr) {
- Tcl_AppendResult(interp, "attempt to misuse API", NULL);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "attempt to misuse API", -1));
Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL);
return TCL_ERROR;
}
@@ -1725,7 +1776,8 @@ TclOODefineUnexportObjCmd(
}
clsPtr = oPtr->classPtr;
if (!isInstanceUnexport && !clsPtr) {
- Tcl_AppendResult(interp, "attempt to misuse API", NULL);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "attempt to misuse API", -1));
Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL);
return TCL_ERROR;
}
@@ -1910,7 +1962,8 @@ ClassFilterGet(
if (oPtr == NULL) {
return TCL_ERROR;
} else if (!oPtr->classPtr) {
- Tcl_AppendResult(interp, "attempt to misuse API", NULL);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "attempt to misuse API", -1));
Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL);
return TCL_ERROR;
}
@@ -1945,7 +1998,8 @@ ClassFilterSet(
if (oPtr == NULL) {
return TCL_ERROR;
} else if (!oPtr->classPtr) {
- Tcl_AppendResult(interp, "attempt to misuse API", NULL);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "attempt to misuse API", -1));
Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL);
return TCL_ERROR;
} else if (Tcl_ListObjGetElements(interp, objv[0], &filterc,
@@ -1988,7 +2042,8 @@ ClassMixinGet(
if (oPtr == NULL) {
return TCL_ERROR;
} else if (!oPtr->classPtr) {
- Tcl_AppendResult(interp, "attempt to misuse API", NULL);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "attempt to misuse API", -1));
Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL);
return TCL_ERROR;
}
@@ -2026,7 +2081,8 @@ ClassMixinSet(
if (oPtr == NULL) {
return TCL_ERROR;
} else if (!oPtr->classPtr) {
- Tcl_AppendResult(interp, "attempt to misuse API", NULL);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "attempt to misuse API", -1));
Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL);
return TCL_ERROR;
} else if (Tcl_ListObjGetElements(interp, objv[0], &mixinc,
@@ -2043,7 +2099,8 @@ ClassMixinSet(
goto freeAndError;
}
if (TclOOIsReachable(oPtr->classPtr, mixins[i])) {
- Tcl_AppendResult(interp, "may not mix a class into itself", NULL);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "may not mix a class into itself", -1));
Tcl_SetErrorCode(interp, "TCL", "OO", "SELF_MIXIN", NULL);
goto freeAndError;
}
@@ -2089,7 +2146,8 @@ ClassSuperGet(
if (oPtr == NULL) {
return TCL_ERROR;
} else if (!oPtr->classPtr) {
- Tcl_AppendResult(interp, "attempt to misuse API", NULL);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "attempt to misuse API", -1));
Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL);
return TCL_ERROR;
}
@@ -2126,12 +2184,13 @@ ClassSuperSet(
if (oPtr == NULL) {
return TCL_ERROR;
} else if (!oPtr->classPtr) {
- Tcl_AppendResult(interp, "attempt to misuse API", NULL);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "attempt to misuse API", -1));
Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL);
return TCL_ERROR;
} else if (oPtr == oPtr->fPtr->objectCls->thisPtr) {
- Tcl_AppendResult(interp,
- "may not modify the superclass of the root object", NULL);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "may not modify the superclass of the root object", -1));
Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL);
return TCL_ERROR;
} else if (Tcl_ListObjGetElements(interp, objv[0], &superc,
@@ -2157,15 +2216,15 @@ ClassSuperSet(
}
for (j=0 ; j<i ; j++) {
if (superclasses[j] == superclasses[i]) {
- Tcl_AppendResult(interp,
- "class should only be a direct superclass once",NULL);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "class should only be a direct superclass once", -1));
Tcl_SetErrorCode(interp, "TCL", "OO", "REPETITIOUS", NULL);
goto failedAfterAlloc;
}
}
if (TclOOIsReachable(oPtr->classPtr, superclasses[i])) {
- Tcl_AppendResult(interp,
- "attempt to form circular dependency graph", NULL);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "attempt to form circular dependency graph", -1));
Tcl_SetErrorCode(interp, "TCL", "OO", "CIRCULARITY", NULL);
failedAfterAlloc:
ckfree((char *) superclasses);
@@ -2226,7 +2285,8 @@ ClassVarsGet(
if (oPtr == NULL) {
return TCL_ERROR;
} else if (!oPtr->classPtr) {
- Tcl_AppendResult(interp, "attempt to misuse API", NULL);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "attempt to misuse API", -1));
Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL);
return TCL_ERROR;
}
@@ -2262,7 +2322,8 @@ ClassVarsSet(
if (oPtr == NULL) {
return TCL_ERROR;
} else if (!oPtr->classPtr) {
- Tcl_AppendResult(interp, "attempt to misuse API", NULL);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "attempt to misuse API", -1));
Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL);
return TCL_ERROR;
} else if (Tcl_ListObjGetElements(interp, objv[0], &varc,
@@ -2274,15 +2335,16 @@ ClassVarsSet(
const char *varName = Tcl_GetString(varv[i]);
if (strstr(varName, "::") != NULL) {
- Tcl_AppendResult(interp, "invalid declared variable name \"",
- varName, "\": must not contain namespace separators",
- NULL);
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "invalid declared variable name \"%s\": must not %s",
+ varName, "contain namespace separators"));
Tcl_SetErrorCode(interp, "TCL", "OO", "BAD_DECLVAR", NULL);
return TCL_ERROR;
}
if (Tcl_StringMatch(varName, "*(*)")) {
- Tcl_AppendResult(interp, "invalid declared variable name \"",
- varName, "\": must not refer to an array element", NULL);
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "invalid declared variable name \"%s\": must not %s",
+ varName, "refer to an array element"));
Tcl_SetErrorCode(interp, "TCL", "OO", "BAD_DECLVAR", NULL);
return TCL_ERROR;
}
@@ -2552,15 +2614,16 @@ ObjVarsSet(
const char *varName = Tcl_GetString(varv[i]);
if (strstr(varName, "::") != NULL) {
- Tcl_AppendResult(interp, "invalid declared variable name \"",
- varName, "\": must not contain namespace separators",
- NULL);
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "invalid declared variable name \"%s\": must not %s",
+ varName, "contain namespace separators"));
Tcl_SetErrorCode(interp, "TCL", "OO", "BAD_DECLVAR", NULL);
return TCL_ERROR;
}
if (Tcl_StringMatch(varName, "*(*)")) {
- Tcl_AppendResult(interp, "invalid declared variable name \"",
- varName, "\": must not refer to an array element", NULL);
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "invalid declared variable name \"%s\": must not %s",
+ varName, "refer to an array element"));
Tcl_SetErrorCode(interp, "TCL", "OO", "BAD_DECLVAR", NULL);
return TCL_ERROR;
}
lass="hl opt">; delete memberGroupSDict; } /*! Compute the HTML anchor names for all members in the class */ void FileDef::computeAnchors() { MemberList *ml = getMemberList(MemberList::allMembersList); if (ml) setAnchors(0,'a',ml); } void FileDef::distributeMemberGroupDocumentation() { //printf("FileDef::distributeMemberGroupDocumentation()\n"); if (memberGroupSDict) { MemberGroupSDict::Iterator mgli(*memberGroupSDict); MemberGroup *mg; for (;(mg=mgli.current());++mgli) { mg->distributeMemberGroupDocumentation(); } } } void FileDef::findSectionsInDocumentation() { docFindSections(documentation(),this,0,docFile()); if (memberGroupSDict) { MemberGroupSDict::Iterator mgli(*memberGroupSDict); MemberGroup *mg; for (;(mg=mgli.current());++mgli) { mg->findSectionsInDocumentation(); } } QListIterator<MemberList> mli(m_memberLists); MemberList *ml; for (mli.toFirst();(ml=mli.current());++mli) { if (ml->listType()&MemberList::declarationLists) { ml->findSectionsInDocumentation(); } } } void FileDef::writeDetailedDescription(OutputList &ol,const QCString &title) { if ((!briefDescription().isEmpty() && Config_getBool("REPEAT_BRIEF")) || !documentation().isEmpty() || (Config_getBool("SOURCE_BROWSER") && getStartBodyLine()!=-1 && getBodyDef()) ) { ol.writeRuler(); ol.pushGeneratorState(); ol.disableAllBut(OutputGenerator::Html); ol.writeAnchor(0,"details"); ol.popGeneratorState(); ol.startGroupHeader(); ol.parseText(title); ol.endGroupHeader(); ol.startTextBlock(); if (!briefDescription().isEmpty() && Config_getBool("REPEAT_BRIEF")) { ol.parseDoc(briefFile(),briefLine(),this,0,briefDescription(),FALSE,FALSE); } if (!briefDescription().isEmpty() && Config_getBool("REPEAT_BRIEF") && !documentation().isEmpty()) { ol.pushGeneratorState(); ol.disable(OutputGenerator::Man); ol.disable(OutputGenerator::RTF); // ol.newParagraph(); // FIXME:PARA ol.enableAll(); ol.disableAllBut(OutputGenerator::Man); ol.writeString("\n\n"); ol.popGeneratorState(); } if (!documentation().isEmpty()) { ol.parseDoc(docFile(),docLine(),this,0,documentation()+"\n",TRUE,FALSE); } //printf("Writing source ref for file %s\n",name().data()); if (Config_getBool("SOURCE_BROWSER")) { ol.startParagraph(); QCString refText = theTranslator->trDefinedInSourceFile(); int fileMarkerPos = refText.find("@0"); if (fileMarkerPos!=-1) // should always pass this. { ol.parseText(refText.left(fileMarkerPos)); //text left from marker 1 ol.writeObjectLink(0,getSourceFileBase(), 0,name()); ol.parseText(refText.right( refText.length()-fileMarkerPos-2)); // text right from marker 2 } ol.endParagraph(); } ol.endTextBlock(); } } void FileDef::writeBriefDescription(OutputList &ol) { if (!briefDescription().isEmpty() && Config_getBool("BRIEF_MEMBER_DESC")) { ol.startParagraph(); ol.parseDoc(briefFile(),briefLine(),this,0, briefDescription(),TRUE,FALSE,0,TRUE,FALSE); ol.pushGeneratorState(); ol.disable(OutputGenerator::RTF); ol.writeString(" \n"); ol.enable(OutputGenerator::RTF); if (Config_getBool("REPEAT_BRIEF") || !documentation().isEmpty() ) { ol.disableAllBut(OutputGenerator::Html); ol.startTextLink(0,"details"); ol.parseText(theTranslator->trMore()); ol.endTextLink(); } ol.popGeneratorState(); ol.endParagraph(); //ol.pushGeneratorState(); //ol.disable(OutputGenerator::RTF); //ol.newParagraph(); //ol.popGeneratorState(); } ol.writeSynopsis(); } void FileDef::writeIncludeFiles(OutputList &ol) { if (/*Config_getBool("SHOW_INCLUDE_FILES") &&*/ includeList && includeList->count()>0) { ol.startTextBlock(TRUE); QListIterator<IncludeInfo> ili(*includeList); IncludeInfo *ii; for (;(ii=ili.current());++ili) { if (!ii->indirect) { FileDef *fd=ii->fileDef; bool isIDLorJava = FALSE; if (fd) { SrcLangExt lang = fd->getLanguage(); isIDLorJava = lang==SrcLangExt_IDL || lang==SrcLangExt_Java; } ol.startTypewriter(); if (isIDLorJava) // IDL/Java include { ol.docify("import "); } else if (ii->imported) // Objective-C include { ol.docify("#import "); } else // C/C++ include { ol.docify("#include "); } if (ii->local || isIDLorJava) ol.docify("\""); else ol.docify("<"); ol.disable(OutputGenerator::Html); ol.docify(ii->includeName); ol.enableAll(); ol.disableAllBut(OutputGenerator::Html); // Here we use the include file name as it appears in the file. // we could also we the name as it is used within doxygen, // then we should have used fd->docName() instead of ii->includeName if (fd && fd->isLinkable()) { ol.writeObjectLink(fd->getReference(), fd->generateSourceFile() ? fd->includeName() : fd->getOutputFileBase(), 0,ii->includeName); if (!Config_getString("GENERATE_TAGFILE").isEmpty() && !fd->isReference()) { const char *locStr = (ii->local || isIDLorJava) ? "yes" : "no"; const char *impStr = (ii->imported || isIDLorJava) ? "yes" : "no"; Doxygen::tagFile << " <includes id=\"" << convertToXML(fd->getOutputFileBase()) << "\" " << "name=\"" << convertToXML(fd->name()) << "\" " << "local=\"" << locStr << "\" " << "imported=\"" << impStr << "\">" << convertToXML(ii->includeName) << "</includes>" << endl; } } else { ol.docify(ii->includeName); } ol.enableAll(); if (ii->local || isIDLorJava) ol.docify("\""); else ol.docify(">"); if (isIDLorJava) ol.docify(";"); ol.endTypewriter(); ol.lineBreak(); } } ol.endTextBlock(); } } void FileDef::writeIncludeGraph(OutputList &ol) { if (Config_getBool("HAVE_DOT") /*&& Config_getBool("INCLUDE_GRAPH")*/) { //printf("Graph for file %s\n",name().data()); DotInclDepGraph incDepGraph(this,FALSE); if (!incDepGraph.isTrivial() && !incDepGraph.isTooBig()) { ol.startTextBlock(); ol.disable(OutputGenerator::Man); ol.startInclDepGraph(); ol.parseText(theTranslator->trInclDepGraph(name())); ol.endInclDepGraph(incDepGraph); ol.enableAll(); ol.endTextBlock(TRUE); } //incDepGraph.writeGraph(Config_getString("HTML_OUTPUT"),fd->getOutputFileBase()); } } void FileDef::writeIncludedByGraph(OutputList &ol) { if (Config_getBool("HAVE_DOT") /*&& Config_getBool("INCLUDED_BY_GRAPH")*/) { //printf("Graph for file %s\n",name().data()); DotInclDepGraph incDepGraph(this,TRUE); if (!incDepGraph.isTrivial() && !incDepGraph.isTooBig()) { ol.startTextBlock(); ol.disable(OutputGenerator::Man); ol.startInclDepGraph(); ol.parseText(theTranslator->trInclByDepGraph()); ol.endInclDepGraph(incDepGraph); ol.enableAll(); ol.endTextBlock(TRUE); } //incDepGraph.writeGraph(Config_getString("HTML_OUTPUT"),fd->getOutputFileBase()); } } void FileDef::writeSourceLink(OutputList &ol) { //printf("%s: generateSourceFile()=%d\n",name().data(),generateSourceFile()); if (generateSourceFile()) { ol.disableAllBut(OutputGenerator::Html); ol.startParagraph(); ol.startTextLink(includeName(),0); ol.parseText(theTranslator->trGotoSourceCode()); ol.endTextLink(); ol.endParagraph(); ol.enableAll(); } } void FileDef::writeNamespaceDeclarations(OutputList &ol,const QCString &title) { // write list of namespaces if (namespaceSDict) namespaceSDict->writeDeclaration(ol,title); } void FileDef::writeClassDeclarations(OutputList &ol,const QCString &title) { // write list of classes if (classSDict) classSDict->writeDeclaration(ol,0,title,FALSE); } void FileDef::writeInlineClasses(OutputList &ol) { if (classSDict) classSDict->writeDocumentation(ol,this); } void FileDef::startMemberDeclarations(OutputList &ol) { ol.startMemberSections(); } void FileDef::endMemberDeclarations(OutputList &ol) { ol.endMemberSections(); } void FileDef::startMemberDocumentation(OutputList &ol) { if (Config_getBool("SEPARATE_MEMBER_PAGES")) { ol.disable(OutputGenerator::Html); Doxygen::suppressDocWarnings = TRUE; } } void FileDef::endMemberDocumentation(OutputList &ol) { if (Config_getBool("SEPARATE_MEMBER_PAGES")) { ol.enable(OutputGenerator::Html); Doxygen::suppressDocWarnings = FALSE; } } void FileDef::writeMemberGroups(OutputList &ol) { /* write user defined member groups */ if (memberGroupSDict) { memberGroupSDict->sort(); MemberGroupSDict::Iterator mgli(*memberGroupSDict); MemberGroup *mg; for (;(mg=mgli.current());++mgli) { if ((!mg->allMembersInSameSection() || !m_subGrouping) && mg->header()!="[NOHEADER]") { mg->writeDeclarations(ol,0,0,this,0); } } } } void FileDef::writeAuthorSection(OutputList &ol) { // write Author section (Man only) ol.pushGeneratorState(); ol.disableAllBut(OutputGenerator::Man); ol.startGroupHeader(); ol.parseText(theTranslator->trAuthor(TRUE,TRUE)); ol.endGroupHeader(); ol.parseText(theTranslator->trGeneratedAutomatically(Config_getString("PROJECT_NAME"))); ol.popGeneratorState(); } void FileDef::writeSummaryLinks(OutputList &ol) { ol.pushGeneratorState(); ol.disableAllBut(OutputGenerator::Html); QListIterator<LayoutDocEntry> eli( LayoutDocManager::instance().docEntries(LayoutDocManager::File)); LayoutDocEntry *lde; bool first=TRUE; for (eli.toFirst();(lde=eli.current());++eli) { if ((lde->kind()==LayoutDocEntry::FileClasses && classSDict && classSDict->declVisible()) || (lde->kind()==LayoutDocEntry::FileNamespaces && namespaceSDict && namespaceSDict->declVisible()) ) { LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde; QCString label = lde->kind()==LayoutDocEntry::FileClasses ? "nested-classes" : "namespaces"; writeSummaryLink(ol,label,ls->title,first); } else if (lde->kind()==LayoutDocEntry::MemberDecl) { LayoutDocEntryMemberDecl *lmd = (LayoutDocEntryMemberDecl*)lde; MemberList * ml = getMemberList(lmd->type); if (ml && ml->declVisible()) { writeSummaryLink(ol,ml->listTypeAsString(),lmd->title,first); } } } if (!first) { ol.writeString(" </div>\n"); } ol.popGeneratorState(); } /*! Write the documentation page for this file to the file of output generators \a ol. */ void FileDef::writeDocumentation(OutputList &ol) { static bool generateTreeView = Config_getBool("GENERATE_TREEVIEW"); //funcList->countDecMembers(); //QCString fn = name(); //if (Config_getBool("FULL_PATH_NAMES")) //{ // fn.prepend(stripFromPath(getPath().copy())); //} //printf("WriteDocumentation diskname=%s\n",diskname.data()); QCString versionTitle; if (!fileVersion.isEmpty()) { versionTitle=("("+fileVersion+")"); } QCString title = docname+versionTitle; QCString pageTitle=theTranslator->trFileReference(docname); if (getDirDef()) { startFile(ol,getOutputFileBase(),name(),pageTitle,HLI_FileVisible,!generateTreeView); if (!generateTreeView) { getDirDef()->writeNavigationPath(ol); ol.endQuickIndices(); } QCString pageTitleShort=theTranslator->trFileReference(name()); startTitle(ol,getOutputFileBase(),this); ol.pushGeneratorState(); ol.disableAllBut(OutputGenerator::Html); ol.parseText(pageTitleShort); // Html only ol.enableAll(); ol.disable(OutputGenerator::Html); ol.parseText(pageTitle); // other output formats ol.popGeneratorState(); addGroupListToTitle(ol,this); endTitle(ol,getOutputFileBase(),title); } else { startFile(ol,getOutputFileBase(),name(),pageTitle,HLI_FileVisible,!generateTreeView); if (!generateTreeView) { ol.endQuickIndices(); } startTitle(ol,getOutputFileBase(),this); ol.parseText(pageTitle); addGroupListToTitle(ol,this); endTitle(ol,getOutputFileBase(),title); } ol.startContents(); if (!fileVersion.isEmpty()) { ol.disableAllBut(OutputGenerator::Html); ol.startProjectNumber(); ol.docify(versionTitle); ol.endProjectNumber(); ol.enableAll(); } if (Doxygen::searchIndex) { Doxygen::searchIndex->setCurrentDoc(pageTitle,getOutputFileBase()); Doxygen::searchIndex->addWord(localName(),TRUE); } if (!Config_getString("GENERATE_TAGFILE").isEmpty()) { Doxygen::tagFile << " <compound kind=\"file\">" << endl; Doxygen::tagFile << " <name>" << convertToXML(name()) << "</name>" << endl; Doxygen::tagFile << " <path>" << convertToXML(getPath()) << "</path>" << endl; Doxygen::tagFile << " <filename>" << convertToXML(getOutputFileBase()) << "</filename>" << endl; } //---------------------------------------- start flexible part ------------------------------- QListIterator<LayoutDocEntry> eli( LayoutDocManager::instance().docEntries(LayoutDocManager::File)); LayoutDocEntry *lde; for (eli.toFirst();(lde=eli.current());++eli) { switch (lde->kind()) { case LayoutDocEntry::BriefDesc: writeBriefDescription(ol); break; case LayoutDocEntry::MemberDeclStart: startMemberDeclarations(ol); break; case LayoutDocEntry::FileIncludes: writeIncludeFiles(ol); break; case LayoutDocEntry::FileIncludeGraph: writeIncludeGraph(ol); break; case LayoutDocEntry::FileIncludedByGraph: writeIncludedByGraph(ol); break; case LayoutDocEntry::FileSourceLink: writeSourceLink(ol); break; case LayoutDocEntry::FileClasses: { LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde; writeClassDeclarations(ol,ls->title); } break; case LayoutDocEntry::FileNamespaces: { LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde; writeNamespaceDeclarations(ol,ls->title); } break; case LayoutDocEntry::MemberGroups: writeMemberGroups(ol); break; case LayoutDocEntry::MemberDecl: { LayoutDocEntryMemberDecl *lmd = (LayoutDocEntryMemberDecl*)lde; writeMemberDeclarations(ol,lmd->type,lmd->title); } break; case LayoutDocEntry::MemberDeclEnd: endMemberDeclarations(ol); break; case LayoutDocEntry::DetailedDesc: { LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde; writeDetailedDescription(ol,ls->title); } break; case LayoutDocEntry::MemberDefStart: startMemberDocumentation(ol); break; case LayoutDocEntry::FileInlineClasses: writeInlineClasses(ol); break; case LayoutDocEntry::MemberDef: { LayoutDocEntryMemberDef *lmd = (LayoutDocEntryMemberDef*)lde; writeMemberDocumentation(ol,lmd->type,lmd->title); } break; case LayoutDocEntry::MemberDefEnd: endMemberDocumentation(ol); break; case LayoutDocEntry::AuthorSection: writeAuthorSection(ol); break; case LayoutDocEntry::ClassIncludes: case LayoutDocEntry::ClassInheritanceGraph: case LayoutDocEntry::ClassNestedClasses: case LayoutDocEntry::ClassCollaborationGraph: case LayoutDocEntry::ClassAllMembersLink: case LayoutDocEntry::ClassUsedFiles: case LayoutDocEntry::ClassInlineClasses: case LayoutDocEntry::NamespaceNestedNamespaces: case LayoutDocEntry::NamespaceClasses: case LayoutDocEntry::NamespaceInlineClasses: case LayoutDocEntry::GroupClasses: case LayoutDocEntry::GroupInlineClasses: case LayoutDocEntry::GroupNamespaces: case LayoutDocEntry::GroupDirs: case LayoutDocEntry::GroupNestedGroups: case LayoutDocEntry::GroupFiles: case LayoutDocEntry::GroupGraph: case LayoutDocEntry::GroupPageDocs: case LayoutDocEntry::DirSubDirs: case LayoutDocEntry::DirFiles: case LayoutDocEntry::DirGraph: err("Internal inconsistency: member %d should not be part of " "LayoutDocManager::File entry list\n",lde->kind()); break; } } //---------------------------------------- end flexible part ------------------------------- if (!Config_getString("GENERATE_TAGFILE").isEmpty()) { writeDocAnchorsToTagFile(); Doxygen::tagFile << " </compound>" << endl; } ol.endContents(); endFileWithNavPath(this,ol); if (Config_getBool("SEPARATE_MEMBER_PAGES")) { MemberList *ml = getMemberList(MemberList::allMembersList); if (ml) ml->sort(); writeMemberPages(ol); } } void FileDef::writeMemberPages(OutputList &ol) { ol.pushGeneratorState(); ol.disableAllBut(OutputGenerator::Html); QListIterator<MemberList> mli(m_memberLists); MemberList *ml; for (mli.toFirst();(ml=mli.current());++mli) { if (ml->listType()&MemberList::documentationLists) { ml->writeDocumentationPage(ol,name(),this); } } ol.popGeneratorState(); } void FileDef::writeQuickMemberLinks(OutputList &ol,MemberDef *currentMd) const { static bool createSubDirs=Config_getBool("CREATE_SUBDIRS"); ol.writeString(" <div class=\"navtab\">\n"); ol.writeString(" <table>\n"); MemberList *allMemberList = getMemberList(MemberList::allMembersList); if (allMemberList) { MemberListIterator mli(*allMemberList); MemberDef *md; for (mli.toFirst();(md=mli.current());++mli) { if (md->getFileDef()==this && md->getNamespaceDef()==0 && md->isLinkable()) { ol.writeString(" <tr><td class=\"navtab\">"); if (md->isLinkableInProject()) { if (md==currentMd) // selected item => highlight { ol.writeString("<a class=\"qindexHL\" "); } else { ol.writeString("<a class=\"qindex\" "); } ol.writeString("href=\""); if (createSubDirs) ol.writeString("../../"); ol.writeString(md->getOutputFileBase()+Doxygen::htmlFileExtension+"#"+md->anchor()); ol.writeString("\">"); ol.writeString(convertToHtml(md->localName())); ol.writeString("</a>"); } ol.writeString("</td></tr>\n"); } } } ol.writeString(" </table>\n"); ol.writeString(" </div>\n"); } /*! Write a source listing of this file to the output */ void FileDef::writeSource(OutputList &ol) { static bool generateTreeView = Config_getBool("GENERATE_TREEVIEW"); static bool filterSourceFiles = Config_getBool("FILTER_SOURCE_FILES"); static bool latexSourceCode = Config_getBool("LATEX_SOURCE_CODE"); QCString title = docname; if (!fileVersion.isEmpty()) { title+=(" ("+fileVersion+")"); } QCString pageTitle = theTranslator->trSourceFile(title); ol.disable(OutputGenerator::Man); ol.disable(OutputGenerator::RTF); if (!latexSourceCode) ol.disable(OutputGenerator::Latex); if (getDirDef()) { startFile(ol,getSourceFileBase(),0,pageTitle,HLI_FileVisible, !generateTreeView,getOutputFileBase()); if (!generateTreeView) { getDirDef()->writeNavigationPath(ol); ol.endQuickIndices(); } startTitle(ol,getOutputFileBase()); ol.parseText(name()); endTitle(ol,getOutputFileBase(),title); } else { startFile(ol,getSourceFileBase(),0,pageTitle,HLI_FileVisible, FALSE,getOutputFileBase()); startTitle(ol,getSourceFileBase()); ol.parseText(title); endTitle(ol,getSourceFileBase(),0); } ol.startContents(); if (isLinkable()) { if (latexSourceCode) ol.disable(OutputGenerator::Latex); ol.startTextLink(getOutputFileBase(),0); ol.parseText(theTranslator->trGotoDocumentation()); ol.endTextLink(); if (latexSourceCode) ol.enable(OutputGenerator::Latex); } ParserInterface *pIntf = Doxygen::parserManager->getParser(getDefFileExtension()); pIntf->resetCodeParserState(); ol.startCodeFragment(); pIntf->parseCode(ol,0, fileToString(absFilePath(),filterSourceFiles,TRUE), FALSE,0,this ); ol.endCodeFragment(); ol.endContents(); endFileWithNavPath(this,ol); ol.enableAll(); } void FileDef::parseSource() { static bool filterSourceFiles = Config_getBool("FILTER_SOURCE_FILES"); DevNullCodeDocInterface devNullIntf; ParserInterface *pIntf = Doxygen::parserManager->getParser(getDefFileExtension()); pIntf->resetCodeParserState(); pIntf->parseCode( devNullIntf,0, fileToString(absFilePath(),filterSourceFiles,TRUE), FALSE,0,this ); } void FileDef::addMembersToMemberGroup() { QListIterator<MemberList> mli(m_memberLists); MemberList *ml; for (mli.toFirst();(ml=mli.current());++mli) { if (ml->listType()&MemberList::declarationLists) { ::addMembersToMemberGroup(ml,&memberGroupSDict,this); } } // add members inside sections to their groups if (memberGroupSDict) { MemberGroupSDict::Iterator mgli(*memberGroupSDict); MemberGroup *mg; for (;(mg=mgli.current());++mgli) { if (mg->allMembersInSameSection() && m_subGrouping) { //printf("----> addToDeclarationSection(%s)\n",mg->header().data()); mg->addToDeclarationSection(); } } } } /*! Adds member definition \a md to the list of all members of this file */ void FileDef::insertMember(MemberDef *md) { if (md->isHidden()) return; //printf("%s:FileDef::insertMember(%s (=%p) list has %d elements)\n", // name().data(),md->name().data(),md,allMemberList.count()); MemberList *allMemberList = getMemberList(MemberList::allMembersList); if (allMemberList && allMemberList->findRef(md)!=-1) // TODO optimize the findRef! { return; } if (allMemberList==0) { allMemberList = new MemberList(MemberList::allMembersList);; m_memberLists.append(allMemberList); } allMemberList->append(md); //::addFileMemberNameToIndex(md); switch (md->memberType()) { case MemberDef::Variable: case MemberDef::Property: addMemberToList(MemberList::decVarMembers,md); addMemberToList(MemberList::docVarMembers,md); break; case MemberDef::Function: addMemberToList(MemberList::decFuncMembers,md); addMemberToList(MemberList::docFuncMembers,md); break; case MemberDef::Typedef: addMemberToList(MemberList::decTypedefMembers,md); addMemberToList(MemberList::docTypedefMembers,md); break; case MemberDef::Enumeration: addMemberToList(MemberList::decEnumMembers,md); addMemberToList(MemberList::docEnumMembers,md); break; case MemberDef::EnumValue: // enum values are shown inside their enums break; case MemberDef::Define: addMemberToList(MemberList::decDefineMembers,md); addMemberToList(MemberList::docDefineMembers,md); break; default: err("FileDef::insertMembers(): " "member `%s' with class scope `%s' inserted in file scope `%s'!\n", md->name().data(), md->getClassDef() ? md->getClassDef()->name().data() : "<global>", name().data()); } //addMemberToGroup(md,groupId); } /*! Adds compound definition \a cd to the list of all compounds of this file */ void FileDef::insertClass(ClassDef *cd) { if (cd->isHidden()) return; if (classSDict==0) { classSDict = new ClassSDict(17); } if (Config_getBool("SORT_BRIEF_DOCS")) classSDict->inSort(cd->name(),cd); else classSDict->append(cd->name(),cd); } /*! Adds namespace definition \a nd to the list of all compounds of this file */ void FileDef::insertNamespace(NamespaceDef *nd) { if (nd->isHidden()) return; if (!nd->name().isEmpty() && (namespaceSDict==0 || namespaceSDict->find(nd->name())==0)) { if (namespaceSDict==0) { namespaceSDict = new NamespaceSDict; } if (Config_getBool("SORT_BRIEF_DOCS")) namespaceSDict->inSort(nd->name(),nd); else namespaceSDict->append(nd->name(),nd); } } void FileDef::addSourceRef(int line,Definition *d,MemberDef *md) { //printf("FileDef::addSourceDef(%d,%p,%p)\n",line,d,md); if (d) { if (srcDefDict==0) srcDefDict = new QIntDict<Definition>(257); if (srcMemberDict==0) srcMemberDict = new QIntDict<MemberDef>(257); srcDefDict->insert(line,d); if (md) srcMemberDict->insert(line,md); //printf("Adding member %s with anchor %s at line %d to file %s\n", // md->name().data(),md->anchor().data(),line,name().data()); } } Definition *FileDef::getSourceDefinition(int lineNr) { Definition *result=0; if (srcDefDict) { result = srcDefDict->find(lineNr); } return result; } MemberDef *FileDef::getSourceMember(int lineNr) { MemberDef *result=0; if (srcMemberDict) { result = srcMemberDict->find(lineNr); } return result; } void FileDef::addUsingDirective(NamespaceDef *nd) { if (usingDirList==0) { usingDirList = new NamespaceSDict; } if (usingDirList->find(nd->qualifiedName())==0) { usingDirList->append(nd->qualifiedName(),nd); } //printf("%p: FileDef::addUsingDirective: %s:%d\n",this,name().data(),usingDirList->count()); } NamespaceSDict *FileDef::getUsedNamespaces() const { //printf("%p: FileDef::getUsedNamespace: %s:%d\n",this,name().data(),usingDirList?usingDirList->count():0); return usingDirList; } void FileDef::addUsingDeclaration(Definition *d) { if (usingDeclList==0) { usingDeclList = new SDict<Definition>(17); } if (usingDeclList->find(d->qualifiedName())==0) { usingDeclList->append(d->qualifiedName(),d); } } void FileDef::addIncludeDependency(FileDef *fd,const char *incName,bool local, bool imported,bool indirect) { //printf("FileDef::addIncludeDependency(%p,%s,%d)\n",fd,incName,local); QCString iName = fd ? fd->absFilePath().data() : incName; if (!iName.isEmpty() && (!includeDict || includeDict->find(iName)==0)) { if (includeDict==0) { includeDict = new QDict<IncludeInfo>(61); includeList = new QList<IncludeInfo>; includeList->setAutoDelete(TRUE); } IncludeInfo *ii = new IncludeInfo; ii->fileDef = fd; ii->includeName = incName; ii->local = local; ii->imported = imported; ii->indirect = indirect; includeList->append(ii); includeDict->insert(iName,ii); } } void FileDef::addIncludedUsingDirectives() { if (visited) return; visited=TRUE; //printf("( FileDef::addIncludedUsingDirectives for file %s\n",name().data()); NamespaceList nl; if (includeList) // file contains #includes { { QListIterator<IncludeInfo> iii(*includeList); IncludeInfo *ii; for (iii.toFirst();(ii=iii.current());++iii) // foreach #include... { if (ii->fileDef && !ii->fileDef->visited) // ...that is a known file { // recurse into this file ii->fileDef->addIncludedUsingDirectives(); } } } { QListIterator<IncludeInfo> iii(*includeList); IncludeInfo *ii; // iterate through list from last to first for (iii.toLast();(ii=iii.current());--iii) { if (ii->fileDef && ii->fileDef!=this) { // add using directives NamespaceSDict *unl = ii->fileDef->usingDirList; if (unl) { NamespaceSDict::Iterator nli(*unl); NamespaceDef *nd; for (nli.toLast();(nd=nli.current());--nli) { // append each using directive found in a #include file if (usingDirList==0) usingDirList = new NamespaceSDict; //printf("Prepending used namespace %s to the list of file %s\n", // nd->name().data(),name().data()); if (usingDirList->find(nd->qualifiedName())==0) // not yet added { usingDirList->prepend(nd->qualifiedName(),nd); } } } // add using declarations SDict<Definition> *udl = ii->fileDef->usingDeclList; if (udl) { SDict<Definition>::Iterator udi(*udl); Definition *d; for (udi.toLast();(d=udi.current());--udi) { //printf("Adding using declaration %s\n",d->name().data()); if (usingDeclList==0) { usingDeclList = new SDict<Definition>(17); } if (usingDeclList->find(d->qualifiedName())==0) { usingDeclList->prepend(d->qualifiedName(),d); } } } } } } } //printf(") end FileDef::addIncludedUsingDirectives for file %s\n",name().data()); } void FileDef::addIncludedByDependency(FileDef *fd,const char *incName, bool local,bool imported) { //printf("FileDef::addIncludedByDependency(%p,%s,%d)\n",fd,incName,local); QCString iName = fd ? fd->absFilePath().data() : incName; if (!iName.isEmpty() && (includedByDict==0 || includedByDict->find(iName)==0)) { if (includedByDict==0) { includedByDict = new QDict<IncludeInfo>(61); includedByList = new QList<IncludeInfo>; includedByList->setAutoDelete(TRUE); } IncludeInfo *ii = new IncludeInfo; ii->fileDef = fd; ii->includeName = incName; ii->local = local; ii->imported = imported; ii->indirect = FALSE; includedByList->append(ii); includedByDict->insert(iName,ii); } } bool FileDef::isIncluded(const QCString &name) const { if (name.isEmpty()) return FALSE; return includeDict!=0 && includeDict->find(name)!=0; } bool FileDef::generateSourceFile() const { QCString extension = name().right(4); return !isReference() && (Config_getBool("SOURCE_BROWSER") || (Config_getBool("VERBATIM_HEADERS") && guessSection(name())==Entry::HEADER_SEC) ) && extension!=".doc" && extension!=".txt" && extension!=".dox" && extension!=".md" && extension!=".markdown"; } void FileDef::addListReferences() { { LockingPtr< QList<ListItemInfo> > xrefItems = xrefListItems(); addRefItem(xrefItems.pointer(), getOutputFileBase(), theTranslator->trFile(TRUE,TRUE), getOutputFileBase(),name(), 0 ); } if (memberGroupSDict) { MemberGroupSDict::Iterator mgli(*memberGroupSDict); MemberGroup *mg; for (;(mg=mgli.current());++mgli) { mg->addListReferences(this); } } QListIterator<MemberList> mli(m_memberLists); MemberList *ml; for (mli.toFirst();(ml=mli.current());++mli) { if (ml->listType()&MemberList::documentationLists) { ml->addListReferences(this); } } } //------------------------------------------------------------------- static int findMatchingPart(const QCString &path,const QCString dir) { int si1; int pos1=0,pos2=0; while ((si1=path.find('/',pos1))!=-1) { int si2=dir.find('/',pos2); //printf(" found slash at pos %d in path %d: %s<->%s\n",si1,si2, // path.mid(pos1,si1-pos2).data(),dir.mid(pos2).data()); if (si2==-1 && path.mid(pos1,si1-pos2)==dir.mid(pos2)) // match at end { return dir.length(); } if (si1!=si2 || path.mid(pos1,si1-pos2)!=dir.mid(pos2,si2-pos2)) // no match in middle { return QMAX(pos1-1,0); } pos1=si1+1; pos2=si2+1; } return 0; } static Directory *findDirNode(Directory *root,const QCString &name) { QListIterator<DirEntry> dli(root->children()); DirEntry *de; for (dli.toFirst();(de=dli.current());++dli) { if (de->kind()==DirEntry::Dir) { Directory *dir = (Directory *)de; QCString dirName=dir->name(); int sp=findMatchingPart(name,dirName); //printf("findMatchingPart(%s,%s)=%d\n",name.data(),dirName.data(),sp); if (sp>0) // match found { if ((uint)sp==dirName.length()) // whole directory matches { // recurse into the directory return findDirNode(dir,name.mid(dirName.length()+1)); } else // partial match => we need to split the path into three parts { QCString baseName =dirName.left(sp); QCString oldBranchName=dirName.mid(sp+1); QCString newBranchName=name.mid(sp+1); // strip file name from path int newIndex=newBranchName.findRev('/'); if (newIndex>0) newBranchName=newBranchName.left(newIndex); //printf("Splitting off part in new branch \n" // "base=%s old=%s new=%s\n", // baseName.data(), // oldBranchName.data(), // newBranchName.data() // ); Directory *base = new Directory(root,baseName); Directory *newBranch = new Directory(base,newBranchName); dir->reParent(base); dir->rename(oldBranchName); base->addChild(dir); base->addChild(newBranch); dir->setLast(FALSE); // remove DirEntry container from list (without deleting it) root->children().setAutoDelete(FALSE); root->children().removeRef(dir); root->children().setAutoDelete(TRUE); // add new branch to the root if (!root->children().isEmpty()) { root->children().last()->setLast(FALSE); } root->addChild(base); return newBranch; } } } } int si=name.findRev('/'); if (si==-1) // no subdir { return root; // put the file under the root node. } else // need to create a subdir { QCString baseName = name.left(si); //printf("new subdir %s\n",baseName.data()); Directory *newBranch = new Directory(root,baseName); if (!root->children().isEmpty()) { root->children().last()->setLast(FALSE); } root->addChild(newBranch); return newBranch; } } static void mergeFileDef(Directory *root,FileDef *fd) { QCString rootPath = root->name(); QCString filePath = fd->absFilePath(); //printf("merging %s\n",filePath.data()); Directory *dirNode = findDirNode(root,filePath); if (!dirNode->children().isEmpty()) { dirNode->children().last()->setLast(FALSE); } DirEntry *e=new DirEntry(dirNode,fd); dirNode->addChild(e); } #if 0 static void generateIndent(QTextStream &t,DirEntry *de,int level) { if (de->parent()) { generateIndent(t,de->parent(),level+1); } // from the root up to node n do... if (level==0) // item before a dir or document { if (de->isLast()) { if (de->kind()==DirEntry::Dir) { t << "<img " << FTV_IMGATTRIBS(plastnode) << "/>"; } else { t << "<img " << FTV_IMGATTRIBS(lastnode) << "/>"; } } else { if (de->kind()==DirEntry::Dir) { t << "<img " << FTV_IMGATTRIBS(pnode) << "/>"; } else { t << "<img " << FTV_IMGATTRIBS(node) << "/>"; } } } else // item at another level { if (de->isLast()) { t << "<img " << FTV_IMGATTRIBS(blank) << "/>"; } else { t << "<img " << FTV_IMGATTRIBS(vertline) << "/>"; } } } static void writeDirTreeNode(QTextStream &t,Directory *root,int level) { QCString indent; indent.fill(' ',level*2); QListIterator<DirEntry> dli(root->children()); DirEntry *de; for (dli.toFirst();(de=dli.current());++dli) { t << indent << "<p>"; generateIndent(t,de,0); if (de->kind()==DirEntry::Dir) { Directory *dir=(Directory *)de; //printf("%s [dir]: %s (last=%d,dir=%d)\n",indent.data(),dir->name().data(),dir->isLast(),dir->kind()==DirEntry::Dir); t << "<img " << FTV_IMGATTRIBS(folderclosed) << "/>"; t << dir->name(); t << "</p>\n"; t << indent << "<div>\n"; writeDirTreeNode(t,dir,level+1); t << indent << "</div>\n"; } else { //printf("%s [file]: %s (last=%d,dir=%d)\n",indent.data(),de->file()->name().data(),de->isLast(),de->kind()==DirEntry::Dir); t << "<img " << FTV_IMGATTRIBS(doc) << "/>"; t << de->file()->name(); t << "</p>\n"; } } } #endif static void addDirsAsGroups(Directory *root,GroupDef *parent,int level) { GroupDef *gd=0; if (root->kind()==DirEntry::Dir) { gd = new GroupDef("[generated]", 1, root->path(), // name root->name() // title ); if (parent) { parent->addGroup(gd); gd->makePartOfGroup(parent); } else { Doxygen::groupSDict->append(root->path(),gd); } } QListIterator<DirEntry> dli(root->children()); DirEntry *de; for (dli.toFirst();(de=dli.current());++dli) { if (de->kind()==DirEntry::Dir) { addDirsAsGroups((Directory *)de,gd,level+1); } } } void generateFileTree() { Directory *root=new Directory(0,"root"); root->setLast(TRUE); FileNameListIterator fnli(*Doxygen::inputNameList); FileName *fn; for (fnli.toFirst();(fn=fnli.current());++fnli) { FileNameIterator fni(*fn); FileDef *fd; for (;(fd=fni.current());++fni) { mergeFileDef(root,fd); } } //t << "<div class=\"directory\">\n"; //writeDirTreeNode(t,root,0); //t << "</div>\n"; addDirsAsGroups(root,0,0); delete root; } //------------------------------------------------------------------- void FileDef::combineUsingRelations() { if (visited) return; // already done visited=TRUE; if (usingDirList) { NamespaceSDict::Iterator nli(*usingDirList); NamespaceDef *nd; for (nli.toFirst();(nd=nli.current());++nli) { nd->combineUsingRelations(); } for (nli.toFirst();(nd=nli.current());++nli) { // add used namespaces of namespace nd to this namespace if (nd->getUsedNamespaces()) { NamespaceSDict::Iterator unli(*nd->getUsedNamespaces()); NamespaceDef *und; for (unli.toFirst();(und=unli.current());++unli) { //printf("Adding namespace %s to the using list of %s\n",und->qualifiedName().data(),qualifiedName().data()); addUsingDirective(und); } } // add used classes of namespace nd to this namespace if (nd->getUsedClasses()) { SDict<Definition>::Iterator cli(*nd->getUsedClasses()); Definition *ucd; for (cli.toFirst();(ucd=cli.current());++cli) { //printf("Adding class %s to the using list of %s\n",cd->qualifiedName().data(),qualifiedName().data()); addUsingDeclaration(ucd); } } } } } bool FileDef::isDocumentationFile() const { return name().right(4)==".doc" || name().right(4)==".txt" || name().right(4)==".dox" || name().right(3)==".md" || name().right(9)==".markdown"; } void FileDef::acquireFileVersion() { QCString vercmd = Config_getString("FILE_VERSION_FILTER"); if (!vercmd.isEmpty() && !filepath.isEmpty() && filepath!="generated") { msg("Version of %s : ",filepath.data()); QCString cmd = vercmd+" \""+filepath+"\""; Debug::print(Debug::ExtCmd,0,"Executing popen(`%s`)\n",cmd.data()); FILE *f=portable_popen(cmd,"r"); if (!f) { err("error: could not execute %s\n",vercmd.data()); return; } const int bufSize=1024; char buf[bufSize]; int numRead = fread(buf,1,bufSize,f); portable_pclose(f); if (numRead>0 && !(fileVersion=QCString(buf,numRead).stripWhiteSpace()).isEmpty()) { msg("%s\n",fileVersion.data());