diff options
Diffstat (limited to 'src/libs/xpcom18a4/xpcom/base')
55 files changed, 10266 insertions, 0 deletions
diff --git a/src/libs/xpcom18a4/xpcom/base/.cvsignore b/src/libs/xpcom18a4/xpcom/base/.cvsignore new file mode 100644 index 00000000..235f7398 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/base/.cvsignore @@ -0,0 +1,2 @@ +Makefile +bloatblame diff --git a/src/libs/xpcom18a4/xpcom/base/Makefile.in b/src/libs/xpcom18a4/xpcom/base/Makefile.in new file mode 100644 index 00000000..a897bca8 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/base/Makefile.in @@ -0,0 +1,133 @@ +# +# ***** BEGIN LICENSE BLOCK ***** +# Version: MPL 1.1/GPL 2.0/LGPL 2.1 +# +# The contents of this file are subject to the Mozilla Public License Version +# 1.1 (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS IS" basis, +# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +# for the specific language governing rights and limitations under the +# License. +# +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the terms of +# either of the GNU General Public License Version 2 or later (the "GPL"), +# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), +# in which case the provisions of the GPL or the LGPL are applicable instead +# of those above. If you wish to allow use of your version of this file only +# under the terms of either the GPL or the LGPL, and not to allow others to +# use your version of this file under the terms of the MPL, indicate your +# decision by deleting the provisions above and replace them with the notice +# and other provisions required by the GPL or the LGPL. If you do not delete +# the provisions above, a recipient may use your version of this file under +# the terms of any one of the MPL, the GPL or the LGPL. +# +# ***** END LICENSE BLOCK ***** + +DEPTH = ../.. +topsrcdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +include $(DEPTH)/config/autoconf.mk + +MODULE = xpcom +XPIDL_MODULE = xpcom_base +LIBRARY_NAME = xpcombase_s +GRE_MODULE = 1 + +REQUIRES = string \ + $(NULL) + +CPPSRCS = \ + nsAllocator.cpp \ + nsConsoleMessage.cpp \ + nsConsoleService.cpp \ + nsDebugImpl.cpp \ + nsErrorService.cpp \ + nsExceptionService.cpp \ + nsID.cpp \ + nsMemoryImpl.cpp \ + nsTraceRefcntImpl.cpp \ + $(NULL) + +ifdef GC_LEAK_DETECTOR +CSRCS += nsGarbageCollector.c +CPPSRCS += nsLeakDetector.cpp +REQUIRES += boehm +endif + +EXPORTS = \ + nsAgg.h \ + nsAutoPtr.h \ + nsCom.h \ + nsDebugImpl.h \ + nsIAllocator.h \ + nsIID.h \ + nsISupportsObsolete.h \ + nsTraceRefcntImpl.h \ + nsWeakPtr.h \ + $(NULL) + +ifeq ($(OS_ARCH),WINNT) +ifdef MOZ_DEBUG +CSRCS += pure_api.c +EXPORTS += pure.h +endif +CPPSRCS += nsStackFrameWin.cpp +endif + +ifneq ($(OS_ARCH),WINNT) +CPPSRCS += nsStackFrameUnix.cpp +endif + +SDK_XPIDLSRCS = \ + nsIDebug.idl \ + nsIInterfaceRequestor.idl \ + nsIMemory.idl \ + nsIProgrammingLanguage.idl \ + nsISupports.idl \ + nsITraceRefcnt.idl \ + nsIWeakReference.idl \ + nsrootidl.idl \ + +SDK_HEADERS = \ + nsError.h \ + nsID.h \ + nsISupportsBase.h \ + nscore.h \ + +XPIDLSRCS = \ + nsIConsoleListener.idl \ + nsIConsoleMessage.idl \ + nsIConsoleService.idl \ + nsIErrorService.idl \ + nsIException.idl \ + nsIExceptionService.idl \ + $(NULL) + +ifdef GC_LEAK_DETECTOR +XPIDLSRCS += nsILeakDetector.idl +endif + +# we don't want the shared lib, but we want to force the creation of a static lib. +FORCE_STATIC_LIB = 1 + +# Force use of PIC +FORCE_USE_PIC = 1 + +include $(topsrcdir)/config/rules.mk + +DEFINES += -D_IMPL_NS_COM + diff --git a/src/libs/xpcom18a4/xpcom/base/nsAgg.h b/src/libs/xpcom18a4/xpcom/base/nsAgg.h new file mode 100644 index 00000000..c818639e --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/base/nsAgg.h @@ -0,0 +1,155 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef nsAgg_h___ +#define nsAgg_h___ + +#include "nsISupports.h" + + +//////////////////////////////////////////////////////////////////////////////// + +// Put this in your class's declaration: +#define NS_DECL_AGGREGATED \ + NS_DECL_ISUPPORTS \ + \ +public: \ + \ + /* You must implement this operation instead of the nsISupports */ \ + /* methods if you inherit from nsAggregated. */ \ + NS_IMETHOD \ + AggregatedQueryInterface(const nsIID& aIID, void** aInstancePtr); \ + \ +protected: \ + \ + class Internal : public nsISupports { \ + public: \ + \ + Internal() {} \ + \ + NS_IMETHOD QueryInterface(const nsIID& aIID, \ + void** aInstancePtr); \ + NS_IMETHOD_(nsrefcnt) AddRef(void); \ + NS_IMETHOD_(nsrefcnt) Release(void); \ + \ + }; \ + \ + friend class Internal; \ + \ + nsISupports* fOuter; \ + Internal fAggregated; \ + \ + nsISupports* GetInner(void) { return &fAggregated; } \ + \ +public: \ + + +// Put this in your class's constructor: +#define NS_INIT_AGGREGATED(outer) \ + PR_BEGIN_MACRO \ + fOuter = outer ? outer : &fAggregated; \ + PR_END_MACRO + + +// Put this in your class's implementation file: +#define NS_IMPL_AGGREGATED(_class) \ +NS_IMETHODIMP \ +_class::QueryInterface(const nsIID& aIID, void** aInstancePtr) \ +{ \ + return fOuter->QueryInterface(aIID, aInstancePtr); \ +} \ + \ +NS_IMETHODIMP_(nsrefcnt) \ +_class::AddRef(void) \ +{ \ + return fOuter->AddRef(); \ +} \ + \ +NS_IMETHODIMP_(nsrefcnt) \ +_class::Release(void) \ +{ \ + return fOuter->Release(); \ +} \ + \ +NS_IMETHODIMP \ +_class::Internal::QueryInterface(const nsIID& aIID, void** aInstancePtr) \ +{ \ + _class* agg = (_class*)((char*)(this) - offsetof(_class, fAggregated)); \ + return agg->AggregatedQueryInterface(aIID, aInstancePtr); \ +} \ + \ +NS_IMETHODIMP_(nsrefcnt) \ +_class::Internal::AddRef(void) \ +{ \ + _class* agg = (_class*)((char*)(this) - offsetof(_class, fAggregated)); \ + NS_PRECONDITION(PRInt32(agg->mRefCnt) >= 0, "illegal refcnt"); \ + ++agg->mRefCnt; \ + NS_LOG_ADDREF(this, agg->mRefCnt, #_class, sizeof(*this)); \ + return agg->mRefCnt; \ +} \ + \ +NS_IMETHODIMP_(nsrefcnt) \ +_class::Internal::Release(void) \ +{ \ + _class* agg = (_class*)((char*)(this) - offsetof(_class, fAggregated)); \ + NS_PRECONDITION(0 != agg->mRefCnt, "dup release"); \ + --agg->mRefCnt; \ + NS_LOG_RELEASE(this, agg->mRefCnt, #_class); \ + if (agg->mRefCnt == 0) { \ + agg->mRefCnt = 1; /* stabilize */ \ + NS_DELETEXPCOM(agg); \ + return 0; \ + } \ + return agg->mRefCnt; \ +} \ + +// for use with QI macros in nsISupportsUtils.h: + +#define NS_INTERFACE_MAP_BEGIN_AGGREGATED(_class) \ + NS_IMPL_AGGREGATED_QUERY_HEAD(_class) + +#define NS_IMPL_AGGREGATED_QUERY_HEAD(_class) \ +NS_IMETHODIMP \ +_class::AggregatedQueryInterface(REFNSIID aIID, void** aInstancePtr) \ +{ \ + NS_ASSERTION(aInstancePtr, \ + "AggregatedQueryInterface requires a non-NULL result ptr!"); \ + if ( !aInstancePtr ) \ + return NS_ERROR_NULL_POINTER; \ + nsISupports* foundInterface; + +#endif /* nsAgg_h___ */ diff --git a/src/libs/xpcom18a4/xpcom/base/nsAllocator.cpp b/src/libs/xpcom18a4/xpcom/base/nsAllocator.cpp new file mode 100644 index 00000000..d565329d --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/base/nsAllocator.cpp @@ -0,0 +1,41 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Pierre Phaneuf <pp@ludusdesign.com> + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +//////////////////////////////////////////////////////////////////////////////// +// obsolete +//////////////////////////////////////////////////////////////////////////////// diff --git a/src/libs/xpcom18a4/xpcom/base/nsAllocator.h b/src/libs/xpcom18a4/xpcom/base/nsAllocator.h new file mode 100644 index 00000000..5320469c --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/base/nsAllocator.h @@ -0,0 +1,50 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +//////////////////////////////////////////////////////////////////////////////// +// obsolete +//////////////////////////////////////////////////////////////////////////////// + +#ifndef nsAllocator_h__ +#define nsAllocator_h__ + +#include "nsIAllocator.h" +#include "prmem.h" +#include "nsAgg.h" +#include "nsIFactory.h" + +#endif // nsAllocator_h__ diff --git a/src/libs/xpcom18a4/xpcom/base/nsAutoPtr.h b/src/libs/xpcom18a4/xpcom/base/nsAutoPtr.h new file mode 100644 index 00000000..874b1e31 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/base/nsAutoPtr.h @@ -0,0 +1,1353 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Scott Collins <scc@mozilla.org> (original author of nsCOMPtr) + * L. David Baron <dbaron@dbaron.org> + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef nsAutoPtr_h___ +#define nsAutoPtr_h___ + + // Wrapping includes can speed up compiles (see "Large Scale C++ Software Design") +#ifndef nsCOMPtr_h___ + // For |already_AddRefed|, |nsDerivedSafe|, |NSCAP_Zero|, + // |NSCAP_DONT_PROVIDE_NONCONST_OPEQ|, + // |NSCAP_FEATURE_INLINE_STARTASSIGNMENT| +#include "nsCOMPtr.h" +#endif + +/*****************************************************************************/ + +// template <class T> class nsAutoPtrGetterTransfers; + +template <class T> +class nsAutoPtr + { + private: + void** + begin_assignment() + { + assign(0); + return NS_REINTERPRET_CAST(void**, &mRawPtr); + } + + void + assign( T* newPtr ) + { + T* oldPtr = mRawPtr; + mRawPtr = newPtr; + delete oldPtr; + } + + private: + T* mRawPtr; + + public: + typedef T element_type; + + ~nsAutoPtr() + { + delete mRawPtr; + } + + // Constructors + + nsAutoPtr() + : mRawPtr(0) + // default constructor + { + } + + nsAutoPtr( T* aRawPtr ) + : mRawPtr(aRawPtr) + // construct from a raw pointer (of the right type) + { + } + + nsAutoPtr( nsAutoPtr<T>& aSmartPtr ) + : mRawPtr( aSmartPtr.forget() ) + // Construct by transferring ownership from another smart pointer. + { + } + + + // Assignment operators + + nsAutoPtr<T>& + operator=( T* rhs ) + // assign from a raw pointer (of the right type) + { + assign(rhs); + return *this; + } + + nsAutoPtr<T>& operator=( nsAutoPtr<T>& rhs ) + // assign by transferring ownership from another smart pointer. + { + assign(rhs.forget()); + return *this; + } + + // Other pointer operators + + T* + get() const + /* + Prefer the implicit conversion provided automatically by + |operator T*() const|. Use |get()| _only_ to resolve + ambiguity. + */ + { + return mRawPtr; + } + + operator T*() const + /* + ...makes an |nsAutoPtr| act like its underlying raw pointer + type whenever it is used in a context where a raw pointer + is expected. It is this operator that makes an |nsAutoPtr| + substitutable for a raw pointer. + + Prefer the implicit use of this operator to calling |get()|, + except where necessary to resolve ambiguity. + */ + { + return get(); + } + + T* + forget() + { + T* temp = mRawPtr; + mRawPtr = 0; + return temp; + } + + T* + operator->() const + { + NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsAutoPtr with operator->()."); + return get(); + } + +#ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY + // broken version for IRIX + + nsAutoPtr<T>* + get_address() const + // This is not intended to be used by clients. See |address_of| + // below. + { + return NS_CONST_CAST(nsAutoPtr<T>*, this); + } + +#else // CANT_RESOLVE_CPP_CONST_AMBIGUITY + + nsAutoPtr<T>* + get_address() + // This is not intended to be used by clients. See |address_of| + // below. + { + return this; + } + + const nsAutoPtr<T>* + get_address() const + // This is not intended to be used by clients. See |address_of| + // below. + { + return this; + } + +#endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY + + public: + T& + operator*() const + { + NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsAutoPtr with operator*()."); + return *get(); + } + + T** + StartAssignment() + { +#ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT + return NS_REINTERPRET_CAST(T**, begin_assignment()); +#else + assign(0); + return NS_REINTERPRET_CAST(T**, &mRawPtr); +#endif + } + }; + +#ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY + +// This is the broken version for IRIX, which can't handle the version below. + +template <class T> +inline +nsAutoPtr<T>* +address_of( const nsAutoPtr<T>& aPtr ) + { + return aPtr.get_address(); + } + +#else // CANT_RESOLVE_CPP_CONST_AMBIGUITY + +template <class T> +inline +nsAutoPtr<T>* +address_of( nsAutoPtr<T>& aPtr ) + { + return aPtr.get_address(); + } + +template <class T> +inline +const nsAutoPtr<T>* +address_of( const nsAutoPtr<T>& aPtr ) + { + return aPtr.get_address(); + } + +#endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY + +template <class T> +class nsAutoPtrGetterTransfers + /* + ... + + This class is designed to be used for anonymous temporary objects in the + argument list of calls that return COM interface pointers, e.g., + + nsAutoPtr<IFoo> fooP; + ...->GetTransferedPointer(getter_Transfers(fooP)) + + DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE. Use |getter_Transfers()| instead. + + When initialized with a |nsAutoPtr|, as in the example above, it returns + a |void**|, a |T**|, or an |nsISupports**| as needed, that the + outer call (|GetTransferedPointer| in this case) can fill in. + + This type should be a nested class inside |nsAutoPtr<T>|. + */ + { + public: + explicit + nsAutoPtrGetterTransfers( nsAutoPtr<T>& aSmartPtr ) + : mTargetSmartPtr(aSmartPtr) + { + // nothing else to do + } + + operator void**() + { + return NS_REINTERPRET_CAST(void**, mTargetSmartPtr.StartAssignment()); + } + + operator T**() + { + return mTargetSmartPtr.StartAssignment(); + } + + T*& + operator*() + { + return *(mTargetSmartPtr.StartAssignment()); + } + + private: + nsAutoPtr<T>& mTargetSmartPtr; + }; + +template <class T> +inline +nsAutoPtrGetterTransfers<T> +getter_Transfers( nsAutoPtr<T>& aSmartPtr ) + /* + Used around a |nsAutoPtr| when + ...makes the class |nsAutoPtrGetterTransfers<T>| invisible. + */ + { + return nsAutoPtrGetterTransfers<T>(aSmartPtr); + } + + + + // Comparing two |nsAutoPtr|s + +template <class T, class U> +inline +NSCAP_BOOL +operator==( const nsAutoPtr<T>& lhs, const nsAutoPtr<U>& rhs ) + { + return NS_STATIC_CAST(const T*, lhs.get()) == NS_STATIC_CAST(const U*, rhs.get()); + } + + +template <class T, class U> +inline +NSCAP_BOOL +operator!=( const nsAutoPtr<T>& lhs, const nsAutoPtr<U>& rhs ) + { + return NS_STATIC_CAST(const T*, lhs.get()) != NS_STATIC_CAST(const U*, rhs.get()); + } + + + // Comparing an |nsAutoPtr| to a raw pointer + +template <class T, class U> +inline +NSCAP_BOOL +operator==( const nsAutoPtr<T>& lhs, const U* rhs ) + { + return NS_STATIC_CAST(const T*, lhs.get()) == NS_STATIC_CAST(const U*, rhs); + } + +template <class T, class U> +inline +NSCAP_BOOL +operator==( const U* lhs, const nsAutoPtr<T>& rhs ) + { + return NS_STATIC_CAST(const U*, lhs) == NS_STATIC_CAST(const T*, rhs.get()); + } + +template <class T, class U> +inline +NSCAP_BOOL +operator!=( const nsAutoPtr<T>& lhs, const U* rhs ) + { + return NS_STATIC_CAST(const T*, lhs.get()) != NS_STATIC_CAST(const U*, rhs); + } + +template <class T, class U> +inline +NSCAP_BOOL +operator!=( const U* lhs, const nsAutoPtr<T>& rhs ) + { + return NS_STATIC_CAST(const U*, lhs) != NS_STATIC_CAST(const T*, rhs.get()); + } + + // To avoid ambiguities caused by the presence of builtin |operator==|s + // creating a situation where one of the |operator==| defined above + // has a better conversion for one argument and the builtin has a + // better conversion for the other argument, define additional + // |operator==| without the |const| on the raw pointer. + // See bug 65664 for details. + +#ifndef NSCAP_DONT_PROVIDE_NONCONST_OPEQ +template <class T, class U> +inline +NSCAP_BOOL +operator==( const nsAutoPtr<T>& lhs, U* rhs ) + { + return NS_STATIC_CAST(const T*, lhs.get()) == NS_CONST_CAST(const U*, rhs); + } + +template <class T, class U> +inline +NSCAP_BOOL +operator==( U* lhs, const nsAutoPtr<T>& rhs ) + { + return NS_CONST_CAST(const U*, lhs) == NS_STATIC_CAST(const T*, rhs.get()); + } + +template <class T, class U> +inline +NSCAP_BOOL +operator!=( const nsAutoPtr<T>& lhs, U* rhs ) + { + return NS_STATIC_CAST(const T*, lhs.get()) != NS_CONST_CAST(const U*, rhs); + } + +template <class T, class U> +inline +NSCAP_BOOL +operator!=( U* lhs, const nsAutoPtr<T>& rhs ) + { + return NS_CONST_CAST(const U*, lhs) != NS_STATIC_CAST(const T*, rhs.get()); + } +#endif + + + + // Comparing an |nsAutoPtr| to |0| + +template <class T> +inline +NSCAP_BOOL +operator==( const nsAutoPtr<T>& lhs, NSCAP_Zero* rhs ) + // specifically to allow |smartPtr == 0| + { + return NS_STATIC_CAST(const void*, lhs.get()) == NS_REINTERPRET_CAST(const void*, rhs); + } + +template <class T> +inline +NSCAP_BOOL +operator==( NSCAP_Zero* lhs, const nsAutoPtr<T>& rhs ) + // specifically to allow |0 == smartPtr| + { + return NS_REINTERPRET_CAST(const void*, lhs) == NS_STATIC_CAST(const void*, rhs.get()); + } + +template <class T> +inline +NSCAP_BOOL +operator!=( const nsAutoPtr<T>& lhs, NSCAP_Zero* rhs ) + // specifically to allow |smartPtr != 0| + { + return NS_STATIC_CAST(const void*, lhs.get()) != NS_REINTERPRET_CAST(const void*, rhs); + } + +template <class T> +inline +NSCAP_BOOL +operator!=( NSCAP_Zero* lhs, const nsAutoPtr<T>& rhs ) + // specifically to allow |0 != smartPtr| + { + return NS_REINTERPRET_CAST(const void*, lhs) != NS_STATIC_CAST(const void*, rhs.get()); + } + + +#ifdef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO + + // We need to explicitly define comparison operators for `int' + // because the compiler is lame. + +template <class T> +inline +NSCAP_BOOL +operator==( const nsAutoPtr<T>& lhs, int rhs ) + // specifically to allow |smartPtr == 0| + { + return NS_STATIC_CAST(const void*, lhs.get()) == NS_REINTERPRET_CAST(const void*, rhs); + } + +template <class T> +inline +NSCAP_BOOL +operator==( int lhs, const nsAutoPtr<T>& rhs ) + // specifically to allow |0 == smartPtr| + { + return NS_REINTERPRET_CAST(const void*, lhs) == NS_STATIC_CAST(const void*, rhs.get()); + } + +#endif // !defined(HAVE_CPP_TROUBLE_COMPARING_TO_ZERO) + +/*****************************************************************************/ + +// template <class T> class nsAutoArrayPtrGetterTransfers; + +template <class T> +class nsAutoArrayPtr + { + private: + void** + begin_assignment() + { + assign(0); + return NS_REINTERPRET_CAST(void**, &mRawPtr); + } + + void + assign( T* newPtr ) + { + T* oldPtr = mRawPtr; + mRawPtr = newPtr; + delete [] oldPtr; + } + + private: + T* mRawPtr; + + public: + typedef T element_type; + + ~nsAutoArrayPtr() + { + delete [] mRawPtr; + } + + // Constructors + + nsAutoArrayPtr() + : mRawPtr(0) + // default constructor + { + } + + nsAutoArrayPtr( T* aRawPtr ) + : mRawPtr(aRawPtr) + // construct from a raw pointer (of the right type) + { + } + + nsAutoArrayPtr( nsAutoArrayPtr<T>& aSmartPtr ) + : mRawPtr( aSmartPtr.forget() ) + // Construct by transferring ownership from another smart pointer. + { + } + + + // Assignment operators + + nsAutoArrayPtr<T>& + operator=( T* rhs ) + // assign from a raw pointer (of the right type) + { + assign(rhs); + return *this; + } + + nsAutoArrayPtr<T>& operator=( nsAutoArrayPtr<T>& rhs ) + // assign by transferring ownership from another smart pointer. + { + assign(rhs.forget()); + return *this; + } + + // Other pointer operators + + T* + get() const + /* + Prefer the implicit conversion provided automatically by + |operator T*() const|. Use |get()| _only_ to resolve + ambiguity. + */ + { + return mRawPtr; + } + + operator T*() const + /* + ...makes an |nsAutoArrayPtr| act like its underlying raw pointer + type whenever it is used in a context where a raw pointer + is expected. It is this operator that makes an |nsAutoArrayPtr| + substitutable for a raw pointer. + + Prefer the implicit use of this operator to calling |get()|, + except where necessary to resolve ambiguity. + */ + { + return get(); + } + + T* + forget() + { + T* temp = mRawPtr; + mRawPtr = 0; + return temp; + } + + T* + operator->() const + { + NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsAutoArrayPtr with operator->()."); + return get(); + } + +#ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY + // broken version for IRIX + + nsAutoArrayPtr<T>* + get_address() const + // This is not intended to be used by clients. See |address_of| + // below. + { + return NS_CONST_CAST(nsAutoArrayPtr<T>*, this); + } + +#else // CANT_RESOLVE_CPP_CONST_AMBIGUITY + + nsAutoArrayPtr<T>* + get_address() + // This is not intended to be used by clients. See |address_of| + // below. + { + return this; + } + + const nsAutoArrayPtr<T>* + get_address() const + // This is not intended to be used by clients. See |address_of| + // below. + { + return this; + } + +#endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY + + public: + T& + operator*() const + { + NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsAutoArrayPtr with operator*()."); + return *get(); + } + + T** + StartAssignment() + { +#ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT + return NS_REINTERPRET_CAST(T**, begin_assignment()); +#else + assign(0); + return NS_REINTERPRET_CAST(T**, &mRawPtr); +#endif + } + }; + +#ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY + +// This is the broken version for IRIX, which can't handle the version below. + +template <class T> +inline +nsAutoArrayPtr<T>* +address_of( const nsAutoArrayPtr<T>& aPtr ) + { + return aPtr.get_address(); + } + +#else // CANT_RESOLVE_CPP_CONST_AMBIGUITY + +template <class T> +inline +nsAutoArrayPtr<T>* +address_of( nsAutoArrayPtr<T>& aPtr ) + { + return aPtr.get_address(); + } + +template <class T> +inline +const nsAutoArrayPtr<T>* +address_of( const nsAutoArrayPtr<T>& aPtr ) + { + return aPtr.get_address(); + } + +#endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY + +template <class T> +class nsAutoArrayPtrGetterTransfers + /* + ... + + This class is designed to be used for anonymous temporary objects in the + argument list of calls that return COM interface pointers, e.g., + + nsAutoArrayPtr<IFoo> fooP; + ...->GetTransferedPointer(getter_Transfers(fooP)) + + DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE. Use |getter_Transfers()| instead. + + When initialized with a |nsAutoArrayPtr|, as in the example above, it returns + a |void**|, a |T**|, or an |nsISupports**| as needed, that the + outer call (|GetTransferedPointer| in this case) can fill in. + + This type should be a nested class inside |nsAutoArrayPtr<T>|. + */ + { + public: + explicit + nsAutoArrayPtrGetterTransfers( nsAutoArrayPtr<T>& aSmartPtr ) + : mTargetSmartPtr(aSmartPtr) + { + // nothing else to do + } + + operator void**() + { + return NS_REINTERPRET_CAST(void**, mTargetSmartPtr.StartAssignment()); + } + + operator T**() + { + return mTargetSmartPtr.StartAssignment(); + } + + T*& + operator*() + { + return *(mTargetSmartPtr.StartAssignment()); + } + + private: + nsAutoArrayPtr<T>& mTargetSmartPtr; + }; + +template <class T> +inline +nsAutoArrayPtrGetterTransfers<T> +getter_Transfers( nsAutoArrayPtr<T>& aSmartPtr ) + /* + Used around a |nsAutoArrayPtr| when + ...makes the class |nsAutoArrayPtrGetterTransfers<T>| invisible. + */ + { + return nsAutoArrayPtrGetterTransfers<T>(aSmartPtr); + } + + + + // Comparing two |nsAutoArrayPtr|s + +template <class T, class U> +inline +NSCAP_BOOL +operator==( const nsAutoArrayPtr<T>& lhs, const nsAutoArrayPtr<U>& rhs ) + { + return NS_STATIC_CAST(const T*, lhs.get()) == NS_STATIC_CAST(const U*, rhs.get()); + } + + +template <class T, class U> +inline +NSCAP_BOOL +operator!=( const nsAutoArrayPtr<T>& lhs, const nsAutoArrayPtr<U>& rhs ) + { + return NS_STATIC_CAST(const T*, lhs.get()) != NS_STATIC_CAST(const U*, rhs.get()); + } + + + // Comparing an |nsAutoArrayPtr| to a raw pointer + +template <class T, class U> +inline +NSCAP_BOOL +operator==( const nsAutoArrayPtr<T>& lhs, const U* rhs ) + { + return NS_STATIC_CAST(const T*, lhs.get()) == NS_STATIC_CAST(const U*, rhs); + } + +template <class T, class U> +inline +NSCAP_BOOL +operator==( const U* lhs, const nsAutoArrayPtr<T>& rhs ) + { + return NS_STATIC_CAST(const U*, lhs) == NS_STATIC_CAST(const T*, rhs.get()); + } + +template <class T, class U> +inline +NSCAP_BOOL +operator!=( const nsAutoArrayPtr<T>& lhs, const U* rhs ) + { + return NS_STATIC_CAST(const T*, lhs.get()) != NS_STATIC_CAST(const U*, rhs); + } + +template <class T, class U> +inline +NSCAP_BOOL +operator!=( const U* lhs, const nsAutoArrayPtr<T>& rhs ) + { + return NS_STATIC_CAST(const U*, lhs) != NS_STATIC_CAST(const T*, rhs.get()); + } + + // To avoid ambiguities caused by the presence of builtin |operator==|s + // creating a situation where one of the |operator==| defined above + // has a better conversion for one argument and the builtin has a + // better conversion for the other argument, define additional + // |operator==| without the |const| on the raw pointer. + // See bug 65664 for details. + +#ifndef NSCAP_DONT_PROVIDE_NONCONST_OPEQ +template <class T, class U> +inline +NSCAP_BOOL +operator==( const nsAutoArrayPtr<T>& lhs, U* rhs ) + { + return NS_STATIC_CAST(const T*, lhs.get()) == NS_CONST_CAST(const U*, rhs); + } + +template <class T, class U> +inline +NSCAP_BOOL +operator==( U* lhs, const nsAutoArrayPtr<T>& rhs ) + { + return NS_CONST_CAST(const U*, lhs) == NS_STATIC_CAST(const T*, rhs.get()); + } + +template <class T, class U> +inline +NSCAP_BOOL +operator!=( const nsAutoArrayPtr<T>& lhs, U* rhs ) + { + return NS_STATIC_CAST(const T*, lhs.get()) != NS_CONST_CAST(const U*, rhs); + } + +template <class T, class U> +inline +NSCAP_BOOL +operator!=( U* lhs, const nsAutoArrayPtr<T>& rhs ) + { + return NS_CONST_CAST(const U*, lhs) != NS_STATIC_CAST(const T*, rhs.get()); + } +#endif + + + + // Comparing an |nsAutoArrayPtr| to |0| + +template <class T> +inline +NSCAP_BOOL +operator==( const nsAutoArrayPtr<T>& lhs, NSCAP_Zero* rhs ) + // specifically to allow |smartPtr == 0| + { + return NS_STATIC_CAST(const void*, lhs.get()) == NS_REINTERPRET_CAST(const void*, rhs); + } + +template <class T> +inline +NSCAP_BOOL +operator==( NSCAP_Zero* lhs, const nsAutoArrayPtr<T>& rhs ) + // specifically to allow |0 == smartPtr| + { + return NS_REINTERPRET_CAST(const void*, lhs) == NS_STATIC_CAST(const void*, rhs.get()); + } + +template <class T> +inline +NSCAP_BOOL +operator!=( const nsAutoArrayPtr<T>& lhs, NSCAP_Zero* rhs ) + // specifically to allow |smartPtr != 0| + { + return NS_STATIC_CAST(const void*, lhs.get()) != NS_REINTERPRET_CAST(const void*, rhs); + } + +template <class T> +inline +NSCAP_BOOL +operator!=( NSCAP_Zero* lhs, const nsAutoArrayPtr<T>& rhs ) + // specifically to allow |0 != smartPtr| + { + return NS_REINTERPRET_CAST(const void*, lhs) != NS_STATIC_CAST(const void*, rhs.get()); + } + + +#ifdef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO + + // We need to explicitly define comparison operators for `int' + // because the compiler is lame. + +template <class T> +inline +NSCAP_BOOL +operator==( const nsAutoArrayPtr<T>& lhs, int rhs ) + // specifically to allow |smartPtr == 0| + { + return NS_STATIC_CAST(const void*, lhs.get()) == NS_REINTERPRET_CAST(const void*, rhs); + } + +template <class T> +inline +NSCAP_BOOL +operator==( int lhs, const nsAutoArrayPtr<T>& rhs ) + // specifically to allow |0 == smartPtr| + { + return NS_REINTERPRET_CAST(const void*, lhs) == NS_STATIC_CAST(const void*, rhs.get()); + } + +#endif // !defined(HAVE_CPP_TROUBLE_COMPARING_TO_ZERO) + + +/*****************************************************************************/ + +// template <class T> class nsRefPtrGetterAddRefs; + +template <class T> +class nsRefPtr + { + private: + + void + assign_with_AddRef( T* rawPtr ) + { + if ( rawPtr ) + rawPtr->AddRef(); + assign_assuming_AddRef(rawPtr); + } + + void** + begin_assignment() + { + assign_assuming_AddRef(0); + return NS_REINTERPRET_CAST(void**, &mRawPtr); + } + + void + assign_assuming_AddRef( T* newPtr ) + { + T* oldPtr = mRawPtr; + mRawPtr = newPtr; + if ( oldPtr ) + oldPtr->Release(); + } + + private: + T* mRawPtr; + + public: + typedef T element_type; + + ~nsRefPtr() + { + if ( mRawPtr ) + mRawPtr->Release(); + } + + // Constructors + + nsRefPtr() + : mRawPtr(0) + // default constructor + { + } + + nsRefPtr( const nsRefPtr<T>& aSmartPtr ) + : mRawPtr(aSmartPtr.mRawPtr) + // copy-constructor + { + if ( mRawPtr ) + mRawPtr->AddRef(); + } + + nsRefPtr( T* aRawPtr ) + : mRawPtr(aRawPtr) + // construct from a raw pointer (of the right type) + { + if ( mRawPtr ) + mRawPtr->AddRef(); + } + + nsRefPtr( const already_AddRefed<T>& aSmartPtr ) + : mRawPtr(aSmartPtr.mRawPtr) + // construct from |dont_AddRef(expr)| + { + } + + // Assignment operators + + nsRefPtr<T>& + operator=( const nsRefPtr<T>& rhs ) + // copy assignment operator + { + assign_with_AddRef(rhs.mRawPtr); + return *this; + } + + nsRefPtr<T>& + operator=( T* rhs ) + // assign from a raw pointer (of the right type) + { + assign_with_AddRef(rhs); + return *this; + } + + nsRefPtr<T>& + operator=( const already_AddRefed<T>& rhs ) + // assign from |dont_AddRef(expr)| + { + assign_assuming_AddRef(rhs.mRawPtr); + return *this; + } + + // Other pointer operators + + void + swap( nsRefPtr<T>& rhs ) + // ...exchange ownership with |rhs|; can save a pair of refcount operations + { + T* temp = rhs.mRawPtr; + rhs.mRawPtr = mRawPtr; + mRawPtr = temp; + } + + void + swap( T*& rhs ) + // ...exchange ownership with |rhs|; can save a pair of refcount operations + { + T* temp = rhs; + rhs = mRawPtr; + mRawPtr = temp; + } + + nsDerivedSafe<T>* + get() const + /* + Prefer the implicit conversion provided automatically by |operator nsDerivedSafe<T>*() const|. + Use |get()| _only_ to resolve ambiguity. + + Returns a |nsDerivedSafe<T>*| to deny clients the use of |AddRef| and |Release|. + */ + { + return NS_CONST_CAST(nsDerivedSafe<T>*, + NS_REINTERPRET_CAST(const nsDerivedSafe<T>*, mRawPtr)); + } + + operator nsDerivedSafe<T>*() const + /* + ...makes an |nsRefPtr| act like its underlying raw pointer type (except against |AddRef()|, |Release()|, + and |delete|) whenever it is used in a context where a raw pointer is expected. It is this operator + that makes an |nsRefPtr| substitutable for a raw pointer. + + Prefer the implicit use of this operator to calling |get()|, except where necessary to resolve ambiguity. + */ + { + return get(); + } + + nsDerivedSafe<T>* + operator->() const + { + NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsRefPtr with operator->()."); + return get(); + } + +#ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY + // broken version for IRIX + + nsRefPtr<T>* + get_address() const + // This is not intended to be used by clients. See |address_of| + // below. + { + return NS_CONST_CAST(nsRefPtr<T>*, this); + } + +#else // CANT_RESOLVE_CPP_CONST_AMBIGUITY + + nsRefPtr<T>* + get_address() + // This is not intended to be used by clients. See |address_of| + // below. + { + return this; + } + + const nsRefPtr<T>* + get_address() const + // This is not intended to be used by clients. See |address_of| + // below. + { + return this; + } + +#endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY + + public: + nsDerivedSafe<T>& + operator*() const + { + NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsRefPtr with operator*()."); + return *get(); + } + + T** + StartAssignment() + { +#ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT + return NS_REINTERPRET_CAST(T**, begin_assignment()); +#else + assign_assuming_AddRef(0); + return NS_REINTERPRET_CAST(T**, &mRawPtr); +#endif + } + }; + +#ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY + +// This is the broken version for IRIX, which can't handle the version below. + +template <class T> +inline +nsRefPtr<T>* +address_of( const nsRefPtr<T>& aPtr ) + { + return aPtr.get_address(); + } + +#else // CANT_RESOLVE_CPP_CONST_AMBIGUITY + +template <class T> +inline +nsRefPtr<T>* +address_of( nsRefPtr<T>& aPtr ) + { + return aPtr.get_address(); + } + +template <class T> +inline +const nsRefPtr<T>* +address_of( const nsRefPtr<T>& aPtr ) + { + return aPtr.get_address(); + } + +#endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY + +template <class T> +class nsRefPtrGetterAddRefs + /* + ... + + This class is designed to be used for anonymous temporary objects in the + argument list of calls that return COM interface pointers, e.g., + + nsRefPtr<IFoo> fooP; + ...->GetAddRefedPointer(getter_AddRefs(fooP)) + + DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE. Use |getter_AddRefs()| instead. + + When initialized with a |nsRefPtr|, as in the example above, it returns + a |void**|, a |T**|, or an |nsISupports**| as needed, that the + outer call (|GetAddRefedPointer| in this case) can fill in. + + This type should be a nested class inside |nsRefPtr<T>|. + */ + { + public: + explicit + nsRefPtrGetterAddRefs( nsRefPtr<T>& aSmartPtr ) + : mTargetSmartPtr(aSmartPtr) + { + // nothing else to do + } + + operator void**() + { + return NS_REINTERPRET_CAST(void**, mTargetSmartPtr.StartAssignment()); + } + + operator T**() + { + return mTargetSmartPtr.StartAssignment(); + } + + T*& + operator*() + { + return *(mTargetSmartPtr.StartAssignment()); + } + + private: + nsRefPtr<T>& mTargetSmartPtr; + }; + +template <class T> +inline +nsRefPtrGetterAddRefs<T> +getter_AddRefs( nsRefPtr<T>& aSmartPtr ) + /* + Used around a |nsRefPtr| when + ...makes the class |nsRefPtrGetterAddRefs<T>| invisible. + */ + { + return nsRefPtrGetterAddRefs<T>(aSmartPtr); + } + + + + // Comparing two |nsRefPtr|s + +template <class T, class U> +inline +NSCAP_BOOL +operator==( const nsRefPtr<T>& lhs, const nsRefPtr<U>& rhs ) + { + return NS_STATIC_CAST(const T*, lhs.get()) == NS_STATIC_CAST(const U*, rhs.get()); + } + + +template <class T, class U> +inline +NSCAP_BOOL +operator!=( const nsRefPtr<T>& lhs, const nsRefPtr<U>& rhs ) + { + return NS_STATIC_CAST(const T*, lhs.get()) != NS_STATIC_CAST(const U*, rhs.get()); + } + + + // Comparing an |nsRefPtr| to a raw pointer + +template <class T, class U> +inline +NSCAP_BOOL +operator==( const nsRefPtr<T>& lhs, const U* rhs ) + { + return NS_STATIC_CAST(const T*, lhs.get()) == NS_STATIC_CAST(const U*, rhs); + } + +template <class T, class U> +inline +NSCAP_BOOL +operator==( const U* lhs, const nsRefPtr<T>& rhs ) + { + return NS_STATIC_CAST(const U*, lhs) == NS_STATIC_CAST(const T*, rhs.get()); + } + +template <class T, class U> +inline +NSCAP_BOOL +operator!=( const nsRefPtr<T>& lhs, const U* rhs ) + { + return NS_STATIC_CAST(const T*, lhs.get()) != NS_STATIC_CAST(const U*, rhs); + } + +template <class T, class U> +inline +NSCAP_BOOL +operator!=( const U* lhs, const nsRefPtr<T>& rhs ) + { + return NS_STATIC_CAST(const U*, lhs) != NS_STATIC_CAST(const T*, rhs.get()); + } + + // To avoid ambiguities caused by the presence of builtin |operator==|s + // creating a situation where one of the |operator==| defined above + // has a better conversion for one argument and the builtin has a + // better conversion for the other argument, define additional + // |operator==| without the |const| on the raw pointer. + // See bug 65664 for details. + +#ifndef NSCAP_DONT_PROVIDE_NONCONST_OPEQ +template <class T, class U> +inline +NSCAP_BOOL +operator==( const nsRefPtr<T>& lhs, U* rhs ) + { + return NS_STATIC_CAST(const T*, lhs.get()) == NS_CONST_CAST(const U*, rhs); + } + +template <class T, class U> +inline +NSCAP_BOOL +operator==( U* lhs, const nsRefPtr<T>& rhs ) + { + return NS_CONST_CAST(const U*, lhs) == NS_STATIC_CAST(const T*, rhs.get()); + } + +template <class T, class U> +inline +NSCAP_BOOL +operator!=( const nsRefPtr<T>& lhs, U* rhs ) + { + return NS_STATIC_CAST(const T*, lhs.get()) != NS_CONST_CAST(const U*, rhs); + } + +template <class T, class U> +inline +NSCAP_BOOL +operator!=( U* lhs, const nsRefPtr<T>& rhs ) + { + return NS_CONST_CAST(const U*, lhs) != NS_STATIC_CAST(const T*, rhs.get()); + } +#endif + + + + // Comparing an |nsRefPtr| to |0| + +template <class T> +inline +NSCAP_BOOL +operator==( const nsRefPtr<T>& lhs, NSCAP_Zero* rhs ) + // specifically to allow |smartPtr == 0| + { + return NS_STATIC_CAST(const void*, lhs.get()) == NS_REINTERPRET_CAST(const void*, rhs); + } + +template <class T> +inline +NSCAP_BOOL +operator==( NSCAP_Zero* lhs, const nsRefPtr<T>& rhs ) + // specifically to allow |0 == smartPtr| + { + return NS_REINTERPRET_CAST(const void*, lhs) == NS_STATIC_CAST(const void*, rhs.get()); + } + +template <class T> +inline +NSCAP_BOOL +operator!=( const nsRefPtr<T>& lhs, NSCAP_Zero* rhs ) + // specifically to allow |smartPtr != 0| + { + return NS_STATIC_CAST(const void*, lhs.get()) != NS_REINTERPRET_CAST(const void*, rhs); + } + +template <class T> +inline +NSCAP_BOOL +operator!=( NSCAP_Zero* lhs, const nsRefPtr<T>& rhs ) + // specifically to allow |0 != smartPtr| + { + return NS_REINTERPRET_CAST(const void*, lhs) != NS_STATIC_CAST(const void*, rhs.get()); + } + + +#ifdef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO + + // We need to explicitly define comparison operators for `int' + // because the compiler is lame. + +template <class T> +inline +NSCAP_BOOL +operator==( const nsRefPtr<T>& lhs, int rhs ) + // specifically to allow |smartPtr == 0| + { + return NS_STATIC_CAST(const void*, lhs.get()) == NS_REINTERPRET_CAST(const void*, rhs); + } + +template <class T> +inline +NSCAP_BOOL +operator==( int lhs, const nsRefPtr<T>& rhs ) + // specifically to allow |0 == smartPtr| + { + return NS_REINTERPRET_CAST(const void*, lhs) == NS_STATIC_CAST(const void*, rhs.get()); + } + +#endif // !defined(HAVE_CPP_TROUBLE_COMPARING_TO_ZERO) + +/*****************************************************************************/ + +#endif // !defined(nsAutoPtr_h___) diff --git a/src/libs/xpcom18a4/xpcom/base/nsCom.h b/src/libs/xpcom18a4/xpcom/base/nsCom.h new file mode 100644 index 00000000..54b0b8bf --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/base/nsCom.h @@ -0,0 +1,43 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef nsCom_h__ +#define nsCom_h__ +#include "nscore.h" +#endif + + diff --git a/src/libs/xpcom18a4/xpcom/base/nsConsoleMessage.cpp b/src/libs/xpcom18a4/xpcom/base/nsConsoleMessage.cpp new file mode 100644 index 00000000..02dc589b --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/base/nsConsoleMessage.cpp @@ -0,0 +1,69 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/* + * Base implementation for console messages. + */ + +#include "nsConsoleMessage.h" +#include "nsReadableUtils.h" + +NS_IMPL_THREADSAFE_ISUPPORTS1(nsConsoleMessage, nsIConsoleMessage) + +nsConsoleMessage::nsConsoleMessage() +{ +} + +nsConsoleMessage::nsConsoleMessage(const PRUnichar *message) +{ + mMessage.Assign(message); +} + +NS_IMETHODIMP +nsConsoleMessage::GetMessage(PRUnichar **result) { + *result = ToNewUnicode(mMessage); + + return NS_OK; +} + +// NS_IMETHODIMP +// nsConsoleMessage::Init(const PRUnichar *message) { +// nsAutoString newMessage(message); +// mMessage = ToNewUnicode(newMessage); +// return NS_OK; +// } + diff --git a/src/libs/xpcom18a4/xpcom/base/nsConsoleMessage.h b/src/libs/xpcom18a4/xpcom/base/nsConsoleMessage.h new file mode 100644 index 00000000..3d4a7e6c --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/base/nsConsoleMessage.h @@ -0,0 +1,58 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef __nsconsolemessage_h__ +#define __nsconsolemessage_h__ + +#include "nsIConsoleMessage.h" +#include "nsString.h" + +class nsConsoleMessage : public nsIConsoleMessage { +public: + nsConsoleMessage(); + nsConsoleMessage(const PRUnichar *message); + + NS_DECL_ISUPPORTS + NS_DECL_NSICONSOLEMESSAGE + +private: + ~nsConsoleMessage() {} + + nsString mMessage; +}; + +#endif /* __nsconsolemessage_h__ */ diff --git a/src/libs/xpcom18a4/xpcom/base/nsConsoleService.cpp b/src/libs/xpcom18a4/xpcom/base/nsConsoleService.cpp new file mode 100644 index 00000000..1b369071 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/base/nsConsoleService.cpp @@ -0,0 +1,321 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/* + * Maintains a circular buffer of recent messages, and notifies + * listeners when new messages are logged. + */ + +/* Threadsafe. */ + +#include "nsMemory.h" +#include "nsIServiceManager.h" +#include "nsIProxyObjectManager.h" +#include "nsSupportsArray.h" + +#include "nsConsoleService.h" +#include "nsConsoleMessage.h" + +NS_IMPL_THREADSAFE_ISUPPORTS1(nsConsoleService, nsIConsoleService) + +nsConsoleService::nsConsoleService() + : mCurrent(0), mFull(PR_FALSE), mListening(PR_FALSE), mLock(nsnull) +{ + // XXX grab this from a pref! + // hm, but worry about circularity, bc we want to be able to report + // prefs errs... + mBufferSize = 250; + + // XXX deal with these two allocations by detecting null mLock in factory? + mMessages = (nsIConsoleMessage **) + nsMemory::Alloc(mBufferSize * sizeof(nsIConsoleMessage *)); + + mLock = PR_NewLock(); + + // Array elements should be 0 initially for circular buffer algorithm. + for (PRUint32 i = 0; i < mBufferSize; i++) { + mMessages[i] = nsnull; + } + +} + +nsConsoleService::~nsConsoleService() +{ + PRUint32 i = 0; + while (i < mBufferSize && mMessages[i] != nsnull) { + NS_RELEASE(mMessages[i]); + i++; + } + +#ifdef DEBUG_mccabe + if (mListeners.Count() != 0) { + fprintf(stderr, + "WARNING - %d console error listeners still registered!\n" + "More calls to nsIConsoleService::UnregisterListener needed.\n", + mListeners.Count()); + } + +#endif + + nsMemory::Free(mMessages); + if (mLock) + PR_DestroyLock(mLock); +} + +static PRBool PR_CALLBACK snapshot_enum_func(nsHashKey *key, void *data, void* closure) +{ + nsISupportsArray *array = (nsISupportsArray *)closure; + + // Copy each element into the temporary nsSupportsArray... + array->AppendElement((nsISupports*)data); + return PR_TRUE; +} + +// nsIConsoleService methods +NS_IMETHODIMP +nsConsoleService::LogMessage(nsIConsoleMessage *message) +{ + if (message == nsnull) + return NS_ERROR_INVALID_ARG; + + nsSupportsArray listenersSnapshot; + nsIConsoleMessage *retiredMessage; + + NS_ADDREF(message); // early, in case it's same as replaced below. + + /* + * Lock while updating buffer, and while taking snapshot of + * listeners array. + */ + { + nsAutoLock lock(mLock); + + /* + * If there's already a message in the slot we're about to replace, + * we've wrapped around, and we need to release the old message. We + * save a pointer to it, so we can release below outside the lock. + */ + retiredMessage = mMessages[mCurrent]; + + mMessages[mCurrent++] = message; + if (mCurrent == mBufferSize) { + mCurrent = 0; // wrap around. + mFull = PR_TRUE; + } + + /* + * Copy the listeners into the snapshot array - in case a listener + * is removed during an Observe(...) notification... + */ + mListeners.Enumerate(snapshot_enum_func, &listenersSnapshot); + } + if (retiredMessage != nsnull) + NS_RELEASE(retiredMessage); + + /* + * Iterate through any registered listeners and tell them about + * the message. We use the mListening flag to guard against + * recursive message logs. This could sometimes result in + * listeners being skipped because of activity on other threads, + * when we only care about the recursive case. + */ + nsCOMPtr<nsIConsoleListener> listener; + nsresult rv; + nsresult returned_rv; + PRUint32 snapshotCount; + rv = listenersSnapshot.Count(&snapshotCount); + if (NS_FAILED(rv)) + return rv; + + { + nsAutoLock lock(mLock); + if (mListening) + return NS_OK; + mListening = PR_TRUE; + } + + returned_rv = NS_OK; + for (PRUint32 i = 0; i < snapshotCount; i++) { + rv = listenersSnapshot.GetElementAt(i, getter_AddRefs(listener)); + if (NS_FAILED(rv)) { + returned_rv = rv; + break; // fall thru to mListening restore code below. + } + listener->Observe(message); + } + + { + nsAutoLock lock(mLock); + mListening = PR_FALSE; + } + + return returned_rv; +} + +NS_IMETHODIMP +nsConsoleService::LogStringMessage(const PRUnichar *message) +{ + nsConsoleMessage *msg = new nsConsoleMessage(message); + return this->LogMessage(msg); +} + +NS_IMETHODIMP +nsConsoleService::GetMessageArray(nsIConsoleMessage ***messages, PRUint32 *count) +{ + nsIConsoleMessage **messageArray; + + /* + * Lock the whole method, as we don't want anyone mucking with mCurrent or + * mFull while we're copying out the buffer. + */ + nsAutoLock lock(mLock); + + if (mCurrent == 0 && !mFull) { + /* + * Make a 1-length output array so that nobody gets confused, + * and return a count of 0. This should result in a 0-length + * array object when called from script. + */ + messageArray = (nsIConsoleMessage **) + nsMemory::Alloc(sizeof (nsIConsoleMessage *)); + *messageArray = nsnull; + *messages = messageArray; + *count = 0; + + return NS_OK; + } + + PRUint32 resultSize = mFull ? mBufferSize : mCurrent; + messageArray = + (nsIConsoleMessage **)nsMemory::Alloc((sizeof (nsIConsoleMessage *)) + * resultSize); + + if (messageArray == nsnull) { + *messages = nsnull; + *count = 0; + return NS_ERROR_FAILURE; + } + + PRUint32 i; + if (mFull) { + for (i = 0; i < mBufferSize; i++) { + // if full, fill the buffer starting from mCurrent (which'll be + // oldest) wrapping around the buffer to the most recent. + messageArray[i] = mMessages[(mCurrent + i) % mBufferSize]; + NS_ADDREF(messageArray[i]); + } + } else { + for (i = 0; i < mCurrent; i++) { + messageArray[i] = mMessages[i]; + NS_ADDREF(messageArray[i]); + } + } + *count = resultSize; + *messages = messageArray; + + return NS_OK; +} + +NS_IMETHODIMP +nsConsoleService::RegisterListener(nsIConsoleListener *listener) { + nsresult rv; + + /* + * Store a threadsafe proxy to the listener rather than the + * listener itself; we want the console service to be callable + * from any thread, but listeners can be implemented in + * thread-specific ways, and we always want to call them on their + * originating thread. JavaScript is the motivating example. + */ + nsCOMPtr<nsIConsoleListener> proxiedListener; + + rv = GetProxyForListener(listener, getter_AddRefs(proxiedListener)); + if (NS_FAILED(rv)) + return rv; + + { + nsAutoLock lock(mLock); + nsISupportsKey key(listener); + + /* + * Put the proxy event listener into a hashtable using the *real* + * listener as the key. + * + * This is necessary because proxy objects do *not* maintain + * nsISupports identity. Therefore, since GetProxyForListener(...) + * can return different proxies for the same object (see bug #85831) + * we need to use the real object as the unique key... + */ + mListeners.Put(&key, proxiedListener); + } + return NS_OK; +} + +NS_IMETHODIMP +nsConsoleService::UnregisterListener(nsIConsoleListener *listener) { + nsAutoLock lock(mLock); + + nsISupportsKey key(listener); + mListeners.Remove(&key); + return NS_OK; +} + +nsresult +nsConsoleService::GetProxyForListener(nsIConsoleListener* aListener, + nsIConsoleListener** aProxy) +{ + nsresult rv; + *aProxy = nsnull; + + nsCOMPtr<nsIProxyObjectManager> proxyManager = + (do_GetService(NS_XPCOMPROXY_CONTRACTID)); + + if (proxyManager == nsnull) + return NS_ERROR_NOT_AVAILABLE; + + /* + * NOTE this will fail if the calling thread doesn't have an eventQ. + * + * Would it be better to catch that case and leave the listener unproxied? + */ + rv = proxyManager->GetProxyForObject(NS_CURRENT_EVENTQ, + NS_GET_IID(nsIConsoleListener), + aListener, + PROXY_ASYNC | PROXY_ALWAYS, + (void**) aProxy); + return rv; +} diff --git a/src/libs/xpcom18a4/xpcom/base/nsConsoleService.h b/src/libs/xpcom18a4/xpcom/base/nsConsoleService.h new file mode 100644 index 00000000..59758f84 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/base/nsConsoleService.h @@ -0,0 +1,89 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/* + * nsConsoleService class declaration. + */ + +#ifndef __nsconsoleservice_h__ +#define __nsconsoleservice_h__ + +#include "nsCOMPtr.h" +#include "nsHashtable.h" +#include "nsAutoLock.h" + +#include "nsIConsoleService.h" + +class nsConsoleService : public nsIConsoleService +{ +public: + nsConsoleService(); + + NS_DECL_ISUPPORTS + NS_DECL_NSICONSOLESERVICE + +private: + ~nsConsoleService(); + + // build (or find) a proxy for the listener + nsresult GetProxyForListener(nsIConsoleListener* aListener, + nsIConsoleListener** aProxy); + + // Circular buffer of saved messages + nsIConsoleMessage **mMessages; + + // How big? + PRUint32 mBufferSize; + + // Index of slot in mMessages that'll be filled by *next* log message + PRUint32 mCurrent; + + // Is the buffer full? (Has mCurrent wrapped around at least once?) + PRBool mFull; + + // Listeners to notify whenever a new message is logged. + nsSupportsHashtable mListeners; + + // Current listener being notified of a logged error - to prevent + // stack overflows. + PRBool mListening; + + // To serialize interesting methods. + PRLock *mLock; +}; + +#endif /* __nsconsoleservice_h__ */ diff --git a/src/libs/xpcom18a4/xpcom/base/nsDebugImpl.cpp b/src/libs/xpcom18a4/xpcom/base/nsDebugImpl.cpp new file mode 100644 index 00000000..f8806092 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/base/nsDebugImpl.cpp @@ -0,0 +1,477 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * IBM Corp. + * Henry Sobotka + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsXPCOMPrivate.h" +#include "nsDebugImpl.h" +#include "nsDebug.h" +#include "prprf.h" +#include "prlog.h" +#include "prinit.h" +#include "plstr.h" +#include "nsError.h" +#include "prerror.h" +#include "prerr.h" + +#if defined(XP_BEOS) +/* For DEBUGGER macros */ +#include <Debug.h> +#endif + +#if defined(XP_UNIX) || defined(_WIN32) || defined(XP_OS2) || defined(XP_BEOS) +/* for abort() and getenv() */ +#include <stdlib.h> +#endif + +#if defined(XP_UNIX) && !defined(UNIX_CRASH_ON_ASSERT) +#include <signal.h> +/* for nsTraceRefcnt::WalkTheStack() */ +#include "nsISupportsUtils.h" +#include "nsTraceRefcntImpl.h" + +#if defined(__GNUC__) && defined(__i386) +# define DebugBreak() { asm("int $3"); } +#elif defined(__APPLE__) && defined(TARGET_CARBON) +# include "MacTypes.h" +# define DebugBreak() { Debugger(); } +#else +# define DebugBreak() +#endif +#endif + +#if defined(XP_OS2) + /* Added definitions for DebugBreak() for 2 different OS/2 compilers. Doing + * the int3 on purpose so that a developer can step over the + * instruction if so desired. Not always possible if trapping due to exception + * handling IBM-AKR + */ + #define INCL_WINDIALOGS // need for WinMessageBox + #include <os2.h> + #include <string.h> + + #if defined(DEBUG) + #define DebugBreak() { asm("int $3"); } + #else + #define DebugBreak() + #endif /* DEBUG */ +#endif /* XP_OS2 */ + +#if defined(_WIN32) +#include <windows.h> +#include <signal.h> +#elif defined(XP_MAC) + #define TEMP_MAC_HACK + + //------------------------ + #ifdef TEMP_MAC_HACK + #include <MacTypes.h> + #include <Processes.h> + #include <string.h> + + // TEMPORARY UNTIL WE HAVE MACINTOSH ENVIRONMENT VARIABLES THAT CAN TURN ON + // LOGGING ON MACINTOSH + // At this moment, NSPR's logging is a no-op on Macintosh. + + #include <stdarg.h> + #include <stdio.h> + + #undef PR_LOG + #undef PR_LogFlush + #define PR_LOG(module,level,args) dprintf args + #define PR_LogFlush() + static void dprintf(const char *format, ...) + { + va_list ap; + Str255 buffer; + + va_start(ap, format); + buffer[0] = std::vsnprintf((char *)buffer + 1, sizeof(buffer) - 1, format, ap); + va_end(ap); + if (PL_strcasestr((char *)&buffer[1], "warning")) + printf("¥¥¥%s\n", (char*)buffer + 1); + else + DebugStr(buffer); + } + #endif // TEMP_MAC_HACK + //------------------------ +#elif defined(XP_UNIX) +#include<stdlib.h> +#endif + +/* + * Determine if debugger is present in windows. + */ +#if defined (_WIN32) + +typedef WINBASEAPI BOOL (WINAPI* LPFNISDEBUGGERPRESENT)(); +PRBool InDebugger() +{ + PRBool fReturn = PR_FALSE; + LPFNISDEBUGGERPRESENT lpfnIsDebuggerPresent = NULL; + HINSTANCE hKernel = LoadLibrary("Kernel32.dll"); + + if(hKernel) + { + lpfnIsDebuggerPresent = + (LPFNISDEBUGGERPRESENT)GetProcAddress(hKernel, "IsDebuggerPresent"); + if(lpfnIsDebuggerPresent) + { + fReturn = (*lpfnIsDebuggerPresent)(); + } + FreeLibrary(hKernel); + } + + return fReturn; +} + +#endif /* WIN32*/ + +NS_IMPL_THREADSAFE_ISUPPORTS1(nsDebugImpl, nsIDebug) + +nsDebugImpl::nsDebugImpl() +{ +} + +/** + * Implementation of the nsDebug methods. Note that this code is + * always compiled in, in case some other module that uses it is + * compiled with debugging even if this library is not. + */ +static PRLogModuleInfo* gDebugLog; + +static void InitLog(void) +{ + if (0 == gDebugLog) { + gDebugLog = PR_NewLogModule("nsDebug"); + gDebugLog->level = PR_LOG_DEBUG; + } +} + + + +NS_IMETHODIMP +nsDebugImpl::Assertion(const char *aStr, const char *aExpr, const char *aFile, PRInt32 aLine) +{ + InitLog(); + + char buf[1000]; + PR_snprintf(buf, sizeof(buf), + "###!!! ASSERTION: %s: '%s', file %s, line %d", + aStr, aExpr, aFile, aLine); + + // Write out the assertion message to the debug log + PR_LOG(gDebugLog, PR_LOG_ERROR, ("%s", buf)); + PR_LogFlush(); + + // And write it out to the stderr + fprintf(stderr, "%s\n", buf); + fflush(stderr); + +#if defined(_WIN32) + char* assertBehavior = getenv("XPCOM_DEBUG_BREAK"); + if (assertBehavior && strcmp(assertBehavior, "warn") == 0) + return NS_OK; + + if(!InDebugger()) + { + DWORD code = IDRETRY; + + /* Create the debug dialog out of process to avoid the crashes caused by + * Windows events leaking into our event loop from an in process dialog. + * We do this by launching windbgdlg.exe (built in xpcom/windbgdlg). + * See http://bugzilla.mozilla.org/show_bug.cgi?id=54792 + */ + PROCESS_INFORMATION pi; + STARTUPINFO si; + char executable[MAX_PATH]; + char* pName; + + memset(&pi, 0, sizeof(pi)); + + memset(&si, 0, sizeof(si)); + si.cb = sizeof(si); + si.wShowWindow = SW_SHOW; + + if(GetModuleFileName(GetModuleHandle(XPCOM_DLL), executable, MAX_PATH) && + NULL != (pName = strrchr(executable, '\\')) && + NULL != strcpy(pName+1, "windbgdlg.exe") && +#ifdef DEBUG_jband + (printf("Launching %s\n", executable), PR_TRUE) && +#endif + CreateProcess(executable, buf, NULL, NULL, PR_FALSE, + DETACHED_PROCESS | NORMAL_PRIORITY_CLASS, + NULL, NULL, &si, &pi) && + WAIT_OBJECT_0 == WaitForSingleObject(pi.hProcess, INFINITE) && + GetExitCodeProcess(pi.hProcess, &code)) + { + CloseHandle(pi.hProcess); + } + + switch(code) + { + case IDABORT: + //This should exit us + raise(SIGABRT); + //If we are ignored exit this way.. + _exit(3); + break; + + case IDIGNORE: + return NS_OK; + // Fall Through + } + } +#endif + +#if defined(XP_OS2) + char* assertBehavior = getenv("XPCOM_DEBUG_BREAK"); + if (assertBehavior && strcmp(assertBehavior, "warn") == 0) + return NS_OK; + + char msg[1200]; + PR_snprintf(msg, sizeof(msg), + "%s\n\nClick Cancel to Debug Application.\n" + "Click Enter to continue running the Application.", buf); + ULONG code = MBID_ERROR; + code = WinMessageBox(HWND_DESKTOP, HWND_DESKTOP, msg, + "nsDebug::Assertion", 0, + MB_ERROR | MB_ENTERCANCEL); + + /* It is possible that we are executing on a thread that doesn't have a + * message queue. In that case, the message won't appear, and code will + * be 0xFFFF. We'll give the user a chance to debug it by calling + * Break() + * Actually, that's a really bad idea since this happens a lot with threadsafe + * assertions and since it means that you can't actually run the debug build + * outside a debugger without it crashing constantly. + */ + if(( code == MBID_ENTER ) || (code == MBID_ERROR)) + { + return NS_OK; + // If Retry, Fall Through + } +#endif + + Break(aFile, aLine); + return NS_OK; +} + +NS_IMETHODIMP +nsDebugImpl::Break(const char *aFile, PRInt32 aLine) +{ +#ifndef TEMP_MAC_HACK + // Write out the assertion message to the debug log + InitLog(); + + PR_LOG(gDebugLog, PR_LOG_ERROR, + ("###!!! Break: at file %s, line %d", aFile, aLine)); + PR_LogFlush(); + + fprintf(stderr, "Break: at file %s, line %d\n",aFile, aLine); fflush(stderr); + fflush(stderr); + +#if defined(_WIN32) +#ifdef _M_IX86 + ::DebugBreak(); +#endif +#elif defined(XP_UNIX) && !defined(UNIX_CRASH_ON_ASSERT) + fprintf(stderr, "\07"); + + char *assertBehavior = getenv("XPCOM_DEBUG_BREAK"); + + if (!assertBehavior) { + + // the default; nothing else to do + ; + + } else if ( strcmp(assertBehavior, "suspend")== 0 ) { + + // the suspend case is first because we wanna send the signal before + // other threads have had a chance to get too far from the state that + // caused this assertion (in case they happen to have been involved). + // + fprintf(stderr, "Suspending process; attach with the debugger.\n"); + kill(0, SIGSTOP); + + } else if ( strcmp(assertBehavior, "warn")==0 ) { + + // same as default; nothing else to do (see "suspend" case comment for + // why this compare isn't done as part of the default case) + // + ; + + } + else if ( strcmp(assertBehavior,"stack")==0 ) { + + // walk the stack + // + nsTraceRefcntImpl::WalkTheStack(stderr); + } + else if ( strcmp(assertBehavior,"abort")==0 ) { + + // same as UNIX_CRASH_ON_ASSERT + // + Abort(aFile, aLine); + + } else if ( strcmp(assertBehavior,"trap")==0 ) { + + DebugBreak(); + + } else { + + fprintf(stderr, "unrecognized value of XPCOM_DEBUG_BREAK env var!\n"); + + } + fflush(stderr); // this shouldn't really be necessary, i don't think, + // but maybe there's some lame stdio that buffers stderr + +#elif defined(XP_BEOS) + { +#ifdef UNIX_CRASH_ON_ASSERT + char buf[2000]; + sprintf(buf, "Break: at file %s, line %d", aFile, aLine); + DEBUGGER(buf); +#endif + } +#else + Abort(aFile, aLine); +#endif +#endif // TEMP_MAC_HACK + return NS_OK; +} + +NS_IMETHODIMP +nsDebugImpl::Abort(const char *aFile, PRInt32 aLine) +{ + InitLog(); + + PR_LOG(gDebugLog, PR_LOG_ERROR, + ("###!!! Abort: at file %s, line %d", aFile, aLine)); + PR_LogFlush(); + fprintf(stderr, "\07 Abort\n"); fflush(stderr); + fflush(stderr); + +#if defined(_WIN32) +#ifdef _M_IX86 + long* __p = (long*) 0x7; + *__p = 0x7; +#else /* _M_ALPHA */ + PR_Abort(); +#endif +#elif defined(XP_MAC) + ExitToShell(); +#elif defined(XP_UNIX) + PR_Abort(); +#elif defined(XP_OS2) + DebugBreak(); + return NS_OK; +#elif defined(XP_BEOS) + { +#ifndef DEBUG_cls + char buf[2000]; + sprintf(buf, "Abort: at file %s, line %d", aFile, aLine); + DEBUGGER(buf); +#endif + } +#endif + return NS_OK; +} + +NS_IMETHODIMP +nsDebugImpl::Warning(const char* aMessage, + const char* aFile, PRIntn aLine) +{ + InitLog(); + + char buf[1000]; + PR_snprintf(buf, sizeof(buf), + "WARNING: %s, file %s, line %d", + aMessage, aFile, aLine); + + // Write out the warning message to the debug log + PR_LOG(gDebugLog, PR_LOG_ERROR, ("%s", buf)); + + // And write it out to the stdout + fprintf(stderr, "%s\n", buf); + fflush(stderr); + return NS_OK; +} + +NS_METHOD +nsDebugImpl::Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr) +{ + *aInstancePtr = nsnull; + nsIDebug* debug = new nsDebugImpl(); + if (!debug) + return NS_ERROR_OUT_OF_MEMORY; + + nsresult rv = debug->QueryInterface(aIID, aInstancePtr); + if (NS_FAILED(rv)) { + delete debug; + } + + return rv; +} + +//////////////////////////////////////////////////////////////////////////////// + +NS_COM nsresult +NS_ErrorAccordingToNSPR() +{ + PRErrorCode err = PR_GetError(); + switch (err) { + case PR_OUT_OF_MEMORY_ERROR: return NS_ERROR_OUT_OF_MEMORY; + case PR_WOULD_BLOCK_ERROR: return NS_BASE_STREAM_WOULD_BLOCK; + case PR_FILE_NOT_FOUND_ERROR: return NS_ERROR_FILE_NOT_FOUND; + case PR_READ_ONLY_FILESYSTEM_ERROR: return NS_ERROR_FILE_READ_ONLY; + case PR_NOT_DIRECTORY_ERROR: return NS_ERROR_FILE_NOT_DIRECTORY; + case PR_IS_DIRECTORY_ERROR: return NS_ERROR_FILE_IS_DIRECTORY; + case PR_LOOP_ERROR: return NS_ERROR_FILE_UNRESOLVABLE_SYMLINK; + case PR_FILE_EXISTS_ERROR: return NS_ERROR_FILE_ALREADY_EXISTS; + case PR_FILE_IS_LOCKED_ERROR: return NS_ERROR_FILE_IS_LOCKED; + case PR_FILE_TOO_BIG_ERROR: return NS_ERROR_FILE_TOO_BIG; + case PR_NO_DEVICE_SPACE_ERROR: return NS_ERROR_FILE_NO_DEVICE_SPACE; + case PR_NAME_TOO_LONG_ERROR: return NS_ERROR_FILE_NAME_TOO_LONG; + case PR_DIRECTORY_NOT_EMPTY_ERROR: return NS_ERROR_FILE_DIR_NOT_EMPTY; + case PR_NO_ACCESS_RIGHTS_ERROR: return NS_ERROR_FILE_ACCESS_DENIED; + default: return NS_ERROR_FAILURE; + } +} + +//////////////////////////////////////////////////////////////////////////////// + diff --git a/src/libs/xpcom18a4/xpcom/base/nsDebugImpl.h b/src/libs/xpcom18a4/xpcom/base/nsDebugImpl.h new file mode 100644 index 00000000..b6ca9770 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/base/nsDebugImpl.h @@ -0,0 +1,61 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is XPCOM + * + * The Initial Developer of the Original Code is Doug Turner <dougt@meer.net> + * + * Portions created by the Initial Developer are Copyright (C) 2003 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsIDebug.h" + +class nsDebugImpl : public nsIDebug +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSIDEBUG + + nsDebugImpl(); + static NS_METHOD Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr); + +private: + ~nsDebugImpl() {} +}; + + +#define NS_DEBUG_CONTRACTID "@mozilla.org/xpcom/debug;1" +#define NS_DEBUG_CLASSNAME "nsDebug Interface" +#define NS_DEBUG_CID \ +{ /* a80b1fb3-aaf6-4852-b678-c27eb7a518af */ \ + 0xa80b1fb3, \ + 0xaaf6, \ + 0x4852, \ + {0xb6, 0x78, 0xc2, 0x7e, 0xb7, 0xa5, 0x18, 0xaf} \ +} diff --git a/src/libs/xpcom18a4/xpcom/base/nsError.h b/src/libs/xpcom18a4/xpcom/base/nsError.h new file mode 100644 index 00000000..e0f3fe54 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/base/nsError.h @@ -0,0 +1,317 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef nsError_h__ +#define nsError_h__ + +#ifndef nscore_h___ +#include "nscore.h" /* needed for nsresult */ +#endif + +/* + * To add error code to your module, you need to do the following: + * + * 1) Add a module offset code. Add yours to the bottom of the list + * right below this comment, adding 1. + * + * 2) In your module, define a header file which uses one of the + * NE_ERROR_GENERATExxxxxx macros. Some examples below: + * + * #define NS_ERROR_MYMODULE_MYERROR1 NS_ERROR_GENERATE(NS_ERROR_SEVERITY_ERROR,NS_ERROR_MODULE_MYMODULE,1) + * #define NS_ERROR_MYMODULE_MYERROR2 NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_MYMODULE,2) + * #define NS_ERROR_MYMODULE_MYERROR3 NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_MYMODULE,3) + * + */ + + +/** + * @name Standard Module Offset Code. Each Module should identify a unique number + * and then all errors associated with that module become offsets from the + * base associated with that module id. There are 16 bits of code bits for + * each module. + */ + +#define NS_ERROR_MODULE_XPCOM 1 +#define NS_ERROR_MODULE_BASE 2 +#define NS_ERROR_MODULE_GFX 3 +#define NS_ERROR_MODULE_WIDGET 4 +#define NS_ERROR_MODULE_CALENDAR 5 +#define NS_ERROR_MODULE_NETWORK 6 +#define NS_ERROR_MODULE_PLUGINS 7 +#define NS_ERROR_MODULE_LAYOUT 8 +#define NS_ERROR_MODULE_HTMLPARSER 9 +#define NS_ERROR_MODULE_RDF 10 +#define NS_ERROR_MODULE_UCONV 11 +#define NS_ERROR_MODULE_REG 12 +#define NS_ERROR_MODULE_FILES 13 +#define NS_ERROR_MODULE_DOM 14 +#define NS_ERROR_MODULE_IMGLIB 15 +#define NS_ERROR_MODULE_MAILNEWS 16 +#define NS_ERROR_MODULE_EDITOR 17 +#define NS_ERROR_MODULE_XPCONNECT 18 +#define NS_ERROR_MODULE_PROFILE 19 +#define NS_ERROR_MODULE_LDAP 20 +#define NS_ERROR_MODULE_SECURITY 21 +#define NS_ERROR_MODULE_DOM_XPATH 22 +#define NS_ERROR_MODULE_DOM_RANGE 23 +#define NS_ERROR_MODULE_URILOADER 24 +#define NS_ERROR_MODULE_CONTENT 25 +#define NS_ERROR_MODULE_PYXPCOM 26 +#define NS_ERROR_MODULE_XSLT 27 +#define NS_ERROR_MODULE_IPC 28 +#define NS_ERROR_MODULE_SVG 29 + +/* NS_ERROR_MODULE_GENERAL should be used by modules that do not + * care if return code values overlap. Callers of methods that + * return such codes should be aware that they are not + * globally unique. Implementors should be careful about blindly + * returning codes from other modules that might also use + * the generic base. + */ +#define NS_ERROR_MODULE_GENERAL 51 + +/** + * @name Standard Error Handling Macros + */ + +#define NS_FAILED(_nsresult) (NS_UNLIKELY((_nsresult) & 0x80000000)) +#define NS_SUCCEEDED(_nsresult) (NS_LIKELY(!((_nsresult) & 0x80000000))) + +/** + * @name Severity Code. This flag identifies the level of warning + */ + +#define NS_ERROR_SEVERITY_SUCCESS 0 +#define NS_ERROR_SEVERITY_ERROR 1 + +/** + * @name Mozilla Code. This flag separates consumers of mozilla code + * from the native platform + */ + +#define NS_ERROR_MODULE_BASE_OFFSET 0x45 + +/** + * @name Standard Error Generating Macros + */ + +#define NS_ERROR_GENERATE(sev,module,code) \ + ((nsresult) (((PRUint32)(sev)<<31) | ((PRUint32)(module+NS_ERROR_MODULE_BASE_OFFSET)<<16) | ((PRUint32)(code))) ) + +#define NS_ERROR_GENERATE_SUCCESS(module,code) \ + ((nsresult) (((PRUint32)(NS_ERROR_SEVERITY_SUCCESS)<<31) | ((PRUint32)(module+NS_ERROR_MODULE_BASE_OFFSET)<<16) | ((PRUint32)(code))) ) + +#define NS_ERROR_GENERATE_FAILURE(module,code) \ + ((nsresult) (((PRUint32)(NS_ERROR_SEVERITY_ERROR)<<31) | ((PRUint32)(module+NS_ERROR_MODULE_BASE_OFFSET)<<16) | ((PRUint32)(code))) ) + +/** + * @name Standard Macros for retrieving error bits + */ + +#define NS_ERROR_GET_CODE(err) ((err) & 0xffff) +#define NS_ERROR_GET_MODULE(err) (((((err) >> 16) - NS_ERROR_MODULE_BASE_OFFSET) & 0x1fff)) +#define NS_ERROR_GET_SEVERITY(err) (((err) >> 31) & 0x1) + +/** + * @name Standard return values + */ + +/*@{*/ + +/* Standard "it worked" return value */ +#define NS_OK 0 + +#define NS_ERROR_BASE ((nsresult) 0xC1F30000) + +/* Returned when an instance is not initialized */ +#define NS_ERROR_NOT_INITIALIZED (NS_ERROR_BASE + 1) + +/* Returned when an instance is already initialized */ +#define NS_ERROR_ALREADY_INITIALIZED (NS_ERROR_BASE + 2) + +/* Returned by a not implemented function */ +#define NS_ERROR_NOT_IMPLEMENTED ((nsresult) 0x80004001L) + +/* Returned when a given interface is not supported. */ +#define NS_NOINTERFACE ((nsresult) 0x80004002L) +#define NS_ERROR_NO_INTERFACE NS_NOINTERFACE + +#define NS_ERROR_INVALID_POINTER ((nsresult) 0x80004003L) +#define NS_ERROR_NULL_POINTER NS_ERROR_INVALID_POINTER + +/* Returned when a function aborts */ +#define NS_ERROR_ABORT ((nsresult) 0x80004004L) + +/* Returned when a function fails */ +#define NS_ERROR_FAILURE ((nsresult) 0x80004005L) + +/* Returned when an IPC fails */ +#define NS_ERROR_CALL_FAILED ((nsresult) 0x800706beL) + +/* Returned when an unexpected error occurs */ +#define NS_ERROR_UNEXPECTED ((nsresult) 0x8000ffffL) + +/* Returned when a memory allocation fails */ +#define NS_ERROR_OUT_OF_MEMORY ((nsresult) 0x8007000eL) + +/* Returned when an illegal value is passed */ +#define NS_ERROR_ILLEGAL_VALUE ((nsresult) 0x80070057L) +#define NS_ERROR_INVALID_ARG NS_ERROR_ILLEGAL_VALUE + +/* Returned when a class doesn't allow aggregation */ +#define NS_ERROR_NO_AGGREGATION ((nsresult) 0x80040110L) + +/* Returned when an operation can't complete due to an unavailable resource */ +#define NS_ERROR_NOT_AVAILABLE ((nsresult) 0x80040111L) + +/* Returned when a class is not registered */ +#define NS_ERROR_FACTORY_NOT_REGISTERED ((nsresult) 0x80040154L) + +/* Returned when a class cannot be registered, but may be tried again later */ +#define NS_ERROR_FACTORY_REGISTER_AGAIN ((nsresult) 0x80040155L) + +/* Returned when a dynamically loaded factory couldn't be found */ +#define NS_ERROR_FACTORY_NOT_LOADED ((nsresult) 0x800401f8L) + +/* Returned when a factory doesn't support signatures */ +#define NS_ERROR_FACTORY_NO_SIGNATURE_SUPPORT \ + (NS_ERROR_BASE + 0x101) + +/* Returned when a factory already is registered */ +#define NS_ERROR_FACTORY_EXISTS (NS_ERROR_BASE + 0x100) + +/* Socket failures */ +#define NS_ERROR_SOCKET_FAIL (NS_ERROR_BASE + 0x200) + + +/* For COM compatibility reasons, we want to use exact error code numbers + for NS_ERROR_PROXY_INVALID_IN_PARAMETER and NS_ERROR_PROXY_INVALID_OUT_PARAMETER. + The first matches: + + #define RPC_E_INVALID_PARAMETER _HRESULT_TYPEDEF_(0x80010010L) + + Errors returning this mean that the xpcom proxy code could not create a proxy for + one of the in paramaters. + + Because of this, we are ignoring the convention if using a base and offset for + error numbers. + +*/ + +/* Returned when a proxy could not be create a proxy for one of the IN parameters + This is returned only when the "real" meathod has NOT been invoked. +*/ + +#define NS_ERROR_PROXY_INVALID_IN_PARAMETER ((nsresult) 0x80010010L) + +/* Returned when a proxy could not be create a proxy for one of the OUT parameters + This is returned only when the "real" meathod has ALREADY been invoked. +*/ + +#define NS_ERROR_PROXY_INVALID_OUT_PARAMETER ((nsresult) 0x80010011L) + + +/*@}*/ + + /* I/O Errors */ + + /* Stream closed */ +#define NS_BASE_STREAM_CLOSED NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_BASE, 2) + /* Error from the operating system */ +#define NS_BASE_STREAM_OSERROR NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_BASE, 3) + /* Illegal arguments */ +#define NS_BASE_STREAM_ILLEGAL_ARGS NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_BASE, 4) + /* For unichar streams */ +#define NS_BASE_STREAM_NO_CONVERTER NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_BASE, 5) + /* For unichar streams */ +#define NS_BASE_STREAM_BAD_CONVERSION NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_BASE, 6) + +#define NS_BASE_STREAM_WOULD_BLOCK NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_BASE, 7) + + +#define NS_ERROR_FILE_UNRECOGNIZED_PATH NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 1) +#define NS_ERROR_FILE_UNRESOLVABLE_SYMLINK NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 2) +#define NS_ERROR_FILE_EXECUTION_FAILED NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 3) +#define NS_ERROR_FILE_UNKNOWN_TYPE NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 4) +#define NS_ERROR_FILE_DESTINATION_NOT_DIR NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 5) +#define NS_ERROR_FILE_TARGET_DOES_NOT_EXIST NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 6) +#define NS_ERROR_FILE_COPY_OR_MOVE_FAILED NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 7) +#define NS_ERROR_FILE_ALREADY_EXISTS NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 8) +#define NS_ERROR_FILE_INVALID_PATH NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 9) +#define NS_ERROR_FILE_DISK_FULL NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 10) +#define NS_ERROR_FILE_CORRUPTED NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 11) +#define NS_ERROR_FILE_NOT_DIRECTORY NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 12) +#define NS_ERROR_FILE_IS_DIRECTORY NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 13) +#define NS_ERROR_FILE_IS_LOCKED NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 14) +#define NS_ERROR_FILE_TOO_BIG NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 15) +#define NS_ERROR_FILE_NO_DEVICE_SPACE NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 16) +#define NS_ERROR_FILE_NAME_TOO_LONG NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 17) +#define NS_ERROR_FILE_NOT_FOUND NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 18) +#define NS_ERROR_FILE_READ_ONLY NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 19) +#define NS_ERROR_FILE_DIR_NOT_EMPTY NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 20) +#define NS_ERROR_FILE_ACCESS_DENIED NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 21) + +#define NS_SUCCESS_FILE_DIRECTORY_EMPTY NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_FILES, 1) + + /* Result codes used by nsIVariant */ + +#define NS_ERROR_CANNOT_CONVERT_DATA NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_XPCOM, 1) +#define NS_ERROR_OBJECT_IS_IMMUTABLE NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_XPCOM, 2) +#define NS_ERROR_LOSS_OF_SIGNIFICANT_DATA NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_XPCOM, 3) + +#define NS_SUCCESS_LOSS_OF_INSIGNIFICANT_DATA NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_XPCOM, 1) + + + /* + * This will return the nsresult corresponding to the most recent NSPR failure + * returned by PR_GetError. + * + *********************************************************************** + * Do not depend on this function. It will be going away! + *********************************************************************** + */ +extern NS_COM nsresult +NS_ErrorAccordingToNSPR(); + + +#ifdef _MSC_VER +#pragma warning(disable: 4251) /* 'nsCOMPtr<class nsIInputStream>' needs to have dll-interface to be used by clients of class 'nsInputStream' */ +#pragma warning(disable: 4275) /* non dll-interface class 'nsISupports' used as base for dll-interface class 'nsIRDFNode' */ +#endif + +#endif + diff --git a/src/libs/xpcom18a4/xpcom/base/nsErrorService.cpp b/src/libs/xpcom18a4/xpcom/base/nsErrorService.cpp new file mode 100644 index 00000000..f38495ed --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/base/nsErrorService.cpp @@ -0,0 +1,153 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsErrorService.h" +#include "nsCRT.h" + +static void* PR_CALLBACK +CloneCString(nsHashKey *aKey, void *aData, void* closure) +{ + return nsCRT::strdup((const char*)aData); +} + +static PRBool PR_CALLBACK +DeleteCString(nsHashKey *aKey, void *aData, void* closure) +{ + nsCRT::free((char*)aData); + return PR_TRUE; +} + +nsInt2StrHashtable::nsInt2StrHashtable() + : mHashtable(CloneCString, nsnull, DeleteCString, nsnull, 16) +{ +} + +nsresult +nsInt2StrHashtable::Put(PRUint32 key, const char* aData) +{ + char* value = nsCRT::strdup(aData); + if (value == nsnull) + return NS_ERROR_OUT_OF_MEMORY; + nsPRUint32Key k(key); + char* oldValue = (char*)mHashtable.Put(&k, value); + if (oldValue) + nsCRT::free(oldValue); + return NS_OK; +} + +char* +nsInt2StrHashtable::Get(PRUint32 key) +{ + nsPRUint32Key k(key); + const char* value = (const char*)mHashtable.Get(&k); + if (value == nsnull) + return nsnull; + return nsCRT::strdup(value); +} + +nsresult +nsInt2StrHashtable::Remove(PRUint32 key) +{ + nsPRUint32Key k(key); + char* oldValue = (char*)mHashtable.Remove(&k); + if (oldValue) + nsCRT::free(oldValue); + return NS_OK; +} + +//////////////////////////////////////////////////////////////////////////////// + +NS_IMPL_ISUPPORTS1(nsErrorService, nsIErrorService) + +NS_METHOD +nsErrorService::Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr) +{ + NS_ENSURE_NO_AGGREGATION(outer); + nsErrorService* serv = new nsErrorService(); + if (serv == nsnull) + return NS_ERROR_OUT_OF_MEMORY; + NS_ADDREF(serv); + nsresult rv = serv->QueryInterface(aIID, aInstancePtr); + NS_RELEASE(serv); + return rv; +} + +NS_IMETHODIMP +nsErrorService::RegisterErrorStringBundle(PRInt16 errorModule, const char *stringBundleURL) +{ + return mErrorStringBundleURLMap.Put(errorModule, stringBundleURL); +} + +NS_IMETHODIMP +nsErrorService::UnregisterErrorStringBundle(PRInt16 errorModule) +{ + return mErrorStringBundleURLMap.Remove(errorModule); +} + +NS_IMETHODIMP +nsErrorService::GetErrorStringBundle(PRInt16 errorModule, char **result) +{ + char* value = mErrorStringBundleURLMap.Get(errorModule); + if (value == nsnull) + return NS_ERROR_OUT_OF_MEMORY; + *result = value; + return NS_OK; +} + +NS_IMETHODIMP +nsErrorService::RegisterErrorStringBundleKey(nsresult error, const char *stringBundleKey) +{ + return mErrorStringBundleKeyMap.Put(error, stringBundleKey); +} + +NS_IMETHODIMP +nsErrorService::UnregisterErrorStringBundleKey(nsresult error) +{ + return mErrorStringBundleKeyMap.Remove(error); +} + +NS_IMETHODIMP +nsErrorService::GetErrorStringBundleKey(nsresult error, char **result) +{ + char* value = mErrorStringBundleKeyMap.Get(error); + if (value == nsnull) + return NS_ERROR_OUT_OF_MEMORY; + *result = value; + return NS_OK; +} + +//////////////////////////////////////////////////////////////////////////////// diff --git a/src/libs/xpcom18a4/xpcom/base/nsErrorService.h b/src/libs/xpcom18a4/xpcom/base/nsErrorService.h new file mode 100644 index 00000000..70a30c0e --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/base/nsErrorService.h @@ -0,0 +1,76 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef nsErrorService_h__ +#define nsErrorService_h__ + +#include "nsIErrorService.h" +#include "nsHashtable.h" + +class nsInt2StrHashtable +{ +public: + nsInt2StrHashtable(); + + nsresult Put(PRUint32 key, const char* aData); + char* Get(PRUint32 key); + nsresult Remove(PRUint32 key); + +protected: + nsObjectHashtable mHashtable; +}; + +class nsErrorService : public nsIErrorService +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSIERRORSERVICE + + nsErrorService() {} + + static NS_METHOD + Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr); + +private: + ~nsErrorService() {} + +protected: + nsInt2StrHashtable mErrorStringBundleURLMap; + nsInt2StrHashtable mErrorStringBundleKeyMap; +}; + +#endif // nsErrorService_h__ diff --git a/src/libs/xpcom18a4/xpcom/base/nsExceptionService.cpp b/src/libs/xpcom18a4/xpcom/base/nsExceptionService.cpp new file mode 100644 index 00000000..f68f2d5f --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/base/nsExceptionService.cpp @@ -0,0 +1,383 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * ActiveState Tool Corp.. + * Portions created by the Initial Developer are Copyright (C) 2001 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Mark Hammond <MarkH@ActiveState.com> + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsISupports.h" +#include "nsExceptionService.h" +#include "nsIServiceManager.h" +#include "nsCOMPtr.h" +#include "prthread.h" +#include "prlock.h" +static const PRUintn BAD_TLS_INDEX = (PRUintn) -1; + +#define CHECK_SERVICE_USE_OK() if (tlsIndex == BAD_TLS_INDEX) return NS_ERROR_NOT_INITIALIZED +#define CHECK_MANAGER_USE_OK() if (!mService || nsExceptionService::tlsIndex == BAD_TLS_INDEX) return NS_ERROR_NOT_INITIALIZED + +// A key for our registered module providers hashtable +class nsProviderKey : public nsHashKey { +protected: + PRUint32 mKey; +public: + nsProviderKey(PRUint32 key) : mKey(key) {} + PRUint32 HashCode(void) const { + return mKey; + } + PRBool Equals(const nsHashKey *aKey) const { + return mKey == ((const nsProviderKey *) aKey)->mKey; + } + nsHashKey *Clone() const { + return new nsProviderKey(mKey); + } + PRUint32 GetValue() { return mKey; } +}; + +/** Exception Manager definition **/ +class nsExceptionManager : public nsIExceptionManager +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSIEXCEPTIONMANAGER + + nsExceptionManager(nsExceptionService *svc); + /* additional members */ + nsCOMPtr<nsIException> mCurrentException; + nsExceptionManager *mNextThread; // not ref-counted. + nsExceptionService *mService; // not ref-counted +#ifdef NS_DEBUG + static PRInt32 totalInstances; +#endif + +#ifdef NS_DEBUG + inline nsrefcnt ReleaseQuiet() { + // shut up NS_ASSERT_OWNINGTHREAD (see explanation below) + nsAutoOwningThread old = _mOwningThread; + _mOwningThread = nsAutoOwningThread(); + nsrefcnt ref = Release(); + NS_ASSERTION(ref == 0, "the object is still referenced by other threads while it shouldn't"); + if (ref != 0) + _mOwningThread = old; + return ref; + } +#else + inline nsrefcnt ReleaseQuiet(void) { return Release(); } +#endif + +private: + ~nsExceptionManager(); +}; + + +#ifdef NS_DEBUG +PRInt32 nsExceptionManager::totalInstances = 0; +#endif + +// Note: the nsExceptionManager object is single threaded - the exception +// service itself ensures one per thread. However, there are two methods that +// may be called on foreign threads: DropAllThreads (called on the thread +// shutting down xpcom) and ThreadDestruct (called after xpcom destroyed the +// internal thread struct, so that PR_GetCurrentThread() will create a new one +// from scratch which will obviously not match the old one stored in the +// instance on creation). In both cases, there should be no other threads +// holding objects (i.e. it's thread-safe to call them), but +// NS_CheckThreadSafe() assertions will still happen and yell in the debug +// build. Since it is quite annoying, we use a special ReleaseQuiet() method +// in DoDropThread() to shut them up. +NS_IMPL_THREADSAFE_ISUPPORTS1(nsExceptionManager, nsIExceptionManager) + +nsExceptionManager::nsExceptionManager(nsExceptionService *svc) : + mNextThread(nsnull), + mService(svc) +{ + /* member initializers and constructor code */ +#ifdef NS_DEBUG + PR_AtomicIncrement(&totalInstances); +#endif +} + +nsExceptionManager::~nsExceptionManager() +{ + /* destructor code */ +#ifdef NS_DEBUG + PR_AtomicDecrement(&totalInstances); +#endif // NS_DEBUG +} + +/* void setCurrentException (in nsIException error); */ +NS_IMETHODIMP nsExceptionManager::SetCurrentException(nsIException *error) +{ + CHECK_MANAGER_USE_OK(); + mCurrentException = error; + return NS_OK; +} + +/* nsIException getCurrentException (); */ +NS_IMETHODIMP nsExceptionManager::GetCurrentException(nsIException **_retval) +{ + CHECK_MANAGER_USE_OK(); + *_retval = mCurrentException; + NS_IF_ADDREF(*_retval); + return NS_OK; +} + +/* nsIException getExceptionFromProvider( in nsresult rc, in nsIException defaultException); */ +NS_IMETHODIMP nsExceptionManager::GetExceptionFromProvider(nsresult rc, nsIException * defaultException, nsIException **_retval) +{ + CHECK_MANAGER_USE_OK(); + // Just delegate back to the service with the provider map. + return mService->GetExceptionFromProvider(rc, defaultException, _retval); +} + +/* The Exception Service */ + +PRUintn nsExceptionService::tlsIndex = BAD_TLS_INDEX; +PRLock *nsExceptionService::lock = nsnull; +nsExceptionManager *nsExceptionService::firstThread = nsnull; + +#ifdef NS_DEBUG +PRInt32 nsExceptionService::totalInstances = 0; +#endif + +NS_IMPL_THREADSAFE_ISUPPORTS2(nsExceptionService, nsIExceptionService, nsIObserver) + +nsExceptionService::nsExceptionService() + : mProviders(4, PR_TRUE) /* small, thread-safe hashtable */ +{ +#ifdef NS_DEBUG + if (PR_AtomicIncrement(&totalInstances)!=1) { + NS_ERROR("The nsExceptionService is a singleton!"); + } +#endif + /* member initializers and constructor code */ + if (tlsIndex == BAD_TLS_INDEX) { + PRStatus status; + status = PR_NewThreadPrivateIndex( &tlsIndex, ThreadDestruct ); + NS_WARN_IF_FALSE(status==0, "ScriptErrorService could not allocate TLS storage."); + } + lock = PR_NewLock(); + NS_WARN_IF_FALSE(lock, "Error allocating ExceptionService lock"); + + // observe XPCOM shutdown. + nsCOMPtr<nsIObserverService> observerService = do_GetService("@mozilla.org/observer-service;1"); + NS_WARN_IF_FALSE(observerService, "Could not get observer service!"); + if (observerService) + observerService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, PR_FALSE); +} + +nsExceptionService::~nsExceptionService() +{ + Shutdown(); + if (lock) { + PRLock *tmp = lock; + lock = nsnull; + PR_DestroyLock(tmp); + } + /* destructor code */ +#ifdef NS_DEBUG + PR_AtomicDecrement(&totalInstances); +#endif +} + +/*static*/ +void nsExceptionService::ThreadDestruct( void *data ) +{ + if (!lock) { + NS_WARNING("nsExceptionService ignoring thread destruction after shutdown"); + return; + } + DropThread( (nsExceptionManager *)data ); +} + + +void nsExceptionService::Shutdown() +{ + PRUintn tmp = tlsIndex; + tlsIndex = BAD_TLS_INDEX; + PR_SetThreadPrivate(tmp, nsnull); + mProviders.Reset(); + if (lock) { + DropAllThreads(); + } +} + +/* void setCurrentException (in nsIException error); */ +NS_IMETHODIMP nsExceptionService::SetCurrentException(nsIException *error) +{ + CHECK_SERVICE_USE_OK(); + nsCOMPtr<nsIExceptionManager> sm; + nsresult nr = GetCurrentExceptionManager(getter_AddRefs(sm)); + if (NS_FAILED(nr)) + return nr; + return sm->SetCurrentException(error); +} + +/* nsIException getCurrentException (); */ +NS_IMETHODIMP nsExceptionService::GetCurrentException(nsIException **_retval) +{ + CHECK_SERVICE_USE_OK(); + nsCOMPtr<nsIExceptionManager> sm; + nsresult nr = GetCurrentExceptionManager(getter_AddRefs(sm)); + if (NS_FAILED(nr)) + return nr; + return sm->GetCurrentException(_retval); +} + +/* nsIException getExceptionFromProvider( in nsresult rc, in nsIException defaultException); */ +NS_IMETHODIMP nsExceptionService::GetExceptionFromProvider(nsresult rc, + nsIException * defaultException, nsIException **_retval) +{ + CHECK_SERVICE_USE_OK(); + return DoGetExceptionFromProvider(rc, defaultException, _retval); +} + +/* readonly attribute nsIExceptionManager currentExceptionManager; */ +NS_IMETHODIMP nsExceptionService::GetCurrentExceptionManager(nsIExceptionManager * *aCurrentScriptManager) +{ + CHECK_SERVICE_USE_OK(); + nsExceptionManager *mgr = (nsExceptionManager *)PR_GetThreadPrivate(tlsIndex); + if (mgr == nsnull) { + // Stick the new exception object in with no reference count. + mgr = new nsExceptionManager(this); + if (mgr == nsnull) + return NS_ERROR_OUT_OF_MEMORY; + PR_SetThreadPrivate(tlsIndex, mgr); + // The reference count is held in the thread-list + AddThread(mgr); + } + *aCurrentScriptManager = mgr; + NS_ADDREF(*aCurrentScriptManager); + return NS_OK; +} + +/* void registerErrorProvider (in nsIExceptionProvider provider, in PRUint32 moduleCode); */ +NS_IMETHODIMP nsExceptionService::RegisterExceptionProvider(nsIExceptionProvider *provider, PRUint32 errorModule) +{ + CHECK_SERVICE_USE_OK(); + + nsProviderKey key(errorModule); + if (mProviders.Put(&key, provider)) { + NS_WARNING("Registration of exception provider overwrote another provider with the same module code!"); + } + return NS_OK; +} + +/* void unregisterErrorProvider (in nsIExceptionProvider provider, in PRUint32 errorModule); */ +NS_IMETHODIMP nsExceptionService::UnregisterExceptionProvider(nsIExceptionProvider *provider, PRUint32 errorModule) +{ + CHECK_SERVICE_USE_OK(); + nsProviderKey key(errorModule); + if (!mProviders.Remove(&key)) { + NS_WARNING("Attempt to unregister an unregistered exception provider!"); + return NS_ERROR_UNEXPECTED; + } + return NS_OK; +} + +// nsIObserver +NS_IMETHODIMP nsExceptionService::Observe(nsISupports *aSubject, const char *aTopic, const PRUnichar *someData) +{ + Shutdown(); + return NS_OK; +} + +nsresult +nsExceptionService::DoGetExceptionFromProvider(nsresult errCode, + nsIException * defaultException, + nsIException **_exc) +{ + // Check for an existing exception + nsresult nr = GetCurrentException(_exc); + if (NS_SUCCEEDED(nr) && *_exc) { + (*_exc)->GetResult(&nr); + // If it matches our result then use it + if (nr == errCode) + return NS_OK; + NS_RELEASE(*_exc); + } + nsProviderKey key(NS_ERROR_GET_MODULE(errCode)); + nsCOMPtr<nsIExceptionProvider> provider = + dont_AddRef((nsIExceptionProvider *)mProviders.Get(&key)); + + // No provider so we'll return the default exception + if (!provider) { + *_exc = defaultException; + NS_IF_ADDREF(*_exc); + return NS_OK; + } + + return provider->GetException(errCode, defaultException, _exc); +} + +// thread management +/*static*/ void nsExceptionService::AddThread(nsExceptionManager *thread) +{ + PR_Lock(lock); + thread->mNextThread = firstThread; + firstThread = thread; + NS_ADDREF(thread); + PR_Unlock(lock); +} + +/*static*/ void nsExceptionService::DoDropThread(nsExceptionManager *thread) +{ + nsExceptionManager **emp = &firstThread; + while (*emp != thread) { + if (!*emp) + { + NS_WARNING("Could not find the thread to drop!"); + return; + } + emp = &(*emp)->mNextThread; + } + *emp = thread->mNextThread; + thread->ReleaseQuiet(); + thread = nsnull; +} + +/*static*/ void nsExceptionService::DropThread(nsExceptionManager *thread) +{ + PR_Lock(lock); + DoDropThread(thread); + PR_Unlock(lock); +} + +/*static*/ void nsExceptionService::DropAllThreads() +{ + PR_Lock(lock); + while (firstThread) + DoDropThread(firstThread); + PR_Unlock(lock); +} diff --git a/src/libs/xpcom18a4/xpcom/base/nsExceptionService.h b/src/libs/xpcom18a4/xpcom/base/nsExceptionService.h new file mode 100644 index 00000000..441a4c5b --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/base/nsExceptionService.h @@ -0,0 +1,94 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * ActiveState Tool Corp.. + * Portions created by the Initial Developer are Copyright (C) 2001 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Mark Hammond <MarkH@ActiveState.com> + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef nsExceptionService_h__ +#define nsExceptionService_h__ + +#include "nsVoidArray.h" +#include "nsIException.h" +#include "nsIExceptionService.h" +#include "nsIObserverService.h" +#include "nsHashtable.h" +#include "nsIObserver.h" + +class nsExceptionManager; + +/** Exception Service definition **/ +class nsExceptionService : public nsIExceptionService, public nsIObserver +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSIEXCEPTIONSERVICE + NS_DECL_NSIEXCEPTIONMANAGER + NS_DECL_NSIOBSERVER + + nsExceptionService(); + + /* additional members */ + nsresult DoGetExceptionFromProvider(nsresult errCode, + nsIException *defaultException, + nsIException **_richError); + void Shutdown(); + + + /* thread management and cleanup */ + static void AddThread(nsExceptionManager *); + static void DropThread(nsExceptionManager *); + static void DoDropThread(nsExceptionManager *thread); + + static void DropAllThreads(); + static nsExceptionManager *firstThread; + + nsSupportsHashtable mProviders; + + /* single lock protects both providers hashtable + and thread list */ + static PRLock* lock; + + static PRUintn tlsIndex; + static void PR_CALLBACK ThreadDestruct( void *data ); +#ifdef NS_DEBUG + static PRInt32 totalInstances; +#endif + +private: + ~nsExceptionService(); +}; + + +#endif // nsExceptionService_h__ diff --git a/src/libs/xpcom18a4/xpcom/base/nsGarbageCollector.c b/src/libs/xpcom18a4/xpcom/base/nsGarbageCollector.c new file mode 100644 index 00000000..b0447598 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/base/nsGarbageCollector.c @@ -0,0 +1,127 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Mozilla browser. + * + * The Initial Developer of the Original Code is + * Netscape Communications, Inc. + * Portions created by the Initial Developer are Copyright (C) 1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Patrick Beard <beard@netscape.com> + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/* + nsGarbageCollector.c + */ + +#ifdef GC_LEAK_DETECTOR + +/* for FILE */ +#include <stdio.h> + +/* NSPR stuff */ +#include "generic_threads.h" +#include "prthread.h" +#include "prlock.h" + +/* Linux/Win32 export private NSPR files to include/private */ +#ifdef XP_MAC +#include "pprthred.h" +#else +#include "private/pprthred.h" +#endif + +#include "nsLeakDetector.h" + +extern FILE *GC_stdout, *GC_stderr; + +extern void GC_gcollect(void); +extern void GC_clear_roots(void); + +static PRStatus PR_CALLBACK scanner(PRThread* t, void** baseAddr, PRUword count, void* closure) +{ + char* begin = (char*)baseAddr; + char* end = (char*)(baseAddr + count); + GC_mark_range_proc marker = (GC_mark_range_proc) closure; + marker(begin, end); + return PR_SUCCESS; +} + +static void mark_all_stacks(GC_mark_range_proc marker) +{ + /* PR_ThreadScanStackPointers(PR_GetCurrentThread(), &scanner, marker); */ + PR_ScanStackPointers(&scanner, (void *)marker); +} + +static void locker(void* mutex) +{ + PR_Lock(mutex); +} + +static void unlocker(void* mutex) +{ + PR_Unlock(mutex); +} + +static void stopper(void* unused) +{ + PR_SuspendAll(); +} + +static void starter(void* unused) +{ + PR_ResumeAll(); +} + +nsresult NS_InitGarbageCollector() +{ + PRLock* mutex; + + /* redirect GC's stderr to catch startup leaks. */ + GC_stderr = fopen("StartupLeaks", "w"); + + mutex = PR_NewLock(); + if (mutex == NULL) + return NS_ERROR_FAILURE; + + GC_generic_init_threads(&mark_all_stacks, mutex, + &locker, &unlocker, + &stopper, &starter); + + return NS_OK; +} + +nsresult NS_ShutdownGarbageCollector() +{ + /* do anything you need to shut down the collector. */ + return NS_OK; +} + +#endif /* GC_LEAK_DETECTOR */ diff --git a/src/libs/xpcom18a4/xpcom/base/nsIAllocator.h b/src/libs/xpcom18a4/xpcom/base/nsIAllocator.h new file mode 100644 index 00000000..2195f42d --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/base/nsIAllocator.h @@ -0,0 +1,56 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/** + * XXX This file is obsolete. Use nsIMemory.idl or nsMemory.h instead. + */ + +#ifndef nsIAllocator_h___ +#define nsIAllocator_h___ + +#include "nsMemory.h" + +#define nsIAllocator nsIMemory +#define nsAllocator nsMemory +#define GetGlobalAllocator GetGlobalMemoryService + +#define NS_IALLOCATOR_IID NS_GET_IID(nsIMemory) +#define NS_ALLOCATOR_CONTRACTID NS_MEMORY_CONTRACTID +#define NS_ALLOCATOR_CLASSNAME NS_MEMORY_CLASSNAME +#define NS_ALLOCATOR_CID NS_MEMORY_CID + +#endif /* nsIAllocator_h___ */ diff --git a/src/libs/xpcom18a4/xpcom/base/nsIConsoleListener.idl b/src/libs/xpcom18a4/xpcom/base/nsIConsoleListener.idl new file mode 100644 index 00000000..f983132d --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/base/nsIConsoleListener.idl @@ -0,0 +1,49 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/* + * Used by the console service to notify listeners of new console messages. + */ + +#include "nsISupports.idl" +#include "nsIConsoleMessage.idl" + +[scriptable, uuid(eaaf61d6-1dd1-11b2-bc6e-8fc96480f20d)] +interface nsIConsoleListener : nsISupports +{ + void observe(in nsIConsoleMessage aMessage); +}; diff --git a/src/libs/xpcom18a4/xpcom/base/nsIConsoleMessage.idl b/src/libs/xpcom18a4/xpcom/base/nsIConsoleMessage.idl new file mode 100644 index 00000000..0662a2d2 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/base/nsIConsoleMessage.idl @@ -0,0 +1,56 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsISupports.idl" + +/** + * This is intended as a base interface; implementations may want to + * provide an object that can be qi'ed to provide more specific + * message information. + */ +[scriptable, uuid(41bd8784-1dd2-11b2-9553-8606958fffe1)] +interface nsIConsoleMessage : nsISupports +{ + readonly attribute wstring message; +}; + +%{ C++ +#define NS_CONSOLEMESSAGE_CID \ +{ 0x56c9d666, 0x1dd2, 0x11b2, { 0xb4, 0x3c, 0xa8, 0x4b, 0xf3, 0xb3, 0xec, 0xbb }} + +#define NS_CONSOLEMESSAGE_CONTRACTID "@mozilla.org/consolemessage;1" +%} diff --git a/src/libs/xpcom18a4/xpcom/base/nsIConsoleService.idl b/src/libs/xpcom18a4/xpcom/base/nsIConsoleService.idl new file mode 100644 index 00000000..283c7acc --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/base/nsIConsoleService.idl @@ -0,0 +1,85 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsISupports.idl" +#include "nsIConsoleListener.idl" +#include "nsIConsoleMessage.idl" + +[scriptable, uuid(a647f184-1dd1-11b2-a9d1-8537b201161b)] +interface nsIConsoleService : nsISupports +{ + void logMessage(in nsIConsoleMessage message); + + /** + * Convenience method for logging simple messages. + */ + void logStringMessage(in wstring message); + + /** + * Get an array of all the messages logged so far. If no messages + * are logged, this function will return a count of 0, but still + * will allocate one word for messages, so as to show up as a + * 0-length array when called from script. + */ + void getMessageArray([array, size_is(count)] out nsIConsoleMessage messages, + out PRUint32 count); + + /** + * To guard against stack overflows from listeners that could log + * messages (it's easy to do this inadvertently from listeners + * implemented in JavaScript), we don't call any listeners when + * another error is already being logged. + */ + void registerListener(in nsIConsoleListener listener); + + /** + * Each registered listener should also be unregistered. + */ + void unregisterListener(in nsIConsoleListener listener); + +}; + + +%{ C++ +#define NS_CONSOLESERVICE_CLASSNAME "Console Service" + +#define NS_CONSOLESERVICE_CID \ +{ 0x7e3ff85c, 0x1dd2, 0x11b2, { 0x8d, 0x4b, 0xeb, 0x45, 0x2c, 0xb0, 0xff, 0x40 }} + +#define NS_CONSOLESERVICE_CONTRACTID "@mozilla.org/consoleservice;1" +%} + diff --git a/src/libs/xpcom18a4/xpcom/base/nsID.cpp b/src/libs/xpcom18a4/xpcom/base/nsID.cpp new file mode 100644 index 00000000..adb0d41c --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/base/nsID.cpp @@ -0,0 +1,152 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Daniel Bratell <bratell@lysator.liu.se> + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +#include "nsID.h" +#include "prprf.h" +#include "prmem.h" + +static const char gIDFormat[] = + "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}"; + +static const char gIDFormat2[] = + "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x"; + + +/** + * Multiplies the_int_var with 16 (0x10) and adds the value of the + * hexadecimal digit the_char. If it fails it returns PR_FALSE from + * the function it's used in. + */ + +#define ADD_HEX_CHAR_TO_INT_OR_RETURN_FALSE(the_char, the_int_var) \ + the_int_var = (the_int_var << 4) + the_char; \ + if(the_char >= '0' && the_char <= '9') the_int_var -= '0'; \ + else if(the_char >= 'a' && the_char <= 'f') the_int_var -= 'a'-10; \ + else if(the_char >= 'A' && the_char <= 'F') the_int_var -= 'A'-10; \ + else return PR_FALSE + + +/** + * Parses number_of_chars characters from the char_pointer pointer and + * puts the number in the dest_variable. The pointer is moved to point + * at the first character after the parsed ones. If it fails it returns + * PR_FALSE from the function the macro is used in. + */ + +#define PARSE_CHARS_TO_NUM(char_pointer, dest_variable, number_of_chars) \ + do { PRInt32 _i=number_of_chars; \ + dest_variable = 0; \ + while(_i) { \ + ADD_HEX_CHAR_TO_INT_OR_RETURN_FALSE(*char_pointer, dest_variable); \ + char_pointer++; \ + _i--; \ + } } while(0) + + +/** + * Parses a hyphen from the char_pointer string. If there is no hyphen there + * the function returns PR_FALSE from the function it's used in. The + * char_pointer is advanced one step. + */ + + #define PARSE_HYPHEN(char_pointer) if(*(char_pointer++) != '-') return PR_FALSE + +/* + * Turns a {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} string into + * an nsID. It can also handle the old format without the { and }. + */ + +NS_COM PRBool nsID::Parse(const char *aIDStr) +{ + /* Optimized for speed */ + if(!aIDStr) { + return PR_FALSE; + } + + PRBool expectFormat1 = (aIDStr[0] == '{'); + if(expectFormat1) aIDStr++; + + PARSE_CHARS_TO_NUM(aIDStr, m0, 8); + PARSE_HYPHEN(aIDStr); + PARSE_CHARS_TO_NUM(aIDStr, m1, 4); + PARSE_HYPHEN(aIDStr); + PARSE_CHARS_TO_NUM(aIDStr, m2, 4); + PARSE_HYPHEN(aIDStr); + int i; + for(i=0; i<2; i++) + PARSE_CHARS_TO_NUM(aIDStr, m3[i], 2); + PARSE_HYPHEN(aIDStr); + while(i < 8) { + PARSE_CHARS_TO_NUM(aIDStr, m3[i], 2); + i++; + } + + return expectFormat1 ? *aIDStr == '}' : PR_TRUE; +} + +/* + * Returns an allocated string in {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} + * format. The string is allocated with PR_Malloc and should be freed by + * the caller. + */ + +NS_COM char *nsID::ToString() const +{ + char *res = (char*)PR_Malloc(39); // use PR_Malloc if this is to be freed with nsCRT::free + + if (res != NULL) { + PR_snprintf(res, 39, gIDFormat, + m0, (PRUint32) m1, (PRUint32) m2, + (PRUint32) m3[0], (PRUint32) m3[1], (PRUint32) m3[2], + (PRUint32) m3[3], (PRUint32) m3[4], (PRUint32) m3[5], + (PRUint32) m3[6], (PRUint32) m3[7]); + } + return res; +} + +#ifdef VBOX +void nsID::ToProvidedString(char (&dest)[NSID_LENGTH]) const +{ + PR_snprintf(dest, NSID_LENGTH, gIDFormat, + m0, (PRUint32) m1, (PRUint32) m2, + (PRUint32) m3[0], (PRUint32) m3[1], (PRUint32) m3[2], + (PRUint32) m3[3], (PRUint32) m3[4], (PRUint32) m3[5], + (PRUint32) m3[6], (PRUint32) m3[7]); +} +#endif + + diff --git a/src/libs/xpcom18a4/xpcom/base/nsID.h b/src/libs/xpcom18a4/xpcom/base/nsID.h new file mode 100644 index 00000000..257ba927 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/base/nsID.h @@ -0,0 +1,166 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef nsID_h__ +#define nsID_h__ + +#include <string.h> + +#ifndef nscore_h___ +#include "nscore.h" +#endif + +#ifdef VBOX +#define NSID_LENGTH 39 +#endif + +/** + * A "unique identifier". This is modeled after OSF DCE UUIDs. + * @status FROZEN + */ + +struct nsID { + /** + * @name Indentifier values + */ + + //@{ + PRUint32 m0; + PRUint16 m1; + PRUint16 m2; + PRUint8 m3[8]; + //@} + + /** + * @name Methods + */ + + //@{ + /** + * Equivalency method. Compares this nsID with another. + * @return <b>PR_TRUE</b> if they are the same, <b>PR_FALSE</b> if not. + */ + + inline PRBool Equals(const nsID& other) const { + // One would think that this could be done faster with a really + // efficient implementation of memcmp(), but evidently no + // memcmp()'s out there are better than this code. + // + // See bug http://bugzilla.mozilla.org/show_bug.cgi?id=164580 for + // details. + + return (PRBool) + ((((PRUint32*) &m0)[0] == ((PRUint32*) &other.m0)[0]) && + (((PRUint32*) &m0)[1] == ((PRUint32*) &other.m0)[1]) && + (((PRUint32*) &m0)[2] == ((PRUint32*) &other.m0)[2]) && + (((PRUint32*) &m0)[3] == ((PRUint32*) &other.m0)[3])); + } + + /** + * nsID Parsing method. Turns a {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} + * string into an nsID + */ + NS_COM PRBool Parse(const char *aIDStr); + + /** + * nsID string encoder. Returns an allocated string in + * {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} format. Caller should free string. + */ + NS_COM char* ToString() const; + +#ifdef VBOX + /** + * nsID string encoder. Builds a string in + * {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} format, into a char[NSID_LENGTH] + * buffer provided by the caller (for instance, on the stack). + */ + NS_COM void ToProvidedString(char (&dest)[NSID_LENGTH]) const; +#endif + + //@} +}; + +/* + * Class IDs + */ + +typedef nsID nsCID; + +// Define an CID +#define NS_DEFINE_CID(_name, _cidspec) \ + const nsCID _name = _cidspec + +#define REFNSCID const nsCID& + +/** + * An "interface id" which can be used to uniquely identify a given + * interface. + */ + +typedef nsID nsIID; + +/** + * A macro shorthand for <tt>const nsIID&<tt> + */ + +#define REFNSIID const nsIID& + +/** + * Define an IID + * obsolete - do not use this macro + */ + +#define NS_DEFINE_IID(_name, _iidspec) \ + const nsIID _name = _iidspec + +/** + * A macro to build the static const IID accessor method + */ + +#define NS_DEFINE_STATIC_IID_ACCESSOR(the_iid) \ + static const nsIID& GetIID() {static const nsIID iid = the_iid; return iid;} + +/** + * A macro to build the static const CID accessor method + */ + +#define NS_DEFINE_STATIC_CID_ACCESSOR(the_cid) \ + static const nsID& GetCID() {static const nsID cid = the_cid; return cid;} + +#endif + + diff --git a/src/libs/xpcom18a4/xpcom/base/nsIDebug.idl b/src/libs/xpcom18a4/xpcom/base/nsIDebug.idl new file mode 100644 index 00000000..73b3912a --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/base/nsIDebug.idl @@ -0,0 +1,67 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is XPCOM + * + * The Initial Developer of the Original Code is Doug Turner <dougt@meer.net> + * + * Portions created by the Initial Developer are Copyright (C) 2003 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + + +#include "nsISupports.idl" + +/** + * nsIDebug is an interface between XPCOM Glue and XPCOM. Users should access + * the nsIDebug interface through the static class nsDebug. + * @see nsDebug.h + * + * @status UNDER_REVIEW + * + */ + +[scriptable, uuid(3bf0c3d7-3bd9-4cf2-a971-33572c503e1e)] +interface nsIDebug : nsISupports +{ + void assertion(in string aStr, + in string aExpr, + in string aFile, + in long aLine); + + void warning(in string aStr, + in string aFile, + in long aLine); + + void break(in string aFile, + in long aLine); + + void abort(in string aFile, + in long aLine); +}; + diff --git a/src/libs/xpcom18a4/xpcom/base/nsIErrorService.idl b/src/libs/xpcom18a4/xpcom/base/nsIErrorService.idl new file mode 100644 index 00000000..c4ed3964 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/base/nsIErrorService.idl @@ -0,0 +1,100 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsISupports.idl" + +/** + * nsIErrorService: This is an interim service that allows nsresult codes to be mapped to + * string bundles that can be used to look up error messages. String bundle keys can also + * be mapped. + * + * This service will eventually get replaced by extending xpidl to allow errors to be defined. + * (http://bugzilla.mozilla.org/show_bug.cgi?id=13423). + */ +[scriptable, uuid(e72f94b2-5f85-11d4-9877-00c04fa0cf4a)] +interface nsIErrorService : nsISupports +{ + /** + * Registers a string bundle URL for an error module. Error modules are obtained from + * nsresult code with NS_ERROR_GET_MODULE. + */ + void registerErrorStringBundle(in short errorModule, in string stringBundleURL); + + /** + * Registers a string bundle URL for an error module. + */ + void unregisterErrorStringBundle(in short errorModule); + + /** + * Retrieves a string bundle URL for an error module. + */ + string getErrorStringBundle(in short errorModule); + + /** + * Registers a key in a string bundle for an nsresult error code. Only the code portion + * of the nsresult is used (obtained with NS_ERROR_GET_CODE) in this registration. The + * string bundle key is used to look up internationalized messages in the string bundle. + */ + void registerErrorStringBundleKey(in nsresult error, in string stringBundleKey); + + /** + * Unregisters a key in a string bundle for an nsresult error code. + */ + void unregisterErrorStringBundleKey(in nsresult error); + + /** + * Retrieves a key in a string bundle for an nsresult error code. If no key is registered + * for the specified nsresult's code (obtained with NS_ERROR_GET_CODE), then the stringified + * version of the nsresult code is returned. + */ + string getErrorStringBundleKey(in nsresult error); +}; + +%{C++ + +// The global nsIErrorService: +#define NS_ERRORSERVICE_NAME "Error Service" +#define NS_ERRORSERVICE_CONTRACTID "@mozilla.org/xpcom/error-service;1" +#define NS_ERRORSERVICE_CID \ +{ /* 744afd5e-5f8c-11d4-9877-00c04fa0cf4a */ \ + 0x744afd5e, \ + 0x5f8c, \ + 0x11d4, \ + {0x98, 0x77, 0x00, 0xc0, 0x4f, 0xa0, 0xcf, 0x4a} \ +} + +%} diff --git a/src/libs/xpcom18a4/xpcom/base/nsIException.idl b/src/libs/xpcom18a4/xpcom/base/nsIException.idl new file mode 100644 index 00000000..affbb36e --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/base/nsIException.idl @@ -0,0 +1,101 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/* + * Interfaces for representing cross-language exceptions and stack traces. + */ + + +#include "nsISupports.idl" +#include "nsIProgrammingLanguage.idl" + +// XXX - most "string"s in this file should probably move to Unicode +// so may as well use AStrings... + + +[scriptable, uuid(91d82105-7c62-4f8b-9779-154277c0ee90)] +interface nsIStackFrame : nsISupports +{ + // see nsIProgrammingLanguage for list of language consts + readonly attribute PRUint32 language; + readonly attribute string languageName; + readonly attribute string filename; + readonly attribute string name; + // Valid line numbers begin at '1'. '0' indicates unknown. + readonly attribute PRInt32 lineNumber; + readonly attribute string sourceLine; + readonly attribute nsIStackFrame caller; + + string toString(); +}; + +[scriptable, uuid(F3A8D3B4-C424-4edc-8BF6-8974C983BA78)] +interface nsIException : nsISupports +{ + // A custom message set by the thrower. + readonly attribute string message; + // The nsresult associated with this exception. + readonly attribute nsresult result; + // The name of the error code (ie, a string repr of |result|) + readonly attribute string name; + + // Filename location. This is the location that caused the + // error, which may or may not be a source file location. + // For example, standard language errors would generally have + // the same location as their top stack entry. File + // parsers may put the location of the file they were parsing, + // etc. + + // null indicates "no data" + readonly attribute string filename; + // Valid line numbers begin at '1'. '0' indicates unknown. + readonly attribute PRUint32 lineNumber; + // Valid column numbers begin at 0. + // We don't have an unambiguous indicator for unknown. + readonly attribute PRUint32 columnNumber; + + // A stack trace, if available. + readonly attribute nsIStackFrame location; + // An inner exception that triggered this, if available. + readonly attribute nsIException inner; + + // Arbitary data for the implementation. + readonly attribute nsISupports data; + + // A generic formatter - make it suitable to print, etc. + string toString(); +}; diff --git a/src/libs/xpcom18a4/xpcom/base/nsIExceptionService.idl b/src/libs/xpcom18a4/xpcom/base/nsIExceptionService.idl new file mode 100644 index 00000000..22ebe751 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/base/nsIExceptionService.idl @@ -0,0 +1,97 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * ActiveState Tool Corp.. + * Portions created by the Initial Developer are Copyright (C) 2001 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Mark Hammond <MarkH@ActiveState.com> + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsISupports.idl" +#include "nsIException.idl" + +// An exception provider. These can turn special nsresult codes +// into nsIExceptions + +[scriptable, uuid(0577744c-c1d2-47f2-8bcc-ce7a9e5a88fc)] +interface nsIExceptionProvider : nsISupports +{ + /** Gets an nsIException or returns NULL if not possible. **/ + nsIException getException(in nsresult result, in nsIException defaultException); +}; + +// A ScriptErrorManager for a single thread. These objects +// are _not_ thread-safe. Use the ScriptErrorService +// to get a script error manager for your current thread. +[scriptable, uuid(efc9d00b-231c-4feb-852c-ac017266a415)] +interface nsIExceptionManager : nsISupports +{ + /** Sets (or clears with nsnull) the current error on the this thread. */ + void setCurrentException( in nsIException error); + + /** Gets the current error for the current thread, or NULL if no error */ + nsIException getCurrentException(); + + /** Gets an exception from a registered exception provider.. + This has no effect on the "current exception" */ + nsIException getExceptionFromProvider( in nsresult rc, in nsIException defaultException); +}; + + +// The Exception Service. Allows you to get an set exceptions in a thread +// safe manner, or to get an ExceptionManager for your specific thread. +[scriptable, uuid(35A88F54-F267-4414-92A7-191F6454AB52)] +interface nsIExceptionService : nsIExceptionManager +{ + /** Obtains an exception manager for the current thread. */ + readonly attribute nsIExceptionManager currentExceptionManager; + + /** Installs an "exception provider" which is capable of + translating an nsresult into an exception. This enables + error providers to return simple nsresults and only provide + rich errors when specifically requested. It also has the + advantage of allowing code like the DOM to handle all errors + in a single function rather than at each XPCOM entry point. + NOTE: This interface must be thread-safe - it will be called + on whatever thread needs the error translation performed.*/ + void registerExceptionProvider( in nsIExceptionProvider provider, in PRUint32 moduleCode ); + void unregisterExceptionProvider( in nsIExceptionProvider provider, in PRUint32 moduleCode ); +}; + + +%{ C++ +#define NS_EXCEPTIONSERVICE_CLASSNAME "Exception Service" +// {35A88F54-F267-4414-92A7-191F6454AB52} +#define NS_EXCEPTIONSERVICE_CID \ +{ 0x35a88f54, 0xf267, 0x4414, { 0x92, 0xa7, 0x19, 0x1f, 0x64, 0x54, 0xab, 0x52 } } +#define NS_EXCEPTIONSERVICE_CONTRACTID "@mozilla.org/exceptionservice;1" +%} diff --git a/src/libs/xpcom18a4/xpcom/base/nsIID.h b/src/libs/xpcom18a4/xpcom/base/nsIID.h new file mode 100644 index 00000000..f00d6b23 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/base/nsIID.h @@ -0,0 +1,41 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef __nsIID_h +#define __nsIID_h +#include "nsID.h" +#endif /* __nsIID_h */ diff --git a/src/libs/xpcom18a4/xpcom/base/nsIInterfaceRequestor.idl b/src/libs/xpcom18a4/xpcom/base/nsIInterfaceRequestor.idl new file mode 100644 index 00000000..31388643 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/base/nsIInterfaceRequestor.idl @@ -0,0 +1,72 @@ +/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Mozilla browser. + * + * The Initial Developer of the Original Code is + * Netscape Communications, Inc. + * Portions created by the Initial Developer are Copyright (C) 1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Travis Bogard <travis@netscape.com> + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsISupports.idl" + +/** + * The nsIInterfaceRequestor interface defines a generic interface for + * requesting interfaces that a given object might provide access to. + * This is very similar to QueryInterface found in nsISupports. + * The main difference is that interfaces returned from GetInterface() + * are not required to provide a way back to the object implementing this + * interface. The semantics of QI() dictate that given an interface A that + * you QI() on to get to interface B, you must be able to QI on B to get back + * to A. This interface however allows you to obtain an interface C from A + * that may or most likely will not have the ability to get back to A. + * + * @status FROZEN + */ + +[scriptable, uuid(033A1470-8B2A-11d3-AF88-00A024FFC08C)] +interface nsIInterfaceRequestor : nsISupports +{ + /** + * Retrieves the specified interface pointer. + * + * @param uuid The IID of the interface being requested. + * @param result [out] The interface pointer to be filled in if + * the interface is accessible. + * @return NS_OK - interface was successfully returned. + * NS_NOINTERFACE - interface not accessible. + * NS_ERROR* - method failure. + */ + void getInterface(in nsIIDRef uuid, + [iid_is(uuid),retval] out nsQIResult result); +}; + diff --git a/src/libs/xpcom18a4/xpcom/base/nsILeakDetector.idl b/src/libs/xpcom18a4/xpcom/base/nsILeakDetector.idl new file mode 100644 index 00000000..6d27fa70 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/base/nsILeakDetector.idl @@ -0,0 +1,54 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Mozilla browser. + * + * The Initial Developer of the Original Code is + * Netscape Communications, Inc. + * Portions created by the Initial Developer are Copyright (C) 1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Patrick C. Beard <beard@netscape.com> + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsISupports.idl" + +interface nsICollection; + +/** + * Controls the leak detector. + */ +[scriptable, uuid(a2ec052c-1dd1-11b2-9c92-84be252fe47e)] +interface nsILeakDetector : nsISupports { + void dumpLeaks(); + void traceObject(in nsISupports object, in PRBool verbose); + void traceCollection(in nsICollection objects, in PRBool verbose); + void markObject(in nsISupports object, in PRBool marked); + readonly attribute nsISupports services; +}; diff --git a/src/libs/xpcom18a4/xpcom/base/nsIMemory.idl b/src/libs/xpcom18a4/xpcom/base/nsIMemory.idl new file mode 100644 index 00000000..071aed06 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/base/nsIMemory.idl @@ -0,0 +1,126 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsISupports.idl" + +/** + * + * nsIMemory: interface to allocate and deallocate memory. Also provides + * for notifications in low-memory situations. + * + * A client that wishes to be notified of low memory situations (for + * example, because the client maintains a large memory cache that + * could be released when memory is tight) should register with the + * observer service (see nsIObserverService) using the topic + * "memory-pressure". There are three specific types of notications + * that can occur. These types will be passed as the |aData| + * parameter of the of the "memory-pressure" notification: + * + * "low-memory" + * This will be passed as the extra data when the pressure + * observer is being asked to flush for low-memory conditions. + * + * "heap-minimize" + * This will be passed as the extra data when the pressure + * observer is being asked to flush because of a heap minimize + * call. + * + * "alloc-failure" + * This will be passed as the extra data when the pressure + * observer has been asked to flush because a malloc() or + * realloc() has failed. + * + * @status FROZEN + */ + +[scriptable, uuid(59e7e77a-38e4-11d4-8cf5-0060b0fc14a3)] +interface nsIMemory : nsISupports +{ + /** + * Allocates a block of memory of a particular size. If the memory + * cannot be allocated (because of an out-of-memory condition), null + * is returned. + * + * @param size - the size of the block to allocate + * @result the block of memory + */ + [noscript, notxpcom] voidPtr alloc(in size_t size); + + /** + * Reallocates a block of memory to a new size. + * + * @param ptr - the block of memory to reallocate + * @param size - the new size + * @result the reallocated block of memory + * + * If ptr is null, this function behaves like malloc. + * If s is the size of the block to which ptr points, the first + * min(s, size) bytes of ptr's block are copied to the new block. + * If the allocation succeeds, ptr is freed and a pointer to the + * new block returned. If the allocation fails, ptr is not freed + * and null is returned. The returned value may be the same as ptr. + */ + [noscript, notxpcom] voidPtr realloc(in voidPtr ptr, + in size_t newSize); + + /** + * Frees a block of memory. Null is a permissible value, in which case + * nothing happens. + * + * @param ptr - the block of memory to free + */ + [noscript, notxpcom] void free(in voidPtr ptr); + + /** + * Attempts to shrink the heap. + * @param immediate - if true, heap minimization will occur + * immediately if the call was made on the main thread. If + * false, the flush will be scheduled to happen when the app is + * idle. + * @return NS_ERROR_FAILURE if 'immediate' is set an the call + * was not on the application's main thread. + */ + void heapMinimize(in boolean immediate); + + /** + * This predicate can be used to determine if we're in a low-memory + * situation (what constitutes low-memory is platform dependent). This + * can be used to trigger the memory pressure observers. + */ + boolean isLowMemory(); +}; + diff --git a/src/libs/xpcom18a4/xpcom/base/nsIProgrammingLanguage.idl b/src/libs/xpcom18a4/xpcom/base/nsIProgrammingLanguage.idl new file mode 100644 index 00000000..2fe6fb58 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/base/nsIProgrammingLanguage.idl @@ -0,0 +1,70 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * John Bandhauer <jband@netscape.com> + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsISupports.idl" + +%{C++ +#ifdef XP_OS2 // OS2 has UNKNOWN problems :) +#undef UNKNOWN +#endif +%} + +/** + * Enumeration of Programming Languages + * @status FROZEN + */ + +[scriptable, uuid(ea604e90-40ba-11d5-90bb-0010a4e73d9a)] +interface nsIProgrammingLanguage : nsISupports +{ + /** + * Identifiers for programming languages. + */ + const PRUint32 UNKNOWN = 0; + const PRUint32 CPLUSPLUS = 1; + const PRUint32 JAVASCRIPT = 2; + const PRUint32 PYTHON = 3; + const PRUint32 PERL = 4; + const PRUint32 JAVA = 5; + const PRUint32 ZX81_BASIC = 6; // it could happen :) + const PRUint32 JAVASCRIPT2 = 7; + // This list can grow indefinitely. Just don't ever change an existing item. + +}; diff --git a/src/libs/xpcom18a4/xpcom/base/nsISupports.idl b/src/libs/xpcom18a4/xpcom/base/nsISupports.idl new file mode 100644 index 00000000..6bf08ac4 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/base/nsISupports.idl @@ -0,0 +1,80 @@ +/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/** + * The mother of all xpcom interfaces. + * @status FROZEN + */ + +/* In order to get both the right typelib and the right header we force +* the 'real' output from xpidl to be commented out in the generated header +* and includes a copy of the original nsISupports.h. This is all just to deal +* with the Mac specific ": public __comobject" thing. +*/ + +#include "nsrootidl.idl" + +%{C++ +/* + * Start commenting out the C++ versions of the below in the output header + */ +#if 0 +%} + +[scriptable, uuid(00000000-0000-0000-c000-000000000046)] +interface nsISupports { + void QueryInterface(in nsIIDRef uuid, + [iid_is(uuid),retval] out nsQIResult result); + [noscript, notxpcom] nsrefcnt AddRef(); + [noscript, notxpcom] nsrefcnt Release(); +}; + +%{C++ +/* + * End commenting out the C++ versions of the above in the output header + */ +#endif +%} + + +%{C++ +#include "nsISupportsBase.h" + +#ifndef MOZILLA_STRICT_API +#include "nsISupportsUtils.h" +#endif +%} diff --git a/src/libs/xpcom18a4/xpcom/base/nsISupportsBase.h b/src/libs/xpcom18a4/xpcom/base/nsISupportsBase.h new file mode 100644 index 00000000..bea876f5 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/base/nsISupportsBase.h @@ -0,0 +1,119 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is XPCOM. + * + * The Initial Developer of the Original Code is Netscape Communications Corp. + * Portions created by the Initial Developer are Copyright (C) 2001 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef nsISupportsBase_h__ +#define nsISupportsBase_h__ + +#ifndef nscore_h___ +#include "nscore.h" +#endif + +#ifndef nsID_h__ +#include "nsID.h" +#endif + + +/*@{*/ +/** + * IID for the nsISupports interface + * {00000000-0000-0000-c000-000000000046} + * + * To maintain binary compatibility with COM's IUnknown, we define the IID + * of nsISupports to be the same as that of COM's IUnknown. + */ +#define NS_ISUPPORTS_IID \ + { 0x00000000, 0x0000, 0x0000, \ + {0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46} } + +/** + * Reference count values + * + * This is the return type for AddRef() and Release() in nsISupports. + * IUnknown of COM returns an unsigned long from equivalent functions. + * The following ifdef exists to maintain binary compatibility with + * IUnknown. + */ +#if defined(XP_WIN) && PR_BYTES_PER_LONG == 4 +typedef unsigned long nsrefcnt; +#else +typedef PRUint32 nsrefcnt; +#endif + +/** + * Basic component object model interface. Objects which implement + * this interface support runtime interface discovery (QueryInterface) + * and a reference counted memory model (AddRef/Release). This is + * modelled after the win32 IUnknown API. + */ +class NS_NO_VTABLE nsISupports { +public: + + /** + * @name Methods + */ + + //@{ + /** + * A run time mechanism for interface discovery. + * @param aIID [in] A requested interface IID + * @param aInstancePtr [out] A pointer to an interface pointer to + * receive the result. + * @return <b>NS_OK</b> if the interface is supported by the associated + * instance, <b>NS_NOINTERFACE</b> if it is not. + * <b>NS_ERROR_INVALID_POINTER</b> if <i>aInstancePtr</i> is <b>NULL</b>. + */ + NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) = 0; + /** + * Increases the reference count for this interface. + * The associated instance will not be deleted unless + * the reference count is returned to zero. + * + * @return The resulting reference count. + */ + NS_IMETHOD_(nsrefcnt) AddRef(void) = 0; + + /** + * Decreases the reference count for this interface. + * Generally, if the reference count returns to zero, + * the associated instance is deleted. + * + * @return The resulting reference count. + */ + NS_IMETHOD_(nsrefcnt) Release(void) = 0; + + //@} +}; +/*@}*/ +#endif diff --git a/src/libs/xpcom18a4/xpcom/base/nsISupportsObsolete.h b/src/libs/xpcom18a4/xpcom/base/nsISupportsObsolete.h new file mode 100644 index 00000000..874d859f --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/base/nsISupportsObsolete.h @@ -0,0 +1,243 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is XPCOM. + * + * The Initial Developer of the Original Code is Netscape Communications Corp. + * Portions created by the Initial Developer are Copyright (C) 2001 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + + +#ifndef nsISupportsObsolete_h__ +#define nsISupportsObsolete_h__ + +#include "prcmon.h" + +/////////////////////////////////////////////////////////////////////////////// + + +#define NS_INIT_REFCNT() NS_INIT_ISUPPORTS() + +/** + * Macro to free an array of pointers to nsISupports (or classes + * derived from it). A convenience wrapper around + * NS_FREE_XPCOM_POINTER_ARRAY. + * + * Note that if you know that none of your nsISupports pointers are + * going to be 0, you can gain a bit of speed by calling + * NS_FREE_XPCOM_POINTER_ARRAY directly and using NS_RELEASE as your + * free function. + * + * @param size Number of elements in the array. If not a constant, this + * should be a PRInt32. Note that this means this macro + * will not work if size >= 2^31. + * @param array The array to be freed. + */ +#define NS_FREE_XPCOM_ISUPPORTS_POINTER_ARRAY(size, array) \ + NS_FREE_XPCOM_POINTER_ARRAY((size), (array), NS_IF_RELEASE) + + +/////////////////////////////////////////////////////////////////////////////// + +/* use these functions to associate get/set methods with a + C++ member variable +*/ + +#define NS_METHOD_GETTER(_method, _type, _member) \ +_method(_type* aResult) \ +{\ + if (!aResult) return NS_ERROR_NULL_POINTER; \ + *aResult = _member; \ + return NS_OK; \ +} + +#define NS_METHOD_SETTER(_method, _type, _member) \ +_method(_type aResult) \ +{ \ + _member = aResult; \ + return NS_OK; \ +} + +/* + * special for strings to get/set char* strings + * using PL_strdup and PR_FREEIF + */ +#define NS_METHOD_GETTER_STR(_method,_member) \ +_method(char* *aString) \ +{ \ + if (!aString) return NS_ERROR_NULL_POINTER; \ + if (!(*aString = PL_strdup(_member))) \ + return NS_ERROR_OUT_OF_MEMORY; \ + return NS_OK; \ +} + +#define NS_METHOD_SETTER_STR(_method, _member) \ +_method(const char *aString) \ +{ \ + if (_member) PR_Free(_member); \ + if (!aString) \ + _member = nsnull; \ + else if (!(_member = PL_strdup(aString))) \ + return NS_ERROR_OUT_OF_MEMORY; \ + return NS_OK; \ +} + +/* Getter/Setter macros. + Usage: + NS_IMPL_[CLASS_]GETTER[_<type>](method, [type,] member); + NS_IMPL_[CLASS_]SETTER[_<type>](method, [type,] member); + NS_IMPL_[CLASS_]GETSET[_<type>]([class, ]postfix, [type,] member); + + where: + CLASS_ - implementation is inside a class definition + (otherwise the class name is needed) + Do NOT use in publicly exported header files, because + the implementation may be included many times over. + Instead, use the non-CLASS_ version. + _<type> - For more complex (STR, IFACE) data types + (otherwise the simple data type is needed) + method - name of the method, such as GetWidth or SetColor + type - simple data type if required + member - class member variable such as m_width or mColor + class - the class name, such as Window or MyObject + postfix - Method part after Get/Set such as "Width" for "GetWidth" + + Example: + class Window { + public: + NS_IMPL_CLASS_GETSET(Width, int, m_width); + NS_IMPL_CLASS_GETTER_STR(GetColor, m_color); + NS_IMETHOD SetColor(char *color); + + private: + int m_width; // read/write + char *m_color; // readonly + }; + + // defined outside of class + NS_IMPL_SETTER_STR(Window::GetColor, m_color); + + Questions/Comments to alecf@netscape.com +*/ + + +/* + * Getter/Setter implementation within a class definition + */ + +/* simple data types */ +#define NS_IMPL_CLASS_GETTER(_method, _type, _member) \ +NS_IMETHOD NS_METHOD_GETTER(_method, _type, _member) + +#define NS_IMPL_CLASS_SETTER(_method, _type, _member) \ +NS_IMETHOD NS_METHOD_SETTER(_method, _type, _member) + +#define NS_IMPL_CLASS_GETSET(_postfix, _type, _member) \ +NS_IMPL_CLASS_GETTER(Get##_postfix, _type, _member) \ +NS_IMPL_CLASS_SETTER(Set##_postfix, _type, _member) + +/* strings */ +#define NS_IMPL_CLASS_GETTER_STR(_method, _member) \ +NS_IMETHOD NS_METHOD_GETTER_STR(_method, _member) + +#define NS_IMPL_CLASS_SETTER_STR(_method, _member) \ +NS_IMETHOD NS_METHOD_SETTER_STR(_method, _member) + +#define NS_IMPL_CLASS_GETSET_STR(_postfix, _member) \ +NS_IMPL_CLASS_GETTER_STR(Get##_postfix, _member) \ +NS_IMPL_CLASS_SETTER_STR(Set##_postfix, _member) + +/* Getter/Setter implementation outside of a class definition */ + +/* simple data types */ +#define NS_IMPL_GETTER(_method, _type, _member) \ +NS_IMETHODIMP NS_METHOD_GETTER(_method, _type, _member) + +#define NS_IMPL_SETTER(_method, _type, _member) \ +NS_IMETHODIMP NS_METHOD_SETTER(_method, _type, _member) + +#define NS_IMPL_GETSET(_class, _postfix, _type, _member) \ +NS_IMPL_GETTER(_class::Get##_postfix, _type, _member) \ +NS_IMPL_SETTER(_class::Set##_postfix, _type, _member) + +/* strings */ +#define NS_IMPL_GETTER_STR(_method, _member) \ +NS_IMETHODIMP NS_METHOD_GETTER_STR(_method, _member) + +#define NS_IMPL_SETTER_STR(_method, _member) \ +NS_IMETHODIMP NS_METHOD_SETTER_STR(_method, _member) + +#define NS_IMPL_GETSET_STR(_class, _postfix, _member) \ +NS_IMPL_GETTER_STR(_class::Get##_postfix, _member) \ +NS_IMPL_SETTER_STR(_class::Set##_postfix, _member) + +/** + * IID for the nsIsThreadsafe interface + * {88210890-47a6-11d2-bec3-00805f8a66dc} + * + * This interface is *only* used for debugging purposes to determine if + * a given component is threadsafe. + */ +#define NS_ISTHREADSAFE_IID \ + { 0x88210890, 0x47a6, 0x11d2, \ + {0xbe, 0xc3, 0x00, 0x80, 0x5f, 0x8a, 0x66, 0xdc} } + +#define NS_LOCK_INSTANCE() \ + PR_CEnterMonitor((void*)this) +#define NS_UNLOCK_INSTANCE() \ + PR_CExitMonitor((void*)this) + +/** + * This implements query interface with two assumptions: First, the + * class in question implements nsISupports and its own interface and + * nothing else. Second, the implementation of the class's primary + * inheritance chain leads to its own interface. + * + * @param _class The name of the class implementing the method + * @param _classiiddef The name of the #define symbol that defines the IID + * for the class (e.g. NS_ISUPPORTS_IID) + */ +#if defined(NS_DEBUG) +#define NS_VERIFY_THREADSAFE_INTERFACE(_iface) \ + if (NULL != (_iface)) { \ + nsISupports* tmp; \ + static NS_DEFINE_IID(kIsThreadsafeIID, NS_ISTHREADSAFE_IID); \ + NS_PRECONDITION((NS_OK == _iface->QueryInterface(kIsThreadsafeIID, \ + (void**)&tmp)), \ + "Interface is not threadsafe"); \ + } +#else +#define NS_VERIFY_THREADSAFE_INTERFACE(_iface) +#endif + +//////////////////////////////////////////////////////////////////////////////// + + + +#endif diff --git a/src/libs/xpcom18a4/xpcom/base/nsISystemInfo.idl b/src/libs/xpcom18a4/xpcom/base/nsISystemInfo.idl new file mode 100644 index 00000000..0351196a --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/base/nsISystemInfo.idl @@ -0,0 +1,62 @@ +/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Mike Shaver <shaver@mozilla.org> + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsISupports.idl" + +/** + * System information service. + * + * At present, a thin wrapper around PR_GetSystemInfo. + */ + +[scriptable,uuid(4189b420-1dd2-11b2-bff7-daaf5c1f7b10)] +interface nsISystemInfo : nsISupports +{ + /** The system hostname. */ + readonly attribute string hostname; + + /** The operating system name. */ + readonly attribute string OSName; + + /** The operating system version. */ + readonly attribute string OSVersion; + + /** The processor architecture of the machine. */ + readonly attribute string architecture; +}; + diff --git a/src/libs/xpcom18a4/xpcom/base/nsITraceRefcnt.idl b/src/libs/xpcom18a4/xpcom/base/nsITraceRefcnt.idl new file mode 100644 index 00000000..536861a0 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/base/nsITraceRefcnt.idl @@ -0,0 +1,72 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is XPCOM + * + * The Initial Developer of the Original Code is Doug Turner <dougt@meer.net> + * + * Portions created by the Initial Developer are Copyright (C) 2003 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + + +#include "nsISupports.idl" + +/** + * nsITraceRefcnt is an interface between XPCOM Glue and XPCOM. Users should + * access the nsITraceRefcnt interface through the static class nsTraceRefcnt. + * @see nsTraceRefcnt.h + * + * @status UNDER_REVIEW + */ + +[uuid(273dc92f-0fe6-4545-96a9-21be77828039)] +interface nsITraceRefcnt : nsISupports +{ + void logAddRef(in voidPtr aPtr, + in nsrefcnt aNewRefcnt, + in string aTypeName, + in unsigned long aInstanceSize); + + void logRelease(in voidPtr aPtr, + in nsrefcnt aNewRefcnt, + in string aTypeName); + + void logCtor(in voidPtr aPtr, + in string aTypeName, + in unsigned long aInstanceSize); + + void logDtor(in voidPtr aPtr, + in string aTypeName, + in unsigned long aInstanceSize); + + + void logAddCOMPtr(in voidPtr aPtr, in nsISupports aObject); + + void logReleaseCOMPtr(in voidPtr aPtr, in nsISupports aObject); +}; diff --git a/src/libs/xpcom18a4/xpcom/base/nsIWeakReference.idl b/src/libs/xpcom18a4/xpcom/base/nsIWeakReference.idl new file mode 100644 index 00000000..2806fc8a --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/base/nsIWeakReference.idl @@ -0,0 +1,102 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Mozilla browser. + * + * The Initial Developer of the Original Code is + * Netscape Communications, Inc. + * Portions created by the Initial Developer are Copyright (C) 1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Pierre Phaneuf <pp@ludusdesign.com> + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsISupports.idl" + + +/** + * An instance of |nsIWeakReference| is a proxy object that cooperates with + * its referent to give clients a non-owning, non-dangling reference. Clients + * own the proxy, and should generally manage it with an |nsCOMPtr| (see the + * type |nsWeakPtr| for a |typedef| name that stands out) as they would any + * other XPCOM object. The |QueryReferent| member function provides a + * (hopefully short-lived) owning reference on demand, through which clients + * can get useful access to the referent, while it still exists. + * + * @status FROZEN + * @version 1.0 + * @see nsISupportsWeakReference + * @see nsWeakReference + * @see nsWeakPtr + */ +[scriptable, uuid(9188bc85-f92e-11d2-81ef-0060083a0bcf)] +interface nsIWeakReference : nsISupports + { + /** + * |QueryReferent| queries the referent, if it exists, and like |QueryInterface|, produces + * an owning reference to the desired interface. It is designed to look and act exactly + * like (a proxied) |QueryInterface|. Don't hold on to the produced interface permanently; + * that would defeat the purpose of using a non-owning |nsIWeakReference| in the first place. + */ + void QueryReferent( in nsIIDRef uuid, [iid_is(uuid), retval] out nsQIResult result ); + }; + + +/** + * |nsISupportsWeakReference| is a factory interface which produces appropriate + * instances of |nsIWeakReference|. Weak references in this scheme can only be + * produced for objects that implement this interface. + * + * @status FROZEN + * @version 1.0 + * @see nsIWeakReference + * @see nsSupportsWeakReference + */ +[scriptable, uuid(9188bc86-f92e-11d2-81ef-0060083a0bcf)] +interface nsISupportsWeakReference : nsISupports + { + /** + * |GetWeakReference| produces an appropriate instance of |nsIWeakReference|. + * As with all good XPCOM `getters', you own the resulting interface and should + * manage it with an |nsCOMPtr|. + * + * @see nsIWeakReference + * @see nsWeakPtr + * @see nsCOMPtr + */ + nsIWeakReference GetWeakReference(); + }; + + +%{C++ +#ifndef MOZILLA_STRICT_API +#include "nsIWeakReferenceUtils.h" +#endif +%} + diff --git a/src/libs/xpcom18a4/xpcom/base/nsLeakDetector.cpp b/src/libs/xpcom18a4/xpcom/base/nsLeakDetector.cpp new file mode 100644 index 00000000..a42f77bf --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/base/nsLeakDetector.cpp @@ -0,0 +1,248 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Mozilla browser. + * + * The Initial Developer of the Original Code is + * Netscape Communications, Inc. + * Portions created by the Initial Developer are Copyright (C) 1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Patrick C. Beard <beard@netscape.com> + * Scott Collins <scc@mozilla.org> + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#if defined(GC_LEAK_DETECTOR) + +#include "nsLeakDetector.h" +#include "nsCOMPtr.h" +#include "nsIComponentManager.h" +#include "nsIServiceManager.h" +#include "nsIGenericFactory.h" +#include "nsILeakDetector.h" +#include "nsICollection.h" + +#include <stdio.h> +#include <time.h> + +#include "gc.h" + +extern "C" { +extern FILE *GC_stdout, *GC_stderr; +extern void GC_trace_object(GC_PTR object, int verbose); +extern void GC_mark_object(GC_PTR object, GC_word mark); +} + +static nsresult nextLeakFile() +{ + if (GC_stderr != NULL) + fclose(GC_stderr); + + // generate a time stamped report name. + time_t timer; + time(&timer); + tm* now = localtime(&timer); + + char reportName[256]; + sprintf(reportName, "Leaks%02d%02d%02d", + now->tm_hour, now->tm_min, now->tm_sec); + GC_stderr = fopen(reportName, "w"); + + return NS_OK; +} + +static FILE* openTraceFile() +{ + // generate a time stamped report name. + time_t timer; + time(&timer); + tm* now = localtime(&timer); + + char reportName[256]; + sprintf(reportName, "Trace%02d%02d%02d", + now->tm_hour, now->tm_min, now->tm_sec); + return fopen(reportName, "w"); +} + +class nsLeakDetector : public nsILeakDetector { +public: + nsLeakDetector(); + + NS_DECL_ISUPPORTS + NS_DECL_NSILEAKDETECTOR +private: + ~nsLeakDetector() {} +}; + +NS_IMPL_ISUPPORTS1(nsLeakDetector, nsILeakDetector) + +nsLeakDetector::nsLeakDetector() { + } + +NS_METHOD nsLeakDetector::DumpLeaks() +{ + GC_gcollect(); + + return nextLeakFile(); +} + +NS_METHOD nsLeakDetector::TraceObject(nsISupports* object, PRBool verbose) +{ + FILE* trace = openTraceFile(); + if (trace != NULL) { + FILE* old_stderr = GC_stderr; + GC_stderr = trace; + GC_trace_object(object, (verbose ? 1 : 0)); + GC_stderr = old_stderr; + fclose(trace); + return NS_OK; + } + return NS_ERROR_FAILURE; +} + +NS_METHOD nsLeakDetector::TraceCollection(nsICollection* objects, PRBool verbose) +{ + PRUint32 count; + if (NS_FAILED(objects->Count(&count))) + return NS_ERROR_FAILURE; + + nsCOMPtr<nsISupports>* elements = new nsCOMPtr<nsISupports>[count]; + if (elements == nsnull) + return NS_ERROR_OUT_OF_MEMORY; + + for (PRUint32 i = 0; i < count; ++i) + objects->GetElementAt(i, getter_AddRefs(elements[i])); + + nsresult rv = NS_ERROR_FAILURE; + FILE* trace = openTraceFile(); + if (trace != NULL) { + FILE* old_stderr = GC_stderr; + GC_stderr = trace; + GC_trace_object(elements, (verbose ? 1 : 0)); + GC_stderr = old_stderr; + fclose(trace); + rv = NS_OK; + } + + delete[] elements; + + return rv; +} + +NS_METHOD nsLeakDetector::MarkObject(nsISupports* object, PRBool marked) +{ + GC_mark_object(object, (marked ? 1 : 0)); + return NS_OK; +} + +NS_METHOD nsLeakDetector::GetServices(nsISupports* *result) +{ + return NS_GetServiceManager((nsIServiceManager**)result); +} + +#define NS_CLEAKDETECTOR_CID_STR "bb1ba360-1dd1-11b2-b30e-aa2314429f54" +#define NS_CLEAKDETECTOR_CID {0xbb1ba360, 0x1dd1, 0x11b2, {0xb3, 0x0e, 0xaa, 0x23, 0x14, 0x42, 0x9f, 0x54}} +#define NS_CLEAKDETECTOR_CONTRACTID "@mozilla.org/xpcom/leakdetector;1" + +NS_GENERIC_FACTORY_CONSTRUCTOR(nsLeakDetector) + +static NS_DEFINE_CID(kCLeakDetectorCID, NS_CLEAKDETECTOR_CID); + +nsresult NS_InitLeakDetector() +{ + nsresult rv; + + // open the first leak file. + rv = nextLeakFile(); + if (NS_FAILED(rv)) + return rv; + + static const nsModuleComponentInfo info = { + "Leak Detector", kCLeakDetectorCID, NS_CLEAKDETECTOR_CONTRACTID, nsLeakDetectorConstructor + }; + + // create a generic factory for the leak detector. + nsCOMPtr<nsIGenericFactory> factory; + rv = NS_NewGenericFactory(getter_AddRefs(factory), &info); + if (NS_FAILED(rv)) + return rv; + + // register this factory with the component manager. + return nsComponentManager::RegisterFactory(info.mCID, info.mDescription, info.mContractID, factory, PR_TRUE); +} + +#ifdef XP_MAC +#define SHUTDOWN_LEAKS_EARLY +#undef SHUTDOWN_LEAKS_MEDIUM +#undef SHUTDOWN_LEAKS_LATE +#else +#undef SHUTDOWN_LEAKS_EARLY +#undef SHUTDOWN_LEAKS_MEDIUM +#define SHUTDOWN_LEAKS_LATE +#endif + +class LeakDetectorFinalizer +{ +public: + ~LeakDetectorFinalizer(); +}; + +#ifdef SHUTDOWN_LEAKS_LATE +// do shutdown leaks when XPCOM library is unloaded +LeakDetectorFinalizer gLeakDetectorFinalizer; +#endif + +LeakDetectorFinalizer::~LeakDetectorFinalizer() +{ + GC_gcollect(); + +#if 0 + nextLeakFile(); + if (GC_stdout != NULL) { + fprintf(GC_stdout, "ShutDown Leaks\n"); + GC_clear_roots(); + GC_gcollect(); + } +#endif +} + +nsresult NS_ShutdownLeakDetector() +{ +#if defined(SHUTDOWN_LEAKS_MEDIUM) + // Make this the first atexit() called so it's before the atexit() crashes + // see http://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=23552 + static LeakDetectorFinalizer trick; +#elif defined(SHUTDOWN_LEAKS_EARLY) + // do shutdown leaks now + LeakDetectorFinalizer trick; +#endif + return NS_OK; +} + +#endif /* defined(GC_LEAK_DETECTOR) */ diff --git a/src/libs/xpcom18a4/xpcom/base/nsLeakDetector.h b/src/libs/xpcom18a4/xpcom/base/nsLeakDetector.h new file mode 100644 index 00000000..5c560401 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/base/nsLeakDetector.h @@ -0,0 +1,60 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Mozilla browser. + * + * The Initial Developer of the Original Code is + * Netscape Communications, Inc. + * Portions created by the Initial Developer are Copyright (C) 1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Patrick C. Beard <beard@netscape.com> + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef nsLeakDetector_h +#define nsLeakDetector_h + +#ifndef nsError_h +#include "nsError.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +nsresult NS_InitGarbageCollector(void); +nsresult NS_InitLeakDetector(void); +nsresult NS_ShutdownLeakDetector(void); +nsresult NS_ShutdownGarbageCollector(void); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* nsLeakDetector_h */ diff --git a/src/libs/xpcom18a4/xpcom/base/nsMemoryImpl.cpp b/src/libs/xpcom18a4/xpcom/base/nsMemoryImpl.cpp new file mode 100644 index 00000000..8aa16e58 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/base/nsMemoryImpl.cpp @@ -0,0 +1,548 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsMemoryImpl.h" +#include "prmem.h" +#include "nsAlgorithm.h" +#include "nsIServiceManager.h" +#include "nsIObserverService.h" +#include "nsAutoLock.h" +#include "nsIThread.h" +#include "nsIEventQueueService.h" +#include "nsString.h" + +#if defined(XP_WIN) +#include <windows.h> +#define NS_MEMORY_FLUSHER_THREAD +#elif defined(XP_MAC) +#include <MacMemory.h> +#define NS_MEMORY_FLUSHER_THREAD +#else +// Need to implement the nsIMemory::IsLowMemory() predicate +#undef NS_MEMORY_FLUSHER_THREAD +#endif + +//---------------------------------------------------------------------- + +#if defined(XDEBUG_waterson) +#define NS_TEST_MEMORY_FLUSHER +#endif + +/** + * A runnable that is used to periodically check the status + * of the system, determine if too much memory is in use, + * and if so, trigger a "memory flush". + */ +class MemoryFlusher : public nsIRunnable +{ +protected: + nsMemoryImpl* mMemoryImpl; // WEAK, it owns us. + PRBool mRunning; + PRIntervalTime mTimeout; + PRLock* mLock; + PRCondVar* mCVar; + + MemoryFlusher(nsMemoryImpl* aMemoryImpl); + + enum { + kInitialTimeout = 60 /*seconds*/ + }; + +private: + ~MemoryFlusher(); + +public: + /** + * Create a memory flusher. + * @param aResult the memory flusher + * @param aMemoryImpl the owning nsMemoryImpl object + * @return NS_OK if the memory flusher was created successfully + */ + static nsresult + Create(MemoryFlusher** aResult, nsMemoryImpl* aMemoryImpl); + + NS_DECL_ISUPPORTS + NS_DECL_NSIRUNNABLE + + /** + * Stop the memory flusher. + */ + nsresult Stop(); +}; + + +MemoryFlusher::MemoryFlusher(nsMemoryImpl* aMemoryImpl) + : mMemoryImpl(aMemoryImpl), + mRunning(PR_FALSE), + mTimeout(PR_SecondsToInterval(kInitialTimeout)), + mLock(nsnull), + mCVar(nsnull) +{ +} + +MemoryFlusher::~MemoryFlusher() +{ + if (mLock) + PR_DestroyLock(mLock); + + if (mCVar) + PR_DestroyCondVar(mCVar); +} + + +nsresult +MemoryFlusher::Create(MemoryFlusher** aResult, nsMemoryImpl* aMemoryImpl) +{ + MemoryFlusher* result = new MemoryFlusher(aMemoryImpl); + if (! result) + return NS_ERROR_OUT_OF_MEMORY; + + do { + if ((result->mLock = PR_NewLock()) == nsnull) + break; + + if ((result->mCVar = PR_NewCondVar(result->mLock)) == nsnull) + break; + + NS_ADDREF(*aResult = result); + return NS_OK; + } while (0); + + // Something bad happened if we get here... + delete result; + return NS_ERROR_OUT_OF_MEMORY; +} + +NS_IMPL_THREADSAFE_ISUPPORTS1(MemoryFlusher, nsIRunnable) + +NS_IMETHODIMP +MemoryFlusher::Run() +{ + nsresult rv; + + mRunning = PR_TRUE; + + while (1) { + PRStatus status; + + { + nsAutoLock l(mLock); + if (! mRunning) { + rv = NS_OK; + break; + } + + status = PR_WaitCondVar(mCVar, mTimeout); + } + + if (status != PR_SUCCESS) { + rv = NS_ERROR_FAILURE; + break; + } + + if (! mRunning) { + rv = NS_OK; + break; + } + + PRBool isLowMemory; + rv = mMemoryImpl->IsLowMemory(&isLowMemory); + if (NS_FAILED(rv)) + break; + +#ifdef NS_TEST_MEMORY_FLUSHER + // Fire the flusher *every* time + isLowMemory = PR_TRUE; +#endif + + if (isLowMemory) { + mMemoryImpl->FlushMemory(NS_LITERAL_STRING("low-memory").get(), PR_FALSE); + } + } + + mRunning = PR_FALSE; + + return rv; +} + + +nsresult +MemoryFlusher::Stop() +{ + if (mRunning) { + nsAutoLock l(mLock); + mRunning = PR_FALSE; + PR_NotifyCondVar(mCVar); + } + + return NS_OK; +} + +//---------------------------------------------------------------------- + +nsMemoryImpl* gMemory = nsnull; + +NS_IMPL_THREADSAFE_ISUPPORTS1(nsMemoryImpl, nsIMemory) + +NS_METHOD +nsMemoryImpl::Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr) +{ + NS_ENSURE_ARG_POINTER(aInstancePtr); + NS_ENSURE_PROPER_AGGREGATION(outer, aIID); + if (gMemory && NS_SUCCEEDED(gMemory->QueryInterface(aIID, aInstancePtr))) + return NS_OK; + + nsMemoryImpl* mm = new nsMemoryImpl(); + if (mm == NULL) + return NS_ERROR_OUT_OF_MEMORY; + + nsresult rv; + + do { + rv = mm->QueryInterface(aIID, aInstancePtr); + if (NS_FAILED(rv)) + break; + + rv = NS_ERROR_OUT_OF_MEMORY; + + mm->mFlushLock = PR_NewLock(); + if (! mm->mFlushLock) + break; + + rv = NS_OK; + } while (0); + + if (NS_FAILED(rv)) + delete mm; + + return rv; +} + + +nsMemoryImpl::nsMemoryImpl() + : mFlusher(nsnull), + mFlushLock(nsnull), + mIsFlushing(PR_FALSE) +{ +} + +nsMemoryImpl::~nsMemoryImpl() +{ + if (mFlushLock) + PR_DestroyLock(mFlushLock); +} + +//////////////////////////////////////////////////////////////////////////////// +// Define NS_OUT_OF_MEMORY_TESTER if you want to force memory failures + +#ifdef DEBUG_xwarren +#define NS_OUT_OF_MEMORY_TESTER +#endif + +#ifdef NS_OUT_OF_MEMORY_TESTER + +// flush memory one in this number of times: +#define NS_FLUSH_FREQUENCY 100000 + +// fail allocation one in this number of flushes: +#define NS_FAIL_FREQUENCY 10 + +PRUint32 gFlushFreq = 0; +PRUint32 gFailFreq = 0; + +static void* +mallocator(PRSize size, PRUint32& counter, PRUint32 max) +{ + if (counter++ >= max) { + counter = 0; + NS_ASSERTION(0, "about to fail allocation... watch out"); + return nsnull; + } + return PR_Malloc(size); +} + +static void* +reallocator(void* ptr, PRSize size, PRUint32& counter, PRUint32 max) +{ + if (counter++ >= max) { + counter = 0; + NS_ASSERTION(0, "about to fail reallocation... watch out"); + return nsnull; + } + return PR_Realloc(ptr, size); +} + +#define MALLOC1(s) mallocator(s, gFlushFreq, NS_FLUSH_FREQUENCY) +#define REALLOC1(p, s) reallocator(p, s, gFlushFreq, NS_FLUSH_FREQUENCY) + +#else + +#define MALLOC1(s) PR_Malloc(s) +#define REALLOC1(p, s) PR_Realloc(p, s) + +#endif // NS_OUT_OF_MEMORY_TESTER + +//////////////////////////////////////////////////////////////////////////////// + +NS_IMETHODIMP_(void *) +nsMemoryImpl::Alloc(PRSize size) +{ + NS_ASSERTION(size, "nsMemoryImpl::Alloc of 0"); + void* result = MALLOC1(size); + if (! result) { + // Request an asynchronous flush + FlushMemory(NS_LITERAL_STRING("alloc-failure").get(), PR_FALSE); + } + return result; +} + +NS_IMETHODIMP_(void *) +nsMemoryImpl::Realloc(void * ptr, PRSize size) +{ + void* result = REALLOC1(ptr, size); + if (! result) { + // Request an asynchronous flush + FlushMemory(NS_LITERAL_STRING("alloc-failure").get(), PR_FALSE); + } + return result; +} + +NS_IMETHODIMP_(void) +nsMemoryImpl::Free(void * ptr) +{ + PR_Free(ptr); +} + +NS_IMETHODIMP +nsMemoryImpl::HeapMinimize(PRBool aImmediate) +{ + return FlushMemory(NS_LITERAL_STRING("heap-minimize").get(), aImmediate); +} + +NS_IMETHODIMP +nsMemoryImpl::IsLowMemory(PRBool *result) +{ +#if defined(XP_WIN) + MEMORYSTATUS stat; + GlobalMemoryStatus(&stat); + *result = ((float)stat.dwAvailPageFile / stat.dwTotalPageFile) < 0.1; +#elif defined(XP_MAC) + + const long kReserveHeapFreeSpace = (256 * 1024); + const long kReserveHeapContigSpace = (128 * 1024); + + long totalSpace, contiguousSpace; + // this call measures how much memory would be available if the OS + // purged. Despite the name, it does not purge (that happens + // automatically when heap space is low). + ::PurgeSpace(&totalSpace, &contiguousSpace); + if (totalSpace < kReserveHeapFreeSpace || contiguousSpace < kReserveHeapContigSpace) + { + NS_WARNING("Found that heap mem is low"); + *result = PR_TRUE; + return NS_OK; + } + + // see how much temp mem is available (since our allocators allocate 1Mb chunks + // in temp mem. We don't use TempMaxMem() (to get contig space) here, because it + // compacts the application heap, so can be slow. + const long kReserveTempFreeSpace = (2 * 1024 * 1024); // 2Mb + long totalTempSpace = ::TempFreeMem(); + if (totalTempSpace < kReserveTempFreeSpace) + { + NS_WARNING("Found that temp mem is low"); + *result = PR_TRUE; + return NS_OK; + } + + *result = PR_FALSE; + +#else + *result = PR_FALSE; +#endif + return NS_OK; +} + +nsresult +nsMemoryImpl::FlushMemory(const PRUnichar* aReason, PRBool aImmediate) +{ + nsresult rv; + + if (aImmediate) { + // They've asked us to run the flusher *immediately*. We've + // got to be on the UI main thread for us to be able to do + // that...are we? + PRBool isOnUIThread = PR_FALSE; + + nsCOMPtr<nsIThread> main; + rv = nsIThread::GetMainThread(getter_AddRefs(main)); + if (NS_SUCCEEDED(rv)) { + nsCOMPtr<nsIThread> current; + rv = nsIThread::GetCurrent(getter_AddRefs(current)); + if (NS_SUCCEEDED(rv)) { + if (current == main) + isOnUIThread = PR_TRUE; + } + } + + if (! isOnUIThread) { + NS_ERROR("can't synchronously flush memory: not on UI thread"); + return NS_ERROR_FAILURE; + } + } + + { + // Are we already flushing? + nsAutoLock l(mFlushLock); + if (mIsFlushing) + return NS_OK; + + // Well, we are now! + mIsFlushing = PR_TRUE; + } + + // Run the flushers immediately if we can; otherwise, proxy to the + // UI thread an run 'em asynchronously. + if (aImmediate) { + rv = RunFlushers(this, aReason); + } + else { + nsCOMPtr<nsIEventQueueService> eqs = do_GetService(NS_EVENTQUEUESERVICE_CONTRACTID, &rv); + if (eqs) { + nsCOMPtr<nsIEventQueue> eq; + rv = eqs->GetThreadEventQueue(NS_UI_THREAD, getter_AddRefs(eq)); + if (NS_SUCCEEDED(rv)) { + PL_InitEvent(&mFlushEvent.mEvent, this, HandleFlushEvent, DestroyFlushEvent); + mFlushEvent.mReason = aReason; + + rv = eq->PostEvent(NS_REINTERPRET_CAST(PLEvent*, &mFlushEvent)); + } + } + } + + return rv; +} + +nsresult +nsMemoryImpl::RunFlushers(nsMemoryImpl* aSelf, const PRUnichar* aReason) +{ + nsCOMPtr<nsIObserverService> os = do_GetService("@mozilla.org/observer-service;1"); + if (os) { + os->NotifyObservers(aSelf, "memory-pressure", aReason); + } + + { + // Done flushing + nsAutoLock l(aSelf->mFlushLock); + aSelf->mIsFlushing = PR_FALSE; + } + + return NS_OK; +} + +void* +nsMemoryImpl::HandleFlushEvent(PLEvent* aEvent) +{ + nsMemoryImpl* self = NS_STATIC_CAST(nsMemoryImpl*, PL_GetEventOwner(aEvent)); + FlushEvent* event = NS_REINTERPRET_CAST(FlushEvent*, aEvent); + + RunFlushers(self, event->mReason); + return 0; +} + +void +nsMemoryImpl::DestroyFlushEvent(PLEvent* aEvent) +{ + // no-op, since mEvent is a member of nsMemoryImpl +} + +static void +EnsureGlobalMemoryService() +{ + if (gMemory) return; + nsresult rv = nsMemoryImpl::Create(nsnull, NS_GET_IID(nsIMemory), (void**)&gMemory); + NS_ASSERTION(NS_SUCCEEDED(rv), "nsMemoryImpl::Create failed"); + NS_ASSERTION(gMemory, "improper xpcom initialization"); +} + +nsresult +nsMemoryImpl::Startup() +{ + EnsureGlobalMemoryService(); + if (! gMemory) + return NS_ERROR_FAILURE; + +#ifdef NS_MEMORY_FLUSHER_THREAD + nsresult rv; + + // Create and start a memory flusher thread + rv = MemoryFlusher::Create(&gMemory->mFlusher, gMemory); + if (NS_FAILED(rv)) return rv; + + rv = NS_NewThread(getter_AddRefs(gMemory->mFlusherThread), + gMemory->mFlusher, + 0, /* XXX use default stack size? */ + PR_JOINABLE_THREAD); + + if (NS_FAILED(rv)) return rv; +#endif + + return NS_OK; +} + +nsresult +nsMemoryImpl::Shutdown() +{ + if (gMemory) { +#ifdef NS_MEMORY_FLUSHER_THREAD + if (gMemory->mFlusher) { + // Stop the runnable... + gMemory->mFlusher->Stop(); + NS_RELEASE(gMemory->mFlusher); + + // ...and wait for the thread to exit + if (gMemory->mFlusherThread) + gMemory->mFlusherThread->Join(); + } +#endif + + NS_RELEASE(gMemory); + gMemory = nsnull; + } + + return NS_OK; +} diff --git a/src/libs/xpcom18a4/xpcom/base/nsMemoryImpl.h b/src/libs/xpcom18a4/xpcom/base/nsMemoryImpl.h new file mode 100644 index 00000000..c9086d11 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/base/nsMemoryImpl.h @@ -0,0 +1,91 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef nsMemoryImpl_h__ +#define nsMemoryImpl_h__ + +#include "nsMemory.h" +#include "nsISupportsArray.h" +#include "nsIRunnable.h" +#include "nsIThread.h" +#include "nsCOMPtr.h" +#include "plevent.h" + +struct PRLock; +class MemoryFlusher; + +class nsMemoryImpl : public nsIMemory +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSIMEMORY + + nsMemoryImpl(); + + nsresult FlushMemory(const PRUnichar* aReason, PRBool aImmediate); + + // called from xpcom initialization/finalization: + static nsresult Startup(); + static nsresult Shutdown(); + + static NS_METHOD + Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr); + +private: + ~nsMemoryImpl(); + +protected: + MemoryFlusher* mFlusher; + nsCOMPtr<nsIThread> mFlusherThread; + + PRLock* mFlushLock; + PRBool mIsFlushing; + + struct FlushEvent { + PLEvent mEvent; + const PRUnichar* mReason; + }; + + FlushEvent mFlushEvent; + + static nsresult RunFlushers(nsMemoryImpl* aSelf, const PRUnichar* aReason); + + static void* PR_CALLBACK HandleFlushEvent(PLEvent* aEvent); + static void PR_CALLBACK DestroyFlushEvent(PLEvent* aEvent); +}; + +#endif // nsMemoryImpl_h__ diff --git a/src/libs/xpcom18a4/xpcom/base/nsStackFrameUnix.cpp b/src/libs/xpcom18a4/xpcom/base/nsStackFrameUnix.cpp new file mode 100644 index 00000000..11fe0fca --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/base/nsStackFrameUnix.cpp @@ -0,0 +1,375 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is nsStackFrameWin.h code, released + * December 20, 2000. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 2003 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsStackFrameUnix.h" +#include <stdlib.h> +#include <string.h> +#include <math.h> +#include "nscore.h" + +// On glibc 2.1, the Dl_info api defined in <dlfcn.h> is only exposed +// if __USE_GNU is defined. I suppose its some kind of standards +// adherence thing. +// +#if (__GLIBC_MINOR__ >= 1) && !defined(__USE_GNU) +#define __USE_GNU +#endif + +#ifdef HAVE_LIBDL +#include <dlfcn.h> +#endif + + + +// This thing is exported by libstdc++ +// Yes, this is a gcc only hack +#if defined(MOZ_DEMANGLE_SYMBOLS) +#include <cxxabi.h> +#include <stdlib.h> // for free() +#endif // MOZ_DEMANGLE_SYMBOLS + +void DemangleSymbol(const char * aSymbol, + char * aBuffer, + int aBufLen) +{ + aBuffer[0] = '\0'; + +#if defined(MOZ_DEMANGLE_SYMBOLS) + /* See demangle.h in the gcc source for the voodoo */ + char * demangled = abi::__cxa_demangle(aSymbol,0,0,0); + + if (demangled) + { + strncpy(aBuffer,demangled,aBufLen); + free(demangled); + } +#endif // MOZ_DEMANGLE_SYMBOLS +} + + +#if defined(linux) && !defined(VBOX) && defined(__GLIBC__) && (defined(__i386) || defined(PPC)) // i386 or PPC Linux stackwalking code + +#include <setjmp.h> +// + +void DumpStackToFile(FILE* aStream) +{ + jmp_buf jb; + setjmp(jb); + + // Stack walking code courtesy Kipp's "leaky". + + // Get the frame pointer out of the jmp_buf + void **bp = (void**) +#if defined(__i386) + (jb[0].__jmpbuf[JB_BP]); +#elif defined(PPC) + (jb[0].__jmpbuf[JB_GPR1]); +#endif + + int skip = 2; + for ( ; (void**)*bp > bp; bp = (void**)*bp) { + void *pc = *(bp+1); + if (--skip <= 0) { + Dl_info info; + int ok = dladdr(pc, &info); + if (!ok) { + fprintf(aStream, "UNKNOWN %p\n", pc); + continue; + } + + PRUint32 foff = (char*)pc - (char*)info.dli_fbase; + + const char * symbol = info.dli_sname; + int len; + if (!symbol || !(len = strlen(symbol))) { + fprintf(aStream, "UNKNOWN [%s +0x%08X]\n", + info.dli_fname, foff); + continue; + } + + char demangled[4096] = "\0"; + + DemangleSymbol(symbol, demangled, sizeof(demangled)); + + if (strlen(demangled)) { + symbol = demangled; + len = strlen(symbol); + } + + PRUint32 off = (char*)pc - (char*)info.dli_saddr; + fprintf(aStream, "%s+0x%08X [%s +0x%08X]\n", + symbol, off, info.dli_fname, foff); + } + } +} + +#elif defined(__sun) && (defined(__sparc) || defined(sparc) || defined(__i386) || defined(i386)) + +/* + * Stack walking code for Solaris courtesy of Bart Smaalder's "memtrak". + */ + +#include <synch.h> +#include <ucontext.h> +#include <sys/frame.h> +#include <sys/regset.h> +#include <sys/stack.h> + +static int load_address ( void * pc, void * arg, FILE * aStream ); +static int write_address_file ( void * pc ); +static struct bucket * newbucket ( void * pc ); +static struct frame * cs_getmyframeptr ( void ); +static void cs_walk_stack ( void * (*read_func)(char * address), + struct frame * fp, + int (*operate_func)(void *, void *), + void * usrarg, FILE * aStream ); +static void cs_operate ( void (*operate_func)(void *, void *), + void * usrarg, FILE * aStream ); + +#ifndef STACK_BIAS +#define STACK_BIAS 0 +#endif /*STACK_BIAS*/ + +#define LOGSIZE 4096 + +/* type of demangling function */ +typedef int demf_t(const char *, char *, size_t); + +static demf_t *demf; + +static int initialized = 0; + +#if defined(sparc) || defined(__sparc) +#define FRAME_PTR_REGISTER REG_SP +#endif + +#if defined(i386) || defined(__i386) +#define FRAME_PTR_REGISTER EBP +#endif + +struct bucket { + void * pc; + int index; + struct bucket * next; +}; + +struct mybuf { + char * buffer; + int chars_left; +}; + + +static void myinit(); + +#pragma init (myinit) + +static void +myinit() +{ + + if (! initialized) { +#ifndef __GNUC__ + void *handle; + const char *libdem = "libdemangle.so.1"; + + /* load libdemangle if we can and need to (only try this once) */ + if ((handle = dlopen(libdem, RTLD_LAZY)) != NULL) { + demf = (demf_t *)dlsym(handle, + "cplus_demangle"); /*lint !e611 */ + /* + * lint override above is to prevent lint from + * complaining about "suspicious cast". + */ + } +#endif /*__GNUC__*/ + } + initialized = 1; +} + + +static int +write_address_file(void * pc, FILE* aStream) +{ + static struct bucket table[2048]; + static mutex_t lock; + struct bucket * ptr; + + unsigned int val = NS_PTR_TO_INT32(pc); + + ptr = table + ((val >> 2)&2047); + + mutex_lock(&lock); + while (ptr->next) { + if (ptr->next->pc == pc) + break; + ptr = ptr->next; + } + + if (ptr->next) { + mutex_unlock(&lock); + return (ptr->next->index); + } else { + char buffer[4096], dembuff[4096]; + Dl_info info; + const char *func = "??", *lib = "??"; + + ptr->next = newbucket(pc); + mutex_unlock(&lock); + + if (dladdr(pc, & info)) { + if (info.dli_fname) + lib = info.dli_fname; + if (info.dli_sname) + func = info.dli_sname; + } + +#ifdef __GNUC__ + DemangleSymbol(func, dembuff, sizeof(dembuff)); +#else + if (!demf || demf(func, dembuff, sizeof (dembuff))) + dembuff[0] = 0; +#endif /*__GNUC__*/ + if (strlen(dembuff)) { + func = dembuff; + } + fprintf(aStream, "%u %s:%s+0x%x\n", + ptr->next->index, + lib, + func, + (char *)pc - (char*)info.dli_saddr); + + return (ptr->next->index); + } +} + + +static int +load_address(void * pc, void * arg, FILE * aStream) +{ + struct mybuf * buf = (struct mybuf *) arg; + + char name[80]; + int len; + + sprintf(name, " %u", write_address_file(pc, aStream)); + + len = strlen(name); + + if (len >= buf->chars_left) + return (1); + + strcat(buf->buffer, name); + + buf->chars_left -= len; + + return (0); +} + + +static struct bucket * +newbucket(void * pc) +{ + struct bucket * ptr = (struct bucket *) malloc(sizeof (*ptr)); + static int index; /* protected by lock in caller */ + + ptr->index = index++; + ptr->next = NULL; + ptr->pc = pc; + return (ptr); +} + + +static struct frame * +csgetframeptr() +{ + ucontext_t u; + struct frame *fp; + + (void) getcontext(&u); + + fp = (struct frame *) + ((char *)u.uc_mcontext.gregs[FRAME_PTR_REGISTER] + + STACK_BIAS); + + /* make sure to return parents frame pointer.... */ + + return ((struct frame *)((ulong_t)fp->fr_savfp + STACK_BIAS)); +} + + +static void +cswalkstack(struct frame *fp, int (*operate_func)(void *, void *, FILE *), + void *usrarg, FILE * aStream) +{ + + while (fp != 0 && fp->fr_savpc != 0) { + + if (operate_func((void *)fp->fr_savpc, usrarg, aStream) != 0) + break; + /* + * watch out - libthread stacks look funny at the top + * so they may not have their STACK_BIAS set + */ + + fp = (struct frame *)((ulong_t)fp->fr_savfp + + (fp->fr_savfp?(ulong_t)STACK_BIAS:0)); + } +} + + +static void +cs_operate(int (*operate_func)(void *, void *, FILE *), void * usrarg, FILE *aStream) +{ + cswalkstack(csgetframeptr(), operate_func, usrarg, aStream); +} + +void DumpStackToFile(FILE* aStream) +{ + char buffer[LOGSIZE]; + struct mybuf mybuf; + + if (!initialized) + myinit(); + + mybuf.chars_left = LOGSIZE - strlen(buffer)-1; + mybuf.buffer = buffer; + cs_operate(load_address, &mybuf, aStream); +} +#endif diff --git a/src/libs/xpcom18a4/xpcom/base/nsStackFrameUnix.h b/src/libs/xpcom18a4/xpcom/base/nsStackFrameUnix.h new file mode 100644 index 00000000..1673ae76 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/base/nsStackFrameUnix.h @@ -0,0 +1,46 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is nsStackFrameWin.h code, released + * December 20, 2000. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 2003 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +#ifndef nsStackFrameUnix_h___ +#define nsStackFrameUnix_h___ + +#include "stdio.h" + +void DumpStackToFile(FILE* out); + +#endif diff --git a/src/libs/xpcom18a4/xpcom/base/nsStackFrameWin.cpp b/src/libs/xpcom18a4/xpcom/base/nsStackFrameWin.cpp new file mode 100644 index 00000000..7228356b --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/base/nsStackFrameWin.cpp @@ -0,0 +1,351 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is nsStackFrameWin.h code, released + * December 20, 2003. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 2003 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Michael Judge, 20-December-2000 + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nscore.h" +#include "windows.h" +#include "imagehlp.h" +#include "stdio.h" +#include "nsStackFrameWin.h" + +// Define these as static pointers so that we can load the DLL on the +// fly (and not introduce a link-time dependency on it). Tip o' the +// hat to Matt Pietrick for this idea. See: +// +// http://msdn.microsoft.com/library/periodic/period97/F1/D3/S245C6.htm +// + + +PR_BEGIN_EXTERN_C + +SYMSETOPTIONSPROC _SymSetOptions; + +SYMINITIALIZEPROC _SymInitialize; + +SYMCLEANUPPROC _SymCleanup; + +STACKWALKPROC _StackWalk; + +SYMFUNCTIONTABLEACCESSPROC _SymFunctionTableAccess; + +SYMGETMODULEBASEPROC _SymGetModuleBase; + +SYMGETSYMFROMADDRPROC _SymGetSymFromAddr; + +SYMLOADMODULE _SymLoadModule; + +SYMUNDNAME _SymUnDName; + +SYMGETMODULEINFO _SymGetModuleInfo; + +ENUMLOADEDMODULES _EnumerateLoadedModules; + +SYMGETLINEFROMADDRPROC _SymGetLineFromAddr; + +PR_END_EXTERN_C + + + + +PRBool +EnsureImageHlpInitialized() +{ + static PRBool gInitialized = PR_FALSE; + + if (! gInitialized) { + HMODULE module = ::LoadLibrary("IMAGEHLP.DLL"); + if (!module) return PR_FALSE; + + _SymSetOptions = (SYMSETOPTIONSPROC) ::GetProcAddress(module, "SymSetOptions"); + if (!_SymSetOptions) return PR_FALSE; + + _SymInitialize = (SYMINITIALIZEPROC) ::GetProcAddress(module, "SymInitialize"); + if (!_SymInitialize) return PR_FALSE; + + _SymCleanup = (SYMCLEANUPPROC)GetProcAddress(module, "SymCleanup"); + if (!_SymCleanup) return PR_FALSE; + + _StackWalk = (STACKWALKPROC)GetProcAddress(module, "StackWalk"); + if (!_StackWalk) return PR_FALSE; + + _SymFunctionTableAccess = (SYMFUNCTIONTABLEACCESSPROC) GetProcAddress(module, "SymFunctionTableAccess"); + if (!_SymFunctionTableAccess) return PR_FALSE; + + _SymGetModuleBase = (SYMGETMODULEBASEPROC)GetProcAddress(module, "SymGetModuleBase"); + if (!_SymGetModuleBase) return PR_FALSE; + + _SymGetSymFromAddr = (SYMGETSYMFROMADDRPROC)GetProcAddress(module, "SymGetSymFromAddr"); + if (!_SymGetSymFromAddr) return PR_FALSE; + + _SymLoadModule = (SYMLOADMODULE)GetProcAddress(module, "SymLoadModule"); + if (!_SymLoadModule) return PR_FALSE; + + _SymUnDName = (SYMUNDNAME)GetProcAddress(module, "SymUnDName"); + if (!_SymUnDName) return PR_FALSE; + + _SymGetModuleInfo = (SYMGETMODULEINFO)GetProcAddress(module, "SymGetModuleInfo"); + if (!_SymGetModuleInfo) return PR_FALSE; + + _EnumerateLoadedModules = (ENUMLOADEDMODULES)GetProcAddress(module, "EnumerateLoadedModules"); + if (!_EnumerateLoadedModules) return PR_FALSE; + + _SymGetLineFromAddr = (SYMGETLINEFROMADDRPROC)GetProcAddress(module, "SymGetLineFromAddr"); + if (!_SymGetLineFromAddr) return PR_FALSE; + + gInitialized = PR_TRUE; + } + + return gInitialized; +} + +/* + * Callback used by SymGetModuleInfoEspecial + */ +static BOOL CALLBACK callbackEspecial(LPSTR aModuleName, ULONG aModuleBase, ULONG aModuleSize, PVOID aUserContext) +{ + BOOL retval = TRUE; + DWORD addr = (DWORD)aUserContext; + + /* + * You'll want to control this if we are running on an + * architecture where the addresses go the other direction. + * Not sure this is even a realistic consideration. + */ + const BOOL addressIncreases = TRUE; + + /* + * If it falls in side the known range, load the symbols. + */ + if(addressIncreases + ? (addr >= aModuleBase && addr <= (aModuleBase + aModuleSize)) + : (addr <= aModuleBase && addr >= (aModuleBase - aModuleSize)) + ) + { + BOOL loadRes = FALSE; + HANDLE process = GetCurrentProcess(); + + loadRes = _SymLoadModule(process, NULL, aModuleName, NULL, aModuleBase, aModuleSize); + PR_ASSERT(FALSE != loadRes); + } + + return retval; +} + +/* + * SymGetModuleInfoEspecial + * + * Attempt to determine the module information. + * Bug 112196 says this DLL may not have been loaded at the time + * SymInitialize was called, and thus the module information + * and symbol information is not available. + * This code rectifies that problem. + */ +BOOL SymGetModuleInfoEspecial(HANDLE aProcess, DWORD aAddr, PIMAGEHLP_MODULE aModuleInfo, PIMAGEHLP_LINE aLineInfo) +{ + BOOL retval = FALSE; + + /* + * Init the vars if we have em. + */ + aModuleInfo->SizeOfStruct = sizeof(IMAGEHLP_MODULE); + if (nsnull != aLineInfo) { + aLineInfo->SizeOfStruct = sizeof(IMAGEHLP_LINE); + } + + /* + * Give it a go. + * It may already be loaded. + */ + retval = _SymGetModuleInfo(aProcess, aAddr, aModuleInfo); + + if (FALSE == retval) { + BOOL enumRes = FALSE; + + /* + * Not loaded, here's the magic. + * Go through all the modules. + */ + enumRes = _EnumerateLoadedModules(aProcess, callbackEspecial, (PVOID)aAddr); + if(FALSE != enumRes) + { + /* + * One final go. + * If it fails, then well, we have other problems. + */ + retval = _SymGetModuleInfo(aProcess, aAddr, aModuleInfo); + } + } + + /* + * If we got module info, we may attempt line info as well. + * We will not report failure if this does not work. + */ + if (FALSE != retval && nsnull != aLineInfo && nsnull != _SymGetLineFromAddr) { + DWORD displacement = 0; + BOOL lineRes = FALSE; + + lineRes = _SymGetLineFromAddr(aProcess, aAddr, &displacement, aLineInfo); + } + + return retval; +} + +PRBool +EnsureSymInitialized() +{ + static PRBool gInitialized = PR_FALSE; + + if (! gInitialized) { + if (! EnsureImageHlpInitialized()) + return PR_FALSE; + _SymSetOptions(SYMOPT_LOAD_LINES | SYMOPT_UNDNAME); + gInitialized = _SymInitialize(GetCurrentProcess(), 0, TRUE); + } + return gInitialized; +} + + +/** + * Walk the stack, translating PC's found into strings and recording the + * chain in aBuffer. For this to work properly, the dll's must be rebased + * so that the address in the file agrees with the address in memory. + * Otherwise StackWalk will return FALSE when it hits a frame in a dll's + * whose in memory address doesn't match it's in-file address. + * + * Fortunately, there is a handy dandy routine in IMAGEHLP.DLL that does + * the rebasing and accordingly I've made a tool to use it to rebase the + * DLL's in one fell swoop (see xpcom/tools/windows/rebasedlls.cpp). + */ + + +void +DumpStackToFile(FILE* aStream) +{ + HANDLE myProcess = ::GetCurrentProcess(); + HANDLE myThread = ::GetCurrentThread(); + BOOL ok; + + ok = EnsureSymInitialized(); + if (! ok) + return; + + // Get the context information for this thread. That way we will + // know where our sp, fp, pc, etc. are and can fill in the + // STACKFRAME with the initial values. + CONTEXT context; + context.ContextFlags = CONTEXT_FULL; + ok = GetThreadContext(myThread, &context); + if (! ok) + return; + + // Setup initial stack frame to walk from + STACKFRAME frame; + memset(&frame, 0, sizeof(frame)); + frame.AddrPC.Offset = context.Eip; + frame.AddrPC.Mode = AddrModeFlat; + frame.AddrStack.Offset = context.Esp; + frame.AddrStack.Mode = AddrModeFlat; + frame.AddrFrame.Offset = context.Ebp; + frame.AddrFrame.Mode = AddrModeFlat; + + // Now walk the stack and map the pc's to symbol names + int skip = 2; + while (1) { + ok = _StackWalk(IMAGE_FILE_MACHINE_I386, + myProcess, + myThread, + &frame, + &context, + 0, // read process memory routine + _SymFunctionTableAccess, // function table access routine + _SymGetModuleBase, // module base routine + 0); // translate address routine + + if (!ok) { + LPVOID lpMsgBuf; + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + (LPTSTR) &lpMsgBuf, + 0, + NULL + ); + fprintf(aStream, "### ERROR: WalkStack: %s", lpMsgBuf); + fflush(aStream); + LocalFree( lpMsgBuf ); + } + if (!ok || frame.AddrPC.Offset == 0) + break; + + if (skip-- > 0) + continue; + + // + // Attempt to load module info before we attempt to reolve the symbol. + // This just makes sure we get good info if available. + // + IMAGEHLP_MODULE modInfo; + modInfo.SizeOfStruct = sizeof(modInfo); + BOOL modInfoRes = TRUE; + modInfoRes = SymGetModuleInfoEspecial(myProcess, frame.AddrPC.Offset, &modInfo, nsnull); + + char buf[sizeof(IMAGEHLP_SYMBOL) + 512]; + PIMAGEHLP_SYMBOL symbol = (PIMAGEHLP_SYMBOL) buf; + symbol->SizeOfStruct = sizeof(buf); + symbol->MaxNameLength = 512; + + DWORD displacement; + ok = _SymGetSymFromAddr(myProcess, + frame.AddrPC.Offset, + &displacement, + symbol); + + if (ok) { + fprintf(aStream, "%s+0x%08X\n", symbol->Name, displacement); + } + else { + fprintf(aStream, "0x%08X\n", frame.AddrPC.Offset); + } + } +} + diff --git a/src/libs/xpcom18a4/xpcom/base/nsStackFrameWin.h b/src/libs/xpcom18a4/xpcom/base/nsStackFrameWin.h new file mode 100644 index 00000000..d9b6585c --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/base/nsStackFrameWin.h @@ -0,0 +1,126 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is nsStackFrameWin.h code, released + * December 20, 2000. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 2000 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Michael Judge, 20-December-2000 + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +#ifndef nsStackFrameWin_h___ +#define nsStackFrameWin_h___ + + +#if defined(_WIN32) && defined(_M_IX86) // WIN32 x86 stack walking code +#include "nspr.h" +#include <windows.h> +#include <imagehlp.h> + +// Define these as static pointers so that we can load the DLL on the +// fly (and not introduce a link-time dependency on it). Tip o' the +// hat to Matt Pietrick for this idea. See: +// +// http://msdn.microsoft.com/library/periodic/period97/F1/D3/S245C6.htm +// +PR_BEGIN_EXTERN_C + +typedef DWORD (__stdcall *SYMSETOPTIONSPROC)(DWORD); +extern SYMSETOPTIONSPROC _SymSetOptions; + +typedef BOOL (__stdcall *SYMINITIALIZEPROC)(HANDLE, LPSTR, BOOL); +extern SYMINITIALIZEPROC _SymInitialize; + +typedef BOOL (__stdcall *SYMCLEANUPPROC)(HANDLE); +extern SYMCLEANUPPROC _SymCleanup; + +typedef BOOL (__stdcall *STACKWALKPROC)(DWORD, + HANDLE, + HANDLE, + LPSTACKFRAME, + LPVOID, + PREAD_PROCESS_MEMORY_ROUTINE, + PFUNCTION_TABLE_ACCESS_ROUTINE, + PGET_MODULE_BASE_ROUTINE, + PTRANSLATE_ADDRESS_ROUTINE); +extern STACKWALKPROC _StackWalk; + +typedef LPVOID (__stdcall *SYMFUNCTIONTABLEACCESSPROC)(HANDLE, DWORD); +extern SYMFUNCTIONTABLEACCESSPROC _SymFunctionTableAccess; + +typedef DWORD (__stdcall *SYMGETMODULEBASEPROC)(HANDLE, DWORD); +extern SYMGETMODULEBASEPROC _SymGetModuleBase; + +typedef BOOL (__stdcall *SYMGETSYMFROMADDRPROC)(HANDLE, DWORD, PDWORD, PIMAGEHLP_SYMBOL); +extern SYMGETSYMFROMADDRPROC _SymGetSymFromAddr; + +typedef DWORD ( __stdcall *SYMLOADMODULE)(HANDLE, HANDLE, PSTR, PSTR, DWORD, DWORD); +extern SYMLOADMODULE _SymLoadModule; + +typedef DWORD ( __stdcall *SYMUNDNAME)(PIMAGEHLP_SYMBOL, PSTR, DWORD); +extern SYMUNDNAME _SymUnDName; + +typedef DWORD ( __stdcall *SYMGETMODULEINFO)( HANDLE, DWORD, PIMAGEHLP_MODULE); +extern SYMGETMODULEINFO _SymGetModuleInfo; + +typedef BOOL ( __stdcall *ENUMLOADEDMODULES)( HANDLE, PENUMLOADED_MODULES_CALLBACK, PVOID); +extern ENUMLOADEDMODULES _EnumerateLoadedModules; + +typedef BOOL (__stdcall *SYMGETLINEFROMADDRPROC)(HANDLE, DWORD, PDWORD, PIMAGEHLP_LINE); +extern SYMGETLINEFROMADDRPROC _SymGetLineFromAddr; + +PRBool EnsureSymInitialized(); + +PRBool EnsureImageHlpInitialized(); + +/* + * SymGetModuleInfoEspecial + * + * Attempt to determine the module information. + * Bug 112196 says this DLL may not have been loaded at the time + * SymInitialize was called, and thus the module information + * and symbol information is not available. + * This code rectifies that problem. + * Line information is optional. + */ +BOOL SymGetModuleInfoEspecial(HANDLE aProcess, DWORD aAddr, PIMAGEHLP_MODULE aModuleInfo, PIMAGEHLP_LINE aLineInfo); + + +void DumpStackToFile(FILE* out); + +PR_END_EXTERN_C + +#endif //WIN32 + +#endif //nsStackFrameWin_h___ + + diff --git a/src/libs/xpcom18a4/xpcom/base/nsTraceRefcntImpl.cpp b/src/libs/xpcom18a4/xpcom/base/nsTraceRefcntImpl.cpp new file mode 100644 index 00000000..f74e84df --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/base/nsTraceRefcntImpl.cpp @@ -0,0 +1,1444 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * L. David Baron <dbaron@dbaron.org> + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsTraceRefcntImpl.h" +#include "nscore.h" +#include "nsISupports.h" +#include "nsVoidArray.h" +#include "prprf.h" +#include "prlog.h" +#include "plstr.h" +#include <stdlib.h> +#include "nsCOMPtr.h" +#include "nsCRT.h" +#include <math.h> + +#if defined(_WIN32) +#include <windows.h> +#elif defined(linux) && !defined(VBOX) && defined(__GLIBC__) && (defined(__i386) || defined(PPC)) +#include <setjmp.h> + +// +// On glibc 2.1, the Dl_info api defined in <dlfcn.h> is only exposed +// if __USE_GNU is defined. I suppose its some kind of standards +// adherence thing. +// +#if (__GLIBC_MINOR__ >= 1) && !defined(__USE_GNU) +#define __USE_GNU +#endif + +#include <dlfcn.h> +#endif + +#ifdef HAVE_LIBDL +#include <dlfcn.h> +#endif + +#if defined(XP_MAC) && !TARGET_CARBON +#include "macstdlibextras.h" +#endif + +//////////////////////////////////////////////////////////////////////////////// + +NS_COM void +NS_MeanAndStdDev(double n, double sumOfValues, double sumOfSquaredValues, + double *meanResult, double *stdDevResult) +{ + double mean = 0.0, var = 0.0, stdDev = 0.0; + if (n > 0.0 && sumOfValues >= 0) { + mean = sumOfValues / n; + double temp = (n * sumOfSquaredValues) - (sumOfValues * sumOfValues); + if (temp < 0.0 || n <= 1) + var = 0.0; + else + var = temp / (n * (n - 1)); + // for some reason, Windows says sqrt(0.0) is "-1.#J" (?!) so do this: + stdDev = var != 0.0 ? sqrt(var) : 0.0; + } + *meanResult = mean; + *stdDevResult = stdDev; +} + +//////////////////////////////////////////////////////////////////////////////// + +#ifdef NS_BUILD_REFCNT_LOGGING +#include "plhash.h" +#include "prmem.h" + +#include "prlock.h" + +static PRLock* gTraceLock; + +#define LOCK_TRACELOG() PR_Lock(gTraceLock) +#define UNLOCK_TRACELOG() PR_Unlock(gTraceLock) + +static PLHashTable* gBloatView; +static PLHashTable* gTypesToLog; +static PLHashTable* gObjectsToLog; +static PLHashTable* gSerialNumbers; +static PRInt32 gNextSerialNumber; + +static PRBool gLogging; +static PRBool gLogToLeaky; +static PRBool gLogLeaksOnly; + +static void (*leakyLogAddRef)(void* p, int oldrc, int newrc); +static void (*leakyLogRelease)(void* p, int oldrc, int newrc); + +static PRBool gInitialized = PR_FALSE; +static FILE *gBloatLog = nsnull; +static FILE *gRefcntsLog = nsnull; +static FILE *gAllocLog = nsnull; +static FILE *gLeakyLog = nsnull; +static FILE *gCOMPtrLog = nsnull; +static PRBool gActivityIsLegal = PR_FALSE; + +struct serialNumberRecord { + PRInt32 serialNumber; + PRInt32 refCount; + PRInt32 COMPtrCount; +}; + +struct nsTraceRefcntStats { + nsrefcnt mAddRefs; + nsrefcnt mReleases; + nsrefcnt mCreates; + nsrefcnt mDestroys; + double mRefsOutstandingTotal; + double mRefsOutstandingSquared; + double mObjsOutstandingTotal; + double mObjsOutstandingSquared; +}; + +#ifdef DEBUG_dbaron_off + // I hope to turn this on for everybody once we hit it a little less. +#define ASSERT_ACTIVITY_IS_LEGAL \ + NS_WARN_IF_FALSE(gActivityIsLegal, \ + "XPCOM objects created/destroyed from static ctor/dtor") +#else +#define ASSERT_ACTIVITY_IS_LEGAL +#endif + + +// These functions are copied from nsprpub/lib/ds/plhash.c, with changes +// to the functions not called Default* to free the serialNumberRecord or +// the BloatEntry. + +static void * PR_CALLBACK +DefaultAllocTable(void *pool, PRSize size) +{ +#if defined(XP_MAC) +#pragma unused (pool) +#endif + + return PR_MALLOC(size); +} + +static void PR_CALLBACK +DefaultFreeTable(void *pool, void *item) +{ +#if defined(XP_MAC) +#pragma unused (pool) +#endif + + PR_Free(item); +} + +static PLHashEntry * PR_CALLBACK +DefaultAllocEntry(void *pool, const void *key) +{ +#if defined(XP_MAC) +#pragma unused (pool,key) +#endif + + return PR_NEW(PLHashEntry); +} + +static void PR_CALLBACK +SerialNumberFreeEntry(void *pool, PLHashEntry *he, PRUintn flag) +{ +#if defined(XP_MAC) +#pragma unused (pool) +#endif + + if (flag == HT_FREE_ENTRY) { + PR_Free(NS_REINTERPRET_CAST(serialNumberRecord*,he->value)); + PR_Free(he); + } +} + +static void PR_CALLBACK +TypesToLogFreeEntry(void *pool, PLHashEntry *he, PRUintn flag) +{ +#if defined(XP_MAC) +#pragma unused (pool) +#endif + + if (flag == HT_FREE_ENTRY) { + nsCRT::free(NS_CONST_CAST(char*, + NS_REINTERPRET_CAST(const char*, he->key))); + PR_Free(he); + } +} + +static const PLHashAllocOps serialNumberHashAllocOps = { + DefaultAllocTable, DefaultFreeTable, + DefaultAllocEntry, SerialNumberFreeEntry +}; + +static const PLHashAllocOps typesToLogHashAllocOps = { + DefaultAllocTable, DefaultFreeTable, + DefaultAllocEntry, TypesToLogFreeEntry +}; + +//////////////////////////////////////////////////////////////////////////////// + +class BloatEntry { +public: + BloatEntry(const char* className, PRUint32 classSize) + : mClassSize(classSize) { + mClassName = PL_strdup(className); + Clear(&mNewStats); + Clear(&mAllStats); + mTotalLeaked = 0; + } + + ~BloatEntry() { + PL_strfree(mClassName); + } + + PRUint32 GetClassSize() { return (PRUint32)mClassSize; } + const char* GetClassName() { return mClassName; } + + static void Clear(nsTraceRefcntStats* stats) { + stats->mAddRefs = 0; + stats->mReleases = 0; + stats->mCreates = 0; + stats->mDestroys = 0; + stats->mRefsOutstandingTotal = 0; + stats->mRefsOutstandingSquared = 0; + stats->mObjsOutstandingTotal = 0; + stats->mObjsOutstandingSquared = 0; + } + + void Accumulate() { + mAllStats.mAddRefs += mNewStats.mAddRefs; + mAllStats.mReleases += mNewStats.mReleases; + mAllStats.mCreates += mNewStats.mCreates; + mAllStats.mDestroys += mNewStats.mDestroys; + mAllStats.mRefsOutstandingTotal += mNewStats.mRefsOutstandingTotal; + mAllStats.mRefsOutstandingSquared += mNewStats.mRefsOutstandingSquared; + mAllStats.mObjsOutstandingTotal += mNewStats.mObjsOutstandingTotal; + mAllStats.mObjsOutstandingSquared += mNewStats.mObjsOutstandingSquared; + Clear(&mNewStats); + } + + void AddRef(nsrefcnt refcnt) { + mNewStats.mAddRefs++; + if (refcnt == 1) { + Ctor(); + } + AccountRefs(); + } + + void Release(nsrefcnt refcnt) { + mNewStats.mReleases++; + if (refcnt == 0) { + Dtor(); + } + AccountRefs(); + } + + void Ctor() { + mNewStats.mCreates++; + AccountObjs(); + } + + void Dtor() { + mNewStats.mDestroys++; + AccountObjs(); + } + + void AccountRefs() { + PRInt32 cnt = (mNewStats.mAddRefs - mNewStats.mReleases); + mNewStats.mRefsOutstandingTotal += cnt; + mNewStats.mRefsOutstandingSquared += cnt * cnt; + } + + void AccountObjs() { + PRInt32 cnt = (mNewStats.mCreates - mNewStats.mDestroys); + mNewStats.mObjsOutstandingTotal += cnt; + mNewStats.mObjsOutstandingSquared += cnt * cnt; + } + + static PRIntn PR_CALLBACK DumpEntry(PLHashEntry *he, PRIntn i, void *arg) { + BloatEntry* entry = (BloatEntry*)he->value; + if (entry) { + entry->Accumulate(); + NS_STATIC_CAST(nsVoidArray*, arg)->AppendElement(entry); + } + return HT_ENUMERATE_NEXT; + } + + static PRIntn PR_CALLBACK TotalEntries(PLHashEntry *he, PRIntn i, void *arg) { + BloatEntry* entry = (BloatEntry*)he->value; + if (entry && nsCRT::strcmp(entry->mClassName, "TOTAL") != 0) { + entry->Total((BloatEntry*)arg); + } + return HT_ENUMERATE_NEXT; + } + + void Total(BloatEntry* total) { + total->mAllStats.mAddRefs += mNewStats.mAddRefs + mAllStats.mAddRefs; + total->mAllStats.mReleases += mNewStats.mReleases + mAllStats.mReleases; + total->mAllStats.mCreates += mNewStats.mCreates + mAllStats.mCreates; + total->mAllStats.mDestroys += mNewStats.mDestroys + mAllStats.mDestroys; + total->mAllStats.mRefsOutstandingTotal += mNewStats.mRefsOutstandingTotal + mAllStats.mRefsOutstandingTotal; + total->mAllStats.mRefsOutstandingSquared += mNewStats.mRefsOutstandingSquared + mAllStats.mRefsOutstandingSquared; + total->mAllStats.mObjsOutstandingTotal += mNewStats.mObjsOutstandingTotal + mAllStats.mObjsOutstandingTotal; + total->mAllStats.mObjsOutstandingSquared += mNewStats.mObjsOutstandingSquared + mAllStats.mObjsOutstandingSquared; + PRInt32 count = (mNewStats.mCreates + mAllStats.mCreates); + total->mClassSize += mClassSize * count; // adjust for average in DumpTotal + total->mTotalLeaked += (PRInt32)(mClassSize * + ((mNewStats.mCreates + mAllStats.mCreates) + -(mNewStats.mDestroys + mAllStats.mDestroys))); + } + + nsresult DumpTotal(PRUint32 nClasses, FILE* out) { + mClassSize /= mAllStats.mCreates; + return Dump(-1, out, nsTraceRefcntImpl::ALL_STATS); + } + + static PRBool HaveLeaks(nsTraceRefcntStats* stats) { + return ((stats->mAddRefs != stats->mReleases) || + (stats->mCreates != stats->mDestroys)); + } + + static nsresult PrintDumpHeader(FILE* out, const char* msg) { + fprintf(out, "\n== BloatView: %s\n\n", msg); + fprintf(out, + " |<----------------Class--------------->|<-----Bytes------>|<----------------Objects---------------->|<--------------References-------------->|\n"); + fprintf(out, + " Per-Inst Leaked Total Rem Mean StdDev Total Rem Mean StdDev\n"); + return NS_OK; + } + + nsresult Dump(PRIntn i, FILE* out, nsTraceRefcntImpl::StatisticsType type) { + nsTraceRefcntStats* stats = (type == nsTraceRefcntImpl::NEW_STATS) ? &mNewStats : &mAllStats; + if (gLogLeaksOnly && !HaveLeaks(stats)) { + return NS_OK; + } + + double meanRefs, stddevRefs; + NS_MeanAndStdDev(stats->mAddRefs + stats->mReleases, + stats->mRefsOutstandingTotal, + stats->mRefsOutstandingSquared, + &meanRefs, &stddevRefs); + + double meanObjs, stddevObjs; + NS_MeanAndStdDev(stats->mCreates + stats->mDestroys, + stats->mObjsOutstandingTotal, + stats->mObjsOutstandingSquared, + &meanObjs, &stddevObjs); + + if ((stats->mAddRefs - stats->mReleases) != 0 || + stats->mAddRefs != 0 || + meanRefs != 0 || + stddevRefs != 0 || + (stats->mCreates - stats->mDestroys) != 0 || + stats->mCreates != 0 || + meanObjs != 0 || + stddevObjs != 0) { + fprintf(out, "%4d %-40.40s %8d %8d %8d %8d (%8.2f +/- %8.2f) %8d %8d (%8.2f +/- %8.2f)\n", + i+1, mClassName, + (PRInt32)mClassSize, + (nsCRT::strcmp(mClassName, "TOTAL")) + ?(PRInt32)((stats->mCreates - stats->mDestroys) * mClassSize) + :mTotalLeaked, + stats->mCreates, + (stats->mCreates - stats->mDestroys), + meanObjs, + stddevObjs, + stats->mAddRefs, + (stats->mAddRefs - stats->mReleases), + meanRefs, + stddevRefs); + } + return NS_OK; + } + +protected: + char* mClassName; + double mClassSize; // this is stored as a double because of the way we compute the avg class size for total bloat + PRInt32 mTotalLeaked; // used only for TOTAL entry + nsTraceRefcntStats mNewStats; + nsTraceRefcntStats mAllStats; +}; + +static void PR_CALLBACK +BloatViewFreeEntry(void *pool, PLHashEntry *he, PRUintn flag) +{ +#if defined(XP_MAC) +#pragma unused (pool) +#endif + + if (flag == HT_FREE_ENTRY) { + BloatEntry* entry = NS_REINTERPRET_CAST(BloatEntry*,he->value); + delete entry; + PR_Free(he); + } +} + +const static PLHashAllocOps bloatViewHashAllocOps = { + DefaultAllocTable, DefaultFreeTable, + DefaultAllocEntry, BloatViewFreeEntry +}; + +static void +RecreateBloatView() +{ + gBloatView = PL_NewHashTable(256, + PL_HashString, + PL_CompareStrings, + PL_CompareValues, + &bloatViewHashAllocOps, NULL); +} + +static BloatEntry* +GetBloatEntry(const char* aTypeName, PRUint32 aInstanceSize) +{ + if (!gBloatView) { + RecreateBloatView(); + } + BloatEntry* entry = NULL; + if (gBloatView) { + entry = (BloatEntry*)PL_HashTableLookup(gBloatView, aTypeName); + if (entry == NULL && aInstanceSize > 0) { + + entry = new BloatEntry(aTypeName, aInstanceSize); + PLHashEntry* e = PL_HashTableAdd(gBloatView, aTypeName, entry); + if (e == NULL) { + delete entry; + entry = NULL; + } + } else { + NS_ASSERTION(aInstanceSize == 0 || + entry->GetClassSize() == aInstanceSize, + "bad size recorded"); + } + } + return entry; +} + +static PRIntn PR_CALLBACK DumpSerialNumbers(PLHashEntry* aHashEntry, PRIntn aIndex, void* aClosure) +{ + serialNumberRecord* record = NS_REINTERPRET_CAST(serialNumberRecord *,aHashEntry->value); +#ifdef HAVE_CPP_DYNAMIC_CAST_TO_VOID_PTR + fprintf((FILE*) aClosure, "%d (%d references; %d from COMPtrs)\n", + record->serialNumber, + record->refCount, + record->COMPtrCount); +#else + fprintf((FILE*) aClosure, "%d (%d references)\n", + record->serialNumber, + record->refCount); +#endif + return HT_ENUMERATE_NEXT; +} + + +#endif /* NS_BUILD_REFCNT_LOGGING */ + +nsresult +nsTraceRefcntImpl::DumpStatistics(StatisticsType type, FILE* out) +{ + nsresult rv = NS_OK; +#ifdef NS_BUILD_REFCNT_LOGGING + if (gBloatLog == nsnull || gBloatView == nsnull) { + return NS_ERROR_FAILURE; + } + if (out == nsnull) { + out = gBloatLog; + } + + LOCK_TRACELOG(); + + PRBool wasLogging = gLogging; + gLogging = PR_FALSE; // turn off logging for this method + + const char* msg; + if (type == NEW_STATS) { + if (gLogLeaksOnly) + msg = "NEW (incremental) LEAK STATISTICS"; + else + msg = "NEW (incremental) LEAK AND BLOAT STATISTICS"; + } + else { + if (gLogLeaksOnly) + msg = "ALL (cumulative) LEAK STATISTICS"; + else + msg = "ALL (cumulative) LEAK AND BLOAT STATISTICS"; + } + rv = BloatEntry::PrintDumpHeader(out, msg); + if (NS_FAILED(rv)) goto done; + + { + BloatEntry total("TOTAL", 0); + PL_HashTableEnumerateEntries(gBloatView, BloatEntry::TotalEntries, &total); + total.DumpTotal(gBloatView->nentries, out); + + nsVoidArray entries; + PL_HashTableEnumerateEntries(gBloatView, BloatEntry::DumpEntry, &entries); + + fprintf(stdout, "nsTraceRefcntImpl::DumpStatistics: %d entries\n", + entries.Count()); + + // Sort the entries alphabetically by classname. + PRInt32 i, j; + for (i = entries.Count() - 1; i >= 1; --i) { + for (j = i - 1; j >= 0; --j) { + BloatEntry* left = NS_STATIC_CAST(BloatEntry*, entries[i]); + BloatEntry* right = NS_STATIC_CAST(BloatEntry*, entries[j]); + + if (PL_strcmp(left->GetClassName(), right->GetClassName()) < 0) { + entries.ReplaceElementAt(right, i); + entries.ReplaceElementAt(left, j); + } + } + } + + // Enumerate from back-to-front, so things come out in alpha order + for (i = 0; i < entries.Count(); ++i) { + BloatEntry* entry = NS_STATIC_CAST(BloatEntry*, entries[i]); + entry->Dump(i, out, type); + } + } + + if (gSerialNumbers) { + fprintf(out, "\n\nSerial Numbers of Leaked Objects:\n"); + PL_HashTableEnumerateEntries(gSerialNumbers, DumpSerialNumbers, out); + } + +done: + gLogging = wasLogging; + UNLOCK_TRACELOG(); +#endif + return rv; +} + +void +nsTraceRefcntImpl::ResetStatistics() +{ +#ifdef NS_BUILD_REFCNT_LOGGING + LOCK_TRACELOG(); + if (gBloatView) { + PL_HashTableDestroy(gBloatView); + gBloatView = nsnull; + } + UNLOCK_TRACELOG(); +#endif +} + +#ifdef NS_BUILD_REFCNT_LOGGING +static PRBool LogThisType(const char* aTypeName) +{ + void* he = PL_HashTableLookup(gTypesToLog, aTypeName); + return nsnull != he; +} + +static PRInt32 GetSerialNumber(void* aPtr, PRBool aCreate) +{ +#ifdef GC_LEAK_DETECTOR + // need to disguise this pointer, so the table won't keep the object alive. + aPtr = (void*) ~PLHashNumber(aPtr); +#endif + PLHashEntry** hep = PL_HashTableRawLookup(gSerialNumbers, PLHashNumber(NS_PTR_TO_INT32(aPtr)), aPtr); + if (hep && *hep) { + return PRInt32((NS_REINTERPRET_CAST(serialNumberRecord*,(*hep)->value))->serialNumber); + } + else if (aCreate) { + serialNumberRecord *record = PR_NEW(serialNumberRecord); + record->serialNumber = ++gNextSerialNumber; + record->refCount = 0; + record->COMPtrCount = 0; + PL_HashTableRawAdd(gSerialNumbers, hep, PLHashNumber(NS_PTR_TO_INT32(aPtr)), aPtr, NS_REINTERPRET_CAST(void*,record)); + return gNextSerialNumber; + } + else { + return 0; + } +} + +static PRInt32* GetRefCount(void* aPtr) +{ +#ifdef GC_LEAK_DETECTOR + // need to disguise this pointer, so the table won't keep the object alive. + aPtr = (void*) ~PLHashNumber(aPtr); +#endif + PLHashEntry** hep = PL_HashTableRawLookup(gSerialNumbers, PLHashNumber(NS_PTR_TO_INT32(aPtr)), aPtr); + if (hep && *hep) { + return &((NS_REINTERPRET_CAST(serialNumberRecord*,(*hep)->value))->refCount); + } else { + return nsnull; + } +} + +static PRInt32* GetCOMPtrCount(void* aPtr) +{ +#ifdef GC_LEAK_DETECTOR + // need to disguise this pointer, so the table won't keep the object alive. + aPtr = (void*) ~PLHashNumber(aPtr); +#endif + PLHashEntry** hep = PL_HashTableRawLookup(gSerialNumbers, PLHashNumber(NS_PTR_TO_INT32(aPtr)), aPtr); + if (hep && *hep) { + return &((NS_REINTERPRET_CAST(serialNumberRecord*,(*hep)->value))->COMPtrCount); + } else { + return nsnull; + } +} + +static void RecycleSerialNumberPtr(void* aPtr) +{ +#ifdef GC_LEAK_DETECTOR + // need to disguise this pointer, so the table won't keep the object alive. + aPtr = (void*) ~PLHashNumber(aPtr); +#endif + PL_HashTableRemove(gSerialNumbers, aPtr); +} + +static PRBool LogThisObj(PRInt32 aSerialNumber) +{ + return nsnull != PL_HashTableLookup(gObjectsToLog, (const void*)(uintptr_t)(aSerialNumber)); +} + +static PRBool InitLog(const char* envVar, const char* msg, FILE* *result) +{ + const char* value = getenv(envVar); + if (value) { + if (nsCRT::strcmp(value, "1") == 0) { + *result = stdout; + fprintf(stdout, "### %s defined -- logging %s to stdout\n", + envVar, msg); + return PR_TRUE; + } + else if (nsCRT::strcmp(value, "2") == 0) { + *result = stderr; + fprintf(stdout, "### %s defined -- logging %s to stderr\n", + envVar, msg); + return PR_TRUE; + } + else { + FILE *stream = ::fopen(value, "w"); + if (stream != NULL) { + *result = stream; + fprintf(stdout, "### %s defined -- logging %s to %s\n", + envVar, msg, value); + return PR_TRUE; + } + else { + fprintf(stdout, "### %s defined -- unable to log %s to %s\n", + envVar, msg, value); + return PR_FALSE; + } + } + } + return PR_FALSE; +} + + +static PLHashNumber PR_CALLBACK HashNumber(const void* aKey) +{ + return PLHashNumber(NS_PTR_TO_INT32(aKey)); +} + +static void InitTraceLog(void) +{ + if (gInitialized) return; + gInitialized = PR_TRUE; + +#if defined(XP_MAC) && !TARGET_CARBON + // this can get called before Toolbox has been initialized. + InitializeMacToolbox(); +#endif + + PRBool defined; + defined = InitLog("XPCOM_MEM_BLOAT_LOG", "bloat/leaks", &gBloatLog); + if (!defined) + gLogLeaksOnly = InitLog("XPCOM_MEM_LEAK_LOG", "leaks", &gBloatLog); + if (defined || gLogLeaksOnly) { + RecreateBloatView(); + if (!gBloatView) { + NS_WARNING("out of memory"); + gBloatLog = nsnull; + gLogLeaksOnly = PR_FALSE; + } + } + + (void)InitLog("XPCOM_MEM_REFCNT_LOG", "refcounts", &gRefcntsLog); + + (void)InitLog("XPCOM_MEM_ALLOC_LOG", "new/delete", &gAllocLog); + + defined = InitLog("XPCOM_MEM_LEAKY_LOG", "for leaky", &gLeakyLog); + if (defined) { + gLogToLeaky = PR_TRUE; + void* p = nsnull; + void* q = nsnull; +#ifdef HAVE_LIBDL + p = dlsym(0, "__log_addref"); + q = dlsym(0, "__log_release"); +#endif + if (p && q) { + leakyLogAddRef = (void (*)(void*,int,int)) p; + leakyLogRelease = (void (*)(void*,int,int)) q; + } + else { + gLogToLeaky = PR_FALSE; + fprintf(stdout, "### ERROR: XPCOM_MEM_LEAKY_LOG defined, but can't locate __log_addref and __log_release symbols\n"); + fflush(stdout); + } + } + + const char* classes = getenv("XPCOM_MEM_LOG_CLASSES"); + +#ifdef HAVE_CPP_DYNAMIC_CAST_TO_VOID_PTR + if (classes) { + (void)InitLog("XPCOM_MEM_COMPTR_LOG", "nsCOMPtr", &gCOMPtrLog); + } else { + if (getenv("XPCOM_MEM_COMPTR_LOG")) { + fprintf(stdout, "### XPCOM_MEM_COMPTR_LOG defined -- but XPCOM_MEM_LOG_CLASSES is not defined\n"); + } + } +#else + const char* comptr_log = getenv("XPCOM_MEM_COMPTR_LOG"); + if (comptr_log) { + fprintf(stdout, "### XPCOM_MEM_COMPTR_LOG defined -- but it will not work without dynamic_cast\n"); + } +#endif + + if (classes) { + // if XPCOM_MEM_LOG_CLASSES was set to some value, the value is interpreted + // as a list of class names to track + gTypesToLog = PL_NewHashTable(256, + PL_HashString, + PL_CompareStrings, + PL_CompareValues, + &typesToLogHashAllocOps, NULL); + if (!gTypesToLog) { + NS_WARNING("out of memory"); + fprintf(stdout, "### XPCOM_MEM_LOG_CLASSES defined -- unable to log specific classes\n"); + } + else { + fprintf(stdout, "### XPCOM_MEM_LOG_CLASSES defined -- only logging these classes: "); + const char* cp = classes; + for (;;) { + char* cm = (char*) strchr(cp, ','); + if (cm) { + *cm = '\0'; + } + PL_HashTableAdd(gTypesToLog, nsCRT::strdup(cp), (void*)1); + fprintf(stdout, "%s ", cp); + if (!cm) break; + *cm = ','; + cp = cm + 1; + } + fprintf(stdout, "\n"); + } + + gSerialNumbers = PL_NewHashTable(256, + HashNumber, + PL_CompareValues, + PL_CompareValues, + &serialNumberHashAllocOps, NULL); + + + } + + const char* objects = getenv("XPCOM_MEM_LOG_OBJECTS"); + if (objects) { + gObjectsToLog = PL_NewHashTable(256, + HashNumber, + PL_CompareValues, + PL_CompareValues, + NULL, NULL); + + if (!gObjectsToLog) { + NS_WARNING("out of memory"); + fprintf(stdout, "### XPCOM_MEM_LOG_OBJECTS defined -- unable to log specific objects\n"); + } + else if (! (gRefcntsLog || gAllocLog || gCOMPtrLog)) { + fprintf(stdout, "### XPCOM_MEM_LOG_OBJECTS defined -- but none of XPCOM_MEM_(REFCNT|ALLOC|COMPTR)_LOG is defined\n"); + } + else { + fprintf(stdout, "### XPCOM_MEM_LOG_OBJECTS defined -- only logging these objects: "); + const char* cp = objects; + for (;;) { + char* cm = (char*) strchr(cp, ','); + if (cm) { + *cm = '\0'; + } + PRInt32 top = 0; + PRInt32 bottom = 0; + while (*cp) { + if (*cp == '-') { + bottom = top; + top = 0; + ++cp; + } + top *= 10; + top += *cp - '0'; + ++cp; + } + if (!bottom) { + bottom = top; + } + for(PRInt32 serialno = bottom; serialno <= top; serialno++) { + PL_HashTableAdd(gObjectsToLog, (const void*)serialno, (void*)1); + fprintf(stdout, "%d ", serialno); + } + if (!cm) break; + *cm = ','; + cp = cm + 1; + } + fprintf(stdout, "\n"); + } + } + + + if (gBloatLog || gRefcntsLog || gAllocLog || gLeakyLog || gCOMPtrLog) { + gLogging = PR_TRUE; + } + + gTraceLock = PR_NewLock(); +} + +#endif + +#if defined(_WIN32) && defined(_M_IX86) // WIN32 x86 stack walking code +#include "nsStackFrameWin.h" +void +nsTraceRefcntImpl::WalkTheStack(FILE* aStream) +{ + DumpStackToFile(aStream); +} + +// WIN32 x86 stack walking code +// i386 or PPC Linux stackwalking code or Solaris +#elif (defined(linux) && !defined(VBOX) && defined(__GLIBC__) && (defined(__i386) || defined(PPC))) || (defined(__sun) && (defined(__sparc) || defined(sparc) || defined(__i386) || defined(i386))) +#include "nsStackFrameUnix.h" +void +nsTraceRefcntImpl::WalkTheStack(FILE* aStream) +{ + DumpStackToFile(aStream); +} + +#elif defined(XP_MAC) + +/** + * Stack walking code for the Mac OS. + */ + +#include "gc_fragments.h" + +#include <typeinfo> + +extern "C" { +void MWUnmangle(const char *mangled_name, char *unmangled_name, size_t buffersize); +} + +struct traceback_table { + long zero; + long magic; + long reserved; + long codeSize; + short nameLength; + char name[2]; +}; + +static char* pc2name(long* pc, char name[], long size) +{ + name[0] = '\0'; + + // make sure pc is instruction aligned (at least). + if (UInt32(pc) == (UInt32(pc) & 0xFFFFFFFC)) { + long instructionsToLook = 4096; + long* instruction = (long*)pc; + + // look for the traceback table. + while (instructionsToLook--) { + if (instruction[0] == 0x4E800020 && instruction[1] == 0x00000000) { + traceback_table* tb = (traceback_table*)&instruction[1]; + memcpy(name, tb->name + 1, --nameLength); + name[nameLength] = '\0'; + break; + } + ++instruction; + } + } + + return name; +} + +struct stack_frame { + stack_frame* next; // savedSP + void* savedCR; + void* savedLR; + void* reserved0; + void* reserved1; + void* savedTOC; +}; + +static asm stack_frame* getStackFrame() +{ + mr r3, sp + blr +} + +NS_COM void +nsTraceRefcntImpl::WalkTheStack(FILE* aStream) +{ + stack_frame* currentFrame = getStackFrame(); // WalkTheStack's frame. + currentFrame = currentFrame->next; // WalkTheStack's caller's frame. + currentFrame = currentFrame->next; // WalkTheStack's caller's caller's frame. + + while (true) { + // LR saved at 8(SP) in each frame. subtract 4 to get address of calling instruction. + void* pc = currentFrame->savedLR; + + // convert PC to name, unmangle it, and generate source location, if possible. + static char symbol_name[1024], unmangled_name[1024], file_name[256]; UInt32 file_offset; + + if (GC_address_to_source((char*)pc, symbol_name, file_name, &file_offset)) { + MWUnmangle(symbol_name, unmangled_name, sizeof(unmangled_name)); + fprintf(aStream, "%s[%s,%ld]\n", unmangled_name, file_name, file_offset); + } else { + pc2name((long*)pc, symbol_name, sizeof(symbol_name)); + MWUnmangle(symbol_name, unmangled_name, sizeof(unmangled_name)); + fprintf(aStream, "%s(0x%08X)\n", unmangled_name, pc); + } + + currentFrame = currentFrame->next; + // the bottom-most frame is marked as pointing to NULL, or is ODD if a 68K transition frame. + if (currentFrame == NULL || UInt32(currentFrame) & 0x1) + break; + } +} + +#else // unsupported platform. + +void +nsTraceRefcntImpl::WalkTheStack(FILE* aStream) +{ + fprintf(aStream, "write me, dammit!\n"); +} + +#endif + +//---------------------------------------------------------------------- + +// This thing is exported by libstdc++ +// Yes, this is a gcc only hack +#if defined(MOZ_DEMANGLE_SYMBOLS) +#include <cxxabi.h> +#include <stdlib.h> // for free() +#endif // MOZ_DEMANGLE_SYMBOLS + +NS_COM void +nsTraceRefcntImpl::DemangleSymbol(const char * aSymbol, + char * aBuffer, + int aBufLen) +{ + NS_ASSERTION(nsnull != aSymbol,"null symbol"); + NS_ASSERTION(nsnull != aBuffer,"null buffer"); + NS_ASSERTION(aBufLen >= 32 ,"pulled 32 out of you know where"); + + aBuffer[0] = '\0'; + +#if defined(MOZ_DEMANGLE_SYMBOLS) + /* See demangle.h in the gcc source for the voodoo */ + char * demangled = abi::__cxa_demangle(aSymbol,0,0,0); + + if (demangled) + { + strncpy(aBuffer,demangled,aBufLen); + free(demangled); + } +#endif // MOZ_DEMANGLE_SYMBOLS +} + + +//---------------------------------------------------------------------- + +NS_COM void +nsTraceRefcntImpl::LoadLibrarySymbols(const char* aLibraryName, + void* aLibrayHandle) +{ +#ifdef NS_BUILD_REFCNT_LOGGING +#if defined(_WIN32) && defined(_M_IX86) /* Win32 x86 only */ + if (!gInitialized) + InitTraceLog(); + + if (gAllocLog || gRefcntsLog) { + fprintf(stdout, "### Loading symbols for %s\n", aLibraryName); + fflush(stdout); + + HANDLE myProcess = ::GetCurrentProcess(); + BOOL ok = EnsureSymInitialized(); + if (ok) { + const char* baseName = aLibraryName; + // just get the base name of the library if a full path was given: + PRInt32 len = strlen(aLibraryName); + for (PRInt32 i = len - 1; i >= 0; i--) { + if (aLibraryName[i] == '\\') { + baseName = &aLibraryName[i + 1]; + break; + } + } + DWORD baseAddr = _SymLoadModule(myProcess, + NULL, + (char*)baseName, + (char*)baseName, + 0, + 0); + ok = (baseAddr != nsnull); + } + if (!ok) { + LPVOID lpMsgBuf; + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + (LPTSTR) &lpMsgBuf, + 0, + NULL + ); + fprintf(stdout, "### ERROR: LoadLibrarySymbols for %s: %s\n", + aLibraryName, lpMsgBuf); + fflush(stdout); + LocalFree( lpMsgBuf ); + } + } +#endif +#endif +} + +//---------------------------------------------------------------------- + + + + + + +// don't use the logging ones. :-) +NS_IMETHODIMP_(nsrefcnt) nsTraceRefcntImpl::AddRef(void) +{ + NS_PRECONDITION(PRInt32(mRefCnt) >= 0, "illegal refcnt"); + ++mRefCnt; + return mRefCnt; +} + +NS_IMETHODIMP_(nsrefcnt) nsTraceRefcntImpl::Release(void) +{ + NS_PRECONDITION(0 != mRefCnt, "dup release"); + --mRefCnt; + if (mRefCnt == 0) { + mRefCnt = 1; /* stabilize */ + delete this; + return 0; + } + return mRefCnt; +} + +NS_IMPL_QUERY_INTERFACE1(nsTraceRefcntImpl, nsITraceRefcnt) + +nsTraceRefcntImpl::nsTraceRefcntImpl() +{ + /* member initializers and constructor code */ +} + +NS_IMETHODIMP +nsTraceRefcntImpl::LogAddRef(void* aPtr, + nsrefcnt aRefcnt, + const char* aClazz, + PRUint32 classSize) +{ +#ifdef NS_BUILD_REFCNT_LOGGING + ASSERT_ACTIVITY_IS_LEGAL; + if (!gInitialized) + InitTraceLog(); + if (gLogging) { + LOCK_TRACELOG(); + + if (gBloatLog) { + BloatEntry* entry = GetBloatEntry(aClazz, classSize); + if (entry) { + entry->AddRef(aRefcnt); + } + } + + // Here's the case where neither NS_NEWXPCOM nor MOZ_COUNT_CTOR were used, + // yet we still want to see creation information: + + PRBool loggingThisType = (!gTypesToLog || LogThisType(aClazz)); + PRInt32 serialno = 0; + if (gSerialNumbers && loggingThisType) { + serialno = GetSerialNumber(aPtr, aRefcnt == 1); + PRInt32* count = GetRefCount(aPtr); + if(count) + (*count)++; + + } + + PRBool loggingThisObject = (!gObjectsToLog || LogThisObj(serialno)); + if (aRefcnt == 1 && gAllocLog && loggingThisType && loggingThisObject) { + fprintf(gAllocLog, "\n<%s> 0x%08X %d Create\n", + aClazz, NS_PTR_TO_INT32(aPtr), serialno); + WalkTheStack(gAllocLog); + } + + if (gRefcntsLog && loggingThisType && loggingThisObject) { + if (gLogToLeaky) { + (*leakyLogAddRef)(aPtr, aRefcnt - 1, aRefcnt); + } + else { + // Can't use PR_LOG(), b/c it truncates the line + fprintf(gRefcntsLog, + "\n<%s> 0x%08X %d AddRef %d\n", aClazz, NS_PTR_TO_INT32(aPtr), serialno, aRefcnt); + WalkTheStack(gRefcntsLog); + fflush(gRefcntsLog); + } + } + UNLOCK_TRACELOG(); + } +#endif + return NS_OK; +} + +NS_IMETHODIMP +nsTraceRefcntImpl::LogRelease(void* aPtr, + nsrefcnt aRefcnt, + const char* aClazz) +{ +#ifdef NS_BUILD_REFCNT_LOGGING + ASSERT_ACTIVITY_IS_LEGAL; + if (!gInitialized) + InitTraceLog(); + if (gLogging) { + LOCK_TRACELOG(); + + if (gBloatLog) { + BloatEntry* entry = GetBloatEntry(aClazz, 0); + if (entry) { + entry->Release(aRefcnt); + } + } + + PRBool loggingThisType = (!gTypesToLog || LogThisType(aClazz)); + PRInt32 serialno = 0; + if (gSerialNumbers && loggingThisType) { + serialno = GetSerialNumber(aPtr, PR_FALSE); + PRInt32* count = GetRefCount(aPtr); + if(count) + (*count)--; + + } + + PRBool loggingThisObject = (!gObjectsToLog || LogThisObj(serialno)); + if (gRefcntsLog && loggingThisType && loggingThisObject) { + if (gLogToLeaky) { + (*leakyLogRelease)(aPtr, aRefcnt + 1, aRefcnt); + } + else { + // Can't use PR_LOG(), b/c it truncates the line + fprintf(gRefcntsLog, + "\n<%s> 0x%08X %d Release %d\n", aClazz, NS_PTR_TO_INT32(aPtr), serialno, aRefcnt); + WalkTheStack(gRefcntsLog); + fflush(gRefcntsLog); + } + } + + // Here's the case where neither NS_DELETEXPCOM nor MOZ_COUNT_DTOR were used, + // yet we still want to see deletion information: + + if (aRefcnt == 0 && gAllocLog && loggingThisType && loggingThisObject) { + fprintf(gAllocLog, + "\n<%s> 0x%08X %d Destroy\n", + aClazz, NS_PTR_TO_INT32(aPtr), serialno); + WalkTheStack(gAllocLog); + } + + if (aRefcnt == 0 && gSerialNumbers && loggingThisType) { + RecycleSerialNumberPtr(aPtr); + } + + UNLOCK_TRACELOG(); + } +#endif + return NS_OK; +} + +NS_IMETHODIMP +nsTraceRefcntImpl::LogCtor(void* aPtr, + const char* aType, + PRUint32 aInstanceSize) +{ +#ifdef NS_BUILD_REFCNT_LOGGING + ASSERT_ACTIVITY_IS_LEGAL; + if (!gInitialized) + InitTraceLog(); + + if (gLogging) { + LOCK_TRACELOG(); + + if (gBloatLog) { + BloatEntry* entry = GetBloatEntry(aType, aInstanceSize); + if (entry) { + entry->Ctor(); + } + } + + PRBool loggingThisType = (!gTypesToLog || LogThisType(aType)); + PRInt32 serialno = 0; + if (gSerialNumbers && loggingThisType) { + serialno = GetSerialNumber(aPtr, PR_TRUE); + } + + PRBool loggingThisObject = (!gObjectsToLog || LogThisObj(serialno)); + if (gAllocLog && loggingThisType && loggingThisObject) { + fprintf(gAllocLog, "\n<%s> 0x%08X %d Ctor (%d)\n", + aType, NS_PTR_TO_INT32(aPtr), serialno, aInstanceSize); + WalkTheStack(gAllocLog); + } + + UNLOCK_TRACELOG(); + } +#endif + return NS_OK; +} + + +NS_IMETHODIMP +nsTraceRefcntImpl::LogDtor(void* aPtr, + const char* aType, + PRUint32 aInstanceSize) +{ +#ifdef NS_BUILD_REFCNT_LOGGING + ASSERT_ACTIVITY_IS_LEGAL; + if (!gInitialized) + InitTraceLog(); + + if (gLogging) { + LOCK_TRACELOG(); + + if (gBloatLog) { + BloatEntry* entry = GetBloatEntry(aType, aInstanceSize); + if (entry) { + entry->Dtor(); + } + } + + PRBool loggingThisType = (!gTypesToLog || LogThisType(aType)); + PRInt32 serialno = 0; + if (gSerialNumbers && loggingThisType) { + serialno = GetSerialNumber(aPtr, PR_FALSE); + RecycleSerialNumberPtr(aPtr); + } + + PRBool loggingThisObject = (!gObjectsToLog || LogThisObj(serialno)); + + // (If we're on a losing architecture, don't do this because we'll be + // using LogDeleteXPCOM instead to get file and line numbers.) + if (gAllocLog && loggingThisType && loggingThisObject) { + fprintf(gAllocLog, "\n<%s> 0x%08X %d Dtor (%d)\n", + aType, NS_PTR_TO_INT32(aPtr), serialno, aInstanceSize); + WalkTheStack(gAllocLog); + } + + UNLOCK_TRACELOG(); + } +#endif + return NS_OK; +} + + +NS_IMETHODIMP +nsTraceRefcntImpl::LogAddCOMPtr(void* aCOMPtr, + nsISupports* aObject) +{ +#if defined(NS_BUILD_REFCNT_LOGGING) && defined(HAVE_CPP_DYNAMIC_CAST_TO_VOID_PTR) + // Get the most-derived object. + void *object = dynamic_cast<void *>(aObject); + + // This is a very indirect way of finding out what the class is + // of the object being logged. If we're logging a specific type, + // then + if (!gTypesToLog || !gSerialNumbers) { + return NS_OK; + } + PRInt32 serialno = GetSerialNumber(object, PR_FALSE); + if (serialno == 0) { + return NS_OK; + } + + if (!gInitialized) + InitTraceLog(); + if (gLogging) { + LOCK_TRACELOG(); + + PRInt32* count = GetCOMPtrCount(object); + if(count) + (*count)++; + + PRBool loggingThisObject = (!gObjectsToLog || LogThisObj(serialno)); + + if (gCOMPtrLog && loggingThisObject) { + fprintf(gCOMPtrLog, "\n<?> 0x%08X %d nsCOMPtrAddRef %d 0x%08X\n", + NS_PTR_TO_INT32(object), serialno, count?(*count):-1, NS_PTR_TO_INT32(aCOMPtr)); + WalkTheStack(gCOMPtrLog); + } + + UNLOCK_TRACELOG(); + } +#endif + return NS_OK; +} + + +NS_IMETHODIMP +nsTraceRefcntImpl::LogReleaseCOMPtr(void* aCOMPtr, + nsISupports* aObject) +{ +#if defined(NS_BUILD_REFCNT_LOGGING) && defined(HAVE_CPP_DYNAMIC_CAST_TO_VOID_PTR) + // Get the most-derived object. + void *object = dynamic_cast<void *>(aObject); + + // This is a very indirect way of finding out what the class is + // of the object being logged. If we're logging a specific type, + // then + if (!gTypesToLog || !gSerialNumbers) { + return NS_OK; + } + PRInt32 serialno = GetSerialNumber(object, PR_FALSE); + if (serialno == 0) { + return NS_OK; + } + + if (!gInitialized) + InitTraceLog(); + if (gLogging) { + LOCK_TRACELOG(); + + PRInt32* count = GetCOMPtrCount(object); + if(count) + (*count)--; + + PRBool loggingThisObject = (!gObjectsToLog || LogThisObj(serialno)); + + if (gCOMPtrLog && loggingThisObject) { + fprintf(gCOMPtrLog, "\n<?> 0x%08X %d nsCOMPtrRelease %d 0x%08X\n", + NS_PTR_TO_INT32(object), serialno, count?(*count):-1, NS_PTR_TO_INT32(aCOMPtr)); + WalkTheStack(gCOMPtrLog); + } + + UNLOCK_TRACELOG(); + } +#endif + return NS_OK; +} + +NS_COM void +nsTraceRefcntImpl::Startup() +{ +#ifdef NS_BUILD_REFCNT_LOGGING + SetActivityIsLegal(PR_TRUE); +#endif +} + +NS_COM void +nsTraceRefcntImpl::Shutdown() +{ +#ifdef NS_BUILD_REFCNT_LOGGING + + if (gBloatView) { + PL_HashTableDestroy(gBloatView); + gBloatView = nsnull; + } + if (gTypesToLog) { + PL_HashTableDestroy(gTypesToLog); + gTypesToLog = nsnull; + } + if (gObjectsToLog) { + PL_HashTableDestroy(gObjectsToLog); + gObjectsToLog = nsnull; + } + if (gSerialNumbers) { + PL_HashTableDestroy(gSerialNumbers); + gSerialNumbers = nsnull; + } + + SetActivityIsLegal(PR_FALSE); + +#endif +} + +NS_COM void +nsTraceRefcntImpl::SetActivityIsLegal(PRBool aLegal) +{ +#ifdef NS_BUILD_REFCNT_LOGGING + gActivityIsLegal = aLegal; +#endif +} + + +NS_METHOD +nsTraceRefcntImpl::Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr) +{ + *aInstancePtr = nsnull; + nsITraceRefcnt* tracer = new nsTraceRefcntImpl(); + if (!tracer) + return NS_ERROR_OUT_OF_MEMORY; + + nsresult rv = tracer->QueryInterface(aIID, aInstancePtr); + if (NS_FAILED(rv)) { + delete tracer; + } + + return rv; +} diff --git a/src/libs/xpcom18a4/xpcom/base/nsTraceRefcntImpl.h b/src/libs/xpcom18a4/xpcom/base/nsTraceRefcntImpl.h new file mode 100644 index 00000000..528b285d --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/base/nsTraceRefcntImpl.h @@ -0,0 +1,109 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * L. David Baron <dbaron@dbaron.org> + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +#ifndef nsTraceRefcntImpl_h___ +#define nsTraceRefcntImpl_h___ + +#include <stdio.h> // for FILE +#include "nsITraceRefcnt.h" + +#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP +#define NS_MeanAndStdDev VBoxNsxpNS_MeanAndStdDev +#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */ + +class nsTraceRefcntImpl : public nsITraceRefcnt +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSITRACEREFCNT + + nsTraceRefcntImpl(); + + static NS_COM void Startup(); + static NS_COM void Shutdown(); + + enum StatisticsType { + ALL_STATS, + NEW_STATS + }; + + static NS_COM nsresult DumpStatistics(StatisticsType type = ALL_STATS, + FILE* out = 0); + + static NS_COM void ResetStatistics(void); + + static NS_COM void LoadLibrarySymbols(const char* aLibraryName, + void* aLibrayHandle); + + + static NS_COM void DemangleSymbol(const char * aSymbol, + char * aBuffer, + int aBufLen); + + static NS_COM void WalkTheStack(FILE* aStream); + /** + * Tell nsTraceRefcnt whether refcounting, allocation, and destruction + * activity is legal. This is used to trigger assertions for any such + * activity that occurs because of static constructors or destructors. + */ + static NS_COM void SetActivityIsLegal(PRBool aLegal); + + static NS_METHOD Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr); + +private: + ~nsTraceRefcntImpl() {} +}; + +#define NS_TRACE_REFCNT_CONTRACTID "@mozilla.org/xpcom/trace-refcnt;1" +#define NS_TRACE_REFCNT_CLASSNAME "nsTraceRefcnt Interface" +#define NS_TRACE_REFCNT_CID \ +{ /* e3e7511e-a395-4924-94b1-d527861cded4 */ \ + 0xe3e7511e, \ + 0xa395, \ + 0x4924, \ + {0x94, 0xb1, 0xd5, 0x27, 0x86, 0x1c, 0xde, 0xd4} \ +} \ + +//////////////////////////////////////////////////////////////////////////////// +// And now for that utility that you've all been asking for... + +extern "C" NS_COM void +NS_MeanAndStdDev(double n, double sumOfValues, double sumOfSquaredValues, + double *meanResult, double *stdDevResult); + +//////////////////////////////////////////////////////////////////////////////// +#endif diff --git a/src/libs/xpcom18a4/xpcom/base/nsWeakPtr.h b/src/libs/xpcom18a4/xpcom/base/nsWeakPtr.h new file mode 100644 index 00000000..c15e31f0 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/base/nsWeakPtr.h @@ -0,0 +1,48 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Mozilla browser. + * + * The Initial Developer of the Original Code is + * Netscape Communications, Inc. + * Portions created by the Initial Developer are Copyright (C) 1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Scott Collins <scc@netscape.com> + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef nsWeakPtr_h__ +#define nsWeakPtr_h__ + +#include "nsIWeakReference.h" +#include "nsCOMPtr.h" + +// typedef nsCOMPtr<nsIWeakReference> nsWeakPtr; + +#endif diff --git a/src/libs/xpcom18a4/xpcom/base/nscore.h b/src/libs/xpcom18a4/xpcom/base/nscore.h new file mode 100644 index 00000000..5e1415de --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/base/nscore.h @@ -0,0 +1,459 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +#ifndef nscore_h___ +#define nscore_h___ + +/** + * Make sure that we have the proper platform specific + * c++ definitions needed by nscore.h + */ +#ifndef _XPCOM_CONFIG_H_ +#include "xpcom-config.h" +#endif + +/** + * Incorporate the core NSPR data types which XPCOM uses. + */ +#include "prtypes.h" + +/* Core XPCOM declarations. */ + +/** + * Macros defining the target platform... + */ +#ifdef _WIN32 +#define NS_WIN32 1 + +#elif defined(__unix) +#define NS_UNIX 1 + +#elif defined(XP_OS2) +#define NS_OS2 1 +#endif +/*----------------------------------------------------------------------*/ +/* Import/export defines */ + +/** + * Using the visibility("hidden") attribute allows the compiler to use + * PC-relative addressing to call this function. If a function does not + * access any global data, and does not call any methods which are not either + * file-local or hidden, then on ELF systems we avoid loading the address of + * the PLT into a register at the start of the function, which reduces code + * size and frees up a register for general use. + * + * As a general rule, this should be used for any non-exported symbol + * (including virtual method implementations). NS_IMETHOD uses this by + * default; if you need to have your NS_IMETHOD functions exported, you can + * wrap your class as follows: + * + * #undef IMETHOD_VISIBILITY + * #define IMETHOD_VISIBILITY NS_VISIBILITY_DEFAULT + * + * class Foo { + * ... + * }; + * + * #undef IMETHOD_VISIBILITY + * #define IMETHOD_VISIBILITY NS_VISIBILITY_HIDDEN + * + * Don't forget to change the visibility back to hidden before the end + * of a header! + * + * Other examples: + * + * NS_HIDDEN_(int) someMethod(); + * SomeCtor() NS_HIDDEN; + */ + +#ifdef HAVE_VISIBILITY_ATTRIBUTE +#define NS_VISIBILITY_HIDDEN __attribute__ ((visibility ("hidden"))) +# ifdef VBOX_HAVE_VISIBILITY_HIDDEN +# define NS_VISIBILITY_DEFAULT __attribute__ ((visibility ("default"))) +# else +# define NS_VISIBILITY_DEFAULT +# endif + +#define NS_HIDDEN_(type) NS_VISIBILITY_HIDDEN type +#else +#define NS_VISIBILITY_HIDDEN +#define NS_VISIBILITY_DEFAULT + +#define NS_HIDDEN_(type) type +#endif + +#define NS_HIDDEN NS_VISIBILITY_HIDDEN + +#undef IMETHOD_VISIBILITY +#define IMETHOD_VISIBILITY NS_VISIBILITY_HIDDEN + +/** + * Mark a function as using a potentially non-standard function calling + * convention. This can be used on functions that are called very + * frequently, to reduce the overhead of the function call. It is still worth + * using the macro for C++ functions which take no parameters since it allows + * passing |this| in a register. + * + * - Do not use this on any scriptable interface method since xptcall won't be + * aware of the different calling convention. + * - This must appear on the declaration, not the definition. + * - Adding this to a public function _will_ break binary compatibility. + * - This may be used on virtual functions but you must ensure it is applied + * to all implementations - the compiler will _not_ warn but it will crash. + * - This has no effect for inline functions or functions which take a + * variable number of arguments. + * + * Examples: int NS_FASTCALL func1(char *foo); + * NS_HIDDEN_(int) NS_FASTCALL func2(char *foo); + */ + +#if defined(__i386__) && defined(__GNUC__) && (__GNUC__ >= 3) && !defined(XP_OS2) +#define NS_FASTCALL __attribute__ ((regparm (3), stdcall)) +#else +#define NS_FASTCALL +#endif + +/* XXX: nike, maybe fix */ +#define NS_EXPORT_STATIC_MEMBER_(type) type +#define NS_IMPORT_STATIC_MEMBER_(type) type + +#ifdef NS_WIN32 + +#define NS_IMPORT __declspec(dllimport) +#define NS_IMPORT_(type) type __declspec(dllimport) __stdcall +#define NS_EXPORT __declspec(dllexport) +#define NS_EXPORT_(type) type __declspec(dllexport) __stdcall +#define NS_IMETHOD_(type) virtual type __stdcall +#define NS_IMETHODIMP_(type) type __stdcall +#define NS_METHOD_(type) type __stdcall +#define NS_CALLBACK_(_type, _name) _type (__stdcall * _name) +#define NS_STDCALL __stdcall + +#elif defined(XP_MAC) + +#define NS_IMPORT +#define NS_IMPORT_(type) type +#define NS_EXPORT __declspec(export) +#define NS_EXPORT_(type) __declspec(export) type +#define NS_IMETHOD_(type) virtual type +#define NS_IMETHODIMP_(type) type +#define NS_METHOD_(type) type +#define NS_CALLBACK_(_type, _name) _type (* _name) +#define NS_STDCALL + +#elif defined(XP_OS2) && defined(__declspec) + +#define NS_IMPORT __declspec(dllimport) +#define NS_IMPORT_(type) type __declspec(dllimport) __stdcall +#define NS_EXPORT __declspec(dllexport) +#define NS_EXPORT_(type) type __declspec(dllexport) __stdcall +#define NS_IMETHOD_(type) virtual IMETHOD_VISIBILITY type +#define NS_IMETHODIMP_(type) type +#define NS_METHOD_(type) type +#define NS_CALLBACK_(_type, _name) _type (* _name) +#define NS_STDCALL + +#else + +# ifdef VBOX_HAVE_VISIBILITY_HIDDEN +# define NS_IMPORT +# define NS_IMPORT_(type) type +# define NS_EXPORT __attribute__((visibility("default"))) +# define NS_EXPORT_(type) __attribute__((visibility("default"))) type +# define NS_IMETHOD_(type) virtual IMETHOD_VISIBILITY type +# define NS_IMETHODIMP_(type) type +# define NS_METHOD_(type) type +# define NS_CALLBACK_(_type, _name) _type (* _name) +# define NS_STDCALL +# else +# define NS_IMPORT +# define NS_IMPORT_(type) type +# define NS_EXPORT +# define NS_EXPORT_(type) type +# define NS_IMETHOD_(type) virtual IMETHOD_VISIBILITY type +# define NS_IMETHODIMP_(type) type +# define NS_METHOD_(type) type +# define NS_CALLBACK_(_type, _name) _type (* _name) +# define NS_STDCALL +# endif +#endif + +/** + * Macro for creating typedefs for pointer-to-member types which are + * declared with stdcall. It is important to use this for any type which is + * declared as stdcall (i.e. NS_IMETHOD). For example, instead of writing: + * + * typedef nsresult (nsIFoo::*someType)(nsISupports* arg); + * + * you should write: + * + * typedef + * NS_STDCALL_FUNCPROTO(nsresult, someType, nsIFoo, typeFunc, (nsISupports*)); + * + * where nsIFoo::typeFunc is any method declared as + * NS_IMETHOD typeFunc(nsISupports*); + * + * XXX this can be simplified to always use the non-typeof implementation + * when http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11893 is fixed. + */ + +#ifdef __GNUC__ +#define NS_STDCALL_FUNCPROTO(ret, name, class, func, args) \ + typeof(&class::func) name +#else +#define NS_STDCALL_FUNCPROTO(ret, name, class, func, args) \ + ret (NS_STDCALL class::*name) args +#endif + +/** + * Generic API modifiers which return the standard XPCOM nsresult type + */ +#define NS_IMETHOD NS_IMETHOD_(nsresult) +#define NS_IMETHODIMP NS_IMETHODIMP_(nsresult) +#define NS_METHOD NS_METHOD_(nsresult) +#define NS_CALLBACK(_name) NS_CALLBACK_(nsresult, _name) + +/** + * Import/Export macros for XPCOM APIs + */ + +#ifdef _IMPL_NS_COM +#define NS_COM NS_EXPORT +#elif _IMPL_NS_COM_OFF +#define NS_COM +#elif XPCOM_GLUE +#define NS_COM +#else +#define NS_COM NS_IMPORT +#endif + + +/** + * NS_NO_VTABLE is emitted by xpidl in interface declarations whenever + * xpidl can determine that the interface can't contain a constructor. + * This results in some space savings and possible runtime savings - + * see bug 49416. We undefine it first, as xpidl-generated headers + * define it for IDL uses that don't include this file. + */ +#ifdef NS_NO_VTABLE +#undef NS_NO_VTABLE +#endif +#if defined(_MSC_VER) && _MSC_VER >= 1100 +#define NS_NO_VTABLE __declspec(novtable) +#else +#define NS_NO_VTABLE +#endif + + +/** + * Generic XPCOM result data type + */ +typedef PRUint32 nsresult; + +/** + * The preferred symbol for null. + */ +#define nsnull 0 + +#include "nsError.h" + +/* ------------------------------------------------------------------------ */ +/* Casting macros for hiding C++ features from older compilers */ + + /* + All our compiler support template specialization, but not all support the + |template <>| notation. The compiler that don't understand this notation + just omit it for specialization. + + Need to add an autoconf test for this. + */ + + /* under Metrowerks (Mac), we don't have autoconf yet */ +#ifdef __MWERKS__ + #define HAVE_CPP_PARTIAL_SPECIALIZATION + #define HAVE_CPP_MODERN_SPECIALIZE_TEMPLATE_SYNTAX + + #define HAVE_CPP_ACCESS_CHANGING_USING + #define HAVE_CPP_AMBIGUITY_RESOLVING_USING + #define HAVE_CPP_EXPLICIT + #define HAVE_CPP_TYPENAME + #define HAVE_CPP_BOOL + #define HAVE_CPP_NAMESPACE_STD + #define HAVE_CPP_UNAMBIGUOUS_STD_NOTEQUAL + #define HAVE_CPP_2BYTE_WCHAR_T +#endif + + /* under VC++ (Windows), we don't have autoconf yet */ +#if defined(_MSC_VER) && (_MSC_VER>=1100) + /* VC++ 5.0 and greater implement template specialization, 4.2 is unknown */ + #define HAVE_CPP_MODERN_SPECIALIZE_TEMPLATE_SYNTAX + + #define HAVE_CPP_EXPLICIT + #define HAVE_CPP_TYPENAME + #define HAVE_CPP_ACCESS_CHANGING_USING + + #if (_MSC_VER==1100) + /* VC++5.0 has an internal compiler error (sometimes) without this */ + #undef HAVE_CPP_ACCESS_CHANGING_USING + #endif + + #define HAVE_CPP_NAMESPACE_STD + #define HAVE_CPP_UNAMBIGUOUS_STD_NOTEQUAL + #define HAVE_CPP_2BYTE_WCHAR_T +#endif + +#ifndef __PRUNICHAR__ +#define __PRUNICHAR__ + /* For now, don't use wchar_t on Unix because it breaks the Netscape + * commercial build. When this is fixed there will be no need for the + * |NS_REINTERPRET_CAST| in nsLiteralString.h either. + */ + #if defined(HAVE_CPP_2BYTE_WCHAR_T) && (defined(NS_WIN32) || defined(XP_MAC)) + typedef wchar_t PRUnichar; + #else + typedef PRUint16 PRUnichar; + #endif +#endif + + /* + If the compiler doesn't support |explicit|, we'll just make it go away, trusting + that the builds under compilers that do have it will keep us on the straight and narrow. + */ +#ifndef HAVE_CPP_EXPLICIT + #define explicit +#endif + +#ifndef HAVE_CPP_TYPENAME + #define typename +#endif + +#ifdef HAVE_CPP_MODERN_SPECIALIZE_TEMPLATE_SYNTAX + #define NS_SPECIALIZE_TEMPLATE template <> +#else + #define NS_SPECIALIZE_TEMPLATE +#endif + +/* unix and beos now determine this automatically */ +#if ! defined XP_UNIX && ! defined XP_BEOS && !defined(XP_OS2) +#ifndef HAVE_CPP_NEW_CASTS +#define HAVE_CPP_NEW_CASTS 1 /* we'll be optimistic. */ +#endif +#endif + +#if defined(HAVE_CPP_NEW_CASTS) +#define NS_STATIC_CAST(__type, __ptr) static_cast< __type >(__ptr) +#define NS_CONST_CAST(__type, __ptr) const_cast< __type >(__ptr) + +#define NS_REINTERPRET_POINTER_CAST(__type, __ptr) reinterpret_cast< __type >(__ptr) +#define NS_REINTERPRET_NONPOINTER_CAST(__type, __obj) reinterpret_cast< __type >(__obj) +#define NS_REINTERPRET_CAST(__type, __expr) reinterpret_cast< __type >(__expr) + +#else +#define NS_STATIC_CAST(__type, __ptr) ((__type)(__ptr)) +#define NS_CONST_CAST(__type, __ptr) ((__type)(__ptr)) + +#define NS_REINTERPRET_POINTER_CAST(__type, __ptr) ((__type)((void*)(__ptr))) +#define NS_REINTERPRET_NONPOINTER_CAST(__type, __obj) ((__type)(__obj)) + + /* Note: the following is only appropriate for pointers. */ +#define NS_REINTERPRET_CAST(__type, __expr) NS_REINTERPRET_POINTER_CAST(__type, __expr) + /* + Why cast to a |void*| first? Well, when old-style casting from + a pointer to a base to a pointer to a derived class, the cast will be + ambiguous if the source pointer type appears multiple times in the + destination, e.g., + + class Base {}; + class Derived : public Base, public Base {}; + + void foo( Base* b ) + { + ((Derived*)b)->some_derived_member ... // Error: Ambiguous, expand from which |Base|? + } + + an old-style cast (like |static_cast|) will change the pointer, but + here, doesn't know how. The cast to |void*| prevents it from thinking + it needs to expand the original pointer. + + The cost is, |NS_REINTERPRET_CAST| is no longer appropriate for non-pointer + conversions. Also, mis-applying |NS_REINTERPRET_CAST| to cast |this| to something + will still expand the pointer to the outer object in standards complying compilers. + */ + + /* + No sense in making an NS_DYNAMIC_CAST() macro: you can't duplicate + the semantics. So if you want to dynamic_cast, then just use it + "straight", no macro. + */ +#endif + +#ifndef VBOX +/* + * Use these macros to do 64bit safe pointer conversions. + */ + +#define NS_PTR_TO_INT32(x) ((char *)(x) - (char *)0) +#define NS_INT32_TO_PTR(x) ((void *)((char *)0 + (x))) +#else /* VBOX */ +// This stuff is (contrary to the comment) totally 64bit unsafe, so strip +// it down to only do one direction, which is used by the hashing code. +#define NS_PTR_TO_INT32(x) ((PRInt32)((char *)(x) - (char *)0)) +#endif /* VBOX */ + +/* + * These macros allow you to give a hint to the compiler about branch + * probability so that it can better optimize. Use them like this: + * + * if (NS_LIKELY(v == 1)) { + * ... expected code path ... + * } + * + * if (NS_UNLIKELY(v == 0)) { + * ... non-expected code path ... + * } + * + */ + +#if defined(__GNUC__) && (__GNUC__ > 2) && !defined(FORTIFY_RUNNING) +#define NS_LIKELY(x) (__builtin_expect(!!(x), 1)) +#define NS_UNLIKELY(x) (__builtin_expect(!!(x), 0)) +#else +#define NS_LIKELY(x) (x) +#define NS_UNLIKELY(x) (x) +#endif + +#endif /* nscore_h___ */ + diff --git a/src/libs/xpcom18a4/xpcom/base/nsrootidl.idl b/src/libs/xpcom18a4/xpcom/base/nsrootidl.idl new file mode 100644 index 00000000..0538e4bc --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/base/nsrootidl.idl @@ -0,0 +1,128 @@ +/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Dan Rosen <dr@netscape.com> + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/** + * Root idl declarations to be used by all. + * @status FROZEN + */ + +%{C++ + +#include "nscore.h" +#include "prtime.h" + +/* + * Forward declarations for new string types + */ +class nsAString; +class nsACString; + +/* + * Start commenting out the C++ versions of the below in the output header + */ +#if 0 +%} + +typedef boolean PRBool ; +typedef octet PRUint8 ; +typedef unsigned short PRUint16 ; +typedef unsigned short PRUnichar; +typedef unsigned long PRUint32 ; +typedef unsigned long long PRUint64 ; +typedef unsigned long long PRTime ; +typedef short PRInt16 ; +typedef long PRInt32 ; +typedef long long PRInt64 ; + +typedef unsigned long nsrefcnt ; +typedef unsigned long nsresult ; + +// XXX need this built into xpidl compiler so that it's really size_t or PRSize +// and it's scriptable: +typedef unsigned long size_t; + +[ptr] native voidPtr(void); +[ptr] native charPtr(char); +[ptr] native unicharPtr(PRUnichar); + +[ref, nsid] native nsIDRef(nsID); +[ref, nsid] native nsIIDRef(nsIID); +[ref, nsid] native nsCIDRef(nsCID); + +[ptr, nsid] native nsIDPtr(nsID); +[ptr, nsid] native nsIIDPtr(nsIID); +[ptr, nsid] native nsCIDPtr(nsCID); + +// NOTE: Be careful in using the following 3 types. The *Ref and *Ptr variants +// are more commonly used (and better supported). Those variants require +// nsMemory alloc'd copies when used as 'out' params while these types do not. +// However, currently these types can not be used for 'in' params. And, methods +// that use them as 'out' params *must* be declared [notxpcom] (with an explicit +// return type of nsresult). This makes such methods implicitly not scriptable. +// Use of these types in methods without a [notxpcom] declaration will cause +// the xpidl compiler to raise an error. +// See: http://bugzilla.mozilla.org/show_bug.cgi?id=93792 + +[nsid] native nsIID(nsIID); +[nsid] native nsID(nsID); +[nsid] native nsCID(nsCID); + +[ptr] native nsQIResult(void); + +[ref, domstring] native DOMString(ignored); +[ref, domstring] native DOMStringRef(ignored); +[ptr, domstring] native DOMStringPtr(ignored); + +[ref, utf8string] native AUTF8String(ignored); +[ref, utf8string] native AUTF8StringRef(ignored); +[ptr, utf8string] native AUTF8StringPtr(ignored); + +[ref, cstring] native ACString(ignored); +[ref, cstring] native ACStringRef(ignored); +[ptr, cstring] native ACStringPtr(ignored); + +[ref, astring] native AString(ignored); +[ref, astring] native AStringRef(ignored); +[ptr, astring] native AStringPtr(ignored); + +%{C++ +/* + * End commenting out the C++ versions of the above in the output header + */ +#endif +%} diff --git a/src/libs/xpcom18a4/xpcom/base/pure.h b/src/libs/xpcom18a4/xpcom/base/pure.h new file mode 100644 index 00000000..ea11b99d --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/base/pure.h @@ -0,0 +1,135 @@ +/* + * Header file of Pure API function declarations. + * + * Explicitly no copyright. + * You may recompile and redistribute these definitions as required. + * + * Version 1.0 + */ + +#if defined(c_plusplus) || defined(__cplusplus) +extern "C" { +#endif + +#define PURE_H_VERSION 1 + +////////////////////////////// +// API's Specific to Purify // +////////////////////////////// + +// TRUE when Purify is running. +int __cdecl PurifyIsRunning(void) ; +// +// Print a string to the viewer. +// +int __cdecl PurePrintf(const char *fmt, ...) ; +int __cdecl PurifyPrintf(const char *fmt, ...) ; +// +// Purify functions for leak and memory-in-use functionalty. +// +int __cdecl PurifyNewInuse(void) ; +int __cdecl PurifyAllInuse(void) ; +int __cdecl PurifyClearInuse(void) ; +int __cdecl PurifyNewLeaks(void) ; +int __cdecl PurifyAllLeaks(void) ; +int __cdecl PurifyClearLeaks(void) ; +// +// Purify functions for handle leakage. +// +int __cdecl PurifyAllHandlesInuse(void) ; +int __cdecl PurifyNewHandlesInuse(void) ; +// +// Functions that tell you about the state of memory. +// +int __cdecl PurifyDescribe(void *addr) ; +int __cdecl PurifyWhatColors(void *addr, int size) ; +// +// Functions to test the state of memory. If the memory is not +// accessable, an error is signaled just as if there were a memory +// reference and the function returns false. +// +int __cdecl PurifyAssertIsReadable(const void *addr, int size) ; +int __cdecl PurifyAssertIsWritable(const void *addr, int size) ; +// +// Functions to test the state of memory. If the memory is not +// accessable, these functions return false. No error is signaled. +// +int __cdecl PurifyIsReadable(const void *addr, int size) ; +int __cdecl PurifyIsWritable(const void *addr, int size) ; +int __cdecl PurifyIsInitialized(const void *addr, int size) ; +// +// Functions to set the state of memory. +// +void __cdecl PurifyMarkAsInitialized(void *addr, int size) ; +void __cdecl PurifyMarkAsUninitialized(void *addr, int size) ; +// +// Functions to do late detection of ABWs, FMWs, IPWs. +// +#define PURIFY_HEAP_CRT 0xfffffffe +#define PURIFY_HEAP_ALL 0xfffffffd +#define PURIFY_HEAP_BLOCKS_LIVE 0x80000000 +#define PURIFY_HEAP_BLOCKS_DEFERRED_FREE 0x40000000 +#define PURIFY_HEAP_BLOCKS_ALL (PURIFY_HEAP_BLOCKS_LIVE|PURIFY_HEAP_BLOCKS_DEFERRED_FREE) +int __cdecl PurifyHeapValidate(unsigned int hHeap, unsigned int dwFlags, const void *addr) ; +int __cdecl PurifySetLateDetectScanCounter(int counter); +int __cdecl PurifySetLateDetectScanInterval(int seconds); + + +//////////////////////////////// +// API's Specific to Quantify // +//////////////////////////////// + +// TRUE when Quantify is running. +int __cdecl QuantifyIsRunning(void) ; + +// +// Functions for controlling collection +// +int __cdecl QuantifyDisableRecordingData(void) ; +int __cdecl QuantifyStartRecordingData(void) ; +int __cdecl QuantifyStopRecordingData(void) ; +int __cdecl QuantifyClearData(void) ; +int __cdecl QuantifyIsRecordingData(void) ; + +// Add a comment to the dataset +int __cdecl QuantifyAddAnnotation(char *) ; + +// Save the current data, creating a "checkpoint" dataset +int __cdecl QuantifySaveData(void) ; + +//////////////////////////////// +// API's Specific to Coverage // +//////////////////////////////// + +// TRUE when Coverage is running. +int __cdecl CoverageIsRunning(void) ; +// +// Functions for controlling collection +// +int __cdecl CoverageDisableRecordingData(void) ; +int __cdecl CoverageStartRecordingData(void) ; +int __cdecl CoverageStopRecordingData(void) ; +int __cdecl CoverageClearData(void) ; +int __cdecl CoverageIsRecordingData(void) ; +// Add a comment to the dataset +int __cdecl CoverageAddAnnotation(char *) ; + +// Save the current data, creating a "checkpoint" dataset +int __cdecl CoverageSaveData(void) ; + + + + +//////////////////////////////// +// API's Specific to Purelock // +//////////////////////////////// + +// TRUE when Purelock is running. +int __cdecl PurelockIsRunning(void) ; + + + + +#if defined(c_plusplus) || defined(__cplusplus) +} +#endif diff --git a/src/libs/xpcom18a4/xpcom/base/pure_api.c b/src/libs/xpcom18a4/xpcom/base/pure_api.c new file mode 100644 index 00000000..716460ed --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/base/pure_api.c @@ -0,0 +1,126 @@ +/* + * Header file of Pure API function declarations. + * + * Explicitly no copyright. + * You may recompile and redistribute these definitions as required. + * + * NOTE1: In some situations when compiling with MFC, you should + * enable the setting 'Not using precompiled headers' in Visual C++ + * to avoid a compiler diagnostic. + * + * NOTE2: This file works through the use of deep magic. Calls to functions + * in this file are replaced with calls into the OCI runtime system + * when an instrumented version of this program is run. + * + * NOTE3: The static vars avoidGy_n (where n is a unique number) are used + * to prevent optimizing the functions away when compiler option + * /Gy is set. This is needed so that NOTE2 works properly. + */ +static int avoidGy_1; +static int avoidGy_2; +static int avoidGy_3; +static int avoidGy_4; +static int avoidGy_5; +static int avoidGy_6; +static int avoidGy_7; +static int avoidGy_8; +static int avoidGy_9; +static int avoidGy_10; +static int avoidGy_11; +static int avoidGy_12; +static int avoidGy_13; +static int avoidGy_14; +static int avoidGy_15; +static int avoidGy_16; +static int avoidGy_17; +static int avoidGy_18; +static int avoidGy_19; +static int avoidGy_20; +static int avoidGy_21; +static int avoidGy_22; +static int avoidGy_23; +static int avoidGy_24; +static int avoidGy_25; +static int avoidGy_26; +static int avoidGy_27; +static int avoidGy_28; +static int avoidGy_29; +static int avoidGy_30; +static int avoidGy_31; +static int avoidGy_32; +static int avoidGy_33; +static int avoidGy_34; +static int avoidGy_35; +static int avoidGy_36; +static int avoidGy_37; +static int avoidGy_38; +static int avoidGy_39; +static int avoidGy_40; +static int avoidGy_41; +static int avoidGy_42; +static int avoidGy_43; +static int avoidGy_44; +static int avoidGy_45; +static int avoidGy_46; +static int avoidGy_47; +static int avoidGy_48; +static int avoidGy_49; +static int avoidGy_50; +static int avoidGy_51; +static int avoidGy_52; +static int avoidGy_53; +static int avoidGy_54; +static int avoidGy_55; +static int avoidGy_56; +static int avoidGy_57; +static int avoidGy_58; +static int avoidGy_59; +static int avoidGy_60; +static int avoidGy_PL_01; +__declspec(dllexport) int __cdecl PurePrintf(const char *fmt, ...) { avoidGy_1++; fmt; return 0; } +__declspec(dllexport) int __cdecl PurifyIsRunning(void) { avoidGy_2++; return 0; } +__declspec(dllexport) int __cdecl PurifyPrintf(const char *fmt, ...) { avoidGy_3++; fmt; return 0; } +__declspec(dllexport) int __cdecl PurifyNewInuse(void) { avoidGy_4++; return 0; } +__declspec(dllexport) int __cdecl PurifyAllInuse(void) { avoidGy_5++; return 0; } +__declspec(dllexport) int __cdecl PurifyClearInuse(void) { avoidGy_6++; return 0; } +__declspec(dllexport) int __cdecl PurifyNewLeaks(void) { avoidGy_7++; return 0; } +__declspec(dllexport) int __cdecl PurifyAllLeaks(void) { avoidGy_8++; return 0; } +__declspec(dllexport) int __cdecl PurifyClearLeaks(void) { avoidGy_9++; return 0; } +__declspec(dllexport) int __cdecl PurifyAllHandlesInuse(void) { avoidGy_10++; return 0; } +__declspec(dllexport) int __cdecl PurifyNewHandlesInuse(void) { avoidGy_11++; return 0; } +__declspec(dllexport) int __cdecl PurifyDescribe(void *addr) { avoidGy_12++; addr; return 0; } +__declspec(dllexport) int __cdecl PurifyWhatColors(void *addr, int size) { avoidGy_13++; addr; size; return 0; } +__declspec(dllexport) int __cdecl PurifyAssertIsReadable(const void *addr, int size) { avoidGy_14++; addr; size; return 1; } +__declspec(dllexport) int __cdecl PurifyAssertIsWritable(const void *addr, int size) { avoidGy_15++; addr; size; return 1; } +__declspec(dllexport) int __cdecl PurifyIsReadable(const void *addr, int size) { avoidGy_16++; addr; size; return 1; } +__declspec(dllexport) int __cdecl PurifyIsWritable(const void *addr, int size) { avoidGy_17++; addr; size; return 1; } +__declspec(dllexport) int __cdecl PurifyIsInitialized(const void *addr, int size) { avoidGy_18++; addr; size; return 1; } +__declspec(dllexport) int __cdecl PurifyRed(void *addr, int size) { avoidGy_19++; addr; size; return 0; } +__declspec(dllexport) int __cdecl PurifyGreen(void *addr, int size) { avoidGy_20++; addr; size; return 0; } +__declspec(dllexport) int __cdecl PurifyYellow(void *addr, int size) { avoidGy_21++; addr; size; return 0; } +__declspec(dllexport) int __cdecl PurifyBlue(void *addr, int size) { avoidGy_22++; addr; size; return 0; } +__declspec(dllexport) int __cdecl PurifyMarkAsInitialized(void *addr, int size) { avoidGy_23++; addr; size; return 0; } +__declspec(dllexport) int __cdecl PurifyMarkAsUninitialized(void *addr, int size) { avoidGy_24++; addr; size; return 0; } +__declspec(dllexport) int __cdecl PurifyMarkForTrap(void *addr, int size) { avoidGy_25++; addr; size; return 0; } +__declspec(dllexport) int __cdecl PurifyMarkForNoTrap(void *addr, int size) { avoidGy_26++; addr; size; return 0; } +__declspec(dllexport) int __cdecl PurifyHeapValidate(unsigned int hHeap, unsigned int dwFlags, const void *addr) + { avoidGy_27++; hHeap; dwFlags; addr; return 1; } +__declspec(dllexport) int __cdecl PurifySetLateDetectScanCounter(int counter) { avoidGy_28++; counter; return 0; }; +__declspec(dllexport) int __cdecl PurifySetLateDetectScanInterval(int seconds) { avoidGy_29++; seconds; return 0; }; +__declspec(dllexport) int __cdecl CoverageIsRunning(void) { avoidGy_30++; return 0; } +__declspec(dllexport) int __cdecl CoverageDisableRecordingData(void) { avoidGy_31++; return 0; } +__declspec(dllexport) int __cdecl CoverageStartRecordingData(void) { avoidGy_32++; return 0; } +__declspec(dllexport) int __cdecl CoverageStopRecordingData(void) { avoidGy_33++; return 0; } +__declspec(dllexport) int __cdecl CoverageClearData(void) { avoidGy_34++; return 0; } +__declspec(dllexport) int __cdecl CoverageIsRecordingData(void) { avoidGy_35++; return 0; } +__declspec(dllexport) int __cdecl CoverageAddAnnotation(char *str) { avoidGy_36++; str; return 0; } +__declspec(dllexport) int __cdecl CoverageSaveData(void) { avoidGy_37++; return 0; } +__declspec(dllexport) int __cdecl QuantifyIsRunning(void) { avoidGy_42++; return 0; } +__declspec(dllexport) int __cdecl QuantifyDisableRecordingData(void) { avoidGy_43++; return 0; } +__declspec(dllexport) int __cdecl QuantifyStartRecordingData(void) { avoidGy_44++; return 0; } +__declspec(dllexport) int __cdecl QuantifyStopRecordingData(void) { avoidGy_45++; return 0; } +__declspec(dllexport) int __cdecl QuantifyClearData(void) { avoidGy_46++; return 0; } +__declspec(dllexport) int __cdecl QuantifyIsRecordingData(void) { avoidGy_47++; return 0; } +__declspec(dllexport) int __cdecl QuantifyAddAnnotation(char *str) { avoidGy_48++; str; return 0; } +__declspec(dllexport) int __cdecl QuantifySaveData(void) { avoidGy_49++; return 0; } +__declspec(dllexport) int __cdecl PurelockIsRunning(void) { avoidGy_PL_01++; return 0; } |